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