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