OSDN Git Service

空襲戦で女神で復活すると勝利判定がくるうのを直す
[kancollesniffer/KancolleSniffer.git] / KancolleSniffer / BattleInfo.cs
index c083ebe..8f9d53f 100644 (file)
@@ -60,7 +60,8 @@ namespace KancolleSniffer
         private bool _lastCell;\r
 \r
         public BattleState BattleState { get; set; }\r
-        public string Formation { get; private set; }\r
+        public int[] Formation { get; private set; }\r
+        public int[] FighterPower { get; private set; }\r
         public EnemyFighterPower EnemyFighterPower { get; private set; }\r
         public int AirControlLevel { get; private set; }\r
         public BattleResultRank ResultRank { get; private set; }\r
@@ -96,10 +97,13 @@ namespace KancolleSniffer
 \r
         public void InspectBattle(string url, string request, dynamic json)\r
         {\r
-            Formation = FormationName(json);\r
+            if (json.api_formation())\r
+                Formation = ((dynamic[])json.api_formation).Select(f => f is string ? (int)int.Parse(f) : (int)f)\r
+                    .ToArray();\r
             AirControlLevel = CheckAirControlLevel(json);\r
             ShowResult(false); // 昼戦の結果を夜戦のときに表示する\r
-            SetupResult(request, json);\r
+            SetupResult(request, json, url.Contains("practice"));\r
+            FighterPower = CalcFighterPower();\r
             EnemyFighterPower = CalcEnemyFighterPower(json);\r
             BattleState = IsNightBattle(json) ? BattleState.Night : BattleState.Day;\r
             CalcDamage(json);\r
@@ -118,25 +122,7 @@ namespace KancolleSniffer
             return (int)json.api_deck_id - 1;\r
         }\r
 \r
-        private string FormationName(dynamic json)\r
-        {\r
-            if (!json.api_formation()) // 演習の夜戦\r
-                return "";\r
-            switch ((int)json.api_formation[2])\r
-            {\r
-                case 1:\r
-                    return "同航戦";\r
-                case 2:\r
-                    return "反航戦";\r
-                case 3:\r
-                    return "T字有利";\r
-                case 4:\r
-                    return "T字不利";\r
-            }\r
-            return "";\r
-        }\r
-\r
-        private void SetupResult(string request, dynamic json)\r
+        private void SetupResult(string request, dynamic json, bool practice)\r
         {\r
             if (_friend != null)\r
                 return;\r
@@ -144,19 +130,39 @@ namespace KancolleSniffer
             _fleet = DeckId(json);\r
             var fstats = _shipInfo.GetShipStatuses(_fleet);\r
             FlagshipRecovery(request, fstats[0]);\r
-            _friend = Record.Setup(fstats);\r
-            _guard = json.api_f_nowhps_combined() ? Record.Setup(_shipInfo.GetShipStatuses(1)) : new Record[0];\r
+            _friend = Record.Setup(fstats, practice);\r
+            _guard = json.api_f_nowhps_combined()\r
+                ? Record.Setup(_shipInfo.GetShipStatuses(1), 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
-                ((int[][])json.api_eSlot).Select(slot => slot.Select(_itemInfo.GetSpecByItemId).ToArray()).ToArray());\r
+                ((int[][])json.api_eSlot).Select(slot => slot.Select(_itemInfo.GetSpecByItemId).ToArray()).ToArray(),\r
+                practice);\r
             _enemyGuard = json.api_ship_ke_combined()\r
                 ? Record.Setup((int[])json.api_e_nowhps_combined,\r
                     ((int[])json.api_ship_ke_combined).Select(_shipInfo.GetSpec).ToArray(),\r
                     ((int[][])json.api_eSlot).Select(slot => slot.Select(_itemInfo.GetSpecByItemId).ToArray())\r
-                    .ToArray())\r
+                    .ToArray(), practice)\r
                 : new Record[0];\r
         }\r
 \r
