OSDN Git Service

guard の書き方を統一した
[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     
13     case append
14     case replace
15     case remove
16     case removeAllWithoutFlagship
17 }
18
19 extension Notification.Name {
20     
21     static let HenseiDidChange = Notification.Name("com.masakih.KCD.Notification.HenseiDidChange")
22 }
23
24 final class HenseiDidChangeUserInfo: NSObject {
25     
26     let type: ChangeHenseiType
27     
28     let fleetNumber: Int
29     let position: Int
30     let shipID: Int
31     
32     let replaceFleetNumber: Int?
33     let replacePosition: Int?
34     let replaceShipID: Int?
35     
36     required init(type: ChangeHenseiType,
37                   fleetNumber: Int,
38                   position: Int,
39                   shipID: Int,
40                   replaceFleetNumber: Int? = nil,
41                   replacePosition: Int? = nil,
42                   replaceShipID: Int? = nil) {
43         
44         self.type = type
45         self.fleetNumber = fleetNumber
46         self.position = position
47         self.shipID = shipID
48         self.replaceFleetNumber = replaceFleetNumber
49         self.replacePosition = replacePosition
50         self.replaceShipID = replaceShipID
51         
52         super.init()
53     }
54 }
55
56 final class ChangeHenseiCommand: JSONCommand {
57     
58     static let userInfoKey = "HenseiDidChangeUserInfoKey"
59     
60     override class func canExecuteAPI(_ api: String) -> Bool {
61         
62         if api == "/kcsapi/api_req_hensei/change" { return true }
63         
64         return false
65     }
66     
67     // api_ship_id の値
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() {
72         
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 {
76                 
77                 print("parameter is wrong")
78                 return
79         }
80         
81         if shipId == -2 {
82             
83             excludeShipsWithoutFlagShip(deckNumber: deckNumber)
84             notify(type: .removeAllWithoutFlagship)
85             
86             return
87         }
88         
89         let store = ServerDataStore.oneTimeEditor()
90         let decks = store.decksSortedById()
91         let shipIds = decks.flatMap { deck in (0..<6).map { deck.shipId(of: $0) ?? -1 } }
92         
93         // すでに編成されているか? どこに?
94         let currentIndex = shipIds.index(of: shipId)
95         let shipDeckNumber = currentIndex.map { $0 / 6 } ?? -1
96         let shipDeckIndex = currentIndex.map { $0 % 6 } ?? -1
97         
98         // 配置しようとする位置に今配置されている艦娘
99         let replaceIndex = (deckNumber - 1) * 6 + shipIndex
100         
101         guard case 0..<shipIds.count = replaceIndex else { return }
102         
103         let replaceShipId = shipIds[replaceIndex]
104         
105         // 艦隊に配備
106         guard case 0..<decks.count = (deckNumber - 1) else { return }
107         
108         decks[deckNumber - 1].setShip(id: shipId, for: shipIndex)
109         
110         // 入れ替え
111         if currentIndex != nil, shipId != -1, case 0..<decks.count = shipDeckNumber {
112             
113             decks[shipDeckNumber].setShip(id: replaceShipId, for: shipDeckIndex)
114         }
115         
116         packFleet(store: store)
117         
118         // Notify
119         if currentIndex != nil, shipId == -1 {
120             
121             notify(type: .remove,
122                    fleetNumber: deckNumber,
123                    position: shipIndex,
124                    shipID: replaceShipId)
125             
126         } else if currentIndex != nil {
127             
128             notify(type: .replace,
129                    fleetNumber: deckNumber,
130                    position: shipIndex,
131                    shipID: shipId,
132                    replaceFleetNumber: shipDeckNumber + 1,
133                    replacePosition: shipDeckIndex,
134                    replaceShipID: replaceShipId)
135             
136         } else {
137             
138             notify(type: .append,
139                    fleetNumber: deckNumber,
140                    position: shipIndex,
141                    shipID: shipId)
142         }
143     }
144     
145     private func excludeShipsWithoutFlagShip(deckNumber: Int) {
146         
147         let store = ServerDataStore.oneTimeEditor()
148         
149         guard let deck = store.deck(by: deckNumber) else {
150             
151             print("Deck not found")
152             return
153         }
154         
155         (1..<6).forEach { deck.setShip(id: -1, for: $0) }
156     }
157     
158     private func packFleet(store: ServerDataStore) {
159         
160         store.decksSortedById()
161             .forEach { deck in
162                 
163                 var needsPack = false
164                 (0..<6).forEach {
165                     
166                     let shipId = deck.shipId(of: $0)
167                     // TODO: うまいことする 強制アンラップを消す
168                     if (shipId == nil || shipId! == -1), !needsPack {
169                         
170                         needsPack = true
171                         
172                         return
173                     }
174                     if needsPack {
175                         
176                         deck.setShip(id: shipId!, for: $0 - 1)
177                         if $0 == 5 { deck.setShip(id: -1, for: 5) }
178                     }
179                 }
180         }
181     }
182     
183     private func notify(type: ChangeHenseiType,
184                         fleetNumber: Int = 0,
185                         position: Int = 0,
186                         shipID: Int = 0,
187                         replaceFleetNumber: Int? = nil,
188                         replacePosition: Int? = nil,
189                         replaceShipID: Int? = nil) {
190         
191         let userInfo = HenseiDidChangeUserInfo(type: type,
192                                                fleetNumber: fleetNumber,
193                                                position: position,
194                                                shipID: shipID,
195                                                replaceFleetNumber: replaceFleetNumber,
196                                                replacePosition: replacePosition,
197                                                replaceShipID: replaceShipID)
198         NotificationCenter.default
199             .post(name: .HenseiDidChange,
200                   object: self,
201                   userInfo: [ChangeHenseiCommand.userInfoKey: userInfo])
202     }
203 }