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 KancolleSniffer.Model;
\r
22 using static System.Math;
\r
24 namespace KancolleSniffer.View
\r
26 public class BattleResultPanel : PanelWithToolTip
\r
28 private const int LineHeight = 16;
\r
29 private readonly List<ShipLabels> _friendLabels = new List<ShipLabels>();
\r
30 private readonly List<ShipLabels> _enemyLabels = new List<ShipLabels>();
\r
31 private readonly List<ShipLabel.Hp> _hpLabels = new List<ShipLabel.Hp>();
\r
32 private readonly BattleInfo.BattleResult[] _result = new BattleInfo.BattleResult[2];
\r
33 private Label _phaseLabel, _rankLabel, _supportLabel, _cellLabel;
\r
34 private readonly BattleResultRank[] _rank = new BattleResultRank[2];
\r
35 private readonly InformationPanel _informationPanel;
\r
36 private CellInfo _cellInfo;
\r
37 private string _supportType;
\r
39 public Spoiler Spoilers { get; set; }
\r
41 public BattleResultPanel()
\r
45 _informationPanel = new InformationPanel();
\r
46 Controls.Add(_informationPanel);
\r
50 public event Action HpLabelClick;
\r
52 private void HpLabelClickHandler(object sender, EventArgs ev)
\r
54 HpLabelClick?.Invoke();
\r
57 public void ToggleHpPercent()
\r
59 foreach (var label in _hpLabels)
\r
60 label.ToggleHpPercent();
\r
63 public void Update(Sniffer sniffer)
\r
65 var state = sniffer.Battle.BattleState;
\r
66 _cellInfo = sniffer.CellInfo;
\r
67 switch (sniffer.Battle.BattleState)
\r
69 case BattleState.None:
\r
70 if (_result[0] == null && _result[1] == null)
\r
74 UpdateCellInfo(_cellInfo);
\r
76 case BattleState.Day:
\r
77 case BattleState.SpNight:
\r
78 _result[0] = _result[1] = null;
\r
80 case BattleState.Result:
\r
81 case BattleState.Unknown:
\r
84 _supportType = sniffer.Battle.SupportType;
\r
85 if ((Spoilers & Spoiler.BattleResult) != 0)
\r
87 ShowResult(sniffer.Battle.Result);
\r
88 ShowResultRank(sniffer.Battle.ResultRank);
\r
91 case BattleState.Day:
\r
92 _result[0] = sniffer.Battle.Result;
\r
93 _rank[0] = sniffer.Battle.ResultRank;
\r
96 case BattleState.Night:
\r
97 case BattleState.SpNight:
\r
98 _result[1] = sniffer.Battle.Result;
\r
99 _rank[1] = sniffer.Battle.ResultRank;
\r
103 _informationPanel.Visible = true;
\r
111 case BattleState.Day:
\r
112 _result[0] = sniffer.Battle.Result;
\r
113 _rank[0] = sniffer.Battle.ResultRank;
\r
115 case BattleState.Night:
\r
116 case BattleState.SpNight:
\r
117 _result[1] = sniffer.Battle.Result;
\r
118 _rank[1] = sniffer.Battle.ResultRank;
\r
122 _informationPanel.SetInformation(sniffer.Battle);
\r
125 private void PhaseLabelClick(object sender, EventArgs ev)
\r
127 switch (_phaseLabel.Text)
\r
130 if (_result[0] != null)
\r
132 ShowResult(_result[0]);
\r
133 ShowResultRank(_rank[0]);
\r
136 else if (_result[1] != null)
\r
138 ShowResult(_result[1]);
\r
139 ShowResultRank(_rank[1]);
\r
144 if (_result[1] != null)
\r
146 ShowResult(_result[1]);
\r
147 ShowResultRank(_rank[1]);
\r
152 if (_result[0] != null)
\r
154 ShowResult(_result[0]);
\r
155 ShowResultRank(_rank[0]);
\r
162 private void SetPhase(string phase)
\r
164 _phaseLabel.Text = phase;
\r
165 if (phase == "結果" || _result[0] != null && _result[1] != null)
\r
167 _phaseLabel.BorderStyle = BorderStyle.FixedSingle;
\r
168 _phaseLabel.Cursor = Cursors.Hand;
\r
172 _phaseLabel.BorderStyle = BorderStyle.None;
\r
173 _phaseLabel.Cursor = Cursors.Default;
\r
177 private Point _scrollPosition;
\r
179 private void ClearResult()
\r
181 _scrollPosition = AutoScrollPosition;
\r
182 foreach (var labels in _friendLabels)
\r
183 labels.BackPanel.Visible = false;
\r
184 _informationPanel.Visible = false;
\r
185 _rankLabel.Text = "";
\r
186 _supportLabel.Text = "";
\r
189 private void ShowResult(BattleInfo.BattleResult result)
\r
192 AutoScrollPosition = _scrollPosition;
\r
193 var friend = result.Friend;
\r
194 var enemy = result.Enemy;
\r
195 for (var i = 0; i < friend.Main.Length; i++)
\r
197 var labels = _friendLabels[i];
\r
198 var ship = friend.Main[i];
\r
199 labels.Name.Set(ship);
\r
200 labels.Hp.Set(ship);
\r
201 ToolTip.SetToolTip(labels.Name, GetEquipString(ship));
\r
203 if (friend.Guard.Length > 0)
\r
205 _friendLabels[friend.Main.Length].Name.Text = "護衛";
\r
206 _friendLabels[friend.Main.Length].Hp.Reset();
\r
207 for (var i = 0; i < friend.Guard.Length; i++)
\r
209 var labels = _friendLabels[friend.Main.Length + 1 + i];
\r
210 var ship = friend.Guard[i];
\r
211 labels.Name.Set(ship);
\r
212 labels.Hp.Set(ship);
\r
213 ToolTip.SetToolTip(labels.Name, GetEquipString(ship));
\r
216 var friendLines = friend.Main.Length + (friend.Guard.Length > 0 ? friend.Guard.Length + 1 : 0);
\r
217 for (var i = friendLines; i < _friendLabels.Count; i++)
\r
219 _friendLabels[i].Reset();
\r
221 for (var i = 0; i < enemy.Main.Length; i++)
\r
223 var labels = _enemyLabels[i];
\r
224 var ship = enemy.Main[i];
\r
225 labels.Name.SetName(ShortenName(ship.Name));
\r
226 labels.Hp.Set(ship);
\r
227 ToolTip.SetToolTip(labels.Name, GetEquipString(ship));
\r
229 if (enemy.Guard.Length > 0)
\r
231 _enemyLabels[enemy.Main.Length].Name.Text = "護衛";
\r
232 _enemyLabels[enemy.Main.Length].Hp.Reset();
\r
233 for (var i = 0; i < enemy.Guard.Length; i++)
\r
235 var labels = _enemyLabels[enemy.Main.Length + 1 + i];
\r
236 var ship = enemy.Guard[i];
\r
237 labels.Name.SetName(ShortenName(ship.Name));
\r
238 labels.Hp.Set(ship);
\r
239 ToolTip.SetToolTip(labels.Name, GetEquipString(ship));
\r
242 var enemyLines = enemy.Main.Length + (enemy.Guard.Length > 0 ? enemy.Guard.Length + 1 : 0);
\r
243 for (var i = enemyLines; i < _enemyLabels.Count; i++)
\r
245 _enemyLabels[i].Reset();
\r
247 var lines = Max(friendLines, enemyLines);
\r
248 for (var i = 0; i < lines; i++)
\r
250 var panel = _friendLabels[i].BackPanel;
\r
251 panel.Visible = true;
\r
253 for (var i = lines; i < _friendLabels.Count; i++)
\r
254 _friendLabels[i].BackPanel.Visible = false;
\r
255 ResumeLayout(); // スクロールバーの有無を決定する
\r
256 var panelWidth = Max(ClientSize.Width, // スクロールバーの有無を反映した横幅
\r
257 _enemyLabels[0].Name.Location.X + _enemyLabels.Max(labels => labels.Name.Size.Width) - 1); // 敵の名前の右端
\r
258 for (var i = 0; i < lines; i++)
\r
259 _friendLabels[i].BackPanel.Width = panelWidth;
\r
260 _informationPanel.Location = Scaler.Move(AutoScrollPosition.X, AutoScrollPosition.Y, 0, 20);
\r
261 _informationPanel.Visible = true;
\r
262 UpdateCellInfo(_cellInfo);
\r
265 private string GetEquipString(ShipStatus ship)
\r
268 (from i in Enumerable.Range(0, ship.Slot.Count)
\r
269 let item = ship.Slot[i]
\r
271 select item.Spec.Name +
\r
272 (item.Spec.IsAircraft && ship.OnSlot.Length > 0 && ship.Spec.MaxEq.Length > 0
\r
273 ? $"{ship.OnSlot[i]}/{ship.Spec.MaxEq[i]}"
\r
275 if (ship.SlotEx.Id > 0)
\r
276 result = result.Concat(new[] {ship.SlotEx.Spec.Name});
\r
277 return string.Join("\r\n", result);
\r
280 private string ShortenName(string name)
\r
282 return new Regex(@"\(elite\)|\(flagship\)").Replace(name,
\r
283 match => match.Value == "(elite)" ? "(e)" : "(f)");
\r
286 private void ShowResultRank(BattleResultRank rank)
\r
288 var result = new[] {"完全S", "勝利S", "勝利A", "勝利B", "敗北C", "敗北D", "敗北E"};
\r
289 _rankLabel.Text = result[(int)rank];
\r
290 _supportLabel.Text = _supportType;
\r
293 public void UpdateCellInfo(CellInfo cellInfo)
\r
295 _cellLabel.Text = (Spoilers & Spoiler.NextCell) == 0 ? cellInfo.Current : cellInfo.Next;
\r
296 _cellLabel.Location = new Point(ClientSize.Width - _cellLabel.Width - 2, 4);
\r
299 private void CreateLabels()
\r
301 _phaseLabel = new Label
\r
303 Location = new Point(4, 4),
\r
304 Size = new Size(31, 14)
\r
306 _phaseLabel.Click += PhaseLabelClick;
\r
307 Controls.Add(_phaseLabel);
\r
308 _rankLabel = new Label
\r
310 Location = new Point(37, 4),
\r
311 Size = new Size(42, 12)
\r
313 Controls.Add(_rankLabel);
\r
314 _supportLabel = new Label
\r
316 Location = new Point(77, 4),
\r
319 Controls.Add(_supportLabel);
\r
320 _cellLabel = new Label
\r
322 Location = new Point(0, 4),
\r
325 Controls.Add(_cellLabel);
\r
326 for (var i = 0; i < 13; i++)
\r
328 var y = LineHeight * i + 38;
\r
329 var friend = new ShipLabels
\r
331 Name = new ShipLabel.Name(new Point(1, 2), ShipNameWidth.BattleResult),
\r
332 Hp = new ShipLabel.Hp(new Point(101, 0), LineHeight),
\r
333 BackPanel = new Panel
\r
335 Location = new Point(0, y),
\r
336 Size = new Size(0, LineHeight),
\r
337 BackColor = CustomColors.ColumnColors.DarkFirst(i),
\r
340 _friendLabels.Add(friend);
\r
341 friend.Arrange(this, CustomColors.ColumnColors.DarkFirst(i));
\r
342 _hpLabels.Add(friend.Hp);
\r
343 friend.Hp.Click += HpLabelClickHandler;
\r
344 var enemy = new ShipLabels
\r
346 Name = new ShipLabel.Name(new Point(164, 2), ShipNameWidth.Max),
\r
347 Hp = new ShipLabel.Hp
\r
349 Location = new Point(119, 0),
\r
351 MinimumSize = new Size(0, LineHeight),
\r
352 TextAlign = ContentAlignment.MiddleLeft
\r
355 _enemyLabels.Add(enemy);
\r
356 enemy.Arrange(friend.BackPanel, CustomColors.ColumnColors.DarkFirst(i));
\r
360 protected override void OnMouseWheel(MouseEventArgs e)
\r
362 if (VScroll && (ModifierKeys & Keys.Shift) == Keys.Shift)
\r
369 base.OnMouseWheel(e);
\r
372 private class InformationPanel : PanelWithToolTip
\r
374 private readonly Label[] _formation;
\r
375 private readonly Label[] _fighterPower;
\r
377 public InformationPanel()
\r
380 Size = new Size(206, 16);
\r
381 Controls.AddRange(_formation = new[]
\r
385 Location = new Point(47, 2),
\r
386 Size = new Size(29, 12)
\r
390 Location = new Point(75, 2),
\r
391 Size = new Size(29, 12)
\r
395 Location = new Point(1, 2),
\r
396 Size = new Size(48, 12),
\r
397 TextAlign = ContentAlignment.MiddleCenter
\r
400 Controls.AddRange(_fighterPower = new[]
\r
404 Location = new Point(162, 2),
\r
405 Size = new Size(23, 12),
\r
406 TextAlign = ContentAlignment.MiddleRight
\r
410 Location = new Point(183, 2),
\r
411 Size = new Size(23, 12),
\r
412 TextAlign = ContentAlignment.MiddleRight
\r
416 Location = new Point(110, 2),
\r
417 Size = new Size(53, 12)
\r
420 // ReSharper disable once VirtualMemberCallInConstructor
\r
421 BackColor = CustomColors.ColumnColors.Bright;
\r
424 public void SetInformation(BattleInfo battleInfo)
\r
426 _formation[0].Text = FormationName(battleInfo.Formation[0]);
\r
427 _formation[1].Text = FormationName(battleInfo.Formation[1]);
\r
428 _formation[2].Text = new[] {"同航戦", "反航戦", "T字有利", "T字不利"}[battleInfo.Formation[2] - 1];
\r
430 if (battleInfo.AirControlLevel == -1)
\r
432 if (battleInfo.BattleState == BattleState.Night)
\r
434 foreach (var label in _fighterPower)
\r
435 label.Visible = false;
\r
438 var fp = battleInfo.FighterPower;
\r
439 _fighterPower[0].Text = fp[0].ToString("D");
\r
440 ToolTip.SetToolTip(_fighterPower[0], fp[0] == fp[1] ? "" : $"{fp[0]}~{fp[1]}");
\r
441 var efp = battleInfo.EnemyFighterPower;
\r
442 _fighterPower[1].Text = efp.AirCombat + efp.UnknownMark;
\r
443 ToolTip.SetToolTip(_fighterPower[1],
\r
444 efp.AirCombat == efp.Interception ? "" : "防空:" + efp.Interception + efp.UnknownMark);
\r
445 _fighterPower[2].Text =
\r
446 new[] {"", "制空均衡", "制空確保", "航空優勢", "航空劣勢", "制空喪失"}[battleInfo.AirControlLevel + 1];
\r
447 foreach (var label in _fighterPower)
\r
448 label.Visible = true;
\r
451 private string FormationName(int formation)
\r