OSDN Git Service

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