OSDN Git Service

Doutakuを導入
[kcd/KCD.git] / KCD / CalculateDamageCommand.swift
index 60d0b9e..c72106c 100644 (file)
@@ -29,9 +29,8 @@ final class CalculateDamageCommand: JSONCommand {
     
     override func execute() {
         
-        guard let battleApi = BattleAPI(rawValue: api) else { return }
-        
-        switch battleApi {
+        switch api.endpoint {
+            
         case .battle, .airBattle, .ldAirBattle:
             normalBattle(battleType: .normal)
             
@@ -50,6 +49,9 @@ final class CalculateDamageCommand: JSONCommand {
         case .combinedEachBattleWater:
             normalBattle(battleType: .eachCombinedWater)
             
+        case .combinedEachNightToDay:
+            eachNightToDayBattle(battleType: .normal)
+            
         case .midnightBattle, .midnightSpMidnight:
             midnightBattle(battleType: .normal)
             
@@ -62,6 +64,8 @@ final class CalculateDamageCommand: JSONCommand {
         case .battleResult, .combinedBattleResult:
             applyDamage()
             resetDamage()
+            
+        default: return Logger.shared.log("Missing API: \(apiResponse.api)")
         }
     }
     
@@ -83,6 +87,12 @@ final class CalculateDamageCommand: JSONCommand {
         DamageCalculator(json, battleType).calcEachBattleAir()
     }
     
+    func eachNightToDayBattle(battleType: BattleType) {
+        
+        updateBattleCell()
+        DamageCalculator(json, battleType).calcEachNightToDay()
+    }
+    
     func enemyCombinedBattle(battleType: BattleType) {
         
         updateBattleCell()
@@ -101,51 +111,65 @@ extension CalculateDamageCommand {
         
         let store = TemporaryDataStore.oneTimeEditor()
         
-        store.damages().forEach { store.delete($0) }
+        store.sync { store.damages().forEach(store.delete) }
     }
     
     func applyDamage() {
         
         let store = TemporaryDataStore.oneTimeEditor()
         
-        let totalDamages = store.sortedDamagesById()
-        
-        guard totalDamages.count == 12 else {
-            
-            print("Damages count is invalid. count is \(totalDamages.count).")
-            return
-        }
+        let totalDamages = store.sync { store.sortedDamagesById() }
         
-        let aStore = ServerDataStore.oneTimeEditor()
+        let aStore = ServerDataStore.default
         
-        totalDamages.forEach {
+        Debug.excute(level: .debug) {
             
-            guard let ship = aStore.ship(by: $0.shipID) else { return }
+            print("-------")
             
-            if ship.nowhp != $0.hp {
-                
-                Debug.print("\(ship.name)(\(ship.id)),HP \(ship.nowhp) -> \($0.hp)", level: .debug)
+            store.sync {
+                totalDamages.forEach { damage in
+                    
+                    let shipId = damage.shipID
+                    guard let ship = aStore.sync(execute: { aStore.ship(by: shipId) }) else { return }
+                    
+                    let damagedHp = damage.hp
+                    aStore.sync {
+                        if ship.nowhp != damagedHp {
+                            
+                            print("\(ship.name)(\(ship.id)),HP \(ship.nowhp) -> \(damagedHp)")
+                        }
+                    }
+                }
             }
             
-            ship.nowhp = $0.hp
-            
-            if $0.useDamageControl { removeFirstDamageControl(of: ship) }
+            print("------- End Battle")
         }
         
-        Debug.print("------- End Battle", level: .debug)
+        // 第二艦隊単独出撃で正しくデータが反映されるように逆順にして計算
+        store.sync {
+            totalDamages.reversed().forEach { damage in
+                
+                let shipId = damage.shipID
+                guard let ship = aStore.sync(execute: { aStore.ship(by: shipId) }) else { return }
+                
+                let damagedHp = damage.hp
+                aStore.sync { ship.nowhp = damagedHp }
+                
+                if damage.useDamageControl { self.removeFirstDamageControl(of: shipId) }
+            }
+        }
     }
     
     func updateBattleCell() {
         
         let store = TemporaryDataStore.default
         
-        guard let battle = store.battle() else {
+        guard let battle = store.sync(execute: { store.battle() }) else {
             
-            print("Battle is invalid.")
-            return
+            return Logger.shared.log("Battle is invalid.")
         }
         
-        battle.battleCell = (battle.no == 0 ? nil : battle.no as NSNumber)
+        store.sync { battle.battleCell = (battle.no == 0 ? nil : battle.no as NSNumber) }
         
         Debug.excute(level: .debug) {
             
@@ -176,54 +200,52 @@ extension CalculateDamageCommand {
         }
     }
     
-    func removeFirstDamageControl(of ship: Ship) {
-        
-        let equiped = ship.equippedItem
-        let newEquiped = equiped.array
-        let store = ServerDataStore.default
-        var useDamageControl = false
+    func removeFirstDamageControl(of shipId: Int) {
         
-        equiped.forEach {
+        let store = ServerDataStore.oneTimeEditor()
+        store.sync {
             
-            if useDamageControl { return }
+            guard let ship = store.ship(by: shipId) else { return }
             
-            guard let master = $0 as? SlotItem else { return }
+            let (item, damageControl) = ship
+                .equippedItem
+                .lazy
+                .compactMap { $0 as? SlotItem }
+                .map { ($0, store.masterSlotItemID(by: $0.id)) }
+                .map { ($0.0, DamageControlID(rawValue: $0.1)) }
+                .filter { $0.1 != nil }
+                .first ?? (nil, nil)
+            
+            if let validDamageControl = damageControl {
+                
+                switch validDamageControl {
+                case .damageControl: break
+                    
+                case .goddes:
+                    ship.fuel = ship.maxFuel
+                    ship.bull = ship.maxBull
+                }
+                
+                guard let equiped = ship.equippedItem.array as? [SlotItem] else { return }
+                
+                ship.equippedItem = NSOrderedSet(array: equiped.filter { $0 != item })
+                
+                return
+            }
             
-            let masterSlotItemId = store.masterSlotItemID(by: master.id)
+            // check extra slot
+            let exItemId = store.sync { store.masterSlotItemID(by: ship.slot_ex) }
             
-            guard let type = DamageControlID(rawValue: masterSlotItemId) else { return }
+            guard let exType = DamageControlID(rawValue: exItemId) else { return }
             
-            switch type {
+            switch exType {
+            case .damageControl: break
+                
             case .goddes:
                 ship.fuel = ship.maxFuel
                 ship.bull = ship.maxBull
-                fallthrough
-                
-            case .damageControl:
-                if var equiped = newEquiped as? [SlotItem],
-                    let index = equiped.index(of: master) {
-                    
-                    equiped[index...index] = []
-                    ship.equippedItem = NSOrderedSet(array: equiped)
-                    useDamageControl = true
-                }
             }
-        }
-        
-        if useDamageControl { return }
-        
-        // check extra slot
-        let exItemId = store.masterSlotItemID(by: ship.slot_ex)
-        
-        guard let exType = DamageControlID(rawValue: exItemId) else { return }
-        
-        switch exType {
-        case .goddes:
-            ship.fuel = ship.maxFuel
-            ship.bull = ship.maxBull
-            fallthrough
             
-        case .damageControl:
             ship.slot_ex = -1
         }
     }