OSDN Git Service

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