private Record[] _friend;\r
private Record[] _guard;\r
private int[] _enemyHp;\r
+ private int[] _enemyGuardHp;\r
private int[] _enemyStartHp;\r
+ private int[] _enemyGuardStartHp;\r
private readonly List<int> _escapingShips = new List<int>();\r
private int _flagshipRecoveryType;\r
\r
ShowResult(false); // 昼戦の結果を夜戦のときに表示する\r
SetupResult(json);\r
if (IsNightBattle(json))\r
- CalcHougekiDamage(json.api_hougeki, _friend, _enemyHp);\r
+ {\r
+ CalcHougekiDamage(json.api_hougeki,\r
+ _guard.Length > 0 ? _guard : _friend,\r
+ json.api_active_deck() && json.api_active_deck[1] != 1 ? _enemyGuardHp : _enemyHp);\r
+ }\r
else\r
- CalcDamage(json);\r
+ {\r
+ CalcDamage(json, url.EndsWith("battle_water"));\r
+ }\r
ClearOverKill(_enemyHp);\r
ResultRank = url.EndsWith("ld_airbattle") ? CalcLdAirBattleRank() : CalcResultRank();\r
}\r
_flagshipRecoveryType = int.Parse(type);\r
}\r
\r
+ private bool IsNightBattle(dynamic json) => json.api_hougeki();\r
+\r
private int DeckId(dynamic json)\r
{\r
if (json.api_dock_id()) // 昼戦はtypoしている\r
{\r
if (_friend != null)\r
return;\r
- var combined = json.api_nowhps_combined();\r
var nowhps = (int[])json.api_nowhps;\r
- _fleet = combined ? 0 : DeckId(json);\r
+ _fleet = DeckId(json);\r
var fstats = _shipInfo.GetShipStatuses(_fleet);\r
FlagshipRecovery(fstats[0]);\r
_friend = Record.Setup(fstats);\r
_enemyHp = nowhps.Skip(7).TakeWhile(hp => hp != -1).ToArray();\r
_enemyStartHp = (int[])_enemyHp.Clone();\r
EnemyResultStatus =\r
- (from id in ((int[])json.api_ship_ke).Skip(1)\r
- where id != -1\r
- select new ShipStatus {Id = id, Spec = _shipInfo.GetSpec(id)}).ToArray();\r
- if (combined)\r
- {\r
- var gstats = _shipInfo.GetShipStatuses(1);\r
- _guard = Record.Setup(gstats);\r
- }\r
- else\r
+ (from id in (int[])json.api_ship_ke\r
+ where id != -1\r
+ select new ShipStatus {Id = id, Spec = _shipInfo.GetSpec(id)}).ToArray();\r
+ _guard = new Record[0];\r
+ _enemyGuardHp = new int[0];\r
+ _enemyGuardStartHp = new int[0];\r
+ if (!json.api_nowhps_combined())\r
+ return;\r
+ var combined = (int[])json.api_nowhps_combined;\r
+ if (combined[1] != -1) // 味方が連合艦隊\r
+ _guard = Record.Setup(_shipInfo.GetShipStatuses(1));\r
+ if (combined.Length > 7) // 敵が連合艦隊\r
{\r
- _guard = new Record[0];\r
+ _enemyGuardHp =\r
+ ((int[])json.api_nowhps_combined).\r
+ Skip(7).TakeWhile(hp => hp != -1).ToArray();\r
+ _enemyGuardStartHp = (int[])_enemyGuardHp.Clone();\r
}\r
}\r
\r
}).ToArray();\r
var equips = ((int[][])json.api_eSlot).SelectMany(x => x);\r
return (from slot in equips.Zip(maxEq, (id, max) => new {id, max})\r
- let spec = _itemInfo.GetSpecByItemId(slot.id)\r
- where spec.CanAirCombat\r
- select (int)Floor(spec.AntiAir * Sqrt(slot.max))).DefaultIfEmpty().Sum() + missing;\r
+ let spec = _itemInfo.GetSpecByItemId(slot.id)\r
+ where spec.CanAirCombat\r
+ select (int)Floor(spec.AntiAir * Sqrt(slot.max))).DefaultIfEmpty().Sum() + missing;\r
}\r
\r
private void CalcDamage(dynamic json, bool surfaceFleet = false)\r
{\r
- var combined = json.api_nowhps_combined();\r
+ var fc = _guard.Length > 0;\r
+ var ec = _enemyGuardHp.Length > 0;\r
if (json.api_air_base_attack())\r
CalcAirBaseAttackDamage(json.api_air_base_attack);\r
if (json.api_kouku.api_stage3 != null)\r
CalcSimpleDamage(json.api_kouku.api_stage3, _friend, _enemyHp);\r
if (json.api_kouku.api_stage3_combined() && json.api_kouku.api_stage3_combined != null)\r
- CalcSimpleDamage(json.api_kouku.api_stage3_combined.api_fdam, _guard);\r
+ CalcSimpleDamage(json.api_kouku.api_stage3_combined, _guard, _enemyGuardHp);\r
if (json.api_kouku2()) // 航空戦2回目\r
{\r
if (json.api_kouku2.api_stage3 != null)\r
CalcSimpleDamage(json.api_kouku2.api_stage3, _friend, _enemyHp);\r
if (json.api_kouku2.api_stage3_combined() && json.api_kouku2.api_stage3_combined != null)\r
- CalcSimpleDamage(json.api_kouku2.api_stage3_combined.api_fdam, _guard);\r
+ CalcSimpleDamage(json.api_kouku2.api_stage3_combined, _guard, _enemyGuardHp);\r
}\r
if (!json.api_opening_atack()) // 航空戦のみ\r
return;\r
CalcSupportDamage(json.api_support_info);\r
if (json.api_opening_taisen() && json.api_opening_taisen != null)\r
{\r
- var friend = combined ? _guard : _friend; // 先制対潜攻撃の対象は護衛(たぶん)\r
+ var friend = fc ? _guard : _friend; // 先制対潜攻撃の対象は護衛(たぶん)\r
CalcHougekiDamage(json.api_opening_taisen, friend, _enemyHp);\r
}\r
if (json.api_opening_atack != null)\r
{\r
- var friend = combined ? _guard : _friend; // 雷撃の対象は護衛\r
- CalcSimpleDamage(json.api_opening_atack, friend, _enemyHp);\r
+ var friend = fc ? _guard : _friend; // 雷撃の対象は護衛\r
+ CalcSimpleDamage(json.api_opening_atack, friend, _enemyHp, _enemyGuardHp);\r
}\r
if (json.api_hougeki1() && json.api_hougeki1 != null)\r
{\r
- var friend = combined && !surfaceFleet ? _guard : _friend; // 空母機動部隊は一巡目が護衛\r
- CalcHougekiDamage(json.api_hougeki1, friend, _enemyHp);\r
+ CalcHougekiDamage(json.api_hougeki1,\r
+ fc && !surfaceFleet ? _guard : _friend, // 空母機動部隊は一巡目が護衛\r
+ ec ? _enemyGuardHp : _enemyHp); // 敵連合艦隊は一巡目が護衛\r
}\r
if (json.api_hougeki2() && json.api_hougeki2 != null)\r
{\r
- CalcHougekiDamage(json.api_hougeki2, _friend, _enemyHp);\r
+ if (json.api_hougeki2.api_at_eflag())\r
+ CalcCombinedHougekiDamage(json.api_hougeki2, _friend, _guard, _enemyHp, _enemyGuardHp);\r
+ else\r
+ CalcHougekiDamage(json.api_hougeki2, _friend, _enemyHp);\r
}\r
if (json.api_hougeki3() && json.api_hougeki3 != null)\r
{\r
- var friend = combined && surfaceFleet ? _guard : _friend; // 水上打撃部隊は三順目が護衛\r
- CalcHougekiDamage(json.api_hougeki3, friend, _enemyHp);\r
+ if (json.api_hougeki3.api_at_eflag())\r
+ {\r
+ CalcCombinedHougekiDamage(json.api_hougeki3, _friend, _guard, _enemyHp, _enemyGuardHp);\r
+ }\r
+ else\r
+ {\r
+ var friend = fc && surfaceFleet ? _guard : _friend; // 水上打撃部隊は三順目が護衛\r
+ CalcHougekiDamage(json.api_hougeki3, friend, _enemyHp);\r
+ }\r
}\r
if (json.api_raigeki() && json.api_raigeki != null)\r
{\r
- var friend = combined ? _guard : _friend;\r
- CalcSimpleDamage(json.api_raigeki, friend, _enemyHp);\r
+ var friend = fc ? _guard : _friend;\r
+ CalcSimpleDamage(json.api_raigeki, friend, _enemyHp, _enemyGuardHp);\r
}\r
}\r
\r
if (!entry.api_stage3() || entry.api_stage3 == null)\r
continue;\r
CalcSimpleDamage(entry.api_stage3.api_edam, _enemyHp);\r
+ if (entry.api_stage3_combined())\r
+ CalcSimpleDamage(entry.api_stage3_combined.api_edam, _enemyGuardHp);\r
}\r
}\r
\r
- private bool IsNightBattle(dynamic json) => json.api_hougeki();\r
-\r
private void CalcSimpleDamage(dynamic json, Record[] friend, int[] enemy)\r
{\r
+ if (json.api_fdam())\r
+ CalcSimpleDamage(json.api_fdam, friend);\r
+ if (json.api_edam())\r
+ CalcSimpleDamage(json.api_edam, enemy);\r
+ }\r
+\r
+ private void CalcSimpleDamage(dynamic json, Record[] friend, int[] enemy, int[] enemyGuard)\r
+ {\r
CalcSimpleDamage(json.api_fdam, friend);\r
- CalcSimpleDamage(json.api_edam, enemy);\r
+ var damage = (int[])json.api_edam;\r
+ for (var i = 0; i < enemy.Length; i++)\r
+ enemy[i] -= damage[i + 1];\r
+ for (var i = 0; i < enemyGuard.Length; i++)\r
+ enemyGuard[i] -= damage[i + 6 + 1];\r
}\r
\r
private void CalcSimpleDamage(dynamic rawDamage, Record[] result)\r
private void CalcHougekiDamage(dynamic hougeki, Record[] friend, int[] enemy)\r
{\r
var targets = ((dynamic[])hougeki.api_df_list).Skip(1).SelectMany(x => (int[])x);\r
- var damages = ((dynamic[])hougeki.api_damage).Skip(1).SelectMany(x => (double[])x);\r
+ var damages = ((dynamic[])hougeki.api_damage).Skip(1).SelectMany(x => (int[])x);\r
foreach (var hit in targets.Zip(damages, (t, d) => new {t, d}))\r
{\r
if (hit.t == -1)\r
continue;\r
if (hit.t <= 6)\r
- friend[hit.t - 1].ApplyDamage((int)hit.d);\r
+ friend[hit.t - 1].ApplyDamage(hit.d);\r
else\r
- enemy[(hit.t - 1) % 6] -= (int)hit.d;\r
+ enemy[(hit.t - 1) % 6] -= hit.d;\r
+ }\r
+ }\r
+\r
+ private void CalcCombinedHougekiDamage(dynamic hougeki, Record[] friend, Record[] guard,\r
+ int[] enemy, int[] enemyGuard)\r
+ {\r
+ var targets = ((dynamic[])hougeki.api_df_list).Skip(1).Select(x => (int[])x);\r
+ var damages = ((dynamic[])hougeki.api_damage).Skip(1).Select(x => (int[])x);\r
+ var eflags = ((int[])hougeki.api_at_eflag).Skip(1);\r
+ foreach (var turn in\r
+ targets.Zip(damages, (t, d) => new {t, d}).\r
+ Zip(eflags, (td, e) => new {e, td.t, td.d}))\r
+ {\r
+ foreach (var hit in turn.t.Zip(turn.d, (t, d) => new {t, d}))\r
+ {\r
+ if (turn.e == 1)\r
+ {\r
+ if (hit.t <= 6)\r
+ friend[hit.t - 1].ApplyDamage(hit.d);\r
+ else\r
+ guard[hit.t - 1].ApplyDamage(hit.d);\r
+ }\r
+ else\r
+ {\r
+ if (hit.t <= 6)\r
+ enemy[hit.t - 1] -= hit.d;\r
+ else\r
+ enemyGuard[(hit.t - 1) % 6] -= hit.d;\r
+ }\r
+ }\r
}\r
}\r
\r
{\r
ShowResult();\r
CleanupResult();\r
+ SetEscapeShips(json);\r
}\r
\r
public void InspectPracticeResult(dynamic json)\r
{\r
if (_friend == null)\r
return;\r
- var ships = _shipInfo.GetShipStatuses(_fleet);\r
- foreach (var e in ships.Zip(_friend, (ship, now) => new {ship, now}))\r
- e.now.UpdateShipStatus(e.ship);\r
+ var ships = _guard.Length > 0\r
+ ? _shipInfo.GetShipStatuses(0).Concat(_shipInfo.GetShipStatuses(1)).ToArray()\r
+ : _shipInfo.GetShipStatuses(_fleet);\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
_shipInfo.SetBadlyDamagedShips();\r
else\r
}\r
}\r
\r
- public void InspectCombinedBattle(dynamic json, string url)\r
- {\r
- InBattle = true;\r
- Formation = FormationName(json);\r
- EnemyFighterPower = CalcEnemyFighterPower(json);\r
- AirControlLevel = CheckAirControlLevel(json);\r
- _fleet = 10;\r
- ShowResultCombined(false);\r
- SetupResult(json);\r
- if (IsNightBattle(json))\r
- CalcHougekiDamage(json.api_hougeki, _guard, _enemyHp);\r
- else\r
- CalcDamage(json, url.EndsWith("battle_water"));\r
- ClearOverKill(_enemyHp);\r
- ResultRank = url.EndsWith("ld_airbattle") ? CalcLdAirBattleRank() : CalcResultRank();\r
- }\r
-\r
- public void InspectCombinedBattleResult(dynamic json)\r
+ public void SetEscapeShips(dynamic json)\r
{\r
_escapingShips.Clear();\r
- ShowResultCombined();\r
- CleanupResult();\r
- if ((int)json.api_escape_flag == 0)\r
+ if (!json.api_escape_flag() || (int)json.api_escape_flag == 0)\r
return;\r
var damaged = (int)json.api_escape.api_escape_idx[0] - 1;\r
_escapingShips.Add(_shipInfo.GetDeck(damaged / 6)[damaged % 6]);\r
_escapingShips.Add(_shipInfo.GetDeck(escort / 6)[escort % 6]);\r
}\r
\r
- private void ShowResultCombined(bool warnDamagedShip = true)\r
- {\r
- if (_friend == null)\r
- return;\r
- var ships = _shipInfo.GetShipStatuses(0).Concat(_shipInfo.GetShipStatuses(1)).ToArray();\r
- foreach (var e in ships.Zip(_friend.Concat(_guard), (ship, now) => new {ship, now}))\r
- e.now.UpdateShipStatus(e.ship);\r
- if (warnDamagedShip)\r
- _shipInfo.SetBadlyDamagedShips();\r
- else\r
- _shipInfo.ClearBadlyDamagedShips();\r
- SetEnemyResultStatus();\r
- }\r
-\r
public void CauseCombinedBattleEscape()\r
{\r
_shipInfo.SetEscapedShips(_escapingShips);\r
public int StartHp;\r
\r
public static Record[] Setup(ShipStatus[] ships) =>\r
- (from s in ships select new Record {_status = (ShipStatus)s.Clone(), StartHp = s.NowHp}).ToArray();\r
+ (from s in ships select new Record {_status = (ShipStatus)s.Clone(), StartHp = s.NowHp}).ToArray();\r
\r
public void ApplyDamage(int damage)\r
{\r
//\r
private BattleResultRank CalcResultRank()\r
{\r
- var combined = _friend.Concat(_guard).ToArray();\r
+ var friend = _friend.Concat(_guard).ToArray();\r
+ var enemyHp = _enemyHp.Concat(_enemyGuardHp).ToArray();\r
+ var enemyStartHp = _enemyStartHp.Concat(_enemyGuardStartHp).ToArray();\r
// 戦闘後に残っている艦数\r
- var friendNowShips = combined.Count(r => r.NowHp > 0);\r
- var enemyNowShips = _enemyHp.Count(hp => hp > 0);\r
+ var friendNowShips = friend.Count(r => r.NowHp > 0);\r
+ var enemyNowShips = enemyHp.Count(hp => hp > 0);\r
// 総ダメージ\r
- var friendGauge = Max(combined.Sum(r => r.StartHp - r.NowHp), 0); // ダメコン・女神発動で負になりうる\r
- var enemyGauge = _enemyStartHp.Sum() - _enemyHp.Sum();\r
+ var friendGauge = Max(friend.Sum(r => r.StartHp - r.NowHp), 0); // ダメコン・女神発動で負になりうる\r
+ var enemyGauge = enemyStartHp.Sum() - enemyHp.Sum();\r
// 轟沈・撃沈数\r
- var friendSunk = combined.Count(r => r.NowHp == 0);\r
- var enemySunk = _enemyHp.Count(hp => hp == 0);\r
+ var friendSunk = friend.Count(r => r.NowHp == 0);\r
+ var enemySunk = enemyHp.Count(hp => hp == 0);\r
\r
- var friendGaugeRate = Floor((double)friendGauge / combined.Where(r => !r.Escaped).Sum(r => r.StartHp) * 100);\r
- var enemyGaugeRate = Floor((double)enemyGauge / _enemyStartHp.Sum() * 100);\r
- var equalOrMore = enemyGaugeRate > (0.9 * friendGaugeRate);\r
- var superior = enemyGaugeRate > 0 && enemyGaugeRate > (2.5 * friendGaugeRate);\r
+ var friendGaugeRate = Floor((double)friendGauge / friend.Where(r => !r.Escaped).Sum(r => r.StartHp) * 100);\r
+ var enemyGaugeRate = Floor((double)enemyGauge / enemyStartHp.Sum() * 100);\r
+ var equalOrMore = enemyGaugeRate > 0.9 * friendGaugeRate;\r
+ var superior = enemyGaugeRate > 0 && enemyGaugeRate > 2.5 * friendGaugeRate;\r
\r
if (friendSunk == 0)\r
{\r
return BattleResultRank.P;\r
return BattleResultRank.S;\r
}\r
- if (_enemyHp.Length == 6)\r
+ if (enemyHp.Length == 6)\r
{\r
if (enemySunk >= 4)\r
return BattleResultRank.A;\r