OSDN Git Service

「軽巡」級の改修工事を実施せよ!と続~のカウンターを実装する
[kancollesniffer/KancolleSniffer.git] / KancolleSniffer / Model / QuestCounter.cs
index aa66f17..db979b9 100644 (file)
@@ -77,11 +77,11 @@ namespace KancolleSniffer.Model
 \r
         public override string ToString()\r
         {\r
-            if (Id == 280 || Id == 426 || Id == 854 || Id == 873 || Id == 888 || Id == 894)\r
-                return $"{NowArray.Count(n => n >= 1)}/{Spec.MaxArray.Length}";\r
-            return NowArray != null\r
-                ? string.Join(" ", NowArray.Zip(Spec.MaxArray, (n, m) => $"{n}/{m}"))\r
-                : $"{Now}/{Spec.Max}";\r
+            return Spec.MaxArray != null && Spec.MaxArray.All(x => x == 1)\r
+                ? string.Join("\u200a", NowArray.Select(n => (n % 10).ToString()))\r
+                : Spec.MaxArray != null\r
+                    ? string.Join(" ", NowArray.Zip(Spec.MaxArray, (n, m) => $"{n}/{m}"))\r
+                    : $"{Now}/{Spec.Max}";\r
         }\r
 \r
         public QuestCount Clone()\r
@@ -101,49 +101,33 @@ namespace KancolleSniffer.Model
             return NowArray.SequenceEqual(other.NowArray);\r
         }\r
 \r
+        private static string MapString(int map)\r
+        {\r
+            return map switch\r
+            {\r
+                721 => "7-2G",\r
+                722 => "7-2M",\r
+                _ => $"{map / 10}-{map % 10}"\r
+            };\r
+        }\r
+\r
         public string ToToolTip()\r
         {\r
-            switch (Id)\r
+            if (NowArray == null)\r
+                return "";\r
+            switch (Spec)\r
             {\r
-                case 280:\r
-                    return string.Join(" ",\r
-                        new[] {"1-2", "1-3", "1-4", "2-1"}.Zip(NowArray, (map, n) => n >= 1 ? map : "")\r
-                            .Where(s => !string.IsNullOrEmpty(s)));\r
-                case 426:\r
-                    return string.Join(" ",\r
-                        new[] {"警備任務", "対潜警戒任務", "海上護衛任務", "強硬偵察任務"}\r
-                            .Zip(NowArray, (mission, n) => n >= 1 ? mission : "")\r
-                            .Where(s => !string.IsNullOrEmpty(s)));\r
-                case 428:\r
-                    return string.Join(" ",\r
-                        new[] {"対潜警戒任務", "海峡警備行動", "長時間対潜警戒"}.Zip(NowArray, (mission, n) => n >= 1 ? mission + n : "")\r
-                            .Where(s => !string.IsNullOrEmpty(s)));\r
-                case 854:\r
-                    return string.Join(" ",\r
-                        new[] {"2-4", "6-1", "6-3", "6-4"}.Zip(NowArray, (map, n) => n >= 1 ? map : "")\r
-                            .Where(s => !string.IsNullOrEmpty(s)));\r
-                case 873:\r
-                    return string.Join(" ",\r
-                        new[] {"3-1", "3-2", "3-3"}.Zip(NowArray, (map, n) => n >= 1 ? map : "")\r
-                            .Where(s => !string.IsNullOrEmpty(s)));\r
-                case 888:\r
-                    return string.Join(" ",\r
-                        new[] {"5-1", "5-3", "5-4"}.Zip(NowArray, (map, n) => n >= 1 ? map : "")\r
-                            .Where(s => !string.IsNullOrEmpty(s)));\r
-                case 688:\r
-                    return string.Join(" ",\r
-                        new[] {"艦戦", "艦爆", "艦攻", "水偵"}.Zip(NowArray, (type, n) => n >= 1 ? type + n : "")\r
-                            .Where(s => !string.IsNullOrEmpty(s)));\r
-                case 893:\r
-                    return string.Join(" ",\r
-                        new[] {"1-5", "7-1", "7-2G", "7-2M"}.Zip(NowArray, (map, n) => n >= 1 ? $"{map}:{n}" : "")\r
-                            .Where(s => !string.IsNullOrEmpty(s)));\r
-                case 894:\r
-                    return string.Join(" ",\r
-                        new[] {"1-3", "1-4", "2-1", "2-2", "2-3"}.Zip(NowArray, (map, n) => n >= 1 ? map : "")\r
-                            .Where(s => !string.IsNullOrEmpty(s)));\r
+                case QuestSortie sortie when sortie.Maps != null && sortie.MaxArray != null:\r
+                    return string.Join(" ", sortie.Maps.Zip(NowArray, (map, n) => $"{MapString(map)}:{n}"));\r
+                case QuestMission mission when mission.Ids != null:\r
+                    return string.Join(" ", mission.Names.Zip(NowArray, (name, n) => $"{name}{n}"));\r
+                default:\r
+                    return string.Join(" ", (Id switch\r
+                    {\r
+                        688 => new[] {"艦戦", "艦爆", "艦攻", "水偵"},\r
+                        _ => new string[0]\r
+                    }).Zip(NowArray, (entry, n) => $"{entry}{n}"));\r
             }\r
-            return "";\r
         }\r
 \r
         public bool Cleared => NowArray?.Zip(Spec.MaxArray, (n, m) => n >= m).All(x => x) ??\r
