1 // Copyright (C) 2018 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 static System.Math;
\r
18 namespace KancolleSniffer.Model
\r
20 public struct ChargeStatus
\r
22 public int Fuel { get; set; }
\r
23 public int Bull { get; set; }
\r
25 public ChargeStatus(ShipStatus status) : this()
\r
27 Fuel = CalcChargeState(status.Fuel, status.Spec.FuelMax);
\r
28 Bull = CalcChargeState(status.Bull, status.Spec.BullMax);
\r
31 public ChargeStatus(int fuel, int bull) : this()
\r
37 private int CalcChargeState(int now, int full)
\r
39 if (full == 0 || now == full)
\r
41 var ratio = (double)now / full;
\r
42 if (ratio >= 7.0 / 9)
\r
44 if (ratio >= 3.0 / 9)
\r
52 public enum FleetState
\r
60 public enum CombinedType
\r
70 private readonly ShipInfo _shipInfo;
\r
71 public int Number { get; }
\r
72 public FleetState State { get; set; }
\r
73 public CombinedType CombinedType { get; set; }
\r
74 public int[] Deck { get; set; } = Enumerable.Repeat(-1, ShipInfo.MemberCount).ToArray();
\r
75 public ShipStatus[] Ships => Deck.Where(id => id != -1).Select(_shipInfo.GetStatus).ToArray();
\r
77 public Fleet(ShipInfo shipInfo, int number)
\r
79 _shipInfo = shipInfo;
\r
83 public ChargeStatus ChargeStatus
\r
87 var fs = new ChargeStatus(_shipInfo.GetStatus(Deck[0]));
\r
88 var others = (from id in Deck.Skip(1) select new ChargeStatus(_shipInfo.GetStatus(id))).Aggregate(
\r
89 (result, next) => new ChargeStatus(Max(result.Fuel, next.Fuel), Max(result.Bull, next.Bull)));
\r
90 return new ChargeStatus(fs.Fuel != 0 ? fs.Fuel : others.Fuel + 5,
\r
91 fs.Bull != 0 ? fs.Bull : others.Bull + 5);
\r
95 public int[] FighterPower
\r
96 => Ships.Where(ship => !ship.Escaped).SelectMany(ship =>
\r
97 ship.Slot.Zip(ship.OnSlot, (slot, onslot) => slot.CalcFighterPower(onslot)))
\r
98 .Aggregate(new[] {0, 0}, (prev, cur) => new[] {prev[0] + cur[0], prev[1] + cur[1]});
\r
100 public double ContactTriggerRate
\r
101 => Ships.Where(ship => !ship.Escaped).SelectMany(ship =>
\r
102 ship.Slot.Zip(ship.OnSlot, (slot, onslot) =>
\r
103 slot.Spec.ContactTriggerRate * slot.Spec.LoS * Sqrt(onslot))).Sum();
\r
105 public double GetLineOfSights(int factor)
\r
108 var emptyBonus = 6;
\r
109 foreach (var s in Ships.Where(s => !s.Escaped))
\r
113 foreach (var item in s.Slot)
\r
115 var spec = item.Spec;
\r
116 itemLoS += spec.LoS;
\r
117 result += (spec.LoS + item.LoSLevelBonus) * spec.LoSScaleFactor * factor;
\r
119 result += Sqrt(s.LoS - itemLoS);
\r
121 return result > 0 ? result - Ceiling(_shipInfo.HqLevel * 0.4) + emptyBonus * 2 : 0.0;
\r
124 public double DaihatsuBonus
\r
128 var tokudaiBonus = new[,]
\r
130 {0.00, 0.00, 0.00, 0.00, 0.00},
\r
131 {0.02, 0.02, 0.02, 0.02, 0.02},
\r
132 {0.04, 0.04, 0.04, 0.04, 0.04},
\r
133 {0.05, 0.05, 0.052, 0.054, 0.054},
\r
134 {0.054, 0.056, 0.058, 0.059, 0.06}
\r
141 foreach (var ship in Ships)
\r
143 if (ship.Name == "鬼怒改二")
\r
145 foreach (var item in ship.Slot)
\r
147 switch (item.Spec.Name)
\r
150 level += item.Level;
\r
156 level += item.Level;
\r
161 case "大発動艇(八九式中戦車&陸戦隊)":
\r
162 level += item.Level;
\r
167 level += item.Level;
\r
174 var levelAverage = sum == 0 ? 0.0 : (double)level / sum;
\r
175 bonus = Min(bonus, 0.2);
\r
176 return bonus + 0.01 * bonus * levelAverage + tokudaiBonus[Min(tokudai, 4), Min(daihatsu, 4)];
\r
180 public double TransportPoint => Ships.Where(ship => !ship.Escaped).Sum(ship => ship.TransportPoint);
\r
182 public int CombinedFirepowerBonus
\r
186 switch (CombinedType)
\r
188 case CombinedType.None:
\r
190 case CombinedType.Carrier:
\r
191 return Number == 0 ? 2 : 10;
\r
192 case CombinedType.Surface:
\r
193 return Number == 0 ? 10 : -5;
\r
194 case CombinedType.Transport:
\r
195 return Number == 0 ? -5 : 10;
\r
202 public int CombinedTorpedoPenalty => CombinedType != 0 && Number == 1 ? -5 : 0;
\r