diff --git a/osu.Game.Rulesets.Taiko/Difficulty/Evaluators/ColourEvaluator.cs b/osu.Game.Rulesets.Taiko/Difficulty/Evaluators/ColourEvaluator.cs
index 14f95fbdd5..1627833e8a 100644
--- a/osu.Game.Rulesets.Taiko/Difficulty/Evaluators/ColourEvaluator.cs
+++ b/osu.Game.Rulesets.Taiko/Difficulty/Evaluators/ColourEvaluator.cs
@@ -14,21 +14,7 @@ namespace osu.Game.Rulesets.Taiko.Difficulty.Evaluators
public static double EvaluateDifficultyOf(TaikoDifficultyHitObjectColour colour)
{
- if (colour == null) return 0;
-
- double objectStrain = 1.85;
-
- if (colour.Delta)
- {
- objectStrain *= sigmoid(colour.DeltaRunLength, 3, 3) * 0.5 + 0.5;
- }
- else
- {
- objectStrain *= sigmoid(colour.DeltaRunLength, 2, 2) * 0.5 + 0.5;
- }
-
- objectStrain *= -sigmoid(colour.RepetitionInterval, 1, 8);
- return objectStrain;
+ return 1;
}
public static double EvaluateDifficultyOf(DifficultyHitObject current)
diff --git a/osu.Game.Rulesets.Taiko/Difficulty/Preprocessing/ColourEncoding.cs b/osu.Game.Rulesets.Taiko/Difficulty/Preprocessing/ColourEncoding.cs
new file mode 100644
index 0000000000..e2ac40170e
--- /dev/null
+++ b/osu.Game.Rulesets.Taiko/Difficulty/Preprocessing/ColourEncoding.cs
@@ -0,0 +1,68 @@
+using System.Collections.Generic;
+using osu.Game.Rulesets.Difficulty.Preprocessing;
+
+namespace osu.Game.Rulesets.Taiko.Difficulty.Preprocessing
+{
+ public class ColourEncoding
+ {
+ ///
+ /// Amount consecutive notes of the same colour
+ ///
+ public int MonoRunLength = 1;
+
+ ///
+ /// Amount of consecutive encoding with the same
+ ///
+ public int EncodingRunLength = 1;
+
+ ///
+ /// Beginning index in the data that this encodes
+ ///
+ public int StartIndex = 0;
+
+ public bool isIdenticalTo(ColourEncoding other)
+ {
+ return other.MonoRunLength == MonoRunLength && other.EncodingRunLength == EncodingRunLength;
+ }
+
+ public static List Encode(List data)
+ {
+ // Encoding mono lengths
+ List firstPass = new List();
+ ColourEncoding? lastEncoded = null;
+ for (int i = 0; i < data.Count; i++)
+ {
+ TaikoDifficultyHitObject taikoObject = (TaikoDifficultyHitObject)data[i];
+ // This ignores all non-note objects, which may or may not be the desired behaviour
+ TaikoDifficultyHitObject previousObject = (TaikoDifficultyHitObject)taikoObject.PreviousNote(0);
+
+ if (previousObject == null || lastEncoded == null || taikoObject.HitType != previousObject.HitType)
+ {
+ lastEncoded = new ColourEncoding();
+ lastEncoded.StartIndex = i;
+ firstPass.Add(lastEncoded);
+ continue;
+ }
+
+ lastEncoded.MonoRunLength += 1;
+ }
+
+ // Encode encoding lengths
+ List secondPass = new List();
+ lastEncoded = null;
+ for (int i = 0; i < firstPass.Count; i++)
+ {
+ if (i == 0 || lastEncoded == null || firstPass[i].MonoRunLength != firstPass[i - 1].MonoRunLength)
+ {
+ lastEncoded = firstPass[i];
+ secondPass.Add(firstPass[i]);
+ continue;
+ }
+
+ lastEncoded.EncodingRunLength += 1;
+ }
+
+ return secondPass;
+ }
+ }
+}
\ No newline at end of file
diff --git a/osu.Game.Rulesets.Taiko/Difficulty/Preprocessing/CoupledColourEncoding.cs b/osu.Game.Rulesets.Taiko/Difficulty/Preprocessing/CoupledColourEncoding.cs
new file mode 100644
index 0000000000..81e8ae006f
--- /dev/null
+++ b/osu.Game.Rulesets.Taiko/Difficulty/Preprocessing/CoupledColourEncoding.cs
@@ -0,0 +1,73 @@
+using System.Collections.Generic;
+
+namespace osu.Game.Rulesets.Taiko.Difficulty.Preprocessing
+{
+ public class CoupledColourEncoding
+ {
+ public int RunLength = 1;
+
+ public ColourEncoding[] Payload;
+
+ ///
+ /// Beginning index in the data that this encodes
+ ///
+ public int StartIndex { get; private set; } = 0;
+
+ public int EndIndex { get; private set; } = 0;
+
+ private CoupledColourEncoding(ColourEncoding[] payload)
+ {
+ Payload = payload;
+ }
+
+ public static List Encode(List data)
+ {
+ List encoded = new List();
+
+ CoupledColourEncoding? lastEncoded = null;
+ for (int i = 0; i < data.Count; i++)
+ {
+ if (lastEncoded != null) lastEncoded.EndIndex = data[i].StartIndex - 1;
+
+ if (i >= data.Count - 2 || !data[i].isIdenticalTo(data[i + 2]))
+ {
+ lastEncoded = new CoupledColourEncoding(new ColourEncoding[] { data[i] });
+ lastEncoded.StartIndex = data[i].StartIndex;
+ }
+ else
+ {
+ lastEncoded = new CoupledColourEncoding(new ColourEncoding[] { data[i], data[i + 1] });
+ lastEncoded.StartIndex = data[i].StartIndex;
+ lastEncoded.RunLength = 3;
+ i++;
+
+ // Peek 2 indices ahead
+ while (i < data.Count - 2 && data[i].isIdenticalTo(data[i + 2]))
+ {
+ lastEncoded.RunLength += 1;
+ i++;
+ }
+
+ // Skip over peeked data
+ i++;
+ }
+
+ encoded.Add(lastEncoded);
+ }
+
+ return encoded;
+ }
+
+ public bool hasIdenticalPayload(CoupledColourEncoding other)
+ {
+ if (this.Payload.Length != other.Payload.Length) return false;
+
+ for (int i = 0; i < this.Payload.Length; i++)
+ {
+ if (!this.Payload[i].isIdenticalTo(other.Payload[i])) return false;
+ }
+
+ return true;
+ }
+ }
+}
\ No newline at end of file
diff --git a/osu.Game.Rulesets.Taiko/Difficulty/Preprocessing/TaikoDifficultyHitObject.cs b/osu.Game.Rulesets.Taiko/Difficulty/Preprocessing/TaikoDifficultyHitObject.cs
index f35cf1d8b9..1ee905d94c 100644
--- a/osu.Game.Rulesets.Taiko/Difficulty/Preprocessing/TaikoDifficultyHitObject.cs
+++ b/osu.Game.Rulesets.Taiko/Difficulty/Preprocessing/TaikoDifficultyHitObject.cs
@@ -52,21 +52,21 @@ namespace osu.Game.Rulesets.Taiko.Difficulty.Preprocessing
/// The rate at which the gameplay clock is run at.
public static List Create(IBeatmap beatmap, double clockRate)
{
- List difficultyHitObject = new List();
+ List difficultyHitObjects = new List();
List centreObjects = new List();
List rimObjects = new List();
List noteObjects = new List();
for (int i = 2; i < beatmap.HitObjects.Count; i++)
{
- difficultyHitObject.Add(
+ difficultyHitObjects.Add(
new TaikoDifficultyHitObject(
- beatmap.HitObjects[i], beatmap.HitObjects[i - 1], beatmap.HitObjects[i - 2], clockRate, difficultyHitObject,
- centreObjects, rimObjects, noteObjects, difficultyHitObject.Count)
+ beatmap.HitObjects[i], beatmap.HitObjects[i - 1], beatmap.HitObjects[i - 2], clockRate, difficultyHitObjects,
+ centreObjects, rimObjects, noteObjects, difficultyHitObjects.Count)
);
}
- List colours = TaikoDifficultyHitObjectColour.CreateColoursFor(difficultyHitObject);
+ List colours = TaikoDifficultyHitObjectColour.EncodeAndAssign(difficultyHitObjects);
// Pre-evaluate colours
for (int i = 0; i < colours.Count; i++)
@@ -74,7 +74,7 @@ namespace osu.Game.Rulesets.Taiko.Difficulty.Preprocessing
colours[i].EvaluatedDifficulty = ColourEvaluator.EvaluateDifficultyOf(colours[i]);
}
- return difficultyHitObject;
+ return difficultyHitObjects;
}
///
diff --git a/osu.Game.Rulesets.Taiko/Difficulty/Preprocessing/TaikoDifficultyHitObjectColour.cs b/osu.Game.Rulesets.Taiko/Difficulty/Preprocessing/TaikoDifficultyHitObjectColour.cs
index 74b8899c60..6bd99550be 100644
--- a/osu.Game.Rulesets.Taiko/Difficulty/Preprocessing/TaikoDifficultyHitObjectColour.cs
+++ b/osu.Game.Rulesets.Taiko/Difficulty/Preprocessing/TaikoDifficultyHitObjectColour.cs
@@ -1,5 +1,3 @@
-#nullable disable
-
using System;
using System.Collections.Generic;
using osu.Game.Rulesets.Difficulty.Preprocessing;
@@ -11,72 +9,51 @@ namespace osu.Game.Rulesets.Taiko.Difficulty.Preprocessing
///
public class TaikoDifficultyHitObjectColour
{
+ public CoupledColourEncoding Encoding { get; private set; }
+
private const int max_repetition_interval = 16;
- public TaikoDifficultyHitObjectColour Previous { get; private set; }
-
- ///
- /// True if the current colour is different from the previous colour.
- ///
- public bool Delta { get; private set; }
-
- ///
- /// How many notes are Delta repeated
- ///
- public int DeltaRunLength { get; private set; }
-
///
/// How many notes between the current and previous identical .
/// Negative number means that there is no repetition in range.
/// If no repetition is found this will have a value of + 1.
///
- public int RepetitionInterval { get; private set; }
+ public int RepetitionInterval { get; private set; } = max_repetition_interval + 1;
///
/// Evaluated colour difficulty is cached here, as difficulty don't need to be calculated per-note.
///
/// TODO: Consider having all evaluated difficulty cached in TaikoDifficultyHitObject instead, since we may be
/// reusing evaluator results in the future.
- public double EvaluatedDifficulty;
+ public double EvaluatedDifficulty = 0;
- public TaikoDifficultyHitObjectColour repeatedColour { get; private set; }
+ public TaikoDifficultyHitObjectColour? Previous { get; private set; } = null;
- ///
- /// Get the instance for the given hitObject. This is implemented
- /// as a static function instead of constructor to allow for reusing existing instances.
- ///
- public static List CreateColoursFor(List hitObjects)
+ public TaikoDifficultyHitObjectColour? repeatedColour { get; private set; } = null;
+
+ public TaikoDifficultyHitObjectColour(CoupledColourEncoding encoding)
+ {
+ Encoding = encoding;
+ }
+
+ public static List EncodeAndAssign(List hitObjects)
{
List colours = new List();
-
- for (int i = 0; i < hitObjects.Count; i++)
+ List encodings = CoupledColourEncoding.Encode(ColourEncoding.Encode(hitObjects));
+ TaikoDifficultyHitObjectColour? lastColour = null;
+ for (int i = 0; i < encodings.Count; i++)
{
- TaikoDifficultyHitObject hitObject = (TaikoDifficultyHitObject)hitObjects[i];
- TaikoDifficultyHitObject lastObject = hitObject.PreviousNote(0);
- TaikoDifficultyHitObjectColour previous = lastObject?.Colour;
- bool delta = lastObject == null || hitObject.HitType != lastObject.HitType;
-
- if (previous != null && delta == previous.Delta)
+ lastColour = new TaikoDifficultyHitObjectColour(encodings[i])
{
- previous.DeltaRunLength += 1;
- hitObject.Colour = previous;
- continue;
- }
-
- TaikoDifficultyHitObjectColour colour = new TaikoDifficultyHitObjectColour()
- {
- Delta = delta,
- DeltaRunLength = 1,
- RepetitionInterval = max_repetition_interval + 1,
- Previous = previous
+ Previous = lastColour
};
- hitObject.Colour = colour;
- colours.Add(colour);
+ colours.Add(lastColour);
}
- for (int i = 0; i < colours.Count; i++)
+ foreach (TaikoDifficultyHitObjectColour colour in colours)
{
- colours[i].FindRepetitionInterval();
+ colour.FindRepetitionInterval();
+ ((TaikoDifficultyHitObject)hitObjects[colour.Encoding.StartIndex]).Colour = colour;
}
return colours;
@@ -94,23 +71,23 @@ namespace osu.Game.Rulesets.Taiko.Difficulty.Preprocessing
return;
}
- int interval = Previous.DeltaRunLength;
- TaikoDifficultyHitObjectColour other = Previous.Previous;
-
- while (other != null && interval < max_repetition_interval)
+ TaikoDifficultyHitObjectColour? other = Previous.Previous;
+ int interval = this.Encoding.StartIndex - other.Encoding.EndIndex;
+ while (interval < max_repetition_interval)
{
- if (other.Delta == Delta && other.DeltaRunLength == DeltaRunLength)
+ if (Encoding.hasIdenticalPayload(other.Encoding))
{
RepetitionInterval = Math.Min(interval, max_repetition_interval);
repeatedColour = other;
return;
}
- interval += other.DeltaRunLength;
other = other.Previous;
+ if (other == null) break;
+ interval = this.Encoding.StartIndex - other.Encoding.EndIndex;
}
RepetitionInterval = max_repetition_interval + 1;
}
}
-}
+}
\ No newline at end of file
diff --git a/osu.Game.Rulesets.Taiko/Difficulty/Skills/Colour.cs b/osu.Game.Rulesets.Taiko/Difficulty/Skills/Colour.cs
index 0d69104a58..13d5cd673e 100644
--- a/osu.Game.Rulesets.Taiko/Difficulty/Skills/Colour.cs
+++ b/osu.Game.Rulesets.Taiko/Difficulty/Skills/Colour.cs
@@ -27,10 +27,17 @@ namespace osu.Game.Rulesets.Taiko.Difficulty.Skills
{
TaikoDifficultyHitObjectColour colour = ((TaikoDifficultyHitObject)current).Colour;
double difficulty = colour == null ? 0 : colour.EvaluatedDifficulty;
- // if (current != null && colour != null)
- // {
- // System.Console.WriteLine($"{current.StartTime},{colour.Delta},{colour.RepetitionInterval},{difficulty}");
- // }
+ if (current != null && colour != null)
+ {
+ ColourEncoding[] payload = colour.Encoding.Payload;
+ string payloadDisplay = "";
+ for (int i = 0; i < payload.Length; ++i)
+ {
+ payloadDisplay += $",({payload[i].MonoRunLength},{payload[i].EncodingRunLength})";
+ }
+
+ System.Console.WriteLine($"{current.StartTime},{colour.RepetitionInterval},{colour.Encoding.RunLength}{payloadDisplay}");
+ }
return difficulty;
}