OSDN Git Service

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