OSDN Git Service

一覧ウィンドウの艦娘の装備の表示に改修レベルと搭載数を加える
[kancollesniffer/KancolleSniffer.git] / KancolleSniffer / ItemInfo.cs
1 // Copyright (C) 2013, 2014 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 using System.Collections.Generic;\r
20 using System.Linq;\r
21 using System.Web;\r
22 \r
23 namespace KancolleSniffer\r
24 {\r
25     public class ItemSpec\r
26     {\r
27         public int Id;\r
28         public string Name;\r
29         public int Type;\r
30         public string TypeName;\r
31         public int AntiAir;\r
32         public int LoS;\r
33 \r
34         public ItemSpec()\r
35         {\r
36             Id = -1;\r
37             Name = "";\r
38         }\r
39 \r
40         public bool CanAirCombat\r
41         {\r
42             get\r
43             {\r
44                 switch (Type)\r
45                 {\r
46                     case 6: // 艦戦\r
47                     case 7: // 艦爆\r
48                     case 8: // 艦攻\r
49                     case 11: // 水爆\r
50                         return true;\r
51                 }\r
52                 return false;\r
53             }\r
54         }\r
55 \r
56         // http://ch.nicovideo.jp/biikame/blomaga/ar663428\r
57         public double LoSScaleFactor()\r
58         {\r
59             switch (Type)\r
60             {\r
61                 case 7: // 艦爆\r
62                     return 1.0376255;\r
63                 case 8: // 艦攻\r
64                     return 1.3677954;\r
65                 case 9: // 艦偵\r
66                     return 1.6592780;\r
67                 case 10: // 水偵\r
68                     return 2.0000000;\r
69                 case 11: // 水爆\r
70                     return 1.7787282;\r
71                 case 12: // 小型電探\r
72                     return 1.0045358;\r
73                 case 13: // 大型電探\r
74                     return 0.9906638;\r
75             }\r
76             if (Name == "探照灯")\r
77                 return 0.9067950;\r
78             return 0;\r
79         }\r
80 \r
81         public bool IsAircraft\r
82         {\r
83             get\r
84             {\r
85                 switch (Type)\r
86                 {\r
87                     case 6:\r
88                     case 7:\r
89                     case 8:\r
90                     case 9:\r
91                     case 10:\r
92                     case 11:\r
93                     case 25: // オートジャイロ\r
94                     case 26: // 対潜哨戒機\r
95                         return true;\r
96                 }\r
97                 return false;\r
98             }\r
99         }\r
100     }\r
101 \r
102     public class ItemStatus\r
103     {\r
104         public ItemSpec Spec { get; set; }\r
105         public int Level { get; set; }\r
106         public ShipStatus Ship { get; set; }\r
107 \r
108         public ItemStatus()\r
109         {\r
110             Spec = new ItemSpec();\r
111             Ship = new ShipStatus();\r
112         }\r
113     }\r
114 \r
115     public class ItemInfo\r
116     {\r
117         private int _nowShips, _nowEquips;\r
118         private readonly Dictionary<int, ItemSpec> _itemSpecs = new Dictionary<int, ItemSpec>();\r
119         private readonly Dictionary<int, ItemStatus> _itemInfo = new Dictionary<int, ItemStatus>();\r
120 \r
121         public int MaxShips { get; private set; }\r
122         public int MarginShips { get; set; }\r
123         public bool RingShips { get; set; }\r
124         public int MaxEquips { get; private set; }\r
125         public int MarginEquips { get; set; }\r
126         public bool RingEquips { get; set; }\r
127         public MaterialCount[] MaterialHistory { get; private set; }\r
128 \r
129         public bool NeedSave\r
130         {\r
131             get { return MaterialHistory.Any(m => m.NeedSave); }\r
132             private set\r
133             {\r
134                 foreach (var m in MaterialHistory)\r
135                     m.NeedSave = value;\r
136             }\r
137         }\r
138 \r
139         public int NowShips\r
140         {\r
141             get { return _nowShips; }\r
142             set\r
143             {\r
144                 if (MaxShips != 0)\r
145                 {\r
146                     var limit = MaxShips - MarginShips;\r
147                     RingShips = _nowShips < limit && value >= limit;\r
148                 }\r
149                 _nowShips = value;\r
150             }\r
151         }\r
152 \r
153         public bool TooManyShips\r
154         {\r
155             get { return MaxShips != 0 && NowShips >= MaxShips - MarginShips; }\r
156         }\r
157 \r
158         public int NowEquips\r
159         {\r
160             get { return _nowEquips; }\r
161             private set\r
162             {\r
163                 if (MaxEquips != 0)\r
164                 {\r
165                     var limit = MaxEquips - MarginEquips;\r
166                     RingEquips = _nowEquips < limit && value >= limit;\r
167                 }\r
168                 _nowEquips = value;\r
169             }\r
170         }\r
171 \r
172         public bool TooManyEquips\r
173         {\r
174             get { return MaxEquips != 0 && NowEquips >= MaxEquips - MarginEquips; }\r
175         }\r
176 \r
177         public ItemInfo()\r
178         {\r
179             MaterialHistory = new MaterialCount[Enum.GetValues(typeof (Material)).Length];\r
180             foreach (Material m in Enum.GetValues(typeof (Material)))\r
181                 MaterialHistory[(int)m] = new MaterialCount();\r
182             MarginShips = 4;\r
183             MarginEquips = 10;\r
184         }\r
185 \r
186         public void InspectBasic(dynamic json)\r
187         {\r
188             MaxShips = (int)json.api_max_chara;\r
189             MaxEquips = (int)json.api_max_slotitem;\r
190         }\r
191 \r
192         public void InspectMaterial(dynamic json)\r
193         {\r
194             foreach (var entry in json)\r
195                 MaterialHistory[(int)entry.api_id - 1].Now = (int)entry.api_value;\r
196         }\r
197 \r
198         public void InspectMaster(dynamic json)\r
199         {\r
200             var dict = new Dictionary<int, string>();\r
201             foreach (var entry in json.api_mst_slotitem_equiptype)\r
202                 dict[(int)entry.api_id] = entry.api_name;\r
203             foreach (var entry in json.api_mst_slotitem)\r
204             {\r
205                 _itemSpecs[(int)entry.api_id] = new ItemSpec\r
206                 {\r
207                     Id = (int)entry.api_id,\r
208                     Name = (string)entry.api_name,\r
209                     Type = (int)entry.api_type[2],\r
210                     TypeName = dict[(int)entry.api_type[2]],\r
211                     AntiAir = (int)entry.api_tyku,\r
212                     LoS = (int)entry.api_saku\r
213                 };\r
214             }\r
215             _itemSpecs[-1] = new ItemSpec();\r
216         }\r
217 \r
218         public void InspectSlotItem(dynamic json, bool full = false)\r
219         {\r
220             if (!json.IsArray)\r
221                 json = new[] {json};\r
222             if (full)\r
223             {\r
224                 _itemInfo.Clear();\r
225                 _itemInfo[-1] = new ItemStatus();\r
226             }\r
227             foreach (var entry in json)\r
228             {\r
229                 _itemInfo[(int)entry.api_id] = new ItemStatus\r
230                 {\r
231                     Spec = _itemSpecs[(int)entry.api_slotitem_id],\r
232                     Level = entry.api_level() ? (int)entry.api_level : 0\r
233                 };\r
234             }\r
235             NowEquips = _itemInfo.Count - 1;\r
236         }\r
237 \r
238         public void InspectCreateItem(dynamic json)\r
239         {\r
240             var m = (dynamic[])json.api_material;\r
241             for (var i = 0; i < m.Length; i++)\r
242                 MaterialHistory[i].Now = (int)m[i];\r
243             if (!json.IsDefined("api_slot_item"))\r
244                 return;\r
245             InspectSlotItem(json.api_slot_item);\r
246         }\r
247 \r
248         public void InspectGetShip(dynamic json)\r
249         {\r
250             NowShips += 1;\r
251             if (json.api_slotitem == null) // まるゆにはスロットがない\r
252                 return;\r
253             InspectSlotItem(json.api_slotitem);\r
254         }\r
255 \r
256         public void InspectDestroyItem(string request, dynamic json)\r
257         {\r
258             var values = HttpUtility.ParseQueryString(request);\r
259             DeleteItems(values["api_slotitem_ids"].Split(',').Select(int.Parse).ToArray());\r
260             var get = (int[])json.api_get_material;\r
261             for (var i = 0; i < get.Length; i++)\r
262                 MaterialHistory[i].Now += get[i];\r
263         }\r
264 \r
265         public void InspectRemodelSlot(dynamic json)\r
266         {\r
267             if (json.api_after_slot())\r
268                 InspectSlotItem(json.api_after_slot);\r
269             if (!json.api_use_slot_id())\r
270                 return;\r
271             DeleteItems(((int[])json.api_use_slot_id));\r
272         }\r
273 \r
274         public void DeleteItems(int[] ids)\r
275         {\r
276             foreach (var id in ids.Where(id => id != -1))\r
277             {\r
278                 _itemInfo.Remove(id);\r
279                 NowEquips--;\r
280             }\r
281         }\r
282 \r
283         public void CountNewItems(int[] ids)\r
284         {\r
285             foreach (var id in ids.Where(id => id != -1 && !_itemInfo.ContainsKey(id)))\r
286             {\r
287                 _itemInfo[id] = new ItemStatus();\r
288                 NowEquips++;\r
289             }\r
290         }\r
291 \r
292         public void InspectMissionResult(dynamic json)\r
293         {\r
294             if ((int)json.api_clear_result == 0) // 失敗\r
295                 return;\r
296             var get = (int[])json.api_get_material;\r
297             for (var i = 0; i < get.Length; i++)\r
298                 MaterialHistory[i].Now += get[i];\r
299         }\r
300 \r
301         public ItemSpec this[int id]\r
302         {\r
303             get { return GetSpecById(id); }\r
304         }\r
305 \r
306         public ItemSpec GetSpecById(int id)\r
307         {\r
308             return _itemInfo[id].Spec;\r
309         }\r
310 \r
311         public ItemSpec GetSpecByItemId(int id)\r
312         {\r
313             return _itemSpecs[id];\r
314         }\r
315 \r
316         public Dictionary<int, ItemStatus> ItemDict\r
317         {\r
318             get { return _itemInfo; }\r
319         }\r
320 \r
321         public void SetItemOwner(ShipStatus[] shipList)\r
322         {\r
323             foreach (var e in _itemInfo)\r
324                 e.Value.Ship = new ShipStatus();\r
325             foreach (var s in shipList)\r
326             {\r
327                 foreach (var id in s.Slot)\r
328                     _itemInfo[id].Ship = s;\r
329             }\r
330         }\r
331 \r
332         public void SaveState(Status status)\r
333         {\r
334             NeedSave = false;\r
335             status.MatreialHistory = MaterialHistory;\r
336         }\r
337 \r
338         public void LoadSate(Status status)\r
339         {\r
340             if (status.MatreialHistory != null)\r
341                 status.MatreialHistory.CopyTo(MaterialHistory, 0);\r
342         }\r
343     }\r
344 \r
345     public enum Material\r
346     {\r
347         Fuel,\r
348         Bullet,\r
349         Steal,\r
350         Bouxite,\r
351         Burner,\r
352         Bucket,\r
353         Development,\r
354         Screw,\r
355     }\r
356 \r
357     public class MaterialCount\r
358     {\r
359         private int _now;\r
360 \r
361         public int BegOfDay { get; set; }\r
362         public int BegOfWeek { get; set; }\r
363         public DateTime LastSet { get; set; }\r
364         public bool NeedSave { get; set; }\r
365 \r
366         public int Now\r
367         {\r
368             get { return _now; }\r
369             set\r
370             {\r
371                 var prev = _now;\r
372                 _now = value;\r
373                 if (Status.Restoring) // JSONから値を復旧するときは履歴に触らない\r
374                     return;\r
375                 if (_now != prev)\r
376                     NeedSave = true;\r
377                 if (LastSet == DateTime.MinValue)\r
378                 {\r
379                     BegOfDay = BegOfWeek = value;\r
380                     LastSet = DateTime.Now;\r
381                     return;\r
382                 }\r
383                 UpdateHistory(prev);\r
384                 LastSet = DateTime.Now;\r
385             }\r
386         }\r
387 \r
388         private void UpdateHistory(int prev)\r
389         {\r
390             var morning = DateTime.Today.AddHours(5);\r
391             var dow = (int)morning.DayOfWeek;\r
392             var monday = morning.AddDays(dow == 0 ? -6 : -dow + 1);\r
393             if (DateTime.Now >= morning && LastSet < morning)\r
394                 BegOfDay = prev;\r
395             if (DateTime.Now >= monday && LastSet < monday)\r
396                 BegOfWeek = prev;\r
397         }\r
398     }\r
399 }