@@ -153,18 +137,60 @@ namespace KancolleSniffer.Model
     public class QuestCounter\r
     {\r
         private readonly QuestInfo _questInfo;\r
-        private readonly ItemInfo _itemInfo;\r
+        private readonly ItemInventory _itemInventory;\r
+        private readonly ShipInventory _shipInventory;\r
         private readonly BattleInfo _battleInfo;\r
         private readonly SortedDictionary<int, QuestStatus> _quests;\r
         private int _map;\r
-        private int _cell;\r
         private bool _boss;\r
 \r
-        public QuestCounter(QuestInfo questInfo, ItemInfo itemInfo, BattleInfo battleInfo)\r
+        private class ResultShipSpecs\r
+        {\r
+            public ShipSpec[] Specs { get; }\r
+            public NameChecker Names { get; }\r
+            public int[] Types { get; }\r
+            public int[] Classes { get; }\r
+            public ShipSpec Flagship { get; }\r
+            public int FlagshipType { get; }\r
+\r
+            public class NameChecker\r
+            {\r
+                private readonly string[] _names;\r
+\r
+                public NameChecker(ShipSpec[] specs)\r
+                {\r
+                    _names = specs.Select(spec => spec.Name).ToArray();\r
+                }\r
+\r
+                public bool Contains(string demand)\r
+                {\r
+                    return _names.Any(name => name.StartsWith(demand));\r
+                }\r
+\r
+                public int Count(params string[] demands)\r
+                {\r
+                    return demands.Sum(demand => _names.Count(name => name.StartsWith(demand)));\r
+                }\r
+            }\r
+\r
+            public ResultShipSpecs(BattleInfo battleInfo)\r
+            {\r
+                Specs = battleInfo.Result?.Friend.Main.Where(s => s.NowHp > 0).Select(ship => ship.Spec).ToArray() ??\r
+                        new ShipSpec[0];\r
+                Names = new NameChecker(Specs);\r
+                Types = Specs.Select(spec => spec.ShipType).ToArray();\r
+                Classes = Specs.Select(spec => spec.ShipClass).ToArray();\r
+                Flagship = Specs.FirstOrDefault();\r
+                FlagshipType = Types.FirstOrDefault();\r
+            }\r
+        }\r
+\r
+        public QuestCounter(QuestInfo questInfo, ItemInventory itemInventory, ShipInventory shipInventory, BattleInfo battleInfo)\r
         {\r
             _questInfo = questInfo;\r
             _quests = questInfo.QuestDictionary;\r
-            _itemInfo = itemInfo;\r
+            _itemInventory = itemInventory;\r
+            _shipInventory = shipInventory;\r
             _battleInfo = battleInfo;\r
         }\r
 \r
@@ -183,277 +209,159 @@ namespace KancolleSniffer.Model
         public void InspectMapNext(dynamic json)\r
         {\r
             _map = (int)json.api_maparea_id * 10 + (int)json.api_mapinfo_no;\r
-            _cell = json.api_no() ? (int)json.api_no : 0;\r
+            var cell = json.api_no() ? (int)json.api_no : 0;\r
+            if (_map == 72)\r
+            {\r
+                if (cell == 7)\r
+                    _map = 721;\r
+                else if (cell == 15)\r
+                    _map = 722;\r
+            }\r
+            if (_map == 73)\r
+            {\r
+                if (cell == 5)\r
+                    _map = 731;\r
+                else if (cell == 18)\r
+                    _map = 732;\r
+            }\r
             _boss = (int)json.api_event_id == 5;\r
 \r
-            if (_quests.TryGetValue(861, out var q861))\r
+            if (_map != 16 || (int)json.api_event_id != 8)\r
+                return;\r
+            foreach (var count in _quests.Values.Select(q => q.Count))\r
             {\r
-                if (_map == 16 && (int)json.api_event_id == 8)\r
-                {\r
-                    var fleet = _battleInfo.Result.Friend.Main.Where(s => s.NowHp > 0).Select(s => s.Spec.ShipType)\r
-                        .ToArray();\r
-                    if (fleet.Count(s => s == 10 || s == 22) == 2)\r
-                        Increment(q861.Count);\r
-                }\r
+                if (!(count.Spec is QuestSortie sortie) || sortie.Maps == null)\r
+                    continue;\r
+                if (!FleetCheck(count.Id))\r
+                    continue;\r
+                if (sortie.Count(count, "S", _map, true))\r
+                    NeedSave = true;\r
             }\r
         }\r
 \r
         public void InspectBattleResult(dynamic json)\r
         {\r
             var rank = json.api_win_rank;\r
-            foreach (var quest in _quests.Values)\r
+            foreach (var count in _quests.Values.Select(q => q.Count))\r
             {\r
-                var count = quest.Count;\r
                 switch (count.Spec)\r
                 {\r
                     case QuestSortie sortie:\r
-                        if (count.Id == 216 && !_boss || sortie.Check(rank, _map, _boss))\r
+                        if (!FleetCheck(count.Id))\r
+                            continue;\r
+                        if (!_boss && count.Id == 216)\r
+                        {\r
                             Increment(count);\r
-                        break;\r
+                            continue;\r
+                        }\r
+                        if (sortie.Count(count, rank, _map, _boss))\r
+                            NeedSave = true;\r
+                        continue;\r
                     case QuestEnemyType enemyType:\r
                         var num = enemyType.CountResult(\r
                             _battleInfo.Result.Enemy.Main.Concat(_battleInfo.Result.Enemy.Guard));\r
                         if (num > 0)\r
                             Add(count, num);\r
-                        break;\r
-                }\r
-            }\r
-            if (_quests.TryGetValue(214, out var ago))\r
-            {\r
-                var count = ago.Count;\r
-                if (_boss)\r
-                {\r
-                    IncrementNth(count, 2);\r
-                    if (QuestSortie.CompareRank(rank, "B") <= 0)\r
-                        IncrementNth(count, 3);\r
-                }\r
-                if (rank == "S")\r
-                    IncrementNth(count, 1);\r
-            }\r
-            if (_quests.TryGetValue(249, out var q249))\r
-            {\r
-                if (_map == 25 && _boss && QuestSortie.CompareRank(rank, "S") == 0)\r
-                {\r
-                    var fleet = _battleInfo.Result.Friend.Main.Where(s => s.NowHp > 0).Select(s => s.Spec.Id)\r
-                        .ToArray();\r
-                    if (fleet.Intersect(new[] {62, 63, 64, 265, 266, 268, 319, 192, 194}).Count() == 3)\r
-                        Increment(q249.Count);\r
+                        continue;\r
                 }\r
+                if (count.Id == 214)\r
+                    CountAgo(count, rank);\r
             }\r
-            if (_quests.TryGetValue(257, out var q257))\r
-            {\r
-                if (_map == 14 && _boss && QuestSortie.CompareRank(rank, "S") == 0)\r
-                {\r
-                    var fleet = _battleInfo.Result.Friend.Main.Where(s => s.NowHp > 0).Select(s => s.Spec.ShipType)\r
-                        .ToArray();\r
-                    if (fleet[0] == 3 && fleet.Count(s => s == 3) <= 3 && fleet.All(s => s == 2 || s == 3))\r
-                        Increment(q257.Count);\r
-                }\r
-            }\r
-            if (_quests.TryGetValue(259, out var q259))\r
+        }\r
+\r
+        private void CountAgo(QuestCount count, string rank)\r
+        {\r
+            if (QuestSortie.CompareRank(rank, "S") == 0)\r
+                IncrementNth(count, 1);\r
+            if (!_boss)\r
+                return;\r
+            IncrementNth(count, 2);\r
+            if (QuestSortie.CompareRank(rank, "B") <= 0)\r
+                IncrementNth(count, 3);\r
+        }\r
+\r
+        private bool FleetCheck(int id)\r
+        {\r
+            var specs = new ResultShipSpecs(_battleInfo);\r
+            switch (id)\r
             {\r
-                if (_map == 51 && _boss && QuestSortie.CompareRank(rank, "S") == 0)\r
-                {\r
-                    var fleet = _battleInfo.Result.Friend.Main.Where(s => s.NowHp > 0).Select(s => s.Spec).ToArray();\r
-                    // ReSharper disable once IdentifierTypo\r
-                    var ctype = new[]\r
+                case 249:\r
+                    return specs.Names.Count("妙高", "那智", "羽黒") == 3;\r
+                case 257:\r
+                    return specs.FlagshipType == 3 && specs.Types.Count(s => s == 3) <= 3 &&\r
+                           specs.Types.All(s => s == 2 || s == 3);\r
+                case 259:\r
+                    return specs.Types.Count(type => type == 3) > 0 && specs.Classes.Count(c => new[]\r
                     {\r
                         2, // 伊勢型\r
                         19, // 長門型\r
                         26, // 扶桑型\r
                         37 // 大和型\r
-                    };\r
-                    if (fleet.Select(s => s.ShipClass).Count(c => ctype.Contains(c)) == 3 &&\r
-                        fleet.Count(s => s.ShipType == 3) > 0)\r
-                    {\r
-                        Increment(q259.Count);\r
-                    }\r
-                }\r
-            }\r
-            if (_quests.TryGetValue(264, out var q264))\r
-            {\r
-                if (_map == 42 && _boss && QuestSortie.CompareRank(rank, "S") == 0)\r
-                {\r
-                    var fleet = _battleInfo.Result.Friend.Main.Where(s => s.NowHp > 0).Select(s => s.Spec)\r
-                        .ToArray();\r
-                    if (fleet.Count(spec => spec.ShipType == 2) >= 2 &&\r
-                        fleet.Count(spec => spec.IsAircraftCarrier) >= 2)\r
-                        Increment(q264.Count);\r
-                }\r
-            }\r
-            if (_quests.TryGetValue(266, out var q266))\r
-            {\r
-                if (_map == 25 && _boss && QuestSortie.CompareRank(rank, "S") == 0)\r
-                {\r
-                    var fleet = _battleInfo.Result.Friend.Main.Where(s => s.NowHp > 0).Select(s => s.Spec.ShipType)\r
-                        .ToArray();\r
-                    if (fleet[0] == 2 && fleet.OrderBy(x => x).SequenceEqual(new[] {2, 2, 2, 2, 3, 5}))\r
-                        Increment(q266.Count);\r
-                }\r
-            }\r
-            if (_quests.TryGetValue(280, out var q280))\r
-            {\r
-                if (!(_boss && QuestSortie.CompareRank(rank, "S") == 0))\r
-                    return;\r
-                var shipTypes = _battleInfo.Result.Friend.Main.Where(s => s.NowHp > 0).Select(s => s.Spec.ShipType)\r
-                    .ToArray();\r
-                if (!(shipTypes.Count(type => type == 1 || type == 2) >= 3 &&\r
-                      shipTypes.Any(type => new[] {3, 4, 7, 21}.Contains(type))))\r
-                    return;\r
-                var count = q280.Count;\r
-                switch (_map)\r
-                {\r
-                    case 12:\r
-                        IncrementNth(count, 0);\r
-                        break;\r
-                    case 13:\r
-                        IncrementNth(count, 1);\r
-                        break;\r
-                    case 14:\r
-                        IncrementNth(count, 2);\r
-                        break;\r
-                    case 21:\r
-                        IncrementNth(count, 3);\r
-                        break;\r
-                }\r
-            }\r
-            if (_quests.TryGetValue(854, out var opz) && _boss)\r
-            {\r
-                var count = opz.Count;\r
-                switch (_map)\r
-                {\r
-                    case 24 when QuestSortie.CompareRank(rank, "A") <= 0:\r
-                        IncrementNth(count, 0);\r
-                        break;\r
-                    case 61 when QuestSortie.CompareRank(rank, "A") <= 0:\r
-                        IncrementNth(count, 1);\r
-                        break;\r
-                    case 63 when QuestSortie.CompareRank(rank, "A") <= 0:\r
-                        IncrementNth(count, 2);\r
-                        break;\r
-                    case 64 when QuestSortie.CompareRank(rank, "S") <= 0:\r
-                        IncrementNth(count, 3);\r
-                        break;\r
-                }\r
-            }\r
-            if (_quests.TryGetValue(862, out var q862))\r
-            {\r
-                if (_map == 63 && _boss && QuestSortie.CompareRank(rank, "A") <= 0)\r
-                {\r
-                    var fleet = _battleInfo.Result.Friend.Main.Where(s => s.NowHp > 0).Select(s => s.Spec.ShipType)\r
-                        .ToArray();\r
-                    if (fleet.Count(s => s == 3) >= 2 && fleet.Count(s => s == 16) >= 1)\r
-                        Increment(q862.Count);\r
-                }\r
-            }\r
-            if (_quests.TryGetValue(873, out var q873))\r
-            {\r
-                if (_battleInfo.Result.Friend.Main.Count(s => s.NowHp > 0 && s.Spec.ShipType == 3) >= 1 &&\r
-                    _boss && QuestSortie.CompareRank(rank, "A") <= 0)\r
-                {\r
-                    var count = q873.Count;\r
-                    switch (_map)\r
-                    {\r
-                        case 31:\r
-                            IncrementNth(count, 0);\r
-                            break;\r
-                        case 32:\r
-                            IncrementNth(count, 1);\r
-                            break;\r
-                        case 33:\r
-                            IncrementNth(count, 2);\r
-                            break;\r
-                    }\r
-                }\r
-            }\r
-            if (_quests.TryGetValue(875, out var q875))\r
-            {\r
-                if (_map == 54 && _boss && QuestSortie.CompareRank(rank, "S") == 0)\r
-                {\r
-                    var fleet = _battleInfo.Result.Friend.Main.Where(s => s.NowHp > 0).Select(s => s.Spec.Id).ToArray();\r
-                    if (fleet.Contains(543) && fleet.Intersect(new[] {344, 345, 359}).Any())\r
-                        Increment(q875.Count);\r
-                }\r
-            }\r
-            if (_quests.TryGetValue(888, out var q888))\r
-            {\r
-                if (!_boss || QuestSortie.CompareRank(rank, "S") != 0)\r
-                    return;\r
-                var fleet = from ship in _battleInfo.Result.Friend.Main where ship.NowHp > 0 select ship.Spec.Id;\r
-                var member = new[]\r
-                {\r
-                    69, 272, 427, // 鳥海\r
-                    61, 264, // 青葉\r
-                    123, 295, 142, // 衣笠\r
-                    59, 262, 416, // 古鷹\r
-                    60, 263, 417, // 加古\r
-                    51, 213, 477, // 天龍\r
-                    115, 293 // 夕張\r
-                };\r
-                if (fleet.Intersect(member).Count() < 4)\r
-                    return;\r
-                var count = q888.Count;\r
-                switch (_map)\r
-                {\r
-                    case 51:\r
-                        IncrementNth(count, 0);\r
-                        break;\r
-                    case 53:\r
-                        IncrementNth(count, 1);\r
-                        break;\r
-                    case 54:\r
-                        IncrementNth(count, 2);\r
-                        break;\r
-                }\r
-            }\r
-            if (_quests.TryGetValue(893, out var q893))\r
-            {\r
-                if (!_boss || QuestSortie.CompareRank(rank, "S") != 0)\r
-                    return;\r
-                var count = q893.Count;\r
-                switch (_map)\r
-                {\r
-                    case 15:\r
-                        IncrementNth(count, 0);\r
-                        break;\r
-                    case 71:\r
-                        IncrementNth(count, 1);\r
-                        break;\r
-                    case 72:\r
-                        if (_cell == 7)\r
-                        {\r
-                            IncrementNth(count, 2);\r
-                            break;\r
-                        }\r
-                        IncrementNth(count, 3);\r
-                        break;\r
-                }\r
-            }\r
-            if (_quests.TryGetValue(894, out var q894))\r
-            {\r
-                if (!_boss ||\r
-                    QuestSortie.CompareRank(rank, "S") != 0 ||\r
-                    !_battleInfo.Result.Friend.Main.Any(s => s.Spec.IsAircraftCarrier && s.NowHp > 0))\r
-                    return;\r
-                var count = q894.Count;\r
-                switch (_map)\r
-                {\r
-                    case 13:\r
-                        IncrementNth(count, 0);\r
-                        break;\r
-                    case 14:\r
-                        IncrementNth(count, 1);\r
-                        break;\r
-                    case 21:\r
-                        IncrementNth(count, 2);\r
-                        break;\r
-                    case 22:\r
-                        IncrementNth(count, 3);\r
-                        break;\r
-                    case 23:\r
-                        IncrementNth(count, 4);\r
-                        break;\r
-                }\r
+                    }.Contains(c)) == 3;\r
+                case 264:\r
+                    return specs.Types.Count(type => type == 2) >= 2 &&\r
+                           specs.Specs.Count(spec => spec.IsAircraftCarrier) >= 2;\r
+                case 266:\r
+                    return specs.FlagshipType == 2 &&\r
+                           specs.Types.OrderBy(x => x).SequenceEqual(new[] {2, 2, 2, 2, 3, 5});\r
+                case 280:\r
+                case 284:\r
+                    return specs.Types.Count(type => type == 1 || type == 2) >= 3 &&\r
+                           specs.Types.Intersect(new[] {3, 4, 7, 21}).Any();\r
+                case 840:\r
+                    return new[] {3, 4, 7, 21}.Contains(specs.FlagshipType) &&\r
+                           specs.Types.Count(type => type == 2 || type == 1) >= 3;\r
+                case 861:\r
+                    return specs.Types.Count(s => s == 10 || s == 22) == 2;\r
+                case 862:\r
+                    return specs.Types.Count(s => s == 3) >= 2 && specs.Types.Count(s => s == 16) >= 1;\r
+                case 873:\r
+                    return specs.Types.Count(type => type == 3) >= 1;\r
+                case 875:\r
+                    return specs.Names.Contains("長波改二") &&\r
+                           specs.Names.Count("朝霜改", "高波改", "沖波改") > 0;\r
+                case 888:\r
+                    return specs.Names.Count("鳥海", "青葉", "衣笠", "加古", "古鷹", "天龍", "夕張") >= 4;\r
+                case 894:\r
+                    return specs.Specs.Any(spec => spec.IsAircraftCarrier);\r
+                case 903:\r
+                    return specs.Flagship.Name.StartsWith("夕張改二") &&\r
+                           (specs.Names.Count("睦月", "如月", "弥生", "卯月", "菊月", "望月") >= 2 || specs.Names.Contains("由良改二"));\r
+                case 904:\r
+                    return specs.Names.Count("綾波改二", "敷波改二") == 2;\r
+                case 905:\r
+                    return specs.Types.Count(type => type == 1) >= 3 && specs.Types.Length <= 5;\r
+                case 912:\r
+                    return specs.Flagship.Name.StartsWith("明石") && specs.Types.Count(type => type == 2) >= 3;\r
+                case 914:\r
+                    return specs.Types.Count(type => type == 5) >= 3 && specs.Types.Count(type => type == 2) >= 1;\r
+                case 928:\r
+                    return specs.Names.Count("羽黒", "足柄", "妙高", "高雄", "神風") >= 2;\r
+                case 318:\r
+                    return specs.Types.Count(type => type == 3) >= 2;\r
+                case 329:\r
+                    return specs.Types.Count(type => type == 2 || type == 1) >= 2;\r
+                case 330:\r
+                    return specs.Flagship.IsAircraftCarrier &&\r
+                           specs.Specs.Count(spec => spec.IsAircraftCarrier) >= 2 &&\r
+                           specs.Types.Count(type => type == 2) >= 2;\r
+                case 337:\r
+                    return specs.Names.Count("陽炎", "不知火", "霰", "霞") == 4;\r
+                case 339:\r
+                    return specs.Names.Count("磯波", "浦波", "綾波", "敷波") == 4;\r
+                case 342:\r
+                    var t12 = specs.Types.Count(type => type == 1 || type == 2);\r
+                    return t12 >= 4 || t12 >= 3 && specs.Types.Intersect(new[] {3, 4, 7, 21}).Any();\r
+                case 345:\r
+                    return specs.Names.Count("Warspite", "金剛", "Ark Royal", "Nelson", "Jervis", "Janus") >= 4;\r
+                case 346:\r
+                    return specs.Names.Count("夕雲改二", "巻雲改二", "風雲改二", "秋雲改二") == 4;\r
+                case 348:\r
+                    return new[] {3, 21}.Contains(specs.FlagshipType) &&\r
+                           specs.Types.Skip(1).Count(type => new[] {3, 4, 21}.Contains(type)) >= 2 &&\r
+                           specs.Types.Count(type => type == 2) >= 2;\r
+                default:\r
+                    return true;\r
             }\r
         }\r
 \r
