1
0
mirror of https://github.com/ppy/osu.git synced 2024-11-16 19:07:25 +08:00
osu-lazer/osu.Game.Rulesets.Taiko/Difficulty/Preprocessing/Colour/TaikoColourDifficultyPreprocessor.cs

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

169 lines
7.7 KiB
C#
Raw Normal View History

2022-07-15 19:07:01 +08:00
// 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.Difficulty.Preprocessing;
2022-07-15 19:07:01 +08:00
using osu.Game.Rulesets.Taiko.Difficulty.Preprocessing.Colour.Data;
using osu.Game.Rulesets.Taiko.Objects;
namespace osu.Game.Rulesets.Taiko.Difficulty.Preprocessing.Colour
{
/// <summary>
2022-08-15 20:26:54 +08:00
/// Utility class to perform various encodings.
/// </summary>
public static class TaikoColourDifficultyPreprocessor
{
/// <summary>
2022-07-21 08:52:41 +08:00
/// Processes and encodes a list of <see cref="TaikoDifficultyHitObject"/>s into a list of <see cref="TaikoDifficultyHitObjectColour"/>s,
/// assigning the appropriate <see cref="TaikoDifficultyHitObjectColour"/>s to each <see cref="TaikoDifficultyHitObject"/>.
/// </summary>
2022-08-15 20:38:40 +08:00
public static void ProcessAndAssign(List<DifficultyHitObject> hitObjects)
{
2022-08-19 15:45:43 +08:00
List<RepeatingHitPatterns> hitPatterns = encode(hitObjects);
// Assign indexing and encoding data to all relevant objects.
2022-08-19 15:45:43 +08:00
foreach (var repeatingHitPattern in hitPatterns)
{
// The outermost loop is kept a ForEach loop since it doesn't need index information, and we want to
2022-08-19 15:45:43 +08:00
// keep i and j for AlternatingMonoPattern's and MonoStreak's index respectively, to keep it in line with
// documentation.
2022-08-19 15:45:43 +08:00
for (int i = 0; i < repeatingHitPattern.AlternatingMonoPatterns.Count; ++i)
{
2022-08-19 15:45:43 +08:00
AlternatingMonoPattern monoPattern = repeatingHitPattern.AlternatingMonoPatterns[i];
monoPattern.Parent = repeatingHitPattern;
monoPattern.Index = i;
2022-08-19 15:45:43 +08:00
for (int j = 0; j < monoPattern.MonoStreaks.Count; ++j)
{
2022-08-19 15:45:43 +08:00
MonoStreak monoStreak = monoPattern.MonoStreaks[j];
monoStreak.Parent = monoPattern;
monoStreak.Index = j;
foreach (var hitObject in monoStreak.HitObjects)
{
hitObject.Colour.RepeatingHitPattern = repeatingHitPattern;
hitObject.Colour.AlternatingMonoPattern = monoPattern;
hitObject.Colour.MonoStreak = monoStreak;
}
}
}
2022-08-15 20:26:54 +08:00
}
}
/// <summary>
2022-08-19 15:31:03 +08:00
/// Encodes a list of <see cref="TaikoDifficultyHitObject"/>s into a list of <see cref="RepeatingHitPatterns"/>s.
/// </summary>
2022-08-19 15:31:03 +08:00
private static List<RepeatingHitPatterns> encode(List<DifficultyHitObject> data)
{
2022-08-19 15:45:43 +08:00
List<MonoStreak> monoStreaks = encodeMonoStreak(data);
List<AlternatingMonoPattern> alternatingMonoPatterns = encodeAlternatingMonoPattern(monoStreaks);
List<RepeatingHitPatterns> repeatingHitPatterns = encodeRepeatingHitPattern(alternatingMonoPatterns);
2022-08-19 15:45:43 +08:00
return repeatingHitPatterns;
}
/// <summary>
2022-08-19 15:31:03 +08:00
/// Encodes a list of <see cref="TaikoDifficultyHitObject"/>s into a list of <see cref="MonoStreak"/>s.
/// </summary>
2022-08-19 15:45:43 +08:00
private static List<MonoStreak> encodeMonoStreak(List<DifficultyHitObject> data)
{
2022-08-19 15:45:43 +08:00
List<MonoStreak> monoStreaks = new List<MonoStreak>();
MonoStreak? currentMonoStreak = null;
2022-07-15 19:07:01 +08:00
for (int i = 0; i < data.Count; i++)
{
TaikoDifficultyHitObject taikoObject = (TaikoDifficultyHitObject)data[i];
2022-08-15 20:26:54 +08:00
// This ignores all non-note objects, which may or may not be the desired behaviour
2022-07-15 19:07:01 +08:00
TaikoDifficultyHitObject? previousObject = taikoObject.PreviousNote(0);
2022-08-19 15:45:43 +08:00
// If this is the first object in the list or the colour changed, create a new mono streak
if (currentMonoStreak == null || previousObject == null || (taikoObject.BaseObject as Hit)?.Type != (previousObject.BaseObject as Hit)?.Type)
{
2022-08-19 15:45:43 +08:00
currentMonoStreak = new MonoStreak();
monoStreaks.Add(currentMonoStreak);
}
2022-07-21 08:52:41 +08:00
// Add the current object to the encoded payload.
2022-08-19 15:45:43 +08:00
currentMonoStreak.HitObjects.Add(taikoObject);
}
2022-08-19 15:45:43 +08:00
return monoStreaks;
}
/// <summary>
2022-08-19 15:31:03 +08:00
/// Encodes a list of <see cref="MonoStreak"/>s into a list of <see cref="AlternatingMonoPattern"/>s.
/// </summary>
2022-08-19 15:45:43 +08:00
private static List<AlternatingMonoPattern> encodeAlternatingMonoPattern(List<MonoStreak> data)
{
2022-08-19 15:45:43 +08:00
List<AlternatingMonoPattern> monoPatterns = new List<AlternatingMonoPattern>();
AlternatingMonoPattern? currentMonoPattern = null;
2022-07-15 19:07:01 +08:00
for (int i = 0; i < data.Count; i++)
{
2022-08-19 15:45:43 +08:00
// Start a new AlternatingMonoPattern if the previous MonoStreak has a different mono length, or if this is the first MonoStreak in the list.
if (currentMonoPattern == null || data[i].RunLength != data[i - 1].RunLength)
{
2022-08-19 15:45:43 +08:00
currentMonoPattern = new AlternatingMonoPattern();
monoPatterns.Add(currentMonoPattern);
}
2022-08-19 15:45:43 +08:00
// Add the current MonoStreak to the encoded payload.
currentMonoPattern.MonoStreaks.Add(data[i]);
}
2022-08-19 15:45:43 +08:00
return monoPatterns;
}
/// <summary>
2022-08-19 15:31:03 +08:00
/// Encodes a list of <see cref="AlternatingMonoPattern"/>s into a list of <see cref="RepeatingHitPatterns"/>s.
/// </summary>
2022-08-19 15:45:43 +08:00
private static List<RepeatingHitPatterns> encodeRepeatingHitPattern(List<AlternatingMonoPattern> data)
{
2022-08-19 15:45:43 +08:00
List<RepeatingHitPatterns> hitPatterns = new List<RepeatingHitPatterns>();
RepeatingHitPatterns? currentHitPattern = null;
2022-07-15 19:07:01 +08:00
for (int i = 0; i < data.Count; i++)
{
2022-08-19 15:45:43 +08:00
// Start a new RepeatingHitPattern. AlternatingMonoPatterns that should be grouped together will be handled later within this loop.
currentHitPattern = new RepeatingHitPatterns(currentHitPattern);
2022-08-19 15:45:43 +08:00
// Determine if future AlternatingMonoPatterns should be grouped.
2022-07-15 19:07:01 +08:00
bool isCoupled = i < data.Count - 2 && data[i].IsRepetitionOf(data[i + 2]);
if (!isCoupled)
{
2022-08-19 15:45:43 +08:00
// If not, add the current AlternatingMonoPattern to the encoded payload and continue.
currentHitPattern.AlternatingMonoPatterns.Add(data[i]);
}
else
{
2022-08-19 15:45:43 +08:00
// If so, add the current AlternatingMonoPattern to the encoded payload and start repeatedly checking if the
// subsequent AlternatingMonoPatterns should be grouped by increasing i and doing the appropriate isCoupled check.
while (isCoupled)
{
2022-08-19 15:45:43 +08:00
currentHitPattern.AlternatingMonoPatterns.Add(data[i]);
i++;
2022-07-15 19:07:01 +08:00
isCoupled = i < data.Count - 2 && data[i].IsRepetitionOf(data[i + 2]);
}
2022-07-21 08:52:41 +08:00
// Skip over viewed data and add the rest to the payload
2022-08-19 15:45:43 +08:00
currentHitPattern.AlternatingMonoPatterns.Add(data[i]);
currentHitPattern.AlternatingMonoPatterns.Add(data[i + 1]);
i++;
}
2022-08-19 15:45:43 +08:00
hitPatterns.Add(currentHitPattern);
}
// Final pass to find repetition intervals
2022-08-19 15:45:43 +08:00
for (int i = 0; i < hitPatterns.Count; i++)
{
2022-08-19 15:45:43 +08:00
hitPatterns[i].FindRepetitionInterval();
}
2022-08-19 15:45:43 +08:00
return hitPatterns;
}
}
2022-07-15 19:07:01 +08:00
}