OSDN Git Service

バージョン11.15の準備
[kancollesniffer/KancolleSniffer.git] / KancolleSniffer / ErrorLog.cs
1 // Copyright (C) 2017 Kazuhiro Fujieda <fujieda@users.osdn.me>\r
2 //\r
3 // Licensed under the Apache License, Version 2.0 (the "License");\r
4 // you may not use this file except in compliance with the License.\r
5 // You may obtain a copy of the License at\r
6 //\r
7 //    http://www.apache.org/licenses/LICENSE-2.0\r
8 //\r
9 // Unless required by applicable law or agreed to in writing, software\r
10 // distributed under the License is distributed on an "AS IS" BASIS,\r
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
12 // See the License for the specific language governing permissions and\r
13 // limitations under the License.\r
14 \r
15 using System;\r
16 using System.Collections.Generic;\r
17 using System.IO;\r
18 using System.IO.Compression;\r
19 using System.Linq;\r
20 using System.Text;\r
21 using System.Windows.Forms;\r
22 using KancolleSniffer.Model;\r
23 using KancolleSniffer.Util;\r
24 \r
25 namespace KancolleSniffer\r
26 {\r
27     public class BattleResultError : Exception\r
28     {\r
29     }\r
30 \r
31     public class ErrorLog\r
32     {\r
33         private readonly Sniffer _sniffer;\r
34         private BattleState _prevBattleState = BattleState.None;\r
35         private readonly List<string[]> _battleApiLog = new List<string[]>();\r
36 \r
37         public ErrorLog(Sniffer sniffer)\r
38         {\r
39             _sniffer = sniffer;\r
40         }\r
41 \r
42         public void CheckBattleApi(string url, string request, string response)\r
43         {\r
44             if (_prevBattleState == BattleState.None)\r
45                 _battleApiLog.Clear();\r
46             try\r
47             {\r
48                 if (_sniffer.Battle.BattleState != BattleState.None)\r
49                 {\r
50                     _battleApiLog.Add(new[] {url, request, response});\r
51                 }\r
52                 else if (_prevBattleState == BattleState.Result &&\r
53                          // battleresultのあとのship_deckかportでのみエラー判定する\r
54                          _sniffer.IsBattleResultError)\r
55                 {\r
56                     throw new BattleResultError();\r
57                 }\r
58             }\r
59             finally\r
60             {\r
61                 _prevBattleState = _sniffer.Battle.BattleState;\r
62             }\r
63         }\r
64 \r
65         public string GenerateBattleErrorLog()\r
66         {\r
67             foreach (var logs in _battleApiLog)\r
68                 Privacy.Remove(ref logs[0], ref logs[1], ref logs[2]);\r
69             var version = string.Join(".", Application.ProductVersion.Split('.').Take(2));\r
70             var api = CompressApi(string.Join("\r\n",\r
71                 new[] {BattleStartSlots()}.Concat(_battleApiLog.SelectMany(logs => logs))));\r
72             var rank = _sniffer.Battle.DisplayedResultRank;\r
73             var status = string.Join("\r\n", new[]\r
74             {\r
75                 rank.IsError ? $"{rank.Assumed}->{rank.Actual}" : "",\r
76                 HpDiffLog()\r
77             }.Where(s => !string.IsNullOrEmpty(s)));\r
78             var result = $"{{{{{{\r\n{DateTime.Now:g} {version}\r\n{status}\r\n{api}\r\n}}}}}}";\r
79             File.WriteAllText("error.log", result);\r
80             return result;\r
81         }\r
82 \r
83         private string BattleStartSlots()\r
84         {\r
85             return JsonObject.CreateJsonObject((from ship in _sniffer.BattleStartStatus\r
86                 group ship by ship.Fleet\r
87                 into fleet\r
88                 select\r
89                 (from s in fleet\r
90                     select (from item in s.AllSlot select item.Spec.Id).ToArray()\r
91                 ).ToArray()\r
92             ).ToArray()).ToString();\r
93         }\r
94 \r
95         private string HpDiffLog() => string.Join(" ",\r
96             from pair in _sniffer.BattleResultStatusDiff\r
97             let assumed = pair.Assumed // こちらのFleetはnull\r
98             let actual = pair.Actual\r
99             select $"({actual.Fleet.Number}-{actual.DeckIndex}) {assumed.NowHp}->{actual.NowHp}");\r
100 \r
101         public string GenerateErrorLog(string url, string request, string response, string exception)\r
102         {\r
103             Privacy.Remove(ref url, ref request, ref response);\r
104             var version = string.Join(".", Application.ProductVersion.Split('.').Take(2));\r
105             var api = CompressApi($"{url}\r\n{request}\r\n{response}");\r
106             var result = $"{{{{{{\r\n{DateTime.Now:g} {version}\r\n{exception}\r\n{api}\r\n}}}}}}";\r
107             File.WriteAllText("error.log", result);\r
108             return result;\r
109         }\r
110 \r
111         private string CompressApi(string api)\r
112         {\r
113             var output = new MemoryStream();\r
114             var gzip = new GZipStream(output, CompressionLevel.Optimal);\r
115             var bytes = Encoding.UTF8.GetBytes(api);\r
116             gzip.Write(bytes, 0, bytes.Length);\r
117             gzip.Close();\r
118             var ascii85 = Ascii85.Encode(output.ToArray());\r
119             var result = new List<string>();\r
120             var rest = ascii85.Length;\r
121             const int lineLength = 80;\r
122             for (var i = 0; i < ascii85.Length; i += lineLength, rest -= lineLength)\r
123                 result.Add(ascii85.Substring(i, Math.Min(rest, lineLength)));\r
124             return string.Join("\r\n", result);\r
125         }\r
126     }\r
127 }