Revisión | e252d359b55626b89ff0329ad6734415b6bf6cd8 (tree) |
---|---|
Tiempo | 2020-02-21 19:35:48 |
Autor | Kazuhiro Fujieda <fujieda@user...> |
Commiter | Kazuhiro Fujieda |
LogProcessorのリファクタリング
@@ -173,5 +173,26 @@ namespace KancolleSniffer.Test | ||
173 | 173 | var excel = "2018/9/10 20:13"; |
174 | 174 | PAssert.That(() => "[\"2018-09-10 20:13:00\"" + expected == dateProcessor(excel), "Excelの形式から変換する"); |
175 | 175 | } |
176 | + | |
177 | + /// <summary> | |
178 | + /// 壊れたログを取り除く | |
179 | + /// </summary> | |
180 | + [TestMethod] | |
181 | + public void TruncatedLog() | |
182 | + { | |
183 | + var processor = new LogProcessor(); | |
184 | + var logs = new[] | |
185 | + { | |
186 | + "2014-12-15 23:10:34,29734,29855,28016,41440,1407,1529,2151,13", | |
187 | + "2014-12-15 23:13:29,29709,29819,28019,41440,1407,1529,21", | |
188 | + "2014-12-15 23:16:06,29710,29819,28018,41440,1407,1529,2151,13" | |
189 | + }; | |
190 | + var result = processor.Process(logs, "資材ログ", DateTime.MinValue, DateTime.MaxValue, true); | |
191 | + PAssert.That(() => result.SequenceEqual(new[] | |
192 | + { | |
193 | + "[1418652634000,29734,29855,28016,41440,1407,1529,2151,13]", | |
194 | + ",\n[1418652966000,29710,29819,28018,41440,1407,1529,2151,13]" | |
195 | + })); | |
196 | + } | |
176 | 197 | } |
177 | 198 | } |
\ No newline at end of file |
@@ -20,7 +20,7 @@ using KancolleSniffer.Model; | ||
20 | 20 | |
21 | 21 | namespace KancolleSniffer.Log |
22 | 22 | { |
23 | - public class BattleLogProcessor | |
23 | + public class BattleLogProcessor : LogProcessor.Processor | |
24 | 24 | { |
25 | 25 | private readonly Dictionary<string, string> _mapDictionary; |
26 | 26 |
@@ -29,7 +29,7 @@ namespace KancolleSniffer.Log | ||
29 | 29 | _mapDictionary = mapDictionary ?? new Dictionary<string, string>(); |
30 | 30 | } |
31 | 31 | |
32 | - public string[] Process(string[] data) | |
32 | + public override string[] Process(string[] data) | |
33 | 33 | { |
34 | 34 | string map; |
35 | 35 | switch (data.Length) |
@@ -49,8 +49,10 @@ namespace KancolleSniffer.Log | ||
49 | 49 | Array.Copy(data, 24, data, 23, 15); |
50 | 50 | goto case 38; |
51 | 51 | default: |
52 | - return data; | |
52 | + Skip = true; | |
53 | + return null; | |
53 | 54 | } |
55 | + Skip = false; | |
54 | 56 | if (data[5] == "T字戦(有利)") |
55 | 57 | data[5] = "T字有利"; |
56 | 58 | if (data[5] == "T字戦(不利)") |
@@ -32,40 +32,55 @@ namespace KancolleSniffer.Log | ||
32 | 32 | _battleLogProcessor = new BattleLogProcessor(mapDictionary); |
33 | 33 | } |
34 | 34 | |
35 | - public IEnumerable<string> Process(IEnumerable<string> lines, string path, DateTime from, DateTime to, | |
36 | - bool number, DateTime now = default) | |
35 | + public class Processor | |
37 | 36 | { |
38 | - var fields = 0; | |
39 | - var mission = false; | |
40 | - var battle = false; | |
41 | - var material = false; | |
42 | - switch (Path.GetFileNameWithoutExtension(path)) | |
37 | + protected virtual int Fields { get; } | |
38 | + public bool Skip { get; protected set; } | |
39 | + | |
40 | + public Processor() | |
43 | 41 | { |
44 | - case "遠征報告書": | |
45 | - mission = true; | |
46 | - fields = 11; | |
47 | - break; | |
48 | - case "改修報告書": | |
49 | - fields = 15; | |
50 | - break; | |
51 | - case "海戦・ドロップ報告書": | |
52 | - fields = 40; | |
53 | - battle = true; | |
54 | - break; | |
55 | - case "開発報告書": | |
56 | - fields = 9; | |
57 | - break; | |
58 | - case "建造報告書": | |
59 | - fields = 12; | |
60 | - break; | |
61 | - case "資材ログ": | |
62 | - fields = 9; | |
63 | - material = true; | |
64 | - break; | |
65 | - case "戦果": | |
66 | - fields = 3; | |
67 | - break; | |
68 | 42 | } |
43 | + | |
44 | + public Processor(int fields) | |
45 | + { | |
46 | + Fields = fields; | |
47 | + } | |
48 | + | |
49 | + public virtual string[] Process(string[] data) | |
50 | + { | |
51 | + Skip = data.Length != Fields; | |
52 | + return Skip ? null : data; | |
53 | + } | |
54 | + } | |
55 | + | |
56 | + private class MissionProcessor : Processor | |
57 | + { | |
58 | + protected override int Fields { get; } = 11; | |
59 | + | |
60 | + public override string[] Process(string[] data) | |
61 | + { | |
62 | + return data.Concat(new[] {"0"}).Take(Fields).ToArray(); | |
63 | + } | |
64 | + } | |
65 | + | |
66 | + private class MaterialProcessor : Processor | |
67 | + { | |
68 | + protected override int Fields { get; } = 9; | |
69 | + | |
70 | + public override string[] Process(string[] data) | |
71 | + { | |
72 | + if (data.Length >= Fields) | |
73 | + Array.Resize(ref data, Fields); | |
74 | + return base.Process(data); | |
75 | + } | |
76 | + } | |
77 | + | |
78 | + public IEnumerable<string> Process(IEnumerable<string> lines, string path, DateTime from, DateTime to, | |
79 | + bool number, DateTime now = default) | |
80 | + { | |
81 | + var logName = Path.GetFileNameWithoutExtension(path); | |
82 | + var currentMaterial = logName == "資材ログ" && !number; | |
83 | + var processor = DecideProcessor(logName); | |
69 | 84 | var delimiter = ""; |
70 | 85 | foreach (var line in lines) |
71 | 86 | { |
@@ -78,14 +93,8 @@ namespace KancolleSniffer.Log | ||
78 | 93 | if (date < from) |
79 | 94 | continue; |
80 | 95 | data[0] = Logger.FormatDateTime(date); |
81 | - var entries = data; | |
82 | - if (mission) | |
83 | - entries = data.Concat(new[] {"0"}).Take(fields).ToArray(); | |
84 | - if (material) | |
85 | - entries = data.Take(fields).ToArray(); | |
86 | - if (battle) | |
87 | - entries = _battleLogProcessor.Process(data); | |
88 | - if (entries.Length != fields) | |
96 | + var entries = processor.Process(data); | |
97 | + if (processor.Skip) | |
89 | 98 | continue; |
90 | 99 | var result = |
91 | 100 | number |
@@ -94,11 +103,34 @@ namespace KancolleSniffer.Log | ||
94 | 103 | delimiter = ",\n"; |
95 | 104 | yield return result; |
96 | 105 | } |
97 | - if (material && !number) // 資材の現在値を出力する | |
106 | + if (currentMaterial) // 資材の現在値を出力する | |
98 | 107 | yield return delimiter + "[\"" + Logger.FormatDateTime(now) + "\",\"" + |
99 | 108 | string.Join("\",\"", _materialCount.Select(c => c.Now)) + "\"]"; |
100 | 109 | } |
101 | 110 | |
111 | + private Processor DecideProcessor(string logName) | |
112 | + { | |
113 | + switch (logName) | |
114 | + { | |
115 | + case "遠征報告書": | |
116 | + return new MissionProcessor(); | |
117 | + case "改修報告書": | |
118 | + return new Processor(15); | |
119 | + case "海戦・ドロップ報告書": | |
120 | + return _battleLogProcessor; | |
121 | + case "開発報告書": | |
122 | + return new Processor(9); | |
123 | + case "建造報告書": | |
124 | + return new Processor(12); | |
125 | + case "資材ログ": | |
126 | + return new MaterialProcessor(); | |
127 | + case "戦果": | |
128 | + return new Processor(3); | |
129 | + default: | |
130 | + return new Processor(); | |
131 | + } | |
132 | + } | |
133 | + | |
102 | 134 | private DateTime ParseDateTime(string dateTime) |
103 | 135 | { |
104 | 136 | if (DateTime.TryParseExact(dateTime, Logger.DateTimeFormat, CultureInfo.InvariantCulture, |