OSDN Git Service

出撃情報表示に関する部分を別クラスに分けた
[kcd/KCD.git] / KCD / CalculateDamageCommand.swift
1 //
2 //  CalculateDamageCommand.swift
3 //  KCD
4 //
5 //  Created by Hori,Masaki on 2017/01/15.
6 //  Copyright © 2017年 Hori,Masaki. All rights reserved.
7 //
8
9 import Cocoa
10 import SwiftyJSON
11
12 enum BattleType {
13     
14     case normal
15     case combinedAir
16     case combinedWater
17     case eachCombinedAir
18     case eachCombinedWater
19     case enemyCombined
20 }
21
22 enum DamageControlID: Int {
23     
24     case damageControl = 42
25     case goddes = 43
26 }
27
28 final class CalculateDamageCommand: JSONCommand {
29     
30     override func execute() {
31         
32         guard let battleApi = BattleAPI(rawValue: api) else { return }
33         
34         switch battleApi {
35         case .battle, .airBattle, .ldAirBattle:
36             normalBattle(battleType: .normal)
37             
38         case .combinedEcBattle:
39             enemyCombinedBattle(battleType: .enemyCombined)
40             
41         case .combinedBattle, .combinedAirBattle:
42             combinedAirBattle(battleType: .combinedAir)
43             
44         case .combinedBattleWater, .combinedLdAirBattle:
45             normalBattle(battleType: .combinedWater)
46             
47         case .combinedEachBattle:
48             eachAirBattle(battleType: .eachCombinedAir)
49             
50         case .combinedEachBattleWater:
51             normalBattle(battleType: .eachCombinedWater)
52             
53         case .midnightBattle, .midnightSpMidnight:
54             midnightBattle(battleType: .normal)
55             
56         case .combinedMidnightBattle, .combinedSpMidnight:
57             midnightBattle(battleType: .combinedAir)
58             
59         case .combinedEcMidnightBattle:
60             midnightBattle(battleType: .eachCombinedAir)
61             
62         case .battleResult, .combinedBattleResult:
63             applyDamage()
64             resetDamage()
65         }
66     }
67     
68     func normalBattle(battleType: BattleType) {
69         
70         updateBattleCell()
71         DamageCalculator(json, battleType).calculateBattle()
72     }
73     
74     func combinedAirBattle(battleType: BattleType) {
75         
76         updateBattleCell()
77         DamageCalculator(json, battleType).calcCombinedBattleAir()
78     }
79     
80     func eachAirBattle(battleType: BattleType) {
81         
82         updateBattleCell()
83         DamageCalculator(json, battleType).calcEachBattleAir()
84     }
85     
86     func enemyCombinedBattle(battleType: BattleType) {
87         
88         updateBattleCell()
89         DamageCalculator(json, battleType).calcEnemyCombinedBattle()
90     }
91     
92     func midnightBattle(battleType: BattleType) {
93         
94         DamageCalculator(json, battleType).calcMidnight()
95     }
96 }
97
98 extension CalculateDamageCommand {
99     
100     func resetDamage() {
101         
102         let store = TemporaryDataStore.oneTimeEditor()
103         
104         store.damages().forEach(store.delete)
105     }
106     
107     func applyDamage() {
108         
109         let store = TemporaryDataStore.oneTimeEditor()
110         
111         let totalDamages = store.sortedDamagesById()
112         
113         let aStore = ServerDataStore.oneTimeEditor()
114         
115         Debug.excute(level: .debug) {
116             
117             print("-------")
118             
119             totalDamages.forEach {
120                 
121                 guard let ship = aStore.ship(by: $0.shipID) else { return }
122                 
123                 if ship.nowhp != $0.hp {
124                     
125                     print("\(ship.name)(\(ship.id)),HP \(ship.nowhp) -> \($0.hp)")
126                 }
127             }
128             
129             
130             print("------- End Battle")
131         }
132         
133         // 第二艦隊単独出撃で正しくデータが反映されるように逆順にして計算
134         totalDamages.reversed().forEach {
135             
136             guard let ship = aStore.ship(by: $0.shipID) else { return }
137             
138             ship.nowhp = $0.hp
139             
140             if $0.useDamageControl { removeFirstDamageControl(of: ship) }
141         }
142         
143     }
144     
145     func updateBattleCell() {
146         
147         let store = TemporaryDataStore.default
148         
149         guard let battle = store.battle() else { return Logger.shared.log("Battle is invalid.") }
150         
151         battle.battleCell = (battle.no == 0 ? nil : battle.no as NSNumber)
152         
153         Debug.excute(level: .debug) {
154             
155             print("Enter Cell ------- ")
156             
157             if let seiku = json["api_data"]["api_kouku"]["api_stage1"]["api_disp_seiku"].int {
158                 
159                 switch seiku {
160                 case 0: print("制空権 均衡")
161                 case 1: print("制空権 確保")
162                 case 2: print("制空権 優勢")
163                 case 3: print("制空権 劣勢")
164                 case 4: print("制空権 喪失")
165                 default: break
166                 }
167             }
168             
169             if let intercept = json["api_data"]["api_formation"][2].int {
170                 
171                 switch intercept {
172                 case 1: print("交戦形態 同航戦")
173                 case 2: print("交戦形態 反航戦")
174                 case 3: print("交戦形態 T字戦有利")
175                 case 4: print("交戦形態 T字戦不利")
176                 default: break
177                 }
178             }
179         }
180     }
181     
182     func removeFirstDamageControl(of ship: Ship) {
183         
184         let store = ServerDataStore.default
185         
186         let (item, damageControl) = ship
187             .equippedItem
188             .lazy
189             .flatMap { $0 as? SlotItem }
190             .map { ($0, store.masterSlotItemID(by: $0.id)) }
191             .map { ($0.0, DamageControlID(rawValue: $0.1)) }
192             .filter { $0.1 != nil }
193             .first ?? (nil, nil)
194         
195         if let validDamageControl = damageControl {
196             
197             switch validDamageControl {
198             case .damageControl: break
199                 
200             case .goddes:
201                 ship.fuel = ship.maxFuel
202                 ship.bull = ship.maxBull
203             }
204             
205             guard let equiped = ship.equippedItem.array as? [SlotItem] else { return }
206                 
207             ship.equippedItem = NSOrderedSet(array: equiped.filter { $0 != item })
208             
209             return
210         }
211         
212         // check extra slot
213         let exItemId = store.masterSlotItemID(by: ship.slot_ex)
214         
215         guard let exType = DamageControlID(rawValue: exItemId) else { return }
216         
217         switch exType {
218         case .damageControl: break
219             
220         case .goddes:
221             ship.fuel = ship.maxFuel
222             ship.bull = ship.maxBull
223         }
224         
225         ship.slot_ex = -1
226     }
227 }