X-Git-Url: http://git.osdn.net/view?a=blobdiff_plain;f=KancolleSniffer%2FItemInfo.cs;h=c3d2e32c0de3e87f88e9248f6c70ea6c0070f394;hb=6af1e5409b2adf196e1aed1858defd4303262d70;hp=9d332dfcd14947ff55dca3b39f4edf8f3089df98;hpb=b8d9297c610388b4b5eb854876f07c27bc99b26c;p=kancollesniffer%2FKancolleSniffer.git diff --git a/KancolleSniffer/ItemInfo.cs b/KancolleSniffer/ItemInfo.cs index 9d332df..c3d2e32 100644 --- a/KancolleSniffer/ItemInfo.cs +++ b/KancolleSniffer/ItemInfo.cs @@ -1,44 +1,457 @@ -// Copyright (C) 2013, 2014 Kazuhiro Fujieda +// Copyright (C) 2013, 2014, 2015 Kazuhiro Fujieda // -// This program is part of KancolleSniffer. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at // -// KancolleSniffer is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. +// http://www.apache.org/licenses/LICENSE-2.0 // -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, see . +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. -using System; using System.Collections.Generic; -using System.Web; +using System.Drawing; +using System.Linq; +using static System.Math; namespace KancolleSniffer { - public struct ItemSpec + public class ItemSpec { + public static bool IncreaceLandPowerTp = false; + public int Id; public string Name; - public int TyKu; + public int Type; + public string TypeName; + public int IconType; + public int AntiAir; + public int LoS; + public int AntiSubmarine; + public int Torpedo; + public int Bomber; + public int Interception; + public int AntiBomber; + + public ItemSpec() + { + Id = -1; + Name = ""; + } + + public bool CanAirCombat + { + get + { + switch (Type) + { + case 6: // 艦戦 + case 7: // 艦爆 + case 8: // 艦攻 + case 11: // 水爆 + case 45: // 水戦 + return true; + } + return false; + } + } + + // http://ja.kancolle.wikia.com/wiki/%E3%83%9E%E3%83%83%E3%83%97%E7%B4%A2%E6%95%B5 + public double LoSScaleFactor + { + get + { + switch (Type) + { + case 8: // 艦攻 + return 0.8; + case 9: // 艦偵 + return 1; + case 10: // 水偵 + return 1.2; + case 11: // 水爆 + return 1.1; + default: + return 0.6; + } + } + } + + public bool IsAircraft + { + get + { + switch (Type) + { + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 25: // オートジャイロ + case 26: // 対潜哨戒機 + case 41: // 大艇 + case 45: + case 47: // 陸上攻撃機 + case 48: // 局地戦闘機 + return true; + } + return false; + } + } + + public int RealAntiSubmarine + { + get + { + switch (Type) + { + case 1: // 小口径(12.7cm連装高角砲(後期型)) + case 10: // 水偵 + case 12: // 小型電探(22号対水上電探改四) + case 45: // 水戦 + return 0; + default: + return AntiSubmarine; + } + } + } + + public bool IsSonar => Type == 14 || // ソナー + Type == 40; // 大型ソナー + + public bool IsDepthCharge => Type == 15; + + public bool IsRepairFacility => Type == 31; + + public double ContactTriggerRate + { + get + { + switch (Type) + { + case 9: // 艦偵 + case 10: // 水偵 + case 41: // 大艇 + return 0.04; + default: + return 0; + } + } + } + + public double TransportPoint + { + get + { + switch (Id) + { + case 75: // ドラム缶(輸送用) + return 5.0; + case 68: // 大発動艇 + return 8.0; + case 193: // 特大発動艇 + return 8.0; + case 166: // 大発動艇(八九式中戦車&陸戦隊) + return IncreaceLandPowerTp ? 13.0 : 8.0; + case 167: // 特二式内火艇 + return IncreaceLandPowerTp ? 7.0 : 2.0; + case 145: // 戦闘糧食 + return 1.0; + case 150: // 秋刀魚の缶詰 + return 1.0; + default: + return 0; + } + } + } + + public double AirDefenceBonus + { + get + { + switch (Type) + { + case 9: + return LoS <= 7 ? 1.2 : 1.3; + case 10: + case 41: + return LoS <= 7 ? 1.1 : LoS <= 8 ? 1.13 : 1.16; + } + return 1; + } + } + + public Color Color + { + get + { + switch (IconType) + { + case 1: + case 2: + case 3: // 主砲 + case 13: // 徹甲弾 + return Color.FromArgb(209, 89, 89); + case 4: // 副砲 + return Color.FromArgb(253, 233, 0); + case 5: // 魚雷 + return Color.FromArgb(88, 134, 170); + case 6: // 艦戦 + return Color.FromArgb(93, 179, 108); + case 7: // 艦爆 + return Color.FromArgb(223, 102, 102); + case 8: // 艦攻 + return Color.FromArgb(95, 173, 234); + case 9: // 艦偵 + return Color.FromArgb(254, 191, 0); + case 10: // 水上機 + return Color.FromArgb(142, 203, 152); + case 11: // 電探 + return Color.FromArgb(231, 153, 53); + case 12: // 三式弾 + return Color.FromArgb(69, 175, 88); + case 14: // 応急修理要員 + return Color.FromArgb(254, 254, 254); + case 15: // 機銃 + case 16: // 高角砲 + return Color.FromArgb(102, 204, 118); + case 17: // 爆雷 + case 18: // ソナー + return Color.FromArgb(126, 203, 215); + case 19: // 缶 + return Color.FromArgb(254, 195, 77); + case 20: // 大発 + case 36: // 特型内火艇 + return Color.FromArgb(154, 163, 90); + case 21: // オートジャイロ + return Color.FromArgb(99, 203, 115); + case 22: // 対潜哨戒機 + return Color.FromArgb(125, 205, 217); + case 23: // 追加装甲 + return Color.FromArgb(152, 124, 172); + case 24: // 探照灯 + case 27: // 照明弾 + return Color.FromArgb(254, 155, 0); + case 25: // ドラム缶 + return Color.FromArgb(161, 161, 160); + case 26: // 艦艇修理施設 + return Color.FromArgb(175, 156, 126); + case 28: // 司令部施設 + return Color.FromArgb(204, 172, 252); + case 29: // 航空要員 + return Color.FromArgb(206, 166, 108); + case 30: // 高射装置 + return Color.FromArgb(137, 153, 77); + case 31: // 対地装備 + return Color.FromArgb(253, 49, 49); + case 32: // 水上艦要員 + return Color.FromArgb(188, 238, 155); + case 33: // 大型飛行艇 + return Color.FromArgb(142, 203, 152); + case 34: // 戦闘糧食 + return Color.FromArgb(254, 254, 254); + case 35: // 補給物資 + return Color.FromArgb(90, 200, 155); + case 37: // 陸上攻撃機 + return Color.FromArgb(57, 182, 78); + case 38: // 局地戦闘機 + return Color.FromArgb(57, 182, 78); + default: + return SystemColors.Control; + } + } + } + } + + public class ItemStatus + { + public int Id { get; set; } + public ItemSpec Spec { get; set; } = new ItemSpec(); + public int Level { get; set; } + public int Alv { get; set; } + public ShipStatus Holder { get; set; } + + public ItemStatus() + { + Id = -1; + } + + public ItemStatus(int id) + { + Id = id == 0 ? -1 : id; + } + + private readonly double[] _alvBonusMin = + { + Sqrt(0.0), Sqrt(1.0), Sqrt(2.5), Sqrt(4.0), Sqrt(5.5), Sqrt(7.0), + Sqrt(8.5), Sqrt(10.0) + }; + + private readonly double[] _alvBonusMax = + { + Sqrt(0.9), Sqrt(2.4), Sqrt(3.9), Sqrt(5.4), Sqrt(6.9), Sqrt(8.4), + Sqrt(9.9), Sqrt(12.0) + }; + + private readonly Dictionary _alvTypeBonus = new Dictionary + { + {06, new[] {0, 0, 2, 5, 9, 14, 14, 22}}, // 艦戦 + {07, new[] {0, 0, 0, 0, 0, 0, 0, 0}}, // 艦爆 + {08, new[] {0, 0, 0, 0, 0, 0, 0, 0}}, // 艦攻 + {11, new[] {0, 0, 1, 1, 1, 3, 3, 6}}, // 水爆 + {45, new[] {0, 0, 2, 5, 9, 14, 14, 22}}, // 水戦 + {48, new[] {0, 0, 2, 5, 9, 14, 14, 22}} // 局地戦闘機 + }; + + public double[] AlvBonus + { + get + { + int[] table; + if (!_alvTypeBonus.TryGetValue(Spec.Type, out table)) + return new[] {0.0, 0.0}; + return new[] {table[Alv] + _alvBonusMin[Alv], table[Alv] + _alvBonusMax[Alv]}; + } + } + + public double[] AlvBonusInBase + { + get + { + switch (Spec.Type) + { + case 9: // 艦偵 + case 10: // 水偵 + case 41: // 大艇 + return new[] {_alvBonusMin[Alv], _alvBonusMax[Alv]}; + default: + return AlvBonus; + } + } + } + + public double FighterPowerLevelBonus + { + get + { + if (Spec.Type == 6) + return 0.2 * Level; + if (Spec.Type == 7) // 改修可能なのは爆戦のみ + return 0.25 * Level; + return 0; + } + } + + public double LoSLevelBonus + { + get + { + switch (Spec.Type) + { + case 10: // 水偵 + return 1.2 * Sqrt(Level); + case 12: // 小型電探 + case 13: // 大型電探 + return 1.25 * Sqrt(Level); + default: + return 0; + } + } + } + + public double FirePowerLevelBonus + { + get + { + switch (Spec.Type) + { + case 1: // 小口径 + case 2: // 中口径 + return Sqrt(Level); + case 3: // 大口径 + return 1.5 * Sqrt(Level); + case 4: // 副砲 + return Sqrt(Level); + case 14: // ソナー + case 15: // 爆雷 + return 0.75 * Sqrt(Level); + case 19: // 徹甲弾 + return Sqrt(Level); + default: + return 0; + } + } + } + + public double TorpedoLevelBonus + { + get + { + if (Spec.Type == 5) // 魚雷 + return 1.2 * Sqrt(Level); + if (Spec.Type == 21) // 機銃 + return 1.2 * Sqrt(Level); + return 0; + } + } + + public double AntiSubmarineLevelBonus + { + get + { + switch (Spec.Type) + { + case 14: + case 15: + return Sqrt(Level); + default: + return 0; + } + } + } + + public double NightBattleLevelBonus + { + get + { + switch (Spec.Type) + { + case 1: // 小口径 + case 2: // 中口径 + case 3: // 大口径 + return Sqrt(Level); + case 4: // 副砲 + return Sqrt(Level); + case 5: // 魚雷 + case 19: // 徹甲弾 + case 29: // 探照灯 + case 36: // 高射装置 + case 42: // 大型探照灯 + return Sqrt(Level); + default: + return 0; + } + } + } } public class ItemInfo { - private int _nowShips; + private int _nowShips, _nowEquips; private readonly Dictionary _itemSpecs = new Dictionary(); - private readonly Dictionary _itemIds = new Dictionary(); + private readonly Dictionary _itemInfo = new Dictionary(); + private readonly Dictionary _useItemName = new Dictionary(); public int MaxShips { get; private set; } public int MarginShips { get; set; } - public bool NeedRing { get; set; } - public int NowItems { get; set; } - public int MaxItems { get; private set; } - public MaterialCount[] MaterialHistory { get; private set; } + public bool RingShips { get; set; } + public int MaxEquips { get; private set; } + public int MarginEquips { get; set; } + public bool RingEquips { get; set; } public int NowShips { @@ -48,49 +461,72 @@ namespace KancolleSniffer if (MaxShips != 0) { var limit = MaxShips - MarginShips; - NeedRing = _nowShips < limit && value >= limit; + RingShips = RingShips || _nowShips < limit && value >= limit; } _nowShips = value; } } - public bool TooManyShips + public bool TooManyShips => MaxShips != 0 && NowShips >= MaxShips - MarginShips; + + public int NowEquips { - get { return MaxShips != 0 && NowShips >= MaxShips - MarginShips; } + get { return _nowEquips; } + private set + { + if (MaxEquips != 0) + { + var limit = MaxEquips - MarginEquips; + RingEquips = RingEquips || _nowEquips < limit && value >= limit; + } + _nowEquips = value; + } } + public bool TooManyEquips => MaxEquips != 0 && NowEquips >= MaxEquips - MarginEquips; + public ItemInfo() { - MaterialHistory = new MaterialCount[Enum.GetValues(typeof (Material)).Length]; - foreach (Material m in Enum.GetValues(typeof (Material))) - MaterialHistory[(int)m] = new MaterialCount(); MarginShips = 4; + MarginEquips = 10; } public void InspectBasic(dynamic json) { MaxShips = (int)json.api_max_chara; - MaxItems = (int)json.api_max_slotitem; - } - - public void InspectMaterial(dynamic json) - { - foreach (var entry in json) - MaterialHistory[(int)entry.api_id - 1].Now = (int)entry.api_value; + var check = MaxEquips == 0; + MaxEquips = (int)json.api_max_slotitem; + if (check) + RingEquips = NowEquips >= MaxEquips - MarginEquips; } public void InspectMaster(dynamic json) { - foreach (var entry in json) + var dict = new Dictionary(); + foreach (var entry in json.api_mst_slotitem_equiptype) + dict[(int)entry.api_id] = entry.api_name; + foreach (var entry in json.api_mst_slotitem) { + var type = (int)entry.api_type[2]; _itemSpecs[(int)entry.api_id] = new ItemSpec { + Id = (int)entry.api_id, Name = (string)entry.api_name, - TyKu = (int)entry.api_type[0] == 3 || (int)entry.api_type[2] == 11 ? (int)entry.api_tyku : 0 - // 艦載機と水上爆撃機のみ + Type = type, + TypeName = dict[(int)entry.api_type[2]], + IconType = (int)entry.api_type[3], + AntiAir = (int)entry.api_tyku, + LoS = (int)entry.api_saku, + AntiSubmarine = (int)entry.api_tais, + Torpedo = (int)entry.api_raig, + Bomber = (int)entry.api_baku, + Interception = type == 48 ? (int)entry.api_houk : 0, // 局地戦闘機は回避の値が迎撃 + AntiBomber = type == 48 ? (int)entry.api_houm : 0 // 〃命中の値が対爆 }; } - _itemSpecs[-1] = new ItemSpec(); + _itemSpecs[-1] = _itemSpecs[0] = new ItemSpec(); + foreach (var entry in json.api_mst_useitem) + _useItemName[(int)entry.api_id] = entry.api_name; } public void InspectSlotItem(dynamic json, bool full = false) @@ -98,10 +534,21 @@ namespace KancolleSniffer if (!json.IsArray) json = new[] {json}; if (full) - NowItems = ((object[])json).Length; + { + _itemInfo.Clear(); + _itemInfo[-1] = new ItemStatus(); + } foreach (var entry in json) - _itemIds[(int)entry.api_id] = (int)entry.api_slotitem_id; - _itemIds[-1] = -1; + { + var id = (int)entry.api_id; + _itemInfo[id] = new ItemStatus(id) + { + Spec = _itemSpecs[(int)entry.api_slotitem_id], + Level = entry.api_level() ? (int)entry.api_level : 0, + Alv = entry.api_alv() ? (int)entry.api_alv : 0 + }; + } + NowEquips = _itemInfo.Count - 1; } public void InspectCreateItem(dynamic json) @@ -109,7 +556,6 @@ namespace KancolleSniffer if (!json.IsDefined("api_slot_item")) return; InspectSlotItem(json.api_slot_item); - NowItems++; } public void InspectGetShip(dynamic json) @@ -118,96 +564,55 @@ namespace KancolleSniffer if (json.api_slotitem == null) // まるゆにはスロットがない return; InspectSlotItem(json.api_slotitem); - NowItems += ((object[])json.api_slotitem).Length; } public void InspectDestroyItem(string request, dynamic json) { var values = HttpUtility.ParseQueryString(request); - NowItems -= values["api_slotitem_ids"].Split(',').Length; - var get = (int[])json.api_get_material; - for (var i = 0; i < get.Length; i++) - MaterialHistory[i].Now += get[i]; + DeleteItems(values["api_slotitem_ids"].Split(',').Select(int.Parse).ToArray()); } - public void InspectMissionResult(dynamic json) + public void InspectRemodelSlot(dynamic json) { - if ((int)json.api_clear_result == 0) // 失敗 + if (json.api_after_slot()) + InspectSlotItem(json.api_after_slot); + if (!json.api_use_slot_id()) return; - var get = (int[])json.api_get_material; - for (var i = 0; i < get.Length; i++) - MaterialHistory[i].Now += get[i]; + DeleteItems((int[])json.api_use_slot_id); } - public ItemSpec this[int id] + public void DeleteItems(ItemStatus[] items) { - get { return GetSpecById(id); } + DeleteItems(items.Select(item => item.Id)); } - public ItemSpec GetSpecById(int id) + private void DeleteItems(IEnumerable ids) { - return _itemSpecs[_itemIds[id]]; + foreach (var id in ids.Where(id => id != -1)) + { + _itemInfo.Remove(id); + NowEquips--; + } } - public ItemSpec GetSpecByItemId(int id) - { - return _itemSpecs[id]; - } + public ItemSpec GetSpecByItemId(int id) => _itemSpecs[id]; - public void SaveState(Status status) - { - status.MatreialHistory = MaterialHistory; - } + public string GetName(int id) => GetStatus(id).Spec.Name; - public void LoadSate(Status status) + public ItemStatus GetStatus(int id) { - if (status.MatreialHistory != null) - MaterialHistory = status.MatreialHistory; + ItemStatus item; + return _itemInfo.TryGetValue(id, out item) ? item : new ItemStatus(id); } - } - - public enum Material - { - Fuel, - Bullet, - Steal, - Bouxite, - Development, - Bucket, - Burner, - } - - public class MaterialCount - { - private int _now; - - public int BegOfDay { get; set; } - public int BegOfWeek { get; set; } - public DateTime LastSet { get; set; } - public int Now + public void ClearHolder() { - get { return _now; } - set - { - if (!Status.Restoring) // JSONから値を復旧するときは履歴に触らない - { - UpdateHistory(); - LastSet = DateTime.Now; - } - _now = value; - } + foreach (var item in _itemInfo.Values) + item.Holder = new ShipStatus(); } - public void UpdateHistory() - { - var morning = DateTime.Today.AddHours(5); - var dow = (int)morning.DayOfWeek; - var monday = morning.AddDays(dow == 0 ? -6 : -dow + 1); - if (DateTime.Now >= morning && LastSet < morning) - BegOfDay = _now; - if (DateTime.Now >= monday && LastSet < monday) - BegOfWeek = _now; - } + public ItemStatus[] ItemList => (from e in _itemInfo where e.Key != -1 select e.Value).ToArray(); + + public string GetUseItemName(int id) => _useItemName[id]; } } \ No newline at end of file