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 // Licensed under the Apache License, Version 2.0 (the "License");\r
4 // you may not use this file except in compliance with the License.\r
5 // You may obtain a copy of the License at\r
6 //\r
7 //    http://www.apache.org/licenses/LICENSE-2.0\r
8 //\r
9 // Unless required by applicable law or agreed to in writing, software\r
10 // distributed under the License is distributed on an "AS IS" BASIS,\r
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
12 // See the License for the specific language governing permissions and\r
13 // limitations under the License.\r
14 \r
15 using System;\r
16 using System.Linq;\r
17 \r
18 namespace KancolleSniffer\r
19 {\r
20     public class ConditionTimer : IHaveState\r
21     {\r
22         private readonly ShipInfo _shipInfo;\r
23         private const int Interval = 180;\r
24         private int _lastCond = int.MinValue;\r
25         private DateTime _lastUpdate;\r
26         private double _regenTime;\r
27         private DateTime _prevNotice;\r
28 \r
29         public bool NeedSave { get; private set; }\r
30 \r
31         public ConditionTimer(ShipInfo shipInfo)\r
32         {\r
33             _shipInfo = shipInfo;\r
34         }\r
35 \r
36         public void CalcRegenTime()\r
37         {\r
38             var now = DateTime.Now;\r
39             var prevTime = _lastUpdate;\r
40             var prevCond = _lastCond;\r
41             _lastUpdate = now;\r
42             _lastCond = _shipInfo.ShipList.Min(s => s.Cond);\r
43 // ReSharper disable once CompareOfFloatsByEqualityOperator\r
44             if (_regenTime == double.MinValue)\r
45             {\r
46                 ResetRegenTime(now);\r
47                 return;\r
48             }\r
49             if (prevCond == int.MinValue || prevCond == _lastCond)\r
50                 return;\r
51             var next = NextRegenTime(prevTime);\r
52             var ticks = next > now ? 0 : (int)(now - next).TotalSeconds / Interval + 1;\r
53             var diff = (_lastCond - prevCond + 2) / 3 - ticks;\r
54             if (_lastCond == 49 ? diff > 0 : diff != 0)\r
55                 ResetRegenTime(now);\r
56         }\r
57 \r
58         private DateTime NextRegenTime(DateTime now)\r
59         {\r
60             var batch = new DateTime((long)((now.Ticks / TimeSpan.TicksPerSecond / Interval * Interval + _regenTime) *\r
61                                             TimeSpan.TicksPerSecond));\r
62             return batch < now ? batch.AddSeconds(Interval) : batch;\r
63         }\r
64 \r
65         private void ResetRegenTime(DateTime now)\r
66         {\r
67             _regenTime = (double)now.Ticks / TimeSpan.TicksPerSecond % Interval;\r
68             NeedSave = true;\r
69         }\r
70 \r
71         public void InvalidateCond()\r
72         {\r
73             _lastCond = int.MinValue;\r
74         }\r
75 \r
76         public void CheckCond()\r
77         {\r
78             if (_lastCond != _shipInfo.ShipList.Min(s => s.Cond))\r
79                 _lastCond = int.MinValue;\r
80         }\r
81 \r
82         public DateTime GetTimer(int fleet)\r
83         {\r
84             if (_shipInfo.InMission(fleet) || _shipInfo.InSortie(fleet))\r
85                 return DateTime.MinValue;\r
86             var cond = _shipInfo.GetShipStatuses(fleet).Select(s => s.Cond).DefaultIfEmpty(49).Min();\r
87             if (cond >= 49)\r
88                 return DateTime.MinValue;\r
89             var nextRegen = NextRegenTime(_lastUpdate);\r
90             return cond >= 46 ? nextRegen : nextRegen.AddSeconds((46 - cond + 2) / 3 * Interval);\r
91         }\r
92 \r
93         public int[] GetNotice()\r
94         {\r
95             var result = new int[ShipInfo.FleetCount];\r
96             var now = DateTime.Now;\r
97             var prev = _prevNotice;\r
98             _prevNotice = now;\r
99             if (prev == DateTime.MinValue)\r
100                 return result;\r
101             for (var f = 0; f < result.Length; f++)\r
102             {\r
103                 if (_shipInfo.InMission(f) || _shipInfo.InSortie(f))\r
104                     continue;\r
105                 var timer = GetTimer(f);\r
106                 if (timer == DateTime.MinValue || prev < _lastUpdate)\r
107                     continue;\r
108                 if (prev < timer.AddMinutes(-9) && now >= timer.AddMinutes(-9))\r
109                     result[f] = 40;\r
110                 else if (prev < timer && now >= timer)\r
111                     result[f] = 49;\r
112             }\r
113             return result;\r
114         }\r
115 \r
116         public void SaveState(Status status)\r
117         {\r
118             NeedSave = false;\r
119             status.CondRegenTime = _regenTime;\r
120         }\r
121 \r
122         public void LoadState(Status status)\r
123         {\r
124             _regenTime = status.CondRegenTime;\r
125         }\r
126     }\r
127 }