OSDN Git Service

不要となっていたプロパティを削除
[kcd/KCD.git] / KCD / ChangeHenseiCommand.swift
index 0c112a3..1805712 100644 (file)
@@ -9,17 +9,23 @@
 import Cocoa
 
 enum ChangeHenseiType: Int {
+    
     case append
+    
     case replace
+    
     case remove
+    
     case removeAllWithoutFlagship
 }
 
 extension Notification.Name {
+    
     static let HenseiDidChange = Notification.Name("com.masakih.KCD.Notification.HenseiDidChange")
 }
 
-class HenseiDidChangeUserInfo: NSObject {
+final class HenseiDidChangeUserInfo: NSObject {
+    
     let type: ChangeHenseiType
     
     let fleetNumber: Int
@@ -37,6 +43,7 @@ class HenseiDidChangeUserInfo: NSObject {
                   replaceFleetNumber: Int? = nil,
                   replacePosition: Int? = nil,
                   replaceShipID: Int? = nil) {
+        
         self.type = type
         self.fleetNumber = fleetNumber
         self.position = position
@@ -44,16 +51,18 @@ class HenseiDidChangeUserInfo: NSObject {
         self.replaceFleetNumber = replaceFleetNumber
         self.replacePosition = replacePosition
         self.replaceShipID = replaceShipID
+        
         super.init()
     }
 }
 
-class ChangeHenseiCommand: JSONCommand {
+final class ChangeHenseiCommand: JSONCommand {
+    
     static let userInfoKey = "HenseiDidChangeUserInfoKey"
     
-    override class func canExecuteAPI(_ api: String) -> Bool {
-        if api == "/kcsapi/api_req_hensei/change" { return true }
-        return false
+    override class func canExecuteAPI(_ api: API) -> Bool {
+        
+        return api.endpoint == .change
     }
     
     // api_ship_id の値
@@ -61,85 +70,150 @@ class ChangeHenseiCommand: JSONCommand {
     // ship_id == -1 : remove.
     // ship_id == -2 : remove all without flag ship.
     override func execute() {
-        guard let deckNumber = arguments["api_id"].flatMap({ Int($0) }),
-            let shipId = arguments["api_ship_id"].flatMap({ Int($0) }),
-            let shipIndex = arguments["api_ship_idx"].flatMap({ Int($0) })
-            else { return print("parameter is wrong") }
+        
+        guard let deckNumber = parameter["api_id"].int,
+            let shipId = parameter["api_ship_id"].int,
+            let shipIndex = parameter["api_ship_idx"].int else {
+                
+                Logger.shared.log("parameter is wrong")
+                
+                return
+        }
+        
+        if shipId == -1 {
+            
+            guard let shipId = removeShip(deckNumber: deckNumber, index: shipIndex) else {
+                
+                return
+            }
+            notify(type: .remove, fleetNumber: deckNumber, position: shipIndex, shipID: shipId)
+            
+            return
+        }
+        
         if shipId == -2 {
+            
             excludeShipsWithoutFlagShip(deckNumber: deckNumber)
             notify(type: .removeAllWithoutFlagship)
+            
             return
         }
+        
+        guard case 0..<Deck.maxShipCount = shipIndex else {
+            
+            return
+        }
+        
         let store = ServerDataStore.oneTimeEditor()
-        let decks = store.decksSortedById()
-        let shipIds = decks.flatMap { deck in (0..<6).map { deck.shipId(of: $0) ?? -1 } }
+        guard let deck = store.sync(execute: { store.deck(by: deckNumber) }) else {
+            
+            return
+        }
         
         // すでに編成されているか? どこに?
-        let currentIndex = shipIds.index(of: shipId)
-        let shipDeckNumber = currentIndex.map { $0 / 6 } ?? -1
-        let shipDeckIndex = currentIndex.map { $0 % 6 } ?? -1
+        let (shipDeckNumber, shipDeckIndex) = position(of: shipId)
         
         // 配置しようとする位置に今配置されている艦娘
-        let replaceIndex = (deckNumber - 1) * 6 + shipIndex
-        guard 0..<shipIds.count ~= replaceIndex else { return }
-        let replaceShipId = shipIds[replaceIndex]
+        let replaceShipId = store.sync { deck[shipIndex]?.id }
         
         // 艦隊に配備
-        guard 0..<decks.count ~= (deckNumber - 1) else { return }
-        decks[deckNumber - 1].setShip(id: shipId, for: shipIndex)
+        store.sync { deck.setShip(id: shipId, for: shipIndex) }
         
         // 入れ替え
-        if currentIndex != nil, shipId != -1, 0..<decks.count ~= shipDeckNumber {
-            decks[shipDeckNumber].setShip(id: replaceShipId, for: shipDeckIndex)
+        if shipDeckNumber != nil {
+            
+            let shipDeck = store.sync { store.deck(by: shipDeckNumber!) }
+            store.sync { shipDeck?.setShip(id: replaceShipId ?? -1, for: shipDeckIndex) }
+            shipDeck.map { packFleet(store: store, deck: $0) }
         }
         
-        packFleet(store: store)
+        packFleet(store: store, deck: deck)
         
         // Notify
-        if currentIndex != nil, shipId == -1 {
-            notify(type: .remove,
-                   fleetNumber: deckNumber,
-                   position: shipIndex,
-                   shipID: replaceShipId)
-        } else if currentIndex != nil {
+        if shipDeckNumber != nil {
+            
             notify(type: .replace,
                    fleetNumber: deckNumber,
                    position: shipIndex,
                    shipID: shipId,
-                   replaceFleetNumber: shipDeckNumber + 1,
+                   replaceFleetNumber: shipDeckNumber!,
                    replacePosition: shipDeckIndex,
                    replaceShipID: replaceShipId)
+            
         } else {
-            notify(type: .append,
-                   fleetNumber: deckNumber,
-                   position: shipIndex,
-                   shipID: shipId)
+            
+            notify(type: .append, fleetNumber: deckNumber, position: shipIndex, shipID: shipId)
+        }
+    }
+    
+    private func position(of shipId: Int) -> (deckNumber: Int?, shipId: Int) {
+        
+        let store = ServerDataStore.default
+        
+        return store.sync {
+            
+            store
+                .decksSortedById()
+                .lazy
+                .enumerated()
+                .map { (idx, deck) -> (Int, [Ship]) in (idx + 1, deck[0..<Deck.maxShipCount]) }
+                .filter { $0.1.contains { $0.id == shipId } }
+                .map { (deck, ships) in (deck, ships.index(where: { $0.id == shipId })!) }
+                .first ?? (nil, -1)
+        }
+    }
+    
+    private func removeShip(deckNumber: Int, index: Int) -> Int? {
+        
+        let store = ServerDataStore.oneTimeEditor()
+        
+        guard let deck = store.sync(execute: { store.deck(by: deckNumber) }) else {
+            
+            Logger.shared.log("Deck not found")
+            
+            return nil
         }
+        
+        let shipId = store.sync { deck[index]?.id ?? -1 }
+        store.sync { deck.setShip(id: -1, for: index) }
+        
+        packFleet(store: store, deck: deck)
+        
+        return shipId
     }
     
     private func excludeShipsWithoutFlagShip(deckNumber: Int) {
+        
         let store = ServerDataStore.oneTimeEditor()
-        guard let deck = store.deck(byId: deckNumber)
-            else { return print("Deck not found") }
-        (1..<6).forEach { deck.setShip(id: -1, for: $0) }
+        store.sync {
+            guard let deck = store.deck(by: deckNumber) else {
+                
+                Logger.shared.log("Deck not found")
+                
+                return
+            }
+            
+            (1..<Deck.maxShipCount).forEach { deck.setShip(id: -1, for: $0) }
+        }
     }
     
-    private func packFleet(store: ServerDataStore) {
-        store.decksSortedById()
-            .forEach { (deck) in
-                var needsPack = false
-                (0..<6).forEach {
-                    let shipId = deck.shipId(of: $0)
-                    if (shipId == nil || shipId! == -1) && !needsPack {
-                        needsPack = true
-                        return
-                    }
-                    if needsPack {
-                        deck.setShip(id: shipId!, for: $0 - 1)
-                        if $0 == 5 { deck.setShip(id: -1, for: 5) }
-                    }
-                }
+    private func packFleet(store: ServerDataStore, deck: Deck) {
+        
+        func set(_ ships: [Ship], at index: Int, in deck: Deck) {
+            
+            guard index < Deck.maxShipCount else {
+                
+                return
+            }
+            
+            deck.setShip(id: ships.first?.id ?? -1, for: index)
+            
+            let newShips = ships.isEmpty ? [] : Array(ships[1...])
+            
+            set(newShips, at: index + 1, in: deck)
         }
+        
+        store.sync { set(deck[0..<Deck.maxShipCount], at: 0, in: deck) }
     }
     
     private func notify(type: ChangeHenseiType,
@@ -149,6 +223,7 @@ class ChangeHenseiCommand: JSONCommand {
                         replaceFleetNumber: Int? = nil,
                         replacePosition: Int? = nil,
                         replaceShipID: Int? = nil) {
+        
         let userInfo = HenseiDidChangeUserInfo(type: type,
                                                fleetNumber: fleetNumber,
                                                position: position,