import Cocoa
import SwiftyJSON
-extension MappingConfiguration {
-
- func change(dataKeys: [String]) -> MappingConfiguration {
-
- return MappingConfiguration(entity: self.entity,
- dataKeys: dataKeys,
- primaryKeys: self.primaryKeys,
- editorStore: self.editorStore,
- ignoreKeys: self.ignoreKeys)
- }
-}
-
final class ShipMapper: JSONMapper {
- typealias ObjectType = Ship
+ private static let ignoreKeys: Set<String> = ["api_gomes", "api_gomes2", "api_broken", "api_powup",
+ "api_voicef", "api_afterlv", "api_aftershipid", "api_backs",
+ "api_slotnum", "api_stype", "api_name", "api_yomi",
+ "api_raig", "api_luck", "api_saku", "api_raim", "api_baku",
+ "api_taik", "api_houg", "api_houm", "api_tyku",
+ "api_ndock_item", "api_star",
+ "api_ndock_time_str", "api_member_id",
+ "api_fuel_max", "api_bull_max"]
+
let apiResponse: APIResponse
let configuration: MappingConfiguration<Ship>
required init(_ apiResponse: APIResponse) {
self.apiResponse = apiResponse
- self.configuration = MappingConfiguration(entity: Ship.entity,
+ self.configuration = MappingConfiguration(entity: Ship.self,
dataKeys: ShipMapper.dataKeys(apiResponse),
editorStore: ServerDataStore.oneTimeEditor(),
- ignoreKeys:
- ["api_gomes", "api_gomes2", "api_broken", "api_powup",
- "api_voicef", "api_afterlv", "api_aftershipid", "api_backs",
- "api_slotnum", "api_stype", "api_name", "api_yomi",
- "api_raig", "api_luck", "api_saku", "api_raim", "api_baku",
- "api_taik", "api_houg", "api_houm", "api_tyku",
- "api_ndock_item", "api_star",
- "api_ndock_time_str", "api_member_id",
- "api_fuel_max", "api_bull_max"])
-
- // kaisouSlotDepriveでは同時に2種類のデータが入る
- if let api = ShipAPI(rawValue: apiResponse.api),
- api == .kaisouSlotDeprive {
-
- let conf = self.configuration.change(dataKeys: ["api_data", "api_ship_data", "api_unset_ship"])
- ShipMapper(apiResponse, configuration: conf).commit()
- }
+ ignoreKeys: ShipMapper.ignoreKeys)
}
- private init(_ apiResponse: APIResponse, configuration: MappingConfiguration<Ship>) {
+ // slotDepriveの時に2種類のデータが来るため
+ init(forSlotDepriveUnset apiResponse: APIResponse) {
self.apiResponse = apiResponse
- self.configuration = configuration
- }
-
-
- private enum ShipAPI: String {
-
- case getMemberShip = "/kcsapi/api_get_member/ship"
- case port = "/kcsapi/api_port/port"
- case getMemberShip3 = "/kcsapi/api_get_member/ship3"
- case kousyouGetShip = "/kcsapi/api_req_kousyou/getship"
- case getMemberShipDeck = "/kcsapi/api_get_member/ship_deck"
- case kaisouPowerUp = "/kcsapi/api_req_kaisou/powerup"
- case kaisouSlotDeprive = "/kcsapi/api_req_kaisou/slot_deprive"
+ self.configuration = MappingConfiguration(entity: Ship.self,
+ dataKeys: ["api_data", "api_ship_data", "api_unset_ship"],
+ editorStore: ServerDataStore.oneTimeEditor(),
+ ignoreKeys: ShipMapper.ignoreKeys)
}
private class func dataKeys(_ apiResponse: APIResponse) -> [String] {
- guard let shipApi = ShipAPI(rawValue: apiResponse.api)
- else { return ["api_data"] }
-
- switch shipApi {
- case .port: return ["api_data", "api_ship"]
+ switch apiResponse.api.endpoint {
- case .getMemberShip3: return ["api_data", "api_ship_data"]
+ case .port, .getShip, .powerup: return ["api_data", "api_ship"]
- case .kousyouGetShip: return ["api_data", "api_ship"]
+ case .ship3, .shipDeck: return ["api_data", "api_ship_data"]
- case .getMemberShipDeck: return ["api_data", "api_ship_data"]
+ case .slotDeprive: return ["api_data", "api_ship_data", "api_set_ship"]
- case .kaisouPowerUp: return ["api_data", "api_ship"]
+ case .ship, .ship2: return ["api_data"]
- case .kaisouSlotDeprive: return ["api_data", "api_ship_data", "api_set_ship"]
+ default:
+
+ Logger.shared.log("Missing API: \(apiResponse.api)")
- case .getMemberShip: return ["api_data"]
+ return ["api_data"]
}
}
private var registerIds: [Int] = []
private lazy var masterShips: [MasterShip] = {
- return ServerDataStore.default.sortedMasterShipsById()
+ guard let store = configuration.editorStore as? ServerDataStore else {
+
+ return []
+ }
+
+ return store.sortedMasterShipsById()
+
}()
private lazy var slotItems: [SlotItem] = {
- return ServerDataStore.default.sortedSlotItemsById()
- }()
- private var isDeleteNotExist: Bool {
+ guard let store = configuration.editorStore as? ServerDataStore else {
+
+ return []
+ }
- guard let shipApi = ShipAPI(rawValue: apiResponse.api)
- else { return true }
+ return store.sortedSlotItemsById()
+ }()
+
+ private var needsDeleteUnregisteredShip: Bool {
- switch shipApi {
- case .getMemberShip3, .kousyouGetShip, .getMemberShipDeck,
- .kaisouPowerUp, .kaisouSlotDeprive:
+ switch apiResponse.api.endpoint {
+
+ case .ship3, .getShip, .shipDeck, .powerup, .slotDeprive:
+
return false
+ case .ship2:
+ // 特殊任務のクリア時にship2がapi_shipid付きでリクエストされ、その艦娘のデータしかない時があるため
+
+ return !apiResponse.parameter["api_shipid"].valid
+
default:
+
return true
+
}
}
// 取得後破棄した装備のデータを削除するため保有IDを保存
if key == "api_id" {
- guard let id = value.int
- else { return false }
+ guard let id = value.int else {
+
+ return false
+ }
registerIds.append(id)
if key == "api_ship_id" {
- guard let masterId = value.int
- else { return false }
+ guard let masterId = value.int else {
+
+ return false
+ }
+
+ if ship.ship_id == masterId {
+
+ return true
+ }
setMaster(masterId, to: ship)
if key == "api_exp" {
- guard let exp = value[0].int
- else { return false }
+ guard let exp = value[0].int else {
+
+ return false
+ }
+
+ if ship.exp == exp {
+
+ return true
+ }
ship.exp = exp
if key == "api_slot_ex" {
- guard let ex = value.int
- else { return false }
+ guard let ex = value.int else {
+
+ ship.extraItem = nil
+
+ return false
+ }
+
+ if ship.slot_ex == ex {
+
+ return true
+ }
setExtraSlot(ex, to: ship)
- return false
+ ship.slot_ex = ex
+
+ return true
}
return false
func finishOperating() {
- if !isDeleteNotExist { return }
+ if !needsDeleteUnregisteredShip {
+
+ return
+ }
store?.ships(exclude: registerIds).forEach { store?.delete($0) }
}
private func setMaster(_ masterId: Int, to ship: Ship) {
- if ship.ship_id == masterId { return }
-
guard let mShip = masterShips.binarySearch(comparator: { $0.id ==? masterId }),
- let masterShip = store?.object(with: mShip.objectID) as? MasterShip
- else { return print("Can not convert to current moc object masterShip") }
+ let masterShip = store?.exchange(mShip) else {
+
+ Logger.shared.log("Can not convert to current moc object masterShip")
+
+ return
+ }
ship.master_ship = masterShip
ship.ship_id = masterId
private func setSlot(_ slotItems: JSON, to ship: Ship) {
- guard let converSlotItems = slotItems.arrayObject as? [Int],
- let store = store
- else { return }
+ guard let convertedSlotItems = slotItems.arrayObject as? [Int] else {
+
+ return
+ }
+ guard let store = store else {
+
+ return
+ }
- let newItems: [SlotItem] =
- converSlotItems.flatMap { item in
-
- if item == 0 || item == -1 { return nil }
+ let newItems: [SlotItem] = convertedSlotItems
+ .filter { $0 != 0 && $0 != -1 }
+ .compactMap { item in
guard let found = self.slotItems.binarySearch(comparator: { $0.id ==? item }),
- let slotItem = store.object(with: found.objectID) as? SlotItem
- else {
+ let slotItem = store.exchange(found) else {
- let maxV = converSlotItems.last
+ let maxV = convertedSlotItems.last
if maxV != nil, maxV! < item {
- #if DEBUG
- print("item is maybe unregistered, so it is new ship's equipment.")
- #endif
+ Debug.print("item is maybe unregistered, so it is new ship's equipment.")
+
return nil
}
- print("Can not convert to current moc object slotItem")
+ Logger.shared.log("Can not convert to current moc object slotItem")
+
return nil
}
private func setExtraSlot(_ exSlotItem: Int, to ship: Ship) {
- guard exSlotItem != -1,
- exSlotItem != 0
- else { return }
-
+ guard exSlotItem != -1, exSlotItem != 0 else {
+
+ ship.extraItem = nil
+
+ return
+ }
guard let found = slotItems.binarySearch(comparator: { $0.id ==? exSlotItem }),
- let ex = store?.object(with: found.objectID) as? SlotItem
- else { return print("Can not convert to current moc object") }
+ let ex = store?.exchange(found) else {
+
+ Logger.shared.log("Can not convert to current moc object")
+
+ return
+ }
ship.extraItem = ex
}