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     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     required init(type: ChangeHenseiType,
34                   fleetNumber: Int,
35                   position: Int,
36                   shipID: Int,
37                   replaceFleetNumber: Int? = nil,
38                   replacePosition: Int? = nil,
39                   replaceShipID: Int? = nil) {
40         self.type = type
41         self.fleetNumber = fleetNumber
42         self.position = position
43         self.shipID = shipID
44         self.replaceFleetNumber = replaceFleetNumber
45         self.replacePosition = replacePosition
46         self.replaceShipID = replaceShipID
47         super.init()
48     }
49 }
50
51 class ChangeHenseiCommand: JSONCommand {
52     static let userInfoKey = "HenseiDidChangeUserInfoKey"
53     
54     override class func canExecuteAPI(_ api: String) -> Bool {
55         if api == "/kcsapi/api_req_hensei/change" { return true }
56         return false
57     }
58     
59     // api_ship_id の値
60     // ship_id > 0 : 艦娘のID append or replace
61     // ship_id == -1 : remove.
62     // ship_id == -2 : remove all without flag ship.
63     override func execute() {
64         guard let deckNumber = parameter["api_id"].int,
65             let shipId = parameter["api_ship_id"].int,
66             let shipIndex = parameter["api_ship_idx"].int
67             else { return print("parameter is wrong") }
68         if shipId == -2 {
69             excludeShipsWithoutFlagShip(deckNumber: deckNumber)
70             notify(type: .removeAllWithoutFlagship)
71             return
72         }
73         let store = ServerDataStore.oneTimeEditor()
74         let decks = store.decksSortedById()
75         let shipIds = decks.flatMap { deck in (0..<6).map { deck.shipId(of: $0) ?? -1 } }
76         
77         // すでに編成されているか? どこに?
78         let currentIndex = shipIds.index(of: shipId)
79         let shipDeckNumber = currentIndex.map { $0 / 6 } ?? -1
80         let shipDeckIndex = currentIndex.map { $0 % 6 } ?? -1
81         
82         // 配置しようとする位置に今配置されている艦娘
83         let replaceIndex = (deckNumber - 1) * 6 + shipIndex
84         guard 0..<shipIds.count ~= replaceIndex else { return }
85         let replaceShipId = shipIds[replaceIndex]
86         
87         // 艦隊に配備
88         guard 0..<decks.count ~= (deckNumber - 1) else { return }
89         decks[deckNumber - 1].setShip(id: shipId, for: shipIndex)
90         
91         // 入れ替え
92         if currentIndex != nil, shipId != -1, 0..<decks.count ~= shipDeckNumber {
93             decks[shipDeckNumber].setShip(id: replaceShipId, for: shipDeckIndex)
94         }
95         
96         packFleet(store: store)
97         
98         // Notify
99         if currentIndex != nil, shipId == -1 {
100             notify(type: .remove,
101                    fleetNumber: deckNumber,
102                    position: shipIndex,
103                    shipID: replaceShipId)
104         } else if currentIndex != nil {
105             notify(type: .replace,
106                    fleetNumber: deckNumber,
107                    position: shipIndex,
108                    shipID: shipId,
109                    replaceFleetNumber: shipDeckNumber + 1,
110                    replacePosition: shipDeckIndex,
111                    replaceShipID: replaceShipId)
112         } else {
113             notify(type: .append,
114                    fleetNumber: deckNumber,
115                    position: shipIndex,
116                    shipID: shipId)
117         }
118     }
119     
120     private func excludeShipsWithoutFlagShip(deckNumber: Int) {
121         let store = ServerDataStore.oneTimeEditor()
122         guard let deck = store.deck(byId: deckNumber)
123             else { return print("Deck not found") }
124         (1..<6).forEach { deck.setShip(id: -1, for: $0) }
125     }
126     
127     private func packFleet(store: ServerDataStore) {
128         store.decksSortedById()
129             .forEach { deck in
130                 var needsPack = false
131                 (0..<6).forEach {
132                     let shipId = deck.shipId(of: $0)
133                     // TODO: うまいことする 強制アンラップを消す
134                     if (shipId == nil || shipId! == -1), !needsPack {
135                         needsPack = true
136                         return
137                     }
138                     if needsPack {
139                         deck.setShip(id: shipId!, for: $0 - 1)
140                         if $0 == 5 { deck.setShip(id: -1, for: 5) }
141                     }
142                 }
143         }
144     }
145     
146     private func notify(type: ChangeHenseiType,
147                         fleetNumber: Int = 0,
148                         position: Int = 0,
149                         shipID: Int = 0,
150                         replaceFleetNumber: Int? = nil,
151                         replacePosition: Int? = nil,
152                         replaceShipID: Int? = nil) {
153         let userInfo = HenseiDidChangeUserInfo(type: type,
154                                                fleetNumber: fleetNumber,
155                                                position: position,
156                                                shipID: shipID,
157                                                replaceFleetNumber: replaceFleetNumber,
158                                                replacePosition: replacePosition,
159                                                replaceShipID: replaceShipID)
160         NotificationCenter.default
161             .post(name: .HenseiDidChange,
162                   object: self,
163                   userInfo: [ChangeHenseiCommand.userInfoKey: userInfo])
164     }
165 }