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