5 // Created by Hori,Masaki on 2017/02/23.
6 // Copyright © 2017年 Hori,Masaki. All rights reserved.
12 extension MappingConfiguration {
14 func change(dataKeys: [String]) -> MappingConfiguration {
16 return MappingConfiguration(entity: self.entity,
18 primaryKeys: self.primaryKeys,
19 editorStore: self.editorStore,
20 ignoreKeys: self.ignoreKeys)
24 final class ShipMapper: JSONMapper {
26 let apiResponse: APIResponse
27 let configuration: MappingConfiguration<Ship>
29 required init(_ apiResponse: APIResponse) {
31 self.apiResponse = apiResponse
32 self.configuration = MappingConfiguration(entity: Ship.entity,
33 dataKeys: ShipMapper.dataKeys(apiResponse),
34 editorStore: ServerDataStore.oneTimeEditor(),
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"])
45 // kaisouSlotDepriveでは同時に2種類のデータが入る
46 if let api = ShipAPI(rawValue: apiResponse.api),
47 api == .kaisouSlotDeprive {
49 let conf = self.configuration.change(dataKeys: ["api_data", "api_ship_data", "api_unset_ship"])
50 ShipMapper(apiResponse, configuration: conf).commit()
54 private init(_ apiResponse: APIResponse, configuration: MappingConfiguration<Ship>) {
56 self.apiResponse = apiResponse
57 self.configuration = configuration
61 private enum ShipAPI: String {
63 case getMemberShip = "/kcsapi/api_get_member/ship"
64 case port = "/kcsapi/api_port/port"
65 case getMemberShip3 = "/kcsapi/api_get_member/ship3"
66 case kousyouGetShip = "/kcsapi/api_req_kousyou/getship"
67 case getMemberShipDeck = "/kcsapi/api_get_member/ship_deck"
68 case kaisouPowerUp = "/kcsapi/api_req_kaisou/powerup"
69 case kaisouSlotDeprive = "/kcsapi/api_req_kaisou/slot_deprive"
72 private class func dataKeys(_ apiResponse: APIResponse) -> [String] {
74 guard let shipApi = ShipAPI(rawValue: apiResponse.api) else { return ["api_data"] }
77 case .port: return ["api_data", "api_ship"]
79 case .getMemberShip3: return ["api_data", "api_ship_data"]
81 case .kousyouGetShip: return ["api_data", "api_ship"]
83 case .getMemberShipDeck: return ["api_data", "api_ship_data"]
85 case .kaisouPowerUp: return ["api_data", "api_ship"]
87 case .kaisouSlotDeprive: return ["api_data", "api_ship_data", "api_set_ship"]
89 case .getMemberShip: return ["api_data"]
93 private var registerIds: [Int] = []
94 private lazy var masterShips: [MasterShip] = {
96 return ServerDataStore.default.sortedMasterShipsById()
98 private lazy var slotItems: [SlotItem] = {
100 return ServerDataStore.default.sortedSlotItemsById()
102 private var isDeleteNotExist: Bool {
104 guard let shipApi = ShipAPI(rawValue: apiResponse.api) else { return true }
107 case .getMemberShip3, .kousyouGetShip, .getMemberShipDeck,
108 .kaisouPowerUp, .kaisouSlotDeprive:
116 private var store: ServerDataStore? {
118 return configuration.editorStore as? ServerDataStore
121 func beginRegister(_ ship: Ship) {
123 ship.sally_area = nil
126 func handleExtraValue(_ value: JSON, forKey key: String, to ship: Ship) -> Bool {
128 // 取得後破棄した装備のデータを削除するため保有IDを保存
131 guard let id = value.int else { return false }
133 registerIds.append(id)
138 if key == "api_ship_id" {
140 guard let masterId = value.int else { return false }
142 setMaster(masterId, to: ship)
147 if key == "api_exp" {
149 guard let exp = value[0].int else { return false }
156 if key == "api_slot" {
158 setSlot(value, to: ship)
163 if key == "api_slot_ex" {
165 guard let ex = value.int else { return false }
167 setExtraSlot(ex, to: ship)
175 func finishOperating() {
177 if !isDeleteNotExist { return }
179 store?.ships(exclude: registerIds).forEach { store?.delete($0) }
182 private func setMaster(_ masterId: Int, to ship: Ship) {
184 if ship.ship_id == masterId { return }
186 guard let mShip = masterShips.binarySearch(comparator: { $0.id ==? masterId }),
187 let masterShip = store?.object(of: MasterShip.entity, with: mShip.objectID) else {
189 print("Can not convert to current moc object masterShip")
193 ship.master_ship = masterShip
194 ship.ship_id = masterId
197 private func setSlot(_ slotItems: JSON, to ship: Ship) {
199 guard let converSlotItems = slotItems.arrayObject as? [Int] else { return }
200 guard let store = store else { return }
202 let newItems: [SlotItem] =
203 converSlotItems.flatMap { item in
205 if item == 0 || item == -1 { return nil }
207 guard let found = self.slotItems.binarySearch(comparator: { $0.id ==? item }),
208 let slotItem = store.object(of: SlotItem.entity, with: found.objectID) else {
210 let maxV = converSlotItems.last
211 if maxV != nil, maxV! < item {
214 print("item is maybe unregistered, so it is new ship's equipment.")
218 print("Can not convert to current moc object slotItem")
225 ship.equippedItem = NSOrderedSet(array: newItems)
228 private func setExtraSlot(_ exSlotItem: Int, to ship: Ship) {
230 guard exSlotItem != -1, exSlotItem != 0 else { return }
231 guard let found = slotItems.binarySearch(comparator: { $0.id ==? exSlotItem }),
232 let ex = store?.object(of: SlotItem.entity, with: found.objectID) else {
234 print("Can not convert to current moc object")