From a92a57c92d73ff6a586ef7cc7a83d1acb1b1a022 Mon Sep 17 00:00:00 2001 From: Kazuhiro Fujieda Date: Thu, 2 Aug 2018 21:54:22 +0900 Subject: [PATCH] =?utf8?q?Fleet=E3=82=AF=E3=83=A9=E3=82=B9=E3=81=A7?= =?utf8?q?=E8=89=A6=E9=9A=8A=E7=B7=A8=E6=88=90=E3=82=92=E8=A1=8C=E3=81=84S?= =?utf8?q?hipStatus=E3=81=AE=E3=83=AA=E3=82=B9=E3=83=88=E3=82=92=E6=A7=8B?= =?utf8?q?=E7=AF=89=E3=81=99=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- KancolleSniffer.Test/BattleTest.cs | 2 +- KancolleSniffer.Test/SnifferTest.cs | 2 +- KancolleSniffer/Logger.cs | 67 ++++++++++---------- KancolleSniffer/MainForm.cs | 12 ++-- KancolleSniffer/Model/AkashiTimer.cs | 26 ++++---- KancolleSniffer/Model/BattleInfo.cs | 50 ++++++++------- KancolleSniffer/Model/Fleet.cs | 86 +++++++++++++++++++++---- KancolleSniffer/Model/ShipInfo.cs | 111 +++++++++++++-------------------- KancolleSniffer/Model/ShipStatus.cs | 4 +- KancolleSniffer/Sniffer.cs | 2 +- KancolleSniffer/TextGenerator.cs | 6 +- KancolleSniffer/View/AntiAirPanel.cs | 2 +- KancolleSniffer/View/FleetPanel.cs | 48 +++++++------- KancolleSniffer/View/MainFormLabels.cs | 36 +++++------ KancolleSniffer/View/MiscTextInfo.cs | 4 +- 15 files changed, 247 insertions(+), 211 deletions(-) diff --git a/KancolleSniffer.Test/BattleTest.cs b/KancolleSniffer.Test/BattleTest.cs index 28b05b0..38bdd0e 100644 --- a/KancolleSniffer.Test/BattleTest.cs +++ b/KancolleSniffer.Test/BattleTest.cs @@ -62,8 +62,8 @@ namespace KancolleSniffer.Test var id = _shipInventry.MaxId + 1; var ships = nowhps.Zip(maxhps, (now, max) => new ShipStatus {Id = id++, NowHp = now, MaxHp = max}).ToArray(); - _shipInfo.Fleets[deck].Deck = (from ship in ships select ship.Id).ToArray(); _shipInventry.Add(ships); + _shipInfo.Fleets[deck].Deck = (from ship in ships select ship.Id).ToArray(); foreach (var entry in ships.Zip(slots, (ship, slot) => new {ship, slot})) { entry.ship.Slot = _itemInfo.InjectItems(entry.slot.Take(5)); diff --git a/KancolleSniffer.Test/SnifferTest.cs b/KancolleSniffer.Test/SnifferTest.cs index 71f62ed..8f5e929 100644 --- a/KancolleSniffer.Test/SnifferTest.cs +++ b/KancolleSniffer.Test/SnifferTest.cs @@ -420,7 +420,7 @@ namespace KancolleSniffer.Test { var sniffer = new Sniffer(); SniffLogFile(sniffer, "nightbattlepower_001"); - var ships = sniffer.Fleets[0].Ships; + var ships = sniffer.Fleets[0].ActualShips; PAssert.That(() => ships.Select(ship => (int)(ship.NightBattlePower * 100)) .SequenceEqual(new[] {11202, 14985, 20092, 17354})); diff --git a/KancolleSniffer/Logger.cs b/KancolleSniffer/Logger.cs index 597219c..341b8a0 100644 --- a/KancolleSniffer/Logger.cs +++ b/KancolleSniffer/Logger.cs @@ -245,56 +245,53 @@ namespace KancolleSniffer int deckId = BattleInfo.DeckId(_battle); if (_battle.api_f_nowhps_combined()) { - var main = _shipInfo.Fleets[0].Deck; - var guard = _shipInfo.Fleets[1].Deck; - return main.Zip(guard, (m, g) => + var mainShips = _shipInfo.Fleets[0].Ships; + var guardShips = _shipInfo.Fleets[1].Ships; + return mainShips.Zip(guardShips, (main, guard) => { - if (m == -1 && g == -1) + if (main.Empty && guard.Empty) return ","; var name = ""; var hp = ""; - if (m != -1) + if (!main.Empty) { - var sm = _shipInfo.GetStatus(m); - name = $"{sm.Name}(Lv{sm.Level})"; - hp = $"{sm.NowHp}/{sm.MaxHp}"; + name = $"{main.Name}(Lv{main.Level})"; + hp = $"{main.NowHp}/{main.MaxHp}"; } name += "・"; hp += "・"; - if (g != -1) + if (!guard.Empty) { - var sg = _shipInfo.GetStatus(g); - name += $"{sg.Name}(Lv{sg.Level})"; - hp += $"{sg.NowHp}/{sg.MaxHp}"; + name += $"{guard.Name}(Lv{guard.Level})"; + hp += $"{guard.NowHp}/{guard.MaxHp}"; } return name + "," + hp; }).ToList(); } - var deck = _shipInfo.Fleets[deckId].Deck; - if (deck.Length > 6) + var ships = _shipInfo.Fleets[deckId].Ships; + if (ships.Count > 6) { var result = new List(); - for (var i = 0; i < 12 - deck.Length; i++) + for (var i = 0; i < 12 - ships.Count; i++) { - var s = _shipInfo.GetStatus(deck[i]); - result.Add($"{s.Name}(Lv{s.Level}),{s.NowHp}/{s.MaxHp}"); + var ship = ships[i]; + result.Add($"{ship.Name}(Lv{ship.Level}),{ship.NowHp}/{ship.MaxHp}"); } - for (var i = 0; i < deck.Length - 6; i++) + for (var i = 0; i < ships.Count - 6; i++) { - var s1 = _shipInfo.GetStatus(deck[12 - deck.Length + i]); - var s2 = _shipInfo.GetStatus(deck[6 + i]); + var s1 = ships[12 - ships.Count + i]; + var s2 = ships[6 + i]; result.Add( $"{s1.Name}(Lv{s1.Level})・{s2.Name}(Lv{s2.Level})," + $"{s1.NowHp}/{s1.MaxHp}・{s2.NowHp}/{s2.MaxHp}"); } return result; } - return deck.Select(id => + return ships.Select(ship => { - if (id == -1) + if (ship.Empty) return ","; - var s = _shipInfo.GetStatus(id); - return $"{s.Name}(Lv{s.Level}),{s.NowHp}/{s.MaxHp}"; + return $"{ship.Name}(Lv{ship.Level}),{ship.NowHp}/{ship.MaxHp}"; }).ToList(); } @@ -305,25 +302,25 @@ namespace KancolleSniffer { return result.Select(s => s.Empty ? "," : $"{s.Name},{s.NowHp}/{s.MaxHp}").ToList(); } - var main = result; - var guard = _battleInfo.Result.Enemy.Guard.Concat(Enumerable.Repeat(new ShipStatus(), 6)).Take(6); - return main.Zip(guard, (m, g) => + var mainShips = result; + var guardShips = _battleInfo.Result.Enemy.Guard.Concat(Enumerable.Repeat(new ShipStatus(), 6)).Take(6); + return mainShips.Zip(guardShips, (main, guard) => { - if (m.Empty && g.Empty) + if (main.Empty && guard.Empty) return ","; var name = ""; var hp = ""; - if (!m.Empty) + if (!main.Empty) { - name = $"{m.Name}"; - hp = $"{m.NowHp}/{m.MaxHp}"; + name = $"{main.Name}"; + hp = $"{main.NowHp}/{main.MaxHp}"; } name += "・"; hp += "・"; - if (!g.Empty) + if (!guard.Empty) { - name += $"{g.Name}"; - hp += $"{g.NowHp}/{g.MaxHp}"; + name += $"{guard.Name}"; + hp += $"{guard.NowHp}/{guard.MaxHp}"; } return name + "," + hp; }).ToList(); @@ -553,7 +550,7 @@ namespace KancolleSniffer var ship1 = Secretary(); var ship2 = ""; var ships = _shipInfo.Fleets[0].Ships; - if (ships.Length >= 2) + if (!ships[1].Empty) ship2 = ships[1].Name + "(" + ships[1].Level + ")"; _writer("改修報告書", FormatDateTime(now) + "," + diff --git a/KancolleSniffer/MainForm.cs b/KancolleSniffer/MainForm.cs index e65597c..905b4f0 100644 --- a/KancolleSniffer/MainForm.cs +++ b/KancolleSniffer/MainForm.cs @@ -524,8 +524,8 @@ namespace KancolleSniffer if (!_listForm.Visible) return; var idx = (int)((Control)sender).Tag; - var ships = _sniffer.Fleets[_currentFleet].Ships; - if (ships.Length <= idx) + var ships = _sniffer.Fleets[_currentFleet].ActualShips; + if (ships.Count <= idx) return; _listForm.ShowShip(ships[idx].Id); } @@ -642,15 +642,15 @@ namespace KancolleSniffer private void UpdatePanelShipInfo() { var fleets = _sniffer.Fleets; - var ships = fleets[_currentFleet].Ships; - panel7Ships.Visible = ships.Length == 7; + var ships = fleets[_currentFleet].ActualShips; + panel7Ships.Visible = ships.Count == 7; _mainLabels.SetShipLabels(ships); if (!_sniffer.IsCombinedFleet) _combinedFleet = false; labelFleet1.Text = _combinedFleet ? "連合" : "第一"; panelCombinedFleet.Visible = _combinedFleet; if (_combinedFleet) - _mainLabels.SetCombinedShipLabels(fleets[0].Ships, fleets[1].Ships); + _mainLabels.SetCombinedShipLabels(fleets[0].ActualShips, fleets[1].ActualShips); for (var i = 0; i < _labelCheckFleets.Length; i++) _labelCheckFleets[i].Visible = _currentFleet == i; UpdateAkashiTimer(); @@ -924,7 +924,7 @@ namespace KancolleSniffer { if (_config.UsePresetAkashi) UpdatePresetAkashiTimer(); - _mainLabels.SetAkashiTimer(_sniffer.Fleets[_currentFleet].Ships, + _mainLabels.SetAkashiTimer(_sniffer.Fleets[_currentFleet].ActualShips, _sniffer.AkashiTimer.GetTimers(_currentFleet)); } diff --git a/KancolleSniffer/Model/AkashiTimer.cs b/KancolleSniffer/Model/AkashiTimer.cs index 0490206..acba9ed 100644 --- a/KancolleSniffer/Model/AkashiTimer.cs +++ b/KancolleSniffer/Model/AkashiTimer.cs @@ -41,8 +41,8 @@ namespace KancolleSniffer.Model private class RepairStatus { - private ShipStatus[] _target = new ShipStatus[0]; - private int[] _deck = new int[0]; + private IReadOnlyList _target = new ShipStatus[0]; + private IReadOnlyList _deck = new int[0]; private TimeSpan FirstRepairTime => TimeSpan.FromMinutes(20); private bool PassedFirstRepairTime(DateTime start, DateTime prev, DateTime now) => @@ -52,7 +52,7 @@ namespace KancolleSniffer.Model TimeSpan.FromMinutes(Math.Ceiling(ship.RepairTime.TotalMinutes / (ship.MaxHp - ship.NowHp) * damage)); - public int[] Deck + public IReadOnlyList Deck { set => _deck = value; } @@ -183,11 +183,11 @@ namespace KancolleSniffer.Model private void CheckFleet(Fleet fleet) { - var deck = fleet.Deck.ToArray(); + var deck = fleet.Deck; + var ships = fleet.Ships; var repair = _repairStatuses[fleet.Number]; - var fs = _shipInfo.GetStatus(deck[0]); repair.State = State.Continue; - if (!fs.Spec.IsRepairShip) + if (!ships[0].Spec.IsRepairShip) { repair.UpdateTarget(new ShipStatus[0]); repair.Deck = deck; @@ -198,15 +198,15 @@ namespace KancolleSniffer.Model repair.State = State.Reset; repair.Deck = deck; } - var target = RepairTarget(deck); + var target = RepairTarget(ships); if (repair.IsRepaired(target)) repair.State = State.Reset; repair.UpdateTarget(target); } - private ShipStatus[] RepairTarget(int[] deck) + private ShipStatus[] RepairTarget(IReadOnlyList ships) { - var fs = _shipInfo.GetStatus(deck[0]); + var fs = ships[0]; if (!fs.Spec.IsRepairShip || _dockInfo.InNDock(fs.Id) || fs.DamageLevel >= ShipStatus.Damage.Half) return new ShipStatus[0]; var cap = fs.Slot.Count(item => item.Spec.IsRepairFacility) + 2; @@ -215,11 +215,11 @@ namespace KancolleSniffer.Model * - 入渠中の艦娘は終わったときに回復扱いされないようNowHp=MaxHpに * - 中破以上でNowHp=MaxHpにすると回復扱いされるのでNowHp=MaxHp=0に */ - return (from id in deck.Take(cap) - let s = (ShipStatus)_shipInfo.GetStatus(id).Clone() + return (from ship in ships.Take(cap) + let s = (ShipStatus)ship.Clone() let full = new ShipStatus {NowHp = s.MaxHp, MaxHp = s.MaxHp} let zero = new ShipStatus() - select _dockInfo.InNDock(id) ? full : s.DamageLevel >= ShipStatus.Damage.Half ? zero : s).ToArray(); + select _dockInfo.InNDock(s.Id) ? full : s.DamageLevel >= ShipStatus.Damage.Half ? zero : s).ToArray(); } public RepairSpan[] GetTimers(int fleet) @@ -242,7 +242,7 @@ namespace KancolleSniffer.Model public bool CheckPresetRepairing() => _presetDeck.Decks.Where(deck => deck != null) - .Any(deck => RepairTarget(deck).Any(s => s.NowHp < s.MaxHp)); + .Any(deck => RepairTarget(deck.Select(id => _shipInfo.GetShip(id)).ToArray()).Any(s => s.NowHp < s.MaxHp)); public Notice[] GetNotice(DateTime prev, DateTime now) { diff --git a/KancolleSniffer/Model/BattleInfo.cs b/KancolleSniffer/Model/BattleInfo.cs index 31a4f1a..d4057cc 100644 --- a/KancolleSniffer/Model/BattleInfo.cs +++ b/KancolleSniffer/Model/BattleInfo.cs @@ -131,10 +131,10 @@ namespace KancolleSniffer.Model _shipInfo.SaveBattleStartStatus(); var fleets = _shipInfo.Fleets; _fleet = fleets[DeckId(json)]; - FlagshipRecovery(request, _fleet.Ships[0]); - _friend = Record.Setup(_fleet.Ships, practice); + FlagshipRecovery(request, _fleet.ActualShips[0]); + _friend = Record.Setup(_fleet.ActualShips, practice); _guard = json.api_f_nowhps_combined() - ? Record.Setup(fleets[1].Ships, practice) + ? Record.Setup(fleets[1].ActualShips, practice) : new Record[0]; _enemy = Record.Setup((int[])json.api_e_nowhps, ((int[])json.api_ship_ke).Select(_shipInfo.GetSpec).ToArray(), @@ -165,7 +165,7 @@ namespace KancolleSniffer.Model }; } - private void FlagshipRecovery(string request, ShipStatus flagship) + private void FlagshipRecovery(string request, ShipStatus flagship) { var type = int.Parse(HttpUtility.ParseQueryString(request)["api_recovery_type"] ?? "0"); switch (type) @@ -477,6 +477,8 @@ namespace KancolleSniffer.Model public void InspectBattleResult(dynamic json) { BattleState = BattleState.Result; + if (_friend == null) + return; ShowResult(!_lastCell); _shipInfo.SaveBattleResult(); _shipInfo.DropShipId = json.api_get_ship() ? (int)json.api_get_ship.api_ship_id : -1; @@ -485,23 +487,11 @@ namespace KancolleSniffer.Model SetEscapeShips(json); } - private void VerifyResultRank(dynamic json) - { - if (_friend == null) - return; - if (!json.api_win_rank()) - return; - var assumed = "PSABCDE"[(int)ResultRank]; - if (assumed == 'P') - assumed = 'S'; - var actual = ((string)json.api_win_rank)[0]; - DisplayedResultRank.Assumed = assumed; - DisplayedResultRank.Actual = actual; - } - public void InspectPracticeResult(dynamic json) { BattleState = BattleState.Result; + if (_friend == null) + return; ShowResult(false); VerifyResultRank(json); CleanupResult(); @@ -513,8 +503,8 @@ namespace KancolleSniffer.Model return; var fleets = _shipInfo.Fleets; var ships = _guard.Length > 0 - ? fleets[0].Ships.Concat(fleets[1].Ships) - : _fleet.Ships; + ? fleets[0].ActualShips.Concat(fleets[1].ActualShips) + : _fleet.ActualShips; foreach (var entry in ships.Zip(_friend.Concat(_guard), (ship, now) => new {ship, now})) entry.now.UpdateShipStatus(entry.ship); if (warnDamagedShip) @@ -523,6 +513,18 @@ namespace KancolleSniffer.Model _shipInfo.ClearBadlyDamagedShips(); } + private void VerifyResultRank(dynamic json) + { + if (!json.api_win_rank()) + return; + var assumed = "PSABCDE"[(int)ResultRank]; + if (assumed == 'P') + assumed = 'S'; + var actual = ((string)json.api_win_rank)[0]; + DisplayedResultRank.Assumed = assumed; + DisplayedResultRank.Actual = actual; + } + public void SetEscapeShips(dynamic json) { _escapingShips.Clear(); @@ -558,11 +560,11 @@ namespace KancolleSniffer.Model public string Name => _status.Name; public int StartHp { get; private set; } - public static Record[] Setup(ShipStatus[] ships, bool practice) => + public static Record[] Setup(IEnumerable ships, bool practice) => (from s in ships select new Record {_status = (ShipStatus)s.Clone(), _practice = practice, StartHp = s.NowHp}).ToArray(); - public static Record[] Setup(int[] nowhps, ShipSpec[] ships, ItemSpec[][] slots, bool practice) + public static Record[] Setup(int[] nowhps, ShipSpec[] specs, ItemSpec[][] slots, bool practice) { return Enumerable.Range(0, nowhps.Length).Select(i => new Record @@ -570,10 +572,10 @@ namespace KancolleSniffer.Model StartHp = nowhps[i], _status = new ShipStatus { - Id = ships[i].Id, + Id = specs[i].Id, NowHp = nowhps[i], MaxHp = nowhps[i], - Spec = ships[i], + Spec = specs[i], Slot = slots[i].Select(spec => new ItemStatus {Id = spec.Id, Spec = spec}).ToArray(), SlotEx = new ItemStatus(0) }, diff --git a/KancolleSniffer/Model/Fleet.cs b/KancolleSniffer/Model/Fleet.cs index c4237cf..5236020 100644 --- a/KancolleSniffer/Model/Fleet.cs +++ b/KancolleSniffer/Model/Fleet.cs @@ -12,6 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +using System; +using System.Collections.Generic; using System.Linq; using static System.Math; @@ -67,25 +69,87 @@ namespace KancolleSniffer.Model public class Fleet { - private readonly ShipInfo _shipInfo; + private readonly ShipInventry _shipInventry; + private readonly Func _getHqLevel; + private int[] _deck = Enumerable.Repeat(-1, ShipInfo.MemberCount).ToArray(); public int Number { get; } public FleetState State { get; set; } public CombinedType CombinedType { get; set; } - public int[] Deck { get; set; } = Enumerable.Repeat(-1, ShipInfo.MemberCount).ToArray(); - public ShipStatus[] Ships => Deck.Where(id => id != -1).Select(_shipInfo.GetStatus).ToArray(); + public IReadOnlyList Ships { get; private set; } + public IReadOnlyList ActualShips { get; private set; } - public Fleet(ShipInfo shipInfo, int number) + public Fleet(ShipInventry shipInventry, int number, Func getHqLevel) { - _shipInfo = shipInfo; + _shipInventry = shipInventry; Number = number; + _getHqLevel = getHqLevel; + Ships = _deck.Select(id => new ShipStatus()).ToArray(); + ActualShips = new ShipStatus[0]; + } + + public IReadOnlyList Deck + { + get => _deck; + set + { + _deck = value.ToArray(); + SetDeck(); + } + } + + public void SetDeck() + { + foreach (var ship in Ships) + { + ship.Fleet = null; + ship.DeckIndex = -1; + } + Ships = _deck.Select((id, idx) => + { + var ship = _shipInventry[id]; + if (ship.Empty) + return ship; + ship.DeckIndex = id; + ship.Fleet = this; + return ship; + }).ToArray(); + ActualShips = Ships.Where(ship => !ship.Empty).ToArray(); + } + + public int SetShip(int index, int shipId) + { + var prev = _deck[index]; + _deck[index] = shipId; + SetDeck(); + return prev; + } + + public void WithdrowShip(int index) + { + if (index == -1) // 旗艦以外解除 + { + for (var i = 1; i < _deck.Length; i++) + _deck[i] = -1; + SetDeck(); + return; + } + var dst = index; + for (var src = index + 1; src < _deck.Length; src++) + { + if (_deck[src] != -1) + _deck[dst++] = _deck[src]; + } + for (; dst < _deck.Length; dst++) + _deck[dst] = -1; + SetDeck(); } public ChargeStatus ChargeStatus { get { - var fs = new ChargeStatus(_shipInfo.GetStatus(Deck[0])); - var others = (from id in Deck.Skip(1) select new ChargeStatus(_shipInfo.GetStatus(id))).Aggregate( + var fs = new ChargeStatus(Ships[0]); + var others = (from ship in Ships.Skip(1) select new ChargeStatus(ship)).Aggregate( (result, next) => new ChargeStatus(Max(result.Fuel, next.Fuel), Max(result.Bull, next.Bull))); return new ChargeStatus(fs.Fuel != 0 ? fs.Fuel : others.Fuel + 5, fs.Bull != 0 ? fs.Bull : others.Bull + 5); @@ -93,12 +157,12 @@ namespace KancolleSniffer.Model } public int[] FighterPower - => Ships.Where(ship => !ship.Escaped).SelectMany(ship => + => ActualShips.Where(ship => !ship.Escaped).SelectMany(ship => ship.Slot.Zip(ship.OnSlot, (slot, onslot) => slot.CalcFighterPower(onslot))) .Aggregate(new[] {0, 0}, (prev, cur) => new[] {prev[0] + cur[0], prev[1] + cur[1]}); public double ContactTriggerRate - => Ships.Where(ship => !ship.Escaped).SelectMany(ship => + => ActualShips.Where(ship => !ship.Escaped).SelectMany(ship => ship.Slot.Zip(ship.OnSlot, (slot, onslot) => slot.Spec.ContactTriggerRate * slot.Spec.LoS * Sqrt(onslot))).Sum(); @@ -106,7 +170,7 @@ namespace KancolleSniffer.Model { var result = 0.0; var emptyBonus = 6; - foreach (var s in Ships.Where(s => !s.Escaped)) + foreach (var s in ActualShips.Where(s => !s.Escaped)) { emptyBonus--; var itemLoS = 0; @@ -118,7 +182,7 @@ namespace KancolleSniffer.Model } result += Sqrt(s.LoS - itemLoS); } - return result > 0 ? result - Ceiling(_shipInfo.HqLevel * 0.4) + emptyBonus * 2 : 0.0; + return result > 0 ? result - Ceiling(_getHqLevel() * 0.4) + emptyBonus * 2 : 0.0; } public double DaihatsuBonus diff --git a/KancolleSniffer/Model/ShipInfo.cs b/KancolleSniffer/Model/ShipInfo.cs index 250e862..4780e78 100644 --- a/KancolleSniffer/Model/ShipInfo.cs +++ b/KancolleSniffer/Model/ShipInfo.cs @@ -12,7 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -using System; using System.Collections.Generic; using System.Linq; using KancolleSniffer.Util; @@ -24,15 +23,15 @@ namespace KancolleSniffer.Model public const int FleetCount = 4; public const int MemberCount = 6; - private readonly Fleet[] _fleets; + private readonly IReadOnlyList _fleets; private readonly ShipMaster _shipMaster; private readonly ShipInventry _shipInventry; private readonly ItemInventry _itemInventry; private readonly List _escapedShips = new List(); private ShipStatus[] _battleResult = new ShipStatus[0]; private readonly NumEquipsChecker _numEquipsChecker = new NumEquipsChecker(); + private int _hqLevel; public AlarmCounter Counter { get; } - public int HqLevel { get; private set; } public ShipStatusPair[] BattleResultDiff { get; private set; } = new ShipStatusPair[0]; public bool IsBattleResultError => BattleResultDiff.Length > 0; public ShipStatus[] BattleStartStatus { get; private set; } = new ShipStatus[0]; @@ -67,7 +66,7 @@ namespace KancolleSniffer.Model { _shipMaster = shipMaster; _shipInventry = shipInventry; - _fleets = Enumerable.Range(0, FleetCount).Select((x, i) => new Fleet(this, i)).ToArray(); + _fleets = Enumerable.Range(0, FleetCount).Select((x, i) => new Fleet(_shipInventry, i, () => _hqLevel)).ToArray(); _itemInventry = itemInventry; Counter = new AlarmCounter(() => _shipInventry.Count){Margin = 4}; } @@ -86,8 +85,7 @@ namespace KancolleSniffer.Model _escapedShips.Clear(); for (var i = 0; i < FleetCount; i++) _fleets[i].State = FleetState.Port; - InspectDeck(json.api_deck_port); - InspectShipData(json.api_ship); + InspectShipDataAndDeck(json.api_ship, json.api_deck_port); InspectBasic(json.api_basic); if (json.api_combined_flag()) _fleets[0].CombinedType = _fleets[1].CombinedType = (CombinedType)(int)json.api_combined_flag; @@ -95,13 +93,11 @@ namespace KancolleSniffer.Model } else if (json.api_data()) // ship2 { - InspectDeck(json.api_data_deck); - InspectShipData(json.api_data); + InspectShipDataAndDeck(json.api_data, json.api_data_deck); } else if (json.api_ship_data()) // ship3とship_deck { - InspectDeck(json.api_deck_data); - InspectShipData(json.api_ship_data); + InspectShipDataAndDeck(json.api_ship_data, json.api_deck_data); VerifyBattleResult(); // ship_deckでドロップ艦を反映する if (DropShipId != -1) @@ -112,7 +108,7 @@ namespace KancolleSniffer.Model _itemInventry.InflateCount(num); } } - else if (json.api_ship()) // getshipとpowerup + else if (json.api_ship()) // getship { InspectShipData(new[] {json.api_ship}); } @@ -122,14 +118,14 @@ namespace KancolleSniffer.Model public void SaveBattleResult() { _battleResult = _fleets.Where(fleet => - fleet.State >= FleetState.Sortie && !GetStatus(fleet.Deck[0]).Spec.IsRepairShip) - .SelectMany(fleet => fleet.Deck.Select(GetStatus)).ToArray(); + fleet.State >= FleetState.Sortie && !fleet.Ships[0].Spec.IsRepairShip) + .SelectMany(fleet => fleet.Ships).ToArray(); } private void VerifyBattleResult() { BattleResultDiff = (from assumed in _battleResult - let actual = GetStatus(assumed.Id) + let actual = GetShip(assumed.Id) where !assumed.Escaped && assumed.NowHp != actual.NowHp select new ShipStatusPair(assumed, actual)).ToArray(); _battleResult = new ShipStatus[0]; @@ -138,7 +134,13 @@ namespace KancolleSniffer.Model public void SaveBattleStartStatus() { BattleStartStatus = _fleets.Where(fleet => fleet.State >= FleetState.Sortie) - .SelectMany(fleet => fleet.Deck.Select(id => (ShipStatus)GetStatus(id).Clone())).ToArray(); + .SelectMany(fleet => fleet.Ships.Select(ship => (ShipStatus)ship.Clone())).ToArray(); + } + + private void InspectShipDataAndDeck(dynamic ship, dynamic deck) + { + InspectShipData(ship); + InspectDeck(deck); // FleetのDeckを設定した時点でShipStatusを取得するので必ずdeckが後 } public void InspectDeck(dynamic json) @@ -191,7 +193,7 @@ namespace KancolleSniffer.Model private void InspectBasic(dynamic json) { - HqLevel = (int)json.api_level; + _hqLevel = (int)json.api_level; Counter.Max = (int)json.api_max_chara; } @@ -209,37 +211,30 @@ namespace KancolleSniffer.Model public void InspectChange(string request) { var values = HttpUtility.ParseQueryString(request); - var fleet = _fleets[int.Parse(values["api_id"]) - 1]; - var idx = int.Parse(values["api_ship_idx"]); - var ship = int.Parse(values["api_ship_id"]); + var dstFleet = _fleets[int.Parse(values["api_id"]) - 1]; + var dstIdx = int.Parse(values["api_ship_idx"]); + var shipId = int.Parse(values["api_ship_id"]); - if (idx == -1) - { - var deck = fleet.Deck; - for (var i = 1; i < deck.Length; i++) - deck[i] = -1; - return; - } - if (ship == -1) + if (dstIdx == -1 || shipId == -1) // 解除 { - WithdrowShip(fleet, idx); + dstFleet.WithdrowShip(dstIdx); return; } - var of = FindFleet(ship, out var oi); - var orig = fleet.Deck[idx]; - fleet.Deck[idx] = ship; - if (of == null) + var srcFleet = FindFleet(shipId, out var srcIdx); + var prevShipId = dstFleet.SetShip(dstIdx, shipId); + if (srcFleet == null) return; // 入れ替えの場合 - if ((of.Deck[oi] = orig) == -1) - WithdrowShip(of, oi); + srcFleet.SetShip(srcIdx, prevShipId); + if (prevShipId == -1) + srcFleet.WithdrowShip(srcIdx); } private Fleet FindFleet(int ship, out int idx) { foreach (var fleet in _fleets) { - idx = Array.FindIndex(fleet.Deck, id => id == ship); + idx = fleet.Deck.ToList().IndexOf(ship); if (idx < 0) continue; return fleet; @@ -248,19 +243,6 @@ namespace KancolleSniffer.Model return null; } - private void WithdrowShip(Fleet fleet, int idx) - { - var deck = fleet.Deck; - var j = idx; - for (var i = idx + 1; i < deck.Length; i++) - { - if (deck[i] != -1) - deck[j++] = deck[i]; - } - for (; j < deck.Length; j++) - deck[j] = -1; - } - public void InspectPowerup(string request, dynamic json) { var values = HttpUtility.ParseQueryString(request); @@ -269,8 +251,7 @@ namespace KancolleSniffer.Model return; _itemInventry.Remove(ships.SelectMany(id => _shipInventry[id].Slot)); _shipInventry.Remove(ships); - InspectDeck(json.api_deck); - InspectShip(json); + InspectShipDataAndDeck(new[]{json.api_ship}, json.api_deck); } public void InspectSlotExchange(string request, dynamic json) @@ -283,20 +264,21 @@ namespace KancolleSniffer.Model public void InspectSlotDeprive(dynamic json) { InspectShipData(new[] {json.api_ship_data.api_set_ship, json.api_ship_data.api_unset_ship}); + foreach (var fleet in _fleets) + fleet.SetDeck(); // ShipStatusの差し替え } public void InspectDestroyShip(string request, dynamic json) { var values = HttpUtility.ParseQueryString(request); var delitem = int.Parse(values["api_slot_dest_flag"] ?? "0") == 1; - foreach (var id in values["api_ship_id"].Split(',').Select(int.Parse)) + foreach (var shipId in values["api_ship_id"].Split(',').Select(int.Parse)) { if (delitem) - _itemInventry.Remove(_shipInventry[id].AllSlot); - var of = FindFleet(id, out var oi); - if (of != null) - WithdrowShip(of, oi); - _shipInventry.Remove(id); + _itemInventry.Remove(_shipInventry[shipId].AllSlot); + var srcFleet = FindFleet(shipId, out var srcIdx); + srcFleet?.WithdrowShip(srcIdx); + _shipInventry.Remove(shipId); } } @@ -328,18 +310,9 @@ namespace KancolleSniffer.Model _fleets[fleet].State = FleetState.Practice; } - public Fleet[] Fleets => _fleets; + public IReadOnlyList Fleets => _fleets; - public ShipStatus GetStatus(int id) => FillUp(_shipInventry[id]); - - private ShipStatus FillUp(ShipStatus ship) - { - if (ship.Empty) - return ship; - ship.Fleet = FindFleet(ship.Id, out var idx); - ship.DeckIndex = idx; - return ship; - } + public ShipStatus GetShip(int id) => _shipInventry[id]; public void SetItemHolder() { @@ -353,7 +326,7 @@ namespace KancolleSniffer.Model public ShipSpec GetSpec(int id) => _shipMaster.GetSpec(id); - public ShipStatus[] ShipList => _shipInventry.AllShips.Select(FillUp).ToArray(); + public ShipStatus[] ShipList => _shipInventry.AllShips.ToArray(); public ShipStatus[] GetRepairList(DockInfo dockInfo) => (from s in ShipList @@ -367,7 +340,7 @@ namespace KancolleSniffer.Model { BadlyDamagedShips = (from s in _fleets.Where(fleet => fleet.State == FleetState.Sortie) - .SelectMany(fleet => fleet.Deck.Where(id => id != -1).Select(GetStatus)) + .SelectMany(fleet => fleet.ActualShips) where !s.Escaped && s.DamageLevel == ShipStatus.Damage.Badly && !(s.Fleet.CombinedType != 0 && s.Fleet.Number == 1 && s.DeckIndex == 0) // 第二艦隊の旗艦を除く select s.Name).ToArray(); diff --git a/KancolleSniffer/Model/ShipStatus.cs b/KancolleSniffer/Model/ShipStatus.cs index ba0bba4..edb983b 100644 --- a/KancolleSniffer/Model/ShipStatus.cs +++ b/KancolleSniffer/Model/ShipStatus.cs @@ -56,8 +56,8 @@ namespace KancolleSniffer.Model public IReadOnlyList Slot { - get => _slot.Select(item => GetItem(item)).ToList(); - set => _slot = value.ToList(); + get => _slot.Select(item => GetItem(item)).ToArray(); + set => _slot = value.ToArray(); } public ItemStatus SlotEx diff --git a/KancolleSniffer/Sniffer.cs b/KancolleSniffer/Sniffer.cs index 5fc84da..fda5fa9 100644 --- a/KancolleSniffer/Sniffer.cs +++ b/KancolleSniffer/Sniffer.cs @@ -600,7 +600,7 @@ namespace KancolleSniffer public AlarmCounter ShipCounter => _shipInfo.Counter; - public Fleet[] Fleets => _shipInfo.Fleets; + public IReadOnlyList Fleets => _shipInfo.Fleets; public ShipInfo.ShipStatusPair[] BattleResultStatusDiff => _shipInfo.BattleResultDiff; diff --git a/KancolleSniffer/TextGenerator.cs b/KancolleSniffer/TextGenerator.cs index 820959c..0f4a849 100644 --- a/KancolleSniffer/TextGenerator.cs +++ b/KancolleSniffer/TextGenerator.cs @@ -77,7 +77,7 @@ namespace KancolleSniffer var sb = new StringBuilder(); var fn = new[] {"第一艦隊", "第二艦隊", "第三艦隊", "第四艦隊"}; sb.Append(fn[fleet] + "\r\n"); - sb.Append(string.Concat(from s in target.Ships + sb.Append(string.Concat(from s in target.ActualShips select ($"{s.Name} Lv{s.Level} " + string.Join(",", from item in s.AllSlot @@ -146,8 +146,8 @@ namespace KancolleSniffer if (fleet.Number != 0) sb.Append(","); sb.Append($"\"f{fleet.Number + 1}\":{{"); - var ships = fleet.Ships; - for (var s = 0; s < ships.Length; s++) + var ships = fleet.ActualShips; + for (var s = 0; s < ships.Count; s++) { if (s != 0) sb.Append(","); diff --git a/KancolleSniffer/View/AntiAirPanel.cs b/KancolleSniffer/View/AntiAirPanel.cs index ca6278b..cd1ea0f 100644 --- a/KancolleSniffer/View/AntiAirPanel.cs +++ b/KancolleSniffer/View/AntiAirPanel.cs @@ -56,7 +56,7 @@ namespace KancolleSniffer.View var fn = new[] {"第一艦隊", "第二艦隊", "第三艦隊", "第四艦隊"}; foreach (var fleet in sniffer.Fleets) { - var ships = fleet.Ships; + var ships = fleet.ActualShips; var rawForFleet = ships.Sum(ship => ship.EffectiveAntiAirForFleet); var forFleet = new[] {1.0, 1.2, 1.6}.Select(r => (int)(rawForFleet * r) * 2 / 1.3).ToArray(); _table.Add(new Record diff --git a/KancolleSniffer/View/FleetPanel.cs b/KancolleSniffer/View/FleetPanel.cs index 484b6bf..931dd09 100644 --- a/KancolleSniffer/View/FleetPanel.cs +++ b/KancolleSniffer/View/FleetPanel.cs @@ -94,15 +94,15 @@ namespace KancolleSniffer.View foreach (var fleet in sniffer.Fleets) { var total = new Total(); - var ships = new List(); - foreach (var s in fleet.Ships) + var shipRecords = new List(); + foreach (var ship in fleet.ActualShips) { var equips = new List(); - for (var i = 0; i < s.Slot.Count; i++) + for (var i = 0; i < ship.Slot.Count; i++) { - var item = s.Slot[i]; - var onslot = s.OnSlot[i]; - var max = s.Spec.MaxEq[i]; + var item = ship.Slot[i]; + var onslot = ship.OnSlot[i]; + var max = ship.Spec.MaxEq[i]; if (item.Empty) continue; var airspec = ""; @@ -124,32 +124,32 @@ namespace KancolleSniffer.View Color = item.Spec.Color }); } - if (s.SlotEx.Id > 0) + if (ship.SlotEx.Id > 0) { - var item = s.SlotEx; + var item = ship.SlotEx; equips.Add(new Record {Equip = GenEquipString(item), Color = item.Spec.Color}); } - total.Add(s); - var fire = s.EffectiveFirepower; - var subm = s.EffectiveAntiSubmarine; - var torp = s.EffectiveTorpedo; - var night = s.NightBattlePower; - var oasa = s.CanOpeningAntiSubmarineAttack ? "*" : ""; - var ship = new Record + total.Add(ship); + var fire = ship.EffectiveFirepower; + var subm = ship.EffectiveAntiSubmarine; + var torp = ship.EffectiveTorpedo; + var night = ship.NightBattlePower; + var oasa = ship.CanOpeningAntiSubmarineAttack ? "*" : ""; + var record = new Record { - Ship = (s.Escaped ? "[避]" : "") + s.Name + " Lv" + s.Level, - Ship2 = $"燃{s.EffectiveFuelMax} 弾{s.EffectiveBullMax}", - Id = s.Id, + Ship = (ship.Escaped ? "[避]" : "") + ship.Name + " Lv" + ship.Level, + Ship2 = $"燃{ship.EffectiveFuelMax} 弾{ship.EffectiveBullMax}", + Id = ship.Id, Spec = HideIfZero("砲", fire) + HideIfZero(" 潜", subm) + oasa, Spec2 = (HideIfZero("雷", torp) + HideIfZero(" 夜", night)).TrimStart(' ') }; - if (ship.Spec == "") + if (record.Spec == "") { - ship.Spec = ship.Spec2; - ship.Spec2 = ""; + record.Spec = record.Spec2; + record.Spec2 = ""; } - ships.Add(ship); - ships.AddRange(equips); + shipRecords.Add(record); + shipRecords.AddRange(equips); } var daihatsu = fleet.DaihatsuBonus; var tp = fleet.TransportPoint; @@ -170,7 +170,7 @@ namespace KancolleSniffer.View ? "" : $"\r\nTP:S{(int)tp} A{(int)(tp * 0.7)}") }); - list.AddRange(ships); + list.AddRange(shipRecords); } if (sniffer.BaseAirCorps != null) { diff --git a/KancolleSniffer/View/MainFormLabels.cs b/KancolleSniffer/View/MainFormLabels.cs index 10f3533..1caee95 100644 --- a/KancolleSniffer/View/MainFormLabels.cs +++ b/KancolleSniffer/View/MainFormLabels.cs @@ -144,22 +144,22 @@ namespace KancolleSniffer.View label.ToggleHpPercent(); } - public void SetShipLabels(ShipStatus[] statuses) + public void SetShipLabels(IReadOnlyList ships) { - SetShipLabels(statuses, statuses.Length == 7 ? _shipLabels7 : _shiplabels); + SetShipLabels(ships, ships.Count == 7 ? _shipLabels7 : _shiplabels); } - public void SetShipLabels(ShipStatus[] statuses, ShipLabel[][] shipLabels) + public void SetShipLabels(IReadOnlyList ships, ShipLabel[][] shipLabels) { for (var i = 0; i < shipLabels.Length; i++) { var labels = shipLabels[i]; - var s = i < statuses.Length ? statuses[i] : null; - labels[0].SetHp(s); - labels[1].SetCond(s); - labels[2].SetLevel(s); - labels[3].SetExpToNext(s); - labels[4].SetName(s, ShipNameWidth.MainPanel); + var ship = i < ships.Count ? ships[i] : null; + labels[0].SetHp(ship); + labels[1].SetCond(ship); + labels[2].SetLevel(ship); + labels[3].SetExpToNext(ship); + labels[4].SetName(ship, ShipNameWidth.MainPanel); } } @@ -223,14 +223,14 @@ namespace KancolleSniffer.View parent.ResumeLayout(); } - public void SetCombinedShipLabels(ShipStatus[] first, ShipStatus[] second) + public void SetCombinedShipLabels(IReadOnlyList first, IReadOnlyList second) { for (var i = 0; i < _combinedLabels.Length; i++) { var idx = i % ShipInfo.MemberCount; - var statuses = i < ShipInfo.MemberCount ? first : second; + var ships = i < ShipInfo.MemberCount ? first : second; var labels = _combinedLabels[i]; - var s = idx < statuses.Length ? statuses[idx] : null; + var s = idx < ships.Count ? ships[idx] : null; labels[0].SetHp(s); labels[1].SetCond(s); labels[2].SetName(s, ShipNameWidth.Combined); @@ -290,19 +290,19 @@ namespace KancolleSniffer.View } } - public void SetAkashiTimer(ShipStatus[] statuses, AkashiTimer.RepairSpan[] timers) + public void SetAkashiTimer(IReadOnlyList ships, AkashiTimer.RepairSpan[] timers) { - if (statuses.Length == 7) + if (ships.Count == 7) { - SetAkashiTimer(statuses, timers, _akashiTimers7, _shipLabels7); + SetAkashiTimer(ships, timers, _akashiTimers7, _shipLabels7); } else { - SetAkashiTimer(statuses, timers, _akashiTimers, _shiplabels); + SetAkashiTimer(ships, timers, _akashiTimers, _shiplabels); } } - public void SetAkashiTimer(ShipStatus[] statuses, AkashiTimer.RepairSpan[] timers, ShipLabel[] timerLabels, + public void SetAkashiTimer(IReadOnlyList ships, AkashiTimer.RepairSpan[] timers, ShipLabel[] timerLabels, ShipLabel[][] shipLabels) { var shortest = -1; @@ -325,7 +325,7 @@ namespace KancolleSniffer.View continue; } var timer = timers[i]; - var stat = statuses[i]; + var stat = ships[i]; label.Visible = true; label.Text = timer.Span.ToString(@"mm\:ss"); label.ForeColor = Control.DefaultForeColor; diff --git a/KancolleSniffer/View/MiscTextInfo.cs b/KancolleSniffer/View/MiscTextInfo.cs index c7e8a07..a0f2b1b 100644 --- a/KancolleSniffer/View/MiscTextInfo.cs +++ b/KancolleSniffer/View/MiscTextInfo.cs @@ -114,11 +114,11 @@ namespace KancolleSniffer.View var raw = _expTable[Min(s1, _expTable.Length) - 1] / 100.0 + _expTable[Min(s2, _expTable.Length) - 1] / 300.0; var exp = raw >= 500 ? 500 + (int)Sqrt(raw - 500) : (int)raw; - var bonus = 1 + TrainingCruiserBonus(_shipInfo.Fleets[0].Ships); + var bonus = 1 + TrainingCruiserBonus(_shipInfo.Fleets[0].ActualShips); Text += $"獲得経験値 : {(int)(exp * bonus)}\r\nS勝利 : {(int)((int)(exp * 1.2) * bonus)}"; } - private double TrainingCruiserBonus(ShipStatus[] fleet) + private double TrainingCruiserBonus(IReadOnlyList fleet) { if (fleet[0].Spec.IsTrainingCruiser) { -- 2.11.0