OSDN Git Service

戦況にツールチップで味方の装備を表示する
[kancollesniffer/KancolleSniffer.git] / KancolleSniffer / BaseAirCoprs.cs
1 // Copyright (C) 2016 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 System.Collections.Generic;\r
17 using System.Collections.Specialized;\r
18 using System.Linq;\r
19 \r
20 namespace KancolleSniffer\r
21 {\r
22     public class BaseAirCoprs\r
23     {\r
24         private readonly ItemInfo _itemInfo;\r
25         private List<int> _relocationgPlanes = new List<int>();\r
26 \r
27         public BaseAirCoprs(ItemInfo item)\r
28         {\r
29             _itemInfo = item;\r
30         }\r
31 \r
32         public BaseInfo[] AllAirCorps { get; set; }\r
33 \r
34         public class BaseInfo\r
35         {\r
36             public int AreaId { get; set; }\r
37             public string AreaName => AreaId == 6 ? "中部海域" : "限定海域";\r
38             public AirCorpsInfo[] AirCorps { get; set; }\r
39         }\r
40 \r
41         public class FighterPower\r
42         {\r
43             public int[] AirCombat { get; set; }\r
44             public int[] Interception { get; set; }\r
45             public bool IsInterceptor => AirCombat[0] != Interception[0];\r
46         }\r
47 \r
48         public class AirCorpsInfo\r
49         {\r
50             public int Distance { get; set; }\r
51             public int Action { get; set; }\r
52             public PlaneInfo[] Planes { get; set; }\r
53 \r
54             public string ActionName\r
55             {\r
56                 get\r
57                 {\r
58                     switch (Action)\r
59                     {\r
60                         case 0:\r
61                             return "待機";\r
62                         case 1:\r
63                             return "出撃";\r
64                         case 2:\r
65                             return "防空";\r
66                         case 3:\r
67                             return "退避";\r
68                         case 4:\r
69                             return "休息";\r
70                         default:\r
71                             return "";\r
72                     }\r
73                 }\r
74             }\r
75 \r
76             public FighterPower FighterPower =>\r
77                 new FighterPower {AirCombat = CalcFighterPower(false), Interception = CalcFighterPower(true)};\r
78 \r
79             private int[] CalcFighterPower(bool interception)\r
80             {\r
81                 var reconPlaneBonus = interception\r
82                     ? Planes.Max(plane => plane.Slot.Spec.ReconPlaneInterceptionBonus)\r
83                     : 1.0;\r
84                 return Planes.Aggregate(new[] {0, 0}, (prev, plane) =>\r
85                 {\r
86                     if (plane.State != 1)\r
87                         return prev;\r
88                     var cur = plane.Slot.CalcFighterPowerInBase(plane.Count, interception);\r
89                     return new[] {prev[0] + cur[0], prev[1] + cur[1]};\r
90                 }).Select(fp => (int)(fp * reconPlaneBonus)).ToArray();\r
91             }\r
92         }\r
93 \r
94         public class PlaneInfo\r
95         {\r
96             public int State { get; set; }\r
97             public ItemStatus Slot { get; set; }\r
98             public int Count { get; set; }\r
99             public int MaxCount { get; set; }\r
100 \r
101             public string StateName\r
102             {\r
103                 get\r
104                 {\r
105                     switch (State)\r
106                     {\r
107                         case 0:\r
108                             return "未配備";\r
109                         case 1:\r
110                             return "配備中";\r
111                         case 2:\r
112                             return "配置転換中";\r
113                         default:\r
114                             return "";\r
115                     }\r
116                 }\r
117             }\r
118 \r
119             public FighterPower FighterPower\r
120                 => new FighterPower{AirCombat = CalcFighterPower(false), Interception = CalcFighterPower(true)};\r
121 \r
122             private int[] CalcFighterPower(bool interception) => Slot.CalcFighterPowerInBase(Count, interception);\r
123         }\r
124 \r
125         public void Inspect(dynamic json)\r
126         {\r
127             AllAirCorps = (from entry in (dynamic[])json\r
128                 group\r
129                 new AirCorpsInfo\r
130                 {\r
131                     Distance = (int)entry.api_distance,\r
132                     Action = (int)entry.api_action_kind,\r
133                     Planes = (from plane in (dynamic[])entry.api_plane_info\r
134                         select new PlaneInfo\r
135                         {\r
136                             Slot = _itemInfo.GetStatus((int)plane.api_slotid),\r
137                             State = (int)plane.api_state,\r
138                             Count = plane.api_count() ? (int)plane.api_count : 0,\r
139                             MaxCount = plane.api_max_count() ? (int)plane.api_max_count : 0,\r
140                         }).ToArray()\r
141                 } by entry.api_area_id() ? (int)entry.api_area_id : 0\r
142                 into grp\r
143                 select new BaseInfo {AreaId = grp.Key, AirCorps = grp.ToArray()}).ToArray();\r
144         }\r
145 \r
146         public void InspectSetPlane(string request, dynamic json)\r
147         {\r
148             if (AllAirCorps == null)\r
149                 return;\r
150             var values = HttpUtility.ParseQueryString(request);\r
151             var airCorps = GetBaseInfo(values).AirCorps[int.Parse(values["api_base_id"]) - 1];\r
152             if (json.api_distance()) // 2016春イベにはない\r
153                 airCorps.Distance = (int)json.api_distance;\r
154             foreach (var planeInfo in json.api_plane_info)\r
155             {\r
156                 var planeId = (int)planeInfo.api_squadron_id - 1;\r
157                 var prev = airCorps.Planes[planeId];\r
158                 if (prev.Slot.Id != -1)\r
159                     _relocationgPlanes.Add(prev.Slot.Id);\r
160                 airCorps.Planes[planeId] = new PlaneInfo\r
161                 {\r
162                     Slot = _itemInfo.GetStatus((int)planeInfo.api_slotid),\r
163                     State = (int)planeInfo.api_state,\r
164                     Count = planeInfo.api_count() ? (int)planeInfo.api_count : 0,\r
165                     MaxCount = planeInfo.api_max_count() ? (int)planeInfo.api_max_count : 0\r
166                 };\r
167             }\r
168         }\r
169 \r
170         public void InspectSupply(string request, dynamic json)\r
171         {\r
172             InspectSetPlane(request, json);\r
173         }\r
174 \r
175         public void InspectSetAction(string request)\r
176         {\r
177             if (AllAirCorps == null)\r
178                 return;\r
179             var values = HttpUtility.ParseQueryString(request);\r
180             var airCorps = GetBaseInfo(values).AirCorps;\r
181             foreach (var entry in\r
182                 values["api_base_id"].Split(',')\r
183                     .Zip(values["api_action_kind"].Split(','), (b, a) => new {baseId = b, action = a}))\r
184             {\r
185                 airCorps[int.Parse(entry.baseId) - 1].Action = int.Parse(entry.action);\r
186             }\r
187         }\r
188 \r
189         public void InspectExpandBase(string request, dynamic json)\r
190         {\r
191             var values = HttpUtility.ParseQueryString(request);\r
192             var baseInfo = GetBaseInfo(values);\r
193             var airCorps = baseInfo.AirCorps;\r
194             Array.Resize(ref airCorps, airCorps.Length + 1);\r
195             baseInfo.AirCorps = airCorps;\r
196             airCorps[airCorps.Length - 1] = new AirCorpsInfo\r
197             {\r
198                 Planes =\r
199                     ((dynamic[])json[0].api_plane_info).\r
200                         Select(plane => new PlaneInfo {Slot = new ItemStatus()}).ToArray()\r
201             };\r
202         }\r
203 \r
204         private BaseInfo GetBaseInfo(NameValueCollection values)\r
205         {\r
206             var areaId = int.Parse(values["api_area_id"] ?? "0"); // 古いAPIに対応するため\r
207             return AllAirCorps.First(b => b.AreaId == areaId);\r
208         }\r
209 \r
210         public void InspectPlaneInfo(dynamic json)\r
211         {\r
212             _relocationgPlanes = json.api_base_convert_slot()\r
213                 ? new List<int>((int[])json.api_base_convert_slot)\r
214                 : new List<int>();\r
215         }\r
216 \r
217         public void InspectEventObject(dynamic json)\r
218         {\r
219             InspectPlaneInfo(json);\r
220         }\r
221 \r
222         public void SetItemHolder()\r
223         {\r
224             if (AllAirCorps == null)\r
225                 return;\r
226             var name = new[] {"第一", "第二", "第三"};\r
227             foreach (var baseInfo in AllAirCorps.Select((data, i) => new {data, i}))\r
228             {\r
229                 var areaAame = baseInfo.data.AreaName;\r
230                 foreach (var airCorps in baseInfo.data.AirCorps.Select((data, i) => new {data, i}))\r
231                 {\r
232                     var ship = new ShipStatus\r
233                     {\r
234                         Id = 10000 + baseInfo.i * 1000 + airCorps.i,\r
235                         Spec = new ShipSpec {Name = areaAame + " " + name[airCorps.i] + "航空隊"}\r
236                     };\r
237                     foreach (var plane in airCorps.data.Planes)\r
238                     {\r
239                         if (plane.State != 1)\r
240                             continue;\r
241                         _itemInfo.GetStatus(plane.Slot.Id).Holder = ship;\r
242                     }\r
243                 }\r
244             }\r
245             if (_relocationgPlanes == null)\r
246                 return;\r
247             var relocating = new ShipStatus {Id = 1500, Spec = new ShipSpec {Name = "配置転換中"}};\r
248             foreach (var id in _relocationgPlanes)\r
249                 _itemInfo.GetStatus(id).Holder = relocating;\r
250         }\r
251     }\r
252 }