OSDN Git Service

資材ログに変動理由を付ける
[kancollesniffer/KancolleSniffer.git] / KancolleSniffer / Sniffer.cs
1 // Copyright (C) 2013, 2014 Kazuhiro Fujieda <fujieda@users.sourceforge.jp>\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 \r
20 namespace KancolleSniffer\r
21 {\r
22     public class Sniffer\r
23     {\r
24         private bool _start;\r
25         private readonly ShipMaster _shipMaster = new ShipMaster();\r
26         private readonly ItemInfo _itemInfo = new ItemInfo();\r
27         private readonly QuestInfo _questInfo = new QuestInfo();\r
28         private readonly MissionInfo _missionInfo = new MissionInfo();\r
29         private readonly ShipInfo _shipInfo;\r
30         private readonly DockInfo _dockInfo;\r
31         private readonly AkashiTimer _akashiTimer;\r
32         private readonly Achievement _achievement = new Achievement();\r
33         private readonly BattleInfo _battleInfo;\r
34         private readonly Logger _logger;\r
35         private readonly Status _status = new Status();\r
36 \r
37         [Flags]\r
38         public enum Update\r
39         {\r
40             None = 0,\r
41             Start = 1,\r
42             Item = 2,\r
43             Ship = 4,\r
44             Timer = 8,\r
45             NDock = 16,\r
46             Mission = 32,\r
47             QuestList = 64,\r
48             Battle = 128,\r
49             All = 255\r
50         }\r
51 \r
52         public Sniffer()\r
53         {\r
54             _shipInfo = new ShipInfo(_shipMaster, _itemInfo);\r
55             _dockInfo = new DockInfo(_shipInfo, _itemInfo);\r
56             _akashiTimer = new AkashiTimer(_shipInfo, _itemInfo, _dockInfo);\r
57             _battleInfo = new BattleInfo(_shipMaster, _shipInfo, _itemInfo);\r
58             _logger = new Logger(_shipMaster, _shipInfo, _itemInfo);\r
59         }\r
60 \r
61         public void SaveState()\r
62         {\r
63             _achievement.SaveState(_status);\r
64             _itemInfo.SaveState(_status);\r
65             _status.Save();\r
66         }\r
67 \r
68         public void LoadState()\r
69         {\r
70             _status.Load();\r
71             _achievement.LoadState(_status);\r
72             _itemInfo.LoadSate(_status);\r
73         }\r
74 \r
75         public Update Sniff(string url, string request, dynamic json)\r
76         {\r
77             var data = json.IsDefined("api_data") ? json.api_data : new object();\r
78 \r
79             if (url.EndsWith("api_start2"))\r
80             {\r
81                 _start = true;\r
82                 _shipMaster.Inspect(data);\r
83                 _missionInfo.InspectMaster(data.api_mst_mission);\r
84                 _itemInfo.InspectMaster(data);\r
85                 return Update.Start;\r
86             }\r
87             if (!_start)\r
88                 return Update.None;\r
89             if (url.EndsWith("api_port/port"))\r
90             {\r
91                 _itemInfo.InspectBasic(data.api_basic);\r
92                 _itemInfo.InspectMaterial(data.api_material);\r
93                 _logger.InspectBasic(data.api_basic);\r
94                 _logger.InspectMaterial(data.api_material);\r
95                 _shipInfo.InspectShip(data);\r
96                 _missionInfo.InspectDeck(data.api_deck_port);\r
97                 _dockInfo.InspectNDock(data.api_ndock);\r
98                 _akashiTimer.SetTimer(true);\r
99                 _achievement.InspectBasic(data.api_basic);\r
100                 _battleInfo.InBattle = false;\r
101                 _battleInfo.HasDamagedShip = false;\r
102                 _shipInfo.ClearEscapedShips();\r
103                 return Update.All;\r
104             }\r
105             if (url.EndsWith("api_get_member/basic"))\r
106             {\r
107                 _itemInfo.InspectBasic(data);\r
108                 _logger.InspectBasic(data);\r
109                 return Update.None;\r
110             }\r
111             if (url.EndsWith("api_get_member/slot_item"))\r
112             {\r
113                 _itemInfo.InspectSlotItem(data, true);\r
114                 return Update.None;\r
115             }\r
116             if (url.EndsWith("api_get_member/kdock"))\r
117             {\r
118                 _dockInfo.InspectKDock(data);\r
119                 _logger.InspectKDock(data);\r
120                 return Update.Timer;\r
121             }\r
122             if (url.EndsWith("api_get_member/ndock"))\r
123             {\r
124                 _dockInfo.InspectNDock(data);\r
125                 _akashiTimer.SetTimer();\r
126                 return Update.NDock | Update.Timer | Update.Ship;\r
127             }\r
128             if (url.EndsWith("api_req_hensei/change"))\r
129             {\r
130                 _shipInfo.InspectChange(request);\r
131                 _akashiTimer.SetTimer();\r
132                 return Update.Ship;\r
133             }\r
134             if (url.EndsWith("api_get_member/questlist"))\r
135             {\r
136                 _questInfo.Inspect(data);\r
137                 return Update.QuestList;\r
138             }\r
139             if (url.EndsWith("api_get_member/deck"))\r
140             {\r
141                 _shipInfo.InspectDeck(data);\r
142                 _missionInfo.InspectDeck(data);\r
143                 _akashiTimer.SetTimer();\r
144                 return Update.Mission | Update.Timer;\r
145             }\r
146             if (url.EndsWith("api_get_member/ship2"))\r
147             {\r
148                 // ここだけjsonなので注意\r
149                 _shipInfo.InspectShip(json);\r
150                 _akashiTimer.SetTimer();\r
151                 _battleInfo.InBattle = false;\r
152                 return Update.Item | Update.Ship | Update.Battle;\r
153             }\r
154             if (url.EndsWith("api_get_member/ship3"))\r
155             {\r
156                 _shipInfo.InspectShip(data);\r
157                 _akashiTimer.SetTimer();\r
158                 return Update.Ship;\r
159             }\r
160             if (url.EndsWith("api_get_member/material"))\r
161             {\r
162                 _itemInfo.InspectMaterial(data);\r
163                 _logger.InspectMaterial(data);\r
164                 return Update.Item;\r
165             }\r
166             if (url.EndsWith("api_req_hokyu/charge"))\r
167             {\r
168                 _shipInfo.InspectCharge(data);\r
169                 _logger.InspectCharge(data);\r
170                 return Update.Item | Update.Ship;\r
171             }\r
172             if (url.EndsWith("api_req_kousyou/createitem"))\r
173             {\r
174                 _itemInfo.InspectCreateItem(data);\r
175                 _logger.InspectCreateItem(request, data);\r
176                 return Update.Item;\r
177             }\r
178             if (url.EndsWith("api_req_kousyou/getship"))\r
179             {\r
180                 _itemInfo.InspectGetShip(data);\r
181                 _shipInfo.InspectShip(data);\r
182                 _dockInfo.InspectKDock(data.api_kdock);\r
183                 return Update.Item | Update.Timer;\r
184             }\r
185             if (url.EndsWith("api_req_kousyou/destroyship"))\r
186             {\r
187                 _shipInfo.InspectDestroyShip(request, data);\r
188                 _akashiTimer.SetTimer();\r
189                 return Update.Item | Update.Ship;\r
190             }\r
191             if (url.EndsWith("api_req_kousyou/destroyitem2"))\r
192             {\r
193                 _itemInfo.InspectDestroyItem(request, data);\r
194                 return Update.Item;\r
195             }\r
196             if (url.EndsWith("api_req_kousyou/remodel_slot"))\r
197             {\r
198                 _itemInfo.InspectRemodelSlot(data);\r
199                 return Update.Item;\r
200             }\r
201             if (url.EndsWith("api_req_kousyou/createship"))\r
202             {\r
203                 _logger.InspectCreateShip(request);\r
204                 return Update.None;\r
205             }\r
206             if (url.EndsWith("api_req_kaisou/powerup"))\r
207             {\r
208                 _shipInfo.InspectPowerup(request, data);\r
209                 _akashiTimer.SetTimer();\r
210                 return Update.Item | Update.Ship;\r
211             }\r
212             if (url.EndsWith("api_req_kaisou/remodeling"))\r
213             {\r
214                 _logger.InspectRemodeling();\r
215                 return Update.None;\r
216             }\r
217             if (url.EndsWith("api_req_nyukyo/start"))\r
218             {\r
219                 _dockInfo.InspectNyukyo(request);\r
220                 _akashiTimer.SetTimer();\r
221                 return Update.Item | Update.Ship;\r
222             }\r
223             if (url.EndsWith("api_req_nyukyo/speedchange"))\r
224             {\r
225                 _dockInfo.InspectSpeedChange(request);\r
226                 return Update.NDock | Update.Timer | Update.Ship;\r
227             }\r
228             if (IsNormalBattleAPI(url))\r
229             {\r
230                 _battleInfo.InspectBattle(data);\r
231                 if (!url.EndsWith("api_req_practice/battle"))\r
232                 {\r
233                     _logger.InspectBattle(data);\r
234                     return Update.Battle;\r
235                 }\r
236                 _shipInfo.StartSortie(request); // 演習を出撃中とみなす\r
237                 return Update.Battle | Update.Timer;\r
238             }\r
239             if (url.EndsWith("api_req_sortie/battleresult"))\r
240             {\r
241                 _battleInfo.CauseDamage();\r
242                 _logger.InspectBattleResult(data);\r
243                 return Update.Ship;\r
244             }\r
245             if (url.EndsWith("api_req_practice/battle_result"))\r
246             {\r
247                 _battleInfo.CausePracticeDamage();\r
248                 return Update.Ship;\r
249             }\r
250             if (IsCombinedBattleAPI(url))\r
251             {\r
252                 _battleInfo.InspectCombinedBattle(data, url.EndsWith("battle_water"));\r
253                 _logger.InspectBattle(data);\r
254                 return Update.Battle;\r
255             }\r
256             if (url.EndsWith("api_req_combined_battle/battleresult"))\r
257             {\r
258                 _battleInfo.InspectCombinedBattleResult(data);\r
259                 _logger.InspectBattleResult(data);\r
260                 return Update.Ship;\r
261             }\r
262             if (url.EndsWith("api_req_combined_battle/goback_port"))\r
263             {\r
264                 _battleInfo.CauseCombinedBattleEscape();\r
265                 return Update.None;\r
266             }\r
267             if (url.EndsWith("api_req_map/start"))\r
268             {\r
269                 _shipInfo.StartSortie(request);\r
270                 _logger.InspectMap(data);\r
271                 return Update.Timer;\r
272             }\r
273             if (url.EndsWith("api_req_map/next"))\r
274             {\r
275                 _logger.InspectMap(data);\r
276                 return Update.None;\r
277             }\r
278             if (url.EndsWith("api_req_mission/result"))\r
279             {\r
280                 _itemInfo.InspectMissionResult(data);\r
281                 _logger.InspectMissionResult(data);\r
282                 return Update.Item;\r
283             }\r
284             if (url.EndsWith("api_req_quest/clearitemget"))\r
285             {\r
286                 _logger.InspectClearItemGet();\r
287                 return Update.None;\r
288             }\r
289             return Update.None;\r
290         }\r
291 \r
292         public bool IsBattleAPI(string url)\r
293         {\r
294             return IsNormalBattleAPI(url) || IsCombinedBattleAPI(url);\r
295         }\r
296 \r
297         public bool IsNormalBattleAPI(string url)\r
298         {\r
299             return url.EndsWith("api_req_sortie/battle") || url.EndsWith("api_req_practice/battle") ||\r
300                    url.EndsWith("api_req_battle_midnight/battle") ||\r
301                    url.EndsWith("api_req_battle_midnight/sp_midnight") ||\r
302                    url.EndsWith("api_req_practice/midnight_battle");\r
303         }\r
304 \r
305         public bool IsCombinedBattleAPI(string url)\r
306         {\r
307             return url.EndsWith("api_req_combined_battle/battle") ||\r
308                    url.EndsWith("api_req_combined_battle/airbattle") ||\r
309                    url.EndsWith("api_req_combined_battle/battle_water") ||\r
310                    url.EndsWith("api_req_combined_battle/midnight_battle") ||\r
311                    url.EndsWith("api_req_combined_battle/sp_midnight");\r
312         }\r
313 \r
314         public NameAndTimer[] NDock\r
315         {\r
316             get { return _dockInfo.NDock; }\r
317         }\r
318 \r
319         public RingTimer[] KDock\r
320         {\r
321             get { return _dockInfo.KDock; }\r
322         }\r
323 \r
324         public ItemInfo Item\r
325         {\r
326             get { return _itemInfo; }\r
327         }\r
328 \r
329         public QuestInfo.NameAndProgress[] Quests\r
330         {\r
331             get { return _questInfo.Quests; }\r
332         }\r
333 \r
334         public NameAndTimer[] Missions\r
335         {\r
336             get { return _missionInfo.Missions; }\r
337         }\r
338 \r
339         public DateTime GetConditionTimer(int fleet)\r
340         {\r
341             return _shipInfo.GetConditionTiemr(fleet);\r
342         }\r
343 \r
344         public int[] GetConditionNotice()\r
345         {\r
346             return _shipInfo.GetConditionNotice();\r
347         }\r
348 \r
349         public ShipStatus[] GetShipStatuses(int fleet)\r
350         {\r
351             return _shipInfo.GetShipStatuses(fleet);\r
352         }\r
353 \r
354         public int[] GetDeck(int fleet)\r
355         {\r
356             return _shipInfo.GetDeck(fleet);\r
357         }\r
358 \r
359         public ChargeStatus[] ChargeStatuses\r
360         {\r
361             get { return _shipInfo.ChargeStatuses; }\r
362         }\r
363 \r
364         public int GetAirSuperiority(int fleet)\r
365         {\r
366             return _shipInfo.GetAirSuperiority(fleet);\r
367         }\r
368 \r
369         public double GetFleetLineOfSights(int fleet)\r
370         {\r
371             return _shipInfo.GetLineOfSights(fleet);\r
372         }\r
373 \r
374         public ShipStatus[] DamagedShipList\r
375         {\r
376             get { return _shipInfo.GetDamagedShipList(_dockInfo); }\r
377         }\r
378 \r
379         public ShipStatus[] ShipList\r
380         {\r
381             get { return _shipInfo.ShipList; }\r
382         }\r
383 \r
384         public AkashiTimer.RepairSpan[] GetAkashiTimers(int fleet)\r
385         {\r
386             return _akashiTimer.GetTimers(fleet);\r
387         }\r
388 \r
389         public string[] GetAkashiTimerNotice()\r
390         {\r
391             return _akashiTimer.GetNotice();\r
392         }\r
393 \r
394         public Achievement Achievement\r
395         {\r
396             get { return _achievement; }\r
397         }\r
398 \r
399         public BattleInfo Battle\r
400         {\r
401             get { return _battleInfo; }\r
402         }\r
403 \r
404         public void SetLogWriter(Action<string, string, string> writer, Func<DateTime> nowFunc)\r
405         {\r
406             _logger.SetWriter(writer, nowFunc);\r
407         }\r
408 \r
409         public void SkipMaster()\r
410         {\r
411             _start = true;\r
412         }\r
413 \r
414         public void EnableLog(LogType type)\r
415         {\r
416             _logger.EnableLog(type);\r
417         }\r
418     }\r
419 \r
420     public class NameAndTimer\r
421     {\r
422         public string Name { get; set; }\r
423         public RingTimer Timer { get; set; }\r
424 \r
425         public NameAndTimer()\r
426         {\r
427             Timer = new RingTimer();\r
428         }\r
429     }\r
430 \r
431     public class RingTimer\r
432     {\r
433         private DateTime _endTime;\r
434         private TimeSpan _rest;\r
435         private readonly TimeSpan _spare;\r
436 \r
437         public RingTimer(int spare = 60)\r
438         {\r
439             _spare = TimeSpan.FromSeconds(spare);\r
440         }\r
441 \r
442         public void SetEndTime(double time)\r
443         {\r
444             SetEndTime((int)time == 0\r
445                 ? DateTime.MinValue\r
446                 : new DateTime(1970, 1, 1).ToLocalTime().AddSeconds(time / 1000));\r
447         }\r
448 \r
449         public void SetEndTime(DateTime time)\r
450         {\r
451             _endTime = time;\r
452             if (_endTime == DateTime.MinValue)\r
453                 IsFinished = false;\r
454         }\r
455 \r
456         public void Update()\r
457         {\r
458             if (_endTime == DateTime.MinValue)\r
459             {\r
460                 _rest = TimeSpan.Zero;\r
461                 return;\r
462             }\r
463             _rest = _endTime - DateTime.Now;\r
464             if (_rest < TimeSpan.Zero)\r
465                 _rest = TimeSpan.Zero;\r
466             if (_rest > _spare || IsFinished)\r
467                 return;\r
468             IsFinished = true;\r
469             NeedRing = true;\r
470         }\r
471 \r
472         public bool IsFinished { get; private set; }\r
473         public bool NeedRing { get; set; }\r
474 \r
475         public override string ToString()\r
476         {\r
477             return _rest.Days == 0 ? _rest.ToString(@"hh\:mm\:ss") : _rest.ToString(@"d\.hh\:mm");\r
478         }\r
479     }\r
480 }