\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 class ShipInfo\r
{\r
public const int FleetCount = 4;\r
public const int MemberCount = 6;\r
\r
- private readonly int[][] _decks;\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 readonly bool[] _inMission = new bool[FleetCount];\r
- private readonly bool[] _inSortie = new bool[FleetCount];\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
- _decks = Enumerable.Repeat(Enumerable.Repeat(-1, MemberCount).ToArray(), FleetCount).ToArray();\r
ClearShipInfo();\r
}\r
\r
{\r
ClearShipInfo();\r
for (var i = 0; i < FleetCount; i++)\r
- _inSortie[i] = false;\r
+ _fleets[i].State = FleetState.Port;\r
InspectDeck(json.api_deck_port);\r
InspectShipData(json.api_ship);\r
InspectBasic(json.api_basic);\r
\r
public void SaveBattleResult()\r
{\r
- _battleResult = _decks.Where((deck, i) =>\r
- _inSortie[i] && !GetStatus(deck[0]).Spec.IsRepairShip)\r
- .SelectMany(deck => deck.Select(GetStatus)).ToArray();\r
+ _battleResult = _fleets.Where(fleet =>\r
+ fleet.State >= FleetState.Sortie && !GetStatus(fleet.Deck[0]).Spec.IsRepairShip)\r
+ .SelectMany(fleet => fleet.Deck.Select(GetStatus)).ToArray();\r
}\r
\r
private void VerifyBattleResult()\r
\r
public void SaveBattleStartStatus()\r
{\r
- BattleStartStatus = _decks.Where((deck, i) => _inSortie[i])\r
- .SelectMany(deck => deck.Select(id => (ShipStatus)GetStatus(id).Clone())).ToArray();\r
+ BattleStartStatus = _fleets.Where(fleet => fleet.State >= FleetState.Sortie)\r
+ .SelectMany(fleet => fleet.Deck.Select(id => (ShipStatus)GetStatus(id).Clone())).ToArray();\r
}\r
\r
private void ClearShipInfo()\r
foreach (var entry in json)\r
{\r
var fleet = (int)entry.api_id - 1;\r
- _decks[fleet] = (int[])entry.api_ship;\r
- _inMission[fleet] = (int)entry.api_mission[0] != 0;\r
+ _fleets[fleet].Deck = (int[])entry.api_ship;\r
+ if ((int)entry.api_mission[0] != 0)\r
+ _fleets[fleet].State = FleetState.Mission;\r
}\r
}\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
var ship = int.Parse(values["api_ship_id"]);\r
if (idx == -1)\r
{\r
- var deck = _decks[fleet];\r
+ var deck = _fleets[fleet].Deck;\r
for (var i = 1; i < deck.Length; i++)\r
deck[i] = -1;\r
return;\r
return;\r
}\r
var of = FindFleet(ship, out var oi);\r
- var orig = _decks[fleet][idx];\r
- _decks[fleet][idx] = ship;\r
+ var orig = _fleets[fleet].Deck[idx];\r
+ _fleets[fleet].Deck[idx] = ship;\r
if (of == -1)\r
return;\r
// 入れ替えの場合\r
- if ((_decks[of][oi] = orig) == -1)\r
+ if ((_fleets[of].Deck[oi] = orig) == -1)\r
WithdrowShip(of, oi);\r
}\r
\r
private int FindFleet(int ship, out int idx)\r
{\r
- for (var f = 0; f < _decks.Length; f++)\r
+ for (var f = 0; f < _fleets.Length; f++)\r
{\r
- idx = Array.FindIndex(_decks[f], id => id == ship);\r
+ idx = Array.FindIndex(_fleets[f].Deck, id => id == ship);\r
if (idx < 0)\r
continue;\r
return f;\r
\r
private void WithdrowShip(int fleet, int idx)\r
{\r
- var deck = _decks[fleet];\r
+ var deck = _fleets[fleet].Deck;\r
var j = idx;\r
for (var i = idx + 1; i < deck.Length; i++)\r
{\r
var fleet = int.Parse(values["api_deck_id"]) - 1;\r
if (_combinedFleetType == 0 || fleet > 1)\r
{\r
- _inSortie[fleet] = true;\r
+ _fleets[fleet].State = FleetState.Sortie;\r
}\r
else\r
{\r
- _inSortie[0] = _inSortie[1] = true;\r
+ _fleets[0].State = _fleets[1].State = FleetState.Sortie;\r
}\r
SetBadlyDamagedShips();\r
}\r
\r
+ public void StartPractice(string request)\r
+ {\r
+ var values = HttpUtility.ParseQueryString(request);\r
+ var fleet = int.Parse(values["api_deck_id"]) - 1;\r
+ _fleets[fleet].State = FleetState.Practice;\r
+ }\r
+\r
public void RepairShip(int id)\r
{\r
var s = _shipInfo[id];\r
s.Cond = Max(40, s.Cond);\r
}\r
\r
- public ShipStatus[] GetShipStatuses(int fleet)\r
- {\r
- return _decks[fleet].Where(id => id != -1).Select(GetStatus).ToArray();\r
- }\r
-\r
- public int[] GetDeck(int fleet) => _decks[fleet];\r
+ public Fleet[] Fleets => _fleets;\r
\r
public ShipStatus GetStatus(int id)\r
{\r
\r
public ShipSpec GetSpec(int id) => _shipMaster.GetSpec(id);\r
\r
- public bool InMission(int fleet) => _inMission[fleet];\r
-\r
- public bool InSortie(int fleet) => _inSortie[fleet];\r
-\r
public int CombinedFleetType => _combinedFleetType;\r
\r
public ShipStatus[] ShipList => _shipInfo.Keys.Where(id => id != -1).Select(GetStatus).ToArray();\r
\r
- public ChargeStatus[] ChargeStatuses\r
- => (from deck in _decks\r
- let flag = new ChargeStatus(_shipInfo[deck[0]])\r
- let others = (from id in 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
BadlyDamagedShips =\r
- _inSortie.SelectMany((flag, i) => !flag\r
- ? new ShipStatus[0]\r
- : _combinedFleetType > 0 && i == 1\r
- ? GetShipStatuses(1).Skip(1) // 連合艦隊第二の旗艦を飛ばす\r
- : GetShipStatuses(i))\r
- .Where(s => !s.Escaped && s.DamageLevel == ShipStatus.Damage.Badly)\r
- .Select(s => s.Name)\r
- .ToArray();\r
+ (from s in _fleets.Where(fleet => fleet.State == FleetState.Sortie)\r
+ .SelectMany(fleet => fleet.Deck.Where(id => id != -1).Select(GetStatus))\r
+ where !s.Escaped && s.DamageLevel == ShipStatus.Damage.Badly &&\r
+ !(s.CombinedFleetType > 0 && s.Fleet == 1 && s.DeckIndex == 0) // 第二艦隊の旗艦を除く\r
+ select s.Name).ToArray();\r
}\r
\r
public void ClearBadlyDamagedShips()\r
_escapedShips.Clear();\r
}\r
\r
- public bool UseOldEnemyId\r
- {\r
- set => _shipMaster.UseOldEnemyId = value;\r
- }\r
-\r
public void InjectShips(dynamic battle, dynamic item)\r
{\r
var deck = (int)battle.api_deck_id - 1;\r
var id = _shipInfo.Keys.Count + 1;\r
var ships = nowhps.Zip(maxhps,\r
(now, max) => new ShipStatus {Id = id++, NowHp = now, MaxHp = max}).ToArray();\r
- _decks[deck] = (from ship in ships select ship.Id).ToArray();\r
+ _fleets[deck].Deck = (from ship in ships select ship.Id).ToArray();\r
foreach (var ship in ships)\r
_shipInfo[ship.Id] = ship;\r
foreach (var entry in ships.Zip(slots, (ship, slot) =>new {ship, slot}))\r