OSDN Git Service

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