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 final class SimpleCalculator: SakutekiCalculator {
18 func calculate(_ ships: [Ship]) -> Double {
20 return Double(ships.reduce(0) { $0 + $1.sakuteki_0 })
24 final class Formula33: SakutekiCalculator {
28 init(_ condition: Int = 1) {
30 self.condition = condition
33 private func printShipData(_ ship: Ship) {
35 let shipData = "\(ship.name)\t\(normalSakuteki(ship))"
39 .flatMap { $0 as? SlotItem }
42 let saku = $1.master_slotItem.saku ?? 0
43 let ratio = typeRatio($1)
44 let bounus = levelBounus($1)
45 let culcSaku = ratio * (Double(truncating: saku) + bounus)
47 return $0 + "\n\t\($1.name)\tLv.\($1.level)\t\t\(saku)\t\(ratio)\t\(bounus)\t\(culcSaku)"
50 print("\(shipData)\(itemNames)\n")
54 func calculate(_ ships: [Ship]) -> Double {
56 Debug.excute(level: .full) {
57 ships.forEach(printShipData)
60 let aliveShips = ships.filter(alive)
62 let saku1 = aliveShips
67 let saku2 = aliveShips
71 let saku3 = shireiSakuteki()
73 let saku4 = 2 * (6 - ships.count)
75 return saku1 + saku2 - saku3 + Double(saku4)
78 private func alive(_ ship: Ship) -> Bool {
80 if let _ = TemporaryDataStore.default.ensuredGuardEscaped(byShipId: ship.id) {
88 private func normalSakuteki(_ ship: Ship) -> Double {
93 .flatMap { $0 as? SlotItem }
94 .flatMap { $0.master_slotItem.saku as? Double }
97 return Double(ship.sakuteki_0) - eqSakuteki
100 private func equipsSakuteki(_ ship: Ship) -> Double {
105 .flatMap { $0 as? SlotItem }
109 return Double(condition) * saku
112 private func equipSakuteki(_ item: SlotItem) -> Double {
114 guard let saku = item.master_slotItem.saku as? Double else { return 0 }
116 let lvBounus = levelBounus(item)
118 let ratio = typeRatio(item)
120 return Double(condition) * ratio * (saku + lvBounus)
123 private func typeRatio(_ item: SlotItem) -> Double {
125 let type2 = item.master_slotItem.type_2
127 guard let eqType = EquipmentType(rawValue: type2) else { return 1 }
130 case .fighter: return 0.6
131 case .bomber: return 0.6
132 case .attacker: return 0.8
133 case .searcher: return 1
134 case .airplaneSearcher: return 1.2
135 case .airplaneBomber: return 1.1
136 case .smallRadar: return 0.6
137 case .largeRadar: return 0.6
138 case .antiSunmrinerSercher: return 0.6
139 case .searchlight: return 0.6
140 case .headquaters: return 0.6
141 case .pilot: return 0.6
142 case .shipPersonnel: return 0.6
143 case .largeSonar: return 0.6
144 case .largeAirplane: return 0.6
145 case .largeSearchlight: return 0.6
146 case .airplaneFighter: return 0.6
147 case .searcherII: return 1
148 case .jetBomber: return 0.6
153 private func levelBounus(_ item: SlotItem) -> Double {
155 let level = item.level
157 let ratio = levelRatio(item)
159 return ratio * sqrt(Double(level))
162 private func levelRatio(_ item: SlotItem) -> Double {
164 let type2 = item.master_slotItem.type_2
166 guard let eqType = EquipmentType(rawValue: type2) else { return 1 }
169 case .smallRadar: return 1.25
170 case .largeRadar: return 1.4
171 case .airplaneSearcher, .searcher: return 1.2
176 private func shireiSakuteki() -> Double {
178 guard let basic = ServerDataStore.default.basic() else { return 0 }
180 return ceil(0.4 * Double(basic.level))