OSDN Git Service

d8ce035073c4e692e212ec1e02d17639e8f9a173
[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 ShipStatus Holder { get; set; }\r
29 \r
30         public ItemStatus()\r
31         {\r
32             Id = -1;\r
33         }\r
34 \r
35         public ItemStatus(int id)\r
36         {\r
37             Id = id;\r
38         }\r
39 \r
40         public int[] CalcFighterPower(int slot)\r
41         {\r
42             if (!Spec.CanAirCombat || slot == 0)\r
43                 return new[] {0, 0};\r
44             var unskilled = (Spec.AntiAir + FighterPowerLevelBonus) * Math.Sqrt(slot);\r
45             return AlvBonus.Select(bonus => (int)(unskilled + bonus)).ToArray();\r
46         }\r
47 \r
48         public int[] CalcFighterPowerInBase(int slot, bool airDefense)\r
49         {\r
50             if (!Spec.IsAircraft || slot == 0)\r
51                 return new[] {0, 0};\r
52             var airDefenseBonus = airDefense ? Spec.AntiBomber * 2 + Spec.Interception : Spec.Interception * 1.5;\r
53             var unskilled = (Spec.AntiAir + airDefenseBonus + FighterPowerLevelBonus) * Math.Sqrt(slot);\r
54             return AlvBonusInBase.Select(bonus => (int)(unskilled + bonus)).ToArray();\r
55         }\r
56 \r
57         private readonly double[] _alvBonusMin =\r
58         {\r
59             Math.Sqrt(0.0), Math.Sqrt(1.0), Math.Sqrt(2.5), Math.Sqrt(4.0), Math.Sqrt(5.5), Math.Sqrt(7.0),\r
60             Math.Sqrt(8.5), Math.Sqrt(10.0)\r
61         };\r
62 \r
63         private readonly double[] _alvBonusMax =\r
64         {\r
65             Math.Sqrt(0.9), Math.Sqrt(2.4), Math.Sqrt(3.9), Math.Sqrt(5.4), Math.Sqrt(6.9), Math.Sqrt(8.4),\r
66             Math.Sqrt(9.9), Math.Sqrt(12.0)\r
67         };\r
68 \r
69         private int[] AlvTypeBonusTable\r
70         {\r
71             get\r
72             {\r
73                 switch (Spec.Type)\r
74                 {\r
75                     case 6: // 艦戦\r
76                     case 45: // 水戦\r
77                     case 48: // 局地戦闘機\r
78                     case 56: // 噴式戦闘機\r
79                         return new[] {0, 0, 2, 5, 9, 14, 14, 22};\r
80                     case 7: // 艦爆\r
81                     case 8: // 艦攻\r
82                     case 47: // 陸攻\r
83                     case 57: // 噴式戦闘爆撃機\r
84                     case 58: // 噴式攻撃機\r
85                         return new[] {0, 0, 0, 0, 0, 0, 0, 0};\r
86                     case 11: // 水爆\r
87                         return new[] {0, 0, 1, 1, 1, 3, 3, 6};\r
88                     default:\r
89                         return null;\r
90                 }\r
91             }\r
92         }\r
93 \r
94         private double[] AlvBonus\r
95         {\r
96             get\r
97             {\r
98                 var table = AlvTypeBonusTable;\r
99                 if (table == null)\r
100                     return new[] {0.0, 0.0};\r
101                 return new[] {table[Alv] + _alvBonusMin[Alv], table[Alv] + _alvBonusMax[Alv]};\r
102             }\r
103         }\r
104 \r
105         private double[] AlvBonusInBase\r
106         {\r
107             get\r
108             {\r
109                 switch (Spec.Type)\r
110                 {\r
111                     case 9: // 艦偵\r
112                     case 10: // 水偵\r
113                     case 41: // 大艇\r
114                         return new[] {_alvBonusMin[Alv], _alvBonusMax[Alv]};\r
115                     default:\r
116                         return AlvBonus;\r
117                 }\r
118             }\r
119         }\r
120 \r
121         private double FighterPowerLevelBonus\r
122         {\r
123             get\r
124             {\r
125                 switch (Spec.Type)\r
126                 {\r
127                     case 6: // 艦戦\r
128                     case 45: // 水戦\r
129                     case 48: // 陸戦・局戦\r
130                         return 0.2 * Level;\r
131                     case 7: // 改修可能なのは爆戦のみ\r
132                         return 0.25 * Level;\r
133                 }\r
134                 return 0;\r
135             }\r
136         }\r
137 \r
138         public double LoSLevelBonus\r
139         {\r
140             get\r
141             {\r
142                 switch (Spec.Type)\r
143                 {\r
144                     case 10: // 水偵\r
145                         return 1.2 * Math.Sqrt(Level);\r
146                     case 11: // 水爆\r
147                         return 1.15 * Math.Sqrt(Level);\r
148                     case 12: // 小型電探\r
149                         return 1.25 * Math.Sqrt(Level);\r
150                     case 13: // 大型電探\r
151                         return 1.4 * Math.Sqrt(Level);\r
152                     case 94: // 艦上偵察機(II)\r
153                         return 1.2 * Math.Sqrt(Level);\r
154                     default:\r
155                         return 0;\r
156                 }\r
157             }\r
158         }\r
159 \r
160         public double FirepowerLevelBonus\r
161         {\r
162             get\r
163             {\r
164                 switch (Spec.Type)\r
165                 {\r
166                     case 1: // 小口径\r
167                     case 2: // 中口径\r
168                     case 19: // 徹甲弾\r
169                     case 21: // 対空機銃\r
170                     case 24: // 上陸用舟艇\r
171                     case 29: // 探照灯\r
172                     case 36: // 高射装置\r
173                     case 42: // 大型探照灯\r
174                     case 46: // 特型内火艇\r
175                         return Math.Sqrt(Level);\r
176                     case 3: // 大口径\r
177                         return 1.5 * Math.Sqrt(Level);\r
178                     case 4: // 副砲\r
179                         return SecondaryGunLevelBonus;\r
180                     case 14: // ソナー\r
181                     case 15: // 爆雷\r
182                         return Spec.Id == 226 // 九五式爆雷\r
183                             ? 0\r
184                             : 0.75 * Math.Sqrt(Level);\r
185                     default:\r
186                         return 0;\r
187                 }\r
188             }\r
189         }\r
190 \r
191         public double SecondaryGunLevelBonus\r
192         {\r
193             get\r
194             {\r
195                 switch (Spec.Id)\r
196                 {\r
197                     case 10: // 12.7cm連装高角砲\r
198                     case 66: // 8cm高角砲\r
199                     case 220: // 8cm高角砲改+増設機銃\r
200                     case 275: // 10cm連装高角砲改+増設機銃\r
201                         return 0.2 * Level;\r
202                     case 12: // 15.5cm三連装副砲\r
203                     case 234: // 15.5cm三連装副砲改\r
204                     case 247: // 15.2cm三連装砲\r
205                         return 0.3 * Level;\r
206                     default:\r
207                         return Math.Sqrt(Level);\r
208                 }\r
209             }\r
210         }\r
211 \r
212         public double TorpedoLevelBonus\r
213         {\r
214             get\r
215             {\r
216                 switch (Spec.Type)\r
217                 {\r
218                     case 5: // 魚雷\r
219                     case 21: // 機銃\r
220                         return 1.2 * Math.Sqrt(Level);\r
221                     default:\r
222                         return 0;\r
223                 }\r
224             }\r
225         }\r
226 \r
227         public double AntiSubmarineLevelBonus\r
228         {\r
229             get\r
230             {\r
231                 switch (Spec.Type)\r
232                 {\r
233                     case 14:\r
234                     case 15:\r
235                         return Math.Sqrt(Level);\r
236                     default:\r
237                         return 0;\r
238                 }\r
239             }\r
240         }\r
241 \r
242         public double BomberLevelBonus => Spec.Type == 11 /* 水爆 */ ? 0.2 * Level : 0;\r
243 \r
244         public double NightBattleLevelBonus\r
245         {\r
246             get\r
247             {\r
248                 switch (Spec.Type)\r
249                 {\r
250                     case 1: // 小口径\r
251                     case 2: // 中口径\r
252                     case 3: // 大口径\r
253                     case 5: // 魚雷\r
254                     case 19: // 徹甲弾\r
255                     case 24: // 上陸用舟艇\r
256                     case 29: // 探照灯\r
257                     case 36: // 高射装置\r
258                     case 42: // 大型探照灯\r
259                     case 46: // 特型内火艇\r
260                         return Math.Sqrt(Level);\r
261                     case 4: // 副砲\r
262                         return SecondaryGunLevelBonus;\r
263                     default:\r
264                         return 0;\r
265                 }\r
266             }\r
267         }\r
268 \r
269         public double EffectiveAntiAirForShip\r
270         {\r
271             get\r
272             {\r
273                 switch (Spec.IconType)\r
274                 {\r
275                     case 15: // 機銃\r
276                         return 6 * Spec.AntiAir + 4 * Math.Sqrt(Level);\r
277                     case 16: // 高角砲\r
278                         return 4 * Spec.AntiAir + (Spec.AntiAir >= 8 ? 3 : 2) * Math.Sqrt(Level);\r
279                     case 11: // 電探\r
280                         return 3 * Spec.AntiAir;\r
281                     case 30: // 高射装置\r
282                         return 4 * Spec.AntiAir + 2 * Math.Sqrt(Level);\r
283                 }\r
284                 return 0;\r
285             }\r
286         }\r
287 \r
288         public double EffectiveAntiAirForFleet\r
289         {\r
290             get\r
291             {\r
292                 switch (Spec.IconType)\r
293                 {\r
294                     case 1:\r
295                     case 2:\r
296                     case 3: // 主砲\r
297                     case 4: // 副砲\r
298                     case 6: // 艦戦\r
299                     case 7: // 艦爆\r
300                     case 15: // 機銃\r
301                         return 0.2 * Spec.AntiAir;\r
302                     case 11: // 電探\r
303                         return 0.4 * Spec.AntiAir + 1.5 * Math.Sqrt(Level);\r
304                     case 12: // 三式弾\r
305                         return 0.6 * Spec.AntiAir;\r
306                     case 16: // 高角砲\r
307                         return 0.35 * Spec.AntiAir + (Spec.AntiAir >= 8 ? 3 : 2) * Math.Sqrt(Level);\r
308                     case 30: // 高射装置\r
309                         return 0.35 * Spec.AntiAir + 2 * Math.Sqrt(Level);\r
310                     default:\r
311                         if (Spec.Id == 9) // 46cm三連装砲\r
312                             return 0.25 * Spec.AntiAir;\r
313                         if (Spec.Type == 10) // 水偵\r
314                             return 0.2 * Spec.AntiAir;\r
315                         break;\r
316                 }\r
317                 return 0;\r
318             }\r
319         }\r
320     }\r
321 }