OSDN Git Service

バージョン12.11の準備
[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 DynaJson;\r
23 using KancolleSniffer.Model;\r
24 using KancolleSniffer.Util;\r
25 \r
26 namespace KancolleSniffer\r
27 {\r
28     public class BattleResultError : Exception\r
29     {\r
30     }\r
31 \r
32     public class ErrorLog\r
33     {\r
34         private readonly Sniffer _sniffer;\r
35         private BattleState _prevBattleState = BattleState.None;\r
36         private readonly List<Main.Session> _battleApiLog = new List<Main.Session>();\r
37 \r
38         public ErrorLog(Sniffer sniffer)\r
39         {\r
40             _sniffer = sniffer;\r
41         }\r
42 \r
43         public void CheckBattleApi(Main.Session session)\r
44         {\r
45             if (_prevBattleState == BattleState.None)\r
46                 _battleApiLog.Clear();\r
47             try\r
48             {\r
49                 if (_sniffer.Battle.BattleState != BattleState.None)\r
50                 {\r
51                     _battleApiLog.Add(session);\r
52                 }\r
53                 else if (_prevBattleState == BattleState.Result &&\r
54                          // battleresultのあとのship_deckかportでのみエラー判定する\r
55                          _sniffer.IsBattleResultError)\r
56                 {\r
57                     throw new BattleResultError();\r
58                 }\r
59             }\r
60             finally\r
61             {\r
62                 _prevBattleState = _sniffer.Battle.BattleState;\r
63             }\r
64         }\r
65 \r
66         public string GenerateBattleErrorLog()\r
67         {\r
68             foreach (var s in _battleApiLog)\r
69                 Privacy.Remove(s);\r
70             var version = string.Join(".", Application.ProductVersion.Split('.').Take(2));\r
71             var api = CompressApi(string.Join("\r\n",\r
72                 new[] {BattleStartSlots()}.Concat(_battleApiLog.SelectMany(s => s.Lines))));\r
73             var rank = _sniffer.Battle.DisplayedResultRank;\r
74             var status = string.Join("\r\n", new[]\r
75             {\r
76                 rank.IsError ? $"{rank.Assumed}->{rank.Actual}" : "",\r
77                 HpDiffLog()\r
78             }.Where(s => !string.IsNullOrEmpty(s)));\r
79             var result = $"{{{{{{\r\n{DateTime.Now:g} {version}\r\n{status}\r\n{api}\r\n}}}}}}";\r
80             File.WriteAllText("error.log", result);\r
81             return result;\r
82         }\r
83 \r
84         private string BattleStartSlots()\r
85         {\r
86             return new JsonObject((from ship in _sniffer.BattleStartStatus\r
87                     group ship by ship.Fleet\r
88                     into fleet\r
89                     select\r
90                         (from s in fleet\r
91                             select (from item in s.AllSlot select item.Spec.Id).ToArray()\r
92                         ).ToArray()\r
93                 ).ToArray()).ToString();\r
94         }\r
95 \r
96         private string HpDiffLog() => string.Join(" ",\r
97             from pair in _sniffer.BattleResultStatusDiff\r
98             let assumed = pair.Assumed // こちらのFleetはnull\r
99             let actual = pair.Actual\r
100             select $"({actual.Fleet.Number}-{actual.DeckIndex}) {assumed.NowHp}->{actual.NowHp}");\r
101 \r
102         public string GenerateErrorLog(Main.Session s, string exception)\r
103         {\r
104             Privacy.Remove(s);\r
105             var version = string.Join(".", Application.ProductVersion.Split('.').Take(2));\r
106             var api = CompressApi(string.Join("\r\n", s.Lines));\r
107             var result = $"{{{{{{\r\n{DateTime.Now:g} {version}\r\n{exception}\r\n{api}\r\n}}}}}}";\r
108             File.WriteAllText("error.log", result);\r
109             return result;\r
110         }\r
111 \r
112         private string CompressApi(string api)\r
113         {\r
114             var output = new MemoryStream();\r
115             var gzip = new GZipStream(output, CompressionLevel.Optimal);\r
116             var bytes = Encoding.UTF8.GetBytes(api);\r
117             gzip.Write(bytes, 0, bytes.Length);\r
118             gzip.Close();\r
119             var ascii85 = Ascii85.Encode(output.ToArray());\r
120             var result = new List<string>();\r
121             var rest = ascii85.Length;\r
122             const int lineLength = 80;\r
123             for (var i = 0; i < ascii85.Length; i += lineLength, rest -= lineLength)\r
124                 result.Add(ascii85.Substring(i, Math.Min(rest, lineLength)));\r
125             return string.Join("\r\n", result);\r
126         }\r
127     }\r
128 }