OSDN Git Service

戦果を集計時間(2時と14時)にリセットできるようにする
[kancollesniffer/KancolleSniffer.git] / KancolleSniffer / MainForm.cs
1 // Copyright (C) 2013, 2014 Kazuhiro Fujieda <fujieda@users.sourceforge.jp>\r
2 // \r
3 // This program is part of KancolleSniffer.\r
4 //\r
5 // KancolleSniffer is free software: you can redistribute it and/or modify\r
6 // it under the terms of the GNU General Public License as published by\r
7 // the Free Software Foundation, either version 3 of the License, or\r
8 // (at your option) any later version.\r
9 //\r
10 // This program is distributed in the hope that it will be useful,\r
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of\r
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
13 // GNU General Public License for more details.\r
14 //\r
15 // You should have received a copy of the GNU General Public License\r
16 // along with this program; if not, see <http://www.gnu.org/licenses/>.\r
17 \r
18 using System;\r
19 using System.Drawing;\r
20 using System.IO;\r
21 using System.Linq;\r
22 using System.Windows.Forms;\r
23 using Codeplex.Data;\r
24 using Fiddler;\r
25 \r
26 namespace KancolleSniffer\r
27 {\r
28     public partial class MainForm : Form\r
29     {\r
30         private readonly Sniffer _sniffer = new Sniffer();\r
31         private readonly dynamic _wmp = Activator.CreateInstance(Type.GetTypeFromProgID("WMPlayer.OCX.7"));\r
32         private readonly Config _config = new Config();\r
33         private readonly ConfigDialog _configDialog = new ConfigDialog();\r
34         private readonly int _labelRightDistance;\r
35         private int _currentFleet;\r
36         private readonly Label[] _labelCheckFleets;\r
37         private bool _started;\r
38 \r
39         public MainForm()\r
40         {\r
41             InitializeComponent();\r
42             FiddlerApplication.AfterSessionComplete += FiddlerApplication_AfterSessionComplete;\r
43             _wmp.PlayStateChange += new EventHandler(_wmp_PlayStateChange);\r
44             _configDialog.Tag = _config;\r
45             _labelRightDistance = labelHP1.Parent.Width - labelHP1.Right;\r
46             _labelCheckFleets = new[] {labelCheckFleet1, labelCheckFleet2, labelCheckFleet3, labelCheckFleet4};\r
47             var i = 0;\r
48             foreach (var label in new[] {labelFleet1, labelFleet2, labelFleet3, labelFleet4})\r
49                 label.Tag = i++;\r
50         }\r
51 \r
52         private void FiddlerApplication_AfterSessionComplete(Session oSession)\r
53         {\r
54             if (!oSession.bHasResponse || !oSession.uriContains("/kcsapi/api_"))\r
55                 return;\r
56             var response = oSession.GetResponseBodyAsString();\r
57             if (!response.StartsWith("svdata="))\r
58                 return;\r
59             response = response.Remove(0, "svdata=".Length);\r
60             var json = DynamicJson.Parse(response);\r
61             var request = oSession.GetRequestBodyAsString();\r
62             var update = (Sniffer.Update)_sniffer.Sniff(oSession.url, request, json);\r
63             if (update == Sniffer.Update.Start)\r
64             {\r
65                 Invoke(new Action(() => { labelLogin.Visible = false; }));\r
66                 _started = true;\r
67                 return;\r
68             }\r
69             if (!_started)\r
70                 return;\r
71             Action action = null;\r
72             if ((update & Sniffer.Update.Item) != 0)\r
73                 action += UpdateItemInfo;\r
74             if ((update & Sniffer.Update.Timer) != 0)\r
75                 action += UpdateTimers;\r
76             if ((update & Sniffer.Update.NDock) != 0)\r
77                 action += UpdateNDocLabels;\r
78             if ((update & Sniffer.Update.Mission) != 0)\r
79                 action += UpdateMissionLabels;\r
80             if ((update & Sniffer.Update.QuestList) != 0)\r
81                 action += UpdateQuestList;\r
82             if ((update & Sniffer.Update.Ship) != 0)\r
83                 action += UpdateShipInfo;\r
84             Invoke(action);\r
85         }\r
86 \r
87         private void MainForm_Load(object sender, EventArgs e)\r
88         {\r
89             _config.Load();\r
90             ApplyConfig();\r
91             _sniffer.LoadState();\r
92             FiddlerApplication.Startup(0, FiddlerCoreStartupFlags.RegisterAsSystemProxy);\r
93         }\r
94 \r
95         private void MainForm_FormClosing(object sender, FormClosingEventArgs e)\r
96         {\r
97             FiddlerApplication.Shutdown();\r
98             _config.Save();\r
99             _sniffer.SaveState();\r
100         }\r
101 \r
102         private void labelHP_SizeChanged(object sender, EventArgs e)\r
103         {\r
104             var label = (Label)sender;\r
105             label.Location = new Point(label.Parent.Width - _labelRightDistance - label.Width, label.Top);\r
106         }\r
107 \r
108         private void notifyIconMain_MouseDoubleClick(object sender, MouseEventArgs e)\r
109         {\r
110             if (WindowState == FormWindowState.Minimized)\r
111                 WindowState = FormWindowState.Normal;\r
112             Activate();\r
113         }\r
114 \r
115         private void ExitToolStripMenuItem_Click(object sender, EventArgs e)\r
116         {\r
117             Application.Exit();\r
118         }\r
119 \r
120 \r
121         private void ConfigToolStripMenuItem_Click(object sender, EventArgs e)\r
122         {\r
123             if (_configDialog.ShowDialog(this) == DialogResult.OK)\r
124                 ApplyConfig();\r
125         }\r
126 \r
127         private void ApplyConfig()\r
128         {\r
129             TopMost = _config.TopMost;\r
130             _wmp.settings.volume = _config.SoundVolume;\r
131             _sniffer.Item.MarginShips = _config.MarginShips;\r
132             _sniffer.Achievement.ResetHours = _config.ResetHours;\r
133         }\r
134 \r
135         private void timerMain_Tick(object sender, EventArgs e)\r
136         {\r
137             if (_started)\r
138                 UpdateTimers();\r
139         }\r
140 \r
141         private void UpdateItemInfo()\r
142         {\r
143             var item = _sniffer.Item;\r
144             labelNumOfShips.Text = string.Format("{0:D}/{1:D}", item.NowShips, item.MaxShips);\r
145             labelNumOfShips.ForeColor = item.TooManyShips ? Color.Red : Color.Black;\r
146             if (item.NeedRing)\r
147             {\r
148                 var message = string.Format("残り{0:D}隻", _sniffer.Item.MaxShips - _sniffer.Item.NowShips);\r
149                 Ring("艦娘が多すぎます", message, _config.MaxShipsSoundFile);\r
150                 item.NeedRing = false;\r
151             }\r
152             labelNumOfEquips.Text = string.Format("{0:D}/{1:D}", item.NowItems, item.MaxItems);\r
153             labelNumOfBuckets.Text = item.NumBuckets.ToString("D");\r
154             labelAchievement.Text = _sniffer.Achievement.Value.ToString("F1");\r
155         }\r
156 \r
157         private void UpdateMissionLabels()\r
158         {\r
159             foreach (var entry in\r
160                 new[] {labelMissionName1, labelMissionName2, labelMissionName3}.Zip(_sniffer.Missions,\r
161                     (label, mission) => new {label, mission.Name}))\r
162                 entry.label.Text = entry.Name;\r
163         }\r
164 \r
165         private void UpdateNDocLabels()\r
166         {\r
167             foreach (var entry in\r
168                 new[] {labelRepairShip1, labelRepairShip2, labelRepairShip3, labelRepairShip4}.Zip(_sniffer.NDock,\r
169                     (label, ndock) => new {label, ndock.Name}))\r
170                 entry.label.Text = entry.Name;\r
171         }\r
172 \r
173         private void UpdateShipInfo()\r
174         {\r
175             var name = new[] {labelShip1, labelShip2, labelShip3, labelShip4, labelShip5, labelShip6};\r
176             var lv = new[] {labelLv1, labelLv2, labelLv3, labelLv4, labelLv5, labelLv6};\r
177             var hp = new[] {labelHP1, labelHP2, labelHP3, labelHP4, labelHP5, labelHP6};\r
178             var cond = new[] {labelCond1, labelCond2, labelCond3, labelCond4, labelCond5, labelCond6};\r
179             var next = new[] {labelNextLv1, labelNextLv2, labelNextLv3, labelNextLv4, labelNextLv5, labelNextLv6};\r
180 \r
181             var statuses = _sniffer.GetShipStatuses(_currentFleet);\r
182             for (var i = 0; i < name.Length; i++)\r
183             {\r
184                 var stat = statuses[i];\r
185                 name[i].Text = stat.Name;\r
186                 lv[i].Text = stat.Level.ToString("D");\r
187                 SetHpLavel(hp[i], stat);\r
188                 if (stat.MaxHp == 0)\r
189                 {\r
190                     cond[i].Text = "0";\r
191                     cond[i].BackColor = DefaultBackColor;\r
192                 }\r
193                 else\r
194                     SetCondLabel(cond[i], stat.Cond);\r
195                 next[i].Text = stat.ExpToNext.ToString("D");\r
196             }\r
197             labelAirSuperiority.Text = _sniffer.GetAirSuperiority(_currentFleet).ToString("D");\r
198             UpdateChargeInfo();\r
199             UpdateCondTimers();\r
200             UpdateAkashiTimer();\r
201         }\r
202 \r
203         private void UpdateChargeInfo()\r
204         {\r
205             var fuel = new[] {labelFuel1, labelFuel2, labelFuel3, labelFuel4};\r
206             var bull = new[] {labelBull1, labelBull2, labelBull3, labelBull4};\r
207 \r
208             for (var i = 0; i < fuel.Length; i++)\r
209             {\r
210                 var stat = _sniffer.ChargeStatuses[i];\r
211                 fuel[i].ImageIndex = stat.Fuel;\r
212                 bull[i].ImageIndex = stat.Bull;\r
213             }\r
214         }\r
215 \r
216         private void SetHpLavel(Label label, ShipStatus status)\r
217         {\r
218             var colors = new[] {DefaultBackColor, Color.FromArgb(255, 240, 240, 100), Color.Orange, Color.Red};\r
219             label.Text = string.Format("{0:D}/{1:D}", status.NowHp, status.MaxHp);\r
220             label.BackColor = colors[status.DamageLevel];\r
221         }\r
222 \r
223         private void SetCondLabel(Label label, int cond)\r
224         {\r
225             label.Text = cond.ToString("D");\r
226             label.BackColor = cond >= 50\r
227                 ? Color.Yellow\r
228                 : cond >= 30\r
229                     ? DefaultBackColor\r
230                     : cond >= 20 ? Color.Orange : Color.Red;\r
231         }\r
232 \r
233         private void UpdateTimers()\r
234         {\r
235             foreach (var entry in\r
236                 new[] {labelMission1, labelMission2, labelMission3}.Zip(_sniffer.Missions,\r
237                     (label, mission) => new {label, mission.Name, mission.Timer}))\r
238             {\r
239                 entry.Timer.Update();\r
240                 SetTimerLabel(entry.label, entry.Timer);\r
241                 if (!entry.Timer.NeedRing)\r
242                     continue;\r
243                 Ring("遠征が終わりました", entry.Name, _config.MissionSoundFile);\r
244                 entry.Timer.NeedRing = false;\r
245             }\r
246             foreach (var entry in\r
247                 new[] {labelRepair1, labelRepair2, labelRepair3, labelRepair4}.Zip(_sniffer.NDock,\r
248                     (label, ndock) => new {label, ndock.Name, ndock.Timer}))\r
249             {\r
250                 entry.Timer.Update();\r
251                 SetTimerLabel(entry.label, entry.Timer);\r
252                 if (!entry.Timer.NeedRing)\r
253                     continue;\r
254                 Ring("入渠が終わりました", entry.Name, _config.NDockSoundFile);\r
255                 entry.Timer.NeedRing = false;\r
256             }\r
257             var kdock = new[] {labelConstruct1, labelConstruct2, labelConstruct3, labelConstruct4};\r
258             for (var i = 0; i < kdock.Length; i++)\r
259             {\r
260                 var timer = _sniffer.KDock[i];\r
261                 timer.Update();\r
262                 SetTimerLabel(kdock[i], timer);\r
263                 if (!timer.NeedRing)\r
264                     continue;\r
265                 Ring("建造が終わりました", string.Format("第{0:D}ドック", i + 1), _config.KDockSoundFile);\r
266                 timer.NeedRing = false;\r
267             }\r
268             UpdateCondTimers();\r
269             UpdateAkashiTimer();\r
270         }\r
271 \r
272         private void SetTimerLabel(Label label, RingTimer timer)\r
273         {\r
274             label.ForeColor = timer.IsFinished ? Color.Red : Color.Black;\r
275             label.Text = timer.ToString();\r
276         }\r
277 \r
278         private void UpdateCondTimers()\r
279         {\r
280             foreach (var entry in\r
281                 new[] {labelCondTimer1, labelCondTimer2, labelCondTimer3}.Zip(\r
282                     _sniffer.GetConditionTimers(_currentFleet), (label, timer) => new {label, timer}))\r
283                 entry.label.Text = entry.timer;\r
284         }\r
285 \r
286         private void UpdateAkashiTimer()\r
287         {\r
288             if (!_sniffer.GetShipStatuses(_currentFleet)[0].Name.StartsWith("明石"))\r
289             {\r
290                 labelAkashiTimer.Visible = false;\r
291                 return;\r
292             }\r
293             labelAkashiTimer.Visible = true;\r
294             var start = _sniffer.GetAkashiStartTime(_currentFleet);\r
295             if (start == DateTime.MinValue)\r
296             {\r
297                 labelAkashiTimer.Text = "00:00:00";\r
298                 return;\r
299             }\r
300             var span = DateTime.Now - start;\r
301             labelAkashiTimer.Text = span.Days == 0 ? span.ToString(@"hh\:mm\:ss") : span.ToString(@"d\.hh\:mm");\r
302         }\r
303 \r
304         private void UpdateQuestList()\r
305         {\r
306             var name = new[] {labelQuest1, labelQuest2, labelQuest3, labelQuest4, labelQuest5};\r
307             var progress = new[] {labelProgress1, labelProgress2, labelProgress3, labelProgress4, labelProgress5};\r
308 \r
309             for (var i = 0; i < name.Length; i++)\r
310             {\r
311                 if (i < _sniffer.Quests.Length)\r
312                 {\r
313                     name[i].Text = _sniffer.Quests[i].Name;\r
314                     progress[i].Text = string.Format("{0:D}%", _sniffer.Quests[i].Progress);\r
315                 }\r
316                 else\r
317                 {\r
318                     name[i].Text = progress[i].Text = "";\r
319                 }\r
320             }\r
321         }\r
322 \r
323         private void Ring(string baloonTitle, string baloonMessage, string soundFile)\r
324         {\r
325             if (_config.FlashWindow)\r
326                 Win32API.FlashWindow(Handle);\r
327             if (_config.ShowBaloonTip)\r
328                 notifyIconMain.ShowBalloonTip(20000, baloonTitle, baloonMessage, ToolTipIcon.Info);\r
329             if (_config.PlaySound && File.Exists(soundFile))\r
330             {\r
331                 _wmp.URL = soundFile;\r
332                 _wmp.controls.play();\r
333             }\r
334         }\r
335 \r
336         private void _wmp_PlayStateChange(object sender, EventArgs e)\r
337         {\r
338             if (_wmp.playState == 8) // MediaEnded\r
339                 _wmp.URL = ""; // 再生したファイルが差し替えできなくなるのを防ぐ。\r
340         }\r
341 \r
342         private void labelFleet_Click(object sender, EventArgs e)\r
343         {\r
344             var fleet = (int)((Label)sender).Tag;\r
345             if (_currentFleet == fleet)\r
346                 return;\r
347             _currentFleet = fleet;\r
348             foreach (var label in _labelCheckFleets)\r
349                 label.Visible = false;\r
350             _labelCheckFleets[fleet].Visible = true;\r
351             if (!_started)\r
352                 return;\r
353             UpdateShipInfo();\r
354         }\r
355 \r
356         private void labelResetAchievement_Click(object sender, EventArgs e)\r
357         {\r
358             _sniffer.Achievement.Reset();\r
359             UpdateItemInfo();\r
360         }\r
361     }\r
362 }