OSDN Git Service

ボス前で空襲戦があるとボス戦で大破警告が出るのを直す
[kancollesniffer/KancolleSniffer.git] / KancolleSniffer / Model / 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.Model\r
19 {\r
20     public class ConditionTimer : IHaveState, Sniffer.IPort\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 _regainTime;\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 Port()\r
36         {\r
37             CalcRegainTime();\r
38         }\r
39 \r
40         private void CalcRegainTime()\r
41         {\r
42             var now = DateTime.Now;\r
43             var prevTime = _lastUpdate;\r
44             var prevCond = _lastCond;\r
45             _lastUpdate = now;\r
46             _lastCond = _shipInfo.ShipList.Min(s => s.Cond);\r
47 // ReSharper disable once CompareOfFloatsByEqualityOperator\r
48             if (_regainTime == double.MinValue)\r
49             {\r
50                 ResetRegainTime(now);\r
51                 return;\r
52             }\r
53             if (prevCond == int.MinValue || prevCond == _lastCond)\r
54                 return;\r
55             var next = NextRegainTime(prevTime);\r
56             var ticks = next > now ? 0 : (int)(now - next).TotalSeconds / Interval + 1;\r
57             var diff = (_lastCond - prevCond + 2) / 3 - ticks;\r
58             if (_lastCond == 49 ? diff > 0 : diff != 0)\r
59                 ResetRegainTime(now);\r
60         }\r
61 \r
62         private DateTime NextRegainTime(DateTime now)\r
63         {\r
64             var batch = new DateTime((long)((now.Ticks / TimeSpan.TicksPerSecond / Interval * Interval + _regainTime) *\r
65                                             TimeSpan.TicksPerSecond));\r
66             return batch < now ? batch.AddSeconds(Interval) : batch;\r
67         }\r
68 \r
69         private void ResetRegainTime(DateTime now)\r
70         {\r
71             _regainTime = (double)now.Ticks / TimeSpan.TicksPerSecond % Interval;\r
72             NeedSave = true;\r
73         }\r
74 \r
75         public void InvalidateCond()\r
76         {\r
77             _lastCond = int.MinValue;\r
78         }\r
79 \r
80         public void CheckCond()\r
81         {\r
82             if (_lastCond != _shipInfo.ShipList.Min(s => s.Cond))\r
83                 _lastCond = int.MinValue;\r
84         }\r
85 \r
86         public DateTime GetTimer(int fleet)\r
87         {\r
88             var target = _shipInfo.Fleets[fleet];\r
89             if (target.State != FleetState.Port)\r
90                 return DateTime.MinValue;\r
91             var cond = target.ActualShips.Select(s => s.Cond).DefaultIfEmpty(49).Min();\r
92             if (cond >= 49)\r
93                 return DateTime.MinValue;\r
94             var nextRegain = NextRegainTime(_lastUpdate);\r
95             return cond >= 46 ? nextRegain : nextRegain.AddSeconds((46 - cond + 2) / 3 * Interval);\r
96         }\r
97 \r
98         public int[] GetNotice(DateTime prev, DateTime now)\r
99         {\r
100             var result = new int[ShipInfo.FleetCount];\r
101             if (prev == DateTime.MinValue)\r
102                 return result;\r
103             foreach (var fleet in _shipInfo.Fleets)\r
104             {\r
105                 if (fleet.State != FleetState.Port)\r
106                     continue;\r
107                 var timer = GetTimer(fleet.Number);\r
108                 if (timer == DateTime.MinValue || prev < _lastUpdate)\r
109                     continue;\r
110                 if (prev < timer.AddMinutes(-9) && now >= timer.AddMinutes(-9))\r
111                     result[fleet.Number] = 40;\r
112                 else if (prev < timer && now >= timer)\r
113                     result[fleet.Number] = 49;\r
114             }\r
115             return result;\r
116         }\r
117 \r
118         public void SaveState(Status status)\r
119         {\r
120             NeedSave = false;\r
121             status.CondRegenTime = _regainTime;\r
122         }\r
123 \r
124         public void LoadState(Status status)\r
125         {\r
126             _regainTime = status.CondRegenTime;\r
127         }\r
128     }\r
129 }