OSDN Git Service

ドロップした艦娘と装備を出撃中にカウントする
authorKazuhiro Fujieda <fujieda@users.osdn.me>
Sun, 22 Jul 2018 09:26:33 +0000 (18:26 +0900)
committerKazuhiro Fujieda <fujieda@users.osdn.me>
Sun, 22 Jul 2018 09:34:48 +0000 (18:34 +0900)
Data/NumEquips.csv [new file with mode: 0644]
KancolleSniffer.Test/LoggerTest.cs
KancolleSniffer.Test/SnifferTest.cs
KancolleSniffer.Test/logs
KancolleSniffer/AdditionalData.cs
KancolleSniffer/BattleInfo.cs
KancolleSniffer/ItemInfo.cs
KancolleSniffer/ShipInfo.cs
KancolleSniffer/ShipMaster.cs
KancolleSniffer/Sniffer.cs

diff --git a/Data/NumEquips.csv b/Data/NumEquips.csv
new file mode 100644 (file)
index 0000000..c828684
--- /dev/null
@@ -0,0 +1,214 @@
+1,\96r\8c\8e,2\r
+2,\94@\8c\8e,1\r
+6,\92·\8c\8e,1\r
+7,\8eO\93ú\8c\8e,1\r
+9,\90\81\90á,2\r
+10,\94\92\90á,1\r
+11,\90[\90á,1\r
+12,\88é\94g,1\r
+13,\88»\94g,2\r
+14,\95~\94g,1\r
+15,\8f\8c,1\r
+16,\92ª,1\r
+17,\97z\89\8a,2\r
+18,\95s\92m\89Î,1\r
+19,\8d\95\92ª,1\r
+20,\90á\95\97,2\r
+21,\92·\97Ç,2\r
+22,\8cÜ\8f\\97é,1\r
+23,\97R\97Ç,1\r
+24,\91å\88ä,2\r
+25,\96k\8fã,2\r
+26,\95}\8cK,3\r
+27,\8eR\8fé,3\r
+28,\8eH\8c\8e,1\r
+29,\95\8c\8e,1\r
+30,\8be\8c\8e,1\r
+31,\96]\8c\8e,1\r
+32,\8f\89\90á,1\r
+33,\91p\89_,1\r
+34,\8bÅ,2\r
+35,\8b¿,1\r
+36,\97\8b,1\r
+37,\93d,1\r
+38,\8f\89\8ft,2\r
+39,\8eq\93ú,1\r
+40,\8eá\97t,1\r
+41,\8f\89\91\9a,1\r
+42,\94\92\98I,2\r
+43,\8e\9e\89J,1\r
+44,\91º\89J,1\r
+45,\97[\97§,1\r
+46,\8cÜ\8c\8e\89J,1\r
+47,\97Á\95\97,2\r
+48,èÅ,1\r
+49,\89à,1\r
+50,\93\87\95\97,2\r
+51,\93V\97´,2\r
+52,\97´\93c,2\r
+53,\96¼\8eæ,1\r
+54,\90ì\93à,2\r
+55,\90_\92Ê,1\r
+56,\93ß\89Ï,1\r
+59,\8cÃ\91é,2\r
+60,\89Á\8cÃ,1\r
+61,\90Â\97t,2\r
+62,\96­\8d\82,2\r
+63,\93ß\92q,1\r
+64,\91«\95¿,1\r
+65,\89H\8d\95,1\r
+66,\8d\82\97Y,2\r
+67,\88¤\93\86,2\r
+68,\96\80\96ë,1\r
+69,\92¹\8aC,1\r
+70,\8dÅ\8fã,2\r
+71,\97\98\8dª,2\r
+72,\92}\96\80,2\r
+74,\8fË\96P,2\r
+75,\94ò\91é,3\r
+76,\97´é\88,2\r
+77,\88É\90¨,3\r
+78,\8bà\8d\84,3\r
+79,\90Y\96¼,3\r
+80,\92·\96å,3\r
+81,\97¤\89\9c,3\r
+83,\90Ô\8fé,3\r
+84,\89Á\89ê,3\r
+85,\96\93\87,3\r
+86,\94ä\89b,3\r
+87,\93ú\8cü,3\r
+89,\96PãÄ,1\r
+90,\91\93\97´,3\r
+91,\94ò\97´,3\r
+92,\94¹\91é,3\r
+93,\9eO,1\r
+94,\97ø,1\r
+95,\92©\92ª,2\r
+96,\91å\92ª,1\r
+97,\96\9e\92ª,1\r
+98,\8dr\92ª,1\r
+99,\8b\85\96\81,2\r
+100,\91½\96\80,1\r
+101,\96Ø\91\,1\r
+102,\90ç\8dÎ,2\r
+103,\90ç\91ã\93c,2\r
+110,ãÄ\92ß,3\r
+111,\90\90\92ß,3\r
+113,\8bS\93{,1\r
+114,\88¢\95\90\8cG,1\r
+115,\97[\92£,2\r
+116,\90\90\96P,2\r
+120,\8eO\8cG,2\r
+122,\95\91\95\97,2\r
+123,\88ß\8a},2\r
+124,\97é\92J,2\r
+125,\8cF\96ì,2\r
+126,\88É168,0\r
+127,\88É58,0\r
+128,\88É8,0\r
+131,\91å\98a,3\r
+132,\8fH\89_,2\r
+133,\97[\89_,2\r
+134,\8aª\89_,2\r
+135,\92·\94g,2\r
+137,\88¢\89ê\96ì,2\r
+138,\94\\91ã,2\r
+139,\96î\94\8a,2\r
+140,\8eð\93õ,2\r
+143,\95\90\91 ,3\r
+153,\91å\96P,3\r
+154,\8d\81\8eæ,3\r
+155,\88É401,0\r
+161,\82 \82«\82Â\8aÛ,2\r
+162,\90_\88Ð,0\r
+163,\82Ü\82é\82ä,0\r
+164,\96í\90¶,1\r
+165,\89K\8c\8e,1\r
+167,\88é\95\97,2\r
+168,\89Y\95\97,2\r
+169,\92J\95\97,2\r
+170,\95l\95\97,2\r
+171,Bismarck,2\r
+174,Z1,1\r
+175,Z3,1\r
+176,Prinz Eugen,2\r
+181,\93V\92Ã\95\97,3\r
+182,\96¾\90Î,2\r
+183,\91å\97\84,3\r
+184,\91å\8c~,2\r
+186,\8e\9e\92Ã\95\97,2\r
+190,\8f\89\95\97,2\r
+191,\88É19,0\r
+331,\93V\8fé,2\r
+332,\8a\8b\8fé,2\r
+404,\89_\97´,2\r
+405,\8ft\89J,2\r
+409,\91\81\91\9a,2\r
+410,\90´\91\9a,2\r
+413,\92©\89_,2\r
+414,\8eR\89_,2\r
+415,\96ì\95ª,2\r
+421,\8fH\8c\8e,3\r
+422,\8fÆ\8c\8e,3\r
+423,\8f\89\8c\8e,3\r
+424,\8d\82\94g,2\r
+425,\92©\91\9a,2\r
+431,U-511,1\r
+432,Graf Zeppelin,2\r
+433,Saratoga,2\r
+439,Warspite,1\r
+440,Iowa,2\r
+441,Littorio,3\r
+442,Roma,3\r
+443,Libeccio,1\r
+444,Aquila,1\r
+445,\8fH\92Ã\8fF,2\r
+448,Zara,1\r
+449,Pola,1\r
+451,\90\90\95ä,2\r
+452,\89«\94g,2\r
+453,\95\97\89_,2\r
+454,\97\92,2\r
+455,\94\8b\95\97,2\r
+456,\90e\92ª,2\r
+457,\8eR\95\97,1\r
+458,\8aC\95\97,1\r
+459,\8d]\95\97,1\r
+460,\91¬\8bz,2\r
+465,\8e­\93\87,3\r
+471,\90_\95\97,2\r
+472,\92©\95\97,2\r
+473,\8ft\95\97,2\r
+474,\8f¼\95\97,2\r
+475,\8aø\95\97,2\r
+479,\93V\96¶,1\r
+480,\8b·\96¶,1\r
+481,\90\85\96³\8c\8e,1\r
+483,\88É26,0\r
+484,\95l\94g,2\r
+485,\93¡\94g,2\r
+486,\89Y\94g,2\r
+491,Commandant Teste,1\r
+492,Richelieu,2\r
+493,\88É400,0\r
+494,\88É13,0\r
+495,\88É14,0\r
+511,\84C\84p\84~\84s\84\85\84\84,2\r
+515,Ark Royal,2\r
+516,\84S\84p\84\8a\84{\84u\84~\84\84,3\r
+517,\90è\8eç,2\r
+518,\8d\91\8cã,2\r
+519,Jervis,1\r
+521,\8ft\93ú\8aÛ,1\r
+524,\91ð\91¨,2\r
+525,\8f¼\97Ö,2\r
+531,\8d²\93n,2\r
+532,\97Á\8c\8e,3\r
+535,Luigi Torelli,0\r
+540,\91Î\94n,2\r
+544,Gambier Bay,1\r
+549,Intrepid,1\r
+551,\93ú\90U,2\r
+552,\91å\93\8c,2\r
+561,Samuel B.Roberts,1\r
+565,\95\9f\8d],2\r
index 3dd6f2f..6f3c292 100644 (file)
@@ -21,6 +21,8 @@ using Moq;
 \r
 namespace KancolleSniffer.Test\r
 {\r
+    using Sniffer = SnifferTest.TestingSniffer;\r
+\r
     [TestClass]\r
     public class LoggerTest\r
     {\r
index c202117..76d8010 100644 (file)
@@ -22,6 +22,8 @@ using Microsoft.VisualStudio.TestTools.UnitTesting;
 \r
 namespace KancolleSniffer.Test\r
 {\r
+    using Sniffer = SnifferTest.TestingSniffer;\r
+\r
     [TestClass]\r
     public class SnifferTest\r
     {\r
@@ -32,6 +34,14 @@ namespace KancolleSniffer.Test
                 .GlobalAssertionConfiguration.WithPrintedListLengthLimit(200).WithMaximumValueLength(1000);\r
         }\r
 \r
+        public class TestingSniffer : KancolleSniffer.Sniffer\r
+        {\r
+            public TestingSniffer(bool start = false) : base(start)\r
+            {\r
+                AdditionalData.UseNumEquipsFile = false;\r
+            }\r
+        }\r
+\r
         public static StreamReader OpenLogFile(string name)\r
         {\r
             var dir = Path.GetDirectoryName(Path.GetDirectoryName(Environment.CurrentDirectory));\r
@@ -846,5 +856,30 @@ namespace KancolleSniffer.Test
             PAssert.That(() =>\r
                 sniffer.MiscText == "[獲得アイテム]\r\n弾薬: 150\r\n開発資材: 1", "途中でリロードして再出撃");\r
         }\r
+\r
+        /// <summary>\r
+        /// 新規のドロップ艦の初期装備数を登録する\r
+        /// </summary>\r
+        [TestMethod]\r
+        public void RecordNumEqipsOfNewDropShip()\r
+        {\r
+            var sniffer = new Sniffer();\r
+            SniffLogFile(sniffer, "dropship_001");\r
+            PAssert.That(() => sniffer.AdditionalData.NumEquips(565) == 2);\r
+            PAssert.That(() => sniffer.ShipList.First(s => s.Spec.Id == 565).Spec.NumEquips == 2);\r
+        }\r
+\r
+        /// <summary>\r
+        /// 既知のドロップ艦とその装備をカウントする\r
+        /// </summary>\r
+        [TestMethod]\r
+        public void CountDropShip()\r
+        {\r
+            var sniffer = new Sniffer();\r
+            sniffer.AdditionalData.RecordNumEquips(11, "", 1);\r
+            SniffLogFile(sniffer, "dropship_002");\r
+            PAssert.That(() => sniffer.Item.NowShips == 250);\r
+            PAssert.That(() => sniffer.Item.NowEquips == 1159);\r
+        }\r
     }\r
 }
\ No newline at end of file
index f536d67..dcb6cd9 160000 (submodule)
@@ -1 +1 @@
-Subproject commit f536d67271f300eb34b6e2bcc1f077ae19d08d8b
+Subproject commit dcb6cd982f57c262ff5280f13873595f3cc4864e
index 425ee4b..39ca448 100644 (file)
@@ -67,5 +67,35 @@ namespace KancolleSniffer
 \r
         public double ItemTp(int id) =>\r
             _tpSpec != null ? _tpSpec.TryGetValue(id, out var tp) ? tp : -1 : -1;\r
+\r
+        private static readonly string NumEquipsFile = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "NumEquips.csv");\r
+\r
+        private Dictionary<int, int> _numEquips = new Dictionary<int, int>();\r
+\r
+        public bool UseNumEquipsFile { get; set; } = true;\r
+\r
+        public void LoadNumEquips()\r
+        {\r
+            try\r
+            {\r
+                if (!UseNumEquipsFile)\r
+                    return;\r
+                _numEquips = File.ReadLines(NumEquipsFile)\r
+                    .Select(line => line.Split(','))\r
+                    .ToDictionary(f => int.Parse(f[0]), f => int.Parse(f[2]));\r
+            }\r
+            catch (IOException)\r
+            {\r
+            }\r
+        }\r
+\r
+        public int NumEquips(int id) => _numEquips.TryGetValue(id, out var num) ? num : -1;\r
+\r
+        public void RecordNumEquips(int id, string name, int numEquips)\r
+        {\r
+            _numEquips[id] = numEquips;\r
+            if (UseNumEquipsFile)\r
+                File.AppendAllText(NumEquipsFile, $"{id},{name},{numEquips}\r\n");\r
+        }\r
     }\r
 }
