mirror of
https://github.com/ppy/osu.git
synced 2026-05-21 23:51:01 +08:00
Merge pull request #33259 from LumpBloom7/ruleset-agnostic-concurrent-check
Make concurrent object check ruleset specific
This commit is contained in:
@@ -5,6 +5,7 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Game.Rulesets.Catch.Edit.Checks;
|
||||
using osu.Game.Rulesets.Edit;
|
||||
using osu.Game.Rulesets.Edit.Checks;
|
||||
using osu.Game.Rulesets.Edit.Checks.Components;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.Edit
|
||||
@@ -13,7 +14,11 @@ namespace osu.Game.Rulesets.Catch.Edit
|
||||
{
|
||||
private readonly List<ICheck> checks = new List<ICheck>
|
||||
{
|
||||
// Compose
|
||||
new CheckBananaShowerGap(),
|
||||
new CheckConcurrentObjects(),
|
||||
|
||||
// Settings
|
||||
new CheckCatchAbnormalDifficultySettings(),
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Edit;
|
||||
using osu.Game.Rulesets.Edit.Checks;
|
||||
using osu.Game.Rulesets.Mania.Edit.Checks;
|
||||
using osu.Game.Rulesets.Mania.Objects;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Tests.Beatmaps;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Tests.Editor.Checks
|
||||
{
|
||||
[TestFixture]
|
||||
public class CheckManiaConcurrentObjectsTest
|
||||
{
|
||||
private CheckConcurrentObjects check = null!;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
check = new CheckManiaConcurrentObjects();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestHoldNotesSeparateOnSameColumn()
|
||||
{
|
||||
assertOk(new List<HitObject>
|
||||
{
|
||||
createHoldNote(startTime: 100, endTime: 400.75d, column: 1),
|
||||
createHoldNote(startTime: 500, endTime: 900.75d, column: 1)
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestHoldNotesConcurrentOnDifferentColumns()
|
||||
{
|
||||
assertOk(new List<HitObject>
|
||||
{
|
||||
createHoldNote(startTime: 100, endTime: 400.75d, column: 1),
|
||||
createHoldNote(startTime: 300, endTime: 700.75d, column: 2)
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestHoldNotesConcurrentOnSameColumn()
|
||||
{
|
||||
assertConcurrentSame(new List<HitObject>
|
||||
{
|
||||
createHoldNote(startTime: 100, endTime: 400.75d, column: 1),
|
||||
createHoldNote(startTime: 300, endTime: 700.75d, column: 1)
|
||||
});
|
||||
}
|
||||
|
||||
private void assertOk(List<HitObject> hitobjects)
|
||||
{
|
||||
Assert.That(check.Run(getContext(hitobjects)), Is.Empty);
|
||||
}
|
||||
|
||||
private void assertConcurrentSame(List<HitObject> hitobjects, int count = 1)
|
||||
{
|
||||
var issues = check.Run(getContext(hitobjects)).ToList();
|
||||
|
||||
Assert.That(issues, Has.Count.EqualTo(count));
|
||||
Assert.That(issues.All(issue => issue.Template is CheckConcurrentObjects.IssueTemplateConcurrentSame));
|
||||
}
|
||||
|
||||
private BeatmapVerifierContext getContext(List<HitObject> hitobjects)
|
||||
{
|
||||
var beatmap = new Beatmap<HitObject> { HitObjects = hitobjects };
|
||||
return new BeatmapVerifierContext(beatmap, new TestWorkingBeatmap(beatmap));
|
||||
}
|
||||
|
||||
private HoldNote createHoldNote(double startTime, double endTime, int column)
|
||||
{
|
||||
return new HoldNote
|
||||
{
|
||||
StartTime = startTime,
|
||||
EndTime = endTime,
|
||||
Column = column
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using osu.Game.Rulesets.Edit;
|
||||
using osu.Game.Rulesets.Edit.Checks;
|
||||
using osu.Game.Rulesets.Edit.Checks.Components;
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Edit.Checks
|
||||
{
|
||||
public class CheckManiaConcurrentObjects : CheckConcurrentObjects
|
||||
{
|
||||
public override IEnumerable<Issue> Run(BeatmapVerifierContext context)
|
||||
{
|
||||
var hitObjects = context.Beatmap.HitObjects;
|
||||
|
||||
for (int i = 0; i < hitObjects.Count - 1; ++i)
|
||||
{
|
||||
var hitobject = hitObjects[i];
|
||||
|
||||
for (int j = i + 1; j < hitObjects.Count; ++j)
|
||||
{
|
||||
var nextHitobject = hitObjects[j];
|
||||
|
||||
// Mania hitobjects are only considered concurrent if they also share the same column.
|
||||
if ((hitobject as IHasColumn)?.Column != (nextHitobject as IHasColumn)?.Column)
|
||||
continue;
|
||||
|
||||
// Two hitobjects cannot be concurrent without also being concurrent with all objects in between.
|
||||
// So if the next object is not concurrent, then we know no future objects will be either.
|
||||
if (!AreConcurrent(hitobject, nextHitobject))
|
||||
break;
|
||||
|
||||
if (hitobject.GetType() == nextHitobject.GetType())
|
||||
yield return new IssueTemplateConcurrentSame(this).Create(hitobject, nextHitobject);
|
||||
else
|
||||
yield return new IssueTemplateConcurrentDifferent(this).Create(hitobject, nextHitobject);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,9 @@ namespace osu.Game.Rulesets.Mania.Edit
|
||||
{
|
||||
private readonly List<ICheck> checks = new List<ICheck>
|
||||
{
|
||||
// Compose
|
||||
new CheckManiaConcurrentObjects(),
|
||||
|
||||
// Settings
|
||||
new CheckKeyCount(),
|
||||
new CheckManiaAbnormalDifficultySettings(),
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Game.Rulesets.Edit;
|
||||
using osu.Game.Rulesets.Edit.Checks;
|
||||
using osu.Game.Rulesets.Edit.Checks.Components;
|
||||
using osu.Game.Rulesets.Osu.Edit.Checks;
|
||||
|
||||
@@ -16,6 +17,7 @@ namespace osu.Game.Rulesets.Osu.Edit
|
||||
// Compose
|
||||
new CheckOffscreenObjects(),
|
||||
new CheckTooShortSpinners(),
|
||||
new CheckConcurrentObjects(),
|
||||
|
||||
// Spread
|
||||
new CheckTimeDistanceEquality(),
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Game.Rulesets.Edit;
|
||||
using osu.Game.Rulesets.Edit.Checks;
|
||||
using osu.Game.Rulesets.Edit.Checks.Components;
|
||||
using osu.Game.Rulesets.Taiko.Edit.Checks;
|
||||
|
||||
@@ -13,6 +14,10 @@ namespace osu.Game.Rulesets.Taiko.Edit
|
||||
{
|
||||
private readonly List<ICheck> checks = new List<ICheck>
|
||||
{
|
||||
// Compose
|
||||
new CheckConcurrentObjects(),
|
||||
|
||||
// Settings
|
||||
new CheckTaikoAbnormalDifficultySettings(),
|
||||
};
|
||||
|
||||
|
||||
@@ -114,36 +114,6 @@ namespace osu.Game.Tests.Editing.Checks
|
||||
Assert.That(issues.Any(issue => issue.Template is CheckConcurrentObjects.IssueTemplateConcurrentSame));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestHoldNotesSeparateOnSameColumn()
|
||||
{
|
||||
assertOk(new List<HitObject>
|
||||
{
|
||||
getHoldNoteMock(startTime: 100, endTime: 400.75d, column: 1).Object,
|
||||
getHoldNoteMock(startTime: 500, endTime: 900.75d, column: 1).Object
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestHoldNotesConcurrentOnDifferentColumns()
|
||||
{
|
||||
assertOk(new List<HitObject>
|
||||
{
|
||||
getHoldNoteMock(startTime: 100, endTime: 400.75d, column: 1).Object,
|
||||
getHoldNoteMock(startTime: 300, endTime: 700.75d, column: 2).Object
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestHoldNotesConcurrentOnSameColumn()
|
||||
{
|
||||
assertConcurrentSame(new List<HitObject>
|
||||
{
|
||||
getHoldNoteMock(startTime: 100, endTime: 400.75d, column: 1).Object,
|
||||
getHoldNoteMock(startTime: 300, endTime: 700.75d, column: 1).Object
|
||||
});
|
||||
}
|
||||
|
||||
private Mock<Slider> getSliderMock(double startTime, double endTime, int repeats = 0)
|
||||
{
|
||||
var mock = new Mock<Slider>();
|
||||
|
||||
@@ -36,7 +36,6 @@ namespace osu.Game.Rulesets.Edit
|
||||
|
||||
// Compose
|
||||
new CheckUnsnappedObjects(),
|
||||
new CheckConcurrentObjects(),
|
||||
new CheckZeroLengthObjects(),
|
||||
new CheckDrainLength(),
|
||||
new CheckUnusedAudioAtEnd(),
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
using System.Collections.Generic;
|
||||
using osu.Game.Rulesets.Edit.Checks.Components;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
|
||||
namespace osu.Game.Rulesets.Edit.Checks
|
||||
{
|
||||
@@ -21,7 +20,7 @@ namespace osu.Game.Rulesets.Edit.Checks
|
||||
new IssueTemplateConcurrentDifferent(this)
|
||||
};
|
||||
|
||||
public IEnumerable<Issue> Run(BeatmapVerifierContext context)
|
||||
public virtual IEnumerable<Issue> Run(BeatmapVerifierContext context)
|
||||
{
|
||||
var hitObjects = context.Beatmap.HitObjects;
|
||||
|
||||
@@ -33,14 +32,9 @@ namespace osu.Game.Rulesets.Edit.Checks
|
||||
{
|
||||
var nextHitobject = hitObjects[j];
|
||||
|
||||
// Accounts for rulesets with hitobjects separated by columns, such as Mania.
|
||||
// In these cases we only care about concurrent objects within the same column.
|
||||
if ((hitobject as IHasColumn)?.Column != (nextHitobject as IHasColumn)?.Column)
|
||||
continue;
|
||||
|
||||
// Two hitobjects cannot be concurrent without also being concurrent with all objects in between.
|
||||
// So if the next object is not concurrent, then we know no future objects will be either.
|
||||
if (!areConcurrent(hitobject, nextHitobject))
|
||||
if (!AreConcurrent(hitobject, nextHitobject))
|
||||
break;
|
||||
|
||||
if (hitobject.GetType() == nextHitobject.GetType())
|
||||
@@ -51,7 +45,7 @@ namespace osu.Game.Rulesets.Edit.Checks
|
||||
}
|
||||
}
|
||||
|
||||
private bool areConcurrent(HitObject hitobject, HitObject nextHitobject) => nextHitobject.StartTime <= hitobject.GetEndTime() + ms_leniency;
|
||||
protected bool AreConcurrent(HitObject hitobject, HitObject nextHitobject) => nextHitobject.StartTime <= hitobject.GetEndTime() + ms_leniency;
|
||||
|
||||
public abstract class IssueTemplateConcurrent : IssueTemplate
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user