2 // ChangeHenseiCommand.swift
5 // Created by Hori,Masaki on 2017/01/09.
6 // Copyright © 2017年 Hori,Masaki. All rights reserved.
11 enum ChangeHenseiType: Int {
16 case removeAllWithoutFlagship
19 extension Notification.Name {
21 static let HenseiDidChange = Notification.Name("com.masakih.KCD.Notification.HenseiDidChange")
24 final class HenseiDidChangeUserInfo: NSObject {
26 let type: ChangeHenseiType
32 let replaceFleetNumber: Int?
33 let replacePosition: Int?
34 let replaceShipID: Int?
36 required init(type: ChangeHenseiType,
40 replaceFleetNumber: Int? = nil,
41 replacePosition: Int? = nil,
42 replaceShipID: Int? = nil) {
45 self.fleetNumber = fleetNumber
46 self.position = position
48 self.replaceFleetNumber = replaceFleetNumber
49 self.replacePosition = replacePosition
50 self.replaceShipID = replaceShipID
56 final class ChangeHenseiCommand: JSONCommand {
58 static let userInfoKey = "HenseiDidChangeUserInfoKey"
60 override class func canExecuteAPI(_ api: API) -> Bool {
62 return api.endpoint == .change
66 // ship_id > 0 : 艦娘のID append or replace
67 // ship_id == -1 : remove.
68 // ship_id == -2 : remove all without flag ship.
69 override func execute() {
71 guard let deckNumber = parameter["api_id"].int,
72 let shipId = parameter["api_ship_id"].int,
73 let shipIndex = parameter["api_ship_idx"].int else {
75 return Logger.shared.log("parameter is wrong")
80 guard let shipId = removeShip(deckNumber: deckNumber, index: shipIndex) else { return }
81 notify(type: .remove, fleetNumber: deckNumber, position: shipIndex, shipID: shipId)
87 excludeShipsWithoutFlagShip(deckNumber: deckNumber)
88 notify(type: .removeAllWithoutFlagship)
92 guard case 0..<Deck.maxShipCount = shipIndex else { return }
94 let store = ServerDataStore.oneTimeEditor()
95 guard let deck = store.sync(execute: { store.deck(by: deckNumber) }) else { return }
98 let (shipDeckNumber, shipDeckIndex) = position(of: shipId)
100 // 配置しようとする位置に今配置されている艦娘
101 let replaceShipId = store.sync { deck[shipIndex]?.id }
104 store.sync { deck.setShip(id: shipId, for: shipIndex) }
107 if shipDeckNumber != nil {
109 let shipDeck = store.sync { store.deck(by: shipDeckNumber!) }
110 store.sync { shipDeck?.setShip(id: replaceShipId ?? -1, for: shipDeckIndex) }
111 shipDeck.map { packFleet(store: store, deck: $0) }
114 packFleet(store: store, deck: deck)
117 if shipDeckNumber != nil {
119 notify(type: .replace,
120 fleetNumber: deckNumber,
123 replaceFleetNumber: shipDeckNumber!,
124 replacePosition: shipDeckIndex,
125 replaceShipID: replaceShipId)
129 notify(type: .append, fleetNumber: deckNumber, position: shipIndex, shipID: shipId)
133 private func position(of shipId: Int) -> (deckNumber: Int?, shipId: Int) {
135 let store = ServerDataStore.default
141 .map { (idx, deck) -> (Int, [Ship]) in (idx + 1, deck[0..<Deck.maxShipCount]) }
142 .filter { $0.1.contains { $0.id == shipId } }
143 .map { (deck, ships) in (deck, ships.index(where: { $0.id == shipId })!) }
148 private func removeShip(deckNumber: Int, index: Int) -> Int? {
150 let store = ServerDataStore.oneTimeEditor()
152 guard let deck = store.sync(execute: { store.deck(by: deckNumber) }) else {
154 return Logger.shared.log("Deck not found", value: nil)
157 let shipId = store.sync { deck[index]?.id ?? -1 }
158 store.sync { deck.setShip(id: -1, for: index) }
160 packFleet(store: store, deck: deck)
165 private func excludeShipsWithoutFlagShip(deckNumber: Int) {
167 let store = ServerDataStore.oneTimeEditor()
169 guard let deck = store.deck(by: deckNumber) else {
171 return Logger.shared.log("Deck not found")
174 (1..<Deck.maxShipCount).forEach { deck.setShip(id: -1, for: $0) }
178 private func packFleet(store: ServerDataStore, deck: Deck) {
180 func set(_ ships: [Ship], at index: Int, in deck: Deck) {
182 guard index < Deck.maxShipCount else { return }
184 deck.setShip(id: ships.first?.id ?? -1, for: index)
186 let newShips = ships.isEmpty ? [] : Array(ships[1...])
188 set(newShips, at: index + 1, in: deck)
191 store.sync { set(deck[0..<Deck.maxShipCount], at: 0, in: deck) }
194 private func notify(type: ChangeHenseiType,
195 fleetNumber: Int = 0,
198 replaceFleetNumber: Int? = nil,
199 replacePosition: Int? = nil,
200 replaceShipID: Int? = nil) {
202 let userInfo = HenseiDidChangeUserInfo(type: type,
203 fleetNumber: fleetNumber,
206 replaceFleetNumber: replaceFleetNumber,
207 replacePosition: replacePosition,
208 replaceShipID: replaceShipID)
209 NotificationCenter.default
210 .post(name: .HenseiDidChange,
212 userInfo: [ChangeHenseiCommand.userInfoKey: userInfo])