1 // Copyright (C) 2014 Kazuhiro Fujieda <fujieda@users.sourceforge.jp>
\r
3 // This program is part of KancolleSniffer.
\r
5 // KancolleSniffer is free software: you can redistribute it and/or modify
\r
6 // it under the terms of the GNU General Public License as published by
\r
7 // the Free Software Foundation, either version 3 of the License, or
\r
8 // (at your option) any later version.
\r
10 // This program is distributed in the hope that it will be useful,
\r
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
13 // GNU General Public License for more details.
\r
15 // You should have received a copy of the GNU General Public License
\r
16 // along with this program; if not, see <http://www.gnu.org/licenses/>.
\r
19 using System.Collections.Generic;
\r
22 namespace KancolleSniffer
\r
24 public class AkashiTimer
\r
26 private readonly ShipInfo _shipInfo;
\r
27 private readonly ItemInfo _itemInfo;
\r
28 private readonly DockInfo _dockInfo;
\r
29 private readonly RepairStatus[] _repairStatuses = new RepairStatus[ShipInfo.FleetCount];
\r
30 private DateTime _start;
\r
31 private DateTime _prev;
\r
33 public class RepairSpan
\r
35 public int Diff { get; set; }
\r
36 public TimeSpan Span { get; set; }
\r
38 public RepairSpan(int diff, TimeSpan span)
\r
45 private class RepairStatus
\r
47 private ShipStatus[] _target = new ShipStatus[0];
\r
48 private RepairSpan[][] _spans = new RepairSpan[0][];
\r
49 private int[] _deck = new int[0];
\r
53 set { _deck = value; }
\r
56 public void Invalidate()
\r
58 _target = new ShipStatus[0];
\r
59 _spans = new RepairSpan[0][];
\r
64 get { return _target.Sum(s => s.NowHp); }
\r
67 public bool DeckChanged(IEnumerable<int> deck)
\r
69 return !_deck.SequenceEqual(deck);
\r
72 public void UpdateTarget(ShipStatus[] target)
\r
78 private void CalcRepairSpan()
\r
80 _spans = (from s in _target
\r
81 let damage = s.MaxHp - s.NowHp
\r
82 let first = new RepairSpan(0, TimeSpan.FromMinutes(20))
\r
85 : new[] {first}.Concat(from d in Enumerable.Range(2, damage < 2 ? 0 : damage - 1)
\r
86 let sec = s.CalcRepairSec(d) + 60
\r
88 select new RepairSpan(d - 1, TimeSpan.FromSeconds(sec))).ToArray()).ToArray();
\r
91 public RepairSpan[] GetTimers(DateTime start, DateTime now)
\r
93 var span = TimeSpan.FromSeconds((int)(now - start).TotalSeconds);
\r
94 return (from spans in _spans
\r
95 select spans == null
\r
96 ? new RepairSpan(0, TimeSpan.MinValue)
\r
97 : (from s in spans select new RepairSpan(s.Diff, s.Span - span))
\r
98 .FirstOrDefault(s => s.Span > TimeSpan.Zero)
\r
99 ?? new RepairSpan(spans.Last().Diff + 1, TimeSpan.Zero)
\r
103 public string GetNotice(DateTime start, DateTime prev, DateTime now)
\r
105 var msg = string.Join(" ", from e in _spans.Zip(_target, (spans, ship) => new {spans, ship})
\r
106 where e.spans != null && e.spans.Any(
\r
107 s => s.Span - (prev - start) > TimeSpan.Zero && s.Span - (now - start) <= TimeSpan.Zero)
\r
108 select e.ship.Name);
\r
109 return msg == "" ? "" : "修理進行: " + msg;
\r
113 public AkashiTimer(ShipInfo ship, ItemInfo item, DockInfo dock)
\r
118 for (var i = 0; i < _repairStatuses.Length; i++)
\r
119 _repairStatuses[i] = new RepairStatus();
\r
122 public void SetTimer(bool port = false)
\r
125 for (var fleet = 0; fleet < ShipInfo.FleetCount; fleet++)
\r
127 if (CheckFleet(fleet, port))
\r
132 _start = DateTime.MinValue;
\r
135 if (_start == DateTime.MinValue)
\r
136 _start = DateTime.Now;
\r
139 private bool CheckFleet(int fleet, bool port)
\r
141 var deck = _shipInfo.GetDeck(fleet);
\r
142 var repair = _repairStatuses[fleet];
\r
144 if (!_shipInfo[fs].Name.StartsWith("明石") || _dockInfo.InNDock(fs) || _shipInfo.InMission(fleet))
\r
146 repair.Invalidate();
\r
149 if (repair.DeckChanged(deck))
\r
151 _start = DateTime.MinValue;
\r
152 repair.Invalidate();
\r
154 repair.Deck = deck.ToArray();
\r
155 var cap = _shipInfo[fs].Slot.Count(item => _itemInfo[item].Name == "艦艇修理施設") + 2;
\r
157 (from id in deck.Take(cap) select IsRepairable(id) ? _shipInfo[id] : new ShipStatus()).ToArray();
\r
158 var totalHp = target.Sum(s => s.NowHp);
\r
161 repair.Invalidate();
\r
164 if (totalHp == repair.TotalHp)
\r
166 if (port && repair.TotalHp > 0 && totalHp != repair.TotalHp)
\r
167 _start = DateTime.MinValue;
\r
168 repair.UpdateTarget(target);
\r
172 private bool IsRepairable(int id)
\r
174 var s = _shipInfo[id];
\r
175 return !_dockInfo.InNDock(id) && s.NowHp < s.MaxHp && s.DamageLevel < ShipStatus.Damage.Half;
\r
178 public RepairSpan[] GetTimers(int fleet)
\r
180 if (_start == DateTime.MinValue)
\r
181 return new RepairSpan[0];
\r
182 return _repairStatuses[fleet].GetTimers(_start, DateTime.Now);
\r
185 public string[] GetNotice()
\r
187 var now = DateTime.Now;
\r
190 if (prev == DateTime.MinValue || _start == DateTime.MinValue)
\r
191 return new string[0];
\r
192 if (prev - _start < TimeSpan.FromMinutes(20) && now - _start >= TimeSpan.FromMinutes(20))
\r
193 return new[] {"20分経過しました。"};
\r
194 return _repairStatuses.Select(repair => repair.GetNotice(_start, prev, now)).ToArray();
\r