OSDN Git Service

BattleResultPanelの実装を大幅に見直す
[kancollesniffer/KancolleSniffer.git] / KancolleSniffer / View / BattleResultPanel.cs
index 9741b71..38b26da 100644 (file)
@@ -25,25 +25,83 @@ namespace KancolleSniffer.View
 {\r
     public class BattleResultPanel : PanelWithToolTip\r
     {\r
-        private const int LineHeight = 16;\r
         private readonly List<ShipLabels> _friendLabels = new List<ShipLabels>();\r
         private readonly List<ShipLabels> _enemyLabels = new List<ShipLabels>();\r
         private readonly List<ShipLabel.Hp> _hpLabels = new List<ShipLabel.Hp>();\r
-        private readonly BattleInfo.BattleResult[] _result = new BattleInfo.BattleResult[2];\r
         private Label _phaseLabel, _rankLabel, _supportLabel, _cellLabel;\r
-        private readonly BattleResultRank[] _rank = new BattleResultRank[2];\r
-        private readonly InformationPanel _informationPanel;\r
+        private readonly InformationPanel _information;\r
         private CellInfo _cellInfo;\r
-        private string _supportType;\r
+        private readonly BattleData _data = new BattleData();\r
 \r
         public Spoiler Spoilers { get; set; }\r
 \r
+        private class BattleData\r
+        {\r
+            private Result _day;\r
+            private Result _night;\r
+            public int[] Formation;\r
+            public int[] FighterPower;\r
+            public EnemyFighterPower EnemyFighterPower;\r
+            public int AirControlLevel;\r
+            public string SupportType;\r
+            public bool HaveDay => _day != null;\r
+            public bool HaveNight => _night != null;\r
+\r
+            public class Result\r
+            {\r
+                public BattleInfo.BattleResult Damage;\r
+                public BattleResultRank Rank;\r
+            }\r
+\r
+            public Result GetResult(BattleState state)\r
+            {\r
+                switch (state)\r
+                {\r
+                    case BattleState.Day:\r
+                        return _day;\r
+                    case BattleState.SpNight:\r
+                    case BattleState.Night:\r
+                        return _night;\r
+                    default:\r
+                        return _day;\r
+                }\r
+            }\r
+\r
+            public void SetData(BattleInfo battle)\r
+            {\r
+                switch (battle.BattleState)\r
+                {\r
+                    case BattleState.Day:\r
+                        _day = new Result {Damage = battle.Result, Rank = battle.ResultRank};\r
+                        _night = null;\r
+                        break;\r
+                    case BattleState.SpNight:\r
+                        _day = null;\r
+                        goto case BattleState.Night;\r
+                    case BattleState.Night:\r
+                        _night = new Result {Damage = battle.Result, Rank = battle.ResultRank};\r
+                        break;\r
+                }\r
+                if (battle.BattleState != BattleState.Night)\r
+                    SetNonStateData(battle);\r
+            }\r
+\r
+            private void SetNonStateData(BattleInfo battle)\r
+            {\r
+                Formation = battle.Formation;\r
+                FighterPower = battle.FighterPower;\r
+                EnemyFighterPower = battle.EnemyFighterPower;\r
+                AirControlLevel = battle.AirControlLevel;\r
+                SupportType = battle.SupportType;\r
+            }\r
+        }\r
+\r
         public BattleResultPanel()\r
         {\r
             SuspendLayout();\r
             CreateLabels();\r
-            _informationPanel = new InformationPanel();\r
-            Controls.Add(_informationPanel);\r
+            _information = new InformationPanel();\r
+            Controls.Add(_information);\r
             ResumeLayout();\r
         }\r
 \r
@@ -67,59 +125,36 @@ namespace KancolleSniffer.View
             switch (sniffer.Battle.BattleState)\r
             {\r
                 case BattleState.None:\r
-                    if (_result[0] == null && _result[1] == null)\r
+                    if (!_data.HaveDay && !_data.HaveNight)\r
                         return;\r
                     ClearResult();\r
                     SetPhase("結果");\r
                     UpdateCellInfo(_cellInfo);\r
                     return;\r
-                case BattleState.Day:\r
-                case BattleState.SpNight:\r
-                    _result[0] = _result[1] = null;\r
-                    break;\r
                 case BattleState.Result:\r
                 case BattleState.Unknown:\r
                     return;\r
             }\r
-            _supportType = sniffer.Battle.SupportType;\r
+            _data.SetData(sniffer.Battle);\r
             if ((Spoilers & Spoiler.BattleResult) != 0)\r
             {\r
-                ShowResult(sniffer.Battle.Result);\r
-                ShowResultRank(sniffer.Battle.ResultRank);\r
+                ShowData(sniffer.Battle.BattleState);\r
                 switch (state)\r
                 {\r
                     case BattleState.Day:\r
-                        _result[0] = sniffer.Battle.Result;\r
-                        _rank[0] = sniffer.Battle.ResultRank;\r
                         SetPhase("昼戦");\r
                         break;\r
                     case BattleState.Night:\r
                     case BattleState.SpNight:\r
-                        _result[1] = sniffer.Battle.Result;\r
-                        _rank[1] = sniffer.Battle.ResultRank;\r
                         SetPhase("夜戦");\r
                         break;\r
                 }\r
-                _informationPanel.Visible = true;\r
             }\r
             else\r
             {\r
                 ClearResult();\r
                 SetPhase("結果");\r
-                switch (state)\r
-                {\r
-                    case BattleState.Day:\r
-                        _result[0] = sniffer.Battle.Result;\r
-                        _rank[0] = sniffer.Battle.ResultRank;\r
-                        break;\r
-                    case BattleState.Night:\r
-                    case BattleState.SpNight:\r
-                        _result[1] = sniffer.Battle.Result;\r
-                        _rank[1] = sniffer.Battle.ResultRank;\r
-                        break;\r
-                }\r
             }\r
-            _informationPanel.SetInformation(sniffer.Battle);\r
         }\r
 \r
         private void PhaseLabelClick(object sender, EventArgs ev)\r
@@ -127,32 +162,28 @@ namespace KancolleSniffer.View
             switch (_phaseLabel.Text)\r
             {\r
                 case "結果":\r
-                    if (_result[0] != null)\r
+                    if (_data.HaveDay)\r
                     {\r
-                        ShowResult(_result[0]);\r
-                        ShowResultRank(_rank[0]);\r
+                        ShowData(BattleState.Day);\r
                         SetPhase("昼戦");\r
                     }\r
-                    else if (_result[1] != null)\r
+                    else if (_data.HaveNight)\r
                     {\r
-                        ShowResult(_result[1]);\r
-                        ShowResultRank(_rank[1]);\r
+                        ShowData(BattleState.Night);\r
                         SetPhase("夜戦");\r
                     }\r
                     break;\r
                 case "昼戦":\r
-                    if (_result[1] != null)\r
+                    if (_data.HaveNight)\r
                     {\r
-                        ShowResult(_result[1]);\r
-                        ShowResultRank(_rank[1]);\r
+                        ShowData(BattleState.Night);\r
                         SetPhase("夜戦");\r
                     }\r
                     break;\r
                 case "夜戦":\r
-                    if (_result[0] != null)\r
+                    if (_data.HaveDay)\r
                     {\r
-                        ShowResult(_result[0]);\r
-                        ShowResultRank(_rank[0]);\r
+                        ShowData(BattleState.Day);\r
                         SetPhase("昼戦");\r
                     }\r
                     break;\r
@@ -162,7 +193,7 @@ namespace KancolleSniffer.View
         private void SetPhase(string phase)\r
         {\r
             _phaseLabel.Text = phase;\r
-            if (phase == "結果" || _result[0] != null && _result[1] != null)\r
+            if (phase == "結果" || _data.HaveDay && _data.HaveNight)\r
             {\r
                 _phaseLabel.BorderStyle = BorderStyle.FixedSingle;\r
                 _phaseLabel.Cursor = Cursors.Hand;\r
@@ -179,90 +210,70 @@ namespace KancolleSniffer.View
         private void ClearResult()\r
         {\r
             _scrollPosition = AutoScrollPosition;\r
-            foreach (var labels in _friendLabels)\r
-                labels.BackPanel.Visible = false;\r
-            _informationPanel.Visible = false;\r
+            SetPanelVisible(0);\r
+            _information.Visible = false;\r
             _rankLabel.Text = "";\r
             _supportLabel.Text = "";\r
         }\r
 \r
-        private void ShowResult(BattleInfo.BattleResult result)\r
+        private void ShowData(BattleState state)\r
+        {\r
+            var result = _data.GetResult(state);\r
+            ShowDamage(result.Damage);\r
+            ShowResultRank(result.Rank);\r
+            _information.Show(_data);\r
+            _supportLabel.Text = _data.SupportType;\r
+            UpdateCellInfo(_cellInfo);\r
+            AutoScrollPosition = new Point(-_scrollPosition.X, -_scrollPosition.Y);\r
+        }\r
+\r
+        private void ShowDamage(BattleInfo.BattleResult result)\r
         {\r
             SuspendLayout();\r
-            AutoScrollPosition = _scrollPosition;\r
-            var friend = result.Friend;\r
-            var enemy = result.Enemy;\r
-            for (var i = 0; i < friend.Main.Length; i++)\r
-            {\r
-                var labels = _friendLabels[i];\r
-                var ship = friend.Main[i];\r
-                labels.Name.Set(ship);\r
-                labels.Hp.Set(ship);\r
-                ToolTip.SetToolTip(labels.Name, GetEquipString(ship));\r
-            }\r
-            if (friend.Guard.Length > 0)\r
+            SetEachResult(_friendLabels, result.Friend);\r
+            SetEachResult(_enemyLabels, result.Enemy);\r
+            var lines = Max(Ships(result.Friend).Length, Ships(result.Enemy).Length);\r
+            SetPanelVisible(lines);\r
+            ResumeLayout(); // スクロールバーの有無を決定する\r
+            AdjustPanelWidth(lines);\r
+        }\r
+\r
+        private void SetEachResult(IReadOnlyList<ShipLabels> labelsList, BattleInfo.BattleResult.Combined fleet)\r
+        {\r
+            var ships = Ships(fleet);\r
+            for (var i = 0; i < ships.Length; i++)\r
             {\r
-                _friendLabels[friend.Main.Length].Name.Text = "護衛";\r
-                _friendLabels[friend.Main.Length].Hp.Reset();\r
-                for (var i = 0; i < friend.Guard.Length; i++)\r
+                var labels = labelsList[i];\r
+                if (i == fleet.Main.Length)\r
                 {\r
-                    var labels = _friendLabels[friend.Main.Length + 1 + i];\r
-                    var ship = friend.Guard[i];\r
-                    labels.Name.Set(ship);\r
-                    labels.Hp.Set(ship);\r
-                    ToolTip.SetToolTip(labels.Name, GetEquipString(ship));\r
+                    labels.Name.Text = "護衛";\r
+                    labels.Hp.Reset();\r
+                    continue;\r
                 }\r
-            }\r
-            var friendLines = friend.Main.Length + (friend.Guard.Length > 0 ? friend.Guard.Length + 1 : 0);\r
-            for (var i = friendLines; i < _friendLabels.Count; i++)\r
-            {\r
-                _friendLabels[i].Reset();\r
-            }\r
-            for (var i = 0; i < enemy.Main.Length; i++)\r
-            {\r
-                var labels = _enemyLabels[i];\r
-                var ship = enemy.Main[i];\r
-                labels.Name.SetName(ShortenName(ship.Name));\r
-                labels.Hp.Set(ship);\r
-                ToolTip.SetToolTip(labels.Name, GetEquipString(ship));\r
-            }\r
-            if (enemy.Guard.Length > 0)\r
-            {\r
-                _enemyLabels[enemy.Main.Length].Name.Text = "護衛";\r
-                _enemyLabels[enemy.Main.Length].Hp.Reset();\r
-                for (var i = 0; i < enemy.Guard.Length; i++)\r
+                var ship = ships[i];\r
+                if (ShipMaster.IsEnemyId(ship.Spec.Id))\r
                 {\r
-                    var labels = _enemyLabels[enemy.Main.Length + 1 + i];\r
-                    var ship = enemy.Guard[i];\r
-                    labels.Name.SetName(ShortenName(ship.Name));\r
                     labels.Hp.Set(ship);\r
-                    ToolTip.SetToolTip(labels.Name, GetEquipString(ship));\r
+                    labels.Name.SetName(ShortenName(ship.Name));\r
                 }\r
+                else\r
+                {\r
+                    labels.Set(ship);\r
+                }\r
+                ToolTip.SetToolTip(labels.Name, GetEquipString(ship));\r
             }\r
-            var enemyLines = enemy.Main.Length + (enemy.Guard.Length > 0 ? enemy.Guard.Length + 1 : 0);\r
-            for (var i = enemyLines; i < _enemyLabels.Count; i++)\r
-            {\r
-                _enemyLabels[i].Reset();\r
-            }\r
-            var lines = Max(friendLines, enemyLines);\r
-            for (var i = 0; i < lines; i++)\r
-            {\r
-                var panel = _friendLabels[i].BackPanel;\r
-                panel.Visible = true;\r
-            }\r
-            for (var i = lines; i < _friendLabels.Count; i++)\r
-                _friendLabels[i].BackPanel.Visible = false;\r
-            ResumeLayout(); // スクロールバーの有無を決定する\r
-            var panelWidth = Max(ClientSize.Width, // スクロールバーの有無を反映した横幅\r
-                _enemyLabels[0].Name.Location.X + _enemyLabels.Max(labels => labels.Name.Size.Width) - 1); // 敵の名前の右端\r
-            for (var i = 0; i < lines; i++)\r
-                _friendLabels[i].BackPanel.Width = panelWidth;\r
-            _informationPanel.Location = Scaler.Move(AutoScrollPosition.X, AutoScrollPosition.Y, 0, 20);\r
-            _informationPanel.Visible = true;\r
-            UpdateCellInfo(_cellInfo);\r
+            for (var i = ships.Length; i < labelsList.Count; i++)\r
+                labelsList[i].Reset();\r
+        }\r
+\r
+        private static ShipStatus[] Ships(BattleInfo.BattleResult.Combined fleet)\r
+        {\r
+            if (fleet.Guard.Length == 0)\r
+                return fleet.Main;\r
+            return fleet.Main.Concat(new[] {new ShipStatus()}.Concat(fleet.Guard)).ToArray();\r
         }\r
 \r
-        private string GetEquipString(ShipStatus ship)\r
+        private static string GetEquipString(ShipStatus ship)\r
         {\r
             var result =\r
                 (from i in Enumerable.Range(0, ship.Slot.Count)\r
@@ -277,7 +288,7 @@ namespace KancolleSniffer.View
             return string.Join("\r\n", result);\r
         }\r
 \r
-        private string ShortenName(string name)\r
+        private static string ShortenName(string name)\r
         {\r
             return new Regex(@"\(elite\)|\(flagship\)").Replace(name,\r
                 match => match.Value == "(elite)" ? "(e)" : "(f)");\r
@@ -287,54 +298,58 @@ namespace KancolleSniffer.View
         {\r
             var result = new[] {"完全S", "勝利S", "勝利A", "勝利B", "敗北C", "敗北D", "敗北E"};\r
             _rankLabel.Text = result[(int)rank];\r
-            _supportLabel.Text = _supportType;\r
         }\r
 \r
         public void UpdateCellInfo(CellInfo cellInfo)\r
         {\r
             _cellLabel.Text = (Spoilers & Spoiler.NextCell) == 0 ? cellInfo.Current : cellInfo.Next;\r
-            _cellLabel.Location = new Point(ClientSize.Width - _cellLabel.Width - 2, 4);\r
+            _cellLabel.Location = new Point(ClientSize.Width - _cellLabel.Width - 2, _cellLabel.Location.Y);\r
         }\r
 \r
+        private const int LineHeight = 16;\r
+        private const int LabelHeight = 12;\r
+        private const int LabelMargin = (LineHeight - LabelHeight) / 2;\r
+        private const int TopMargin = 4;\r
+\r
         private void CreateLabels()\r
         {\r
             _phaseLabel = new Label\r
             {\r
-                Location = new Point(4, 4),\r
-                Size = new Size(31, 14)\r
+                Location = new Point(4, TopMargin),\r
+                Size = new Size(31, LabelHeight + 2)\r
             };\r
             _phaseLabel.Click += PhaseLabelClick;\r
             Controls.Add(_phaseLabel);\r
             _rankLabel = new Label\r
             {\r
-                Location = new Point(37, 4),\r
-                Size = new Size(42, 12)\r
+                Location = new Point(37, TopMargin),\r
+                Size = new Size(42, LabelHeight)\r
             };\r
             Controls.Add(_rankLabel);\r
             _supportLabel = new Label\r
             {\r
-                Location = new Point(77, 4),\r
+                Location = new Point(77, TopMargin),\r
                 AutoSize = true\r
             };\r
             Controls.Add(_supportLabel);\r
             _cellLabel = new Label\r
             {\r
-                Location = new Point(0, 4),\r
+                Location = new Point(0, TopMargin),\r
                 AutoSize = true\r
             };\r
             Controls.Add(_cellLabel);\r
             for (var i = 0; i < 13; i++)\r
             {\r
-                var y = LineHeight * i + 38;\r
                 var friend = new ShipLabels\r
                 {\r
-                    Name = new ShipLabel.Name(new Point(1, 2), ShipNameWidth.BattleResult),\r
+                    Name = new ShipLabel.Name(new Point(1, LabelMargin), ShipNameWidth.BattleResult),\r
                     Hp = new ShipLabel.Hp(new Point(101, 0), LineHeight),\r
                     BackPanel = new Panel\r
                     {\r
-                        Location = new Point(0, y),\r
+                        Location = new Point(0, LineHeight * i + 38),\r
                         Size = new Size(0, LineHeight),\r
                         BackColor = CustomColors.ColumnColors.DarkFirst(i),\r
+                        Visible = false\r
                     }\r
                 };\r
                 _friendLabels.Add(friend);\r
@@ -343,7 +358,7 @@ namespace KancolleSniffer.View
                 friend.Hp.Click += HpLabelClickHandler;\r
                 var enemy = new ShipLabels\r
                 {\r
-                    Name = new ShipLabel.Name(new Point(164, 2), ShipNameWidth.Max),\r
+                    Name = new ShipLabel.Name(new Point(164, LabelMargin), ShipNameWidth.Max),\r
                     Hp = new ShipLabel.Hp\r
                     {\r
                         Location = new Point(119, 0),\r
@@ -357,6 +372,20 @@ namespace KancolleSniffer.View
             }\r
         }\r
 \r
+        private void SetPanelVisible(int showPanels)\r
+        {\r
+            for (var i = 0; i < _friendLabels.Count; i++)\r
+                _friendLabels[i].BackPanel.Visible = i < showPanels;\r
+        }\r
+\r
+        private void AdjustPanelWidth(int lines)\r
+        {\r
+            var panelWidth = Max(ClientSize.Width, // スクロールバーの有無を反映した横幅\r
+                _enemyLabels[0].Name.Location.X + _enemyLabels.Max(labels => labels.Name.Size.Width) - 1); // 敵の名前の右端\r
+            for (var i = 0; i < lines; i++)\r
+                _friendLabels[i].BackPanel.Width = panelWidth;\r
+        }\r
+\r
         protected override void OnMouseWheel(MouseEventArgs e)\r
         {\r
             if (VScroll && (ModifierKeys & Keys.Shift) == Keys.Shift)\r
@@ -369,111 +398,156 @@ namespace KancolleSniffer.View
             base.OnMouseWheel(e);\r
         }\r
 \r
-        private class InformationPanel : PanelWithToolTip\r
+        private sealed class InformationPanel : PanelWithToolTip\r
         {\r
-            private readonly Label[] _formation;\r
-            private readonly Label[] _fighterPower;\r
+            private readonly Formation _formation;\r
+            private readonly FighterPower _fighterPower;\r
 \r
             public InformationPanel()\r
             {\r
-                Visible = false;\r
-                Size = new Size(206, 16);\r
-                Controls.AddRange(_formation = new[]\r
+                _formation = new Formation\r
                 {\r
-                    new Label\r
+                    Friend = new Label\r
                     {\r
-                        Location = new Point(47, 2),\r
-                        Size = new Size(29, 12)\r
+                        Location = new Point(47, LabelMargin),\r
+                        Size = new Size(29, LabelHeight)\r
                     },\r
-                    new Label\r
+                    Enemy = new Label\r
                     {\r
-                        Location = new Point(75, 2),\r
-                        Size = new Size(29, 12)\r
+                        Location = new Point(75, LabelMargin),\r
+                        Size = new Size(29, LabelHeight)\r
                     },\r
-                    new Label\r
+                    State = new Label\r
                     {\r
-                        Location = new Point(1, 2),\r
-                        Size = new Size(48, 12),\r
+                        Location = new Point(1, LabelMargin),\r
+                        Size = new Size(48, LabelHeight),\r
                         TextAlign = ContentAlignment.MiddleCenter\r
                     }\r
-                });\r
-                Controls.AddRange(_fighterPower = new[]\r
+                };\r
+                Controls.AddRange(_formation.Controls);\r
+                _fighterPower = new FighterPower\r
                 {\r
-                    new Label\r
+                    ToolTip = ToolTip,\r
+                    Friend = new Label\r
                     {\r
-                        Location = new Point(162, 2),\r
-                        Size = new Size(23, 12),\r
+                        Location = new Point(162, LabelMargin),\r
+                        Size = new Size(23, LabelHeight),\r
                         TextAlign = ContentAlignment.MiddleRight\r
                     },\r
-                    new Label\r
+                    Enemy = new Label\r
                     {\r
-                        Location = new Point(183, 2),\r
-                        Size = new Size(23, 12),\r
+                        Location = new Point(183, LabelMargin),\r
+                        Size = new Size(23, LabelHeight),\r
                         TextAlign = ContentAlignment.MiddleRight\r
                     },\r
-                    new Label\r
+                    State = new Label\r
                     {\r
-                        Location = new Point(110, 2),\r
-                        Size = new Size(53, 12)\r
+                        Location = new Point(110, LabelMargin),\r
+                        Size = new Size(53, LabelHeight)\r
                     }\r
-                });\r
-                // ReSharper disable once VirtualMemberCallInConstructor\r
+                };\r
+                Controls.AddRange(_fighterPower.Controls);\r
+                Location = new Point(0, 20);\r
+                Size = new Size(206, 16);\r
                 BackColor = CustomColors.ColumnColors.Bright;\r
+                Visible = false;\r
+            }\r
+\r
+            public void Show(BattleData data)\r
+            {\r
+                SetData(data);\r
+                Visible = true;\r
             }\r
 \r
-            public void SetInformation(BattleInfo battleInfo)\r
+            private void SetData(BattleData data)\r
             {\r
-                _formation[0].Text = FormationName(battleInfo.Formation[0]);\r
-                _formation[1].Text = FormationName(battleInfo.Formation[1]);\r
-                _formation[2].Text = new[] {"同航戦", "反航戦", "T字有利", "T字不利"}[battleInfo.Formation[2] - 1];\r
+                _formation.SetFormation(data.Formation);\r
+                _fighterPower.SetFighterPower(data);\r
+            }\r
+\r
+            private class StateLabels\r
+            {\r
+                public Label Friend;\r
+                public Label Enemy;\r
+                public Label State;\r
+\r
+                public Control[] Controls => new Control[] {Friend, Enemy, State};\r
+            }\r
 \r
-                if (battleInfo.AirControlLevel == -1)\r
+            private class Formation : StateLabels\r
+            {\r
+                public void SetFormation(int[] formation)\r
                 {\r
-                    if (battleInfo.BattleState == BattleState.Night)\r
-                        return;\r
-                    foreach (var label in _fighterPower)\r
-                        label.Visible = false;\r
-                    return;\r
+                    Friend.Text = FormationName(formation[0]);\r
+                    Enemy.Text = FormationName(formation[1]);\r
+                    State.Text = new[] {"同航戦", "反航戦", "T字有利", "T字不利"}[formation[2] - 1];\r
+                }\r
+\r
+                private static string FormationName(int formation)\r
+                {\r
+                    switch (formation)\r
+                    {\r
+                        case 1:\r
+                            return "単縦";\r
+                        case 2:\r
+                            return "複縦";\r
+                        case 3:\r
+                            return "輪形";\r
+                        case 4:\r
+                            return "梯形";\r
+                        case 5:\r
+                            return "単横";\r
+                        case 6:\r
+                            return "警戒";\r
+                        case 11:\r
+                            return "第一";\r
+                        case 12:\r
+                            return "第二";\r
+                        case 13:\r
+                            return "第三";\r
+                        case 14:\r
+                            return "第四";\r
+                        default:\r
+                            return "";\r
+                    }\r
                 }\r
-                var fp = battleInfo.FighterPower;\r
-                _fighterPower[0].Text = fp[0].ToString("D");\r
-                ToolTip.SetToolTip(_fighterPower[0], fp[0] == fp[1] ? "" : $"{fp[0]}~{fp[1]}");\r
-                var efp = battleInfo.EnemyFighterPower;\r
-                _fighterPower[1].Text = efp.AirCombat + efp.UnknownMark;\r
-                ToolTip.SetToolTip(_fighterPower[1],\r
-                    efp.AirCombat == efp.Interception ? "" : "防空:" + efp.Interception + efp.UnknownMark);\r
-                _fighterPower[2].Text =\r
-                    new[] {"", "制空均衡", "制空確保", "航空優勢", "航空劣勢", "制空喪失"}[battleInfo.AirControlLevel + 1];\r
-                foreach (var label in _fighterPower)\r
-                    label.Visible = true;\r
             }\r
 \r
-            private string FormationName(int formation)\r
+            private class FighterPower : StateLabels\r
             {\r
-                switch (formation)\r
+                public ToolTip ToolTip { private get; set; }\r
+\r
+                public void SetFighterPower(BattleData data)\r
                 {\r
-                    case 1:\r
-                        return "単縦";\r
-                    case 2:\r
-                        return "複縦";\r
-                    case 3:\r
-                        return "輪形";\r
-                    case 4:\r
-                        return "梯形";\r
-                    case 5:\r
-                        return "単横";\r
-                    case 6:\r
-                        return "警戒";\r
-                    case 11:\r
-                        return "第一";\r
-                    case 12:\r
-                        return "第二";\r
-                    case 13:\r
-                        return "第三";\r
-                    case 14:\r
-                        return "第四";\r
-                    default:\r
-                        return "";\r
+                    if (data.AirControlLevel == -1)\r
+                    {\r
+                        foreach (var control in Controls)\r
+                            control.Text = "";\r
+                        return;\r
+                    }\r
+                    SetFriend(data.FighterPower);\r
+                    SetEnemy(data.EnemyFighterPower);\r
+                    SetAirControlLevel(data.AirControlLevel);\r
+                }\r
+\r
+                private void SetFriend(int[] fighterPower)\r
+                {\r
+                    var fp = fighterPower;\r
+                    Friend.Text = fp[0].ToString("D");\r
+                    ToolTip.SetToolTip(Friend, fp[0] == fp[1] ? "" : $"{fp[0]}~{fp[1]}");\r
+                }\r
+\r
+                private void SetEnemy(EnemyFighterPower enemy)\r
+                {\r
+                    Enemy.Text = enemy.AirCombat + enemy.UnknownMark;\r
+                    ToolTip.SetToolTip(Enemy,\r
+                        enemy.AirCombat == enemy.Interception ? "" : "防空:" + enemy.Interception + enemy.UnknownMark);\r
+                }\r
+\r
+                private void SetAirControlLevel(int level)\r
+                {\r
+                    State.Text =\r
+                        new[] {"", "制空均衡", "制空確保", "航空優勢", "航空劣勢", "制空喪失"}[level + 1];\r
                 }\r
             }\r
         }\r