OSDN Git Service

e213fb75ea826cc43cbebd0455a6b5c9acb4843f
[kancollesniffer/KancolleSniffer.git] / KancolleSniffer / FleetPanel.cs
1 // Copyright (C) 2015 Kazuhiro Fujieda <fujieda@users.osdn.me>\r
2 //\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
6 //\r
7 //    http://www.apache.org/licenses/LICENSE-2.0\r
8 //\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
14 \r
15 using System;\r
16 using System.Collections.Generic;\r
17 using System.Drawing;\r
18 using System.Linq;\r
19 using System.Windows.Forms;\r
20 \r
21 namespace KancolleSniffer\r
22 {\r
23     public class FleetPanel : Panel\r
24     {\r
25         private const int LineHeight = 14;\r
26         private const int LabelHeight = 12;\r
27         private EquipColumn[] _equipList;\r
28         private readonly List<ShipLabel[]> _labelList = new List<ShipLabel[]>();\r
29         private readonly List<Panel> _panelList = new List<Panel>();\r
30         private readonly ToolTip _toolTip = new ToolTip {ShowAlways = true};\r
31 \r
32         private class EquipColumn\r
33         {\r
34             public string Fleet { get; set; }\r
35             public string Fleet2 { get; set; }\r
36             public string Ship { get; set; }\r
37             public int Id { get; set; }\r
38             public string Equip { get; set; }\r
39             public Color Color { get; set; }\r
40             public string Spec { get; set; }\r
41             public string Spec2 { get; set; }\r
42             public string AircraftSpec { get; set; }\r
43 \r
44             public EquipColumn()\r
45             {\r
46                 Fleet = Ship = Equip = AircraftSpec = "";\r
47                 Color = DefaultBackColor;\r
48             }\r
49         }\r
50 \r
51         public void UpdateEquip(Sniffer sniffer)\r
52         {\r
53             CreateEquipList(sniffer);\r
54             SuspendLayout();\r
55             CreateEquipLabels();\r
56             SetEquipLabels();\r
57             ResumeLayout();\r
58         }\r
59 \r
60         private void CreateEquipList(Sniffer sniffer)\r
61         {\r
62             var list = new List<EquipColumn>();\r
63             var fn = new[] {"第一艦隊", "第二艦隊", "第三艦隊", "第四艦隊"};\r
64             var tp = 0.0;\r
65             for (var f = 0; f < fn.Length; f++)\r
66             {\r
67                 var drumTotal = 0;\r
68                 var drumShips = 0;\r
69                 var levelTotal = 0;\r
70                 var ships = new List<EquipColumn>();\r
71                 foreach (var s in sniffer.GetShipStatuses(f))\r
72                 {\r
73                     var drum = 0;\r
74                     var equips = new List<EquipColumn>();\r
75                     for (var i = 0; i < s.Slot.Length; i++)\r
76                     {\r
77                         var item = s.Slot[i];\r
78                         var onslot = s.OnSlot[i];\r
79                         var max = s.Spec.MaxEq[i];\r
80                         if (item.Id == -1)\r
81                             continue;\r
82                         if (item.Spec.Name == "ドラム缶(輸送用)")\r
83                             drum++;\r
84                         var airspec = "";\r
85                         if (item.Spec.IsDiveBomber) // 爆撃\r
86                         {\r
87                             airspec = "航空戦 " + (25 + (int)(item.Spec.Bomber * Math.Sqrt(onslot)));\r
88                         }\r
89                         else if (item.Spec.IsTorpedoBomber)\r
90                         {\r
91                             var normal = 25 + item.Spec.Torpedo * Math.Sqrt(onslot);\r
92                             airspec = "航空戦 " + (int)(normal * 0.8) + "/" + (int)(normal * 1.5);\r
93                         }\r
94                         equips.Add(new EquipColumn\r
95                         {\r
96                             Equip = GenEquipString(item, onslot, max),\r
97                             AircraftSpec = airspec,\r
98                             Color = item.Spec.Color\r
99                         });\r
100                     }\r
101                     if (s.SlotEx.Id > 0)\r
102                     {\r
103                         var item = s.SlotEx;\r
104                         equips.Add(new EquipColumn {Equip = item.Spec.Name, Color = item.Spec.Color});\r
105                     }\r
106                     if (drum != 0)\r
107                         drumShips++;\r
108                     drumTotal += drum;\r
109                     levelTotal += s.Level;\r
110                     if (f < (sniffer.CombinedFleetType == 3 ? 2 : 1))\r
111                         tp += s.TransportPoint;\r
112                     var fire = s.RealFirepower;\r
113                     var subm = s.RealAntiSubmarine;\r
114                     var torp = s.RealTorpedo;\r
115                     var night = s.NightBattlePower;\r
116                     var ship = new EquipColumn\r
117                     {\r
118                         Ship = (s.Escaped ? "[避]" : "") + s.Name + " Lv" + s.Level,\r
119                         Id = s.Id,\r
120                         // ReSharper disable CompareOfFloatsByEqualityOperator\r
121                         Spec = (fire == 0 ? "" : $"砲{fire:f1}") + (subm == 0 ? "" : $" 潜{subm:f1}"),\r
122                         Spec2 = (torp == 0 ? "" : $"雷{torp:f1}") + (night == 0 ? "" : $" 夜{night:f1}")\r
123                         // ReSharper restore CompareOfFloatsByEqualityOperator\r
124                     };\r
125                     if (ship.Spec == "")\r
126                     {\r
127                         ship.Spec = ship.Spec2;\r
128                         ship.Spec2 = "";\r
129                     }\r
130                     ships.Add(ship);\r
131                     ships.AddRange(equips);\r
132                 }\r
133                 list.Add(new EquipColumn\r
134                 {\r
135                     Fleet = fn[f] + (levelTotal == 0 ? "" : " 合計Lv" + levelTotal) +\r
136                             (drumTotal == 0 ? "" : " ドラム缶" + drumTotal + "(" + drumShips + "隻)")\r
137                 });\r
138                 list.AddRange(ships);\r
139             }\r
140             list[0].Fleet2 = $"TP: S{(int)tp} A{(int)(tp * 0.7)}";\r
141             if (sniffer.BaseAirCorps != null)\r
142             {\r
143                 var name = new[] {"第一", "第二", "第三"};\r
144                 foreach (var baseInfo in sniffer.BaseAirCorps)\r
145                 {\r
146                     list.Add(new EquipColumn {Fleet = baseInfo.AreaName + " 基地航空隊"});\r
147                     var i = 0;\r
148                     foreach (var airCorps in baseInfo.AirCorps)\r
149                     {\r
150                         if (i >= name.Length)\r
151                             break;\r
152                         var fp = airCorps.FighterPower;\r
153                         list.Add(new EquipColumn\r
154                         {\r
155                             Ship = name[i++] + " " + airCorps.ActionName,\r
156                             Spec = "制空" + (fp[0] == fp[1] ? fp[0].ToString() : fp[0] + "~" + fp[1]) +\r
157                                    " 距離" + airCorps.Distance\r
158                         });\r
159                         list.AddRange(airCorps.Planes.Select(plane => new EquipColumn\r
160                         {\r
161                             Equip =\r
162                                 plane.State != 1\r
163                                     ? plane.StateName\r
164                                     : GenEquipString(plane.Slot, plane.Count, plane.MaxCount),\r
165                             Color = plane.Slot.Spec.Color\r
166                         }));\r
167                     }\r
168                 }\r
169             }\r
170             _equipList = list.ToArray();\r
171         }\r
172 \r
173         private string GenEquipString(ItemStatus item, int onslot, int max)\r
174         {\r
175             var name = item.Spec.Name;\r
176             var attr = (item.Alv == 0 ? "" : "+" + item.Alv) +\r
177                        (item.Level == 0 ? "" : "★" + item.Level) +\r
178                        (!item.Spec.IsAircraft ? "" : " " + onslot + "/" + max);\r
179             var proposed = new Size(int.MaxValue, int.MaxValue);\r
180             const int maxWidth = 180;\r
181             var result = name + attr;\r
182             if (TextRenderer.MeasureText(result, Font, proposed).Width <= maxWidth)\r
183                 return result;\r
184             attr = " " + attr;\r
185             var truncated = "";\r
186             foreach (var ch in name)\r
187             {\r
188                 var tmp = truncated + ch;\r
189                 if (TextRenderer.MeasureText(tmp + attr, Font, proposed).Width > maxWidth)\r
190                     break;\r
191                 truncated = tmp;\r
192             }\r
193             return truncated + attr;\r
194         }\r
195 \r
196         private void CreateEquipLabels()\r
197         {\r
198             for (var i = _labelList.Count; i < _equipList.Length; i++)\r
199                 CreateEquipLabels(i);\r
200         }\r
201 \r
202         private void CreateEquipLabels(int i)\r
203         {\r
204             var y = 1 + LineHeight * i;\r
205             var lbp = new Panel\r
206             {\r
207                 Location = new Point(0, y),\r
208                 Size = new Size(ListForm.PanelWidth, LineHeight),\r
209                 BackColor = ShipLabels.ColumnColors[(i + 1) % 2],\r
210                 Visible = false\r
211             };\r
212             lbp.Scale(ShipLabel.ScaleFactor);\r
213             lbp.Tag = lbp.Location.Y;\r
214             var labels = new[]\r
215             {\r
216                 new ShipLabel {Location = new Point(1, 2), AutoSize = true},\r
217                 new ShipLabel {Location = new Point(10, 2), AutoSize = true},\r
218                 new ShipLabel {Location = new Point(38, 2), AutoSize = true},\r
219                 new ShipLabel {Location = new Point(35, 2), Size = new Size(4, LabelHeight - 2)},\r
220                 new ShipLabel {Location = new Point(217, 2), AutoSize = true, AnchorRight = true}\r
221             };\r
222             _labelList.Add(labels);\r
223             _panelList.Add(lbp);\r
224             // ReSharper disable once CoVariantArrayConversion\r
225             lbp.Controls.AddRange(labels);\r
226             Controls.Add(lbp);\r
227             foreach (var label in labels)\r
228             {\r
229                 label.Scale();\r
230                 label.PresetColor =\r
231                     label.BackColor = ShipLabels.ColumnColors[(i + 1) % 2];\r
232             }\r
233         }\r
234 \r
235         private void SetEquipLabels()\r
236         {\r
237             for (var i = 0; i < _equipList.Length; i++)\r
238                 SetEquip(i);\r
239             for (var i = _equipList.Length; i < _labelList.Count; i++)\r
240                 _panelList[i].Visible = false;\r
241         }\r
242 \r
243         private void SetEquip(int i)\r
244         {\r
245             var lbp = _panelList[i];\r
246             if (!lbp.Visible)\r
247                 lbp.Location = new Point(lbp.Left, (int)lbp.Tag + AutoScrollPosition.Y);\r
248             var e = _equipList[i];\r
249             var labels = _labelList[i];\r
250             labels[0].Text = e.Fleet;\r
251             labels[1].SetName(e.Ship);\r
252             labels[2].Text = e.Equip;\r
253             labels[3].Visible = e.Equip != "";\r
254             labels[3].BackColor = e.Color;\r
255             labels[4].Text = e.Spec;\r
256             if (e.Fleet != "" && e.Fleet2 != "")\r
257                 _toolTip.SetToolTip(labels[0], e.Fleet2);\r
258             _toolTip.SetToolTip(labels[2], e.AircraftSpec != "" ? e.AircraftSpec : "");\r
259             _toolTip.SetToolTip(labels[4], e.Spec2 != "" ? e.Spec2 : "");\r
260             lbp.Visible = true;\r
261         }\r
262 \r
263         public void ShowShip(int id)\r
264         {\r
265             var i = Array.FindIndex(_equipList, e => e.Id == id);\r
266             if (i == -1)\r
267                 return;\r
268             var y = (int)Math.Round(ShipLabel.ScaleFactor.Height * LineHeight * i);\r
269             AutoScrollPosition = new Point(0, y);\r
270         }\r
271     }\r
272 }