OSDN Git Service

swiftlint 'statement_position' の警告を修正
[kcd/KCD.git] / KCD / ChangeHenseiCommand.swift
1 //
2 //  ChangeHenseiCommand.swift
3 //  KCD
4 //
5 //  Created by Hori,Masaki on 2017/01/09.
6 //  Copyright © 2017年 Hori,Masaki. All rights reserved.
7 //
8
9 import Cocoa
10
11 enum ChangeHenseiType: Int {
12     case append
13     case replace
14     case remove
15     case removeAllWithoutFlagship
16 }
17
18 extension Notification.Name {
19     static let HenseiDidChange = Notification.Name("com.masakih.KCD.Notification.HenseiDidChange")
20 }
21
22 class HenseiDidChangeUserInfo: NSObject {
23     let type: ChangeHenseiType
24     
25     let fleetNumber: Int
26     let position: Int
27     let shipID: Int
28     
29     let replaceFleetNumber: Int?
30     let replacePosition: Int?
31     let replaceShipID: Int?
32     
33     var objcType: Int { return type.rawValue }
34     var objcReplaceFleetNumbner: NSNumber? { return replaceFleetNumber as NSNumber?? ?? nil }
35     var objcReplacePosition: NSNumber? { return replacePosition as NSNumber?? ?? nil }
36     var objcReplaceShipID: NSNumber? { return replaceShipID as NSNumber?? ?? nil }
37     
38     required init(type: ChangeHenseiType,
39                   fleetNumber: Int,
40                   position: Int,
41                   shipID: Int,
42                   replaceFleetNumber: Int? = nil,
43                   replacePosition: Int? = nil,
44                   replaceShipID: Int? = nil) {
45         self.type = type
46         self.fleetNumber = fleetNumber
47         self.position = position
48         self.shipID = shipID
49         self.replaceFleetNumber = replaceFleetNumber
50         self.replacePosition = replacePosition
51         self.replaceShipID = replaceShipID
52         super.init()
53     }
54 }
55
56 class ChangeHenseiCommand: JSONCommand {
57     static let userInfoKey = "HenseiDidChangeUserInfoKey"
58     
59     override class func canExecuteAPI(_ api: String) -> Bool {
60         if api == "/kcsapi/api_req_hensei/change" { return true }
61         return false
62     }
63     
64     // api_ship_id の値
65     // ship_id > 0 : 艦娘のID append or replace
66     // ship_id == -1 : remove.
67     // ship_id == -2 : remove all without flag ship.
68     override func execute() {
69         guard let deckNumber = arguments["api_id"].flatMap({ Int($0) }),
70             let shipId = arguments["api_ship_id"].flatMap({ Int($0) }),
71             let shipIndex = arguments["api_ship_idx"].flatMap({ Int($0) })
72             else { return print("parameter is wrong") }
73         if shipId == -2 {
74             excludeShipsWithoutFlagShip(deckNumber: deckNumber)
75             notify(type: .removeAllWithoutFlagship)
76             return
77         }
78         let store = ServerDataStore.oneTimeEditor()
79         let decks = store.decksSortedById()
80         let shipIds = decks.flatMap { (deck) -> [Int] in
81             return (0..<6).map {
82                 if let res = deck.value(forKey: "ship_\($0)") as? Int {
83                     return res
84                 }
85                 return -1
86             }
87         }
88         
89         // すでに編成されているか? どこに?
90         let alreadyInFleet = shipIds.contains(shipId)
91         let index = alreadyInFleet ? shipIds.index(of: shipId) : nil
92         let shipDeckNumber = index.map { $0 / 6 } ?? -1
93         let shipDeckIndex = index.map { $0 % 6 } ?? -1
94         
95         // 配置しようとする位置に今配置されている艦娘
96         let currentIndex = (deckNumber - 1) * 6 + shipIndex
97         guard 0..<shipIds.count ~= currentIndex
98             else { return }
99         let replaceShipId = shipIds[currentIndex]
100         
101         // 艦隊に配備
102         guard 0..<decks.count ~= (deckNumber - 1)
103             else { return }
104         let deck = decks[deckNumber - 1]
105         deck.setValue(shipId as NSNumber, forKey: "ship_\(shipIndex)")
106         
107         // 入れ替え
108         if alreadyInFleet,
109             shipId != -1,
110             0..<decks.count ~= shipDeckNumber
111         {
112             let aDeck = decks[shipDeckNumber]
113             aDeck.setValue(replaceShipId, forKey: "ship_\(shipDeckIndex)")
114         }
115         
116         packFleet(store: store)
117         
118         // Notify
119         if alreadyInFleet && shipId == -1 {
120             notify(type: .remove,
121                    fleetNumber: deckNumber,
122                    position: shipIndex,
123                    shipID: replaceShipId)
124         } else if alreadyInFleet {
125             notify(type: .replace,
126                    fleetNumber: deckNumber,
127                    position: shipIndex,
128                    shipID: shipId,
129                    replaceFleetNumber: shipDeckNumber + 1,
130                    replacePosition: shipDeckIndex,
131                    replaceShipID: replaceShipId)
132         } else {
133             notify(type: .append,
134                    fleetNumber: deckNumber,
135                    position: shipIndex,
136                    shipID: shipId)
137         }
138     }
139     
140     private func excludeShipsWithoutFlagShip(deckNumber: Int) {
141         let store = ServerDataStore.oneTimeEditor()
142         guard let deck = store.deck(byId: deckNumber)
143             else { return print("Deck not found") }
144         (1..<6).forEach {
145             deck.setValue(-1 as NSNumber, forKey: "ship_\($0)")
146         }
147     }
148     
149     private func packFleet(store: ServerDataStore) {
150         store.decksSortedById()
151             .forEach { (deck) in
152                 var needsPack = false
153                 (0..<6).forEach {
154                     let shipId = deck.value(forKey: "ship_\($0)") as? Int
155                     if (shipId == nil || shipId! == -1) && !needsPack {
156                         needsPack = true
157                         return
158                     }
159                     if needsPack {
160                         deck.setValue(shipId! as NSNumber, forKey: "ship_\($0 - 1)")
161                         if $0 == 5 {
162                             deck.setValue(-1 as NSNumber, forKey: "ship_5")
163                         }
164                     }
165                 }
166         }
167     }
168     
169     private func notify(type: ChangeHenseiType,
170                         fleetNumber: Int = 0,
171                         position: Int = 0,
172                         shipID: Int = 0,
173                         replaceFleetNumber: Int? = nil,
174                         replacePosition: Int? = nil,
175                         replaceShipID: Int? = nil) {
176         let userInfo = HenseiDidChangeUserInfo(type: type,
177                                                fleetNumber: fleetNumber,
178                                                position: position,
179                                                shipID: shipID,
180                                                replaceFleetNumber: replaceFleetNumber,
181                                                replacePosition: replacePosition,
182                                                replaceShipID: replaceShipID)
183         NotificationCenter.default
184             .post(name: .HenseiDidChange,
185                   object: self,
186                   userInfo: [ChangeHenseiCommand.userInfoKey: userInfo])
187     }
188 }