OSDN Git Service

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