@@ -467,33 +375,17 @@ namespace KancolleSniffer.Model
 \r
         public void InspectPracticeResult(dynamic json)\r
         {\r
-            foreach (var quest in _quests.Values)\r
+            foreach (var count in _quests.Values.Select(q => q.Count))\r
             {\r
-                var count = quest.Count;\r
+                if (!FleetCheck(count.Id))\r
+                    continue;\r
+                if (count.Id == 318 && _questFleet != 0)\r
+                    continue;\r
                 if (!(count.Spec is QuestPractice practice))\r
                     continue;\r
                 if (practice.Check(json.api_win_rank))\r
                     Increment(count);\r
             }\r
-            if (_quests.TryGetValue(318, out var q318))\r
-            {\r
-                if (_questFleet == 0 && QuestSortie.CompareRank(json.api_win_rank, "B") <= 0 &&\r
-                    _battleInfo.Result.Friend.Main.Count(s => s.Spec.ShipType == 3) >= 2)\r
-                {\r
-                    Increment(q318.Count);\r
-                }\r
-            }\r
-            if (_quests.TryGetValue(330, out var q330))\r
-            {\r
-                var fleet = _battleInfo.Result.Friend.Main;\r
-                if (QuestSortie.CompareRank(json.api_win_rank, "B") <= 0 &&\r
-                    fleet.Count(s => s.Spec.IsAircraftCarrier) >= 2 &&\r
-                    fleet.Count(s => s.Spec.ShipType == 2) >= 2 &&\r
-                    fleet[0].Spec.IsAircraftCarrier)\r
-                {\r
-                    Increment(q330.Count);\r
-                }\r
-            }\r
         }\r
 \r
         private readonly int[] _missionId = new int[ShipInfo.FleetCount];\r
