1
0
mirror of https://github.com/ppy/osu.git synced 2024-12-14 20:22:55 +08:00

Merge pull request #12665 from frenzibyte/stable-frame-sort

This commit is contained in:
Dean Herbert 2021-05-05 14:35:25 +09:00 committed by GitHub
commit 62fa638515
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 54 additions and 2 deletions

View File

@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using NUnit.Framework;
using osu.Game.Replays;
using osu.Game.Rulesets.Replays;
@ -278,6 +279,54 @@ namespace osu.Game.Tests.NonVisual
setTime(-100, -100);
}
[Test]
public void TestReplayFramesSortStability()
{
const double repeating_time = 5000;
// add a collection of frames in shuffled order time-wise; each frame also stores its original index to check stability later.
// data is hand-picked and breaks if the unstable List<T>.Sort() is used.
// in theory this can still return a false-positive with another unstable algorithm if extremely unlucky,
// but there is no conceivable fool-proof way to prevent that anyways.
replay.Frames.AddRange(new[]
{
repeating_time,
0,
3000,
repeating_time,
repeating_time,
6000,
9000,
repeating_time,
repeating_time,
1000,
11000,
21000,
4000,
repeating_time,
repeating_time,
8000,
2000,
7000,
repeating_time,
repeating_time,
10000
}.Select((time, index) => new TestReplayFrame(time, true, index)));
replay.HasReceivedAllFrames = true;
// create a new handler with the replay for the sort to be performed.
handler = new TestInputHandler(replay);
// ensure sort stability by checking that the frames with time == repeating_time are sorted in ascending frame index order themselves.
var repeatingTimeFramesData = replay.Frames
.Cast<TestReplayFrame>()
.Where(f => f.Time == repeating_time)
.Select(f => f.FrameIndex);
Assert.That(repeatingTimeFramesData, Is.Ordered.Ascending);
}
private void setReplayFrames()
{
replay.Frames = new List<ReplayFrame>
@ -324,11 +373,13 @@ namespace osu.Game.Tests.NonVisual
private class TestReplayFrame : ReplayFrame
{
public readonly bool IsImportant;
public readonly int FrameIndex;
public TestReplayFrame(double time, bool isImportant = false)
public TestReplayFrame(double time, bool isImportant = false, int frameIndex = 0)
: base(time)
{
IsImportant = isImportant;
FrameIndex = frameIndex;
}
}

View File

@ -5,6 +5,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using JetBrains.Annotations;
using osu.Game.Input.Handlers;
using osu.Game.Replays;
@ -97,7 +98,7 @@ namespace osu.Game.Rulesets.Replays
{
// TODO: This replay frame ordering should be enforced on the Replay type.
// Currently, the ordering can be broken if the frames are added after this construction.
replay.Frames.Sort((x, y) => x.Time.CompareTo(y.Time));
replay.Frames = replay.Frames.OrderBy(f => f.Time).ToList();
this.replay = replay;
currentFrameIndex = -1;