1 // Copyright (C) 2013, 2014, 2015 Kazuhiro Fujieda <fujieda@users.osdn.me>
\r
3 // This program is part of KancolleSniffer.
\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
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
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
19 using System.Collections.Generic;
\r
20 using System.Drawing;
\r
24 namespace KancolleSniffer
\r
26 public class ItemSpec
\r
31 public string TypeName;
\r
32 public int IconType;
\r
35 public int AntiSubmarine;
\r
45 public bool CanAirCombat
\r
61 // http://ch.nicovideo.jp/biikame/blomaga/ar663428
\r
62 public double LoSScaleFactor()
\r
86 public bool IsAircraft
\r
106 public bool IsSonar => Type == 14 || // ソナー
\r
107 Type == 40; // 大型ソナー
\r
109 public bool IsDepthCharge => Type == 15;
\r
111 public bool IsReconSeaplane => Type == 10;
\r
123 return Color.FromArgb(209, 89, 89);
\r
125 return Color.FromArgb(253, 233, 0);
\r
127 return Color.FromArgb(88, 134, 170);
\r
129 return Color.FromArgb(93, 179, 108);
\r
131 return Color.FromArgb(223, 102, 102);
\r
133 return Color.FromArgb(95, 173, 234);
\r
135 return Color.FromArgb(254, 191, 0);
\r
137 return Color.FromArgb(142, 203, 152);
\r
139 return Color.FromArgb(231, 153, 53);
\r
141 return Color.FromArgb(69, 175, 88);
\r
143 return Color.FromArgb(254, 254, 254);
\r
146 return Color.FromArgb(102, 204, 118);
\r
149 return Color.FromArgb(126, 203, 215);
\r
151 return Color.FromArgb(254, 195, 77);
\r
153 return Color.FromArgb(154, 163, 90);
\r
154 case 21: // オートジャイロ
\r
155 return Color.FromArgb(99, 203, 115);
\r
157 return Color.FromArgb(125, 205, 217);
\r
159 return Color.FromArgb(152, 124, 172);
\r
162 return Color.FromArgb(254, 155, 0);
\r
164 return Color.FromArgb(161, 161, 160);
\r
166 return Color.FromArgb(175, 156, 126);
\r
168 return Color.FromArgb(204, 172, 252);
\r
170 return Color.FromArgb(206, 166, 108);
\r
172 return Color.FromArgb(137, 153, 77);
\r
174 return Color.FromArgb(253, 49, 49);
\r
176 return Color.FromArgb(188, 238, 155);
\r
178 return Color.FromArgb(142, 203, 152);
\r
180 return Color.FromArgb(254, 254, 254);
\r
182 return SystemColors.Control;
\r
188 public class ItemStatus
\r
190 public ItemSpec Spec { get; set; }
\r
191 public int Level { get; set; }
\r
192 public int Alv { get; set; }
\r
193 public ShipStatus Ship { get; set; }
\r
195 public ItemStatus()
\r
197 Spec = new ItemSpec();
\r
198 Ship = new ShipStatus();
\r
202 public class ItemInfo : IHaveState
\r
204 private int _nowShips, _nowEquips;
\r
205 private readonly Dictionary<int, ItemSpec> _itemSpecs = new Dictionary<int, ItemSpec>();
\r
206 private readonly Dictionary<int, ItemStatus> _itemInfo = new Dictionary<int, ItemStatus>();
\r
208 public int MaxShips { get; private set; }
\r
209 public int MarginShips { get; set; }
\r
210 public bool RingShips { get; set; }
\r
211 public int MaxEquips { get; private set; }
\r
212 public int MarginEquips { get; set; }
\r
213 public bool RingEquips { get; set; }
\r
214 public MaterialCount[] MaterialHistory { get; }
\r
216 public bool NeedSave
\r
218 get { return MaterialHistory.Any(m => m.NeedSave); }
\r
221 foreach (var m in MaterialHistory)
\r
222 m.NeedSave = value;
\r
226 public int NowShips
\r
228 get { return _nowShips; }
\r
233 var limit = MaxShips - MarginShips;
\r
234 RingShips = _nowShips < limit && value >= limit;
\r
240 public bool TooManyShips => MaxShips != 0 && NowShips >= MaxShips - MarginShips;
\r
242 public int NowEquips
\r
244 get { return _nowEquips; }
\r
247 if (MaxEquips != 0)
\r
249 var limit = MaxEquips - MarginEquips;
\r
250 RingEquips = _nowEquips < limit && value >= limit;
\r
252 _nowEquips = value;
\r
256 public bool TooManyEquips => MaxEquips != 0 && NowEquips >= MaxEquips - MarginEquips;
\r
260 MaterialHistory = new MaterialCount[Enum.GetValues(typeof(Material)).Length];
\r
261 foreach (Material m in Enum.GetValues(typeof(Material)))
\r
262 MaterialHistory[(int)m] = new MaterialCount();
\r
267 public void InspectBasic(dynamic json)
\r
269 MaxShips = (int)json.api_max_chara;
\r
270 MaxEquips = (int)json.api_max_slotitem;
\r
273 public void InspectMaterial(dynamic json)
\r
275 foreach (var entry in json)
\r
276 MaterialHistory[(int)entry.api_id - 1].Now = (int)entry.api_value;
\r
279 public void InspectMaster(dynamic json)
\r
281 var dict = new Dictionary<int, string>();
\r
282 foreach (var entry in json.api_mst_slotitem_equiptype)
\r
283 dict[(int)entry.api_id] = entry.api_name;
\r
284 foreach (var entry in json.api_mst_slotitem)
\r
286 _itemSpecs[(int)entry.api_id] = new ItemSpec
\r
288 Id = (int)entry.api_id,
\r
289 Name = (string)entry.api_name,
\r
290 Type = (int)entry.api_type[2],
\r
291 TypeName = dict[(int)entry.api_type[2]],
\r
292 IconType = (int)entry.api_type[3],
\r
293 AntiAir = (int)entry.api_tyku,
\r
294 LoS = (int)entry.api_saku,
\r
295 AntiSubmarine = (int)entry.api_tais,
\r
296 Torpedo = (int)entry.api_raig,
\r
297 Bomber = (int)entry.api_baku
\r
300 _itemSpecs[-1] = new ItemSpec();
\r
303 public void InspectSlotItem(dynamic json, bool full = false)
\r
306 json = new[] {json};
\r
310 _itemInfo[-1] = _itemInfo[0] = new ItemStatus();
\r
312 foreach (var entry in json)
\r
314 _itemInfo[(int)entry.api_id] = new ItemStatus
\r
316 Spec = _itemSpecs[(int)entry.api_slotitem_id],
\r
317 Level = entry.api_level() ? (int)entry.api_level : 0,
\r
318 Alv = entry.api_alv() ? (int)entry.api_alv : 0
\r
321 NowEquips = _itemInfo.Count - 1;
\r
324 public void InspectCreateItem(dynamic json)
\r
326 var m = (dynamic[])json.api_material;
\r
327 for (var i = 0; i < m.Length; i++)
\r
328 MaterialHistory[i].Now = (int)m[i];
\r
329 if (!json.IsDefined("api_slot_item"))
\r
331 InspectSlotItem(json.api_slot_item);
\r
334 public void InspectGetShip(dynamic json)
\r
337 if (json.api_slotitem == null) // まるゆにはスロットがない
\r
339 InspectSlotItem(json.api_slotitem);
\r
342 public void InspectDestroyItem(string request, dynamic json)
\r
344 var values = HttpUtility.ParseQueryString(request);
\r
345 DeleteItems(values["api_slotitem_ids"].Split(',').Select(int.Parse).ToArray());
\r
346 var get = (int[])json.api_get_material;
\r
347 for (var i = 0; i < get.Length; i++)
\r
348 MaterialHistory[i].Now += get[i];
\r
351 public void InspectRemodelSlot(dynamic json)
\r
353 var after = (int[])json.api_after_material;
\r
354 for (var i = 0; i < after.Length; i++)
\r
355 MaterialHistory[i].Now = after[i];
\r
356 if (json.api_after_slot())
\r
357 InspectSlotItem(json.api_after_slot);
\r
358 if (!json.api_use_slot_id())
\r
360 DeleteItems(((int[])json.api_use_slot_id));
\r
363 public void DeleteItems(int[] ids)
\r
365 foreach (var id in ids.Where(id => id != -1))
\r
367 _itemInfo.Remove(id);
\r
372 public void CountNewItems(int[] ids)
\r
374 foreach (var id in ids.Where(id => id != -1 && !_itemInfo.ContainsKey(id)))
\r
376 _itemInfo[id] = new ItemStatus();
\r
381 public void InspectMissionResult(dynamic json)
\r
383 if ((int)json.api_clear_result == 0) // 失敗
\r
385 var get = (int[])json.api_get_material;
\r
386 for (var i = 0; i < get.Length; i++)
\r
387 MaterialHistory[i].Now += get[i];
\r
390 public ItemSpec this[int id] => GetSpecById(id);
\r
392 public ItemSpec GetSpecById(int id) => _itemInfo[id].Spec;
\r
394 public ItemSpec GetSpecByItemId(int id) => _itemSpecs[id];
\r
396 public Dictionary<int, ItemStatus> ItemDict => _itemInfo;
\r
398 public void SetItemOwner(ShipStatus[] shipList)
\r
400 foreach (var e in _itemInfo)
\r
401 e.Value.Ship = new ShipStatus();
\r
402 foreach (var s in shipList)
\r
404 foreach (var id in s.Slot)
\r
405 _itemInfo[id].Ship = s;
\r
409 public void SaveState(Status status)
\r
412 status.MatreialHistory = MaterialHistory;
\r
415 public void LoadState(Status status)
\r
417 status.MatreialHistory?.CopyTo(MaterialHistory, 0);
\r
421 public enum Material
\r
433 public class MaterialCount
\r
437 public int BegOfDay { get; set; }
\r
438 public int BegOfWeek { get; set; }
\r
439 public DateTime LastSet { get; set; }
\r
440 public bool NeedSave { get; set; }
\r
444 get { return _now; }
\r
449 if (Status.Restoring) // JSONから値を復旧するときは履歴に触らない
\r
453 if (LastSet == DateTime.MinValue)
\r
455 BegOfDay = BegOfWeek = value;
\r
456 LastSet = DateTime.Now;
\r
459 UpdateHistory(prev);
\r
460 LastSet = DateTime.Now;
\r
464 private void UpdateHistory(int prev)
\r
466 var morning = DateTime.Today.AddHours(5);
\r
467 var dow = (int)morning.DayOfWeek;
\r
468 var monday = morning.AddDays(dow == 0 ? -6 : -dow + 1);
\r
469 if (DateTime.Now >= morning && LastSet < morning)
\r
471 if (DateTime.Now >= monday && LastSet < monday)
\r