OSDN Git Service

swiftlint 'type_body_length'の警告を修正
[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 in (0..<6).map { deck.shipId(of: $0) ?? -1 } }
81         
82         // すでに編成されているか? どこに?
83         let currentIndex = shipIds.index(of: shipId)
84         let shipDeckNumber = currentIndex.map { $0 / 6 } ?? -1
85         let shipDeckIndex = currentIndex.map { $0 % 6 } ?? -1
86         
87         // 配置しようとする位置に今配置されている艦娘
88         let replaceIndex = (deckNumber - 1) * 6 + shipIndex
89         guard 0..<shipIds.count ~= replaceIndex else { return }
90         let replaceShipId = shipIds[replaceIndex]
91         
92         // 艦隊に配備
93         guard 0..<decks.count ~= (deckNumber - 1) else { return }
94         decks[deckNumber - 1].setShip(id: shipId, for: shipIndex)
95         
96         // 入れ替え
97         if currentIndex != nil, shipId != -1, 0..<decks.count ~= shipDeckNumber {
98             decks[shipDeckNumber].setShip(id: replaceShipId, for: shipDeckIndex)
99         }
100         
101         packFleet(store: store)
102         
103         // Notify
104         if currentIndex != nil, shipId == -1 {
105             notify(type: .remove,
106                    fleetNumber: deckNumber,
107                    position: shipIndex,
108                    shipID: replaceShipId)
109         } else if currentIndex != nil {
110             notify(type: .replace,
111                    fleetNumber: deckNumber,
112                    position: shipIndex,
113                    shipID: shipId,
114                    replaceFleetNumber: shipDeckNumber + 1,
115                    replacePosition: shipDeckIndex,
116                    replaceShipID: replaceShipId)
117         } else {
118             notify(type: .append,
119                    fleetNumber: deckNumber,
120                    position: shipIndex,
121                    shipID: shipId)
122         }
123     }
124     
125     private func excludeShipsWithoutFlagShip(deckNumber: Int) {
126         let store = ServerDataStore.oneTimeEditor()
127         guard let deck = store.deck(byId: deckNumber)
128             else { return print("Deck not found") }
129         (1..<6).forEach { deck.setShip(id: -1, for: $0) }
130     }
131     
132     private func packFleet(store: ServerDataStore) {
133         store.decksSortedById()
134             .forEach { (deck) in
135                 var needsPack = false
136                 (0..<6).forEach {
137                     let shipId = deck.shipId(of: $0)
138                     if (shipId == nil || shipId! == -1) && !needsPack {
139                         needsPack = true
140                         return
141                     }
142                     if needsPack {
143                         deck.setShip(id: shipId!, for: $0 - 1)
144                         if $0 == 5 { deck.setShip(id: -1, for: 5) }
145                     }
146                 }
147         }
148     }
149     
150     private func notify(type: ChangeHenseiType,
151                         fleetNumber: Int = 0,
152                         position: Int = 0,
153                         shipID: Int = 0,
154                         replaceFleetNumber: Int? = nil,
155                         replacePosition: Int? = nil,
156                         replaceShipID: Int? = nil) {
157         let userInfo = HenseiDidChangeUserInfo(type: type,
158                                                fleetNumber: fleetNumber,
159                                                position: position,
160                                                shipID: shipID,
161                                                replaceFleetNumber: replaceFleetNumber,
162                                                replacePosition: replacePosition,
163                                                replaceShipID: replaceShipID)
164         NotificationCenter.default
165             .post(name: .HenseiDidChange,
166                   object: self,
167                   userInfo: [ChangeHenseiCommand.userInfoKey: userInfo])
168     }
169 }