OSDN Git Service

特別戦果の合計を表示する
[kancollesniffer/KancolleSniffer.git] / KancolleSniffer / ConditionTimer.cs
1 // Copyright (C) 2013, 2014, 2015 Kazuhiro Fujieda <fujieda@users.osdn.me>\r
2 // \r
3 // This program is part of KancolleSniffer.\r
4 //\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
9 //\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
14 //\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
17 \r
18 using System;\r
19 using System.Linq;\r
20 \r
21 namespace KancolleSniffer\r
22 {\r
23     public class ConditionTimer : IHaveState\r
24     {\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
31 \r
32         public bool NeedSave { get; private set; }\r
33 \r
34         public ConditionTimer(ShipInfo shipInfo)\r
35         {\r
36             _shipInfo = shipInfo;\r
37         }\r
38 \r
39         public void CalcRegenTime()\r
40         {\r
41             var now = DateTime.Now;\r
42             var prevTime = _lastUpdate;\r
43             var prevCond = _lastCond;\r
44             _lastUpdate = now;\r
45             _lastCond = _shipInfo.ShipList.Min(s => s.Cond);\r
46 // ReSharper disable once CompareOfFloatsByEqualityOperator\r
47             if (_regenTime == double.MinValue)\r
48             {\r
49                 ResetRegenTime(now);\r
50                 return;\r
51             }\r
52             if (prevCond == int.MinValue || prevCond == _lastCond)\r
53                 return;\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
59         }\r
60 \r
61         private DateTime NextRegenTime(DateTime now)\r
62         {\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
66         }\r
67 \r
68         private void ResetRegenTime(DateTime now)\r
69         {\r
70             _regenTime = (double)now.Ticks / TimeSpan.TicksPerSecond % Interval;\r
71             NeedSave = true;\r
72         }\r
73 \r
74         public void InvalidateCond()\r
75         {\r
76             _lastCond = int.MinValue;\r
77         }\r
78 \r
79         public void CheckCond()\r
80         {\r
81             if (_lastCond != _shipInfo.ShipList.Min(s => s.Cond))\r
82                 _lastCond = int.MinValue;\r
83         }\r
84 \r
85         public DateTime GetTimer(int fleet)\r
86         {\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
90             if (cond >= 49)\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
94         }\r
95 \r
96         public int[] GetNotice()\r
97         {\r
98             var result = new int[ShipInfo.FleetCount];\r
99             var now = DateTime.Now;\r
100             var prev = _prevNotice;\r
101             _prevNotice = now;\r
102             if (prev == DateTime.MinValue)\r
103                 return result;\r
104             for (var f = 0; f < result.Length; f++)\r
105             {\r
106                 if (_shipInfo.InMission(f) || _shipInfo.InSortie(f))\r
107                     continue;\r
108                 var timer = GetTimer(f);\r
109                 if (timer == DateTime.MinValue || prev < _lastUpdate)\r
110                     continue;\r
111                 if (prev < timer.AddMinutes(-9) && now >= timer.AddMinutes(-9))\r
112                     result[f] = 40;\r
113                 else if (prev < timer && now >= timer)\r
114                     result[f] = 49;\r
115             }\r
116             return result;\r
117         }\r
118 \r
119         public void SaveState(Status status)\r
120         {\r
121             NeedSave = false;\r
122             status.CondRegenTime = _regenTime;\r
123         }\r
124 \r
125         public void LoadState(Status status)\r
126         {\r
127             _regenTime = status.CondRegenTime;\r
128         }\r
129     }\r
130 }