OSDN Git Service

fd9fdc714ee7e03df1cf7f632fac4d7ee0f3a0ac
[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         }
125         else if alreadyInFleet {
126             notify(type: .replace,
127                    fleetNumber: deckNumber,
128                    position: shipIndex,
129                    shipID: shipId,
130                    replaceFleetNumber: shipDeckNumber + 1,
131                    replacePosition: shipDeckIndex,
132                    replaceShipID: replaceShipId)
133         }
134         else {
135             notify(type: .append,
136                    fleetNumber: deckNumber,
137                    position: shipIndex,
138                    shipID: shipId)
139         }
140     }
141     
142     private func excludeShipsWithoutFlagShip(deckNumber: Int) {
143         let store = ServerDataStore.oneTimeEditor()
144         guard let deck = store.deck(byId: deckNumber)
145             else { return print("Deck not found") }
146         (1..<6).forEach {
147             deck.setValue(-1 as NSNumber, forKey: "ship_\($0)")
148         }
149     }
150     
151     private func packFleet(store: ServerDataStore) {
152         store.decksSortedById()
153             .forEach { (deck) in
154                 var needsPack = false
155                 (0..<6).forEach {
156                     let shipId = deck.value(forKey: "ship_\($0)") as? Int
157                     if (shipId == nil || shipId! == -1) && !needsPack {
158                         needsPack = true
159                         return
160                     }
161                     if needsPack {
162                         deck.setValue(shipId! as NSNumber, forKey: "ship_\($0 - 1)")
163                         if $0 == 5 {
164                             deck.setValue(-1 as NSNumber, forKey: "ship_5")
165                         }
166                     }
167                 }
168         }
169     }
170     
171     private func notify(type: ChangeHenseiType,
172                         fleetNumber: Int = 0,
173                         position: Int = 0,
174                         shipID: Int = 0,
175                         replaceFleetNumber: Int? = nil,
176                         replacePosition: Int? = nil,
177                         replaceShipID: Int? = nil) {
178         let userInfo = HenseiDidChangeUserInfo(type: type,
179                                                fleetNumber: fleetNumber,
180                                                position: position,
181                                                shipID: shipID,
182                                                replaceFleetNumber: replaceFleetNumber,
183                                                replacePosition: replacePosition,
184                                                replaceShipID: replaceShipID)
185         NotificationCenter.default
186             .post(name: .HenseiDidChange,
187                   object: self,
188                   userInfo: [ChangeHenseiCommand.userInfoKey: userInfo])
189     }
190 }