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), api == .kaisouSlotDeprive {
48 let conf = self.configuration.change(dataKeys: ["api_data", "api_ship_data", "api_unset_ship"])
49 ShipMapper(apiResponse, configuration: conf).commit()
53 private init(_ apiResponse: APIResponse, configuration: MappingConfiguration<Ship>) {
55 self.apiResponse = apiResponse
56 self.configuration = configuration
60 private enum ShipAPI: String {
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"
71 private class func dataKeys(_ apiResponse: APIResponse) -> [String] {
73 guard let shipApi = ShipAPI(rawValue: apiResponse.api) else { return ["api_data"] }
76 case .port: return ["api_data", "api_ship"]
78 case .getMemberShip3: return ["api_data", "api_ship_data"]
80 case .kousyouGetShip: return ["api_data", "api_ship"]
82 case .getMemberShipDeck: return ["api_data", "api_ship_data"]
84 case .kaisouPowerUp: return ["api_data", "api_ship"]
86 case .kaisouSlotDeprive: return ["api_data", "api_ship_data", "api_set_ship"]
88 case .getMemberShip: return ["api_data"]
92 private var registerIds: [Int] = []
93 private lazy var masterShips: [MasterShip] = {
95 return ServerDataStore.default.sortedMasterShipsById()
97 private lazy var slotItems: [SlotItem] = {
99 return ServerDataStore.default.sortedSlotItemsById()
101 private var isDeleteNotExist: Bool {
103 guard let shipApi = ShipAPI(rawValue: apiResponse.api) else { return true }
106 case .getMemberShip3, .kousyouGetShip, .getMemberShipDeck,
107 .kaisouPowerUp, .kaisouSlotDeprive:
115 private var store: ServerDataStore? {
117 return configuration.editorStore as? ServerDataStore
120 func beginRegister(_ ship: Ship) {
122 ship.sally_area = nil
125 func handleExtraValue(_ value: JSON, forKey key: String, to ship: Ship) -> Bool {
127 // 取得後破棄した装備のデータを削除するため保有IDを保存
130 guard let id = value.int else { return false }
132 registerIds.append(id)
137 if key == "api_ship_id" {
139 guard let masterId = value.int else { return false }
141 setMaster(masterId, to: ship)
146 if key == "api_exp" {
148 guard let exp = value[0].int else { return false }
155 if key == "api_slot" {
157 setSlot(value, to: ship)
162 if key == "api_slot_ex" {
164 guard let ex = value.int else { return false }
166 setExtraSlot(ex, to: ship)
174 func finishOperating() {
176 if !isDeleteNotExist { return }
178 store?.ships(exclude: registerIds).forEach { store?.delete($0) }
181 private func setMaster(_ masterId: Int, to ship: Ship) {
183 if ship.ship_id == masterId { return }
185 guard let mShip = masterShips.binarySearch(comparator: { $0.id ==? masterId }),
186 let masterShip = store?.object(of: MasterShip.entity, with: mShip.objectID) else {
188 print("Can not convert to current moc object masterShip")
192 ship.master_ship = masterShip
193 ship.ship_id = masterId
196 private func setSlot(_ slotItems: JSON, to ship: Ship) {
198 guard let converSlotItems = slotItems.arrayObject as? [Int] else { return }
199 guard let store = store else { return }
201 let newItems: [SlotItem] =
202 converSlotItems.flatMap { item in
204 if item == 0 || item == -1 { return nil }
206 guard let found = self.slotItems.binarySearch(comparator: { $0.id ==? item }),
207 let slotItem = store.object(of: SlotItem.entity, with: found.objectID) else {
209 let maxV = converSlotItems.last
210 if maxV != nil, maxV! < item {
213 print("item is maybe unregistered, so it is new ship's equipment.")
217 print("Can not convert to current moc object slotItem")
224 ship.equippedItem = NSOrderedSet(array: newItems)
227 private func setExtraSlot(_ exSlotItem: Int, to ship: Ship) {
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 {
233 print("Can not convert to current moc object")