X-Git-Url: http://git.osdn.net/view?a=blobdiff_plain;f=KancolleSniffer%2FModel%2FItemInfo.cs;h=991cd59b5c59baabe8cbd31202f69739539bf246;hb=e02a942e514db4466185b2d6bcfba7dae86d365a;hp=1d17b0d6dbc3af0bac2ff6aef67d692472cde6c6;hpb=a1217f69d553cf6b3deff0d8d0d6b47add1b5eae;p=kancollesniffer%2FKancolleSniffer.git diff --git a/KancolleSniffer/Model/ItemInfo.cs b/KancolleSniffer/Model/ItemInfo.cs index 1d17b0d..991cd59 100644 --- a/KancolleSniffer/Model/ItemInfo.cs +++ b/KancolleSniffer/Model/ItemInfo.cs @@ -12,694 +12,33 @@ // See the License for the specific language governing permissions and // limitations under the License. -using System; using System.Collections.Generic; -using System.Drawing; using System.Linq; using KancolleSniffer.Util; -using static System.Math; namespace KancolleSniffer.Model { - public class ItemSpec - { - public static bool IncreaceLandPowerTp = false; - public int Id; - public string Name; - public int Type; - public string TypeName; - public int Firepower; - 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 int Distance; - - public ItemSpec() - { - Id = -1; - Name = ""; - } - - public bool CanAirCombat - { - get - { - switch (Type) - { - case 6: // 艦戦 - case 7: // 艦爆 - case 8: // 艦攻 - case 11: // 水爆 - case 45: // 水戦 - case 56: // 噴式戦闘機 - case 57: // 噴式戦闘爆撃機 - case 58: // 噴式攻撃機 - 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: // 局地戦闘機 - case 56: - case 57: - case 58: - case 59: // 噴式偵察機 - return true; - } - return false; - } - } - - public bool IsDiveBomber => Type == 7 || Type == 11 || Type == 57; - - public bool IsTorpedoBomber => Type == 8 || Type == 58; - - public int EffectiveAntiSubmarine - { - 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 bool IsAntiAirGun => Type == 21; - - public double ContactTriggerRate - { - get - { - switch (Type) - { - case 9: // 艦偵 - case 10: // 水偵 - case 41: // 大艇 - return 0.04; - default: - return 0; - } - } - } - - public Func GetItemTp { get; set; } - - public double TransportPoint - { - get - { - var tp = GetItemTp?.Invoke(); - if (tp >= 0) - return (double)tp; - switch (Id) - { - case 75: // ドラム缶(輸送用) - return 5.0; - case 68: // 大発動艇 - return 8.0; - case 193: // 特大発動艇 - return 8.0; - case 166: // 大発動艇(八九式中戦車&陸戦隊) - return 8.0; - case 167: // 特二式内火艇 - return 2.0; - case 230: // 特大発動艇+戦車第11連隊 - return 8.0; - case 145: // 戦闘糧食 - return 1.0; - case 150: // 秋刀魚の缶詰 - return 1.0; - case 241: // 戦闘糧食(特別なおにぎり) - return 1.0; - default: - return 0; - } - } - } - - public double ReconPlaneInterceptionBonus - { - 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: // 水上機 - case 43: // 水上戦闘機 - 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: // 陸上攻撃機 - case 38: // 局地戦闘機 - case 44: // 陸軍戦闘機 - return Color.FromArgb(57, 182, 78); - case 39: // 噴式景雲改 - case 40: // 橘花改 - return Color.FromArgb(72, 178, 141); - case 42: // 潜水艦機材 - return Color.FromArgb(158, 187, 226); - case 45: // 夜間戦闘機 - case 46: // 夜間攻撃機 - return Color.FromArgb(128, 121, 161); - case 47: // 陸上対潜哨戒機 - return Color.FromArgb(91, 113, 209); - 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; - } - - public int[] CalcFighterPower(int slot) - { - if (!Spec.CanAirCombat || slot == 0) - return new[] {0, 0}; - var unskilled = (Spec.AntiAir + FighterPowerLevelBonus) * Sqrt(slot); - return AlvBonus.Select(bonus => (int)(unskilled + bonus)).ToArray(); - } - - public int[] CalcFighterPowerInBase(int slot, bool airDefence) - { - if (!Spec.IsAircraft || slot == 0) - return new[] {0, 0}; - var airDefenceBonus = airDefence ? Spec.AntiBomber * 2 + Spec.Interception : Spec.Interception * 1.5; - var unskilled = (Spec.AntiAir + airDefenceBonus + FighterPowerLevelBonus) * Sqrt(slot); - return AlvBonusInBase.Select(bonus => (int)(unskilled + bonus)).ToArray(); - } - - 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 int[] AlvTypeBonusTable - { - get - { - switch (Spec.Type) - { - case 6: // 艦戦 - case 45: // 水戦 - case 48: // 局地戦闘機 - case 56: // 噴式戦闘機 - return new[] {0, 0, 2, 5, 9, 14, 14, 22}; - case 7: // 艦爆 - case 8: // 艦攻 - case 47: // 陸攻 - case 57: // 噴式戦闘爆撃機 - case 58: // 噴式攻撃機 - return new[] {0, 0, 0, 0, 0, 0, 0, 0}; - case 11: // 水爆 - return new[] {0, 0, 1, 1, 1, 3, 3, 6}; - default: - return null; - } - } - } - - private double[] AlvBonus - { - get - { - var table = AlvTypeBonusTable; - if (table == null) - return new[] {0.0, 0.0}; - return new[] {table[Alv] + _alvBonusMin[Alv], table[Alv] + _alvBonusMax[Alv]}; - } - } - - private double[] AlvBonusInBase - { - get - { - switch (Spec.Type) - { - case 9: // 艦偵 - case 10: // 水偵 - case 41: // 大艇 - return new[] {_alvBonusMin[Alv], _alvBonusMax[Alv]}; - default: - return AlvBonus; - } - } - } - - private double FighterPowerLevelBonus - { - get - { - switch (Spec.Type) - { - case 6: // 艦戦 - case 45: // 水戦 - case 48: // 陸戦・局戦 - return 0.2 * Level; - case 7: // 改修可能なのは爆戦のみ - return 0.25 * Level; - } - return 0; - } - } - - public double LoSLevelBonus - { - get - { - switch (Spec.Type) - { - case 10: // 水偵 - return 1.2 * Sqrt(Level); - case 11: // 水爆 - return 1.15 * Sqrt(Level); - case 12: // 小型電探 - return 1.25 * Sqrt(Level); - case 13: // 大型電探 - return 1.4 * Sqrt(Level); - case 94: // 艦上偵察機(II) - return 1.2 * Sqrt(Level); - default: - return 0; - } - } - } - - public double FirepowerLevelBonus - { - get - { - switch (Spec.Type) - { - case 1: // 小口径 - case 2: // 中口径 - case 19: // 徹甲弾 - case 21: // 対空機銃 - case 24: // 上陸用舟艇 - case 29: // 探照灯 - case 36: // 高射装置 - case 42: // 大型探照灯 - case 46: // 特型内火艇 - return Sqrt(Level); - case 3: // 大口径 - return 1.5 * Sqrt(Level); - case 4: // 副砲 - return SecondaryGunLevelBonus; - case 14: // ソナー - case 15: // 爆雷 - return Spec.Id == 226 // 九五式爆雷 - ? 0 - : 0.75 * Sqrt(Level); - default: - return 0; - } - } - } - - public double SecondaryGunLevelBonus - { - get - { - switch (Spec.Id) - { - case 10: // 12.7cm連装高角砲 - case 66: // 8cm高角砲 - case 220: // 8cm高角砲改+増設機銃 - case 275: // 10cm連装高角砲改+増設機銃 - return 0.2 * Level; - case 12: // 15.5cm三連装副砲 - case 234: // 15.5cm三連装副砲改 - case 247: // 15.2cm三連装砲 - return 0.3 * Level; - default: - return Sqrt(Level); - } - } - } - - public double TorpedoLevelBonus - { - get - { - switch (Spec.Type) - { - case 5: // 魚雷 - case 21: // 機銃 - return 1.2 * Sqrt(Level); - default: - return 0; - } - } - } - - public double AntiSubmarineLevelBonus - { - get - { - switch (Spec.Type) - { - case 14: - case 15: - return Sqrt(Level); - default: - return 0; - } - } - } - - public double BomberLevelBonus => Spec.Type == 11 /* 水爆 */ ? 0.2 * Level : 0; - - public double NightBattleLevelBonus - { - get - { - switch (Spec.Type) - { - case 1: // 小口径 - case 2: // 中口径 - case 3: // 大口径 - case 5: // 魚雷 - case 19: // 徹甲弾 - case 24: // 上陸用舟艇 - case 29: // 探照灯 - case 36: // 高射装置 - case 42: // 大型探照灯 - case 46: // 特型内火艇 - return Sqrt(Level); - case 4: // 副砲 - return SecondaryGunLevelBonus; - default: - return 0; - } - } - } - - public double EffectiveAntiAirForShip - { - get - { - switch (Spec.IconType) - { - case 15: // 機銃 - return 6 * Spec.AntiAir + 4 * Sqrt(Level); - case 16: // 高角砲 - return 4 * Spec.AntiAir + (Spec.AntiAir >= 8 ? 3 : 2) * Sqrt(Level); - case 11: // 電探 - return 3 * Spec.AntiAir; - case 30: // 高射装置 - return 4 * Spec.AntiAir + 2 * Sqrt(Level); - } - return 0; - } - } - - public double EffectiveAntiAirForFleet - { - get - { - switch (Spec.IconType) - { - case 1: - case 2: - case 3: // 主砲 - case 4: // 副砲 - case 6: // 艦戦 - case 7: // 艦爆 - case 15: // 機銃 - return 0.2 * Spec.AntiAir; - case 11: // 電探 - return 0.4 * Spec.AntiAir + 1.5 * Sqrt(Level); - case 12: // 三式弾 - return 0.6 * Spec.AntiAir; - case 16: // 高角砲 - return 0.35 * Spec.AntiAir + (Spec.AntiAir >= 8 ? 3 : 2) * Sqrt(Level); - case 30: // 高射装置 - return 0.35 * Spec.AntiAir + 2 * Sqrt(Level); - default: - if (Spec.Id == 9) // 46cm三連装砲 - return 0.25 * Spec.AntiAir; - if (Spec.Type == 10) // 水偵 - return 0.2 * Spec.AntiAir; - break; - } - return 0; - } - } - } - public class ItemInfo { - private int _nowShips, _nowEquips; - private readonly Dictionary _itemSpecs = 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 AlarmShips { get; set; } - public int MaxEquips { get; private set; } - public int MarginEquips { get; set; } - public bool AlarmEquips { get; set; } - - public int NowShips - { - get => _nowShips; - set - { - if (MaxShips != 0) - { - var limit = MaxShips - MarginShips; - AlarmShips = AlarmShips || _nowShips < limit && value >= limit; - } - _nowShips = value; - } - } - - public bool TooManyShips => MaxShips != 0 && NowShips >= MaxShips - MarginShips; + private readonly ItemMaster _itemMaster; + private readonly ItemInventory _itemInventory; + public AlarmCounter Counter { get; } - public int NowEquips + public ItemInfo(ItemMaster itemMaster, ItemInventory itemInventory) { - get => _nowEquips; - set - { - if (MaxEquips != 0) - { - var limit = MaxEquips - MarginEquips; - AlarmEquips = AlarmEquips || _nowEquips < limit && value >= limit; - } - _nowEquips = value; - } - } - - public bool TooManyEquips => MaxEquips != 0 && NowEquips >= MaxEquips - MarginEquips; - - public ItemInfo() - { - MarginShips = 4; - MarginEquips = 10; + _itemMaster = itemMaster; + _itemInventory = itemInventory; + Counter = new AlarmCounter(() => _itemInventory.Count) {Margin = 5}; } - public AdditionalData AdditionalData { get; set; } - public void InspectBasic(dynamic json) { - MaxShips = (int)json.api_max_chara; - var check = MaxEquips == 0; - MaxEquips = (int)json.api_max_slotitem; - if (check) - AlarmEquips = NowEquips >= MaxEquips - MarginEquips; + Counter.Max = (int)json.api_max_slotitem; } public void InspectMaster(dynamic json) { - var dict = new Dictionary(); - foreach (var entry in json.api_mst_slotitem_equiptype) - dict[(int)entry.api_id] = entry.api_name; - AdditionalData.LoadTpSpec(); - foreach (var entry in json.api_mst_slotitem) - { - var type = (int)entry.api_type[2]; - var id = (int)entry.api_id; - _itemSpecs[(int)entry.api_id] = new ItemSpec - { - Id = id, - Name = (string)entry.api_name, - Type = type, - TypeName = dict.TryGetValue(type, out var typeName) ? typeName : "不明", - IconType = (int)entry.api_type[3], - Firepower = (int)entry.api_houg, - 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, // 〃命中の値が対爆 - Distance = entry.api_distance() ? (int)entry.api_distance : 0, - GetItemTp = () => AdditionalData.ItemTp(id) - }; - } - _itemSpecs[-1] = _itemSpecs[0] = new ItemSpec(); - foreach (var entry in json.api_mst_useitem) - _useItemName[(int)entry.api_id] = entry.api_name; + _itemMaster.InspectMaster(json); } public void InspectSlotItem(dynamic json, bool full = false) @@ -707,21 +46,17 @@ namespace KancolleSniffer.Model if (!json.IsArray) json = new[] {json}; if (full) - { - _itemInfo.Clear(); - _itemInfo[-1] = new ItemStatus(); - } + _itemInventory.Clear(); foreach (var entry in json) { var id = (int)entry.api_id; - _itemInfo[id] = new ItemStatus(id) + _itemInventory[id] = new ItemStatus(id) { - Spec = _itemSpecs[(int)entry.api_slotitem_id], + Spec = _itemMaster[(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) @@ -733,7 +68,6 @@ namespace KancolleSniffer.Model public void InspectGetShip(dynamic json) { - NowShips += 1; if (json.api_slotitem == null) // まるゆにはスロットがない return; InspectSlotItem(json.api_slotitem); @@ -754,57 +88,49 @@ namespace KancolleSniffer.Model DeleteItems((int[])json.api_use_slot_id); } - public void DeleteItems(IEnumerable items) - { - DeleteItems(items.Select(item => item.Id)); - } - private void DeleteItems(IEnumerable ids) { - foreach (var id in ids.Where(id => id != -1)) - { - _itemInfo.Remove(id); - NowEquips--; - } + _itemInventory.Remove(ids); } - public ItemSpec GetSpecByItemId(int id) => _itemSpecs.TryGetValue(id, out var spec) ? spec : new ItemSpec(); + public ItemSpec GetSpecByItemId(int id) => _itemMaster[id]; public string GetName(int id) => GetStatus(id).Spec.Name; public ItemStatus GetStatus(int id) { - return _itemInfo.TryGetValue(id, out var item) ? item : new ItemStatus(id); + return _itemInventory[id]; } public void ClearHolder() { - foreach (var item in _itemInfo.Values) + foreach (var item in _itemInventory.AllItems) item.Holder = new ShipStatus(); } - public ItemStatus[] ItemList => (from e in _itemInfo where e.Key != -1 select e.Value).ToArray(); + public ItemStatus[] ItemList => _itemInventory.AllItems.ToArray(); - public string GetUseItemName(int id) => _useItemName[id]; + public string GetUseItemName(int id) => _itemMaster.GetUseItemName(id); public void InjectItemSpec(IEnumerable specs) { foreach (var spec in specs) - _itemSpecs.Add(spec.Id, spec); + _itemMaster[spec.Id] = spec; } public ItemStatus[] InjectItems(IEnumerable itemIds) { - var id = _itemInfo.Keys.Count + 1; + var id = _itemInventory.MaxId + 1; return itemIds.Select(itemId => { - if (!_itemSpecs.TryGetValue(itemId, out var spec)) + var spec = _itemMaster[itemId]; + if (spec.Empty) { spec = new ItemSpec {Id = itemId}; - _itemSpecs.Add(itemId, spec); + _itemMaster[itemId] = spec; } var item = new ItemStatus {Id = id++, Spec = spec}; - _itemInfo.Add(item.Id, item); + _itemInventory.Add(item); return item; }).ToArray(); }