OSDN Git Service

ログイン時に流れる情報を取得するまで動かないようにする
[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 \r
38         public MainForm()\r
39         {\r
40             InitializeComponent();\r
41             FiddlerApplication.AfterSessionComplete += FiddlerApplication_AfterSessionComplete;\r
42             _wmp.PlayStateChange += new EventHandler(_wmp_PlayStateChange);\r
43             _configDialog.Tag = _config;\r
44             _labelRightDistance = labelHP1.Parent.Width - labelHP1.Right;\r
45             _labelCheckFleets = new[] {labelCheckFleet1, labelCheckFleet2, labelCheckFleet3, labelCheckFleet4};\r
46             var i = 0;\r
47             foreach (var label in new[] {labelFleet1, labelFleet2, labelFleet3, labelFleet4})\r
48                 label.Tag = i++;\r
49         }\r
50 \r
51         private void FiddlerApplication_AfterSessionComplete(Session oSession)\r
52         {\r
53             if (!oSession.bHasResponse || !oSession.uriContains("/kcsapi/api_"))\r
54                 return;\r
55             var response = oSession.GetResponseBodyAsString();\r
56             if (!response.StartsWith("svdata="))\r
57                 return;\r
58             response = response.Remove(0, "svdata=".Length);\r
59             var json = DynamicJson.Parse(response);\r
60             if (!json.IsDefined("api_data"))\r
61                 return;\r
62             json = json.api_data;\r
63             UpdateInfo update = _sniffer.Sniff(oSession.url, json);\r
64             if (!_sniffer.IsMasterAvailable)\r
65                 return;\r
66             if ((update & UpdateInfo.Item) != 0)\r
67                 Invoke(new Action(UpdateItemInfo));\r
68             if ((update & UpdateInfo.Mission) != 0)\r
69                 Invoke(new Action(UpdateMissionLabels));\r
70             if ((update & UpdateInfo.NDock) != 0)\r
71                 Invoke(new Action(UpdateNDocLabels));\r
72             if ((update & UpdateInfo.Ship) != 0)\r
73                 Invoke(new Action(UpdateShipInfo));\r
74             if ((update & UpdateInfo.Quest) != 0)\r
75                 Invoke(new Action(UpdateQuestList));\r
76             if ((update & UpdateInfo.Charge) != 0)\r
77                 Invoke(new Action(UpdateChargeInfo));\r
78         }\r
79 \r
80         private void MainForm_Load(object sender, EventArgs e)\r
81         {\r
82             _sniffer.LoadMaster();\r
83             _config.Load();\r
84             ApplyConfig();\r
85             FiddlerApplication.Startup(0, FiddlerCoreStartupFlags.RegisterAsSystemProxy);\r
86         }\r
87 \r
88         private void MainForm_FormClosing(object sender, FormClosingEventArgs e)\r
89         {\r
90             FiddlerApplication.Shutdown();\r
91             _sniffer.SaveMaster();\r
92             _config.Save();\r
93         }\r
94 \r
95         private void labelHP_SizeChanged(object sender, EventArgs e)\r
96         {\r
97             var label = (Label)sender;\r
98             label.Location = new Point(label.Parent.Width - _labelRightDistance - label.Width, label.Top);\r
99         }\r
100 \r
101         private void notifyIconMain_MouseDoubleClick(object sender, MouseEventArgs e)\r
102         {\r
103             if (WindowState == FormWindowState.Minimized)\r
104                 WindowState = FormWindowState.Normal;\r
105             Activate();\r
106         }\r
107 \r
108         private void ExitToolStripMenuItem_Click(object sender, EventArgs e)\r
109         {\r
110             Application.Exit();\r
111         }\r
112 \r
113 \r
114         private void ConfigToolStripMenuItem_Click(object sender, EventArgs e)\r
115         {\r
116             if (_configDialog.ShowDialog(this) == DialogResult.OK)\r
117                 ApplyConfig();\r
118         }\r
119 \r
120         private void ApplyConfig()\r
121         {\r
122             TopMost = _config.TopMost;\r
123             _wmp.settings.volume = _config.SoundVolume;\r
124             _sniffer.Item.MarginShips = _config.MarginShips;\r
125         }\r
126 \r
127         private void timerMain_Tick(object sender, EventArgs e)\r
128         {\r
129             if (_sniffer.IsMasterAvailable)\r
130                 UpdateTimers();\r
131         }\r
132 \r
133         private void UpdateItemInfo()\r
134         {\r
135             if (_sniffer.IsMasterAvailable)\r
136                 labelLogin.Visible = false;\r
137             var item = _sniffer.Item;\r
138             labelNumOfShips.Text = string.Format("{0:D}/{1:D}", item.NowShips, item.MaxShips);\r
139             labelNumOfShips.ForeColor = item.TooManyShips ? Color.Red : Color.Black;\r
140             if (item.NeedRing)\r
141             {\r
142                 var message = string.Format("残り{0:D}隻", _sniffer.Item.MaxShips - _sniffer.Item.NowShips);\r
143                 Ring("艦娘が多すぎます", message, _config.MaxShipsSoundFile);\r
144                 item.NeedRing = false;\r
145             }\r
146             labelNumOfEquips.Text = string.Format("{0:D}/{1:D}", item.NowItems, item.MaxItems);\r
147             labelNumOfBuckets.Text = item.NumBuckets.ToString("D");\r
148         }\r
149 \r
150         private void UpdateMissionLabels()\r
151         {\r
152             foreach (var entry in\r
153                 new[] {labelMissionName1, labelMissionName2, labelMissionName3}.Zip(_sniffer.Missions,\r
154                     (label, mission) => new {label, mission.Name}))\r
155                 entry.label.Text = entry.Name;\r
156         }\r
157 \r
158         private void UpdateNDocLabels()\r
159         {\r
160             foreach (var entry in\r
161                 new[] {labelRepairShip1, labelRepairShip2, labelRepairShip3, labelRepairShip4}.Zip(_sniffer.NDock,\r
162                     (label, ndock) => new {label, ndock.Name}))\r
163                 entry.label.Text = entry.Name;\r
164         }\r
165 \r
166         private void UpdateShipInfo()\r
167         {\r
168             var name = new[] {labelShip1, labelShip2, labelShip3, labelShip4, labelShip5, labelShip6};\r
169             var lv = new[] {labelLv1, labelLv2, labelLv3, labelLv4, labelLv5, labelLv6};\r
170             var hp = new[] {labelHP1, labelHP2, labelHP3, labelHP4, labelHP5, labelHP6};\r
171             var cond = new[] {labelCond1, labelCond2, labelCond3, labelCond4, labelCond5, labelCond6};\r
172             var next = new[] {labelNextLv1, labelNextLv2, labelNextLv3, labelNextLv4, labelNextLv5, labelNextLv6};\r
173 \r
174             var statuses = _sniffer.GetShipStatuses(_currentFleet);\r
175             for (var i = 0; i < name.Length; i++)\r
176             {\r
177                 var stat = statuses[i];\r
178                 name[i].Text = stat.Name;\r
179                 lv[i].Text = stat.Level.ToString("D");\r
180                 SetHpLavel(hp[i], stat.NowHp, stat.MaxHp);\r
181                 if (stat.Name == null)\r
182                 {\r
183                     cond[i].Text = "0";\r
184                     cond[i].BackColor = DefaultBackColor;\r
185                 }\r
186                 else\r
187                     SetCondLabel(cond[i], stat.Cond);\r
188                 next[i].Text = stat.ExpToNext.ToString("D");\r
189             }\r
190             labelAirSuperiority.Text = _sniffer.GetAirSuperiority(_currentFleet).ToString("D");\r
191         }\r
192 \r
193         private void UpdateChargeInfo()\r
194         {\r
195             var fuel = new[] {labelFuel1, labelFuel2, labelFuel3, labelFuel4};\r
196             var bull = new[] {labelBull1, labelBull2, labelBull3, labelBull4};\r
197 \r
198             for (var i = 0; i < fuel.Length; i++)\r
199             {\r
200                 var stat = _sniffer.ChargeStatuses[i];\r
201                 fuel[i].ImageIndex = stat.Fuel;\r
202                 bull[i].ImageIndex = stat.Bull;\r
203             }\r
204         }\r
205 \r
206         private void SetHpLavel(Label label, int now, int max)\r
207         {\r
208             label.Text = string.Format("{0:D}/{1:D}", now, max);\r
209             var damage = max == 0 ? 1 : (double)now / max;\r
210             label.BackColor = damage > 0.75\r
211                 ? DefaultBackColor\r
212                 : damage > 0.5 ? Color.FromArgb(255, 240, 240, 100) : damage > 0.25 ? Color.Orange : Color.Red;\r
213         }\r
214 \r
215         private void SetCondLabel(Label label, int cond)\r
216         {\r
217             label.Text = cond.ToString("D");\r
218             label.BackColor = cond >= 50\r
219                 ? Color.Yellow\r
220                 : cond >= 30\r
221                     ? DefaultBackColor\r
222                     : cond >= 20 ? Color.Orange : Color.Red;\r
223         }\r
224 \r
225         private void UpdateTimers()\r
226         {\r
227             foreach (var entry in\r
228                 new[] {labelMission1, labelMission2, labelMission3}.Zip(_sniffer.Missions,\r
229                     (label, mission) => new {label, mission.Name, mission.Timer}))\r
230             {\r
231                 entry.Timer.Update();\r
232                 SetTimerLabel(entry.label, entry.Timer);\r
233                 if (!entry.Timer.NeedRing)\r
234                     continue;\r
235                 Ring("遠征が終わりました", entry.Name, _config.MissionSoundFile);\r
236                 entry.Timer.NeedRing = false;\r
237             }\r
238             foreach (var entry in\r
239                 new[] {labelRepair1, labelRepair2, labelRepair3, labelRepair4}.Zip(_sniffer.NDock,\r
240                     (label, ndock) => new {label, ndock.Name, ndock.Timer}))\r
241             {\r
242                 entry.Timer.Update();\r
243                 SetTimerLabel(entry.label, entry.Timer);\r
244                 if (!entry.Timer.NeedRing)\r
245                     continue;\r
246                 Ring("入渠が終わりました", entry.Name, _config.NDockSoundFile);\r
247                 entry.Timer.NeedRing = false;\r
248             }\r
249             var kdock = new[] {labelConstruct1, labelConstruct2, labelConstruct3, labelConstruct4};\r
250             for (var i = 0; i < kdock.Length; i++)\r
251             {\r
252                 var timer = _sniffer.KDock[i];\r
253                 timer.Update();\r
254                 SetTimerLabel(kdock[i], timer);\r
255                 if (!timer.NeedRing)\r
256                     continue;\r
257                 Ring("建造が終わりました", string.Format("第{0:D}ドック", i + 1), _config.KDockSoundFile);\r
258                 timer.NeedRing = false;\r
259             }\r
260             UpdateCondTimers();\r
261         }\r
262 \r
263         private void SetTimerLabel(Label label, RingTimer timer)\r
264         {\r
265             if (timer.NeedRing)\r
266                 label.ForeColor = Color.Red;\r
267             if (!timer.IsSet)\r
268                 label.ForeColor = Color.Black;\r
269             label.Text = timer.ToString();\r
270         }\r
271 \r
272         private void UpdateCondTimers()\r
273         {\r
274             var now = DateTime.Now;\r
275             foreach (var entry in\r
276                 new[] {labelCondTimer1, labelCondTimer2, labelCondTimer3}.Zip(_sniffer.GetRecoveryTimes(_currentFleet),\r
277                     (label, time) => new {label, time}))\r
278                 entry.label.Text = entry.time > now ? (entry.time - now).ToString(@"mm\:ss") : "00:00";\r
279         }\r
280 \r
281         private void UpdateQuestList()\r
282         {\r
283             var name = new[] {labelQuest1, labelQuest2, labelQuest3, labelQuest4, labelQuest5};\r
284             var progress = new[] {labelProgress1, labelProgress2, labelProgress3, labelProgress4, labelProgress5};\r
285 \r
286             for (var i = 0; i < name.Length; i++)\r
287             {\r
288                 if (i < _sniffer.Quests.Length)\r
289                 {\r
290                     name[i].Text = _sniffer.Quests[i].Name;\r
291                     progress[i].Text = string.Format("{0:D}%", _sniffer.Quests[i].Progress);\r
292                 }\r
293                 else\r
294                 {\r
295                     name[i].Text = progress[i].Text = "";\r
296                 }\r
297             }\r
298         }\r
299 \r
300         private void Ring(string baloonTitle, string baloonMessage, string soundFile)\r
301         {\r
302             if (_config.FlashWindow)\r
303                 Win32API.FlashWindow(Handle);\r
304             if (_config.ShowBaloonTip)\r
305                 notifyIconMain.ShowBalloonTip(20000, baloonTitle, baloonMessage, ToolTipIcon.Info);\r
306             if (_config.PlaySound && File.Exists(soundFile))\r
307             {\r
308                 _wmp.URL = soundFile;\r
309                 _wmp.controls.play();\r
310             }\r
311         }\r
312 \r
313         private void _wmp_PlayStateChange(object sender, EventArgs e)\r
314         {\r
315             if (_wmp.playState == 8) // MediaEnded\r
316                 _wmp.URL = ""; // 再生したファイルが差し替えできなくなるのを防ぐ。\r
317         }\r
318 \r
319         private void labelFleet_Click(object sender, EventArgs e)\r
320         {\r
321             var fleet = (int)((Label)sender).Tag;\r
322             if (_currentFleet == fleet)\r
323                 return;\r
324             _currentFleet = fleet;\r
325             foreach (var label in _labelCheckFleets)\r
326                 label.Visible = false;\r
327             _labelCheckFleets[fleet].Visible = true;\r
328             if (!_sniffer.IsMasterAvailable)\r
329                 return;\r
330             UpdateShipInfo();\r
331             UpdateCondTimers();\r
332         }\r
333     }\r
334 }