_battleInfo.InspectBattle(logs[0], logs[1], battle);\r
dynamic result = JsonParser.Parse(logs[5]);\r
_battleInfo.InspectBattleResult(result);\r
- PAssert.That(() => _shipInfo.GetShipStatuses(2)[4].NowHp == 31);\r
+ PAssert.That(() => _shipInfo.Fleets[2].Ships[4].NowHp == 31);\r
}\r
\r
/// <summary>\r
_shipInfo.InjectShips(battle, JsonParser.Parse(logs[0]));\r
_battleInfo.InspectBattle(logs[1], logs[2], battle);\r
_battleInfo.InspectBattleResult(JsonParser.Parse(logs[6]));\r
- PAssert.That(() => _shipInfo.GetShipStatuses(0)[3].NowHp == 12);\r
+ PAssert.That(() => _shipInfo.Fleets[0].Ships[3].NowHp == 12);\r
}\r
\r
private dynamic Data(string json) => ((dynamic)JsonParser.Parse(json)).api_data;\r
private void AssertEqualBattleResult(Sniffer sniffer, IEnumerable<int> expected, IEnumerable<int> enemy,\r
string msg = null)\r
{\r
- var result = sniffer.GetShipStatuses(0).Select(s => s.NowHp);\r
+ var result = sniffer.Fleets[0].Ships.Select(s => s.NowHp);\r
PAssert.That(() => expected.SequenceEqual(result), msg);\r
var enemyResult = sniffer.Battle.Result.Enemy.Main.Select(s => s.NowHp);\r
PAssert.That(() => enemy.SequenceEqual(enemyResult), msg);\r
{\r
var sniffer = new Sniffer();\r
SniffLogFile(sniffer, "escape_001");\r
- PAssert.That(() => sniffer.GetShipStatuses(0)[5].Escaped &&\r
- sniffer.GetShipStatuses(1)[2].Escaped);\r
+ var fleets = sniffer.Fleets;\r
+ PAssert.That(() => fleets[0].Ships[5].Escaped &&\r
+ fleets[1].Ships[2].Escaped);\r
}\r
\r
/// <summary>\r
{\r
var sniffer = new Sniffer();\r
SniffLogFile(sniffer, "escape_002");\r
- PAssert.That(() => sniffer.GetShipStatuses(2)[1].Escaped);\r
+ PAssert.That(() => sniffer.Fleets[2].Ships[1].Escaped);\r
PAssert.That(() => !sniffer.IsBattleResultStatusError);\r
}\r
\r
{\r
var sniffer = new Sniffer();\r
SniffLogFile(sniffer, "fighterpower_001");\r
- PAssert.That(() => sniffer.GetFighterPower(0).SequenceEqual(new[] {156, 159}));\r
+ var fleet = sniffer.Fleets[0];\r
+ PAssert.That(() => fleet.FighterPower.SequenceEqual(new[] {156, 159}));\r
SniffLogFile(sniffer, "fighterpower_002");\r
- PAssert.That(() => sniffer.GetFighterPower(0).SequenceEqual(new[] {140, 143}), "全滅したスロットがある");\r
+ PAssert.That(() => fleet.FighterPower.SequenceEqual(new[] {140, 143}), "全滅したスロットがある");\r
}\r
\r
/// <summary>\r
{\r
var sniffer = new Sniffer();\r
SniffLogFile(sniffer, "fighterpower_003");\r
- PAssert.That(() => sniffer.GetFighterPower(0).SequenceEqual(new[] {135, 135}));\r
+ PAssert.That(() => sniffer.Fleets[0].FighterPower.SequenceEqual(new[] {135, 135}));\r
}\r
\r
/// <summary>\r
{\r
var sniffer = new Sniffer();\r
SniffLogFile(sniffer, "lineofsight_001");\r
- PAssert.That(() => Math.Abs(sniffer.GetFleetLineOfSights(0, 1) - 39.45) < 0.01);\r
- PAssert.That(() => Math.Abs(sniffer.GetFleetLineOfSights(0, 3) - 115.19) < 0.01);\r
- PAssert.That(() => Math.Abs(sniffer.GetFleetLineOfSights(0, 4) - 153.06) < 0.01);\r
+ var fleet = sniffer.Fleets[0];\r
+ PAssert.That(() => Math.Abs(fleet.GetLineOfSights(1) - 39.45) < 0.01);\r
+ PAssert.That(() => Math.Abs(fleet.GetLineOfSights(3) - 115.19) < 0.01);\r
+ PAssert.That(() => Math.Abs(fleet.GetLineOfSights(4) - 153.06) < 0.01);\r
SniffLogFile(sniffer, "lineofsight_002");\r
- PAssert.That(() => Math.Abs(sniffer.GetFleetLineOfSights(0, 1) - -25.10) < 0.01, "艦隊に空きがある");\r
+ PAssert.That(() => Math.Abs(fleet.GetLineOfSights(1) - -25.10) < 0.01, "艦隊に空きがある");\r
}\r
\r
/// <summary>\r
{\r
var sniffer = new Sniffer();\r
SniffLogFile(sniffer, "contact_001");\r
- PAssert.That(() => Math.Abs(sniffer.GetContactTriggerRate(0) - 1.8182) < 0.0001);\r
+ PAssert.That(() => Math.Abs(sniffer.Fleets[0].ContactTriggerRate - 1.8182) < 0.0001);\r
}\r
\r
/// <summary>\r
var sniffer = new Sniffer();\r
SniffLogFile(sniffer, "transportpoint_00" + (i + 1));\r
var j = i;\r
- PAssert.That(() => (int)sniffer.GetShipStatuses(0).Sum(s => s.TransportPoint) == results[j], msgs[j]);\r
+ PAssert.That(() => (int)sniffer.Fleets[0].TransportPoint == results[j], msgs[j]);\r
}\r
}\r
\r
{\r
var sniffer = new Sniffer();\r
SniffLogFile(sniffer, "antiairfire_001");\r
- var ships = sniffer.GetShipStatuses(0);\r
+ var ships = sniffer.Fleets[0].Ships;\r
PAssert.That(() => ships.Sum(ship => ship.EffectiveAntiAirForFleet) == 88);\r
PAssert.That(\r
() =>\r
{\r
var sniffer = new Sniffer();\r
SniffLogFile(sniffer, "nightbattlepower_001");\r
- var ships = sniffer.GetShipStatuses(0);\r
+ var ships = sniffer.Fleets[0].Ships;\r
PAssert.That(() =>\r
ships.Select(ship => (int)(ship.NightBattlePower * 100))\r
.SequenceEqual(new[] {11202, 14985, 20092, 17354}));\r
{\r
var sniffer = new Sniffer();\r
SniffLogFile(sniffer, "firepower_001");\r
+ var fleet = sniffer.Fleets[0];\r
// ReSharper disable CompareOfFloatsByEqualityOperator\r
- PAssert.That(() => sniffer.GetShipStatuses(0)[0].EffectiveFirepower == 93.5);\r
- PAssert.That(() => sniffer.GetShipStatuses(0)[1].EffectiveFirepower == 82.5);\r
+ PAssert.That(() => fleet.Ships[0].EffectiveFirepower == 93.5);\r
+ PAssert.That(() => fleet.Ships[1].EffectiveFirepower == 82.5);\r
// ReSharper restore CompareOfFloatsByEqualityOperator\r
}\r
\r
{\r
var sniffer = new Sniffer();\r
SniffLogFile(sniffer, "slot_exchange_001");\r
- var result = sniffer.GetShipStatuses(0)[0].Slot.Select(item => item.Id);\r
+ var result = sniffer.Fleets[0].Ships[0].Slot.Select(item => item.Id);\r
PAssert.That(() => new[] {26096, 30571, 77694, 61383, -1}.SequenceEqual(result));\r
}\r
\r
{\r
var sniffer = new Sniffer();\r
SniffLogFile(sniffer, "powerup_001");\r
- PAssert.That(() => Math.Abs(sniffer.GetShipStatuses(0)[0].EffectiveFirepower - 30) < 0.0001);\r
+ PAssert.That(() => Math.Abs(sniffer.Fleets[0].Ships[0].EffectiveFirepower - 30) < 0.0001);\r
}\r
\r
/// <summary>\r
var sniffer = new Sniffer(true);\r
SniffLogFile(sniffer, "twofleets_001");\r
var expected = Enumerable.Repeat(new ChargeStatus(5, 5), ShipInfo.FleetCount);\r
- PAssert.That(() => expected.SequenceEqual(sniffer.ChargeStatuses));\r
+ PAssert.That(() => expected.SequenceEqual(sniffer.Fleets.Select(f => f.ChargeStatus)));\r
}\r
\r
/// <summary>\r
var fn = new[] {"第一艦隊", "第二艦隊", "第三艦隊", "第四艦隊"};\r
for (var f = 0; f < fn.Length; f++)\r
{\r
- var ships = sniffer.GetShipStatuses(f);\r
+ var ships = sniffer.Fleets[f].Ships;\r
var rawForFleet = ships.Sum(ship => ship.EffectiveAntiAirForFleet);\r
var forFleet = new[] {1.0, 1.2, 1.6}.Select(r => (int)(rawForFleet * r) * 2 / 1.3).ToArray();\r
_table.Add(new Record {Fleet = fn[f] + " : " + string.Join("/", forFleet.Select(x => x.ToString("f1")))});\r
return;\r
_shipInfo.SaveBattleStartStatus();\r
_fleet = DeckId(json);\r
- var fstats = _shipInfo.GetShipStatuses(_fleet);\r
+ var fleets = _shipInfo.Fleets;\r
+ var fstats = fleets[_fleet].Ships;\r
FlagshipRecovery(request, fstats[0]);\r
_friend = Record.Setup(fstats, practice);\r
_guard = json.api_f_nowhps_combined()\r
- ? Record.Setup(_shipInfo.GetShipStatuses(1), practice)\r
+ ? Record.Setup(fleets[1].Ships, practice)\r
: new Record[0];\r
_enemy = Record.Setup((int[])json.api_e_nowhps,\r
((int[])json.api_ship_ke).Select(_shipInfo.GetSpec).ToArray(),\r
\r
private int[] CalcFighterPower()\r
{\r
+ var fleets = _shipInfo.Fleets;\r
if (_guard.Length > 0 && _enemyGuard.Length > 0)\r
- return _shipInfo.GetFighterPower(0).Zip(_shipInfo.GetFighterPower(1), (a, b) => a + b).ToArray();\r
- return _shipInfo.GetFighterPower(_fleet);\r
+ return fleets[0].FighterPower.Zip(fleets[1].FighterPower, (a, b) => a + b).ToArray();\r
+ return fleets[_fleet].FighterPower;\r
}\r
\r
private EnemyFighterPower CalcEnemyFighterPower(dynamic json)\r
{\r
if (_friend == null)\r
return;\r
+ var fleets = _shipInfo.Fleets;\r
var ships = _guard.Length > 0\r
- ? _shipInfo.GetShipStatuses(0).Concat(_shipInfo.GetShipStatuses(1)).ToArray()\r
- : _shipInfo.GetShipStatuses(_fleet);\r
+ ? fleets[0].Ships.Concat(fleets[1].Ships)\r
+ : fleets[_fleet].Ships;\r
foreach (var entry in ships.Zip(_friend.Concat(_guard), (ship, now) => new {ship, now}))\r
entry.now.UpdateShipStatus(entry.ship);\r
if (warnDamagedShip)\r
\r
public DateTime GetTimer(int fleet)\r
{\r
- if (_shipInfo.Fleets[fleet].State != FleetState.Port)\r
+ var target = _shipInfo.Fleets[fleet];\r
+ if (target.State != FleetState.Port)\r
return DateTime.MinValue;\r
- var cond = _shipInfo.GetShipStatuses(fleet).Select(s => s.Cond).DefaultIfEmpty(49).Min();\r
+ var cond = target.Ships.Select(s => s.Cond).DefaultIfEmpty(49).Min();\r
if (cond >= 49)\r
return DateTime.MinValue;\r
var nextRegen = NextRegenTime(_lastUpdate);\r
--- /dev/null
+// Copyright (C) 2018 Kazuhiro Fujieda <fujieda@users.osdn.me>\r
+//\r
+// Licensed under the Apache License, Version 2.0 (the "License");\r
+// you may not use this file except in compliance with the License.\r
+// You may obtain a copy of the License at\r
+//\r
+// http://www.apache.org/licenses/LICENSE-2.0\r
+//\r
+// Unless required by applicable law or agreed to in writing, software\r
+// distributed under the License is distributed on an "AS IS" BASIS,\r
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+// See the License for the specific language governing permissions and\r
+// limitations under the License.\r
+\r
+using System.Collections.Generic;\r
+using System.Linq;\r
+using static System.Math;\r
+\r
+namespace KancolleSniffer\r
+{\r
+ public struct ChargeStatus\r
+ {\r
+ public int Fuel { get; set; }\r
+ public int Bull { get; set; }\r
+\r
+ public ChargeStatus(ShipStatus status) : this()\r
+ {\r
+ Fuel = CalcChargeState(status.Fuel, status.Spec.FuelMax);\r
+ Bull = CalcChargeState(status.Bull, status.Spec.BullMax);\r
+ }\r
+\r
+ public ChargeStatus(int fuel, int bull) : this()\r
+ {\r
+ Fuel = fuel;\r
+ Bull = bull;\r
+ }\r
+\r
+ private int CalcChargeState(int now, int full)\r
+ {\r
+ if (full == 0 || now == full)\r
+ return 0;\r
+ var ratio = (double)now / full;\r
+ if (ratio >= 7.0 / 9)\r
+ return 1;\r
+ if (ratio >= 3.0 / 9)\r
+ return 2;\r
+ if (ratio > 0)\r
+ return 3;\r
+ return 4;\r
+ }\r
+ }\r
+\r
+ public enum FleetState\r
+ {\r
+ Port,\r
+ Mission,\r
+ Sortie,\r
+ Practice\r
+ }\r
+\r
+ public class Fleet\r
+ {\r
+ private readonly ShipInfo _shipInfo;\r
+ public FleetState State { get; set; }\r
+ public int[] Deck { get; set; } = Enumerable.Repeat(-1, ShipInfo.MemberCount).ToArray();\r
+ public ShipStatus[] Ships => Deck.Where(id => id != -1).Select(_shipInfo.GetStatus).ToArray();\r
+\r
+ public Fleet(ShipInfo shipInfo)\r
+ {\r
+ _shipInfo = shipInfo;\r
+ }\r
+\r
+ public ChargeStatus ChargeStatus\r
+ {\r
+ get\r
+ {\r
+ var fs = new ChargeStatus(_shipInfo.GetStatus(Deck[0]));\r
+ var others = (from id in Deck.Skip(1) select new ChargeStatus(_shipInfo.GetStatus(id))).Aggregate(\r
+ (result, next) => new ChargeStatus(Max(result.Fuel, next.Fuel), Max(result.Bull, next.Bull)));\r
+ return new ChargeStatus(fs.Fuel != 0 ? fs.Fuel : others.Fuel + 5, fs.Bull != 0 ? fs.Bull : others.Bull + 5);\r
+ }\r
+ }\r
+\r
+ public int[] FighterPower\r
+ => Ships.Where(ship => !ship.Escaped).SelectMany(ship =>\r
+ ship.Slot.Zip(ship.OnSlot, (slot, onslot) => slot.CalcFighterPower(onslot)))\r
+ .Aggregate(new[] {0, 0}, (prev, cur) => new[] {prev[0] + cur[0], prev[1] + cur[1]});\r
+\r
+ public double ContactTriggerRate\r
+ => Ships.Where(ship => !ship.Escaped).SelectMany(ship =>\r
+ ship.Slot.Zip(ship.OnSlot, (slot, onslot) =>\r
+ slot.Spec.ContactTriggerRate * slot.Spec.LoS * Sqrt(onslot))).Sum();\r
+\r
+ public double GetLineOfSights(int factor)\r
+ {\r
+ var result = 0.0;\r
+ var emptyBonus = 6;\r
+ foreach (var s in Ships.Where(s => !s.Escaped))\r
+ {\r
+ emptyBonus--;\r
+ var itemLoS = 0;\r
+ foreach (var item in s.Slot)\r
+ {\r
+ var spec = item.Spec;\r
+ itemLoS += spec.LoS;\r
+ result += (spec.LoS + item.LoSLevelBonus) * spec.LoSScaleFactor * factor;\r
+ }\r
+ result += Sqrt(s.LoS - itemLoS);\r
+ }\r
+ return result > 0 ? result - Ceiling(_shipInfo.HqLevel * 0.4) + emptyBonus * 2 : 0.0;\r
+ }\r
+\r
+ public double DaihatsuBonus\r
+ {\r
+ get\r
+ {\r
+ var tokudaiBonus = new[,]\r
+ {\r
+ {0.00, 0.00, 0.00, 0.00, 0.00},\r
+ {0.02, 0.02, 0.02, 0.02, 0.02},\r
+ {0.04, 0.04, 0.04, 0.04, 0.04},\r
+ {0.05, 0.05, 0.052, 0.054, 0.054},\r
+ {0.054, 0.056, 0.058, 0.059, 0.06}\r
+ };\r
+ var daihatsu = 0;\r
+ var tokudai = 0;\r
+ var bonus = 0.0;\r
+ var level = 0;\r
+ var sum = 0;\r
+ foreach (var ship in Ships)\r
+ {\r
+ if (ship.Name == "鬼怒改二")\r
+ bonus += 0.05;\r
+ foreach (var item in ship.Slot)\r
+ {\r
+ switch (item.Spec.Name)\r
+ {\r
+ case "大発動艇":\r
+ level += item.Level;\r
+ sum++;\r
+ daihatsu++;\r
+ bonus += 0.05;\r
+ break;\r
+ case "特大発動艇":\r
+ level += item.Level;\r
+ sum++;\r
+ tokudai++;\r
+ bonus += 0.05;\r
+ break;\r
+ case "大発動艇(八九式中戦車&陸戦隊)":\r
+ level += item.Level;\r
+ sum++;\r
+ bonus += 0.02;\r
+ break;\r
+ case "特二式内火艇":\r
+ level += item.Level;\r
+ sum++;\r
+ bonus += 0.01;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ var levelAverage = sum == 0 ? 0.0 : (double)level / sum;\r
+ bonus = Min(bonus, 0.2);\r
+ return bonus + 0.01 * bonus * levelAverage + tokudaiBonus[Min(tokudai, 4), Min(daihatsu, 4)];\r
+ }\r
+ }\r
+\r
+ public double TransportPoint => Ships.Where(ship => !ship.Escaped).Sum(ship => ship.TransportPoint);\r
+ }\r
+}
\ No newline at end of file
private void CreateTable(Sniffer sniffer)\r
{\r
var list = new List<Record>();\r
+ var fleets = sniffer.Fleets;\r
var fn = new[] {"第一", "第二", "第三", "第四"};\r
for (var f = 0; f < fn.Length; f++)\r
{\r
var total = new Total();\r
var ships = new List<Record>();\r
- foreach (var s in sniffer.GetShipStatuses(f))\r
+ var fleet = fleets[f];\r
+ foreach (var s in fleet.Ships)\r
{\r
var equips = new List<Record>();\r
for (var i = 0; i < s.Slot.Length; i++)\r
ships.Add(ship);\r
ships.AddRange(equips);\r
}\r
- var daihatsu = sniffer.GetDaihatsuBonus(f);\r
- var tp = sniffer.GetTransportPoint(f);\r
+ var daihatsu = fleet.DaihatsuBonus;\r
+ var tp = fleet.TransportPoint;\r
if (sniffer.CombinedFleetType != 0 && f == 0)\r
- tp += sniffer.GetTransportPoint(1);\r
+ tp += fleets[1].TransportPoint;\r
list.Add(new Record\r
{\r
Fleet = fn[f] + HideIfZero(" Lv", total.Level) +\r
</Compile>\r
<Compile Include="CUDColor.cs" />\r
<Compile Include="DockInfo.cs" />\r
+ <Compile Include="Fleet.cs" />\r
<Compile Include="FleetPanel.cs">\r
<SubType>Component</SubType>\r
</Compile>\r
else\r
dropName += "+" + itemName;\r
}\r
- var fp = _shipInfo.GetFighterPower(BattleInfo.DeckId(_battle));\r
+ var fp = _shipInfo.Fleets[BattleInfo.DeckId(_battle)].FighterPower;\r
var fpower = fp[0] == fp[1] ? fp[0].ToString() : fp[0] + "~" + fp[1];\r
_writer("海戦・ドロップ報告書", string.Join(",", FormatDateTime(_nowFunc()),\r
result.api_quest_name,\r
\r
private string Secretary()\r
{\r
- var ship = _shipInfo.GetShipStatuses(0)[0];\r
+ var ship = _shipInfo.Fleets[0].Ships[0];\r
return ship.Name + "(" + ship.Level + ")";\r
}\r
\r
diff[i] = _currentMaterial[i] - after[i];\r
var ship1 = Secretary();\r
var ship2 = "";\r
- var ships = _shipInfo.GetShipStatuses(0);\r
+ var ships = _shipInfo.Fleets[0].Ships;\r
if (ships.Length >= 2)\r
ship2 = ships[1].Name + "(" + ships[1].Level + ")";\r
_writer("改修報告書",\r
if (!_listForm.Visible)\r
return;\r
var idx = (int)((Control)sender).Tag;\r
- var statuses = _sniffer.GetShipStatuses(_currentFleet);\r
- if (statuses.Length <= idx)\r
+ var ships = _sniffer.Fleets[_currentFleet].Ships;\r
+ if (ships.Length <= idx)\r
return;\r
- _listForm.ShowShip(statuses[idx].Id);\r
+ _listForm.ShowShip(ships[idx].Id);\r
}\r
\r
private void UpdateItemInfo()\r
\r
private void UpdatePanelShipInfo()\r
{\r
- var statuses = _sniffer.GetShipStatuses(_currentFleet);\r
- panel7Ships.Visible = statuses.Length == 7;\r
- _mainLabels.SetShipLabels(statuses);\r
+ var fleets = _sniffer.Fleets;\r
+ var ships = fleets[_currentFleet].Ships;\r
+ panel7Ships.Visible = ships.Length == 7;\r
+ _mainLabels.SetShipLabels(ships);\r
if (_sniffer.CombinedFleetType == 0)\r
_combinedFleet = false;\r
labelFleet1.Text = _combinedFleet ? "連合" : "第一";\r
panelCombinedFleet.Visible = _combinedFleet;\r
if (_combinedFleet)\r
- _mainLabels.SetCombinedShipLabels(_sniffer.GetShipStatuses(0), _sniffer.GetShipStatuses(1));\r
+ _mainLabels.SetCombinedShipLabels(fleets[0].Ships, fleets[1].Ships);\r
for (var i = 0; i < _labelCheckFleets.Length; i++)\r
_labelCheckFleets[i].Visible = _currentFleet == i;\r
UpdateAkashiTimer();\r
\r
public void UpdateFighterPower(bool combined)\r
{\r
+ var fleets = _sniffer.Fleets;\r
var fp = combined\r
- ? _sniffer.GetFighterPower(0).Zip(_sniffer.GetFighterPower(1), (a, b) => a + b).ToArray()\r
- : _sniffer.GetFighterPower(_currentFleet);\r
+ ? fleets[0].FighterPower.Zip(fleets[1].FighterPower, (a, b) => a + b).ToArray()\r
+ : fleets[_currentFleet].FighterPower;\r
labelFighterPower.Text = fp[0].ToString("D");\r
var cr = combined\r
- ? _sniffer.GetContactTriggerRate(0) + _sniffer.GetContactTriggerRate(1)\r
- : _sniffer.GetContactTriggerRate(_currentFleet);\r
+ ? fleets[0].ContactTriggerRate + fleets[1].ContactTriggerRate\r
+ : fleets[_currentFleet].ContactTriggerRate;\r
var text = "制空: " + (fp[0] == fp[1] ? $"{fp[0]}" : $"{fp[0]}~{fp[1]}") +\r
$" 触接: {cr * 100:f1}";\r
_toolTip.SetToolTip(labelFighterPower, text);\r
\r
private void UpdateLoS()\r
{\r
- labelLoS.Text = RoundDown(_sniffer.GetFleetLineOfSights(_currentFleet, 1)).ToString("F1");\r
- var text = $"係数3: {RoundDown(_sniffer.GetFleetLineOfSights(_currentFleet, 3)):F1}\r\n" +\r
- $"係数4: {RoundDown(_sniffer.GetFleetLineOfSights(_currentFleet, 4)):F1}";\r
+ var fleet = _sniffer.Fleets[_currentFleet];\r
+ labelLoS.Text = RoundDown(fleet.GetLineOfSights(1)).ToString("F1");\r
+ var text = $"係数3: {RoundDown(fleet.GetLineOfSights(3)):F1}\r\n" +\r
+ $"係数4: {RoundDown(fleet.GetLineOfSights(4)):F1}";\r
_toolTip.SetToolTip(labelLoS, text);\r
_toolTip.SetToolTip(labelLoSCaption, text);\r
}\r
\r
for (var i = 0; i < fuelSq.Length; i++)\r
{\r
- var stat = _sniffer.ChargeStatuses[i];\r
+ var stat = _sniffer.Fleets[i].ChargeStatus;\r
fuelSq[i].ImageIndex = stat.Fuel;\r
bullSq[i].ImageIndex = stat.Bull;\r
}\r
{\r
if (_config.UsePresetAkashi)\r
UpdatePresetAkashiTimer();\r
- var statuses = _sniffer.GetShipStatuses(_currentFleet);\r
- _mainLabels.SetAkashiTimer(statuses,\r
+ _mainLabels.SetAkashiTimer(_sniffer.Fleets[_currentFleet].Ships,\r
_sniffer.AkashiTimer.GetTimers(_currentFleet));\r
}\r
\r
var raw = _expTable[Min(s1, _expTable.Length) - 1] / 100.0 +\r
_expTable[Min(s2, _expTable.Length) - 1] / 300.0;\r
var exp = raw >= 500 ? 500 + (int)Sqrt(raw - 500) : (int)raw;\r
- var bonus = 1 + TrainingCruiserBonus(_shipInfo.GetShipStatuses(0));\r
+ var bonus = 1 + TrainingCruiserBonus(_shipInfo.Fleets[0].Ships);\r
Text += $"獲得経験値 : {(int)(exp * bonus)}\r\nS勝利 : {(int)((int)(exp * 1.2) * bonus)}";\r
}\r
\r
\r
namespace KancolleSniffer\r
{\r
- public struct ChargeStatus\r
- {\r
- public int Fuel { get; set; }\r
- public int Bull { get; set; }\r
-\r
- public ChargeStatus(ShipStatus status) : this()\r
- {\r
- Fuel = CalcChargeState(status.Fuel, status.Spec.FuelMax);\r
- Bull = CalcChargeState(status.Bull, status.Spec.BullMax);\r
- }\r
-\r
- public ChargeStatus(int fuel, int bull) : this()\r
- {\r
- Fuel = fuel;\r
- Bull = bull;\r
- }\r
-\r
- private int CalcChargeState(int now, int full)\r
- {\r
- if (full == 0 || now == full)\r
- return 0;\r
- var ratio = (double)now / full;\r
- if (ratio >= 7.0 / 9)\r
- return 1;\r
- if (ratio >= 3.0 / 9)\r
- return 2;\r
- if (ratio > 0)\r
- return 3;\r
- return 4;\r
- }\r
- }\r
-\r
- public enum FleetState\r
- {\r
- Port,\r
- Mission,\r
- Sortie,\r
- Practice\r
- }\r
-\r
- public class Fleet\r
- {\r
- public FleetState State { get; set; }\r
- public int[] Deck { get; set; } = Enumerable.Repeat(-1, ShipInfo.MemberCount).ToArray();\r
- }\r
\r
public class ShipInfo\r
{\r
public const int FleetCount = 4;\r
public const int MemberCount = 6;\r
\r
- private readonly Fleet[] _fleets = Enumerable.Range(0, FleetCount).Select(x => new Fleet()).ToArray();\r
+ private readonly Fleet[] _fleets;\r
private readonly Dictionary<int, ShipStatus> _shipInfo = new Dictionary<int, ShipStatus>();\r
private readonly ShipMaster _shipMaster = new ShipMaster();\r
private readonly ItemInfo _itemInfo;\r
- private int _hqLevel;\r
private readonly List<int> _escapedShips = new List<int>();\r
private int _combinedFleetType;\r
private ShipStatus[] _battleResult = new ShipStatus[0];\r
+ public int HqLevel { get; private set; }\r
public ShipStatusPair[] BattleResultDiff { get; private set; } = new ShipStatusPair[0];\r
public bool IsBattleResultError => BattleResultDiff.Length > 0;\r
public ShipStatus[] BattleStartStatus { get; private set; } = new ShipStatus[0];\r
\r
public ShipInfo(ItemInfo itemInfo)\r
{\r
+ _fleets = Enumerable.Range(0, FleetCount).Select(x => new Fleet(this)).ToArray();\r
_itemInfo = itemInfo;\r
ClearShipInfo();\r
}\r
\r
private void InspectBasic(dynamic json)\r
{\r
- _hqLevel = (int)json.api_level;\r
+ HqLevel = (int)json.api_level;\r
}\r
\r
public void InspectCharge(dynamic json)\r
s.Cond = Max(40, s.Cond);\r
}\r
\r
- public ShipStatus[] GetShipStatuses(int fleet)\r
- {\r
- return _fleets[fleet].Deck.Where(id => id != -1).Select(GetStatus).ToArray();\r
- }\r
-\r
public Fleet[] Fleets => _fleets;\r
\r
public ShipStatus GetStatus(int id)\r
\r
public ShipStatus[] ShipList => _shipInfo.Keys.Where(id => id != -1).Select(GetStatus).ToArray();\r
\r
- public ChargeStatus[] ChargeStatuses\r
- => (from fleet in _fleets\r
- let flag = new ChargeStatus(_shipInfo[fleet.Deck[0]])\r
- let others = (from id in fleet.Deck.Skip(1)\r
- select new ChargeStatus(_shipInfo[id]))\r
- .Aggregate(\r
- (result, next) =>\r
- new ChargeStatus(Max(result.Fuel, next.Fuel), Max(result.Bull, next.Bull)))\r
- select new ChargeStatus(flag.Fuel != 0 ? flag.Fuel : others.Fuel + 5,\r
- flag.Bull != 0 ? flag.Bull : others.Bull + 5)).ToArray();\r
-\r
- public int[] GetFighterPower(int fleet)\r
- => GetShipStatuses(fleet).Where(ship => !ship.Escaped).SelectMany(ship =>\r
- ship.Slot.Zip(ship.OnSlot, (slot, onslot) => slot.CalcFighterPower(onslot)))\r
- .Aggregate(new[] {0, 0}, (prev, cur) => new[] {prev[0] + cur[0], prev[1] + cur[1]});\r
-\r
- public double GetContactTriggerRate(int fleet)\r
- => GetShipStatuses(fleet).Where(ship => !ship.Escaped).SelectMany(ship =>\r
- ship.Slot.Zip(ship.OnSlot, (slot, onslot) =>\r
- slot.Spec.ContactTriggerRate * slot.Spec.LoS * Sqrt(onslot))).Sum();\r
-\r
public ShipStatus[] GetRepairList(DockInfo dockInfo)\r
=> (from s in ShipList\r
where s.NowHp < s.MaxHp && !dockInfo.InNDock(s.Id)\r
select s).OrderByDescending(s => s.RepairTime).ToArray();\r
\r
- public double GetLineOfSights(int fleet, int factor)\r
- {\r
- var result = 0.0;\r
- var emptyBonus = 6;\r
- foreach (var s in GetShipStatuses(fleet).Where(s => !s.Escaped))\r
- {\r
- emptyBonus--;\r
- var itemLoS = 0;\r
- foreach (var item in s.Slot)\r
- {\r
- var spec = item.Spec;\r
- itemLoS += spec.LoS;\r
- result += (spec.LoS + item.LoSLevelBonus) * spec.LoSScaleFactor * factor;\r
- }\r
- result += Sqrt(s.LoS - itemLoS);\r
- }\r
- return result > 0 ? result - Ceiling(_hqLevel * 0.4) + emptyBonus * 2 : 0.0;\r
- }\r
-\r
- public double GetDaihatsuBonus(int fleet)\r
- {\r
- var tokudaiBonus = new[,]\r
- {\r
- {0.00, 0.00, 0.00, 0.00, 0.00},\r
- {0.02, 0.02, 0.02, 0.02, 0.02},\r
- {0.04, 0.04, 0.04, 0.04, 0.04},\r
- {0.05, 0.05, 0.052, 0.054, 0.054},\r
- {0.054, 0.056, 0.058, 0.059, 0.06}\r
- };\r
- var daihatsu = 0;\r
- var tokudai = 0;\r
- var bonus = 0.0;\r
- var level = 0;\r
- var sum = 0;\r
- foreach (var ship in GetShipStatuses(fleet))\r
- {\r
- if (ship.Name == "鬼怒改二")\r
- bonus += 0.05;\r
- foreach (var item in ship.Slot)\r
- {\r
- switch (item.Spec.Name)\r
- {\r
- case "大発動艇":\r
- level += item.Level;\r
- sum++;\r
- daihatsu++;\r
- bonus += 0.05;\r
- break;\r
- case "特大発動艇":\r
- level += item.Level;\r
- sum++;\r
- tokudai++;\r
- bonus += 0.05;\r
- break;\r
- case "大発動艇(八九式中戦車&陸戦隊)":\r
- level += item.Level;\r
- sum++;\r
- bonus += 0.02;\r
- break;\r
- case "特二式内火艇":\r
- level += item.Level;\r
- sum++;\r
- bonus += 0.01;\r
- break;\r
- }\r
- }\r
- }\r
- var levelAverage = sum == 0 ? 0.0 : (double)level / sum;\r
- bonus = Min(bonus, 0.2);\r
- return bonus + 0.01 * bonus * levelAverage + tokudaiBonus[Min(tokudai, 4), Min(daihatsu, 4)];\r
- }\r
-\r
- public double GetTransportPoint(int fleet)\r
- {\r
- return GetShipStatuses(fleet).Where(ship => !ship.Escaped).Sum(ship => ship.TransportPoint);\r
- }\r
-\r
public string[] BadlyDamagedShips { get; private set; } = new string[0];\r
\r
public void SetBadlyDamagedShips()\r
\r
public int[] GetConditionNotice(DateTime prev, DateTime now) => _conditionTimer.GetNotice(prev, now);\r
\r
- public ShipStatus[] GetShipStatuses(int fleet) => _shipInfo.GetShipStatuses(fleet);\r
-\r
public Fleet[] Fleets => _shipInfo.Fleets;\r
\r
public ShipInfo.ShipStatusPair[] BattleResultStatusDiff => _shipInfo.BattleResultDiff;\r
\r
public int CombinedFleetType => _shipInfo.CombinedFleetType;\r
\r
- public ChargeStatus[] ChargeStatuses => _shipInfo.ChargeStatuses;\r
-\r
- public int[] GetFighterPower(int fleet) => _shipInfo.GetFighterPower(fleet);\r
-\r
- public double GetContactTriggerRate(int fleet) => _shipInfo.GetContactTriggerRate(fleet);\r
-\r
- public double GetFleetLineOfSights(int fleet, int factor) => _shipInfo.GetLineOfSights(fleet, factor);\r
-\r
public ShipStatus[] RepairList => _shipInfo.GetRepairList(_dockInfo);\r
\r
public ShipStatus[] ShipList => _shipInfo.ShipList;\r
\r
public string[] BadlyDamagedShips => _shipInfo.BadlyDamagedShips;\r
\r
- public double GetDaihatsuBonus(int fleet) => _shipInfo.GetDaihatsuBonus(fleet);\r
-\r
- public double GetTransportPoint(int fleet) => _shipInfo.GetTransportPoint(fleet);\r
-\r
public ItemStatus[] ItemList\r
{\r
get\r
\r
private static StringBuilder GenerateFleetData(Sniffer sniffer, int fleet, ItemName dict)\r
{\r
+ var target = sniffer.Fleets[fleet];\r
var sb = new StringBuilder();\r
var fn = new[] {"第一艦隊", "第二艦隊", "第三艦隊", "第四艦隊"};\r
sb.Append(fn[fleet] + "\r\n");\r
- sb.Append(string.Concat(from s in sniffer.GetShipStatuses(fleet)\r
+ sb.Append(string.Concat(from s in target.Ships\r
select ($"{s.Name} Lv{s.Level} " +\r
string.Join(",",\r
from item in s.AllSlot\r
where item.Id != -1\r
select dict[item.Spec.Name] + ItemStatusString(item))).TrimEnd(' ') + "\r\n"));\r
- var fp = sniffer.GetFighterPower(fleet);\r
+ var fp = target.FighterPower;\r
sb.Append($"制空: {(fp[0] == fp[1] ? fp[0].ToString() : fp[0] + "~" + fp[1])} " +\r
- $"索敵: {sniffer.GetFleetLineOfSights(fleet, 1):F1}\r\n");\r
+ $"索敵: {target.GetLineOfSights(1):F1}\r\n");\r
return sb;\r
}\r
\r
if (f != 0)\r
sb.Append(",");\r
sb.Append($"\"f{f + 1}\":{{");\r
- var ships = sniffer.GetShipStatuses(f);\r
+ var ships = sniffer.Fleets[f].Ships;\r
for (var s = 0; s < ships.Length; s++)\r
{\r
if (s != 0)\r