OSDN Git Service

艦隊に関する責務をShipInfoからFleetクラスに移す
[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             var target = _shipInfo.Fleets[fleet];\r
84             if (target.State != FleetState.Port)\r
85                 return DateTime.MinValue;\r
86             var cond = target.Ships.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(DateTime prev, DateTime now)\r
94         {\r
95             var result = new int[ShipInfo.FleetCount];\r
96             if (prev == DateTime.MinValue)\r
97                 return result;\r
98             for (var f = 0; f < result.Length; f++)\r
99             {\r
100                 if (_shipInfo.Fleets[f].State != FleetState.Port)\r
101                     continue;\r
102                 var timer = GetTimer(f);\r
103                 if (timer == DateTime.MinValue || prev < _lastUpdate)\r
104                     continue;\r
105                 if (prev < timer.AddMinutes(-9) && now >= timer.AddMinutes(-9))\r
106                     result[f] = 40;\r
107                 else if (prev < timer && now >= timer)\r
108                     result[f] = 49;\r
109             }\r
110             return result;\r
111         }\r
112 \r
113         public void SaveState(Status status)\r
114         {\r
115             NeedSave = false;\r
116             status.CondRegenTime = _regenTime;\r
117         }\r
118 \r
119         public void LoadState(Status status)\r
120         {\r
121             _regenTime = status.CondRegenTime;\r
122         }\r
123     }\r
124 }