@@ -511,48 +403,12 @@ namespace KancolleSniffer.Model
             if ((int)json.api_clear_result == 0)\r
                 return;\r
             var mid = _missionId[deck - 1];\r
-            foreach (var quest in _quests.Values)\r
+            foreach (var count in _quests.Values.Select(q => q.Count))\r
             {\r
-                var count = quest.Count;\r
                 if (!(count.Spec is QuestMission mission))\r
                     continue;\r
-                if (mission.Check(mid))\r
-                    Increment(count);\r
-            }\r
-            if (_quests.TryGetValue(426, out var q426))\r
-            {\r
-                var count = q426.Count;\r
-                switch (mid)\r
-                {\r
-                    case 3:\r
-                        IncrementNth(count, 0);\r
-                        break;\r
-                    case 4:\r
-                        IncrementNth(count, 1);\r
-                        break;\r
-                    case 5:\r
-                        IncrementNth(count, 2);\r
-                        break;\r
-                    case 10:\r
-                        IncrementNth(count, 3);\r
-                        break;\r
-                }\r
-            }\r
-            if (_quests.TryGetValue(428, out var q428))\r
-            {\r
-                var count = q428.Count;\r
-                switch (mid)\r
-                {\r
-                    case 4:\r
-                        IncrementNth(count, 0);\r
-                        break;\r
-                    case 101:\r
-                        IncrementNth(count, 1);\r
-                        break;\r
-                    case 102:\r
-                        IncrementNth(count, 2);\r
-                        break;\r
-                }\r
+                if (mission.Count(count, mid))\r
+                    NeedSave = true;\r
             }\r
         }\r
 \r
