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