1 // Copyright (C) 2015 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;
\r
17 using System.Collections.Generic;
\r
18 using System.Drawing;
\r
20 using System.Windows.Forms;
\r
21 using KancolleSniffer.Model;
\r
23 namespace KancolleSniffer.View
\r
25 public class FleetPanel : PanelWithToolTip
\r
27 private const int LineHeight = 14;
\r
28 private const int LabelHeight = 12;
\r
29 private Record[] _table = new Record[0];
\r
30 private readonly List<FleetLabels> _labelList = new List<FleetLabels>();
\r
31 private readonly List<Panel> _panelList = new List<Panel>();
\r
35 ToolTip.AutoPopDelay = 10000;
\r
40 public string Fleet { get; set; }
\r
41 public string Fleet2 { get; set; }
\r
42 public string Ship { get; set; }
\r
43 public string Ship2 { get; set; }
\r
44 public int Id { get; set; }
\r
45 public string Equip { get; set; }
\r
46 public Color Color { get; set; }
\r
47 public string Spec { get; set; }
\r
48 public string Spec2 { get; set; }
\r
49 public string AircraftSpec { get; set; }
\r
53 Fleet = Ship = Equip = AircraftSpec = "";
\r
54 Color = DefaultBackColor;
\r
58 public void Update(Sniffer sniffer)
\r
60 _table = CreateTable(sniffer);
\r
70 public int DrumShips;
\r
72 public int FirePower;
\r
73 public int AntiSubmarine;
\r
79 public void Add(ShipStatus s)
\r
81 var drum = s.Slot.Count(item => item.Spec.IsDrum);
\r
82 DrumShips += drum != 0 ? 1 : 0;
\r
85 FirePower += s.Firepower;
\r
86 AntiSubmarine += s.MissionAntiSubmarine;
\r
87 AntiAir += s.AntiAir;
\r
89 Fuel += s.EffectiveFuelMax;
\r
90 Bull += s.EffectiveBullMax;
\r
94 public Record[] CreateTable(Sniffer sniffer)
\r
96 var list = new List<Record>();
\r
97 var fn = new[] {"第一", "第二", "第三", "第四"};
\r
98 foreach (var fleet in sniffer.Fleets)
\r
100 var total = new Total();
\r
101 var shipRecords = new List<Record>();
\r
102 var speed = int.MaxValue;
\r
103 foreach (var ship in fleet.ActualShips)
\r
105 var equips = new List<Record>();
\r
106 for (var i = 0; i < ship.Slot.Count; i++)
\r
108 var item = ship.Slot[i];
\r
109 var onSlot = ship.OnSlot[i];
\r
110 var max = ship.Spec.MaxEq[i];
\r
114 if (item.Spec.IsDiveBomber) // 爆撃
\r
117 (25 + (int)((item.Spec.Bomber + item.BomberLevelBonus) * Math.Sqrt(onSlot)));
\r
119 else if (item.Spec.IsTorpedoBomber)
\r
121 var normal = 25 + item.Spec.Torpedo * Math.Sqrt(onSlot);
\r
122 airSpec = "航空戦 " + (int)(normal * 0.8) + "/" + (int)(normal * 1.5);
\r
124 equips.Add(new Record
\r
126 Equip = GenEquipString(item),
\r
127 Spec = item.Spec.IsAircraft ? $"+{item.Alv} {onSlot}/{max}" : "",
\r
128 AircraftSpec = airSpec,
\r
129 Color = item.Spec.Color
\r
132 if (ship.SlotEx.Id > 0)
\r
134 var item = ship.SlotEx;
\r
135 equips.Add(new Record {Equip = GenEquipString(item), Color = item.Spec.Color});
\r
138 speed = Math.Min(speed, ship.Speed);
\r
139 var fire = ship.EffectiveFirepower;
\r
140 // ReSharper disable IdentifierTypo
\r
141 var subm = ship.EffectiveAntiSubmarine;
\r
142 var torp = ship.EffectiveTorpedo;
\r
143 var night = ship.NightBattlePower;
\r
144 var oasa = ship.CanOpeningAntiSubmarineAttack ? "*" : "";
\r
145 // ReSharper restore IdentifierTypo
\r
146 var record = new Record
\r
148 Ship = (ship.Escaped ? "[避]" : "") + ship.Name + " Lv" + ship.Level,
\r
149 Ship2 = $"燃{ship.EffectiveFuelMax} 弾{ship.EffectiveBullMax}",
\r
151 Spec = HideIfZero("砲", fire) + HideIfZero(" 潜", subm) + oasa,
\r
152 Spec2 = (HideIfZero("雷", torp) + HideIfZero(" 夜", night)).TrimStart(' ')
\r
154 if (record.Spec == "")
\r
156 record.Spec = record.Spec2;
\r
159 shipRecords.Add(record);
\r
160 shipRecords.AddRange(equips);
\r
162 var daihatsu = fleet.DaihatsuBonus;
\r
163 var tp = fleet.TransportPoint;
\r
164 if (sniffer.IsCombinedFleet && fleet.Number == 0)
\r
165 tp += sniffer.Fleets[1].TransportPoint;
\r
166 var speedName = speed == int.MaxValue ? "" : new[] {"", "低速", "高速", "高速+", "最速"}[speed / 5];
\r
167 list.Add(new Record
\r
169 Fleet = fn[fleet.Number] + " " + speedName,
\r
171 "計:" + HideIfZero(" Lv", total.Level) +
\r
172 HideIfZero(" ド", total.Drum) + HideIfZero("(", total.DrumShips, "隻)") +
\r
173 HideIfZero(" 大", daihatsu * 100, "%") + "\r\n" +
\r
174 " 火" + CutOverFlow(total.FirePower) +
\r
175 " 空" + CutOverFlow(total.AntiAir) +
\r
176 " 潜" + CutOverFlow(total.AntiSubmarine) +
\r
177 " 索" + CutOverFlow(total.LoS) + "\r\n" +
\r
178 $"戦闘:燃{total.Fuel / 5}弾{total.Bull / 5} 支援:燃{total.Fuel / 2}弾{(int)(total.Bull * 0.8)}" +
\r
179 (sniffer.IsCombinedFleet && fleet.Number == 1
\r
181 : $"\r\nTP:S{(int)tp} A{(int)(tp * 0.7)}")
\r
183 list.AddRange(shipRecords);
\r
185 if (sniffer.AirBase != null)
\r
187 var name = new[] {"第一", "第二", "第三"};
\r
188 foreach (var baseInfo in sniffer.AirBase)
\r
190 list.Add(new Record {Fleet = baseInfo.AreaName + " 基地航空隊"});
\r
192 foreach (var airCorps in baseInfo.AirCorps)
\r
194 if (i >= name.Length)
\r
196 var corpsFp = airCorps.CalcFighterPower();
\r
197 var airCombat = new[] { (int)corpsFp[0].AirCombat, (int)corpsFp[1].AirCombat };
\r
198 var interception = new[] { (int)corpsFp[0].Interception, (int)corpsFp[1].Interception };
\r
199 var different = interception[0] != airCombat[0];
\r
202 if (airCorps.Action == 2)
\r
204 spec = "制空:" + RangeString(interception);
\r
205 spec2 = different ? "制空(出撃):" + RangeString(airCombat) : "";
\r
209 spec = "制空:" + RangeString(airCombat);
\r
210 spec2 = different ? "制空(防空):" + RangeString(interception) : "";
\r
212 var cost = airCorps.CostForSortie;
\r
213 list.Add(new Record
\r
215 Ship = name[i++] + " " + airCorps.ActionName,
\r
216 Ship2 = $"出撃コスト:燃{cost[0]}弾{cost[1]}",
\r
217 Spec = spec + $" 距離:{airCorps.Distance}",
\r
220 list.AddRange(airCorps.Planes.Select(plane =>
\r
222 var planeFp = plane.FighterPower;
\r
223 airCombat = new[] {(int)planeFp[0].AirCombat, (int)planeFp[1].AirCombat};
\r
224 interception = new[] {(int) planeFp[0].Interception, (int)planeFp[1].Interception };
\r
225 different = interception[0] != airCombat[0];
\r
228 Equip = plane.State != 1 ? plane.StateName : GenEquipString(plane.Slot),
\r
229 Spec = plane.State != 1 ? "" : $"+{plane.Slot.Alv} {plane.Count}/{plane.MaxCount}",
\r
231 $"距離:{plane.Slot.Spec.Distance} 制空:{RangeString(airCombat)}" +
\r
232 (different ? $" 防空:{RangeString(interception)}" : ""),
\r
233 Color = plane.Slot.Spec.Color
\r
239 return list.ToArray();
\r
242 private string RangeString(int[] fp) => fp[0] == fp[1] ? fp[0].ToString() : $"{fp[0]}~{fp[1]}";
\r
244 private int CutOverFlow(int value) => value > 999 ? 999 : value;
\r
246 private string HideIfZero(string name, double value, string suffix = "")
\r
248 return value > 0 ? name + value.ToString("f1") + suffix : "";
\r
251 private string HideIfZero(string name, int value, string suffix = "")
\r
253 return value > 0 ? name + value + suffix : "";
\r
256 private string GenEquipString(ItemStatus item)
\r
258 var name = item.Spec.Name;
\r
259 var attr = item.Level == 0 ? "" : "★" + item.Level;
\r
260 var proposed = new Size(int.MaxValue, int.MaxValue);
\r
261 var maxWidth = item.Spec.IsAircraft ? 132 : 180;
\r
262 var result = name + attr;
\r
263 if (TextRenderer.MeasureText(result, Font, proposed).Width <= maxWidth)
\r
265 var truncated = "";
\r
266 foreach (var ch in name)
\r
268 var tmp = truncated + ch;
\r
269 if (TextRenderer.MeasureText(tmp + attr, Font, proposed).Width > maxWidth)
\r
273 return truncated + attr;
\r
276 private void CreateLabels()
\r
278 for (var i = _labelList.Count; i < _table.Length; i++)
\r
282 private class FleetLabels : IEnumerable<ShipLabel>
\r
284 public ShipLabel Fleet { get; set; }
\r
285 public ShipLabel Name { get; set; }
\r
286 public ShipLabel Equip { get; set; }
\r
287 public ShipLabel EquipColor { get; set; }
\r
288 public ShipLabel Spec { get; set; }
\r
290 public IEnumerator<ShipLabel> GetEnumerator() =>
\r
291 ((IEnumerable<ShipLabel>)new[] {Fleet, Name, Equip, EquipColor, Spec}).GetEnumerator();
\r
293 IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
\r
296 private void CreateLabels(int i)
\r
298 var y = 1 + LineHeight * i;
\r
299 var lbp = new Panel
\r
301 Location = new Point(0, y),
\r
302 Size = new Size(ListForm.PanelWidth, LineHeight),
\r
303 BackColor = ShipLabel.ColumnColors[(i + 1) % 2],
\r
307 lbp.Tag = lbp.Location.Y;
\r
308 var labels = new FleetLabels
\r
310 Fleet = new ShipLabel {Location = new Point(1, 2), AutoSize = true},
\r
311 Name = new ShipLabel {Location = new Point(10, 2), AutoSize = true},
\r
312 Equip = new ShipLabel {Location = new Point(38, 2), AutoSize = true},
\r
313 EquipColor = new ShipLabel {Location = new Point(35, 2), Size = new Size(4, LabelHeight - 2)},
\r
314 Spec = new ShipLabel {Location = new Point(217, 2), AutoSize = true, AnchorRight = true}
\r
316 _labelList.Add(labels);
\r
317 _panelList.Add(lbp);
\r
318 lbp.Controls.AddRange(labels.Cast<Control>().ToArray());
\r
320 foreach (var label in labels)
\r
322 Scaler.Scale(label);
\r
323 label.BackColor = ShipLabel.ColumnColors[(i + 1) % 2];
\r
327 private void SetRecords()
\r
329 for (var i = 0; i < _table.Length; i++)
\r
331 for (var i = _table.Length; i < _labelList.Count; i++)
\r
332 _panelList[i].Visible = false;
\r
335 private void SetRecord(int i)
\r
337 var lbp = _panelList[i];
\r
339 lbp.Location = new Point(lbp.Left, (int)lbp.Tag + AutoScrollPosition.Y);
\r
341 var labels = _labelList[i];
\r
342 labels.Fleet.Text = e.Fleet;
\r
343 labels.Name.SetName(e.Ship);
\r
345 ToolTip.SetToolTip(labels.Name, e.Ship2);
\r
346 labels.Equip.Text = e.Equip;
\r
347 labels.EquipColor.Visible = e.Equip != "";
\r
348 labels.EquipColor.BackColor = e.Color;
\r
349 labels.Spec.Text = e.Spec;
\r
350 if (e.Fleet != "" && e.Fleet2 != "")
\r
351 ToolTip.SetToolTip(labels.Fleet, e.Fleet2);
\r
352 ToolTip.SetToolTip(labels.Equip, e.AircraftSpec != "" ? e.AircraftSpec : "");
\r
353 ToolTip.SetToolTip(labels.Spec, e.Spec2 != "" ? e.Spec2 : "");
\r
354 lbp.Visible = true;
\r
357 public void ShowShip(int id)
\r
359 var i = Array.FindIndex(_table, e => e.Id == id);
\r
362 var y = Scaler.ScaleHeight(LineHeight * i);
\r
363 AutoScrollPosition = new Point(0, y);
\r
366 public void ShowFleet(string fn)
\r
368 var i = Array.FindIndex(_table, e => e.Fleet.StartsWith(fn));
\r
371 var y = Scaler.ScaleHeight(LineHeight * i);
\r
372 AutoScrollPosition = new Point(0, y);
\r