+        private void SetResult()\r
+        {\r
+            Result = new BattleResult\r
+            {\r
+                Friend = new BattleResult.Combined\r
+                {\r
+                    Main = _friend.Select(r => r.SnapShot).ToArray(),\r
+                    Guard = _guard.Select(r => r.SnapShot).ToArray()\r
+                },\r
+                Enemy = new BattleResult.Combined\r
+                {\r
+                    Main = _enemy.Select(r => r.SnapShot).ToArray(),\r
+                    Guard = _enemyGuard.Select(r => r.SnapShot).ToArray()\r
+                }\r
+            };\r
+        }\r
+\r
         private void FlagshipRecovery(string request, ShipStatus flagship)\r
         {\r
             var type = int.Parse(HttpUtility.ParseQueryString(request)["api_recovery_type"] ?? "0");\r
@@ -212,6 +218,13 @@ namespace KancolleSniffer
             return (int)stage1.api_disp_seiku;\r
         }\r
 \r
+        private int[] CalcFighterPower()\r
+        {\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
+        }\r
+\r
         private EnemyFighterPower CalcEnemyFighterPower(dynamic json)\r
         {\r
             var result = new EnemyFighterPower();\r
@@ -248,7 +261,8 @@ namespace KancolleSniffer
             ByTurn,\r
             Support,\r
             Aircraft,\r
-            AirBase\r
+            AirBase,\r
+            Friend\r
         }\r
 \r
         private class Phase\r
@@ -281,6 +295,7 @@ namespace KancolleSniffer
                 new Phase("support_info", CombatType.Support),\r
                 new Phase("opening_taisen", CombatType.ByTurn),\r
                 new Phase("opening_atack", CombatType.AtOnce),\r
+                new Phase("friendly_battle", CombatType.Friend),\r
                 new Phase("hougeki", CombatType.ByTurn),\r
                 new Phase("hougeki1", CombatType.ByTurn),\r
                 new Phase("hougeki2", CombatType.ByTurn),\r
@@ -314,6 +329,9 @@ namespace KancolleSniffer
                 case CombatType.AirBase:\r
                     CalcAirBaseAttackDamage(json[api]);\r
                     break;\r
+                case CombatType.Friend:\r
+                    CalcFriendAttackDamage(json[api]);\r
+                    break;\r
             }\r
         }\r
 \r
@@ -339,12 +357,17 @@ namespace KancolleSniffer
             }\r
         }\r
 \r
+        private void CalcFriendAttackDamage(dynamic json)\r
+        {\r
+            CalcDamageByTurn(json.api_hougeki, true);\r
+        }\r
+\r
         private void AddAirBattleResult(dynamic json, string phaseName)\r
         {\r
             var stage1 = json.api_stage1;\r
             if (stage1 == null || (stage1.api_f_count == 0 && stage1.api_e_count == 0))\r
                 return;\r
-            AirBattleResults.Add(new AirBattleResult\r
+            var result = new AirBattleResult\r
             {\r
                 PhaseName = phaseName,\r
                 AirControlLevel = json.api_stage1.api_disp_seiku() ? (int)json.api_stage1.api_disp_seiku : 0,\r
@@ -370,7 +393,19 @@ namespace KancolleSniffer
                         EnemyCount = (int)json.api_stage2.api_e_count,\r
                         EnemyLost = (int)json.api_stage2.api_e_lostcount\r
                     }\r
-            });\r
+            };\r
+            if (json.api_stage2 != null && json.api_stage2.api_air_fire())\r
+            {\r
+                var airfire = json.api_stage2.api_air_fire;\r
+                var idx = (int)airfire.api_idx;\r
+                result.AirFire = new AirBattleResult.AirFireResult\r
+                {\r
+                    ShipName = idx < _friend.Length ? _friend[idx].Name : _guard[idx - 6].Name,\r
+                    Kind = (int)airfire.api_kind,\r
+                    Items = ((int[])airfire.api_use_items).Select(id => _itemInfo.GetSpecByItemId(id).Name).ToArray()\r
+                };\r
+            }\r
+            AirBattleResults.Add(result);\r
         }\r
 \r
         private void CalcKoukuDamage(dynamic json)\r
