OSDN Git Service

Model、View、Net、Utilの名前空間にクラスを分類する
[kancollesniffer/KancolleSniffer.git] / KancolleSniffer / Model / Fleet.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.Linq;\r
16 using static System.Math;\r
17 \r
18 namespace KancolleSniffer.Model\r
19 {\r
20     public struct ChargeStatus\r
21     {\r
22         public int Fuel { get; set; }\r
23         public int Bull { get; set; }\r
24 \r
25         public ChargeStatus(ShipStatus status) : this()\r
26         {\r
27             Fuel = CalcChargeState(status.Fuel, status.Spec.FuelMax);\r
28             Bull = CalcChargeState(status.Bull, status.Spec.BullMax);\r
29         }\r
30 \r
31         public ChargeStatus(int fuel, int bull) : this()\r
32         {\r
33             Fuel = fuel;\r
34             Bull = bull;\r
35         }\r
36 \r
37         private int CalcChargeState(int now, int full)\r
38         {\r
39             if (full == 0 || now == full)\r
40                 return 0;\r
41             var ratio = (double)now / full;\r
42             if (ratio >= 7.0 / 9)\r
43                 return 1;\r
44             if (ratio >= 3.0 / 9)\r
45                 return 2;\r
46             if (ratio > 0)\r
47                 return 3;\r
48             return 4;\r
49         }\r
50     }\r
51 \r
52     public enum FleetState\r
53     {\r
54         Port,\r
55         Mission,\r
56         Sortie,\r
57         Practice\r
58     }\r
59 \r
60     public enum CombinedType\r
61     {\r
62         None,\r
63         Carrier, // 機動\r
64         Surface, // 水上\r
65         Transport // 輸送\r
66     }\r
67 \r
68     public class Fleet\r
69     {\r
70         private readonly ShipInfo _shipInfo;\r
71         public int Number { get; }\r
72         public FleetState State { get; set; }\r
73         public CombinedType CombinedType { get; set; }\r
74         public int[] Deck { get; set; } = Enumerable.Repeat(-1, ShipInfo.MemberCount).ToArray();\r
75         public ShipStatus[] Ships => Deck.Where(id => id != -1).Select(_shipInfo.GetStatus).ToArray();\r
76 \r
77         public Fleet(ShipInfo shipInfo, int number)\r
78         {\r
79             _shipInfo = shipInfo;\r
80             Number = number;\r
81         }\r
82 \r
83         public ChargeStatus ChargeStatus\r
84         {\r
85             get\r
86             {\r
87                 var fs = new ChargeStatus(_shipInfo.GetStatus(Deck[0]));\r
88                 var others = (from id in Deck.Skip(1) select new ChargeStatus(_shipInfo.GetStatus(id))).Aggregate(\r
89                     (result, next) => new ChargeStatus(Max(result.Fuel, next.Fuel), Max(result.Bull, next.Bull)));\r
90                 return new ChargeStatus(fs.Fuel != 0 ? fs.Fuel : others.Fuel + 5,\r
91                     fs.Bull != 0 ? fs.Bull : others.Bull + 5);\r
92             }\r
93         }\r
94 \r
95         public int[] FighterPower\r
96             => Ships.Where(ship => !ship.Escaped).SelectMany(ship =>\r
97                     ship.Slot.Zip(ship.OnSlot, (slot, onslot) => slot.CalcFighterPower(onslot)))\r
98                 .Aggregate(new[] {0, 0}, (prev, cur) => new[] {prev[0] + cur[0], prev[1] + cur[1]});\r
99 \r
100         public double ContactTriggerRate\r
101             => Ships.Where(ship => !ship.Escaped).SelectMany(ship =>\r
102                 ship.Slot.Zip(ship.OnSlot, (slot, onslot) =>\r
103                     slot.Spec.ContactTriggerRate * slot.Spec.LoS * Sqrt(onslot))).Sum();\r
104 \r
105         public double GetLineOfSights(int factor)\r
106         {\r
107             var result = 0.0;\r
108             var emptyBonus = 6;\r
109             foreach (var s in Ships.Where(s => !s.Escaped))\r
110             {\r
111                 emptyBonus--;\r
112                 var itemLoS = 0;\r
113                 foreach (var item in s.Slot)\r
114                 {\r
115                     var spec = item.Spec;\r
116                     itemLoS += spec.LoS;\r
117                     result += (spec.LoS + item.LoSLevelBonus) * spec.LoSScaleFactor * factor;\r
118                 }\r
119                 result += Sqrt(s.LoS - itemLoS);\r
120             }\r
121             return result > 0 ? result - Ceiling(_shipInfo.HqLevel * 0.4) + emptyBonus * 2 : 0.0;\r
122         }\r
123 \r
124         public double DaihatsuBonus\r
125         {\r
126             get\r
127             {\r
128                 var tokudaiBonus = new[,]\r
129                 {\r
130                     {0.00, 0.00, 0.00, 0.00, 0.00},\r
131                     {0.02, 0.02, 0.02, 0.02, 0.02},\r
132                     {0.04, 0.04, 0.04, 0.04, 0.04},\r
133                     {0.05, 0.05, 0.052, 0.054, 0.054},\r
134                     {0.054, 0.056, 0.058, 0.059, 0.06}\r
135                 };\r
136                 var daihatsu = 0;\r
137                 var tokudai = 0;\r
138                 var bonus = 0.0;\r
139                 var level = 0;\r
140                 var sum = 0;\r
141                 foreach (var ship in Ships)\r
142                 {\r
143                     if (ship.Name == "鬼怒改二")\r
144                         bonus += 0.05;\r
145                     foreach (var item in ship.Slot)\r
146                     {\r
147                         switch (item.Spec.Name)\r
148                         {\r
149                             case "大発動艇":\r
150                                 level += item.Level;\r
151                                 sum++;\r
152                                 daihatsu++;\r
153                                 bonus += 0.05;\r
154                                 break;\r
155                             case "特大発動艇":\r
156                                 level += item.Level;\r
157                                 sum++;\r
158                                 tokudai++;\r
159                                 bonus += 0.05;\r
160                                 break;\r
161                             case "大発動艇(八九式中戦車&陸戦隊)":\r
162                                 level += item.Level;\r
163                                 sum++;\r
164                                 bonus += 0.02;\r
165                                 break;\r
166                             case "特二式内火艇":\r
167                                 level += item.Level;\r
168                                 sum++;\r
169                                 bonus += 0.01;\r
170                                 break;\r
171                         }\r
172                     }\r
173                 }\r
174                 var levelAverage = sum == 0 ? 0.0 : (double)level / sum;\r
175                 bonus = Min(bonus, 0.2);\r
176                 return bonus + 0.01 * bonus * levelAverage + tokudaiBonus[Min(tokudai, 4), Min(daihatsu, 4)];\r
177             }\r
178         }\r
179 \r
180         public double TransportPoint => Ships.Where(ship => !ship.Escaped).Sum(ship => ship.TransportPoint);\r
181 \r
182         public int CombinedFirepowerBonus\r
183         {\r
184             get\r
185             {\r
186                 switch (CombinedType)\r
187                 {\r
188                     case CombinedType.None:\r
189                         return 0;\r
190                     case CombinedType.Carrier:\r
191                         return Number == 0 ? 2 : 10;\r
192                     case CombinedType.Surface:\r
193                         return Number == 0 ? 10 : -5;\r
194                     case CombinedType.Transport:\r
195                         return Number == 0 ? -5 : 10;\r
196                     default:\r
197                         return 0;\r
198                 }\r
199             }\r
200         }\r
201 \r
202         public int CombinedTorpedoPenalty => CombinedType != 0 && Number == 1 ? -5 : 0;\r
203     }\r
204 }