OSDN Git Service

enum Materialの順序を間違えているのを直す
[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 int NowShips\r
107         {\r
108             get { return _nowShips; }\r
109             set\r
110             {\r
111                 if (MaxShips != 0)\r
112                 {\r
113                     var limit = MaxShips - MarginShips;\r
114                     RingShips = _nowShips < limit && value >= limit;\r
115                 }\r
116                 _nowShips = value;\r
117             }\r
118         }\r
119 \r
120         public bool TooManyShips\r
121         {\r
122             get { return MaxShips != 0 && NowShips >= MaxShips - MarginShips; }\r
123         }\r
124 \r
125         public int NowEquips\r
126         {\r
127             get { return _nowEquips; }\r
128             private set\r
129             {\r
130                 if (MaxEquips != 0)\r
131                 {\r
132                     var limit = MaxEquips - MarginEquips;\r
133                     RingEquips = _nowEquips < limit && value >= limit;\r
134                 }\r
135                 _nowEquips = value;\r
136             }\r
137         }\r
138 \r
139         public bool TooManyEquips\r
140         {\r
141             get { return MaxEquips != 0 && NowEquips >= MaxEquips - MarginEquips; }\r
142         }\r
143 \r
144         public ItemInfo()\r
145         {\r
146             MaterialHistory = new MaterialCount[Enum.GetValues(typeof (Material)).Length];\r
147             foreach (Material m in Enum.GetValues(typeof (Material)))\r
148                 MaterialHistory[(int)m] = new MaterialCount();\r
149             MarginShips = 4;\r
150             MarginEquips = 10;\r
151         }\r
152 \r
153         public void InspectBasic(dynamic json)\r
154         {\r
155             MaxShips = (int)json.api_max_chara;\r
156             MaxEquips = (int)json.api_max_slotitem;\r
157         }\r
158 \r
159         public void InspectMaterial(dynamic json)\r
160         {\r
161             foreach (var entry in json)\r
162                 MaterialHistory[(int)entry.api_id - 1].Now = (int)entry.api_value;\r
163         }\r
164 \r
165         public void InspectMaster(dynamic json)\r
166         {\r
167             var dict = new Dictionary<int, string>();\r
168             foreach (var entry in json.api_mst_slotitem_equiptype)\r
169                 dict[(int)entry.api_id] = entry.api_name;\r
170             foreach (var entry in json.api_mst_slotitem)\r
171             {\r
172                 _itemSpecs[(int)entry.api_id] = new ItemSpec\r
173                 {\r
174                     Id = (int)entry.api_id,\r
175                     Name = (string)entry.api_name,\r
176                     Type = (int)entry.api_type[2],\r
177                     TypeName = dict[(int)entry.api_type[2]],\r
178                     AntiAir = (int)entry.api_tyku,\r
179                     LoS = (int)entry.api_saku\r
180                 };\r
181             }\r
182             _itemSpecs[-1] = new ItemSpec();\r
183         }\r
184 \r
185         public void InspectSlotItem(dynamic json, bool full = false)\r
186         {\r
187             if (!json.IsArray)\r
188                 json = new[] {json};\r
189             if (full)\r
190             {\r
191                 _itemInfo.Clear();\r
192                 _itemInfo[-1] = new ItemStatus();\r
193             }\r
194             foreach (var entry in json)\r
195             {\r
196                 _itemInfo[(int)entry.api_id] = new ItemStatus\r
197                 {\r
198                     Spec = _itemSpecs[(int)entry.api_slotitem_id],\r
199                     Level = entry.api_level() ? (int)entry.api_level : 0\r
200                 };\r
201             }\r
202             NowEquips = _itemInfo.Count - 1;\r
203         }\r
204 \r
205         public void InspectCreateItem(dynamic json)\r
206         {\r
207             var m = (dynamic[])json.api_material;\r
208             for (var i = 0; i < m.Length; i++)\r
209                 MaterialHistory[i].Now = (int)m[i];\r
210             if (!json.IsDefined("api_slot_item"))\r
211                 return;\r
212             InspectSlotItem(json.api_slot_item);\r
213         }\r
214 \r
215         public void InspectGetShip(dynamic json)\r
216         {\r
217             NowShips += 1;\r
218             if (json.api_slotitem == null) // まるゆにはスロットがない\r
219                 return;\r
220             InspectSlotItem(json.api_slotitem);\r
221         }\r
222 \r
223         public void InspectDestroyItem(string request, dynamic json)\r
224         {\r
225             var values = HttpUtility.ParseQueryString(request);\r
226             DeleteItems(values["api_slotitem_ids"].Split(',').Select(int.Parse).ToArray());\r
227             var get = (int[])json.api_get_material;\r
228             for (var i = 0; i < get.Length; i++)\r
229                 MaterialHistory[i].Now += get[i];\r
230         }\r
231 \r
232         public void InspectRemodelSlot(dynamic json)\r
233         {\r
234             if (json.api_after_slot())\r
235                 InspectSlotItem(json.api_after_slot);\r
236             if (!json.api_use_slot_id())\r
237                 return;\r
238             DeleteItems(((int[])json.api_use_slot_id));\r
239         }\r
240 \r
241         public void DeleteItems(int[] ids)\r
242         {\r
243             foreach (var id in ids.Where(id => id != -1))\r
244             {\r
245                 _itemInfo.Remove(id);\r
246                 NowEquips--;\r
247             }\r
248         }\r
249 \r
250         public void CountNewItems(int[] ids)\r
251         {\r
252             foreach (var id in ids.Where(id => id != -1 && !_itemInfo.ContainsKey(id)))\r
253             {\r
254                 _itemInfo[id] = new ItemStatus();\r
255                 NowEquips++;\r
256             }\r
257         }\r
258 \r
259         public void InspectMissionResult(dynamic json)\r
260         {\r
261             if ((int)json.api_clear_result == 0) // 失敗\r
262                 return;\r
263             var get = (int[])json.api_get_material;\r
264             for (var i = 0; i < get.Length; i++)\r
265                 MaterialHistory[i].Now += get[i];\r
266         }\r
267 \r
268         public ItemSpec this[int id]\r
269         {\r
270             get { return GetSpecById(id); }\r
271         }\r
272 \r
273         public ItemSpec GetSpecById(int id)\r
274         {\r
275             return _itemInfo[id].Spec;\r
276         }\r
277 \r
278         public ItemSpec GetSpecByItemId(int id)\r
279         {\r
280             return _itemSpecs[id];\r
281         }\r
282 \r
283         public ItemStatus[] GetItemList(ShipInfo ship)\r
284         {\r
285             foreach (var e in _itemInfo)\r
286                 e.Value.Ship = new ShipStatus();\r
287             foreach (var s in ship.ShipList)\r
288             {\r
289                 foreach (var id in s.Slot)\r
290                     _itemInfo[id].Ship = s;\r
291             }\r
292             return _itemInfo.Where(e => e.Key != -1).Select(e => e.Value).ToArray();\r
293         }\r
294 \r
295         public void SaveState(Status status)\r
296         {\r
297             status.MatreialHistory = MaterialHistory;\r
298         }\r
299 \r
300         public void LoadSate(Status status)\r
301         {\r
302             if (status.MatreialHistory != null)\r
303                 status.MatreialHistory.CopyTo(MaterialHistory, 0);\r
304         }\r
305     }\r
306 \r
307     public enum Material\r
308     {\r
309         Fuel,\r
310         Bullet,\r
311         Steal,\r
312         Bouxite,\r
313         Burner,\r
314         Bucket,\r
315         Development,\r
316         Screw,\r
317     }\r
318 \r
319     public class MaterialCount\r
320     {\r
321         private int _now;\r
322 \r
323         public int BegOfDay { get; set; }\r
324         public int BegOfWeek { get; set; }\r
325         public DateTime LastSet { get; set; }\r
326 \r
327         public int Now\r
328         {\r
329             get { return _now; }\r
330             set\r
331             {\r
332                 if (!Status.Restoring) // JSONから値を復旧するときは履歴に触らない\r
333                 {\r
334                     UpdateHistory(value, _now);\r
335                     LastSet = DateTime.Now;\r
336                 }\r
337                 _now = value;\r
338             }\r
339         }\r
340 \r
341         private void UpdateHistory(int now, int prev)\r
342         {\r
343             if (LastSet == DateTime.MinValue)\r
344             {\r
345                 BegOfDay = BegOfWeek = now;\r
346                 return;\r
347             }\r
348             var morning = DateTime.Today.AddHours(5);\r
349             var dow = (int)morning.DayOfWeek;\r
350             var monday = morning.AddDays(dow == 0 ? -6 : -dow + 1);\r
351             if (DateTime.Now >= morning && LastSet < morning)\r
352                 BegOfDay = prev;\r
353             if (DateTime.Now >= monday && LastSet < monday)\r
354                 BegOfWeek = prev;\r
355         }\r
356     }\r
357 }