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