OSDN Git Service

無駄な行や改行を削除
[kcd/KCD.git] / KCD / ShipMapper.swift
1 //
2 //  ShipMapper.swift
3 //  KCD
4 //
5 //  Created by Hori,Masaki on 2017/02/23.
6 //  Copyright © 2017年 Hori,Masaki. All rights reserved.
7 //
8
9 import Cocoa
10 import SwiftyJSON
11
12 extension MappingConfiguration {
13     
14     func change(dataKeys: [String]) -> MappingConfiguration {
15         
16         return MappingConfiguration(entity: self.entity,
17                                     dataKeys: dataKeys,
18                                     primaryKeys: self.primaryKeys,
19                                     editorStore: self.editorStore,
20                                     ignoreKeys: self.ignoreKeys)
21     }
22 }
23
24 final class ShipMapper: JSONMapper {
25     
26     let apiResponse: APIResponse
27     let configuration: MappingConfiguration<Ship>
28     
29     required init(_ apiResponse: APIResponse) {
30         
31         self.apiResponse = apiResponse
32         self.configuration = MappingConfiguration(entity: Ship.entity,
33                                                   dataKeys: ShipMapper.dataKeys(apiResponse),
34                                                   editorStore: ServerDataStore.oneTimeEditor(),
35                                                   ignoreKeys:
36             ["api_gomes", "api_gomes2", "api_broken", "api_powup",
37              "api_voicef", "api_afterlv", "api_aftershipid", "api_backs",
38              "api_slotnum", "api_stype", "api_name", "api_yomi",
39              "api_raig", "api_luck", "api_saku", "api_raim", "api_baku",
40              "api_taik", "api_houg", "api_houm", "api_tyku",
41              "api_ndock_item", "api_star",
42              "api_ndock_time_str", "api_member_id",
43              "api_fuel_max", "api_bull_max"])
44         
45         // kaisouSlotDepriveでは同時に2種類のデータが入る
46         if let api = ShipAPI(rawValue: apiResponse.api), api == .kaisouSlotDeprive {
47             
48             let conf = self.configuration.change(dataKeys: ["api_data", "api_ship_data", "api_unset_ship"])
49             ShipMapper(apiResponse, configuration: conf).commit()
50         }
51     }
52     
53     private init(_ apiResponse: APIResponse, configuration: MappingConfiguration<Ship>) {
54         
55         self.apiResponse = apiResponse
56         self.configuration = configuration
57     }
58     
59     
60     private enum ShipAPI: String {
61         
62         case getMemberShip = "/kcsapi/api_get_member/ship"
63         case port = "/kcsapi/api_port/port"
64         case getMemberShip3 = "/kcsapi/api_get_member/ship3"
65         case kousyouGetShip = "/kcsapi/api_req_kousyou/getship"
66         case getMemberShipDeck = "/kcsapi/api_get_member/ship_deck"
67         case kaisouPowerUp = "/kcsapi/api_req_kaisou/powerup"
68         case kaisouSlotDeprive = "/kcsapi/api_req_kaisou/slot_deprive"
69     }
70     
71     private class func dataKeys(_ apiResponse: APIResponse) -> [String] {
72         
73         guard let shipApi = ShipAPI(rawValue: apiResponse.api) else { return ["api_data"] }
74         
75         switch shipApi {
76         case .port: return ["api_data", "api_ship"]
77             
78         case .getMemberShip3: return ["api_data", "api_ship_data"]
79             
80         case .kousyouGetShip: return ["api_data", "api_ship"]
81             
82         case .getMemberShipDeck: return ["api_data", "api_ship_data"]
83             
84         case .kaisouPowerUp: return ["api_data", "api_ship"]
85             
86         case .kaisouSlotDeprive: return ["api_data", "api_ship_data", "api_set_ship"]
87             
88         case .getMemberShip: return ["api_data"]
89         }
90     }
91     
92     private var registerIds: [Int] = []
93     private lazy var masterShips: [MasterShip] = {
94         
95         return ServerDataStore.default.sortedMasterShipsById()
96     }()
97     private lazy var slotItems: [SlotItem] = {
98         
99         return ServerDataStore.default.sortedSlotItemsById()
100     }()
101     private var isDeleteNotExist: Bool {
102         
103         guard let shipApi = ShipAPI(rawValue: apiResponse.api) else { return true }
104         
105         switch shipApi {
106         case .getMemberShip3, .kousyouGetShip, .getMemberShipDeck,
107              .kaisouPowerUp, .kaisouSlotDeprive:
108             return false
109             
110         default:
111             return true
112         }
113     }
114     
115     private var store: ServerDataStore? {
116         
117         return configuration.editorStore as? ServerDataStore
118     }
119     
120     func beginRegister(_ ship: Ship) {
121         
122         ship.sally_area = nil
123     }
124     
125     func handleExtraValue(_ value: JSON, forKey key: String, to ship: Ship) -> Bool {
126         
127         // 取得後破棄した装備のデータを削除するため保有IDを保存
128         if key == "api_id" {
129             
130             guard let id = value.int else { return false }
131             
132             registerIds.append(id)
133             
134             return false
135         }
136         
137         if key == "api_ship_id" {
138             
139             guard let masterId = value.int else { return false }
140             
141             setMaster(masterId, to: ship)
142             
143             return true
144         }
145         
146         if key == "api_exp" {
147             
148             guard let exp = value[0].int else { return false }
149             
150             ship.exp = exp
151             
152             return true
153         }
154         
155         if key == "api_slot" {
156             
157             setSlot(value, to: ship)
158             
159             return false
160         }
161         
162         if key == "api_slot_ex" {
163             
164             guard let ex = value.int else { return false }
165             
166             setExtraSlot(ex, to: ship)
167             
168             return false
169         }
170         
171         return false
172     }
173     
174     func finishOperating() {
175         
176         if !isDeleteNotExist { return }
177         
178         store?.ships(exclude: registerIds).forEach { store?.delete($0) }
179     }
180     
181     private func setMaster(_ masterId: Int, to ship: Ship) {
182         
183         if ship.ship_id == masterId { return }
184         
185         guard let mShip = masterShips.binarySearch(comparator: { $0.id ==? masterId }),
186             let masterShip = store?.object(of: MasterShip.entity, with: mShip.objectID) else {
187                 
188                 print("Can not convert to current moc object masterShip")
189                 return
190         }
191         
192         ship.master_ship = masterShip
193         ship.ship_id = masterId
194     }
195     
196     private func setSlot(_ slotItems: JSON, to ship: Ship) {
197         
198         guard let converSlotItems = slotItems.arrayObject as? [Int] else { return }
199         guard let store = store else { return }
200         
201         let newItems: [SlotItem] =
202             converSlotItems.flatMap { item in
203                 
204                 if item == 0 || item == -1 { return nil }
205                 
206                 guard let found = self.slotItems.binarySearch(comparator: { $0.id ==? item }),
207                     let slotItem = store.object(of: SlotItem.entity, with: found.objectID) else {
208                         
209                         let maxV = converSlotItems.last
210                         if maxV != nil, maxV! < item {
211                             
212                             #if DEBUG
213                                 print("item is maybe unregistered, so it is new ship's equipment.")
214                             #endif
215                             return nil
216                         }
217                         print("Can not convert to current moc object slotItem")
218                         return nil
219                 }
220                 
221                 return slotItem
222         }
223         
224         ship.equippedItem = NSOrderedSet(array: newItems)
225     }
226     
227     private func setExtraSlot(_ exSlotItem: Int, to ship: Ship) {
228         
229         guard exSlotItem != -1, exSlotItem != 0 else { return }
230         guard let found = slotItems.binarySearch(comparator: { $0.id ==? exSlotItem }),
231             let ex = store?.object(of: SlotItem.entity, with: found.objectID) else {
232                 
233                 print("Can not convert to current moc object")
234                 return
235         }
236         
237         ship.extraItem = ex
238     }
239 }