@@ -391,7 +426,8 @@ namespace KancolleSniffer
             CalcDamageAtOnce(json, friend, null, enemy, null);\r
         }\r
 \r
-        private void CalcDamageAtOnce(dynamic json, Record[] friend, Record[] guard, Record[] enemy, Record[] enemyGuard)\r
+        private void CalcDamageAtOnce(dynamic json,\r
+            Record[] friend, Record[] guard, Record[] enemy, Record[] enemyGuard)\r
         {\r
             if (json.api_fdam() && json.api_fdam != null)\r
                 CalcRawDamageAtOnce(json.api_fdam, friend, guard);\r
@@ -410,7 +446,7 @@ namespace KancolleSniffer
                 guard[i].ApplyDamage(damage[i + 6]);\r
         }\r
 \r
-        private void CalcDamageByTurn(dynamic json)\r
+        private void CalcDamageByTurn(dynamic json, bool ignoreFriendDamage = false)\r
         {\r
             if (!(json.api_df_list() && json.api_df_list != null &&\r
                   json.api_damage() && json.api_damage != null &&\r
@@ -431,6 +467,8 @@ namespace KancolleSniffer
                 var hit = new {t = targets[i][0], d = damages[i].Sum(d => d >= 0 ? d : 0)};\r
                 if (hit.t == -1)\r
                     continue;\r
+                if (ignoreFriendDamage && eflags[i] == 1)\r
+                    continue;\r
                 records[eflags[i]][hit.t].ApplyDamage(hit.d);\r
             }\r
         }\r
@@ -455,7 +493,6 @@ namespace KancolleSniffer
             SetEscapeShips(json);\r
         }\r
 \r
-\r
         private void VerifyResultRank(dynamic json)\r
         {\r
             if (_friend == null)\r
@@ -474,6 +511,7 @@ namespace KancolleSniffer
         {\r
             BattleState = BattleState.Result;\r
             ShowResult(false);\r
+            VerifyResultRank(json);\r
             CleanupResult();\r
         }\r
 \r
@@ -492,23 +530,6 @@ namespace KancolleSniffer
                 _shipInfo.ClearBadlyDamagedShips();\r
         }\r
 \r
-        private void SetResult()\r
-        {\r
-            Result = new BattleResult\r
-            {\r
-                Friend = new BattleResult.Combined\r
-                {\r
-                    Main = _friend.Select(r => r.SnapShot).ToArray(),\r
-                    Guard = _guard.Select(r => r.SnapShot).ToArray()\r
-                },\r
-                Enemy = new BattleResult.Combined\r
-                {\r
-                    Main = _enemy.Select(r => r.SnapShot).ToArray(),\r
-                    Guard = _enemyGuard.Select(r => r.SnapShot).ToArray()\r
-                }\r
-            };\r
-        }\r
-\r
         public void SetEscapeShips(dynamic json)\r
         {\r
             _escapingShips.Clear();\r
@@ -536,16 +557,19 @@ namespace KancolleSniffer
         private class Record\r
         {\r
             private ShipStatus _status;\r
+            private bool _practice;\r
             public ShipStatus SnapShot => (ShipStatus)_status.Clone();\r
             public int NowHp => _status.NowHp;\r
             public bool Escaped => _status.Escaped;\r
             public ShipStatus.Damage DamageLevel => _status.DamageLevel;\r
-            public int StartHp;\r
+            public string Name => _status.Name;\r
+            public int StartHp { get; private set; }\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
+            public static Record[] Setup(ShipStatus[] ships, bool practice) =>\r
+            (from s in ships\r
+                select new Record {_status = (ShipStatus)s.Clone(), _practice = practice, StartHp = s.NowHp}).ToArray();\r
 \r
-            public static Record[] Setup(int[] nowhps,  ShipSpec[] ships, ItemSpec[][] slots)\r
+            public static Record[] Setup(int[] nowhps, ShipSpec[] ships, ItemSpec[][] slots, bool practice)\r
             {\r
                 return Enumerable.Range(0, nowhps.Length).Select(i =>\r
                     new Record\r
@@ -557,9 +581,10 @@ namespace KancolleSniffer
                             NowHp = nowhps[i],\r
                             MaxHp = nowhps[i],\r
                             Spec = ships[i],\r
-                            Slot = slots[i].Select(spec => new ItemStatus{Id = spec.Id, Spec = spec}).ToArray(),\r
+                            Slot = slots[i].Select(spec => new ItemStatus {Id = spec.Id, Spec = spec}).ToArray(),\r
                             SlotEx = new ItemStatus(0)\r
-                        }\r
+                        },\r
+                        _practice = practice\r
                     }).ToArray();\r
             }\r
 \r