\ No newline at end of file
index 710911e..3b2e767 100644 (file)
@@ -478,6 +478,7 @@ namespace KancolleSniffer
             BattleState = BattleState.Result;\r
             ShowResult(!_lastCell);\r
             _shipInfo.SaveBattleResult();\r
+            _shipInfo.DropShipId = json.api_get_ship() ? (int)json.api_get_ship.api_ship_id : -1;\r
             VerifyResultRank(json);\r
             CleanupResult();\r
             SetEscapeShips(json);\r
index 4824d1c..d14c67f 100644 (file)
@@ -159,13 +159,13 @@ namespace KancolleSniffer
             }\r
         }\r
 \r
-        public Func<int, double?> GetItemTp { private get; set; }\r
+        public Func<double> GetItemTp { get; set; }\r
 \r
         public double TransportPoint\r
         {\r
             get\r
             {\r
-                var tp = GetItemTp?.Invoke(Id);\r
+                var tp = GetItemTp?.Invoke();\r
                 if (tp >= 0)\r
                     return (double)tp;\r
                 switch (Id)\r
@@ -632,7 +632,7 @@ namespace KancolleSniffer
         public int NowEquips\r
         {\r
             get => _nowEquips;\r
-            private set\r
+            set\r
             {\r
                 if (MaxEquips != 0)\r
                 {\r
@@ -667,13 +667,14 @@ namespace KancolleSniffer
             var dict = new Dictionary<int, string>();\r
             foreach (var entry in json.api_mst_slotitem_equiptype)\r
                 dict[(int)entry.api_id] = entry.api_name;\r
-            AdditionalData?.LoadTpSpec();\r
+            AdditionalData.LoadTpSpec();\r
             foreach (var entry in json.api_mst_slotitem)\r
             {\r
                 var type = (int)entry.api_type[2];\r
+                var id = (int)entry.api_id;\r
                 _itemSpecs[(int)entry.api_id] = new ItemSpec\r
                 {\r
-                    Id = (int)entry.api_id,\r
+                    Id = id,\r
                     Name = (string)entry.api_name,\r
                     Type = type,\r
                     TypeName = dict.TryGetValue(type, out var typeName) ? typeName : "不明",\r
@@ -687,7 +688,7 @@ namespace KancolleSniffer
                     Interception = type == 48 ? (int)entry.api_houk : 0, // 局地戦闘機は回避の値が迎撃\r
                     AntiBomber = type == 48 ? (int)entry.api_houm : 0, // 〃命中の値が対爆\r
                     Distance = entry.api_distance() ? (int)entry.api_distance : 0,\r
-                    GetItemTp = id => AdditionalData?.ItemTp(id)\r
+                    GetItemTp = () => AdditionalData.ItemTp(id)\r
                 };\r
             }\r
             _itemSpecs[-1] = _itemSpecs[0] = new ItemSpec();\r
index df6267b..a5c87e4 100644 (file)
@@ -31,10 +31,25 @@ namespace KancolleSniffer
         private readonly ItemInfo _itemInfo;\r
         private readonly List<int> _escapedShips = new List<int>();\r
         private ShipStatus[] _battleResult = new ShipStatus[0];\r
+        private readonly NumEquipsChecker _numEquipsChecker = new NumEquipsChecker();\r
         public int HqLevel { get; private set; }\r
         public ShipStatusPair[] BattleResultDiff { get; private set; } = new ShipStatusPair[0];\r
         public bool IsBattleResultError => BattleResultDiff.Length > 0;\r
         public ShipStatus[] BattleStartStatus { get; private set; } = new ShipStatus[0];\r
+        public int DropShipId { private get; set; } = -1;\r
+\r
+        private class NumEquipsChecker\r
+        {\r
+            public int MaxId { private get; set; } = int.MaxValue;\r
+\r
+            public void Check(ShipStatus ship)\r
+            {\r
+                var spec = ship.Spec;\r
+                if (spec.NumEquips != -1 || ship.Id <= MaxId)\r
+                    return;\r
+                spec.NumEquips = ship.Slot.Count(item => item.Id != -1);\r
+            }\r
+        }\r
 \r
         public class ShipStatusPair\r
         {\r
@@ -59,6 +74,7 @@ namespace KancolleSniffer
         public void InspectMaster(dynamic json)\r
         {\r
             _shipMaster.Inspect(json);\r
+            ClearShipInfo();\r
         }\r
 \r
         public void InspectShip(dynamic json)\r
@@ -78,21 +94,28 @@ namespace KancolleSniffer
             }\r
             else if (json.api_data()) // ship2\r
             {\r
-                // 一隻分のデータしか来ないことがあるので艦娘数を数えない\r
                 InspectDeck(json.api_data_deck);\r
                 InspectShipData(json.api_data);\r
             }\r
             else if (json.api_ship_data()) // ship3とship_deck\r
             {\r
-                // 一隻分のデータしか来ないことがあるので艦娘数を数えない\r
                 InspectDeck(json.api_deck_data);\r
                 InspectShipData(json.api_ship_data);\r
                 VerifyBattleResult();\r
+                // ship_deckでドロップ艦を反映する\r
+                if (DropShipId != -1)\r
+                {\r
+                    _itemInfo.NowShips++;\r
+                    var num = _shipMaster.GetSpec(DropShipId).NumEquips;\r
+                    if (num > 0)\r
+                        _itemInfo.NowEquips += num;\r
+                }\r
             }\r
             else if (json.api_ship()) // getshipとpowerup\r
             {\r
                 InspectShipData(new[] {json.api_ship});\r
             }\r
+            DropShipId = -1;\r
         }\r
 \r
         public void SaveBattleResult()\r
@@ -138,9 +161,10 @@ namespace KancolleSniffer
         {\r
             foreach (var entry in json)\r
             {\r
-                _shipInfo[(int)entry.api_id] = new ShipStatus\r
+                var id = (int)entry.api_id;\r
+                var ship = new ShipStatus\r
                 {\r
-                    Id = (int)entry.api_id,\r
+                    Id = id,\r
                     Spec = _shipMaster.GetSpec((int)entry.api_ship_id),\r
                     Level = (int)entry.api_lv,\r
                     ExpToNext = (int)entry.api_exp[1],\r
@@ -150,7 +174,7 @@ namespace KancolleSniffer
                     Fuel = (int)entry.api_fuel,\r
                     Bull = (int)entry.api_bull,\r
                     OnSlot = (int[])entry.api_onslot,\r
-                    Slot = ((int[])entry.api_slot).Select(id => new ItemStatus(id)).ToArray(),\r
+                    Slot = ((int[])entry.api_slot).Select(item => new ItemStatus(item)).ToArray(),\r
                     SlotEx = entry.api_slot_ex() ? new ItemStatus((int)entry.api_slot_ex) : new ItemStatus(0),\r
                     NdockTime = (int)entry.api_ndock_time,\r
                     NdockItem = (int[])entry.api_ndock_item,\r
@@ -162,7 +186,10 @@ namespace KancolleSniffer
                     Lucky = (int)entry.api_lucky[0],\r
                     Locked = entry.api_locked() && entry.api_locked == 1\r
                 };\r
+                _shipInfo[id] = ship;\r
+                _numEquipsChecker.Check(ship);\r
             }\r
+            _numEquipsChecker.MaxId = _shipInfo.Keys.Max();\r
         }\r
 \r
         private void InspectBasic(dynamic json)\r
index 40a32bb..c9a4d93 100644 (file)
@@ -31,7 +31,8 @@ namespace KancolleSniffer
             foreach (var entry in json.api_mst_stype)\r
                 dict[entry.api_id] = entry.api_name;\r
             dict[8] = "巡洋戦艦";\r
-            AdditionalData?.LoadEnemySlot();\r
+            AdditionalData.LoadEnemySlot();\r
+            AdditionalData.LoadNumEquips();\r
             foreach (var entry in json.api_mst_ship)\r
             {\r
                 var shipSpec = _shipSpecs[(int)entry.api_id] = new ShipSpec\r
@@ -53,7 +54,9 @@ namespace KancolleSniffer
                 }\r
                 shipSpec.GetMaxEq = entry.api_maxeq()\r
                     ? (Func<int[]>)(() => entry.api_maxeq)\r
-                    : () => AdditionalData?.EnemySlot(shipSpec.Id);\r
+                    : () => AdditionalData.EnemySlot(shipSpec.Id);\r
+                shipSpec.GetNumEquips = () => AdditionalData.NumEquips(shipSpec.Id);\r
+                shipSpec.SetNumEquips = num => AdditionalData.RecordNumEquips(shipSpec.Id, shipSpec.Name,num);\r
             }\r
             _shipSpecs[-1] = new ShipSpec();\r
             SetRemodelBaseAndStep();\r
@@ -117,6 +120,15 @@ namespace KancolleSniffer
         public int SlotNum { get; set; }\r
         public Func<int[]> GetMaxEq { get; set; }\r
         public int[] MaxEq => GetMaxEq?.Invoke();\r
+        public Func<int> GetNumEquips { get; set; }\r
+        public Action<int> SetNumEquips { get; set; }\r
+\r
+        public int NumEquips\r
+        {\r
+            get => GetNumEquips();\r
+            set => SetNumEquips(value);\r
+        }\r
+\r
         public int ShipType { get; set; }\r
         public int ShipClass { get; set; }\r
         public string ShipTypeName { get; set; }\r
index 97a273c..e4dad0c 100644 (file)
@@ -250,7 +250,7 @@ namespace KancolleSniffer
                 _shipInfo.InspectShip(data);\r
                 _akashiTimer.CheckFleet();\r
                 _battleInfo.BattleState = BattleState.None;\r
-                return Update.Ship | Update.Battle;\r
+                return Update.Ship | Update.Battle | Update.Item;\r
             }\r
             if (url.EndsWith("api_get_member/ship3"))\r
             {\r