OSDN Git Service

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