OSDN Git Service

編成時に空いた枠を詰める操作を修正
[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                 return Logger.shared.log("parameter is wrong")
78         }
79         
80         if shipId == -2 {
81             
82             excludeShipsWithoutFlagShip(deckNumber: deckNumber)
83             notify(type: .removeAllWithoutFlagship)
84             
85             return
86         }
87         
88         let store = ServerDataStore.oneTimeEditor()
89         let decks = store.decksSortedById()
90         let shipIds = decks.flatMap { deck in (0..<6).map { deck.shipId(of: $0) ?? -1 } }
91         
92         // すでに編成されているか? どこに?
93         let currentIndex = shipIds.index(of: shipId)
94         let shipDeckNumber = currentIndex.map { $0 / 6 } ?? -1
95         let shipDeckIndex = currentIndex.map { $0 % 6 } ?? -1
96         
97         // 配置しようとする位置に今配置されている艦娘
98         let replaceIndex = (deckNumber - 1) * 6 + shipIndex
99         
100         guard case 0..<shipIds.count = replaceIndex else { return }
101         
102         let replaceShipId = shipIds[replaceIndex]
103         
104         // 艦隊に配備
105         guard case 0..<decks.count = (deckNumber - 1) else { return }
106         
107         decks[deckNumber - 1].setShip(id: shipId, for: shipIndex)
108         
109         // 入れ替え
110         if currentIndex != nil, shipId != -1, case 0..<decks.count = shipDeckNumber {
111             
112             decks[shipDeckNumber].setShip(id: replaceShipId, for: shipDeckIndex)
113         }
114         
115         packFleet(store: store)
116         
117         // Notify
118         if currentIndex != nil, shipId == -1 {
119             
120             notify(type: .remove,
121                    fleetNumber: deckNumber,
122                    position: shipIndex,
123                    shipID: replaceShipId)
124             
125         } else if currentIndex != nil {
126             
127             notify(type: .replace,
128                    fleetNumber: deckNumber,
129                    position: shipIndex,
130                    shipID: shipId,
131                    replaceFleetNumber: shipDeckNumber + 1,
132                    replacePosition: shipDeckIndex,
133                    replaceShipID: replaceShipId)
134             
135         } else {
136             
137             notify(type: .append,
138                    fleetNumber: deckNumber,
139                    position: shipIndex,
140                    shipID: shipId)
141         }
142     }
143     
144     private func excludeShipsWithoutFlagShip(deckNumber: Int) {
145         
146         let store = ServerDataStore.oneTimeEditor()
147         
148         guard let deck = store.deck(by: deckNumber) else {
149             
150             return Logger.shared.log("Deck not found")
151         }
152         
153         (1..<6).forEach { deck.setShip(id: -1, for: $0) }
154     }
155     
156     private func packFleet(store: ServerDataStore) {
157         
158         store.decksSortedById()
159             .forEach { deck in
160                 
161                 var ships = deck[0..<Deck.maxShipCount]
162                 
163                 (0..<Deck.maxShipCount).forEach {
164                     
165                     let shipId = ships.first?.id ?? -1
166                     deck.setShip(id: shipId, for: $0)
167                     if !ships.isEmpty { ships.removeFirst() }
168                 }
169         }
170     }
171     
172     private func notify(type: ChangeHenseiType,
173                         fleetNumber: Int = 0,
174                         position: Int = 0,
175                         shipID: Int = 0,
176                         replaceFleetNumber: Int? = nil,
177                         replacePosition: Int? = nil,
178                         replaceShipID: Int? = nil) {
179         
180         let userInfo = HenseiDidChangeUserInfo(type: type,
181                                                fleetNumber: fleetNumber,
182                                                position: position,
183                                                shipID: shipID,
184                                                replaceFleetNumber: replaceFleetNumber,
185                                                replacePosition: replacePosition,
186                                                replaceShipID: replaceShipID)
187         NotificationCenter.default
188             .post(name: .HenseiDidChange,
189                   object: self,
190                   userInfo: [ChangeHenseiCommand.userInfoKey: userInfo])
191     }
192 }