@@ -571,7 +596,9 @@ namespace KancolleSniffer
                     return;\r
                 }\r
                 _status.NowHp = 0;\r
-                foreach (var item in _status.AllSlot)\r
+                if (_practice)\r
+                    return;\r
+                foreach (var item in new[] {_status.SlotEx}.Concat(_status.Slot))\r
                 {\r
                     if (item.Spec.Id == 42)\r
                     {\r
@@ -598,25 +625,19 @@ namespace KancolleSniffer
 \r
         private BattleResultRank CalcLdAirBattleRank()\r
         {\r
-            var combined = _friend.Concat(_guard).ToArray();\r
-            var friendNowShips = combined.Count(r => r.NowHp > 0);\r
+            var combined = _friend.Concat(_guard).Where(r => !r.Escaped).ToArray();\r
             var friendGauge = combined.Sum(r => r.StartHp - r.NowHp);\r
-            var friendSunk = combined.Count(r => r.NowHp == 0);\r
             var friendGaugeRate = Floor((double)friendGauge / combined.Sum(r => r.StartHp) * 100);\r
 \r
-            if (friendSunk == 0)\r
-            {\r
-                if (friendGauge == 0)\r
-                    return BattleResultRank.P;\r
-                if (friendGaugeRate < 10)\r
-                    return BattleResultRank.A;\r
-                if (friendGaugeRate < 20)\r
-                    return BattleResultRank.B;\r
-                if (friendGaugeRate < 50)\r
-                    return BattleResultRank.C;\r
-                return BattleResultRank.D;\r
-            }\r
-            if (friendSunk < friendNowShips)\r
+            if (friendGauge <= 0)\r
+                return BattleResultRank.P;\r
+            if (friendGaugeRate < 10)\r
+                return BattleResultRank.A;\r
+            if (friendGaugeRate < 20)\r
+                return BattleResultRank.B;\r
+            if (friendGaugeRate < 50)\r
+                return BattleResultRank.C;\r
+            if (friendGaugeRate < 80)\r
                 return BattleResultRank.D;\r
             return BattleResultRank.E;\r
         }\r
@@ -671,9 +692,13 @@ namespace KancolleSniffer
         /// <summary>\r
         /// テスト専用\r
         /// </summary>\r
-        public void InjectEnemyResultStatus(ShipStatus[] enemy, ShipStatus[] guard)\r
+        public void InjectResultStatus(ShipStatus[] main, ShipStatus[] guard, ShipStatus[] enemy, ShipStatus[] enemyGuard)\r
         {\r
-            Result = new BattleResult {Enemy = new BattleResult.Combined {Main = enemy, Guard = guard}};\r
+            Result = new BattleResult\r
+            {\r
+                Friend = new BattleResult.Combined { Main = main, Guard = guard},\r
+                Enemy = new BattleResult.Combined {Main = enemy, Guard = enemyGuard}\r
+            };\r
         }\r
     }\r
 }
\ No newline at end of file