OSDN Git Service

SGレーダー(初期型)の装備ボーナスを索敵スコアの計算から除く
[kancollesniffer/KancolleSniffer.git] / KancolleSniffer / Model / ItemStatus.cs
1 // Copyright (C) 2018 Kazuhiro Fujieda <fujieda@users.osdn.me>\r
2 //\r
3 // Licensed under the Apache License, Version 2.0 (the "License");\r
4 // you may not use this file except in compliance with the License.\r
5 // You may obtain a copy of the License at\r
6 //\r
7 //    http://www.apache.org/licenses/LICENSE-2.0\r
8 //\r
9 // Unless required by applicable law or agreed to in writing, software\r
10 // distributed under the License is distributed on an "AS IS" BASIS,\r
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
12 // See the License for the specific language governing permissions and\r
13 // limitations under the License.\r
14 \r
15 using System;\r
16 using System.Linq;\r
17 \r
18 namespace KancolleSniffer.Model\r
19 {\r
20     public class ItemStatus\r
21     {\r
22         public int Id { get; set; }\r
23         public bool Empty => Id == -1;\r
24         public bool Unimplemented => Id == 0;\r
25         public ItemSpec Spec { get; set; } = new ItemSpec();\r
26         public int Level { get; set; }\r
27         public int Alv { get; set; }\r
28         public bool Locked { get; set; }\r
29         public ShipStatus Holder { get; set; }\r
30 \r
31         public ItemStatus()\r
32         {\r
33             Id = -1;\r
34         }\r
35 \r
36         public ItemStatus(int id)\r
37         {\r
38             Id = id;\r
39         }\r
40 \r
41         public Range CalcFighterPower(int slot)\r
42         {\r
43             if (!Spec.CanAirCombat || slot == 0)\r
44                 return new Range();\r
45             var withoutAlv = (Spec.AntiAir + FighterPowerLevelBonus) * Math.Sqrt(slot);\r
46             return new Range(withoutAlv, AlvBonus);\r
47         }\r
48 \r
49         private RangeD AlvBonus\r
50         {\r
51             get\r
52             {\r
53                 var table = AlvTypeBonusTable;\r
54                 if (table == null)\r
55                     return new RangeD();\r
56                 return _alvBonus[Alv] + table[Alv];\r
57             }\r
58         }\r
59 \r
60         public AirCorpsFighterPower.Range CalcFighterPowerInBase(int slot)\r
61         {\r
62             if (!Spec.IsAircraft || slot == 0)\r
63                 return new AirCorpsFighterPower.Range();\r
64             var withoutAlv =\r
65                 (new AirCorpsFighterPower.Pair(Spec.Interception * 1.5, Spec.AntiBomber * 2 + Spec.Interception) +\r
66                  Spec.AntiAir + FighterPowerLevelBonus) * Math.Sqrt(slot);\r
67             return new AirCorpsFighterPower.Range(withoutAlv, AlvBonusInBase);\r
68         }\r
69 \r
70         private RangeD AlvBonusInBase\r
71         {\r
72             get\r
73             {\r
74                 switch (Spec.Type)\r
75                 {\r
76                     case 9: // 艦偵\r
77                     case 10: // 水偵\r
78                     case 41: // 大艇\r
79                     case 49: // 陸偵\r
80                         return _alvBonus[Alv];\r
81                     default:\r
82                         return AlvBonus;\r
83                 }\r
84             }\r
85         }\r
86 \r
87         private readonly RangeD[] _alvBonus =\r
88             new[]\r
89             {\r
90                 new RangeD(0.0, 0.9), new RangeD(1.0, 2.4), new RangeD(2.5, 3.9), new RangeD(4.0, 5.4),\r
91                 new RangeD(5.5, 6.9), new RangeD(7.0, 8.4), new RangeD(8.5, 9.9), new RangeD(10.0, 12.0)\r
92             }.Select(range => range.Sqrt()).ToArray();\r
93 \r
94 \r
95         private int[] AlvTypeBonusTable\r
96         {\r
97             get\r
98             {\r
99                 switch (Spec.Type)\r
100                 {\r
101                     case 6: // 艦戦\r
102                     case 45: // 水戦\r
103                     case 48: // 局地戦闘機\r
104                     case 56: // 噴式戦闘機\r
105                         return new[] {0, 0, 2, 5, 9, 14, 14, 22};\r
106                     case 7: // 艦爆\r
107                     case 8: // 艦攻\r
108                     case 47: // 陸攻\r
109                     case 57: // 噴式戦闘爆撃機\r
110                     case 58: // 噴式攻撃機\r
111                         return new[] {0, 0, 0, 0, 0, 0, 0, 0};\r
112                     case 11: // 水爆\r
113                         return new[] {0, 0, 1, 1, 1, 3, 3, 6};\r
114                     default:\r
115                         return null;\r
116                 }\r
117             }\r
118         }\r
119 \r
120         private double FighterPowerLevelBonus\r
121         {\r
122             get\r
123             {\r
124                 switch (Spec.Type)\r
125                 {\r
126                     case 6: // 艦戦\r
127                     case 45: // 水戦\r
128                     case 48: // 陸戦・局戦\r
129                         return 0.2 * Level;\r
130                     case 7: // 改修可能なのは爆戦のみ\r
131                         return 0.25 * Level;\r
132                 }\r
133                 return 0;\r
134             }\r
135         }\r
136 \r
137         public double EffectiveLoS => (Spec.LoS + LoSLevelBonus) * Spec.LoSScaleFactor;\r
138 \r
139         private double LoSLevelBonus\r
140         {\r
141             get\r
142             {\r
143                 switch (Spec.Type)\r
144                 {\r
145                     case 10: // 水偵\r
146                         return 1.2 * Math.Sqrt(Level);\r
147                     case 11: // 水爆\r
148                         return 1.15 * Math.Sqrt(Level);\r
149                     case 12: // 小型電探\r
150                         return 1.25 * Math.Sqrt(Level);\r
151                     case 13: // 大型電探\r
152                         return 1.4 * Math.Sqrt(Level);\r
153                     case 9: // 艦偵\r
154                     case 94: // 艦上偵察機(II)\r
155                         return 1.2 * Math.Sqrt(Level);\r
156                     default:\r
157                         return 0;\r
158                 }\r
159             }\r
160         }\r
161 \r
162         public double FirepowerLevelBonus\r
163         {\r
164             get\r
165             {\r
166                 switch (Spec.Type)\r
167                 {\r
168                     case 1: // 小口径\r
169                     case 2: // 中口径\r
170                     case 19: // 徹甲弾\r
171                     case 21: // 対空機銃\r
172                     case 24: // 上陸用舟艇\r
173                     case 29: // 探照灯\r
174                     case 36: // 高射装置\r
175                     case 42: // 大型探照灯\r
176                     case 46: // 特型内火艇\r
177                         return Math.Sqrt(Level);\r
178                     case 3: // 大口径\r
179                         return 1.5 * Math.Sqrt(Level);\r
180                     case 4: // 副砲\r
181                         return SecondaryGunLevelBonus;\r
182                     case 14: // ソナー\r
183                     case 15: // 爆雷\r
184                         return Spec.Id == 226 // 九五式爆雷\r
185                             ? 0\r
186                             : 0.75 * Math.Sqrt(Level);\r
187                     default:\r
188                         return 0;\r
189                 }\r
190             }\r
191         }\r
192 \r
193         private double SecondaryGunLevelBonus\r
194         {\r
195             get\r
196             {\r
197                 switch (Spec.Id)\r
198                 {\r
199                     case 10: // 12.7cm連装高角砲\r
200                     case 66: // 8cm高角砲\r
201                     case 220: // 8cm高角砲改+増設機銃\r
202                     case 275: // 10cm連装高角砲改+増設機銃\r
203                         return 0.2 * Level;\r
204                     case 12: // 15.5cm三連装副砲\r
205                     case 234: // 15.5cm三連装副砲改\r
206                     case 247: // 15.2cm三連装砲\r
207                         return 0.3 * Level;\r
208                     default:\r
209                         return Math.Sqrt(Level);\r
210                 }\r
211             }\r
212         }\r
213 \r
214         public double TorpedoLevelBonus\r
215         {\r
216             get\r
217             {\r
218                 switch (Spec.Type)\r
219                 {\r
220                     case 5: // 魚雷\r
221                     case 21: // 機銃\r
222                         return 1.2 * Math.Sqrt(Level);\r
223                     default:\r
224                         return 0;\r
225                 }\r
226             }\r
227         }\r
228 \r
229         public double AntiSubmarineLevelBonus\r
230         {\r
231             get\r
232             {\r
233                 switch (Spec.Type)\r
234                 {\r
235                     case 14:\r
236                     case 15:\r
237                         return Math.Sqrt(Level);\r
238                     default:\r
239                         return 0;\r
240                 }\r
241             }\r
242         }\r
243 \r
244         public double BomberLevelBonus => Spec.Type == 11 /* 水爆 */ ? 0.2 * Level : 0;\r
245 \r
246         public double NightBattleLevelBonus\r
247         {\r
248             get\r
249             {\r
250                 switch (Spec.Type)\r
251                 {\r
252                     case 1: // 小口径\r
253                     case 2: // 中口径\r
254                     case 3: // 大口径\r
255                     case 5: // 魚雷\r
256                     case 19: // 徹甲弾\r
257                     case 22: // 特殊潜航艇\r
258                     case 24: // 上陸用舟艇\r
259                     case 29: // 探照灯\r
260                     case 36: // 高射装置\r
261                     case 42: // 大型探照灯\r
262                     case 46: // 特型内火艇\r
263                         return Math.Sqrt(Level);\r
264                     case 4: // 副砲\r
265                         return SecondaryGunLevelBonus;\r
266                     default:\r
267                         return 0;\r
268                 }\r
269             }\r
270         }\r
271 \r
272         public double EffectiveAntiAirForShip\r
273         {\r
274             get\r
275             {\r
276                 switch (Spec.IconType)\r
277                 {\r
278                     case 15: // 機銃\r
279                         return 6 * Spec.AntiAir + 4 * Math.Sqrt(Level);\r
280                     case 16: // 高角砲\r
281                         return 4 * Spec.AntiAir + (Spec.AntiAir >= 8 ? 3 : 2) * Math.Sqrt(Level);\r
282                     case 11: // 電探\r
283                         return 3 * Spec.AntiAir;\r
284                     case 30: // 高射装置\r
285                         return 4 * Spec.AntiAir + 2 * Math.Sqrt(Level);\r
286                 }\r
287                 return 0;\r
288             }\r
289         }\r
290 \r
291         public double EffectiveAntiAirForFleet\r
292         {\r
293             get\r
294             {\r
295                 switch (Spec.IconType)\r
296                 {\r
297                     case 1:\r
298                     case 2:\r
299                     case 3: // 主砲\r
300                     case 4: // 副砲\r
301                     case 6: // 艦戦\r
302                     case 7: // 艦爆\r
303                     case 15: // 機銃\r
304                         return 0.2 * Spec.AntiAir;\r
305                     case 11: // 電探\r
306                         return 0.4 * Spec.AntiAir + 1.5 * Math.Sqrt(Level);\r
307                     case 12: // 三式弾\r
308                         return 0.6 * Spec.AntiAir;\r
309                     case 16: // 高角砲\r
310                         return 0.35 * Spec.AntiAir + (Spec.AntiAir >= 8 ? 3 : 2) * Math.Sqrt(Level);\r
311                     case 30: // 高射装置\r
312                         return 0.35 * Spec.AntiAir + 2 * Math.Sqrt(Level);\r
313                     default:\r
314                         if (Spec.Id == 9) // 46cm三連装砲\r
315                             return 0.25 * Spec.AntiAir;\r
316                         if (Spec.Type == 10) // 水偵\r
317                             return 0.2 * Spec.AntiAir;\r
318                         break;\r
319                 }\r
320                 return 0;\r
321             }\r
322         }\r
323     }\r
324 }