48 lines
2.2 KiB
C#
48 lines
2.2 KiB
C#
using System.Diagnostics;
|
|
using ProjectQuint.Core.Judgement;
|
|
|
|
namespace ProjectQuint.Probes;
|
|
|
|
public readonly record struct JudgementSnapshot(int Score, int Combo, int MaxCombo,
|
|
int MissCount, int KoolCount, int CoolCount, int GoodCount, int JudgedUnits, bool Finished);
|
|
|
|
public sealed record ReplayObservation(JudgementSnapshot Judgement, double SetupMilliseconds,
|
|
double ReplayMilliseconds, long SetupAllocatedBytes, long ReplayAllocatedBytes);
|
|
|
|
public static class ReplayRunner
|
|
{
|
|
public static ReplayObservation Run(SyntheticWorkload workload, int frameRate)
|
|
{
|
|
if (frameRate < 1 || frameRate > 10_000)
|
|
throw new ArgumentOutOfRangeException(nameof(frameRate), "Use a frame rate from 1 to 10000.");
|
|
var allocationStart = GC.GetAllocatedBytesForCurrentThread();
|
|
var setupStart = Stopwatch.GetTimestamp();
|
|
var engine = new RhythmJudgementEngine(workload.Notes, laneCount: 4);
|
|
var setupEnd = Stopwatch.GetTimestamp();
|
|
var replayAllocationStart = GC.GetAllocatedBytesForCurrentThread();
|
|
|
|
long frame = 0;
|
|
foreach (var input in workload.Events)
|
|
{
|
|
// Merge two timestamped streams; no sleeps or real-time waiting affect this trace.
|
|
while ((double)frame / frameRate <= input.Time)
|
|
engine.Update((double)frame++ / frameRate);
|
|
if (input.Pressed)
|
|
engine.Press(input.Lane, input.Time);
|
|
else
|
|
engine.Release(input.Lane, input.Time);
|
|
}
|
|
engine.Update(workload.Notes[^1].EndTime + 1);
|
|
var replayEnd = Stopwatch.GetTimestamp();
|
|
var allocationEnd = GC.GetAllocatedBytesForCurrentThread();
|
|
return new ReplayObservation(new JudgementSnapshot(engine.Score, engine.Combo, engine.MaxCombo,
|
|
engine.MissCount, engine.KoolCount, engine.CoolCount, engine.GoodCount,
|
|
engine.JudgedNoteCount, engine.IsFinished),
|
|
Milliseconds(setupStart, setupEnd), Milliseconds(setupEnd, replayEnd),
|
|
replayAllocationStart - allocationStart, allocationEnd - replayAllocationStart);
|
|
}
|
|
|
|
private static double Milliseconds(long start, long end) =>
|
|
(end - start) * 1000.0 / Stopwatch.Frequency;
|
|
}
|