OSDN Git Service

staticプロパティをインスタンスプロパティに変更
[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     
16     case combinedAir
17     
18     case combinedWater
19     
20     case eachCombinedAir
21     
22     case eachCombinedWater
23     
24     case enemyCombined
25 }
26
27 enum DamageControlID: Int {
28     
29     case damageControl = 42
30     
31     case goddes = 43
32 }
33
34 final class CalculateDamageCommand: JSONCommand {
35     
36     override func execute() {
37         
38         switch api.endpoint {
39             
40         case .battle, .airBattle, .ldAirBattle:
41             normalBattle(battleType: .normal)
42             
43         case .combinedEcBattle:
44             enemyCombinedBattle(battleType: .enemyCombined)
45             
46         case .combinedBattle, .combinedAirBattle:
47             combinedAirBattle(battleType: .combinedAir)
48             
49         case .combinedBattleWater, .combinedLdAirBattle:
50             normalBattle(battleType: .combinedWater)
51             
52         case .combinedEachBattle:
53             eachAirBattle(battleType: .eachCombinedAir)
54             
55         case .combinedEachBattleWater:
56             normalBattle(battleType: .eachCombinedWater)
57             
58         case .combinedEachNightToDay:
59             eachNightToDayBattle(battleType: .normal)
60             
61         case .midnightBattle, .midnightSpMidnight:
62             midnightBattle(battleType: .normal)
63             
64         case .combinedMidnightBattle, .combinedSpMidnight:
65             midnightBattle(battleType: .combinedAir)
66             
67         case .combinedEcMidnightBattle:
68             midnightBattle(battleType: .eachCombinedAir)
69             
70         case .battleResult, .combinedBattleResult:
71             applyDamage()
72             resetDamage()
73             
74         default:
75             
76             Logger.shared.log("Missing API: \(apiResponse.api)")
77             
78             return
79         }
80     }
81     
82     func normalBattle(battleType: BattleType) {
83         
84         updateBattleCell()
85         DamageCalculator(json, battleType).calculateBattle()
86     }
87     
88     func combinedAirBattle(battleType: BattleType) {
89         
90         updateBattleCell()
91         DamageCalculator(json, battleType).calcCombinedBattleAir()
92     }
93     
94     func eachAirBattle(battleType: BattleType) {
95         
96         updateBattleCell()
97         DamageCalculator(json, battleType).calcEachBattleAir()
98     }
99     
100     func eachNightToDayBattle(battleType: BattleType) {
101         
102         updateBattleCell()
103         DamageCalculator(json, battleType).calcEachNightToDay()
104     }
105     
106     func enemyCombinedBattle(battleType: BattleType) {
107         
108         updateBattleCell()
109         DamageCalculator(json, battleType).calcEnemyCombinedBattle()
110     }
111     
112     func midnightBattle(battleType: BattleType) {
113         
114         DamageCalculator(json, battleType).calcMidnight()
115     }
116 }
117
118 extension CalculateDamageCommand {
119     
120     func resetDamage() {
121         
122         let store = TemporaryDataStore.oneTimeEditor()
123         
124         store.sync { store.damages().forEach(store.delete) }
125     }
126     
127     func applyDamage() {
128         
129         let store = TemporaryDataStore.oneTimeEditor()
130         
131         let totalDamages = store.sync { store.sortedDamagesById() }
132         
133         let aStore = ServerDataStore.default
134         
135         Debug.excute(level: .debug) {
136             
137             print("-------")
138             
139             store.sync {
140                 
141                 totalDamages.forEach { damage in
142                     
143                     let shipId = damage.shipID
144                     guard let ship = aStore.sync(execute: { aStore.ship(by: shipId) }) else {
145                         
146                         return
147                     }
148                     
149                     let damagedHp = damage.hp
150                     aStore.sync {
151                         
152                         if ship.nowhp != damagedHp {
153                             
154                             print("\(ship.name)(\(ship.id)),HP \(ship.nowhp) -> \(damagedHp)")
155                         }
156                     }
157                 }
158             }
159             
160             print("------- End Battle")
161         }
162         
163         // 第二艦隊単独出撃で正しくデータが反映されるように逆順にして計算
164         store.sync {
165             
166             totalDamages.reversed().forEach { damage in
167                 
168                 let shipId = damage.shipID
169                 guard let ship = aStore.sync(execute: { aStore.ship(by: shipId) }) else {
170                     
171                     return
172                 }
173                 
174                 let damagedHp = damage.hp
175                 aStore.sync { ship.nowhp = damagedHp }
176                 
177                 if damage.useDamageControl {
178                     
179                     self.removeFirstDamageControl(of: shipId)
180                 }
181             }
182         }
183     }
184     
185     func updateBattleCell() {
186         
187         let store = TemporaryDataStore.default
188         
189         guard let battle = store.sync(execute: { store.battle() }) else {
190             
191             Logger.shared.log("Battle is invalid.")
192             
193             return
194         }
195         
196         store.sync { battle.battleCell = (battle.no == 0 ? nil : battle.no as NSNumber) }
197         
198         Debug.excute(level: .debug) {
199             
200             print("Enter Cell ------- ")
201             
202             if let seiku = json["api_data"]["api_kouku"]["api_stage1"]["api_disp_seiku"].int {
203                 
204                 switch seiku {
205                     
206                 case 0: print("制空権 均衡")
207                     
208                 case 1: print("制空権 確保")
209                     
210                 case 2: print("制空権 優勢")
211                     
212                 case 3: print("制空権 劣勢")
213                     
214                 case 4: print("制空権 喪失")
215                     
216                 default: break
217                     
218                 }
219             }
220             
221             if let intercept = json["api_data"]["api_formation"][2].int {
222                 
223                 switch intercept {
224                     
225                 case 1: print("交戦形態 同航戦")
226                     
227                 case 2: print("交戦形態 反航戦")
228                     
229                 case 3: print("交戦形態 T字戦有利")
230                     
231                 case 4: print("交戦形態 T字戦不利")
232                     
233                 default: break
234                     
235                 }
236             }
237         }
238     }
239     
240     func removeFirstDamageControl(of shipId: Int) {
241         
242         let store = ServerDataStore.oneTimeEditor()
243         store.sync {
244             
245             guard let ship = store.ship(by: shipId) else {
246                 
247                 return
248             }
249             
250             let (item, damageControl) = ship
251                 .equippedItem
252                 .lazy
253                 .compactMap { $0 as? SlotItem }
254                 .map { ($0, store.masterSlotItemID(by: $0.id)) }
255                 .map { ($0.0, DamageControlID(rawValue: $0.1)) }
256                 .filter { $0.1 != nil }
257                 .first ?? (nil, nil)
258             
259             if let validDamageControl = damageControl {
260                 
261                 switch validDamageControl {
262                     
263                 case .damageControl: break
264                     
265                 case .goddes:
266                     ship.fuel = ship.maxFuel
267                     ship.bull = ship.maxBull
268                     
269                 }
270                 
271                 guard let equiped = ship.equippedItem.array as? [SlotItem] else {
272                     
273                     return
274                 }
275                 
276                 ship.equippedItem = NSOrderedSet(array: equiped.filter { $0 != item })
277                 
278                 return
279             }
280             
281             // check extra slot
282             let exItemId = store.sync { store.masterSlotItemID(by: ship.slot_ex) }
283             
284             guard let exType = DamageControlID(rawValue: exItemId) else {
285                 
286                 return
287             }
288             
289             switch exType {
290                 
291             case .damageControl: break
292                 
293             case .goddes:
294                 ship.fuel = ship.maxFuel
295                 ship.bull = ship.maxBull
296                 
297             }
298             
299             ship.slot_ex = -1
300         }
301     }
302 }