--- /dev/null
+1,\96r\8c\8e,2\r
+2,\94@\8c\8e,1\r
+6,\92·\8c\8e,1\r
+7,\8eO\93ú\8c\8e,1\r
+9,\90\81\90á,2\r
+10,\94\92\90á,1\r
+11,\90[\90á,1\r
+12,\88é\94g,1\r
+13,\88»\94g,2\r
+14,\95~\94g,1\r
+15,\8f\8c,1\r
+16,\92ª,1\r
+17,\97z\89\8a,2\r
+18,\95s\92m\89Î,1\r
+19,\8d\95\92ª,1\r
+20,\90á\95\97,2\r
+21,\92·\97Ç,2\r
+22,\8cÜ\8f\\97é,1\r
+23,\97R\97Ç,1\r
+24,\91å\88ä,2\r
+25,\96k\8fã,2\r
+26,\95}\8cK,3\r
+27,\8eR\8fé,3\r
+28,\8eH\8c\8e,1\r
+29,\95¶\8c\8e,1\r
+30,\8be\8c\8e,1\r
+31,\96]\8c\8e,1\r
+32,\8f\89\90á,1\r
+33,\91p\89_,1\r
+34,\8bÅ,2\r
+35,\8b¿,1\r
+36,\97\8b,1\r
+37,\93d,1\r
+38,\8f\89\8ft,2\r
+39,\8eq\93ú,1\r
+40,\8eá\97t,1\r
+41,\8f\89\91\9a,1\r
+42,\94\92\98I,2\r
+43,\8e\9e\89J,1\r
+44,\91º\89J,1\r
+45,\97[\97§,1\r
+46,\8cÜ\8c\8e\89J,1\r
+47,\97Á\95\97,2\r
+48,èÅ,1\r
+49,\89à,1\r
+50,\93\87\95\97,2\r
+51,\93V\97´,2\r
+52,\97´\93c,2\r
+53,\96¼\8eæ,1\r
+54,\90ì\93à,2\r
+55,\90_\92Ê,1\r
+56,\93ß\89Ï,1\r
+59,\8cÃ\91é,2\r
+60,\89Á\8cÃ,1\r
+61,\90Â\97t,2\r
+62,\96\8d\82,2\r
+63,\93ß\92q,1\r
+64,\91«\95¿,1\r
+65,\89H\8d\95,1\r
+66,\8d\82\97Y,2\r
+67,\88¤\93\86,2\r
+68,\96\80\96ë,1\r
+69,\92¹\8aC,1\r
+70,\8dÅ\8fã,2\r
+71,\97\98\8dª,2\r
+72,\92}\96\80,2\r
+74,\8fË\96P,2\r
+75,\94ò\91é,3\r
+76,\97´é\88,2\r
+77,\88É\90¨,3\r
+78,\8bà\8d\84,3\r
+79,\90Y\96¼,3\r
+80,\92·\96å,3\r
+81,\97¤\89\9c,3\r
+83,\90Ô\8fé,3\r
+84,\89Á\89ê,3\r
+85,\96¶\93\87,3\r
+86,\94ä\89b,3\r
+87,\93ú\8cü,3\r
+89,\96PãÄ,1\r
+90,\91\93\97´,3\r
+91,\94ò\97´,3\r
+92,\94¹\91é,3\r
+93,\9eO,1\r
+94,\97ø,1\r
+95,\92©\92ª,2\r
+96,\91å\92ª,1\r
+97,\96\9e\92ª,1\r
+98,\8dr\92ª,1\r
+99,\8b\85\96\81,2\r
+100,\91½\96\80,1\r
+101,\96Ø\91\,1\r
+102,\90ç\8dÎ,2\r
+103,\90ç\91ã\93c,2\r
+110,ãÄ\92ß,3\r
+111,\90\90\92ß,3\r
+113,\8bS\93{,1\r
+114,\88¢\95\90\8cG,1\r
+115,\97[\92£,2\r
+116,\90\90\96P,2\r
+120,\8eO\8cG,2\r
+122,\95\91\95\97,2\r
+123,\88ß\8a},2\r
+124,\97é\92J,2\r
+125,\8cF\96ì,2\r
+126,\88É168,0\r
+127,\88É58,0\r
+128,\88É8,0\r
+131,\91å\98a,3\r
+132,\8fH\89_,2\r
+133,\97[\89_,2\r
+134,\8aª\89_,2\r
+135,\92·\94g,2\r
+137,\88¢\89ê\96ì,2\r
+138,\94\\91ã,2\r
+139,\96î\94\8a,2\r
+140,\8eð\93õ,2\r
+143,\95\90\91 ,3\r
+153,\91å\96P,3\r
+154,\8d\81\8eæ,3\r
+155,\88É401,0\r
+161,\82 \82«\82Â\8aÛ,2\r
+162,\90_\88Ð,0\r
+163,\82Ü\82é\82ä,0\r
+164,\96í\90¶,1\r
+165,\89K\8c\8e,1\r
+167,\88é\95\97,2\r
+168,\89Y\95\97,2\r
+169,\92J\95\97,2\r
+170,\95l\95\97,2\r
+171,Bismarck,2\r
+174,Z1,1\r
+175,Z3,1\r
+176,Prinz Eugen,2\r
+181,\93V\92Ã\95\97,3\r
+182,\96¾\90Î,2\r
+183,\91å\97\84,3\r
+184,\91å\8c~,2\r
+186,\8e\9e\92Ã\95\97,2\r
+190,\8f\89\95\97,2\r
+191,\88É19,0\r
+331,\93V\8fé,2\r
+332,\8a\8b\8fé,2\r
+404,\89_\97´,2\r
+405,\8ft\89J,2\r
+409,\91\81\91\9a,2\r
+410,\90´\91\9a,2\r
+413,\92©\89_,2\r
+414,\8eR\89_,2\r
+415,\96ì\95ª,2\r
+421,\8fH\8c\8e,3\r
+422,\8fÆ\8c\8e,3\r
+423,\8f\89\8c\8e,3\r
+424,\8d\82\94g,2\r
+425,\92©\91\9a,2\r
+431,U-511,1\r
+432,Graf Zeppelin,2\r
+433,Saratoga,2\r
+439,Warspite,1\r
+440,Iowa,2\r
+441,Littorio,3\r
+442,Roma,3\r
+443,Libeccio,1\r
+444,Aquila,1\r
+445,\8fH\92Ã\8fF,2\r
+448,Zara,1\r
+449,Pola,1\r
+451,\90\90\95ä,2\r
+452,\89«\94g,2\r
+453,\95\97\89_,2\r
+454,\97\92,2\r
+455,\94\8b\95\97,2\r
+456,\90e\92ª,2\r
+457,\8eR\95\97,1\r
+458,\8aC\95\97,1\r
+459,\8d]\95\97,1\r
+460,\91¬\8bz,2\r
+465,\8e\93\87,3\r
+471,\90_\95\97,2\r
+472,\92©\95\97,2\r
+473,\8ft\95\97,2\r
+474,\8f¼\95\97,2\r
+475,\8aø\95\97,2\r
+479,\93V\96¶,1\r
+480,\8b·\96¶,1\r
+481,\90\85\96³\8c\8e,1\r
+483,\88É26,0\r
+484,\95l\94g,2\r
+485,\93¡\94g,2\r
+486,\89Y\94g,2\r
+491,Commandant Teste,1\r
+492,Richelieu,2\r
+493,\88É400,0\r
+494,\88É13,0\r
+495,\88É14,0\r
+511,\84C\84p\84~\84s\84\85\84\84,2\r
+515,Ark Royal,2\r
+516,\84S\84p\84\8a\84{\84u\84~\84\84,3\r
+517,\90è\8eç,2\r
+518,\8d\91\8cã,2\r
+519,Jervis,1\r
+521,\8ft\93ú\8aÛ,1\r
+524,\91ð\91¨,2\r
+525,\8f¼\97Ö,2\r
+531,\8d²\93n,2\r
+532,\97Á\8c\8e,3\r
+535,Luigi Torelli,0\r
+540,\91Î\94n,2\r
+544,Gambier Bay,1\r
+549,Intrepid,1\r
+551,\93ú\90U,2\r
+552,\91å\93\8c,2\r
+561,Samuel B.Roberts,1\r
+565,\95\9f\8d],2\r
\r
namespace KancolleSniffer.Test\r
{\r
+ using Sniffer = SnifferTest.TestingSniffer;\r
+\r
[TestClass]\r
public class LoggerTest\r
{\r
\r
namespace KancolleSniffer.Test\r
{\r
+ using Sniffer = SnifferTest.TestingSniffer;\r
+\r
[TestClass]\r
public class SnifferTest\r
{\r
.GlobalAssertionConfiguration.WithPrintedListLengthLimit(200).WithMaximumValueLength(1000);\r
}\r
\r
+ public class TestingSniffer : KancolleSniffer.Sniffer\r
+ {\r
+ public TestingSniffer(bool start = false) : base(start)\r
+ {\r
+ AdditionalData.UseNumEquipsFile = false;\r
+ }\r
+ }\r
+\r
public static StreamReader OpenLogFile(string name)\r
{\r
var dir = Path.GetDirectoryName(Path.GetDirectoryName(Environment.CurrentDirectory));\r
PAssert.That(() =>\r
sniffer.MiscText == "[獲得アイテム]\r\n弾薬: 150\r\n開発資材: 1", "途中でリロードして再出撃");\r
}\r
+\r
+ /// <summary>\r
+ /// 新規のドロップ艦の初期装備数を登録する\r
+ /// </summary>\r
+ [TestMethod]\r
+ public void RecordNumEqipsOfNewDropShip()\r
+ {\r
+ var sniffer = new Sniffer();\r
+ SniffLogFile(sniffer, "dropship_001");\r
+ PAssert.That(() => sniffer.AdditionalData.NumEquips(565) == 2);\r
+ PAssert.That(() => sniffer.ShipList.First(s => s.Spec.Id == 565).Spec.NumEquips == 2);\r
+ }\r
+\r
+ /// <summary>\r
+ /// 既知のドロップ艦とその装備をカウントする\r
+ /// </summary>\r
+ [TestMethod]\r
+ public void CountDropShip()\r
+ {\r
+ var sniffer = new Sniffer();\r
+ sniffer.AdditionalData.RecordNumEquips(11, "", 1);\r
+ SniffLogFile(sniffer, "dropship_002");\r
+ PAssert.That(() => sniffer.Item.NowShips == 250);\r
+ PAssert.That(() => sniffer.Item.NowEquips == 1159);\r
+ }\r
}\r
}
\ No newline at end of file
-Subproject commit f536d67271f300eb34b6e2bcc1f077ae19d08d8b
+Subproject commit dcb6cd982f57c262ff5280f13873595f3cc4864e
\r
public double ItemTp(int id) =>\r
_tpSpec != null ? _tpSpec.TryGetValue(id, out var tp) ? tp : -1 : -1;\r
+\r
+ private static readonly string NumEquipsFile = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "NumEquips.csv");\r
+\r
+ private Dictionary<int, int> _numEquips = new Dictionary<int, int>();\r
+\r
+ public bool UseNumEquipsFile { get; set; } = true;\r
+\r
+ public void LoadNumEquips()\r
+ {\r
+ try\r
+ {\r
+ if (!UseNumEquipsFile)\r
+ return;\r
+ _numEquips = File.ReadLines(NumEquipsFile)\r
+ .Select(line => line.Split(','))\r
+ .ToDictionary(f => int.Parse(f[0]), f => int.Parse(f[2]));\r
+ }\r
+ catch (IOException)\r
+ {\r
+ }\r
+ }\r
+\r
+ public int NumEquips(int id) => _numEquips.TryGetValue(id, out var num) ? num : -1;\r
+\r
+ public void RecordNumEquips(int id, string name, int numEquips)\r
+ {\r
+ _numEquips[id] = numEquips;\r
+ if (UseNumEquipsFile)\r
+ File.AppendAllText(NumEquipsFile, $"{id},{name},{numEquips}\r\n");\r
+ }\r
}\r
}
\ No newline at end of file
BattleState = BattleState.Result;\r
ShowResult(!_lastCell);\r
_shipInfo.SaveBattleResult();\r
+ _shipInfo.DropShipId = json.api_get_ship() ? (int)json.api_get_ship.api_ship_id : -1;\r
VerifyResultRank(json);\r
CleanupResult();\r
SetEscapeShips(json);\r
}\r
}\r
\r
- public Func<int, double?> GetItemTp { private get; set; }\r
+ public Func<double> GetItemTp { get; set; }\r
\r
public double TransportPoint\r
{\r
get\r
{\r
- var tp = GetItemTp?.Invoke(Id);\r
+ var tp = GetItemTp?.Invoke();\r
if (tp >= 0)\r
return (double)tp;\r
switch (Id)\r
public int NowEquips\r
{\r
get => _nowEquips;\r
- private set\r
+ set\r
{\r
if (MaxEquips != 0)\r
{\r
var dict = new Dictionary<int, string>();\r
foreach (var entry in json.api_mst_slotitem_equiptype)\r
dict[(int)entry.api_id] = entry.api_name;\r
- AdditionalData?.LoadTpSpec();\r
+ AdditionalData.LoadTpSpec();\r
foreach (var entry in json.api_mst_slotitem)\r
{\r
var type = (int)entry.api_type[2];\r
+ var id = (int)entry.api_id;\r
_itemSpecs[(int)entry.api_id] = new ItemSpec\r
{\r
- Id = (int)entry.api_id,\r
+ Id = id,\r
Name = (string)entry.api_name,\r
Type = type,\r
TypeName = dict.TryGetValue(type, out var typeName) ? typeName : "不明",\r
Interception = type == 48 ? (int)entry.api_houk : 0, // 局地戦闘機は回避の値が迎撃\r
AntiBomber = type == 48 ? (int)entry.api_houm : 0, // 〃命中の値が対爆\r
Distance = entry.api_distance() ? (int)entry.api_distance : 0,\r
- GetItemTp = id => AdditionalData?.ItemTp(id)\r
+ GetItemTp = () => AdditionalData.ItemTp(id)\r
};\r
}\r
_itemSpecs[-1] = _itemSpecs[0] = new ItemSpec();\r
private readonly ItemInfo _itemInfo;\r
private readonly List<int> _escapedShips = new List<int>();\r
private ShipStatus[] _battleResult = new ShipStatus[0];\r
+ private readonly NumEquipsChecker _numEquipsChecker = new NumEquipsChecker();\r
public int HqLevel { get; private set; }\r
public ShipStatusPair[] BattleResultDiff { get; private set; } = new ShipStatusPair[0];\r
public bool IsBattleResultError => BattleResultDiff.Length > 0;\r
public ShipStatus[] BattleStartStatus { get; private set; } = new ShipStatus[0];\r
+ public int DropShipId { private get; set; } = -1;\r
+\r
+ private class NumEquipsChecker\r
+ {\r
+ public int MaxId { private get; set; } = int.MaxValue;\r
+\r
+ public void Check(ShipStatus ship)\r
+ {\r
+ var spec = ship.Spec;\r
+ if (spec.NumEquips != -1 || ship.Id <= MaxId)\r
+ return;\r
+ spec.NumEquips = ship.Slot.Count(item => item.Id != -1);\r
+ }\r
+ }\r
\r
public class ShipStatusPair\r
{\r
public void InspectMaster(dynamic json)\r
{\r
_shipMaster.Inspect(json);\r
+ ClearShipInfo();\r
}\r
\r
public void InspectShip(dynamic json)\r
}\r
else if (json.api_data()) // ship2\r
{\r
- // 一隻分のデータしか来ないことがあるので艦娘数を数えない\r
InspectDeck(json.api_data_deck);\r
InspectShipData(json.api_data);\r
}\r
else if (json.api_ship_data()) // ship3とship_deck\r
{\r
- // 一隻分のデータしか来ないことがあるので艦娘数を数えない\r
InspectDeck(json.api_deck_data);\r
InspectShipData(json.api_ship_data);\r
VerifyBattleResult();\r
+ // ship_deckでドロップ艦を反映する\r
+ if (DropShipId != -1)\r
+ {\r
+ _itemInfo.NowShips++;\r
+ var num = _shipMaster.GetSpec(DropShipId).NumEquips;\r
+ if (num > 0)\r
+ _itemInfo.NowEquips += num;\r
+ }\r
}\r
else if (json.api_ship()) // getshipとpowerup\r
{\r
InspectShipData(new[] {json.api_ship});\r
}\r
+ DropShipId = -1;\r
}\r
\r
public void SaveBattleResult()\r
{\r
foreach (var entry in json)\r
{\r
- _shipInfo[(int)entry.api_id] = new ShipStatus\r
+ var id = (int)entry.api_id;\r
+ var ship = new ShipStatus\r
{\r
- Id = (int)entry.api_id,\r
+ Id = id,\r
Spec = _shipMaster.GetSpec((int)entry.api_ship_id),\r
Level = (int)entry.api_lv,\r
ExpToNext = (int)entry.api_exp[1],\r
Fuel = (int)entry.api_fuel,\r
Bull = (int)entry.api_bull,\r
OnSlot = (int[])entry.api_onslot,\r
- Slot = ((int[])entry.api_slot).Select(id => new ItemStatus(id)).ToArray(),\r
+ Slot = ((int[])entry.api_slot).Select(item => new ItemStatus(item)).ToArray(),\r
SlotEx = entry.api_slot_ex() ? new ItemStatus((int)entry.api_slot_ex) : new ItemStatus(0),\r
NdockTime = (int)entry.api_ndock_time,\r
NdockItem = (int[])entry.api_ndock_item,\r
Lucky = (int)entry.api_lucky[0],\r
Locked = entry.api_locked() && entry.api_locked == 1\r
};\r
+ _shipInfo[id] = ship;\r
+ _numEquipsChecker.Check(ship);\r
}\r
+ _numEquipsChecker.MaxId = _shipInfo.Keys.Max();\r
}\r
\r
private void InspectBasic(dynamic json)\r
foreach (var entry in json.api_mst_stype)\r
dict[entry.api_id] = entry.api_name;\r
dict[8] = "巡洋戦艦";\r
- AdditionalData?.LoadEnemySlot();\r
+ AdditionalData.LoadEnemySlot();\r
+ AdditionalData.LoadNumEquips();\r
foreach (var entry in json.api_mst_ship)\r
{\r
var shipSpec = _shipSpecs[(int)entry.api_id] = new ShipSpec\r
}\r
shipSpec.GetMaxEq = entry.api_maxeq()\r
? (Func<int[]>)(() => entry.api_maxeq)\r
- : () => AdditionalData?.EnemySlot(shipSpec.Id);\r
+ : () => AdditionalData.EnemySlot(shipSpec.Id);\r
+ shipSpec.GetNumEquips = () => AdditionalData.NumEquips(shipSpec.Id);\r
+ shipSpec.SetNumEquips = num => AdditionalData.RecordNumEquips(shipSpec.Id, shipSpec.Name,num);\r
}\r
_shipSpecs[-1] = new ShipSpec();\r
SetRemodelBaseAndStep();\r
public int SlotNum { get; set; }\r
public Func<int[]> GetMaxEq { get; set; }\r
public int[] MaxEq => GetMaxEq?.Invoke();\r
+ public Func<int> GetNumEquips { get; set; }\r
+ public Action<int> SetNumEquips { get; set; }\r
+\r
+ public int NumEquips\r
+ {\r
+ get => GetNumEquips();\r
+ set => SetNumEquips(value);\r
+ }\r
+\r
public int ShipType { get; set; }\r
public int ShipClass { get; set; }\r
public string ShipTypeName { get; set; }\r
_shipInfo.InspectShip(data);\r
_akashiTimer.CheckFleet();\r
_battleInfo.BattleState = BattleState.None;\r
- return Update.Ship | Update.Battle;\r
+ return Update.Ship | Update.Battle | Update.Item;\r
}\r
if (url.EndsWith("api_get_member/ship3"))\r
{\r