OSDN Git Service

LogProcessorのリファクタリング
authorKazuhiro Fujieda <fujieda@users.osdn.me>
Mon, 17 Feb 2020 12:31:34 +0000 (21:31 +0900)
committerKazuhiro Fujieda <fujieda@users.osdn.me>
Fri, 21 Feb 2020 10:35:48 +0000 (19:35 +0900)
KancolleSniffer.Test/LogProcessorTest.cs
KancolleSniffer/Log/BattleLogProcessor.cs
KancolleSniffer/Log/LogProcessor.cs

index 1adec3a..b8c7c8c 100644 (file)
@@ -173,5 +173,26 @@ namespace KancolleSniffer.Test
             var excel = "2018/9/10 20:13";\r
             PAssert.That(() => "[\"2018-09-10 20:13:00\"" + expected == dateProcessor(excel), "Excelの形式から変換する");\r
         }\r
+\r
+        /// <summary>\r
+        /// 壊れたログを取り除く\r
+        /// </summary>\r
+        [TestMethod]\r
+        public void TruncatedLog()\r
+        {\r
+            var processor = new LogProcessor();\r
+            var logs = new[]\r
+            {\r
+                "2014-12-15 23:10:34,29734,29855,28016,41440,1407,1529,2151,13",\r
+                "2014-12-15 23:13:29,29709,29819,28019,41440,1407,1529,21",\r
+                "2014-12-15 23:16:06,29710,29819,28018,41440,1407,1529,2151,13"\r
+            };\r
+            var result = processor.Process(logs, "資材ログ", DateTime.MinValue, DateTime.MaxValue, true);\r
+            PAssert.That(() => result.SequenceEqual(new[]\r
+            {\r
+                "[1418652634000,29734,29855,28016,41440,1407,1529,2151,13]",\r
+                ",\n[1418652966000,29710,29819,28018,41440,1407,1529,2151,13]"\r
+            }));\r
+        }\r
     }\r
 }
\ No newline at end of file
index e6fcf08..8a8ad06 100644 (file)
@@ -20,7 +20,7 @@ using KancolleSniffer.Model;
 \r
 namespace KancolleSniffer.Log\r
 {\r
-    public class BattleLogProcessor\r
+    public class BattleLogProcessor : LogProcessor.Processor\r
     {\r
         private readonly Dictionary<string, string> _mapDictionary;\r
 \r
@@ -29,7 +29,7 @@ namespace KancolleSniffer.Log
             _mapDictionary = mapDictionary ?? new Dictionary<string, string>();\r
         }\r
 \r
-        public string[] Process(string[] data)\r
+        public override string[] Process(string[] data)\r
         {\r
             string map;\r
             switch (data.Length)\r
@@ -49,8 +49,10 @@ namespace KancolleSniffer.Log
                     Array.Copy(data, 24, data, 23, 15);\r
                     goto case 38;\r
                 default:\r
-                    return data;\r
+                    Skip = true;\r
+                    return null;\r
             }\r
+            Skip = false;\r
             if (data[5] == "T字戦(有利)")\r
                 data[5] = "T字有利";\r
             if (data[5] == "T字戦(不利)")\r
index e4474a6..64d7208 100644 (file)
@@ -32,40 +32,55 @@ namespace KancolleSniffer.Log
             _battleLogProcessor = new BattleLogProcessor(mapDictionary);\r
         }\r
 \r
