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 ship = removeShip(deckNumber: deckNumber, index: shipIndex) else { return }
81 notify(type: .remove, fleetNumber: deckNumber, position: shipIndex, shipID: ship.id)
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.deck(by: deckNumber) else { return }
98 let (shipDeckNumber, shipDeckIndex) = position(of: shipId)
100 // 配置しようとする位置に今配置されている艦娘
101 let replaceShipId = deck[shipIndex]?.id
104 deck.setShip(id: shipId, for: shipIndex)
107 if shipDeckNumber != nil {
109 let shipDeck = store.deck(by: shipDeckNumber!)
110 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 return ServerDataStore.default
139 .map { (idx, deck) -> (Int, [Ship]) in (idx + 1, deck[0..<Deck.maxShipCount]) }
140 .filter { $0.1.contains { $0.id == shipId } }
141 .map { (deck, ships) in (deck, ships.index(where: { $0.id == shipId })!) }
145 private func removeShip(deckNumber: Int, index: Int) -> Ship? {
147 let store = ServerDataStore.oneTimeEditor()
149 guard let deck = store.deck(by: deckNumber) else { return Logger.shared.log("Deck not found", value: nil) }
151 let shipId = deck[index]?.id ?? -1
152 deck.setShip(id: -1, for: index)
154 packFleet(store: store, deck: deck)
156 return ServerDataStore.default.ship(by: shipId)
159 private func excludeShipsWithoutFlagShip(deckNumber: Int) {
161 let store = ServerDataStore.oneTimeEditor()
163 guard let deck = store.deck(by: deckNumber) else {
165 return Logger.shared.log("Deck not found")
168 (1..<Deck.maxShipCount).forEach { deck.setShip(id: -1, for: $0) }
171 private func packFleet(store: ServerDataStore, deck: Deck) {
173 func set(_ ships: [Ship], at index: Int, in deck: Deck) {
175 guard index < Deck.maxShipCount else { return }
177 deck.setShip(id: ships.first?.id ?? -1, for: index)
179 let newShips = ships.isEmpty ? [] : Array(ships[1...])
181 set(newShips, at: index + 1, in: deck)
184 set(deck[0..<Deck.maxShipCount], at: 0, in: deck)
187 private func notify(type: ChangeHenseiType,
188 fleetNumber: Int = 0,
191 replaceFleetNumber: Int? = nil,
192 replacePosition: Int? = nil,
193 replaceShipID: Int? = nil) {
195 let userInfo = HenseiDidChangeUserInfo(type: type,
196 fleetNumber: fleetNumber,
199 replaceFleetNumber: replaceFleetNumber,
200 replacePosition: replacePosition,
201 replaceShipID: replaceShipID)
202 NotificationCenter.default
203 .post(name: .HenseiDidChange,
205 userInfo: [ChangeHenseiCommand.userInfoKey: userInfo])