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: String) -> Bool {
62 if api == "/kcsapi/api_req_hensei/change" { return true }
68 // ship_id > 0 : 艦娘のID append or replace
69 // ship_id == -1 : remove.
70 // ship_id == -2 : remove all without flag ship.
71 override func execute() {
73 guard let deckNumber = parameter["api_id"].int,
74 let shipId = parameter["api_ship_id"].int,
75 let shipIndex = parameter["api_ship_idx"].int else {
77 return Logger.shared.log("parameter is wrong")
82 guard let ship = removeShip(deckNumber: deckNumber, index: shipIndex) else { return }
83 notify(type: .remove, fleetNumber: deckNumber, position: shipIndex, shipID: ship.id)
89 excludeShipsWithoutFlagShip(deckNumber: deckNumber)
90 notify(type: .removeAllWithoutFlagship)
94 guard case 0..<Deck.maxShipCount = shipIndex else { return }
96 let store = ServerDataStore.oneTimeEditor()
97 guard let deck = store.deck(by: deckNumber) else { return }
100 let (shipDeckNumber, shipDeckIndex) = position(of: shipId)
102 // 配置しようとする位置に今配置されている艦娘
103 let replaceShipId = deck[shipIndex]?.id
106 deck.setShip(id: shipId, for: shipIndex)
109 if shipDeckNumber != nil {
111 let shipDeck = store.deck(by: shipDeckNumber!)
112 shipDeck?.setShip(id: replaceShipId ?? -1, for: shipDeckIndex)
113 shipDeck.map { packFleet(store: store, deck: $0) }
116 packFleet(store: store, deck: deck)
119 if shipDeckNumber != nil {
121 notify(type: .replace,
122 fleetNumber: deckNumber,
125 replaceFleetNumber: shipDeckNumber!,
126 replacePosition: shipDeckIndex,
127 replaceShipID: replaceShipId)
131 notify(type: .append, fleetNumber: deckNumber, position: shipIndex, shipID: shipId)
135 private func position(of shipId: Int) -> (deckNumber: Int?, shipId: Int) {
137 return 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 })!) }
147 private func removeShip(deckNumber: Int, index: Int) -> Ship? {
149 let store = ServerDataStore.oneTimeEditor()
151 guard let deck = store.deck(by: deckNumber) else { return Logger.shared.log("Deck not found", value: nil) }
153 let shipId = deck[index]?.id ?? -1
154 deck.setShip(id: -1, for: index)
156 packFleet(store: store, deck: deck)
158 return ServerDataStore.default.ship(by: shipId)
161 private func excludeShipsWithoutFlagShip(deckNumber: Int) {
163 let store = ServerDataStore.oneTimeEditor()
165 guard let deck = store.deck(by: deckNumber) else {
167 return Logger.shared.log("Deck not found")
170 (1..<Deck.maxShipCount).forEach { deck.setShip(id: -1, for: $0) }
173 private func packFleet(store: ServerDataStore, deck: Deck) {
175 func set(_ ships: [Ship], at index: Int, in deck: Deck) {
177 guard index < Deck.maxShipCount else { return }
179 deck.setShip(id: ships.first?.id ?? -1, for: index)
181 let newShips = ships.isEmpty ? [] : Array(ships[1...])
183 set(newShips, at: index + 1, in: deck)
186 set(deck[0..<Deck.maxShipCount], at: 0, in: deck)
189 private func notify(type: ChangeHenseiType,
190 fleetNumber: Int = 0,
193 replaceFleetNumber: Int? = nil,
194 replacePosition: Int? = nil,
195 replaceShipID: Int? = nil) {
197 let userInfo = HenseiDidChangeUserInfo(type: type,
198 fleetNumber: fleetNumber,
201 replaceFleetNumber: replaceFleetNumber,
202 replacePosition: replacePosition,
203 replaceShipID: replaceShipID)
204 NotificationCenter.default
205 .post(name: .HenseiDidChange,
207 userInfo: [ChangeHenseiCommand.userInfoKey: userInfo])