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
21 namespace KancolleSniffer
\r
23 public class AkashiTimer
\r
25 private readonly ShipInfo _shipInfo;
\r
26 private readonly ItemInfo _itemInfo;
\r
27 private readonly DockInfo _dockInfo;
\r
28 private readonly MissionInfo _missionInfo;
\r
29 private readonly RepairStatus[] _repairStatuses = new RepairStatus[ShipInfo.FleetCount];
\r
31 private struct RepairStatus
\r
33 public DateTime Timer { get; set; }
\r
34 public int TotalHp { get; set; }
\r
35 public int[] Deck { private get; set; }
\r
37 public void Invalidate()
\r
39 Timer = DateTime.MinValue;
\r
44 public bool DeckChanged(int[] deck)
\r
46 return Deck != null && Deck.Where((t, i) => deck[i] != t).Any();
\r
50 public AkashiTimer(ShipInfo ship, ItemInfo item, DockInfo dock, MissionInfo mission)
\r
55 _missionInfo = mission;
\r
58 public void SetTimer(bool port = false)
\r
60 for (var fleet = 0; fleet < ShipInfo.FleetCount; fleet++)
\r
61 SetTimer(fleet, port);
\r
64 private void SetTimer(int fleet, bool port)
\r
66 var deck = _shipInfo.GetDeck(fleet);
\r
68 if (!_shipInfo[fs].Name.StartsWith("明石") || _dockInfo.InNDock(fs) || _missionInfo.InMission(fleet))
\r
70 InvalidateTimer(fleet);
\r
73 if (_repairStatuses[fleet].DeckChanged(deck))
\r
74 InvalidateTimer(fleet);
\r
75 var cap = _shipInfo[fs].Slot.Count(item => _itemInfo[item].Name == "艦艇修理施設") + 2;
\r
76 var targets = deck.Take(cap).Where(id => !_dockInfo.InNDock(id)).ToArray();
\r
77 var totalHp = (from id in targets
\r
78 let status = _shipInfo[id]
\r
79 where status.NowHp < status.MaxHp && status.DamageLevel < ShipStatus.Damage.Half
\r
80 select status.NowHp).Sum();
\r
83 InvalidateTimer(fleet);
\r
86 var r = _repairStatuses[fleet];
\r
87 if (r.TotalHp == totalHp)
\r
89 var timer = r.Timer;
\r
91 * 母港に遷移したときに、耐久値が回復しているか修理開始から20分経過しているときに
\r
94 * Q. なぜ20分でリスタートするのか?
\r
96 * A. 明石の修理は戦闘中も続くので、戦闘中に修理開始から20分経つと母港に戻った
\r
97 * ときに耐久値が回復する。最後の戦闘で損傷すると、損傷と回復が同時に耐久値に
\r
98 * 反映されて回復が起こったことがわからない。耐久値の回復だけを基準にすると
\r
99 * リスタートできないので、20分経過していたらリスタートする。
\r
101 if (timer == DateTime.MinValue ||
\r
102 (port && (totalHp > r.TotalHp || (DateTime.Now - timer).TotalMinutes > 20)))
\r
103 timer = DateTime.Now;
\r
104 _repairStatuses[fleet] = new RepairStatus
\r
108 Deck = deck.ToArray()
\r
112 private void InvalidateTimer(int fleet)
\r
114 _repairStatuses[fleet].Invalidate();
\r
117 public DateTime this[int fleet]
\r
119 get { return _repairStatuses[fleet].Timer; }
\r