Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using ElectronicObserver.Core.Types;
using ElectronicObserver.Database.Sortie;
Expand Down Expand Up @@ -31,44 +32,12 @@ public static class ReplayExtensions
Fleetnum = sortie.FleetData.FleetId,
World = sortie.World,
Mapnum = sortie.Map,
Fleet1 = sortie.FleetData.Fleets.Skip(0).FirstOrDefault()?.Ships
.Select(s => new ReplayShip
{
ShipId = s.Id,
Level = s.Level,
Morale = s.Condition,
Kyouka = s.Kyouka,
Equip = s.EquipmentSlots.Append(s.ExpansionSlot).Select(e => ((int?)e?.Equipment?.Id) ?? 0).ToList(),
}).ToList() ?? new(),
Fleet2 = sortie.FleetData.Fleets.Skip(1).FirstOrDefault()?.Ships
.Select(s => new ReplayShip
{
ShipId = s.Id,
Level = s.Level,
Morale = s.Condition,
Kyouka = s.Kyouka,
Equip = s.EquipmentSlots.Append(s.ExpansionSlot).Select(e => ((int?)e?.Equipment?.Id) ?? 0).ToList(),
}).ToList() ?? new(),
Fleet3 = sortie.FleetData.Fleets.Skip(2).FirstOrDefault()?.Ships
.Select(s => new ReplayShip
{
ShipId = s.Id,
Level = s.Level,
Morale = s.Condition,
Kyouka = s.Kyouka,
Equip = s.EquipmentSlots.Append(s.ExpansionSlot).Select(e => ((int?)e?.Equipment?.Id) ?? 0).ToList(),
}).ToList() ?? new(),
Fleet4 = sortie.FleetData.Fleets.Skip(3).FirstOrDefault()?.Ships
.Select(s => new ReplayShip
{
ShipId = s.Id,
Level = s.Level,
Morale = s.Condition,
Kyouka = s.Kyouka,
Equip = s.EquipmentSlots.Append(s.ExpansionSlot).Select(e => ((int?)e?.Equipment?.Id) ?? 0).ToList(),
}).ToList() ?? new(),
Fleet1 = sortie.FleetData.Fleets.Skip(0).FirstOrDefault().ToReplayFleet(),
Fleet2 = sortie.FleetData.Fleets.Skip(1).FirstOrDefault().ToReplayFleet(),
Fleet3 = sortie.FleetData.Fleets.Skip(2).FirstOrDefault().ToReplayFleet(),
Fleet4 = sortie.FleetData.Fleets.Skip(3).FirstOrDefault().ToReplayFleet(),
AirBases = sortie.FleetData.AirBases
.Where(b => b.MapAreaId == sortie.Map)
.Where(b => b.MapAreaId == sortie.World)
.Select(b => new ReplayAirBase
{
Rid = b.AirCorpsId,
Expand All @@ -95,4 +64,24 @@ public static class ReplayExtensions
}).ToList(),
Battles = new(),
};

private static List<ReplayShip> ToReplayFleet(this SortieFleet? fleet)
=> fleet?.Ships.Select(ToReplayShip).ToList() ?? new();

private static ReplayShip ToReplayShip(SortieShip ship)
{
List<SortieEquipmentSlot?> slots = [.. ship.EquipmentSlots, ship.ExpansionSlot];

return new()
{
ShipId = ship.Id,
Level = ship.Level,
Morale = ship.Condition,
Kyouka = ship.Kyouka,
// equip, stars and ace have to stay index aligned
Equip = slots.Select(s => (int)(s?.Equipment?.Id ?? EquipmentId.Unknown)).ToList(),
Stars = slots.Select(s => s?.Equipment?.Level ?? 0).ToList(),
Ace = slots.Select(s => s?.Equipment?.AircraftLevel ?? 0).ToList(),
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,16 @@ public class ReplayShip

[JsonPropertyName("equip")]
public List<int> Equip { get; set; }

/// <summary>
/// Equipment improvement levels, same order as <see cref="Equip"/>.
/// </summary>
[JsonPropertyName("stars")]
public List<int> Stars { get; set; } = new();

/// <summary>
/// Equipment proficiency levels, same order as <see cref="Equip"/>.
/// </summary>
[JsonPropertyName("ace")]
public List<int> Ace { get; set; } = new();
}
91 changes: 91 additions & 0 deletions ElectronicObserverCoreTests/Replay/ReplayExportTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text.Json;
using System.Threading.Tasks;
using ElectronicObserver.Database.Sortie;
using ElectronicObserver.Window.Tools.SortieRecordViewer.Replay;
using Xunit;

namespace ElectronicObserverCoreTests.Replay;

public class ReplayExportTests
{
private static string DirectoryName => Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)!;
private static string RelativePath => "SortieDetail";
private static string BasePath => Path.Join(DirectoryName, RelativePath);

private static async Task<List<SortieRecord>> GetSortieRecords(string fileName)
{
await using Stream stream = File.OpenRead(Path.Join(BasePath, fileName));
List<SortieRecord>? data = await JsonSerializer.DeserializeAsync<List<SortieRecord>>(stream);

Assert.NotNull(data);
Assert.NotEmpty(data);

return data;
}

[Theory]
[InlineData("SortieDetailTest1.json")]
[InlineData("SortieDetailTest2.json")]
[InlineData("SortieDetailTest4.json")]
public async Task EquipmentImprovementIsExported(string fileName)
{
SortieRecord sortie = (await GetSortieRecords(fileName)).First();

ReplayData replay = sortie.ToReplayData();

List<ReplayShip> ships = new[] { replay.Fleet1, replay.Fleet2, replay.Fleet3, replay.Fleet4 }
.SelectMany(f => f ?? new())
.ToList();

Assert.NotEmpty(ships);

foreach (ReplayShip ship in ships)
{
Assert.Equal(ship.Equip.Count, ship.Stars.Count);
Assert.Equal(ship.Equip.Count, ship.Ace.Count);
}

Assert.Contains(ships, s => s.Stars.Any(v => v > 0));
}

[Fact]
public async Task ImprovementMatchesTheSourceRecord()
{
SortieRecord sortie = (await GetSortieRecords("SortieDetailTest2.json")).First();

ReplayData replay = sortie.ToReplayData();

List<ReplayShip> replayShips = replay.Fleet1!;
List<SortieShip> sourceShips = sortie.FleetData.Fleets[0]!.Ships;

Assert.Equal(sourceShips.Count, replayShips.Count);

foreach ((SortieShip source, ReplayShip exported) in sourceShips.Zip(replayShips))
{
List<SortieEquipmentSlot?> slots = [.. source.EquipmentSlots, source.ExpansionSlot];

Assert.Equal(slots.Select(s => (int)(s?.Equipment?.Id ?? 0)), exported.Equip);
Assert.Equal(slots.Select(s => s?.Equipment?.Level ?? 0), exported.Stars);
Assert.Equal(slots.Select(s => s?.Equipment?.AircraftLevel ?? 0), exported.Ace);
}
}

[Fact]
public async Task AirBasesAreExportedWhenWorldDiffersFromMap()
{
// world 58, map 4 - the filter used to compare MapAreaId against the map number
SortieRecord sortie = (await GetSortieRecords("SortieDetailTest1.json")).First();

Assert.NotEqual(sortie.World, sortie.Map);
Assert.NotEmpty(sortie.FleetData.AirBases);

ReplayData replay = sortie.ToReplayData();

Assert.NotNull(replay.AirBases);
Assert.Equal(sortie.FleetData.AirBases.Count, replay.AirBases!.Count);
}
}
Loading