From: Kazuhiro Fujieda Date: Sun, 21 Sep 2014 12:30:53 +0000 (+0900) Subject: 泊地修理で20分経過後に次に耐久が1回復するまでの時間を表示する X-Git-Tag: v2.5~4 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=adcc3fecb4ed11bdce959cc84c6c5fcce74856f6;p=kancollesniffer%2FKancolleSniffer.git 泊地修理で20分経過後に次に耐久が1回復するまでの時間を表示する --- diff --git a/KancolleSniffer/AkashiTimer.cs b/KancolleSniffer/AkashiTimer.cs index 670a668..2e58366 100644 --- a/KancolleSniffer/AkashiTimer.cs +++ b/KancolleSniffer/AkashiTimer.cs @@ -16,6 +16,7 @@ // along with this program; if not, see . using System; +using System.Collections.Generic; using System.Linq; namespace KancolleSniffer @@ -28,15 +29,47 @@ namespace KancolleSniffer private readonly MissionInfo _missionInfo; private readonly RepairStatus[] _repairStatuses = new RepairStatus[ShipInfo.FleetCount]; - private struct RepairStatus + public class RepairTime { - public DateTime Timer { get; set; } + public int Diff { get; set; } + public DateTime Time { get; set; } + + public RepairTime(int diff, DateTime time) + { + Diff = diff; + Time = time; + } + } + + public class RepairSpan + { + public int Diff { get; set; } + public TimeSpan Span { get; set; } + + public RepairSpan(int diff, TimeSpan span) + { + Diff = diff; + Span = span; + } + + public RepairSpan(RepairTime time) + { + Diff = time.Diff; + Span = TimeSpan.FromSeconds(Math.Ceiling((time.Time - DateTime.Now).TotalSeconds)); + } + } + + private class RepairStatus + { + public DateTime Start { get; set; } + public RepairTime[][] Times { get; set; } public int TotalHp { get; set; } - public int[] Deck { private get; set; } + public int[] Deck { get; set; } public void Invalidate() { - Timer = DateTime.MinValue; + Start = DateTime.MinValue; + Times = null; TotalHp = 0; Deck = null; } @@ -53,6 +86,8 @@ namespace KancolleSniffer _itemInfo = item; _dockInfo = dock; _missionInfo = mission; + for (var i = 0; i < _repairStatuses.Length; i++) + _repairStatuses[i] = new RepairStatus(); } public void SetTimer(bool port = false) @@ -73,20 +108,16 @@ namespace KancolleSniffer if (_repairStatuses[fleet].DeckChanged(deck)) InvalidateTimer(fleet); var cap = _shipInfo[fs].Slot.Count(item => _itemInfo[item].Name == "艦艇修理施設") + 2; - var targets = deck.Take(cap).Where(id => !_dockInfo.InNDock(id)).ToArray(); - var totalHp = (from id in targets - let status = _shipInfo[id] - where status.NowHp < status.MaxHp && status.DamageLevel < ShipStatus.Damage.Half - select status.NowHp).Sum(); + var target = (from id in deck.Take(cap) select IsRepairable(id) ? id : -1).ToList(); + var totalHp = target.Sum(id => _shipInfo[id].NowHp); if (totalHp == 0) { InvalidateTimer(fleet); return; } var r = _repairStatuses[fleet]; - if (r.TotalHp == totalHp) + if (totalHp == r.TotalHp) return; - var timer = r.Timer; /* * 母港に遷移したときに、耐久値が回復しているか修理開始から20分経過しているときに * タイマーをリスタートする。 @@ -98,15 +129,39 @@ namespace KancolleSniffer * 反映されて回復が起こったことがわからない。耐久値の回復だけを基準にすると * リスタートできないので、20分経過していたらリスタートする。 */ - if (timer == DateTime.MinValue || - (port && (totalHp > r.TotalHp || (DateTime.Now - timer).TotalMinutes > 20))) - timer = DateTime.Now; - _repairStatuses[fleet] = new RepairStatus + if (r.Start == DateTime.MinValue || + (port && (totalHp > r.TotalHp || (DateTime.Now - r.Start).TotalMinutes > 20))) { - Timer = timer, - TotalHp = totalHp, - Deck = deck.ToArray() - }; + r.Start = DateTime.Now; + r.Times = EnumTimers(target).ToArray(); + } + else if (totalHp < r.TotalHp && r.Times != null) + { + // 修理対象から外れた艦のタイマーを消す。 + r.Times = target.Zip(r.Times, (id, times) => id != -1 ? times : null).ToArray(); + } + r.TotalHp = totalHp; + r.Deck = deck.ToArray(); + } + + private bool IsRepairable(int id) + { + var s = _shipInfo[id]; + return !_dockInfo.InNDock(id) && s.NowHp < s.MaxHp && s.DamageLevel < ShipStatus.Damage.Half; + } + + private IEnumerable EnumTimers(IEnumerable deck) + { + return from id in deck + let s = _shipInfo[id] + let damage = s.MaxHp - s.NowHp + let first = new RepairTime(0, DateTime.Now.AddMinutes(20)) + select damage == 0 + ? null + : new[] {first}.Concat(from d in Enumerable.Range(2, damage < 2 ? 0 : damage - 1) + let span = s.RepairTime(d) + TimeSpan.FromSeconds((d - 1) * 10 * s.Spec.RepairWeight) + where span.TotalSeconds > 20 * 60 + select new RepairTime(d - 1, DateTime.Now + span)).ToArray(); } private void InvalidateTimer(int fleet) @@ -114,9 +169,17 @@ namespace KancolleSniffer _repairStatuses[fleet].Invalidate(); } - public DateTime this[int fleet] + public RepairSpan[] GetTimers(int fleet) { - get { return _repairStatuses[fleet].Timer; } + var repair = _repairStatuses[fleet]; + if (repair.Times == null) + return null; + return (from e in repair.Times.Zip(repair.Deck, (times, id) => new {times, id}) + select e.times == null || _dockInfo.InNDock(e.id) + ? new RepairSpan(0, TimeSpan.MinValue) + : (from t in e.times select new RepairSpan(t)).FirstOrDefault(s => s.Span > TimeSpan.Zero) + ?? new RepairSpan(e.times.Last().Diff + 1, TimeSpan.Zero) + ).ToArray(); } } } \ No newline at end of file diff --git a/KancolleSniffer/MainForm.Designer.cs b/KancolleSniffer/MainForm.Designer.cs index d99214b..d35a030 100644 --- a/KancolleSniffer/MainForm.Designer.cs +++ b/KancolleSniffer/MainForm.Designer.cs @@ -65,7 +65,6 @@ namespace KancolleSniffer this.labelFormation = new System.Windows.Forms.Label(); this.label29 = new System.Windows.Forms.Label(); this.label19 = new System.Windows.Forms.Label(); - this.labelAkashiTimer = new System.Windows.Forms.Label(); this.labelAirSuperiority = new System.Windows.Forms.Label(); this.label27 = new System.Windows.Forms.Label(); this.label21 = new System.Windows.Forms.Label(); @@ -322,7 +321,6 @@ namespace KancolleSniffer this.panelFleet1.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; this.panelFleet1.Controls.Add(this.panelBattleInfo); this.panelFleet1.Controls.Add(this.label19); - this.panelFleet1.Controls.Add(this.labelAkashiTimer); this.panelFleet1.Controls.Add(this.labelAirSuperiority); this.panelFleet1.Controls.Add(this.label27); this.panelFleet1.Controls.Add(this.label21); @@ -423,16 +421,6 @@ namespace KancolleSniffer this.label19.TabIndex = 34; this.label19.Text = "疲労"; // - // labelAkashiTimer - // - this.labelAkashiTimer.Location = new System.Drawing.Point(48, 20); - this.labelAkashiTimer.Name = "labelAkashiTimer"; - this.labelAkashiTimer.Size = new System.Drawing.Size(45, 12); - this.labelAkashiTimer.TabIndex = 23; - this.labelAkashiTimer.Text = "00:00:00"; - this.labelAkashiTimer.TextAlign = System.Drawing.ContentAlignment.MiddleRight; - this.labelAkashiTimer.Visible = false; - // // labelAirSuperiority // this.labelAirSuperiority.Location = new System.Drawing.Point(29, 117); @@ -1817,7 +1805,6 @@ namespace KancolleSniffer private System.Windows.Forms.Label labelAirSuperiority; private System.Windows.Forms.Label label27; private System.Windows.Forms.Label labelLogin; - private System.Windows.Forms.Label labelAkashiTimer; private System.Windows.Forms.Label labelAchievement; private System.Windows.Forms.Label label28; private System.Windows.Forms.Panel panelBattleInfo; diff --git a/KancolleSniffer/MainForm.cs b/KancolleSniffer/MainForm.cs index 2fc2a42..bb69cd2 100644 --- a/KancolleSniffer/MainForm.cs +++ b/KancolleSniffer/MainForm.cs @@ -34,7 +34,9 @@ namespace KancolleSniffer private readonly int _labelRightDistance; private int _currentFleet; private readonly Label[] _labelCheckFleets; + private readonly Label[] _labelHPs; private readonly Label[][] _damagedShipList = new Label[14][]; + private readonly Label[] _akashiTimers = new Label[ShipInfo.MemberCount]; private bool _started; public MainForm() @@ -46,10 +48,13 @@ namespace KancolleSniffer _configDialog = new ConfigDialog(_config, this); _labelRightDistance = labelHP1.Parent.Width - labelHP1.Right; _labelCheckFleets = new[] {labelCheckFleet1, labelCheckFleet2, labelCheckFleet3, labelCheckFleet4}; + _labelHPs = new[] {labelHP1, labelHP2, labelHP3, labelHP4, labelHP5, labelHP6}; + var i = 0; foreach (var label in new[] {labelFleet1, labelFleet2, labelFleet3, labelFleet4}) label.Tag = i++; CreateDamagedShipList(); + CreateAkashiTimers(); } private void FiddlerApplication_BeforeRequest(Session oSession) @@ -151,7 +156,7 @@ namespace KancolleSniffer _sniffer.Item.MarginShips = _config.MarginShips; _sniffer.Achievement.ResetHours = _config.ResetHours; _sniffer.LogFile = _config.Logging ? _config.LogFile : null; - + if (_config.Location.X == int.MinValue) return; var newBounds = Bounds; @@ -196,7 +201,7 @@ namespace KancolleSniffer var message = string.Format("残り{0:D}隻", _sniffer.Item.MaxShips - _sniffer.Item.NowShips); Ring("艦娘が多すぎます", message, _config.MaxShipsSoundFile); item.NeedRing = false; - } + } } private void UpdateBucketHistory() @@ -213,8 +218,8 @@ namespace KancolleSniffer private void UpdateMaterialHistry() { - var labels = new[] { labelFuelHistory, labelBulletHistory, labelSteelHistory, labelBouxiteHistory }; - var text = new[] { "燃料", "弾薬", "鋼材", "ボーキ" }; + var labels = new[] {labelFuelHistory, labelBulletHistory, labelSteelHistory, labelBouxiteHistory}; + var text = new[] {"燃料", "弾薬", "鋼材", "ボーキ"}; for (var i = 0; i < labels.Length; i++) { var count = _sniffer.Item.MaterialHistory[i]; @@ -248,7 +253,6 @@ namespace KancolleSniffer { var name = new[] {labelShip1, labelShip2, labelShip3, labelShip4, labelShip5, labelShip6}; var lv = new[] {labelLv1, labelLv2, labelLv3, labelLv4, labelLv5, labelLv6}; - var hp = new[] {labelHP1, labelHP2, labelHP3, labelHP4, labelHP5, labelHP6}; var cond = new[] {labelCond1, labelCond2, labelCond3, labelCond4, labelCond5, labelCond6}; var next = new[] {labelNextLv1, labelNextLv2, labelNextLv3, labelNextLv4, labelNextLv5, labelNextLv6}; @@ -259,7 +263,7 @@ namespace KancolleSniffer var stat = i < statuses.Length ? statuses[i] : empty; name[i].Text = stat.Name; lv[i].Text = stat.Level.ToString("D"); - SetHpLavel(hp[i], stat); + SetHpLavel(_labelHPs[i], stat); if (stat == empty) { // SetCondLabelでは背景色が赤になってしまう @@ -311,9 +315,14 @@ namespace KancolleSniffer private void SetHpLavel(Label label, ShipStatus status) { + SetHpLavel(label, status.NowHp, status.MaxHp); + } + + private void SetHpLavel(Label label, int now, int max) + { var colors = new[] {DefaultBackColor, Color.FromArgb(255, 240, 240, 100), Color.Orange, Color.Red}; - label.Text = string.Format("{0:D}/{1:D}", status.NowHp, status.MaxHp); - label.BackColor = colors[(int)status.DamageLevel]; + label.Text = string.Format("{0:D}/{1:D}", now, max); + label.BackColor = colors[(int)ShipStatus.CalcDamage(now, max)]; } private void SetCondLabel(Label label, int cond) @@ -379,23 +388,52 @@ namespace KancolleSniffer entry.label.Text = entry.timer; } - private void UpdateAkashiTimer() + private void CreateAkashiTimers() { - var stat = _sniffer.GetShipStatuses(_currentFleet); - if (stat.Length == 0 || !stat[0].Name.StartsWith("明石")) + var parent = panelFleet1; + parent.SuspendLayout(); + for (var i = 0; i < _akashiTimers.Length; i++) { - labelAkashiTimer.Visible = false; - return; + const int width = 31, height = 12; + const int x = 56; + var y = 20 + 16 * i; + parent.Controls.Add( + _akashiTimers[i] = + new Label {Location = new Point(x, y), Size = new Size(width, height), Visible = false}); + parent.Controls.SetChildIndex(_akashiTimers[i], 0); } - labelAkashiTimer.Visible = true; - var start = _sniffer.GetAkashiStartTime(_currentFleet); - if (start == DateTime.MinValue) + parent.ResumeLayout(); + } + + private void UpdateAkashiTimer() + { + var timers = _sniffer.GetAkashiTimers(_currentFleet); + var statuses = _sniffer.GetShipStatuses(_currentFleet); + for (var i = 0; i < _akashiTimers.Length; i++) { - labelAkashiTimer.Text = "00:00:00"; - return; + var label = _akashiTimers[i]; + var labelHp = _labelHPs[i]; + if (timers == null || i >= timers.Length || timers[i].Span == TimeSpan.MinValue) + { + label.Visible = false; + label.ForeColor = DefaultForeColor; + labelHp.ForeColor = DefaultForeColor; + continue; + } + var timer = timers[i]; + var stat = statuses[i]; + label.Visible = true; + label.Text = timer.Span.ToString(@"mm\:ss"); + if (timer.Diff == 0) + { + label.ForeColor = DefaultForeColor; + labelHp.ForeColor = DefaultForeColor; + continue; + } + label.ForeColor = Color.Gray; + labelHp.ForeColor = Color.Gray; + SetHpLavel(labelHp, stat.NowHp + timer.Diff, stat.MaxHp); } - var span = DateTime.Now - start; - labelAkashiTimer.Text = span.Days == 0 ? span.ToString(@"hh\:mm\:ss") : span.ToString(@"d\.hh\:mm"); } public void CreateDamagedShipList() @@ -431,7 +469,7 @@ namespace KancolleSniffer return; } parent.Size = new Size(width, num * 16 + 3); - var fn = new[] { "", "1", "2", "3", "4" }; + var fn = new[] {"", "1", "2", "3", "4"}; for (var i = 0; i < num; i++) { var entry = _damagedShipList[i]; diff --git a/KancolleSniffer/MainForm.resx b/KancolleSniffer/MainForm.resx index 88b6a39..b29d08d 100644 --- a/KancolleSniffer/MainForm.resx +++ b/KancolleSniffer/MainForm.resx @@ -696,7 +696,7 @@ AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0 ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAAAQ - CwAAAk1TRnQBSQFMAgEBBQEAAagBAAGoAQABDgEAAQ8BAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo + CwAAAk1TRnQBSQFMAgEBBQEAAbABAAGwAQABDgEAAQ8BAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo AwABOAMAAR4DAAEBAQABCAUAAZABBhgAAYACAAGAAwACgAEAAYADAAGAAQABgAEAAoACAAPAAQABwAHc AcABAAHwAcoBpgEAATMFAAEzAQABMwEAATMBAAIzAgADFgEAAxwBAAMiAQADKQEAA1UBAANNAQADQgEA AzkBAAGAAXwB/wEAAlAB/wEAAZMBAAHWAQAB/wHsAcwBAAHGAdYB7wEAAdYC5wEAAZABqQGtAgAB/wEz @@ -754,7 +754,7 @@ AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0 ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAAA0 - CwAAAk1TRnQBSQFMAgEBBQEAAagBAAGoAQABDgEAAQ4BAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo + CwAAAk1TRnQBSQFMAgEBBQEAAbABAAGwAQABDgEAAQ4BAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo AwABOAMAARwDAAEBAQABCAUAASABBhgAAYACAAGAAwACgAEAAYADAAGAAQABgAEAAoACAAPAAQABwAHc AcABAAHwAcoBpgEAATMFAAEzAQABMwEAATMBAAIzAgADFgEAAxwBAAMiAQADKQEAA1UBAANNAQADQgEA AzkBAAGAAXwB/wEAAlAB/wEAAZMBAAHWAQAB/wHsAcwBAAHGAdYB7wEAAdYC5wEAAZABqQGtAgAB/wEz @@ -812,7 +812,7 @@ AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0 ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAABI - BwAAAk1TRnQBSQFMAwEBAAFwAQABcAEAAQUBAAENAQAE/wEJAQAI/wFCAU0BNgEEBgABNgEEAgABKAMA + BwAAAk1TRnQBSQFMAwEBAAF4AQABeAEAAQUBAAENAQAE/wEJAQAI/wFCAU0BNgEEBgABNgEEAgABKAMA ARQDAAENAwABAQEAAQgFAAEEAQEYAAGAAgABgAMAAoABAAGAAwABgAEAAYABAAKAAgADwAEAAcAB3AHA AQAB8AHKAaYBAAEzBQABMwEAATMBAAEzAQACMwIAAxYBAAMcAQADIgEAAykBAANVAQADTQEAA0IBAAM5 AQABgAF8Af8BAAJQAf8BAAGTAQAB1gEAAf8B7AHMAQABxgHWAe8BAAHWAucBAAGQAakBrQIAAf8BMwMA diff --git a/KancolleSniffer/ShipInfo.cs b/KancolleSniffer/ShipInfo.cs index 0513f93..1e878ba 100644 --- a/KancolleSniffer/ShipInfo.cs +++ b/KancolleSniffer/ShipInfo.cs @@ -60,14 +60,16 @@ namespace KancolleSniffer return ratio > 0.75 ? Damage.Minor : ratio > 0.5 ? Damage.Small : ratio > 0.25 ? Damage.Half : Damage.Badly; } - public TimeSpan RepairTime + public TimeSpan RepairTime() { - get - { - var weight = Spec.RepairWeight; - var level = Level < 12 ? Level * 10 : Level * 5 + Math.Floor(Math.Sqrt(Level - 11)) * 10 + 50; - return TimeSpan.FromSeconds(Math.Floor(level * weight * (MaxHp - NowHp)) + 30); - } + return RepairTime(MaxHp - NowHp); + } + + public TimeSpan RepairTime(int damage) + { + var weight = Spec.RepairWeight; + var level = Level < 12 ? Level * 10 : Level * 5 + Math.Floor(Math.Sqrt(Level - 11)) * 10 + 50; + return TimeSpan.FromSeconds(Math.Floor(level * weight * damage) + 30); } } @@ -347,7 +349,7 @@ namespace KancolleSniffer return (from entry in _shipInfo let status = entry.Value where status.NowHp < status.MaxHp && !dockInfo.InNDock(entry.Key) - select new RepairStatus(FindFleet(entry.Key, out oi), status.Name, status.RepairTime)). + select new RepairStatus(FindFleet(entry.Key, out oi), status.Name, status.RepairTime())). OrderByDescending(entry => entry.Time).ToArray(); } } diff --git a/KancolleSniffer/Sniffer.cs b/KancolleSniffer/Sniffer.cs index 041f81d..732c3bf 100644 --- a/KancolleSniffer/Sniffer.cs +++ b/KancolleSniffer/Sniffer.cs @@ -197,6 +197,7 @@ namespace KancolleSniffer if (url.EndsWith("api_req_nyukyo/start")) { _dockInfo.InspectNyukyo(request); + _akashiTimer.SetTimer(); return Update.Item | Update.Ship; } if (url.EndsWith("api_req_nyukyo/speedchange")) @@ -301,9 +302,9 @@ namespace KancolleSniffer get { return _shipInfo.GetDamagedShipList(_dockInfo); } } - public DateTime GetAkashiStartTime(int fleet) + public AkashiTimer.RepairSpan[] GetAkashiTimers(int fleet) { - return _akashiTimer[fleet]; + return _akashiTimer.GetTimers(fleet); } public Achievement Achievement