OSDN Git Service

エラーログから艦隊名などの情報を削除する
[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.Text.RegularExpressions;\r
22 using System.Windows.Forms;\r
23 \r
24 namespace KancolleSniffer\r
25 {\r
26     public class BattleResultError : Exception\r
27     {\r
28     }\r
29 \r
30     public class ErrorLog\r
31     {\r
32         private readonly Sniffer _sniffer;\r
33         private BattleState _prevBattleState = BattleState.None;\r
34         private readonly List<string[]> _battleApiLog = new List<string[]>();\r
35 \r
36         public ErrorLog(Sniffer sniffer)\r
37         {\r
38             _sniffer = sniffer;\r
39         }\r
40 \r
41         public void CheckBattleApi(string url, string request, string response)\r
42         {\r
43             if (!url.EndsWith("api_port/port"))\r
44                 _battleApiLog.Add(new[] {url, request, response});\r
45             try\r
46             {\r
47                 if (_prevBattleState == BattleState.Result &&\r
48                          // battleresultのあとのship_deckかportでのみエラー判定する\r
49                          IsBattleResultError)\r
50                 {\r
51                     throw new BattleResultError();\r
52                 }\r
53             }\r
54             finally\r
55             {\r
56                 _prevBattleState = _sniffer.Battle.BattleState;\r
57             }\r
58             if (url.EndsWith("api_port/port"))\r
59                 _battleApiLog.Clear();\r
60         }\r
61 \r
62         private bool IsBattleResultError =>\r
63             _sniffer.Battle.DisplayedResultRank.IsError || _sniffer.IsBattleResultStatusError;\r
64 \r
65         public string GenerateBattleErrorLog()\r
66         {\r
67             foreach (var logs in _battleApiLog)\r
68                 RemoveUnwantedInformation(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\r
98             let actual = pair.Actual\r
99             select $"({assumed.Fleet}-{assumed.DeckIndex}) {assumed.NowHp}->{actual.NowHp}");\r
100 \r
101         public string GenerateErrorLog(string url, string request, string response, string exception)\r
102         {\r
103             RemoveUnwantedInformation(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         public static void RemoveUnwantedInformation(ref string request, ref string response)\r
112         {\r
113             var token = new Regex(@"&api%5Ftoken=.+?(?=&|$)|api%5Ftoken=.+?(?:&|$)|api%5Fbtime=\d+&?");\r
114             request = token.Replace(request, "");\r
115             var id = new Regex(@"""api_member_id"":""?\d+""?,?|""api_nickname"":"".+?"",?|""api_nickname_id"":""\d+"",?|""api_name_id"":"".+?"",?|");\r
116             response = id.Replace(response, "");\r
117             var name = new Regex(@"""api_name"":"".+?""");\r
118             response = name.Replace(response, @"""api_name"":""""");\r
119         }\r
120 \r
121         private string CompressApi(string api)\r
122         {\r
123             var output = new MemoryStream();\r
124             var gzip = new GZipStream(output, CompressionLevel.Optimal);\r
125             var bytes = Encoding.UTF8.GetBytes(api);\r
126             gzip.Write(bytes, 0, bytes.Length);\r
127             gzip.Close();\r
128             var ascii85 = Ascii85.Encode(output.ToArray());\r
129             var result = new List<string>();\r
130             var rest = ascii85.Length;\r
131             const int lineLength = 80;\r
132             for (var i = 0; i < ascii85.Length; i += lineLength, rest -= lineLength)\r
133                 result.Add(ascii85.Substring(i, Math.Min(rest, lineLength)));\r
134             return string.Join("\r\n", result);\r
135         }\r
136     }\r
137 }