@@ -560,10 +416,12 @@ namespace KancolleSniffer.Model
 \r
         public void CountCharge() => Increment(504);\r
 \r
-        public void CountCreateItem()\r
+        public void InspectCreateItem(string request)\r
         {\r
-            Increment(605);\r
-            Increment(607);\r
+            var values = HttpUtility.ParseQueryString(request);\r
+            var count = values["api_multiple_flag"] == "1" ? 3 : 1;\r
+            Add(605, count);\r
+            Add(607, count);\r
         }\r
 \r
         public void CountCreateShip()\r
@@ -579,58 +437,91 @@ namespace KancolleSniffer.Model
 \r
         public void CountRemodelSlot() => Increment(619);\r
 \r
-        public void InspectDestroyItem(string request, dynamic json)\r
+        public void InspectDestroyItem(string request)\r
         {\r
             var values = HttpUtility.ParseQueryString(request);\r
             var items = values["api_slotitem_ids"].Split(',')\r
-                .Select(id => _itemInfo.GetStatus(int.Parse(id)).Spec).ToArray();\r
+                .Select(id => _itemInventory[int.Parse(id)].Spec).ToArray();\r
             Increment(613); // 613: 資源の再利用\r
             foreach (var quest in _quests.Values)\r
             {\r
                 var count = quest.Count;\r
-                if (!(count.Spec is QuestDestroyItem destroy))\r
+                if (count.Spec is QuestDestroyItem destroy)\r
+                {\r
+                    if (destroy.Count(count, items))\r
+                        NeedSave = true;\r
                     continue;\r
-                if (destroy.Count(count, items))\r
+                }\r
+                if (quest.Id == 680)\r
+                {\r
+                    count.NowArray[0] += items.Count(spec => spec.Type == 21);\r
+                    count.NowArray[1] += items.Count(spec => spec.Type == 12 || spec.Type == 13);\r
                     NeedSave = true;\r
-            }\r
-            if (_quests.TryGetValue(680, out var q680))\r
-            {\r
-                q680.Count.NowArray[0] += items.Count(spec => spec.Type == 21);\r
-                q680.Count.NowArray[1] += items.Count(spec => spec.Type == 12 || spec.Type == 13);\r
-                NeedSave = true;\r
+                }\r
             }\r
         }\r
 \r
