155 lines
5.4 KiB
C#
155 lines
5.4 KiB
C#
using AnotherReplayReader.ReplayFile;
|
||
using System;
|
||
using System.Collections.Generic;
|
||
using System.Linq;
|
||
|
||
namespace AnotherReplayReader.Apm
|
||
{
|
||
internal class DataRow
|
||
{
|
||
public const string AverageApmRow = "APM(整局游戏)";
|
||
public const string PartialApmRow = "APM(当前时间段)";
|
||
|
||
public string Name { get; }
|
||
public bool IsDisabled { get; }
|
||
public DataValue Player1Value => _values[0];
|
||
public DataValue Player2Value => _values[1];
|
||
public DataValue Player3Value => _values[2];
|
||
public DataValue Player4Value => _values[3];
|
||
public DataValue Player5Value => _values[4];
|
||
public DataValue Player6Value => _values[5];
|
||
|
||
private readonly IReadOnlyList<DataValue> _values;
|
||
|
||
public DataRow(string name,
|
||
IEnumerable<string> values,
|
||
bool isDisabled = false)
|
||
{
|
||
Name = name;
|
||
IsDisabled = isDisabled;
|
||
|
||
if (values.Count() < 6)
|
||
{
|
||
values = values.Concat(new string[6 - values.Count()]);
|
||
}
|
||
_values = values.Select(x => new DataValue(x)).ToArray();
|
||
}
|
||
|
||
public static List<DataRow> GetList(ApmPlotter plotter,
|
||
ApmPlotterFilterOptions options,
|
||
PlayerIdentity identity,
|
||
TimeSpan begin,
|
||
TimeSpan end,
|
||
out int apmRowIndex)
|
||
{
|
||
// these commands should appear in this order by default
|
||
var orderedCommands = new List<byte>();
|
||
orderedCommands.AddRange(RA3Commands.UnknownCommands);
|
||
orderedCommands.AddRange(RA3Commands.AutoCommands);
|
||
orderedCommands.AddRange(new byte[]
|
||
{
|
||
0xF5,
|
||
0xF8,
|
||
0x2A,
|
||
0xFA,
|
||
0xFB,
|
||
0x07,
|
||
0x08,
|
||
0x05,
|
||
0x06,
|
||
0x09,
|
||
0x00,
|
||
0x0A,
|
||
0x03,
|
||
0x04,
|
||
0x28,
|
||
0x29,
|
||
0x0D,
|
||
0x0E,
|
||
0x15,
|
||
0x14,
|
||
0x36,
|
||
0x16,
|
||
0x2C,
|
||
0x1A,
|
||
0x4E,
|
||
0xFE,
|
||
0xFF,
|
||
0x32,
|
||
0x2E,
|
||
0x2F,
|
||
0x4B,
|
||
0x4C,
|
||
0x02,
|
||
0x0C,
|
||
0x10,
|
||
});
|
||
|
||
var dataList = new List<DataRow>
|
||
{
|
||
new("ID", plotter.Players.Select(x => x.PlayerName))
|
||
};
|
||
var isPartial = begin > TimeSpan.Zero || end <= plotter.ReplayLength;
|
||
if (isPartial)
|
||
{
|
||
string GetStatus(Player player, int i)
|
||
{
|
||
if (player.IsComputer)
|
||
{
|
||
return "这是 AI";
|
||
}
|
||
if (begin < plotter.StricterPlayerLifes[i])
|
||
{
|
||
return "存活";
|
||
}
|
||
return begin < plotter.PlayerLifes[i]
|
||
? "变身天眼帝国,或双手离开键盘"
|
||
: "可能已离开房间";
|
||
}
|
||
dataList.Add(new("存活状态(推测)", plotter.Players.Select(GetStatus)));
|
||
}
|
||
if (plotter.Replay.Type is ReplayType.Lan && identity.IsUsable)
|
||
{
|
||
string GetIpAndName(Player player) => player.IsComputer
|
||
? "这是 AI"
|
||
: identity.QueryRealNameAndIP(player.PlayerIp) ?? string.Empty;
|
||
dataList.Add(new("局域网 IP", plotter.Players.Select(GetIpAndName)));
|
||
}
|
||
apmRowIndex = dataList.Count;
|
||
// kill-death ratio
|
||
if (plotter.Replay.Footer?.TryGetKillDeathRatios() is { } kdRatios)
|
||
{
|
||
var texts = kdRatios
|
||
.Take(plotter.Players.Length)
|
||
.Select(x => $"{x:0.##}");
|
||
dataList.Add(new("击杀阵亡比(存疑)", texts));
|
||
}
|
||
// get commands
|
||
var commandCounts = plotter.GetCommandCounts(begin, end);
|
||
// add commands in the order specified by the list
|
||
foreach (var command in orderedCommands)
|
||
{
|
||
var counts = commandCounts.TryGetValue(command, out var stored)
|
||
? stored
|
||
: new int[plotter.Players.Length];
|
||
if (!isPartial || counts.Any(x => x > 0))
|
||
{
|
||
dataList.Add(new(RA3Commands.GetCommandName(command),
|
||
counts.Select(x => $"{x}"),
|
||
options.ShouldSkip(command)));
|
||
}
|
||
commandCounts.Remove(command);
|
||
}
|
||
// add other commands
|
||
foreach (var commandCount in commandCounts)
|
||
{
|
||
dataList.Add(new(RA3Commands.GetCommandName(commandCount.Key),
|
||
commandCount.Value.Select(x => $"{x}"),
|
||
options.ShouldSkip(commandCount.Key)));
|
||
}
|
||
|
||
return dataList;
|
||
}
|
||
}
|
||
}
|