}\r
\r
/// <summary>\r
+ /// 基地航空隊の制空値を正しく計算する\r
+ /// </summary>\r
+ [TestMethod]\r
+ public void FighterPowerOfBaseAirCorps()\r
+ {\r
+ var sniffer = new Sniffer();\r
+ SniffLogFile(sniffer, "fighterpower_004");\r
+ PAssert.That(() => sniffer.BaseAirCorps[0].FighterPower[1] == 301);\r
+ }\r
+\r
+ /// <summary>\r
/// マップ索敵の判定式(33)を正しく計算する\r
/// </summary>\r
[TestMethod]\r
-Subproject commit d3ebab42319cc3bcfa60bc8d02d1c5af68055a2d
+Subproject commit ee4fbcaca559af906ae7b7175aa11941a451d187
--- /dev/null
+// Copyright (C) 2016 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.Linq;\r
+using static System.Math;\r
+\r
+namespace KancolleSniffer\r
+{\r
+ public class BaseAirCoprs\r
+ {\r
+ private readonly ItemInfo _itemInfo;\r
+\r
+ public BaseAirCoprs(ItemInfo item)\r
+ {\r
+ _itemInfo = item;\r
+ }\r
+\r
+ public AirCorpsInfo[] AirCorps { get; set; }\r
+\r
+ public class AirCorpsInfo\r
+ {\r
+ public int Distance { get; set; }\r
+ public int Action { get; set; }\r
+ public PlaneInfo[] Planes { get; set; }\r
+\r
+ public string ActionName\r
+ {\r
+ get\r
+ {\r
+ switch (Action)\r
+ {\r
+ case 0:\r
+ return "待機";\r
+ case 1:\r
+ return "出撃";\r
+ case 2:\r
+ return "防空";\r
+ case 3:\r
+ return "退避";\r
+ case 4:\r
+ return "休息";\r
+ default:\r
+ return "";\r
+ }\r
+ }\r
+ }\r
+\r
+ public int[] FighterPower => Planes.Aggregate(new[] {0, 0}, (prev, plane) =>\r
+ {\r
+ if (plane.State != 1)\r
+ return prev;\r
+ var slot = plane.Slot;\r
+ var unskilled = (slot.Spec.AntiAir + slot.Spec.Interception * 1.5 + slot.FighterPowerLevelBonus) *\r
+ Sqrt(plane.Count);\r
+ return new[]\r
+ {\r
+ prev[0] + (int)(unskilled + slot.AlvBonus[0]),\r
+ prev[1] + (int)(unskilled + slot.AlvBonus[1])\r
+ };\r
+ });\r
+ }\r
+\r
+ public class PlaneInfo\r
+ {\r
+ public int State { get; set; }\r
+ public ItemStatus Slot { get; set; }\r
+ public int Count { get; set; }\r
+ public int MaxCount { get; set; }\r
+\r
+ public string StateName\r
+ {\r
+ get\r
+ {\r
+ switch (State)\r
+ {\r
+ case 0:\r
+ return "未配備";\r
+ case 1:\r
+ return "配備中";\r
+ case 2:\r
+ return "配置転換中";\r
+ default:\r
+ return "";\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ public void Inspect(dynamic json)\r
+ {\r
+ AirCorps = (from entry in (dynamic[])json\r
+ select\r
+ new AirCorpsInfo\r
+ {\r
+ Distance = (int)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
+ }).ToArray();\r
+ }\r
+\r
+ public void InspectSetPlane(string request, dynamic json)\r
+ {\r
+ if (AirCorps == null)\r
+ return;\r
+ var values = HttpUtility.ParseQueryString(request);\r
+ var planeInfo = json.api_plane_info[0];\r
+ var airCorps = AirCorps[int.Parse(values["api_base_id"]) - 1];\r
+ airCorps.Distance = (int)json.api_distance;\r
+ airCorps.Planes[(int)planeInfo.api_squadron_id - 1] = new PlaneInfo\r
+ {\r
+ Slot = _itemInfo.GetStatus((int)planeInfo.api_slotid),\r
+ State = (int)planeInfo.api_state,\r
+ Count = planeInfo.api_count() ? (int)planeInfo.api_count : 0,\r
+ MaxCount = planeInfo.api_max_count() ? (int)planeInfo.api_max_count : 0,\r
+ };\r
+ }\r
+\r
+ public void InspectSetAction(string request)\r
+ {\r
+ if (AirCorps == null)\r
+ return;\r
+ var values = HttpUtility.ParseQueryString(request);\r
+ foreach (var entry in\r
+ values["api_base_id"].Split(',')\r
+ .Zip(values["api_action_kind"].Split(','), (b, a) => new {baseId = b, action = a}))\r
+ {\r
+ AirCorps[int.Parse(entry.baseId) - 1].Action = int.Parse(entry.action);\r
+ }\r
+ }\r
+ }\r
+}
\ No newline at end of file
using System;\r
using System.Collections.Generic;\r
using System.Drawing;\r
+using System.Linq;\r
using System.Windows.Forms;\r
\r
namespace KancolleSniffer\r
list.AddRange(ships);\r
}\r
list[0].Fleet2 = $"TP: S{(int)tp} A{(int)(tp * 0.7)}";\r
+ if (sniffer.BaseAirCorps != null)\r
+ {\r
+ var name = new[] {"第一", "第二", "第三"};\r
+ list.Add(new EquipColumn {Fleet = "基地航空隊"});\r
+ var i = 0;\r
+ foreach (var corps in sniffer.BaseAirCorps)\r
+ {\r
+ if (i >= name.Length)\r
+ break;\r
+ var fp = corps.FighterPower;\r
+ list.Add(new EquipColumn\r
+ {\r
+ Ship = name[i++] + " " + corps.ActionName,\r
+ Spec = "制空" + (fp[0] == fp[1] ? fp[0].ToString() : fp[0] + "~" + fp[1]) + " 距離" + corps.Distance\r
+ });\r
+ list.AddRange(corps.Planes.Select(plane => new EquipColumn\r
+ {\r
+ Equip =\r
+ plane.State != 1 ? plane.StateName : GenEquipString(plane.Slot, plane.Count, plane.MaxCount),\r
+ Color = plane.Slot.Spec.Color\r
+ }));\r
+ }\r
+ }\r
_equipList = list.ToArray();\r
}\r
\r
public int AntiSubmarine;\r
public int Torpedo;\r
public int Bomber;\r
+ public int Interception;\r
\r
public ItemSpec()\r
{\r
case 26: // 対潜哨戒機\r
case 41: // 大艇\r
case 45:\r
+ case 47: // 陸上攻撃機\r
+ case 48: // 局地戦闘機\r
return true;\r
}\r
return false;\r
case 35: // 補給物資\r
return Color.FromArgb(90, 200, 155);\r
case 37: // 陸上攻撃機\r
- return Color.FromArgb(33, 194, 89);\r
+ return Color.FromArgb(57, 182, 78);\r
+ case 38: // 局地戦闘機\r
+ return Color.FromArgb(57, 182, 78);\r
default:\r
return SystemColors.Control;\r
}\r
{07, new[] {0, 0, 0, 0, 0, 0, 0, 0}}, // 艦爆\r
{08, new[] {0, 0, 0, 0, 0, 0, 0, 0}}, // 艦攻\r
{11, new[] {0, 0, 1, 1, 1, 3, 3, 6}}, // 水爆\r
- {45, new[] {0, 0, 2, 5, 9, 14, 14, 22}} // 水戦\r
+ {45, new[] {0, 0, 2, 5, 9, 14, 14, 22}}, // 水戦\r
+ {48, new[] {0, 0, 2, 5, 9, 14, 14, 22}} // 局地戦闘機\r
};\r
\r
public double[] AlvBonus\r
dict[(int)entry.api_id] = entry.api_name;\r
foreach (var entry in json.api_mst_slotitem)\r
{\r
+ var type = (int)entry.api_type[2];\r
_itemSpecs[(int)entry.api_id] = new ItemSpec\r
{\r
Id = (int)entry.api_id,\r
Name = (string)entry.api_name,\r
- Type = (int)entry.api_type[2],\r
+ Type = type,\r
TypeName = dict[(int)entry.api_type[2]],\r
IconType = (int)entry.api_type[3],\r
AntiAir = (int)entry.api_tyku,\r
LoS = (int)entry.api_saku,\r
AntiSubmarine = (int)entry.api_tais,\r
Torpedo = (int)entry.api_raig,\r
- Bomber = (int)entry.api_baku\r
+ Bomber = (int)entry.api_baku,\r
+ Interception = type == 48 ? (int)entry.api_houk : 0 // 局地戦闘機は回避の値が迎撃\r
};\r
}\r
_itemSpecs[-1] = _itemSpecs[0] = new ItemSpec();\r
<ItemGroup>\r
<Compile Include="Achievement.cs" />\r
<Compile Include="AkashiTimer.cs" />\r
+ <Compile Include="BaseAirCoprs.cs" />\r
<Compile Include="BattleInfo.cs" />\r
<Compile Include="Config.cs" />\r
<Compile Include="ConfigDialog.cs">\r
private readonly Logger _logger;\r
private readonly ExMapInfo _exMapInfo = new ExMapInfo();\r
private readonly MiscTextInfo _miscTextInfo = new MiscTextInfo();\r
+ private readonly BaseAirCoprs _baseAirCoprs;\r
private readonly Status _status = new Status();\r
private bool _saveState;\r
private readonly List<IHaveState> _haveState;\r
_akashiTimer = new AkashiTimer(_shipInfo, _dockInfo);\r
_battleInfo = new BattleInfo(_shipInfo, _itemInfo);\r
_logger = new Logger(_shipInfo, _itemInfo, _battleInfo);\r
+ _baseAirCoprs = new BaseAirCoprs(_itemInfo);\r
_haveState = new List<IHaveState> {_achievement, _materialInfo, _conditionTimer, _exMapInfo};\r
}\r
\r
_shipInfo.InspectPresetDeck(data);\r
return Update.None;\r
}\r
+ if (url.EndsWith("api_get_member/base_air_corps"))\r
+ {\r
+ _baseAirCoprs.Inspect(data);\r
+ return Update.Ship;\r
+ }\r
return Update.None;\r
}\r
\r
if (url.EndsWith("api_req_air_corps/set_plane"))\r
{\r
_materialInfo.InspectAirCorpsSetPlane(data);\r
- return Update.Item;\r
+ _baseAirCoprs.InspectSetPlane(request, data);\r
+ return Update.Item | Update.Ship;\r
+ }\r
+ if (url.EndsWith("api_req_air_corps/set_action"))\r
+ {\r
+ _baseAirCoprs.InspectSetAction(request);\r
+ return Update.Ship;\r
}\r
return Update.None;\r
}\r
\r
public string MiscText => _miscTextInfo.Text;\r
\r
+ public BaseAirCoprs.AirCorpsInfo[] BaseAirCorps => _baseAirCoprs.AirCorps;\r
+\r
public void SetLogWriter(Action<string, string, string> writer, Func<DateTime> nowFunc)\r
{\r
_logger.SetWriter(writer, nowFunc);\r