-        public void InspectPowerUp(dynamic json)\r
+        public void InspectPowerUp(string request, dynamic json)\r
         {\r
             if ((int)json.api_powerup_flag == 0)\r
                 return;\r
+            var values = HttpUtility.ParseQueryString(request);\r
             foreach (var quest in _quests.Values)\r
             {\r
                 var count = quest.Count;\r
                 if (!(count.Spec is QuestPowerUp))\r
                     continue;\r
+                if (quest.Id == 714 || quest.Id == 715)\r
+                {\r
+                    if (ShipTypeById(values["api_id"]) != 2)\r
+                        return;\r
+                    var ships = values["api_id_items"].Split(',').Select(ShipTypeById).ToArray();\r
+                    var required = quest.Id == 714 ? 2 : quest.Id == 715 ? 3 : -1;\r
+                    if (ships.Count(type => type == required) < 3)\r
+                        return;\r
+                }\r
+                if (quest.Id == 716 || quest.Id == 717)\r
+                {\r
+                    if (!new[] {3, 4, 21}.Contains(ShipTypeById(values["api_id"])))\r
+                        return;\r
+                    var ships = values["api_id_items"].Split(',').Select(ShipTypeById).ToArray();\r
+                    if (quest.Id == 716)\r
+                    {\r
+                        if (ships.Count(type => new[] {3, 4, 21}.Contains(type)) < 3)\r
+                            return;\r
+                    }\r
+                    else\r
+                    {\r
+                        if (ships.Count(type => new[] {5, 6}.Contains(type)) < 3)\r
+                            return;\r
+                    }\r
+                }\r
                 Increment(count);\r
             }\r
         }\r
 \r
-        public void Increment(QuestCount count)\r
+        private int ShipTypeById(string id)\r
+        {\r
+            return _shipInventory[int.Parse(id)].Spec.ShipType;\r
+        }\r
+\r
+        private void Increment(QuestCount count)\r
         {\r
             Add(count, 1);\r
         }\r
 \r
-        public void Add(QuestCount count, int value)\r
+        private void Add(QuestCount count, int value)\r
         {\r
             count.Now += value;\r
             NeedSave = true;\r
         }\r
 \r
-        public void Increment(int id)\r
+        private void Increment(int id)\r
         {\r
             Add(id, 1);\r
         }\r
 \r
-        public void Add(int id, int value)\r
+        private void Add(int id, int value)\r
         {\r
             if (!_quests.TryGetValue(id, out var quest))\r
                 return;\r
@@ -638,7 +529,7 @@ namespace KancolleSniffer.Model
             NeedSave = true;\r
         }\r
 \r
-        public void IncrementNth(QuestCount count, int n)\r
+        private void IncrementNth(QuestCount count, int n)\r
         {\r
             count.NowArray[n]++;\r
             NeedSave = true;\r