-        public IEnumerable<string> Process(IEnumerable<string> lines, string path, DateTime from, DateTime to,\r
-            bool number, DateTime now = default)\r
+        public class Processor\r
         {\r
-            var fields = 0;\r
-            var mission = false;\r
-            var battle = false;\r
-            var material = false;\r
-            switch (Path.GetFileNameWithoutExtension(path))\r
+            protected virtual int Fields { get; }\r
+            public bool Skip { get; protected set; }\r
+\r
+            public Processor()\r
             {\r
-                case "遠征報告書":\r
-                    mission = true;\r
-                    fields = 11;\r
-                    break;\r
-                case "改修報告書":\r
-                    fields = 15;\r
-                    break;\r
-                case "海戦・ドロップ報告書":\r
-                    fields = 40;\r
-                    battle = true;\r
-                    break;\r
-                case "開発報告書":\r
-                    fields = 9;\r
-                    break;\r
-                case "建造報告書":\r
-                    fields = 12;\r
-                    break;\r
-                case "資材ログ":\r
-                    fields = 9;\r
-                    material = true;\r
-                    break;\r
-                case "戦果":\r
-                    fields = 3;\r
-                    break;\r
             }\r
+\r
+            public Processor(int fields)\r
+            {\r
+                Fields = fields;\r
+            }\r
+\r
+            public virtual string[] Process(string[] data)\r
+            {\r
+                Skip = data.Length != Fields;\r
+                return Skip ? null : data;\r
+            }\r
+        }\r
+\r
+        private class MissionProcessor : Processor\r
+        {\r
+            protected override int Fields { get; } = 11;\r
+\r
+            public override string[] Process(string[] data)\r
+            {\r
+                return data.Concat(new[] {"0"}).Take(Fields).ToArray();\r
+            }\r
+        }\r
+\r
+        private class MaterialProcessor : Processor\r
+        {\r
+            protected override int Fields { get; } = 9;\r
+\r
+            public override string[] Process(string[] data)\r
+            {\r
+                if (data.Length >= Fields)\r
+                    Array.Resize(ref data, Fields);\r
+                return base.Process(data);\r
+            }\r
+        }\r
+\r
+        public IEnumerable<string> Process(IEnumerable<string> lines, string path, DateTime from, DateTime to,\r
+            bool number, DateTime now = default)\r
+        {\r
+            var logName = Path.GetFileNameWithoutExtension(path);\r
+            var currentMaterial = logName == "資材ログ" && !number;\r
+            var processor = DecideProcessor(logName);\r
             var delimiter = "";\r
             foreach (var line in lines)\r
             {\r
@@ -78,14 +93,8 @@ namespace KancolleSniffer.Log
                 if (date < from)\r
                     continue;\r
                 data[0] = Logger.FormatDateTime(date);\r
-                var entries = data;\r
-                if (mission)\r
-                    entries = data.Concat(new[] {"0"}).Take(fields).ToArray();\r
-                if (material)\r
-                    entries = data.Take(fields).ToArray();\r
-                if (battle)\r
-                    entries = _battleLogProcessor.Process(data);\r
-                if (entries.Length != fields)\r
+                var entries = processor.Process(data);\r
+                if (processor.Skip)\r
                     continue;\r
                 var result =\r
                     number\r
@@ -94,11 +103,34 @@ namespace KancolleSniffer.Log
                 delimiter = ",\n";\r
                 yield return result;\r
             }\r
-            if (material && !number) // 資材の現在値を出力する\r
+            if (currentMaterial) // 資材の現在値を出力する\r
                 yield return delimiter + "[\"" + Logger.FormatDateTime(now) + "\",\"" +\r
                              string.Join("\",\"", _materialCount.Select(c => c.Now)) + "\"]";\r
         }\r
 \r
+        private Processor DecideProcessor(string logName)\r
+        {\r
+            switch (logName)\r
+            {\r
+                case "遠征報告書":\r
+                    return new MissionProcessor();\r
+                case "改修報告書":\r
+                    return new Processor(15);\r
+                case "海戦・ドロップ報告書":\r
+                    return _battleLogProcessor;\r
+                case "開発報告書":\r
+                    return new Processor(9);\r
+                case "建造報告書":\r
+                    return new Processor(12);\r
+                case "資材ログ":\r
+                    return new MaterialProcessor();\r
+                case "戦果":\r
+                    return new Processor(3);\r
+                default:\r
+                    return new Processor();\r
+            }\r
+        }\r
+\r
         private DateTime ParseDateTime(string dateTime)\r
         {\r
             if (DateTime.TryParseExact(dateTime, Logger.DateTimeFormat, CultureInfo.InvariantCulture,\r