1 // Copyright (C) 2017 Kazuhiro Fujieda <fujieda@users.osdn.me>
\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
7 // http://www.apache.org/licenses/LICENSE-2.0
\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
16 using System.Collections.Generic;
\r
17 using System.Drawing;
\r
19 using System.Text.RegularExpressions;
\r
20 using System.Windows.Forms;
\r
21 using static System.Math;
\r
23 namespace KancolleSniffer
\r
25 public class BattleResultPanel : Panel
\r
27 private const int LineHeight = 16;
\r
28 private readonly List<ShipLabel[]> _friendLabels = new List<ShipLabel[]>();
\r
29 private readonly List<ShipLabel[]> _enemyLabels = new List<ShipLabel[]>();
\r
30 private readonly List<Panel> _panelList = new List<Panel>();
\r
31 private bool _hpPercent;
\r
32 private readonly List<ShipLabel> _hpLabels = new List<ShipLabel>();
\r
33 private readonly ToolTip _toolTip = new ToolTip {ShowAlways = true};
\r
34 private readonly BattleInfo.BattleResult[] _result = new BattleInfo.BattleResult[2];
\r
35 private Label _phaseLabel, _rankLabel;
\r
36 private BattleState _prevBattleState;
\r
37 private readonly BattleResultRank[] _rank = new BattleResultRank[2];
\r
38 private readonly InformationPanel _infomationPanel;
\r
40 public bool Spoiler { get; set; }
\r
42 public BattleResultPanel()
\r
46 _infomationPanel = new InformationPanel();
\r
47 Controls.Add(_infomationPanel);
\r
51 public void SetShowHpPercent(bool hpPercent)
\r
53 if (hpPercent == _hpPercent)
\r
55 foreach (var label in _hpLabels)
\r
56 label.ToggleHpPercent();
\r
57 _hpPercent = hpPercent;
\r
60 public void Update(Sniffer sniffer)
\r
62 if (_prevBattleState == BattleState.None)
\r
63 _result[0] = _result[1] = null;
\r
64 var state = _prevBattleState = sniffer.Battle.BattleState;
\r
65 if (state != BattleState.Day && state != BattleState.Night)
\r
69 ShowResult(sniffer.Battle.Result);
\r
70 ShowResultRank(sniffer.Battle.ResultRank);
\r
71 if (state == BattleState.Day)
\r
73 _result[0] = sniffer.Battle.Result;
\r
74 _rank[0] = sniffer.Battle.ResultRank;
\r
77 else if (state == BattleState.Night)
\r
79 _result[1] = sniffer.Battle.Result;
\r
80 _rank[1] = sniffer.Battle.ResultRank;
\r
83 _infomationPanel.Visible = true;
\r
89 if (state == BattleState.Day)
\r
91 _result[0] = sniffer.Battle.Result;
\r
92 _rank[0] = sniffer.Battle.ResultRank;
\r
94 else if (state == BattleState.Night)
\r
96 _result[1] = sniffer.Battle.Result;
\r
97 _rank[1] = sniffer.Battle.ResultRank;
\r
100 _infomationPanel.SetInformation(sniffer.Battle);
\r
103 private void PhaseLabelClick(object sender, EventArgs ev)
\r
105 switch (_phaseLabel.Text)
\r
108 if (_result[0] != null)
\r
110 ShowResult(_result[0]);
\r
111 ShowResultRank(_rank[0]);
\r
114 else if (_result[1] != null)
\r
116 ShowResult(_result[1]);
\r
117 ShowResultRank(_rank[1]);
\r
122 if (_result[1] != null)
\r
124 ShowResult(_result[1]);
\r
125 ShowResultRank(_rank[1]);
\r
130 if (_result[0] != null)
\r
132 ShowResult(_result[0]);
\r
133 ShowResultRank(_rank[0]);
\r
140 private void SetPhase(string phase)
\r
142 _phaseLabel.Text = phase;
\r
143 if (phase == "結果" || _result[0] != null && _result[1] != null)
\r
145 _phaseLabel.BorderStyle = BorderStyle.FixedSingle;
\r
146 _phaseLabel.Cursor = Cursors.Hand;
\r
150 _phaseLabel.BorderStyle = BorderStyle.None;
\r
151 _phaseLabel.Cursor = Cursors.Default;
\r
155 private void ClearResult()
\r
157 foreach (var panel in _panelList)
\r
158 panel.Visible = false;
\r
159 _rankLabel.Visible = _infomationPanel.Visible = false;
\r
162 private void ShowResult(BattleInfo.BattleResult result)
\r
165 var friend = result.Friend;
\r
166 var enemy = result.Enemy;
\r
167 var fleet = new[] {"第一", "第二", "第三", "第四"};
\r
168 _friendLabels[0][1].Text = fleet[friend.Main[0].Fleet];
\r
169 for (var i = 0; i < friend.Main.Length; i++)
\r
171 _friendLabels[i + 1][0].SetHp(friend.Main[i]);
\r
172 _friendLabels[i + 1][1].SetName(friend.Main[i], ShipNameWidth.BattleResult);
\r
174 if (friend.Guard.Length > 0)
\r
176 _friendLabels[friend.Main.Length + 1][1].Text = fleet[friend.Guard[0].Fleet];
\r
177 _friendLabels[friend.Main.Length + 1][0].SetHp(null);
\r
178 for (var i = 0; i < friend.Guard.Length; i++)
\r
180 var labels = _friendLabels[friend.Main.Length + 2 + i];
\r
181 labels[0].SetHp(friend.Guard[i]);
\r
182 labels[1].SetName(friend.Guard[i], ShipNameWidth.BattleResult);
\r
185 var friendLines = 1 + friend.Main.Length + (friend.Guard.Length > 0 ? friend.Guard.Length + 1 : 0);
\r
186 for (var i = friendLines; i < _friendLabels.Count; i++)
\r
188 _friendLabels[i][0].SetHp(null);
\r
189 _friendLabels[i][1].SetName("");
\r
191 _enemyLabels[0][1].Text = "本隊";
\r
192 for (var i = 0; i < enemy.Main.Length; i++)
\r
194 var labels = _enemyLabels[i + 1];
\r
195 labels[0].SetHp(enemy.Main[i]);
\r
196 labels[1].SetName(ShortenName(enemy.Main[i].Name));
\r
197 _toolTip.SetToolTip(labels[1], string.Join("\r\n", enemy.Main[i].Slot.Select(item => item.Spec.Name)));
\r
199 if (enemy.Guard.Length > 0)
\r
201 _enemyLabels[enemy.Main.Length + 1][0].SetHp(null);
\r
202 _enemyLabels[enemy.Main.Length + 1][1].Text = "護衛";
\r
203 for (var i = 0; i < enemy.Guard.Length; i++)
\r
205 var labels = _enemyLabels[enemy.Main.Length + 2 + i];
\r
206 labels[0].SetHp(enemy.Guard[i]);
\r
207 labels[1].SetName(ShortenName(enemy.Guard[i].Name));
\r
208 _toolTip.SetToolTip(labels[1],
\r
209 string.Join("\r\n", enemy.Guard[i].Slot.Select(item => item.Spec.Name)));
\r
212 var enemyLines = 1 + enemy.Main.Length + (enemy.Guard.Length > 0 ? enemy.Guard.Length + 1 : 0);
\r
213 for (var i = enemyLines; i < _enemyLabels.Count; i++)
\r
215 _enemyLabels[i][0].SetHp(null);
\r
216 _enemyLabels[i][1].SetName("");
\r
218 var lines = Max(friendLines, enemyLines);
\r
219 for (var i = 0; i < lines; i++)
\r
221 var panel = _panelList[i];
\r
224 panel.Location = new Point(AutoScrollPosition.X,
\r
225 (int)Round((int)panel.Tag * ShipLabel.ScaleFactor.Height) + AutoScrollPosition.Y);
\r
226 panel.Visible = true;
\r
228 for (var i = lines; i < _panelList.Count; i++)
\r
229 _panelList[i].Visible = false;
\r
230 ResumeLayout(); // スクロールバーの有無を決定する
\r
231 var panelWidth = Max(ClientSize.Width, // スクロールバーの有無を反映した横幅
\r
232 _enemyLabels[0][1].Location.X + _enemyLabels.Max(labels => labels[1].Size.Width) - 1); // 敵の名前の右端
\r
233 for (var i = 0; i < lines; i++)
\r
234 _panelList[i].Width = panelWidth;
\r
235 _infomationPanel.Location = new Point(AutoScrollPosition.X, 2 + AutoScrollPosition.Y);
\r
236 _infomationPanel.Visible = true;
\r
239 private string ShortenName(string name)
\r
241 return new Regex(@"\(elite\)|\(flagship\)").Replace(name,
\r
242 match => match.Value == "(elite)" ? "(e)" : "(f)");
\r
245 private void ShowResultRank(BattleResultRank rank)
\r
247 _rankLabel.Visible = true;
\r
248 var result = new[] {"完全S", "勝利S", "勝利A", "勝利B", "敗北C", "敗北D", "敗北E"};
\r
249 _rankLabel.Text = result[(int)rank];
\r
252 private void CreateLabels()
\r
254 _phaseLabel = new Label
\r
256 Location = new Point(78, 18),
\r
257 Size = new Size(31, 14)
\r
259 _phaseLabel.Click += PhaseLabelClick;
\r
260 Controls.Add(_phaseLabel);
\r
261 _rankLabel = new Label
\r
263 Location = new Point(110, 18),
\r
264 Size = new Size(42, 12)
\r
266 Controls.Add(_rankLabel);
\r
267 for (var i = 0; i < 14; i++)
\r
269 var y = LineHeight * (i + 1);
\r
270 var panel = new Panel
\r
272 Location = new Point(0, y),
\r
273 Size = new Size(0, LineHeight),
\r
274 BackColor = ShipLabels.ColumnColors[i % 2],
\r
278 _panelList.Add(panel);
\r
282 new ShipLabel {Location = new Point(100, 2), AutoSize = true, AnchorRight = true},
\r
283 new ShipLabel {Location = new Point(1, 2), AutoSize = true}
\r
285 _friendLabels.Add(friend);
\r
286 _hpLabels.Add(friend[0]);
\r
289 new ShipLabel {Location = new Point(119, 2), AutoSize = true},
\r
290 new ShipLabel {Location = new Point(164, 2), AutoSize = true}
\r
292 _enemyLabels.Add(enemy);
\r
293 foreach (var label in friend.Concat(enemy))
\r
295 panel.Controls.Add(label);
\r
296 label.BackColor = label.PresetColor = ShipLabels.ColumnColors[i % 2];
\r
298 Controls.Add(panel);
\r
302 private class InformationPanel : Panel
\r
304 private readonly Label[] _formation;
\r
305 private readonly Label[] _fighterPower;
\r
306 private readonly ToolTip _toolTip = new ToolTip {ShowAlways = true};
\r
308 public InformationPanel()
\r
311 Size = new Size(213, 12);
\r
312 Controls.AddRange(_formation = new[]
\r
316 Location = new Point(47, 0),
\r
317 Size = new Size(29, 12)
\r
321 Location = new Point(75, 0),
\r
322 Size = new Size(29, 12)
\r
326 Location = new Point(0, 0),
\r
327 Size = new Size(48, 12),
\r
328 TextAlign = ContentAlignment.MiddleRight
\r
331 Controls.AddRange(_fighterPower = new[]
\r
335 Location = new Point(168, 0),
\r
336 Size = new Size(23, 12),
\r
337 TextAlign = ContentAlignment.MiddleRight
\r
341 Location = new Point(190, 0),
\r
342 Size = new Size(23, 12),
\r
343 TextAlign = ContentAlignment.MiddleRight
\r
347 Location = new Point(116, 0),
\r
348 Size = new Size(53, 12)
\r
353 public void SetInformation(BattleInfo battleInfo)
\r
355 _formation[0].Text = FormationName(battleInfo.Formation[0]);
\r
356 _formation[1].Text = FormationName(battleInfo.Formation[1]);
\r
357 _formation[2].Text = new[] {"同航戦", "反航戦", "T字有利", "T字不利"}[battleInfo.Formation[2] - 1];
\r
359 if (battleInfo.AirControlLevel == -1)
\r
361 if (battleInfo.BattleState == BattleState.Night)
\r
363 foreach (var label in _fighterPower)
\r
364 label.Visible = false;
\r
367 var fp = battleInfo.FighterPower;
\r
368 _fighterPower[0].Text = fp[0].ToString("D");
\r
369 _toolTip.SetToolTip(_fighterPower[0], fp[0] == fp[1] ? "" : $"{fp[0]}~{fp[1]}");
\r
370 var efp = battleInfo.EnemyFighterPower;
\r
371 _fighterPower[1].Text = efp.AirCombat + efp.UnknownMark;
\r
372 _toolTip.SetToolTip(_fighterPower[1],
\r
373 efp.AirCombat == efp.Interception ? "" : "防空:" + efp.Interception + efp.UnknownMark);
\r
374 _fighterPower[2].Text =
\r
375 new[] {"", "制空均衡", "制空確保", "航空優勢", "航空劣勢", "制空喪失"}[battleInfo.AirControlLevel + 1];
\r
376 foreach (var label in _fighterPower)
\r
377 label.Visible = true;
\r
380 private string FormationName(int formation)
\r