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 \r
28         public bool NeedSave { get; private set; }\r
29 \r
30         public ConditionTimer(ShipInfo shipInfo)\r
31         {\r
32             _shipInfo = shipInfo;\r
33         }\r
34 \r
35         public void CalcRegenTime()\r
36         {\r
37             var now = DateTime.Now;\r
38             var prevTime = _lastUpdate;\r
39             var prevCond = _lastCond;\r
40             _lastUpdate = now;\r
41             _lastCond = _shipInfo.ShipList.Min(s => s.Cond);\r
42 // ReSharper disable once CompareOfFloatsByEqualityOperator\r
43             if (_regenTime == double.MinValue)\r
44             {\r
45                 ResetRegenTime(now);\r
46                 return;\r
47             }\r
48             if (prevCond == int.MinValue || prevCond == _lastCond)\r
49                 return;\r
50             var next = NextRegenTime(prevTime);\r
51             var ticks = next > now ? 0 : (int)(now - next).TotalSeconds / Interval + 1;\r
52             var diff = (_lastCond - prevCond + 2) / 3 - ticks;\r
53             if (_lastCond == 49 ? diff > 0 : diff != 0)\r
54                 ResetRegenTime(now);\r
55         }\r
56 \r
57         private DateTime NextRegenTime(DateTime now)\r
58         {\r
59             var batch = new DateTime((long)((now.Ticks / TimeSpan.TicksPerSecond / Interval * Interval + _regenTime) *\r
60                                             TimeSpan.TicksPerSecond));\r
61             return batch < now ? batch.AddSeconds(Interval) : batch;\r
62         }\r
63 \r
64         private void ResetRegenTime(DateTime now)\r
65         {\r
66             _regenTime = (double)now.Ticks / TimeSpan.TicksPerSecond % Interval;\r
67             NeedSave = true;\r
68         }\r
69 \r
70         public void InvalidateCond()\r
71         {\r
72             _lastCond = int.MinValue;\r
73         }\r
74 \r
75         public void CheckCond()\r
76         {\r
77             if (_lastCond != _shipInfo.ShipList.Min(s => s.Cond))\r
78                 _lastCond = int.MinValue;\r
79         }\r
80 \r
81         public DateTime GetTimer(int fleet)\r
82         {\r
83             if (_shipInfo.InMission[fleet] || _shipInfo.InSortie[fleet])\r
84                 return DateTime.MinValue;\r
85             var cond = _shipInfo.GetShipStatuses(fleet).Select(s => s.Cond).DefaultIfEmpty(49).Min();\r
86             if (cond >= 49)\r
87                 return DateTime.MinValue;\r
88             var nextRegen = NextRegenTime(_lastUpdate);\r
89             return cond >= 46 ? nextRegen : nextRegen.AddSeconds((46 - cond + 2) / 3 * Interval);\r
90         }\r
91 \r
92         public int[] GetNotice(DateTime prev, DateTime now)\r
93         {\r
94             var result = new int[ShipInfo.FleetCount];\r
95             if (prev == DateTime.MinValue)\r
96                 return result;\r
97             for (var f = 0; f < result.Length; f++)\r
98             {\r
99                 if (_shipInfo.InMission[f] || _shipInfo.InSortie[f])\r
100                     continue;\r
101                 var timer = GetTimer(f);\r
102                 if (timer == DateTime.MinValue || prev < _lastUpdate)\r
103                     continue;\r
104                 if (prev < timer.AddMinutes(-9) && now >= timer.AddMinutes(-9))\r
105                     result[f] = 40;\r
106                 else if (prev < timer && now >= timer)\r
107                     result[f] = 49;\r
108             }\r
109             return result;\r
110         }\r
111 \r
112         public void SaveState(Status status)\r
113         {\r
114             NeedSave = false;\r
115             status.CondRegenTime = _regenTime;\r
116         }\r
117 \r
118         public void LoadState(Status status)\r
119         {\r
120             _regenTime = status.CondRegenTime;\r
121         }\r
122     }\r
123 }