2 // SeikuCalclator.swift
5 // Created by Hori,Masaki on 2017/08/20.
6 // Copyright © 2017年 Hori,Masaki. All rights reserved.
11 private let seikuEffectiveTypes = [6, 7, 8, 11, 45, 56, 57, 58]
13 private let fighterTypes = [ 6]
14 private let bomberTypes = [ 7]
15 private let attackerTypes = [ 8]
16 private let floatplaneBomberTypes = [11]
17 private let floatplaneFighterTypes = [45]
18 private let jetFighter = [56]
19 private let jetBomberTypes = [57]
20 private let jetAttackerTypes = [58]
22 // swiftlint:disable comma
23 private let fighterBonus: [Double] = [0, 0, 2, 5, 9, 14, 14, 22]
24 private let bomberBonus: [Double] = [0, 0, 0, 0, 0, 0, 0, 0]
25 private let attackerBonus: [Double] = [0, 0, 0, 0, 0, 0, 0, 0]
26 private let floatplaneBomberBonus: [Double] = [0, 0, 1, 1, 1, 3, 3, 6]
27 private let floatplaneFighterBonus: [Double] = [0, 0, 2, 5, 9, 14, 14, 22]
28 private let jetBomberBonus: [Double] = [0, 0, 0, 0, 0, 0, 0, 0]
29 // swiftlint:enable comma
31 // sqrt 0, 1, 2.5, 4, 5.5, 7, 8.5, 10
32 private let skillBonus: [Double] = [0, 1.000, 1.581, 2.000, 2.345, 2.645, 2.915, 3.162]
35 final class SeikuCalclator {
46 let guardEscaped = TemporaryDataStore.default.ensuredGuardEscaped(byShipId: ship.id)
47 guard guardEscaped == nil else {
52 return (0...4).map(slotSeiku).map { Int($0) }.reduce(0, +)
57 let guardEscaped = TemporaryDataStore.default.ensuredGuardEscaped(byShipId: ship.id)
58 guard guardEscaped == nil else {
63 return (0...4).map(seiku).reduce(0, +)
66 private func slotItem(at index: Int) -> SlotItem? {
68 return ServerDataStore.default.slotItem(by: ship.slotItemId(index))
71 private func typeBonus(_ type: Int) -> [Double]? {
75 case let t where fighterTypes.contains(t): return fighterBonus
77 case let t where bomberTypes.contains(t): return bomberBonus
79 case let t where attackerTypes.contains(t): return attackerBonus
81 case let t where floatplaneBomberTypes.contains(t): return floatplaneBomberBonus
83 case let t where floatplaneFighterTypes.contains(t): return floatplaneFighterBonus
85 case let t where jetBomberTypes.contains(t): return jetBomberBonus
92 private enum SlotState {
94 case valid(SlotItem, Int, Int)
99 private func slotState(at index: Int) -> SlotState {
101 let itemCount = ship.slotItemCount(index)
106 guard let item = slotItem(at: index) else {
111 return .valid(item, itemCount, item.master_slotItem.type_2)
114 private func slotSeiku(at index: Int) -> Double {
116 guard case let .valid(item, itemCount, type2) = slotState(at: index),
117 seikuEffectiveTypes.contains(type2) else {
122 let taiku = Double(item.master_slotItem.tyku)
123 let lv = Double(item.level)
124 let rate = bomberTypes.contains(type2) ? 0.25 : 0.2
126 return (taiku + lv * rate) * sqrt(Double(itemCount))
129 private func skilledSlotSeiku(at index: Int) -> Double {
131 guard case let .valid(item, _, type2) = slotState(at: index),
132 let typeBonus = typeBonus(type2) else {
137 let airLevel = item.alv
139 return typeBonus[airLevel] + skillBonus[airLevel]
142 private func seiku(at index: Int) -> Int {
144 return Int(slotSeiku(at: index) + skilledSlotSeiku(at: index))