OSDN Git Service

各種報告書のドロップと海戦にマップ番号を追加する
[kancollesniffer/KancolleSniffer.git] / KancolleSniffer / Sniffer.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 KancolleSniffer.Util;\r
17 using System.Collections.Generic;\r
18 using System.Linq;\r
19 using KancolleSniffer.Log;\r
20 using KancolleSniffer.Model;\r
21 \r
22 namespace KancolleSniffer\r
23 {\r
24     public class Sniffer\r
25     {\r
26         private bool _start;\r
27         private readonly ItemMaster _itemMaster = new ItemMaster();\r
28         private readonly ItemInventory _itemInventory = new ItemInventory();\r
29         private readonly ItemInfo _itemInfo;\r
30         private readonly ShipMaster _shipMaster = new ShipMaster();\r
31         private readonly ShipInventory _shipInventory = new ShipInventory();\r
32         private readonly ShipInfo _shipInfo;\r
33         private readonly MaterialInfo _materialInfo = new MaterialInfo();\r
34         private readonly QuestInfo _questInfo;\r
35         private readonly MissionInfo _missionInfo = new MissionInfo();\r
36         private readonly ConditionTimer _conditionTimer;\r
37         private readonly DockInfo _dockInfo;\r
38         private readonly AkashiTimer _akashiTimer;\r
39         private readonly Achievement _achievement = new Achievement();\r
40         private readonly BattleInfo _battleInfo;\r
41         private readonly Logger _logger;\r
42         private readonly ExMapInfo _exMapInfo = new ExMapInfo();\r
43         private readonly MiscTextInfo _miscTextInfo;\r
44         private readonly BaseAirCorps _baseAirCorps;\r
45         private readonly PresetDeck _presetDeck = new PresetDeck();\r
46         private readonly CellInfo _cellInfo = new CellInfo();\r
47         private readonly Status _status = new Status();\r
48         private bool _saveState;\r
49         private readonly List<IHaveState> _haveState;\r
50         private AdditionalData _additionalData;\r
51 \r
52         public interface IRepeatingTimerController\r
53         {\r
54             void Stop(string key);\r
55             void Stop(string key, int fleet);\r
56             void Suspend(string exception = null);\r
57             void Resume();\r
58         }\r
59 \r
60         public IRepeatingTimerController RepeatingTimerController { get; set; }\r
61 \r
62         public Dictionary<string, string> MapDictionary { get; } = new Dictionary<string, string>();\r
63 \r
64         [Flags]\r
65         public enum Update\r
66         {\r
67             None = 0,\r
68             Error = 1 << 0,\r
69             Start = 1 << 1,\r
70             Item = 1 << 2,\r
71             Ship = 1 << 3,\r
72             Timer = 1 << 4,\r
73             NDock = 1 << 5,\r
74             Mission = 1 << 6,\r
75             QuestList = 1 << 7,\r
76             Battle = 1 << 8,\r
77             Cell = 1 << 9,\r
78             All = (1 << 10) - 1\r
79         }\r
80 \r
81         public Sniffer(bool start = false)\r
82         {\r
83             _start = start;\r
84             _itemInfo = new ItemInfo(_itemMaster, _itemInventory);\r
85             _shipInfo = new ShipInfo(_shipMaster, _shipInventory, _itemInventory);\r
86             _conditionTimer = new ConditionTimer(_shipInfo);\r
87             _dockInfo = new DockInfo(_shipInventory, _materialInfo);\r
88             _akashiTimer = new AkashiTimer(_shipInfo, _dockInfo, _presetDeck);\r
89             _battleInfo = new BattleInfo(_shipInfo, _itemInfo);\r
90             _logger = new Logger(_shipInfo, _itemInfo, _battleInfo);\r
91             _questInfo = new QuestInfo(_itemInfo, _battleInfo);\r
92             _baseAirCorps = new BaseAirCorps(_itemInfo);\r
93             _miscTextInfo = new MiscTextInfo(_shipInfo, _itemInfo);\r
94             _haveState = new List<IHaveState> {_achievement, _materialInfo, _conditionTimer, _exMapInfo, _questInfo};\r
95             AdditionalData = new AdditionalData();\r
96         }\r
97 \r
98         public AdditionalData AdditionalData\r
99         {\r
100             get => _additionalData;\r
101             set\r
102             {\r
103                 _additionalData = value;\r
104                 _itemMaster.AdditionalData = value;\r
105                 _shipMaster.AdditionalData = value;\r
106             }\r
107         }\r
108 \r
109         public void SaveState()\r
110         {\r
111             if (!_saveState)\r
112                 return;\r
113             if (!_haveState.Any(x => x.NeedSave))\r
114                 return;\r
115             foreach (var x in _haveState)\r
116                 x.SaveState(_status);\r
117             _status.Save();\r
118         }\r
119 \r
120         public void LoadState()\r
121         {\r
122             _status.Load();\r
123             foreach (var x in _haveState)\r
124                 x.LoadState(_status);\r
125             _saveState = true;\r
126         }\r
127 \r
128         public Update Sniff(string url, string request, dynamic json)\r
129         {\r
130             if (!json.api_result())\r
131                 return Update.Error;\r
132             if ((int)json.api_result != 1)\r
133                 return Update.None;\r
134             var data = json.api_data() ? json.api_data : new object();\r
135 \r
136             if (url.Contains("api_start2"))\r
137             {\r
138                 return ApiStart(data);\r
139             }\r
140             if (!_start)\r
141                 return Update.None;\r
142 \r
143             if (url.EndsWith("api_port/port"))\r
144                 return ApiPort(data);\r
145             if (url.Contains("member"))\r
146                 return ApiMember(url, json);\r
147             if (url.Contains("kousyou"))\r
148                 return ApiKousyou(url, request, data);\r
149             if (url.Contains("battle") || url.Contains("sortie"))\r
150                 return ApiBattle(url, request, data);\r
151             if (url.Contains("hensei"))\r
152                 return ApiHensei(url, request, data);\r
153             if (url.Contains("kaisou"))\r
154                 return ApiKaisou(url, request, data);\r
155             if (url.Contains("air_corps"))\r
156                 return ApiAirCorps(url, request, data);\r
157             return ApiOthers(url, request, data);\r
158         }\r
159 \r
160         private Update ApiStart(dynamic data)\r
161         {\r
162             _shipInfo.InspectMaster(data);\r
163             _missionInfo.InspectMaster(data.api_mst_mission);\r
164             _itemInfo.InspectMaster(data);\r
165             _exMapInfo.ResetIfNeeded();\r
166             _miscTextInfo.InspectMaster(data);\r
167             SetMapDictionary(data.api_mst_mapinfo);\r
168             _start = true;\r
169             return Update.Start;\r
170         }\r
171 \r
172         private void SetMapDictionary(dynamic json)\r
173         {\r
174             foreach (var map in json)\r
175                 MapDictionary[map.api_name] = $"{map.api_maparea_id}-{map.api_no}";\r
176         }\r
177 \r
178         private Update ApiPort(dynamic data)\r
179         {\r
180             _itemInfo.InspectBasic(data.api_basic);\r
181             _materialInfo.InspectMaterialPort(data.api_material);\r
182             _logger.InspectBasic(data.api_basic);\r
183             _logger.InspectMaterial(data.api_material);\r
184             _shipInfo.InspectShip(data);\r
185             _shipInfo.ClearBadlyDamagedShips();\r
186             _conditionTimer.CalcRegainTime();\r
187             _missionInfo.InspectDeck(data.api_deck_port);\r
188             _questInfo.InspectDeck(data.api_deck_port);\r
189             _dockInfo.InspectNDock(data.api_ndock);\r
190             _akashiTimer.Port();\r
191             _achievement.InspectBasic(data.api_basic);\r
192             if (data.api_parallel_quest_count()) // 昔のログにはないので\r
193                 _questInfo.AcceptMax = (int)data.api_parallel_quest_count;\r
194             if (data.api_event_object())\r
195                 _baseAirCorps.InspectEventObject(data.api_event_object);\r
196             if (data.api_plane_info())\r
197                 _baseAirCorps.InspectPlaneInfo(data.api_plane_info);\r
198             _battleInfo.CleanupResult();\r
199             _battleInfo.BattleState = BattleState.None;\r
200             _miscTextInfo.Port();\r
201             _cellInfo.Port();\r
202             SaveState();\r
203             RepeatingTimerController?.Resume();\r
204             foreach (var s in new[] {"遠征終了", "入渠終了", "疲労回復", "泊地修理", "大破警告"})\r
205                 RepeatingTimerController?.Stop(s);\r
206             return Update.All;\r
207         }\r
208 \r
209         private Update ApiMember(string url, dynamic json)\r
210         {\r
211             var data = json.api_data() ? json.api_data : new object();\r
212 \r
213             if (url.EndsWith("api_get_member/require_info"))\r
214             {\r
215                 _itemInfo.InspectSlotItem(data.api_slot_item, true);\r
216                 _dockInfo.InspectKDock(data.api_kdock);\r
217                 return Update.None;\r
218             }\r
219             if (url.EndsWith("api_get_member/basic"))\r
220             {\r
221                 _itemInfo.InspectBasic(data);\r
222                 _logger.InspectBasic(data);\r
223                 return Update.None;\r
224             }\r
225             if (url.EndsWith("api_get_member/slot_item"))\r
226             {\r
227                 _itemInfo.InspectSlotItem(data, true);\r
228                 return Update.Item;\r
229             }\r
230             if (url.EndsWith("api_get_member/kdock"))\r
231             {\r
232                 _dockInfo.InspectKDock(data);\r
233                 _logger.InspectKDock(data);\r
234                 return Update.Timer;\r
235             }\r
236             if (url.EndsWith("api_get_member/ndock"))\r
237             {\r
238                 _dockInfo.InspectNDock(data);\r
239                 _conditionTimer.CheckCond();\r
240                 _akashiTimer.CheckFleet();\r
241                 RepeatingTimerController?.Stop("入渠終了");\r
242                 return Update.NDock | Update.Timer | Update.Ship;\r
243             }\r
244             if (url.EndsWith("api_get_member/questlist"))\r
245             {\r
246                 _questInfo.InspectQuestList(data);\r
247                 return Update.QuestList;\r
248             }\r
249             if (url.EndsWith("api_get_member/deck"))\r
250             {\r
251                 _shipInfo.InspectDeck(data);\r
252                 _missionInfo.InspectDeck(data);\r
253                 _akashiTimer.CheckFleet();\r
254                 _questInfo.InspectDeck(data);\r
255                 return Update.Mission | Update.Timer;\r
256             }\r
257             if (url.EndsWith("api_get_member/ship2"))\r
258             {\r
259                 // ここだけjsonなので注意\r
260                 _shipInfo.InspectShip(json);\r
261                 _akashiTimer.CheckFleet();\r
262                 _battleInfo.BattleState = BattleState.None;\r
263                 return Update.Item | Update.Ship | Update.Battle;\r
264             }\r
265             if (url.EndsWith("api_get_member/ship_deck"))\r
266             {\r
267                 _shipInfo.InspectShip(data);\r
268                 _akashiTimer.CheckFleet();\r
269                 _battleInfo.BattleState = BattleState.None;\r
270                 return Update.Ship | Update.Battle | Update.Item;\r
271             }\r
272             if (url.EndsWith("api_get_member/ship3"))\r
273             {\r
274                 _shipInfo.InspectShip(data);\r
275                 _akashiTimer.CheckFleet();\r
276                 _conditionTimer.CheckCond();\r
277                 return Update.Ship;\r
278             }\r
279             if (url.EndsWith("api_get_member/material"))\r
280             {\r
281                 _materialInfo.InspectMaterial(data);\r
282                 return Update.Item;\r
283             }\r
284             if (url.EndsWith("api_get_member/mapinfo"))\r
285             {\r
286                 _exMapInfo.InspectMapInfo(data);\r
287                 _miscTextInfo.InspectMapInfo(data);\r
288                 if (data.api_air_base())\r
289                     _baseAirCorps.Inspect(data.api_air_base);\r
290                 return Update.Item;\r
291             }\r
292             if (url.EndsWith("api_req_member/get_practice_enemyinfo"))\r
293             {\r
294                 _miscTextInfo.InspectPracticeEnemyInfo(data);\r
295                 return Update.Item;\r
296             }\r
297             if (url.EndsWith("api_get_member/preset_deck"))\r
298             {\r
299                 _presetDeck.Inspect(data);\r
300                 return Update.None;\r
301             }\r
302             if (url.EndsWith("api_get_member/base_air_corps"))\r
303             {\r
304                 _baseAirCorps.Inspect(data);\r
305                 return Update.Ship;\r
306             }\r
307             return Update.None;\r
308         }\r
309 \r
310         private Update ApiKousyou(string url, string request, dynamic data)\r
311         {\r
312             if (url.EndsWith("api_req_kousyou/createitem"))\r
313             {\r
314                 _itemInfo.InspectCreateItem(data);\r
315                 _materialInfo.InspectCreateIem(data);\r
316                 _logger.InspectCreateItem(request, data);\r
317                 _questInfo.CountCreateItem();\r
318                 return Update.Item | Update.QuestList;\r
319             }\r
320             if (url.EndsWith("api_req_kousyou/getship"))\r
321             {\r
322                 _itemInfo.InspectGetShip(data);\r
323                 _shipInfo.InspectShip(data);\r
324                 _dockInfo.InspectKDock(data.api_kdock);\r
325                 _conditionTimer.CheckCond();\r
326                 RepeatingTimerController?.Stop("建造完了");\r
327                 return Update.Item | Update.Timer;\r
328             }\r
329             if (url.EndsWith("api_req_kousyou/destroyship"))\r
330             {\r
331                 _shipInfo.InspectDestroyShip(request, data);\r
332                 _materialInfo.InspectDestroyShip(data);\r
333                 _conditionTimer.CheckCond();\r
334                 _akashiTimer.CheckFleet();\r
335                 _questInfo.InspectDestroyShip(request);\r
336                 return Update.Item | Update.Ship | Update.QuestList;\r
337             }\r
338             if (url.EndsWith("api_req_kousyou/destroyitem2"))\r
339             {\r
340                 _questInfo.InspectDestroyItem(request, data); // 本当に削除される前\r
341                 _itemInfo.InspectDestroyItem(request, data);\r
342                 _materialInfo.InspectDestroyItem(data);\r
343                 return Update.Item | Update.QuestList;\r
344             }\r
345             if (url.EndsWith("api_req_kousyou/remodel_slot"))\r
346             {\r
347                 _logger.SetCurrentMaterial(_materialInfo.Current);\r
348                 _logger.InspectRemodelSlot(request, data); // 資材の差が必要なので_materialInfoより前\r
349                 _itemInfo.InspectRemodelSlot(data);\r
350                 _materialInfo.InspectRemodelSlot(data);\r
351                 _questInfo.CountRemodelSlot();\r
352                 return Update.Item | Update.QuestList;\r
353             }\r
354             if (url.EndsWith("api_req_kousyou/createship"))\r
355             {\r
356                 _logger.InspectCreateShip(request);\r
357                 _questInfo.CountCreateShip();\r
358                 return Update.QuestList;\r
359             }\r
360             if (url.EndsWith("api_req_kousyou/createship_speedchange"))\r
361             {\r
362                 _dockInfo.InspectCreateShipSpeedChange(request);\r
363                 return Update.Timer;\r
364             }\r
365             return Update.None;\r
366         }\r
367 \r
368         private Update ApiBattle(string url, string request, dynamic data)\r
369         {\r
370             if (IsNormalBattleAPI(url) || IsCombinedBattleAPI(url))\r
371             {\r
372                 _battleInfo.InspectBattle(url, request, data);\r
373                 _logger.InspectBattle(data);\r
374                 _cellInfo.StartBattle();\r
375                 return Update.Ship | Update.Battle;\r
376             }\r
377             if (url.EndsWith("api_req_practice/battle") || url.EndsWith("api_req_practice/midnight_battle"))\r
378             {\r
379                 if (url.EndsWith("/battle"))\r
380                 {\r
381                     _shipInfo.StartPractice(request);\r
382                     _questInfo.StartPractice(request);\r
383                     _cellInfo.StartPractice();\r
384                     _conditionTimer.InvalidateCond();\r
385                     RepeatingTimerController?.Suspend();\r
386                 }\r
387                 _battleInfo.InspectBattle(url, request, data);\r
388                 return Update.Ship | Update.Battle | Update.Timer;\r
389             }\r
390             if (url.EndsWith("api_req_sortie/battleresult") || url.EndsWith("api_req_combined_battle/battleresult"))\r
391             {\r
392                 _battleInfo.InspectBattleResult(data);\r
393                 _exMapInfo.InspectBattleResult(data);\r
394                 _logger.InspectBattleResult(data);\r
395                 _questInfo.InspectBattleResult(data);\r
396                 _miscTextInfo.InspectBattleResult(data);\r
397                 return Update.Ship | Update.QuestList;\r
398             }\r
399             if (url.EndsWith("api_req_practice/battle_result"))\r
400             {\r
401                 _battleInfo.InspectPracticeResult(data);\r
402                 _questInfo.InspectPracticeResult(data);\r
403                 return Update.Ship | Update.QuestList;\r
404             }\r
405             if (url.EndsWith("/goback_port"))\r
406             {\r
407                 _battleInfo.CauseEscape();\r
408                 return Update.Ship;\r
409             }\r
410             _battleInfo.BattleState = BattleState.Unknown;\r
411             return Update.None;\r
412         }\r
413 \r
414         private bool IsNormalBattleAPI(string url)\r
415         {\r
416             return url.EndsWith("api_req_sortie/battle") ||\r
417                    url.EndsWith("api_req_sortie/airbattle") ||\r
418                    url.EndsWith("api_req_sortie/ld_airbattle") ||\r
419                    url.EndsWith("api_req_battle_midnight/battle") ||\r
420                    url.EndsWith("api_req_battle_midnight/sp_midnight");\r
421         }\r
422 \r
423         private bool IsCombinedBattleAPI(string url)\r
424         {\r
425             return url.EndsWith("api_req_combined_battle/battle") ||\r
426                    url.EndsWith("api_req_combined_battle/airbattle") ||\r
427                    url.EndsWith("api_req_combined_battle/ld_airbattle") ||\r
428                    url.EndsWith("api_req_combined_battle/battle_water") ||\r
429                    url.EndsWith("api_req_combined_battle/midnight_battle") ||\r
430                    url.EndsWith("api_req_combined_battle/sp_midnight") ||\r
431                    url.EndsWith("api_req_combined_battle/ec_battle") ||\r
432                    url.EndsWith("api_req_combined_battle/ec_midnight_battle") ||\r
433                    url.EndsWith("api_req_combined_battle/ec_night_to_day") ||\r
434                    url.EndsWith("api_req_combined_battle/each_battle") ||\r
435                    url.EndsWith("api_req_combined_battle/each_battle_water");\r
436         }\r
437 \r
438         private Update ApiHensei(string url, string request, dynamic data)\r
439         {\r
440             if (url.EndsWith("api_req_hensei/change"))\r
441             {\r
442                 _shipInfo.InspectChange(request);\r
443                 _akashiTimer.InspectChange(request);\r
444                 return Update.Ship;\r
445             }\r
446             if (url.EndsWith("api_req_hensei/preset_select"))\r
447             {\r
448                 _shipInfo.InspectDeck(new[] {data});\r
449                 _akashiTimer.CheckFleet();\r
450                 return Update.Ship;\r
451             }\r
452             if (url.EndsWith("api_req_hensei/preset_register"))\r
453             {\r
454                 _presetDeck.InspectRegister(data);\r
455                 return Update.None;\r
456             }\r
457             if (url.EndsWith("api_req_hensei/preset_delete"))\r
458             {\r
459                 _presetDeck.InspectDelete(request);\r
460                 return Update.Timer;\r
461             }\r
462             if (url.EndsWith("api_req_hensei/combined"))\r
463             {\r
464                 _shipInfo.InspectCombined(request);\r
465                 return Update.Ship;\r
466             }\r
467             return Update.None;\r
468         }\r
469 \r
470         private Update ApiKaisou(string url, string request, dynamic data)\r
471         {\r
472             if (url.EndsWith("api_req_kaisou/powerup"))\r
473             {\r
474                 _shipInfo.InspectPowerUp(request, data);\r
475                 _conditionTimer.CheckCond();\r
476                 _akashiTimer.CheckFleet();\r
477                 _questInfo.InspectPowerUp(data);\r
478                 return Update.Item | Update.Ship | Update.QuestList;\r
479             }\r
480             if (url.EndsWith("api_req_kaisou/slot_exchange_index"))\r
481             {\r
482                 _shipInfo.InspectSlotExchange(request, data);\r
483                 return Update.Ship;\r
484             }\r
485             if (url.EndsWith("api_req_kaisou/slot_deprive"))\r
486             {\r
487                 _shipInfo.InspectSlotDeprive(data);\r
488                 return Update.Ship;\r
489             }\r
490             if (url.EndsWith("api_req_kaisou/marriage"))\r
491             {\r
492                 _shipInfo.InspectMarriage(data);\r
493                 return Update.Ship;\r
494             }\r
495             return Update.None;\r
496         }\r
497 \r
498         private Update ApiAirCorps(string url, string request, dynamic data)\r
499         {\r
500             if (url.EndsWith("api_req_air_corps/supply"))\r
501             {\r
502                 _materialInfo.InspectAirCorpsSupply(data);\r
503                 _baseAirCorps.InspectSupply(request, data);\r
504                 return Update.Item;\r
505             }\r
506             if (url.EndsWith("api_req_air_corps/set_plane"))\r
507             {\r
508                 _materialInfo.InspectAirCorpsSetPlane(data);\r
509                 _baseAirCorps.InspectSetPlane(request, data);\r
510                 return Update.Item | Update.Ship;\r
511             }\r
512             if (url.EndsWith("api_req_air_corps/set_action"))\r
513             {\r
514                 _baseAirCorps.InspectSetAction(request);\r
515                 return Update.Ship;\r
516             }\r
517             if (url.EndsWith("api_req_air_corps/expand_base"))\r
518             {\r
519                 _baseAirCorps.InspectExpandBase(request, data);\r
520                 return Update.Ship;\r
521             }\r
522             return Update.None;\r
523         }\r
524 \r
525         private Update ApiOthers(string url, string request, dynamic data)\r
526         {\r
527             if (url.EndsWith("api_req_hokyu/charge"))\r
528             {\r
529                 _shipInfo.InspectCharge(data);\r
530                 _materialInfo.InspectCharge(data);\r
531                 _questInfo.CountCharge();\r
532                 return Update.Item | Update.Ship | Update.QuestList;\r
533             }\r
534             if (url.EndsWith("api_req_nyukyo/start"))\r
535             {\r
536                 _dockInfo.InspectNyukyo(request);\r
537                 _conditionTimer.CheckCond();\r
538                 _akashiTimer.CheckFleet();\r
539                 _questInfo.CountNyukyo();\r
540                 var ndock = HttpUtility.ParseQueryString(request)["api_ndock_id"];\r
541                 if (ndock != null && int.TryParse(ndock, out int id))\r
542                     RepeatingTimerController?.Stop("入渠終了", id - 1);\r
543                 return Update.Item | Update.Ship | Update.QuestList;\r
544             }\r
545             if (url.EndsWith("api_req_nyukyo/speedchange"))\r
546             {\r
547                 _dockInfo.InspectSpeedChange(request);\r
548                 _conditionTimer.CheckCond();\r
549                 return Update.NDock | Update.Timer | Update.Item | Update.Ship;\r
550             }\r
551             if (url.EndsWith("api_req_map/start"))\r
552             {\r
553                 _shipInfo.InspectMapStart(request); // 出撃中判定が必要なので_conditionTimerより前\r
554                 _conditionTimer.InvalidateCond();\r
555                 _exMapInfo.InspectMapStart(data);\r
556                 _battleInfo.InspectMapStart(data);\r
557                 _logger.InspectMapStart(data);\r
558                 _miscTextInfo.InspectMapStart(data);\r
559                 _questInfo.InspectMapStart(data);\r
560                 _cellInfo.InspectMapStart(data);\r
561                 RepeatingTimerController?.Suspend("大破警告");\r
562                 return Update.Timer | Update.Ship | Update.Cell;\r
563             }\r
564             if (url.EndsWith("api_req_map/next"))\r
565             {\r
566                 _exMapInfo.InspectMapNext(data);\r
567                 _battleInfo.InspectMapNext(data);\r
568                 _logger.InspectMapNext(data);\r
569                 _questInfo.InspectMapNext(data);\r
570                 _miscTextInfo.InspectMapNext(data);\r
571                 _cellInfo.InspectMapNext(data);\r
572                 return Update.Cell;\r
573             }\r
574             if (url.EndsWith("api_req_mission/start"))\r
575             {\r
576                 var deck = HttpUtility.ParseQueryString(request)["api_deck_id"];\r
577                 if (deck != null && int.TryParse(deck, out int id))\r
578                     RepeatingTimerController?.Stop("遠征終了", id - 1);\r
579                 return Update.None;\r
580             }\r
581             if (url.EndsWith("api_req_mission/result"))\r
582             {\r
583                 _materialInfo.InspectMissionResult(data);\r
584                 _logger.InspectMissionResult(data);\r
585                 _questInfo.InspectMissionResult(request, data);\r
586                 return Update.Item;\r
587             }\r
588             if (url.EndsWith("api_req_quest/stop"))\r
589             {\r
590                 _questInfo.InspectStop(request);\r
591                 return Update.QuestList;\r
592             }\r
593             if (url.EndsWith("api_req_quest/clearitemget"))\r
594             {\r
595                 _questInfo.InspectClearItemGet(request);\r
596                 _logger.InspectClearItemGet(data);\r
597                 return Update.QuestList;\r
598             }\r
599             return Update.None;\r
600         }\r
601 \r
602         public NameAndTimer[] NDock => _dockInfo.NDock;\r
603 \r
604         public AlarmTimer[] KDock => _dockInfo.KDock;\r
605 \r
606         public AlarmCounter ItemCounter => _itemInfo.Counter;\r
607 \r
608         public ItemInfo Item => _itemInfo;\r
609 \r
610         public MaterialInfo Material => _materialInfo;\r
611 \r
612         public QuestStatus[] Quests => _questInfo.Quests;\r
613 \r
614         public void ClearQuests() => _questInfo.ClearQuests();\r
615 \r
616         public NameAndTimer[] Missions => _missionInfo.Missions;\r
617 \r
618         public DateTime GetConditionTimer(int fleet) => _conditionTimer.GetTimer(fleet);\r
619 \r
620         public int[] GetConditionNotice(DateTime prev, DateTime now) => _conditionTimer.GetNotice(prev, now);\r
621 \r
622         public AlarmCounter ShipCounter => _shipInfo.Counter;\r
623 \r
624         public IReadOnlyList<Fleet> Fleets => _shipInfo.Fleets;\r
625 \r
626         public ShipInfo.ShipStatusPair[] BattleResultStatusDiff => _shipInfo.BattleResultDiff;\r
627 \r
628         public bool IsBattleResultStatusError => _shipInfo.IsBattleResultError;\r
629 \r
630         public ShipStatus[] BattleStartStatus => _shipInfo.BattleStartStatus;\r
631 \r
632         public bool IsCombinedFleet => _shipInfo.Fleets[0].CombinedType != 0;\r
633 \r
634         public ShipStatus[] RepairList => _shipInfo.GetRepairList(_dockInfo);\r
635 \r
636         public ShipStatus[] ShipList => _shipInfo.ShipList;\r
637 \r
638         public string[] BadlyDamagedShips => _shipInfo.BadlyDamagedShips;\r
639 \r
640         public ItemStatus[] ItemList\r
641         {\r
642             get\r
643             {\r
644                 _itemInfo.ClearHolder();\r
645                 _shipInfo.SetItemHolder();\r
646                 _baseAirCorps.SetItemHolder();\r
647                 return _itemInfo.ItemList;\r
648             }\r
649         }\r
650 \r
651         public AkashiTimer AkashiTimer => _akashiTimer;\r
652 \r
653         public Achievement Achievement => _achievement;\r
654 \r
655         public BattleInfo Battle => _battleInfo;\r
656 \r
657         public ExMapInfo ExMap => _exMapInfo;\r
658 \r
659         public string MiscText => _miscTextInfo.Text;\r
660 \r
661         public BaseAirCorps.BaseInfo[] BaseAirCorps => _baseAirCorps.AllAirCorps;\r
662 \r
663         public CellInfo CellInfo => _cellInfo;\r
664 \r
665         public void SetLogWriter(Action<string, string, string> writer, Func<DateTime> nowFunc)\r
666         {\r
667             _logger.SetWriter(writer, nowFunc);\r
668         }\r
669 \r
670         public void SkipMaster()\r
671         {\r
672             _start = true;\r
673         }\r
674 \r
675         public void EnableLog(LogType type)\r
676         {\r
677             _logger.EnableLog(type);\r
678         }\r
679 \r
680         public int MaterialLogInterval\r
681         {\r
682             set => _logger.MaterialLogInterval = value;\r
683         }\r
684 \r
685         public string LogOutputDir\r
686         {\r
687             set => _logger.OutputDir = value;\r
688         }\r
689 \r
690         public void FlashLog()\r
691         {\r
692             _logger.FlashLog();\r
693         }\r
694     }\r
695 }