2 // ChangeHenseiCommand.swift
5 // Created by Hori,Masaki on 2017/01/09.
6 // Copyright © 2017年 Hori,Masaki. All rights reserved.
11 enum ChangeHenseiType: Int {
19 case removeAllWithoutFlagship
22 extension Notification.Name {
24 static let HenseiDidChange = Notification.Name("com.masakih.KCD.Notification.HenseiDidChange")
27 final class HenseiDidChangeUserInfo: NSObject {
29 let type: ChangeHenseiType
35 let replaceFleetNumber: Int?
36 let replacePosition: Int?
37 let replaceShipID: Int?
39 required init(type: ChangeHenseiType,
43 replaceFleetNumber: Int? = nil,
44 replacePosition: Int? = nil,
45 replaceShipID: Int? = nil) {
48 self.fleetNumber = fleetNumber
49 self.position = position
51 self.replaceFleetNumber = replaceFleetNumber
52 self.replacePosition = replacePosition
53 self.replaceShipID = replaceShipID
59 final class ChangeHenseiCommand: JSONCommand {
61 static let userInfoKey = "HenseiDidChangeUserInfoKey"
63 override class func canExecuteAPI(_ api: API) -> Bool {
65 return api.endpoint == .change
69 // ship_id > 0 : 艦娘のID append or replace
70 // ship_id == -1 : remove.
71 // ship_id == -2 : remove all without flag ship.
72 override func execute() {
74 guard let deckNumber = parameter["api_id"].int,
75 let shipId = parameter["api_ship_id"].int,
76 let shipIndex = parameter["api_ship_idx"].int else {
78 Logger.shared.log("parameter is wrong")
85 guard let shipId = removeShip(deckNumber: deckNumber, index: shipIndex) else {
89 notify(type: .remove, fleetNumber: deckNumber, position: shipIndex, shipID: shipId)
96 excludeShipsWithoutFlagShip(deckNumber: deckNumber)
97 notify(type: .removeAllWithoutFlagship)
102 guard case 0..<Deck.maxShipCount = shipIndex else {
107 let store = ServerDataStore.oneTimeEditor()
108 guard let deck = store.sync(execute: { store.deck(by: deckNumber) }) else {
114 let (shipDeckNumber, shipDeckIndex) = position(of: shipId)
116 // 配置しようとする位置に今配置されている艦娘
117 let replaceShipId = store.sync { deck[shipIndex]?.id }
120 store.sync { deck.setShip(id: shipId, for: shipIndex) }
123 if shipDeckNumber != nil {
125 let shipDeck = store.sync { store.deck(by: shipDeckNumber!) }
126 store.sync { shipDeck?.setShip(id: replaceShipId ?? -1, for: shipDeckIndex) }
127 shipDeck.map { packFleet(store: store, deck: $0) }
130 packFleet(store: store, deck: deck)
133 if shipDeckNumber != nil {
135 notify(type: .replace,
136 fleetNumber: deckNumber,
139 replaceFleetNumber: shipDeckNumber!,
140 replacePosition: shipDeckIndex,
141 replaceShipID: replaceShipId)
145 notify(type: .append, fleetNumber: deckNumber, position: shipIndex, shipID: shipId)
149 private func position(of shipId: Int) -> (deckNumber: Int?, shipId: Int) {
151 let store = ServerDataStore.default
159 .map { (idx, deck) -> (Int, [Ship]) in (idx + 1, deck[0..<Deck.maxShipCount]) }
160 .filter { $0.1.contains { $0.id == shipId } }
161 .map { (deck, ships) in (deck, ships.index(where: { $0.id == shipId })!) }
166 private func removeShip(deckNumber: Int, index: Int) -> Int? {
168 let store = ServerDataStore.oneTimeEditor()
170 guard let deck = store.sync(execute: { store.deck(by: deckNumber) }) else {
172 Logger.shared.log("Deck not found")
177 let shipId = store.sync { deck[index]?.id ?? -1 }
178 store.sync { deck.setShip(id: -1, for: index) }
180 packFleet(store: store, deck: deck)
185 private func excludeShipsWithoutFlagShip(deckNumber: Int) {
187 let store = ServerDataStore.oneTimeEditor()
189 guard let deck = store.deck(by: deckNumber) else {
191 Logger.shared.log("Deck not found")
196 (1..<Deck.maxShipCount).forEach { deck.setShip(id: -1, for: $0) }
200 private func packFleet(store: ServerDataStore, deck: Deck) {
202 func set(_ ships: [Ship], at index: Int, in deck: Deck) {
204 guard index < Deck.maxShipCount else {
209 deck.setShip(id: ships.first?.id ?? -1, for: index)
211 let newShips = ships.isEmpty ? [] : Array(ships[1...])
213 set(newShips, at: index + 1, in: deck)
216 store.sync { set(deck[0..<Deck.maxShipCount], at: 0, in: deck) }
219 private func notify(type: ChangeHenseiType,
220 fleetNumber: Int = 0,
223 replaceFleetNumber: Int? = nil,
224 replacePosition: Int? = nil,
225 replaceShipID: Int? = nil) {
227 let userInfo = HenseiDidChangeUserInfo(type: type,
228 fleetNumber: fleetNumber,
231 replaceFleetNumber: replaceFleetNumber,
232 replacePosition: replacePosition,
233 replaceShipID: replaceShipID)
234 NotificationCenter.default
235 .post(name: .HenseiDidChange,
237 userInfo: [ChangeHenseiCommand.userInfoKey: userInfo])