1 // Copyright (C) 2013, 2014, 2015 Kazuhiro Fujieda <fujieda@users.osdn.me>
\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 ConditionTimer : IHaveState
\r
25 private readonly ShipInfo _shipInfo;
\r
26 private const int Interval = 180;
\r
27 private int _lastCond = int.MinValue;
\r
28 private DateTime _lastUpdate;
\r
29 private double _regenTime;
\r
30 private DateTime _prevNotice;
\r
32 public bool NeedSave { get; private set; }
\r
34 public ConditionTimer(ShipInfo shipInfo)
\r
36 _shipInfo = shipInfo;
\r
39 public void CalcRegenTime()
\r
41 var now = DateTime.Now;
\r
42 var prevTime = _lastUpdate;
\r
43 var prevCond = _lastCond;
\r
45 _lastCond = _shipInfo.ShipList.Min(s => s.Cond);
\r
46 // ReSharper disable once CompareOfFloatsByEqualityOperator
\r
47 if (_regenTime == double.MinValue)
\r
49 ResetRegenTime(now);
\r
52 if (prevCond == int.MinValue || prevCond == _lastCond)
\r
54 var next = NextRegenTime(prevTime);
\r
55 var ticks = next > now ? 0 : (int)(now - next).TotalSeconds / Interval + 1;
\r
56 var diff = (_lastCond - prevCond + 2) / 3 - ticks;
\r
57 if (_lastCond == 49 ? diff > 0 : diff != 0)
\r
58 ResetRegenTime(now);
\r
61 private DateTime NextRegenTime(DateTime now)
\r
63 var batch = new DateTime((long)((now.Ticks / TimeSpan.TicksPerSecond / Interval * Interval + _regenTime) *
\r
64 TimeSpan.TicksPerSecond));
\r
65 return batch < now ? batch.AddSeconds(Interval) : batch;
\r
68 private void ResetRegenTime(DateTime now)
\r
70 _regenTime = (double)now.Ticks / TimeSpan.TicksPerSecond % Interval;
\r
74 public void InvalidateCond()
\r
76 _lastCond = int.MinValue;
\r
79 public void CheckCond()
\r
81 if (_lastCond != _shipInfo.ShipList.Min(s => s.Cond))
\r
82 _lastCond = int.MinValue;
\r
85 public DateTime GetTimer(int fleet)
\r
87 if (_shipInfo.InMission(fleet) || _shipInfo.InSortie(fleet))
\r
88 return DateTime.MinValue;
\r
89 var cond = _shipInfo.GetShipStatuses(fleet).Select(s => s.Cond).DefaultIfEmpty(49).Min();
\r
91 return DateTime.MinValue;
\r
92 var nextRegen = NextRegenTime(_lastUpdate);
\r
93 return cond >= 46 ? nextRegen : nextRegen.AddSeconds((46 - cond + 2) / 3 * Interval);
\r
96 public int[] GetNotice()
\r
98 var result = new int[ShipInfo.FleetCount];
\r
99 var now = DateTime.Now;
\r
100 var prev = _prevNotice;
\r
102 if (prev == DateTime.MinValue)
\r
104 for (var f = 0; f < result.Length; f++)
\r
106 if (_shipInfo.InMission(f) || _shipInfo.InSortie(f))
\r
108 var timer = GetTimer(f);
\r
109 if (timer == DateTime.MinValue || prev < _lastUpdate)
\r
111 if (prev < timer.AddMinutes(-9) && now >= timer.AddMinutes(-9))
\r
113 else if (prev < timer && now >= timer)
\r
119 public void SaveState(Status status)
\r
122 status.CondRegenTime = _regenTime;
\r
125 public void LoadState(Status status)
\r
127 _regenTime = status.CondRegenTime;
\r