{\r
var sniffer = new Sniffer();\r
SniffLogFile(sniffer, "baseaircorps_001");\r
- PAssert.That(() => sniffer.BaseAirCorps[0].AirCorps[0].FighterPower.AirCombat[1] == 301);\r
+ PAssert.That(() => (int)sniffer.BaseAirCorps[0].AirCorps[0].CalcFighterPower()[1].AirCombat == 301);\r
sniffer.BaseAirCorps[0].AirCorps[0].Action = 2; // 防空\r
- PAssert.That(() => sniffer.BaseAirCorps[0].AirCorps[0].FighterPower.Interception[1] == 320);\r
+ PAssert.That(() => (int)sniffer.BaseAirCorps[0].AirCorps[0].CalcFighterPower()[1].Interception == 320);\r
}\r
\r
/// <summary>\r
{\r
var sniffer = new Sniffer();\r
SniffLogFile(sniffer, "baseaircorps_002");\r
- PAssert.That(() => sniffer.BaseAirCorps[0].AirCorps[2].FighterPower.Interception[0] == 353);\r
+ PAssert.That(() => (int)sniffer.BaseAirCorps[0].AirCorps[2].CalcFighterPower()[0].Interception == 353);\r
}\r
\r
/// <summary>\r
{\r
var sniffer = new Sniffer();\r
SniffLogFile(sniffer, "baseaircorps_003");\r
- PAssert.That(() => sniffer.BaseAirCorps[1].AirCorps[0].FighterPower.AirCombat[0] == 121);\r
+ PAssert.That(() => (int)sniffer.BaseAirCorps[1].AirCorps[0].CalcFighterPower()[0].AirCombat == 121);\r
}\r
\r
/// <summary>\r
{\r
var sniffer = new Sniffer();\r
SniffLogFile(sniffer, "baseaircorps_004");\r
- PAssert.That(() => sniffer.BaseAirCorps[1].AirCorps[0].FighterPower.AirCombat[0] == 328);\r
+ PAssert.That(() => (int)sniffer.BaseAirCorps[1].AirCorps[0].CalcFighterPower()[0].AirCombat == 328);\r
}\r
\r
/// <summary>\r
-Subproject commit aa434af1e9da0eca2ae43ad6820fe7e72930be5f
+Subproject commit 661a3e809ab78022829a3541285c86e3f1b0de6a
<Reference Include="System.Xml" />\r
</ItemGroup>\r
<ItemGroup>\r
+ <Compile Include="Model\AirBaseParams.cs" />\r
<Compile Include="Model\QuestCountList.cs" />\r
<Compile Include="Privacy.cs" />\r
<Compile Include="Log\LogProcessor.cs" />\r
--- /dev/null
+// Copyright (C) 2019 Kazuhiro Fujieda <fujieda@users.osdn.me>\r
+//\r
+// Licensed under the Apache License, Version 2.0 (the "License");\r
+// you may not use this file except in compliance with the License.\r
+// You may obtain a copy of the License at\r
+//\r
+// http://www.apache.org/licenses/LICENSE-2.0\r
+//\r
+// Unless required by applicable law or agreed to in writing, software\r
+// distributed under the License is distributed on an "AS IS" BASIS,\r
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+// See the License for the specific language governing permissions and\r
+// limitations under the License.\r
+\r
+using System;\r
+\r
+namespace KancolleSniffer.Model\r
+{\r
+ public struct AirBaseParams\r
+ {\r
+ public double AirCombat { get; }\r
+ public double Interception { get; }\r
+\r
+ public AirBaseParams(double airCombat, double interception)\r
+ {\r
+ AirCombat = airCombat;\r
+ Interception = interception;\r
+ }\r
+\r
+ public static AirBaseParams Max(AirBaseParams value1, AirBaseParams value2)\r
+ {\r
+ return new AirBaseParams(Math.Max(value1.AirCombat, value2.AirCombat),\r
+ Math.Max(value1.Interception, value2.Interception));\r
+ }\r
+\r
+ public static AirBaseParams operator +(AirBaseParams lhs, AirBaseParams rhs)\r
+ {\r
+ return new AirBaseParams(lhs.AirCombat + rhs.AirCombat, lhs.Interception + rhs.Interception);\r
+ }\r
+\r
+ public static AirBaseParams operator +(AirBaseParams lhs, double rhs)\r
+ {\r
+ return new AirBaseParams(lhs.AirCombat + rhs, lhs.Interception + rhs);\r
+ }\r
+\r
+ public static AirBaseParams operator *(AirBaseParams lhs, AirBaseParams rhs)\r
+ {\r
+ return new AirBaseParams(lhs.AirCombat * rhs.AirCombat, lhs.Interception * rhs.Interception);\r
+ }\r
+\r
+ public static AirBaseParams operator *(AirBaseParams lhs, double rhs)\r
+ {\r
+ return new AirBaseParams(lhs.AirCombat * rhs, lhs.Interception * rhs);\r
+ }\r
+\r
+ public AirBaseParams Floor()\r
+ {\r
+ return new AirBaseParams((int)AirCombat, (int)Interception);\r
+ }\r
+ }\r
+}
\ No newline at end of file
public AirCorpsInfo[] AirCorps { get; set; }\r
}\r
\r
- public class FighterPower\r
- {\r
- public int[] AirCombat { get; set; }\r
- public int[] Interception { get; set; }\r
- public bool IsInterceptor => AirCombat[0] != Interception[0];\r
- }\r
-\r
public class Distance\r
{\r
public int Base { get; set; }\r
}\r
}\r
\r
- public FighterPower FighterPower =>\r
- new FighterPower {AirCombat = CalcFighterPower(false), Interception = CalcFighterPower(true)};\r
-\r
- private int[] CalcFighterPower(bool interception)\r
+ public AirBaseParams[] CalcFighterPower()\r
{\r
- var reconPlaneBonus = interception\r
- ? Planes.Max(plane => plane.Slot.Spec.ReconPlaneInterceptionBonus)\r
- : 1.0;\r
- return Planes.Aggregate(new[] {0, 0}, (prev, plane) =>\r
+ var reconPlaneBonus = Planes.Aggregate(new AirBaseParams(), (max, plane) =>\r
+ {\r
+ var bonus = plane.Slot.Spec.ReconPlaneAirBaseBonus;\r
+ return AirBaseParams.Max(max, bonus);\r
+ });\r
+ return Planes.Aggregate(new[] {new AirBaseParams(), new AirBaseParams()}, (previous, plane) =>\r
{\r
if (plane.State != 1)\r
- return prev;\r
- var cur = plane.Slot.CalcFighterPowerInBase(plane.Count, interception);\r
- return new[] {prev[0] + cur[0], prev[1] + cur[1]};\r
- }).Select(fp => (int)(fp * reconPlaneBonus)).ToArray();\r
+ return previous;\r
+ var current = plane.Slot.CalcFighterPowerInBase(plane.Count);\r
+ return new[]\r
+ {\r
+ previous[0] + current[0],\r
+ previous[1] + current[1]\r
+ };\r
+ }).Select(param => (param * reconPlaneBonus).Floor()).ToArray();\r
}\r
\r
public int[] CostForSortie => Planes.Aggregate(new[] {0, 0}, (prev, plane) =>\r
}\r
}\r
\r
- public FighterPower FighterPower\r
- => new FighterPower{AirCombat = CalcFighterPower(false), Interception = CalcFighterPower(true)};\r
-\r
- private int[] CalcFighterPower(bool interception) => Slot.CalcFighterPowerInBase(Count, interception);\r
+ public AirBaseParams[] FighterPower => Slot.CalcFighterPowerInBase(Count);\r
}\r
\r
public void Inspect(dynamic json)\r
{\r
AllAirCorps = (from entry in (dynamic[])json\r
group\r
- new AirCorpsInfo\r
- {\r
- Distance = CreateDistance(entry.api_distance),\r
- Action = (int)entry.api_action_kind,\r
- Planes = (from plane in (dynamic[])entry.api_plane_info\r
- select new PlaneInfo\r
- {\r
- Slot = _itemInfo.GetStatus((int)plane.api_slotid),\r
- State = (int)plane.api_state,\r
- Count = plane.api_count() ? (int)plane.api_count : 0,\r
- MaxCount = plane.api_max_count() ? (int)plane.api_max_count : 0,\r
- }).ToArray()\r
- } by entry.api_area_id() ? (int)entry.api_area_id : 0\r
+ new AirCorpsInfo\r
+ {\r
+ Distance = CreateDistance(entry.api_distance),\r
+ Action = (int)entry.api_action_kind,\r
+ Planes = (from plane in (dynamic[])entry.api_plane_info\r
+ select new PlaneInfo\r
+ {\r
+ Slot = _itemInfo.GetStatus((int)plane.api_slotid),\r
+ State = (int)plane.api_state,\r
+ Count = plane.api_count() ? (int)plane.api_count : 0,\r
+ MaxCount = plane.api_max_count() ? (int)plane.api_max_count : 0\r
+ }).ToArray()\r
+ } by entry.api_area_id() ? (int)entry.api_area_id : 0\r
into grp\r
select new BaseInfo {AreaId = grp.Key, AirCorps = grp.ToArray()}).ToArray();\r
}\r
baseInfo.AirCorps = airCorps;\r
airCorps[airCorps.Length - 1] = new AirCorpsInfo\r
{\r
- Planes =\r
- ((dynamic[])json[0].api_plane_info).\r
- Select(plane => new PlaneInfo {Slot = new ItemStatus()}).ToArray()\r
+ Planes = ((dynamic[])json[0].api_plane_info).Select(plane =>\r
+ new PlaneInfo {Slot = new ItemStatus()}).ToArray()\r
};\r
}\r
\r
public bool IsSonar => Type == 14 || // ソナー\r
Type == 40; // 大型ソナー\r
\r
- public bool IsDCT => // Depth Charge Thrower\r
+ public bool IsDCT => // Depth Charge Thrower\r
Id == 44 || // 九四式爆雷投射機\r
Id == 45; // 三式爆雷投射機\r
\r
}\r
}\r
\r
- public double ReconPlaneInterceptionBonus\r
+ public AirBaseParams ReconPlaneAirBaseBonus\r
{\r
get\r
{\r
switch (Type)\r
{\r
case 9:\r
- return LoS <= 7 ? 1.2 : 1.3;\r
+ return new AirBaseParams(1.0, LoS <= 7 ? 1.2 : 1.3);\r
case 10:\r
case 41:\r
- return LoS <= 7 ? 1.1 :\r
- LoS <= 8 ? 1.13 : 1.16;\r
+ return new AirBaseParams(1.0, LoS <= 7 ? 1.1 :\r
+ LoS <= 8 ? 1.13 : 1.16);\r
}\r
- return 1;\r
+ return new AirBaseParams(1.0, 1.0);\r
}\r
}\r
\r
return AlvBonus.Select(bonus => (int)(unskilled + bonus)).ToArray();\r
}\r
\r
- public int[] CalcFighterPowerInBase(int slot, bool airDefense)\r
+ public AirBaseParams[] CalcFighterPowerInBase(int slot)\r
{\r
if (!Spec.IsAircraft || slot == 0)\r
- return new[] {0, 0};\r
- var airDefenseBonus = airDefense ? Spec.AntiBomber * 2 + Spec.Interception : Spec.Interception * 1.5;\r
- var unskilled = (Spec.AntiAir + airDefenseBonus + FighterPowerLevelBonus) * Math.Sqrt(slot);\r
- return AlvBonusInBase.Select(bonus => (int)(unskilled + bonus)).ToArray();\r
+ return new[] {new AirBaseParams(), new AirBaseParams()};\r
+ var baseFighterPower = (new AirBaseParams(Spec.Interception * 1.5, Spec.AntiBomber * 2 + Spec.Interception) +\r
+ Spec.AntiAir + FighterPowerLevelBonus) * Math.Sqrt(slot);\r
+ return AlvBonusInBase.Select(bonus => (baseFighterPower + bonus).Floor()).ToArray();\r
}\r
\r
private readonly double[] _alvBonusMin =\r
{\r
if (i >= name.Length)\r
break;\r
- var corpsFp = airCorps.FighterPower;\r
+ var corpsFp = airCorps.CalcFighterPower();\r
+ var airCombat = new[] { (int)corpsFp[0].AirCombat, (int)corpsFp[1].AirCombat };\r
+ var interception = new[] { (int)corpsFp[0].Interception, (int)corpsFp[1].Interception };\r
+ var different = interception[0] != airCombat[0];\r
string spec;\r
string spec2;\r
if (airCorps.Action == 2)\r
{\r
- spec = "制空:" + RangeString(corpsFp.Interception);\r
- spec2 = corpsFp.IsInterceptor ? "制空(出撃):" + RangeString(corpsFp.AirCombat) : "";\r
+ spec = "制空:" + RangeString(interception);\r
+ spec2 = different ? "制空(出撃):" + RangeString(airCombat) : "";\r
}\r
else\r
{\r
- spec = "制空:" + RangeString(corpsFp.AirCombat);\r
- spec2 = corpsFp.IsInterceptor ? "制空(防空):" + RangeString(corpsFp.Interception) : "";\r
+ spec = "制空:" + RangeString(airCombat);\r
+ spec2 = different ? "制空(防空):" + RangeString(interception) : "";\r
}\r
var cost = airCorps.CostForSortie;\r
list.Add(new Record\r
list.AddRange(airCorps.Planes.Select(plane =>\r
{\r
var planeFp = plane.FighterPower;\r
+ airCombat = new[] {(int)planeFp[0].AirCombat, (int)planeFp[1].AirCombat};\r
+ interception = new[] {(int) planeFp[0].Interception, (int)planeFp[1].Interception };\r
+ different = interception[0] != airCombat[0];\r
return new Record\r
{\r
Equip = plane.State != 1 ? plane.StateName : GenEquipString(plane.Slot),\r
Spec = plane.State != 1 ? "" : $"+{plane.Slot.Alv} {plane.Count}/{plane.MaxCount}",\r
AircraftSpec =\r
- $"距離:{plane.Slot.Spec.Distance} 制空:{RangeString(planeFp.AirCombat)}" +\r
- (planeFp.IsInterceptor ? $" 防空:{RangeString(planeFp.Interception)}" : ""),\r
+ $"距離:{plane.Slot.Spec.Distance} 制空:{RangeString(airCombat)}" +\r
+ (different ? $" 防空:{RangeString(interception)}" : ""),\r
Color = plane.Slot.Spec.Color\r
};\r
}));\r