2 // SakutekiCalculator.swift
5 // Created by Hori,Masaki on 2017/06/18.
6 // Copyright © 2017年 Hori,Masaki. All rights reserved.
11 protocol SakutekiCalculator {
13 func calculate(_ ships: [Ship]) -> Double
16 extension SakutekiCalculator {
18 fileprivate func alivedShips(ships: [Ship]) -> [Ship] {
22 TemporaryDataStore.default.ensuredGuardEscaped(byShipId: $0.id) == nil
27 final class SimpleCalculator: SakutekiCalculator {
30 func calculate(_ ships: [Ship]) -> Double {
32 return Double(alivedShips(ships: ships).reduce(0) { $0 + $1.sakuteki_0 })
36 final class Formula33: SakutekiCalculator {
40 init(_ condition: Int = 1) {
42 self.condition = condition
45 private func printShipData(_ ship: Ship) {
47 let shipData = "\(ship.name)\t\(normalSakuteki(ship))"
51 .compactMap { $0 as? SlotItem }
54 let saku = $1.master_slotItem.saku ?? 0
55 let ratio = typeRatio($1)
56 let bounus = levelBounus($1)
57 let culcSaku = ratio * (Double(truncating: saku) + bounus)
59 return $0 + "\n\t\($1.name)\tLv.\($1.level)\t\t\(saku)\t\(ratio)\t\(bounus)\t\(culcSaku)"
62 print("\(shipData)\(itemNames)\n")
66 func calculate(_ ships: [Ship]) -> Double {
68 Debug.excute(level: .full) {
70 ships.forEach(printShipData)
73 let aliveShips = alivedShips(ships: ships)
76 let saku1 = aliveShips
82 let saku2 = aliveShips
87 let saku3 = shireiSakuteki()
90 let saku4 = 2 * (6 - aliveShips.count)
92 return saku1 + saku2 - saku3 + Double(saku4)
95 private func normalSakuteki(_ ship: Ship) -> Double {
100 .compactMap { $0 as? SlotItem }
101 .compactMap { $0.master_slotItem.saku as? Double }
104 return Double(ship.sakuteki_0) - eqSakuteki
107 private func equipsSakuteki(_ ship: Ship) -> Double {
112 .compactMap { $0 as? SlotItem }
116 return Double(condition) * saku
119 private func equipSakuteki(_ item: SlotItem) -> Double {
121 guard let saku = item.master_slotItem.saku as? Double else {
126 return Double(condition) * typeRatio(item) * (saku + levelBounus(item))
129 private func typeRatio(_ item: SlotItem) -> Double {
131 guard let eqType = EquipmentType(rawValue: item.master_slotItem.type_2) else {
138 case .fighter: return 0.6
140 case .bomber: return 0.6
142 case .attacker: return 0.8
144 case .searcher: return 1
146 case .airplaneSearcher: return 1.2
148 case .airplaneBomber: return 1.1
150 case .smallRadar: return 0.6
152 case .largeRadar: return 0.6
154 case .antiSunmrinerSercher: return 0.6
156 case .searchlight: return 0.6
158 case .headquaters: return 0.6
160 case .pilot: return 0.6
162 case .shipPersonnel: return 0.6
164 case .largeSonar: return 0.6
166 case .largeAirplane: return 0.6
168 case .largeSearchlight: return 0.6
170 case .airplaneFighter: return 0.6
172 case .searcherII: return 1
174 case .jetBomber: return 0.6
181 private func levelBounus(_ item: SlotItem) -> Double {
183 return levelRatio(item) * sqrt(Double(item.level))
186 private func levelRatio(_ item: SlotItem) -> Double {
188 guard let eqType = EquipmentType(rawValue: item.master_slotItem.type_2) else {
195 case .smallRadar: return 1.25
197 case .largeRadar: return 1.4
199 case .airplaneSearcher, .searcher: return 1.2
206 private func shireiSakuteki() -> Double {
208 guard let basic = ServerDataStore.default.basic() else {
213 return ceil(0.4 * Double(basic.level))