OSDN Git Service

return文の前に改行を入れるようにした
[kcd/KCD.git] / KCD / SakutekiCalculator.swift
1 //
2 //  SakutekiCalculator.swift
3 //  KCD
4 //
5 //  Created by Hori,Masaki on 2017/06/18.
6 //  Copyright © 2017年 Hori,Masaki. All rights reserved.
7 //
8
9 import Foundation
10
11 protocol SakutekiCalculator {
12     
13     func calculate(_ ships: [Ship]) -> Double
14 }
15
16 extension SakutekiCalculator {
17     
18     fileprivate func alivedShips(ships: [Ship]) -> [Ship] {
19         
20         return ships.filter {
21             
22             TemporaryDataStore.default.ensuredGuardEscaped(byShipId: $0.id) == nil
23         }
24     }
25 }
26
27 final class SimpleCalculator: SakutekiCalculator {
28     
29     
30     func calculate(_ ships: [Ship]) -> Double {
31         
32         return Double(alivedShips(ships: ships).reduce(0) { $0 + $1.sakuteki_0 })
33     }
34 }
35
36 final class Formula33: SakutekiCalculator {
37     
38     let condition: Int
39     
40     init(_ condition: Int = 1) {
41         
42         self.condition = condition
43     }
44     
45     private func printShipData(_ ship: Ship) {
46         
47         let shipData = "\(ship.name)\t\(normalSakuteki(ship))"
48         let itemNames = ship
49             .equippedItem
50             .array
51             .compactMap { $0 as? SlotItem }
52             .reduce("") {
53                 
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)
58                 
59                 return $0 + "\n\t\($1.name)\tLv.\($1.level)\t\t\(saku)\t\(ratio)\t\(bounus)\t\(culcSaku)"
60         }
61         
62         print("\(shipData)\(itemNames)\n")
63         
64     }
65     
66     func calculate(_ ships: [Ship]) -> Double {
67         
68         Debug.excute(level: .full) {
69             
70             ships.forEach(printShipData)
71         }
72         
73         let aliveShips = alivedShips(ships: ships)
74         
75         // 艦娘の索敵による索敵値
76         let saku1 = aliveShips
77             .map(normalSakuteki)
78             .map(sqrt)
79             .reduce(0, +)
80         
81         // 装備および分岐点係数による索敵値
82         let saku2 = aliveShips
83             .map(equipsSakuteki)
84             .reduce(0, +)
85         
86         // 艦隊司令部Lv.による影響
87         let saku3 = shireiSakuteki()
88         
89         // 艦隊の艦娘数による影響
90         let saku4 = 2 * (6 - aliveShips.count)
91         
92         return saku1 + saku2 - saku3 + Double(saku4)
93     }
94     
95     private func normalSakuteki(_ ship: Ship) -> Double {
96         
97         let eqSakuteki = ship
98             .equippedItem
99             .array
100             .compactMap { $0 as? SlotItem }
101             .compactMap { $0.master_slotItem.saku as? Double }
102             .reduce(0, +)
103         
104         return Double(ship.sakuteki_0) - eqSakuteki
105     }
106     
107     private func equipsSakuteki(_ ship: Ship) -> Double {
108         
109         let saku = ship
110             .equippedItem
111             .array
112             .compactMap { $0 as? SlotItem }
113             .map(equipSakuteki)
114             .reduce(0, +)
115         
116         return Double(condition) * saku
117     }
118     
119     private func equipSakuteki(_ item: SlotItem) -> Double {
120         
121         guard let saku = item.master_slotItem.saku as? Double else {
122             
123             return 0
124         }
125         
126         return Double(condition) * typeRatio(item) * (saku + levelBounus(item))
127     }
128     
129     private func typeRatio(_ item: SlotItem) -> Double {
130         
131         guard let eqType = EquipmentType(rawValue: item.master_slotItem.type_2) else {
132             
133             return 1
134         }
135         
136         switch eqType {
137             
138         case .fighter: return 0.6
139             
140         case .bomber: return 0.6
141             
142         case .attacker: return 0.8
143             
144         case .searcher: return 1
145             
146         case .airplaneSearcher: return 1.2
147             
148         case .airplaneBomber: return 1.1
149             
150         case .smallRadar: return 0.6
151             
152         case .largeRadar: return 0.6
153             
154         case .antiSunmrinerSercher: return 0.6
155             
156         case .searchlight: return 0.6
157             
158         case .headquaters: return 0.6
159             
160         case .pilot: return 0.6
161             
162         case .shipPersonnel: return 0.6
163             
164         case .largeSonar: return 0.6
165             
166         case .largeAirplane: return 0.6
167             
168         case .largeSearchlight: return 0.6
169             
170         case .airplaneFighter: return 0.6
171             
172         case .searcherII: return 1
173             
174         case .jetBomber: return 0.6
175             
176         default: return 0
177             
178         }
179     }
180     
181     private func levelBounus(_ item: SlotItem) -> Double {
182         
183         return levelRatio(item) * sqrt(Double(item.level))
184     }
185     
186     private func levelRatio(_ item: SlotItem) -> Double {
187                 
188         guard let eqType = EquipmentType(rawValue: item.master_slotItem.type_2) else {
189             
190             return 1
191         }
192         
193         switch eqType {
194             
195         case .smallRadar: return 1.25
196             
197         case .largeRadar: return 1.4
198             
199         case .airplaneSearcher, .searcher: return 1.2
200             
201         default: return 0
202             
203         }
204     }
205     
206     private func shireiSakuteki() -> Double {
207         
208         guard let basic = ServerDataStore.default.basic() else {
209             
210             return 0
211         }
212         
213         return ceil(0.4 * Double(basic.level))
214     }
215     
216 }