From db150d58997c76c0171ffe3340d158a46ec8a41a Mon Sep 17 00:00:00 2001 From: Samuel Cattini-Schultz Date: Sun, 28 Apr 2024 22:01:27 +1000 Subject: [PATCH 1/6] Add validation --- Difficalcy.Catch/Models/CatchScore.cs | 21 ++++++++++++++++++++- Difficalcy.Mania/Models/ManiaScore.cs | 12 ++++++++++++ Difficalcy.Osu/Models/OsuScore.cs | 21 ++++++++++++++++++++- Difficalcy.Taiko/Models/TaikoScore.cs | 19 ++++++++++++++++++- Difficalcy/Models/Score.cs | 2 ++ 5 files changed, 72 insertions(+), 3 deletions(-) diff --git a/Difficalcy.Catch/Models/CatchScore.cs b/Difficalcy.Catch/Models/CatchScore.cs index 39c6e8d..9930fe6 100644 --- a/Difficalcy.Catch/Models/CatchScore.cs +++ b/Difficalcy.Catch/Models/CatchScore.cs @@ -1,13 +1,32 @@ +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; using Difficalcy.Models; namespace Difficalcy.Catch.Models { - public record CatchScore : Score + public record CatchScore : Score, IValidatableObject { + [Range(0, 1)] public double? Accuracy { get; init; } + + [Range(0, int.MaxValue)] public int? Combo { get; init; } + + [Range(0, int.MaxValue)] public int? Misses { get; init; } + + [Range(0, int.MaxValue)] public int? TinyDroplets { get; init; } + + [Range(0, int.MaxValue)] public int? Droplets { get; init; } + + public IEnumerable Validate(ValidationContext validationContext) + { + if (Misses is not null && Combo is null) + { + yield return new ValidationResult("Combo must be specified if Misses are specified.", [nameof(Combo)]); + } + } } } diff --git a/Difficalcy.Mania/Models/ManiaScore.cs b/Difficalcy.Mania/Models/ManiaScore.cs index 3a60b3a..50b8631 100644 --- a/Difficalcy.Mania/Models/ManiaScore.cs +++ b/Difficalcy.Mania/Models/ManiaScore.cs @@ -1,14 +1,26 @@ +using System.ComponentModel.DataAnnotations; using Difficalcy.Models; namespace Difficalcy.Mania.Models { public record ManiaScore : Score { + [Range(0, 1)] public double? Accuracy { get; init; } + + [Range(0, int.MaxValue)] public int? Misses { get; init; } + + [Range(0, int.MaxValue)] public int? Mehs { get; init; } + + [Range(0, int.MaxValue)] public int? Oks { get; init; } + + [Range(0, int.MaxValue)] public int? Goods { get; init; } + + [Range(0, int.MaxValue)] public int? Greats { get; init; } } } diff --git a/Difficalcy.Osu/Models/OsuScore.cs b/Difficalcy.Osu/Models/OsuScore.cs index ef31df2..aebb4b3 100644 --- a/Difficalcy.Osu/Models/OsuScore.cs +++ b/Difficalcy.Osu/Models/OsuScore.cs @@ -1,13 +1,32 @@ +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; using Difficalcy.Models; namespace Difficalcy.Osu.Models { - public record OsuScore : Score + public record OsuScore : Score, IValidatableObject { + [Range(0, 1)] public double? Accuracy { get; init; } + + [Range(0, int.MaxValue)] public int? Combo { get; init; } + + [Range(0, int.MaxValue)] public int? Misses { get; init; } + + [Range(0, int.MaxValue)] public int? Mehs { get; init; } + + [Range(0, int.MaxValue)] public int? Oks { get; init; } + + public IEnumerable Validate(ValidationContext validationContext) + { + if (Misses is not null && Combo is null) + { + yield return new ValidationResult("Combo must be specified if Misses are specified.", [nameof(Combo)]); + } + } } } diff --git a/Difficalcy.Taiko/Models/TaikoScore.cs b/Difficalcy.Taiko/Models/TaikoScore.cs index 476c218..4433797 100644 --- a/Difficalcy.Taiko/Models/TaikoScore.cs +++ b/Difficalcy.Taiko/Models/TaikoScore.cs @@ -1,12 +1,29 @@ +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; using Difficalcy.Models; namespace Difficalcy.Taiko.Models { - public record TaikoScore : Score + public record TaikoScore : Score, IValidatableObject { + [Range(0, 1)] public double? Accuracy { get; init; } + + [Range(0, int.MaxValue)] public int? Combo { get; init; } + + [Range(0, int.MaxValue)] public int? Misses { get; init; } + + [Range(0, int.MaxValue)] public int? Oks { get; init; } + + public IEnumerable Validate(ValidationContext validationContext) + { + if (Misses is not null && Combo is null) + { + yield return new ValidationResult("Combo must be specified if Misses are specified.", [nameof(Combo)]); + } + } } } diff --git a/Difficalcy/Models/Score.cs b/Difficalcy/Models/Score.cs index 73fe0ff..2120600 100644 --- a/Difficalcy/Models/Score.cs +++ b/Difficalcy/Models/Score.cs @@ -6,6 +6,8 @@ public abstract record Score { [Required] public string BeatmapId { get; init; } + + [Range(0, int.MaxValue)] public int? Mods { get; init; } } } From 268387d47fd27ecb5b281a9e8ff9ea374d8c804d Mon Sep 17 00:00:00 2001 From: Samuel Cattini-Schultz Date: Mon, 29 Apr 2024 00:45:15 +1000 Subject: [PATCH 2/6] Remove Accuracy parameters to simplify API --- .../CatchCalculatorServiceTest.cs | 18 +-- Difficalcy.Catch/Models/CatchScore.cs | 16 +- .../Services/CatchCalculatorService.cs | 43 +++-- .../ManiaCalculatorServiceTest.cs | 15 -- Difficalcy.Mania/Models/ManiaScore.cs | 13 +- .../Services/ManiaCalculatorService.cs | 69 ++------ .../OsuCalculatorServiceTest.cs | 14 -- Difficalcy.Osu/Models/OsuScore.cs | 13 +- .../Services/OsuCalculatorService.cs | 36 +---- .../TaikoCalculatorServiceTest.cs | 14 -- Difficalcy.Taiko/Models/TaikoScore.cs | 11 +- .../Services/TaikoCalculatorService.cs | 26 +-- .../DummyCalculatorServiceTest.cs | 2 +- Difficalcy/Models/Score.cs | 2 +- Difficalcy/Services/CalculatorService.cs | 2 +- docs/docs/api-reference/difficalcy-catch.json | 114 ++++++------- docs/docs/api-reference/difficalcy-mania.json | 152 +++++++++--------- docs/docs/api-reference/difficalcy-osu.json | 120 +++++++------- docs/docs/api-reference/difficalcy-taiko.json | 100 +++++------- 19 files changed, 301 insertions(+), 479 deletions(-) diff --git a/Difficalcy.Catch.Tests/CatchCalculatorServiceTest.cs b/Difficalcy.Catch.Tests/CatchCalculatorServiceTest.cs index d3cd804..3f06f91 100644 --- a/Difficalcy.Catch.Tests/CatchCalculatorServiceTest.cs +++ b/Difficalcy.Catch.Tests/CatchCalculatorServiceTest.cs @@ -24,22 +24,8 @@ public void TestAllParameters() Mods = 80, // HR, DT Combo = 100, Misses = 5, - TinyDroplets = 200, - Droplets = 3, - }; - base.TestGetCalculationReturnsCorrectValues(5.739025024925009d, 241.19384779497875d, score); - } - - [Fact] - public void TestAccuracyParameter() - { - var score = new CatchScore - { - BeatmapId = "diffcalc-test", - Mods = 80, // HR, DT - Accuracy = 0.9583333333333334, - Combo = 100, - Misses = 5, + LargeDroplets = 18, + SmallDroplets = 200, }; base.TestGetCalculationReturnsCorrectValues(5.739025024925009d, 241.19384779497875d, score); } diff --git a/Difficalcy.Catch/Models/CatchScore.cs b/Difficalcy.Catch/Models/CatchScore.cs index 9930fe6..44ec453 100644 --- a/Difficalcy.Catch/Models/CatchScore.cs +++ b/Difficalcy.Catch/Models/CatchScore.cs @@ -6,26 +6,26 @@ namespace Difficalcy.Catch.Models { public record CatchScore : Score, IValidatableObject { - [Range(0, 1)] - public double? Accuracy { get; init; } - [Range(0, int.MaxValue)] public int? Combo { get; init; } + /// + /// The number of fruit and large droplet misses. + /// [Range(0, int.MaxValue)] - public int? Misses { get; init; } + public int Misses { get; init; } = 0; // fruit + large droplet misses [Range(0, int.MaxValue)] - public int? TinyDroplets { get; init; } + public int? SmallDroplets { get; init; } [Range(0, int.MaxValue)] - public int? Droplets { get; init; } + public int? LargeDroplets { get; init; } public IEnumerable Validate(ValidationContext validationContext) { - if (Misses is not null && Combo is null) + if (Misses > 0 && Combo is null) { - yield return new ValidationResult("Combo must be specified if Misses are specified.", [nameof(Combo)]); + yield return new ValidationResult("Combo must be specified if Misses are greater than 0.", [nameof(Combo)]); } } } diff --git a/Difficalcy.Catch/Services/CatchCalculatorService.cs b/Difficalcy.Catch/Services/CatchCalculatorService.cs index b2773b1..c961b21 100644 --- a/Difficalcy.Catch/Services/CatchCalculatorService.cs +++ b/Difficalcy.Catch/Services/CatchCalculatorService.cs @@ -52,7 +52,7 @@ protected override async Task EnsureBeatmap(string beatmapId) protected override (object, string) CalculateDifficultyAttributes(CatchScore score) { var workingBeatmap = getWorkingBeatmap(score.BeatmapId); - var mods = CatchRuleset.ConvertFromLegacyMods((LegacyMods)(score.Mods ?? 0)).ToArray(); + var mods = CatchRuleset.ConvertFromLegacyMods((LegacyMods)score.Mods).ToArray(); var difficultyCalculator = CatchRuleset.CreateDifficultyCalculator(workingBeatmap); var difficultyAttributes = difficultyCalculator.Calculate(mods) as CatchDifficultyAttributes; @@ -83,12 +83,11 @@ protected override object DeserialiseDifficultyAttributes(string difficultyAttri protected override CatchPerformance CalculatePerformance(CatchScore score, object difficultyAttributes) { var workingBeatmap = getWorkingBeatmap(score.BeatmapId); - var mods = CatchRuleset.ConvertFromLegacyMods((LegacyMods)(score.Mods ?? 0)).ToArray(); + var mods = CatchRuleset.ConvertFromLegacyMods((LegacyMods)score.Mods).ToArray(); var beatmap = workingBeatmap.GetPlayableBeatmap(CatchRuleset.RulesetInfo, mods); - var hitResultCount = beatmap.HitObjects.Count(h => h is Fruit) + beatmap.HitObjects.OfType().SelectMany(j => j.NestedHitObjects).Count(h => !(h is TinyDroplet)); - var combo = score.Combo ?? hitResultCount; - var statistics = determineHitResults(score.Accuracy ?? 1, hitResultCount, beatmap, score.Misses ?? 0, score.TinyDroplets, score.Droplets); + var combo = score.Combo ?? beatmap.HitObjects.Count(h => h is Fruit) + beatmap.HitObjects.OfType().SelectMany(j => j.NestedHitObjects).Count(h => !(h is TinyDroplet)); + var statistics = getHitResults(beatmap, score.Misses, score.LargeDroplets, score.SmallDroplets); var accuracy = calculateAccuracy(statistics); var scoreInfo = new ScoreInfo(beatmap.BeatmapInfo, CatchRuleset.RulesetInfo) @@ -123,33 +122,29 @@ private CalculatorWorkingBeatmap getWorkingBeatmap(string beatmapId) return new CalculatorWorkingBeatmap(CatchRuleset, beatmapStream, beatmapId); } - private Dictionary determineHitResults(double targetAccuracy, int hitResultCount, IBeatmap beatmap, int countMiss, int? countTinyDroplets, int? countDroplet) + private Dictionary getHitResults(IBeatmap beatmap, int countMiss, int? countDroplet, int? countTinyDroplet) { - // Adapted from https://github.com/ppy/osu-tools/blob/cf5410b04f4e2d1ed2c50c7263f98c8fc5f928ab/PerformanceCalculator/Simulate/CatchSimulateCommand.cs#L58-L86 - int maxTinyDroplets = beatmap.HitObjects.OfType().Sum(s => s.NestedHitObjects.OfType().Count()); - int maxDroplets = beatmap.HitObjects.OfType().Sum(s => s.NestedHitObjects.OfType().Count()) - maxTinyDroplets; - int maxFruits = beatmap.HitObjects.OfType().Count() + 2 * beatmap.HitObjects.OfType().Count() + beatmap.HitObjects.OfType().Sum(s => s.RepeatCount); + var maxTinyDroplets = beatmap.HitObjects.OfType().Sum(s => s.NestedHitObjects.OfType().Count()); + var maxDroplets = beatmap.HitObjects.OfType().Sum(s => s.NestedHitObjects.OfType().Count()) - maxTinyDroplets; + var maxFruits = beatmap.HitObjects.OfType().Count() + 2 * beatmap.HitObjects.OfType().Count() + beatmap.HitObjects.OfType().Sum(s => s.RepeatCount); - // Either given or max value minus misses - int countDroplets = countDroplet ?? Math.Max(0, maxDroplets - countMiss); + var countDroplets = countDroplet ?? maxDroplets; + var countTinyDroplets = countTinyDroplet ?? maxTinyDroplets; - // Max value minus whatever misses are left. Negative if impossible missCount - int countFruits = maxFruits - (countMiss - (maxDroplets - countDroplets)); + var countDropletMiss = maxDroplets - countDroplets; + var fruitMisses = countMiss - countDropletMiss; + var countFruit = maxFruits - fruitMisses; - // Either given or the max amount of hit objects with respect to accuracy minus the already calculated fruits and drops. - // Negative if accuracy not feasable with missCount. - int countTinyDroplet = countTinyDroplets ?? (int)Math.Round(targetAccuracy * (hitResultCount + maxTinyDroplets)) - countFruits - countDroplets; - - // Whatever droplets are left - int countTinyMisses = maxTinyDroplets - countTinyDroplet; + var countTinyDropletMiss = maxTinyDroplets - countTinyDroplets; return new Dictionary { - { HitResult.Great, countFruits }, + { HitResult.Great, countFruit }, { HitResult.LargeTickHit, countDroplets }, - { HitResult.SmallTickHit, countTinyDroplet }, - { HitResult.SmallTickMiss, countTinyMisses }, - { HitResult.Miss, countMiss } + { HitResult.SmallTickHit, countTinyDroplets }, + { HitResult.Miss, countMiss }, // fruit + large droplet misses + // { HitResult.LargeTickMiss, countDropletMiss }, // included in misses for legacy compatibility + { HitResult.SmallTickMiss, countTinyDropletMiss }, }; } diff --git a/Difficalcy.Mania.Tests/ManiaCalculatorServiceTest.cs b/Difficalcy.Mania.Tests/ManiaCalculatorServiceTest.cs index 2e6bf0a..f623b74 100644 --- a/Difficalcy.Mania.Tests/ManiaCalculatorServiceTest.cs +++ b/Difficalcy.Mania.Tests/ManiaCalculatorServiceTest.cs @@ -30,19 +30,4 @@ public void TestAllParameters() }; base.TestGetCalculationReturnsCorrectValues(2.797245912537965d, 43.17076331130473d, score); } - - [Fact] - public void TestAccuracyParameter() - { - var score = new ManiaScore - { - BeatmapId = "diffcalc-test", - Mods = 64, // DT - Accuracy = 0.9271523178807947, - Misses = 5, - }; - // expected pp is slightly higher than above test because there is a different solution to - // the hitresult distribution that yields the same accuracy but gives slightly higher pp - base.TestGetCalculationReturnsCorrectValues(2.797245912537965d, 43.455530879321245d, score); - } } diff --git a/Difficalcy.Mania/Models/ManiaScore.cs b/Difficalcy.Mania/Models/ManiaScore.cs index 50b8631..6afa584 100644 --- a/Difficalcy.Mania/Models/ManiaScore.cs +++ b/Difficalcy.Mania/Models/ManiaScore.cs @@ -5,22 +5,19 @@ namespace Difficalcy.Mania.Models { public record ManiaScore : Score { - [Range(0, 1)] - public double? Accuracy { get; init; } - [Range(0, int.MaxValue)] - public int? Misses { get; init; } + public int Misses { get; init; } = 0; [Range(0, int.MaxValue)] - public int? Mehs { get; init; } + public int Mehs { get; init; } = 0; [Range(0, int.MaxValue)] - public int? Oks { get; init; } + public int Oks { get; init; } = 0; [Range(0, int.MaxValue)] - public int? Goods { get; init; } + public int Goods { get; init; } = 0; [Range(0, int.MaxValue)] - public int? Greats { get; init; } + public int Greats { get; init; } = 0; } } diff --git a/Difficalcy.Mania/Services/ManiaCalculatorService.cs b/Difficalcy.Mania/Services/ManiaCalculatorService.cs index ec7a06e..664a461 100644 --- a/Difficalcy.Mania/Services/ManiaCalculatorService.cs +++ b/Difficalcy.Mania/Services/ManiaCalculatorService.cs @@ -52,7 +52,7 @@ protected override async Task EnsureBeatmap(string beatmapId) protected override (object, string) CalculateDifficultyAttributes(ManiaScore score) { var workingBeatmap = getWorkingBeatmap(score.BeatmapId); - var mods = ManiaRuleset.ConvertFromLegacyMods((LegacyMods)(score.Mods ?? 0)).ToArray(); + var mods = ManiaRuleset.ConvertFromLegacyMods((LegacyMods)score.Mods).ToArray(); var difficultyCalculator = ManiaRuleset.CreateDifficultyCalculator(workingBeatmap); var difficultyAttributes = difficultyCalculator.Calculate(mods) as ManiaDifficultyAttributes; @@ -83,12 +83,12 @@ protected override object DeserialiseDifficultyAttributes(string difficultyAttri protected override ManiaPerformance CalculatePerformance(ManiaScore score, object difficultyAttributes) { var workingBeatmap = getWorkingBeatmap(score.BeatmapId); - var mods = ManiaRuleset.ConvertFromLegacyMods((LegacyMods)(score.Mods ?? 0)).ToArray(); + var mods = ManiaRuleset.ConvertFromLegacyMods((LegacyMods)score.Mods).ToArray(); var beatmap = workingBeatmap.GetPlayableBeatmap(ManiaRuleset.RulesetInfo, mods); - var hitResultCount = beatmap.HitObjects.Count; - var holdNoteCount = beatmap.HitObjects.OfType().Count(); - var statistics = determineHitResults(score.Accuracy ?? 1, hitResultCount, holdNoteCount, score.Misses ?? 0, score.Mehs, score.Oks, score.Goods, score.Greats); + var hitObjectCount = beatmap.HitObjects.Count; + var holdNoteTailCount = beatmap.HitObjects.OfType().Count(); + var statistics = getHitResults(hitObjectCount + holdNoteTailCount, score.Misses, score.Mehs, score.Oks, score.Goods, score.Greats); var accuracy = calculateAccuracy(statistics); var scoreInfo = new ScoreInfo(beatmap.BeatmapInfo, ManiaRuleset.RulesetInfo) @@ -124,61 +124,18 @@ private CalculatorWorkingBeatmap getWorkingBeatmap(string beatmapId) return new CalculatorWorkingBeatmap(ManiaRuleset, beatmapStream, beatmapId); } - private Dictionary determineHitResults(double targetAccuracy, int hitObjectCount, int holdNoteCount, int countMiss, int? countMeh, int? countOk, int? countGood, int? countGreat) + private Dictionary getHitResults(int hitResultCount, int countMiss, int countMeh, int countOk, int countGood, int countGreat) { - // Adapted from https://github.com/ppy/osu-tools/blob/c3cbe410bb1255fc5884a3daf2df3e8f87a0a8a8/PerformanceCalculator/Simulate/ManiaSimulateCommand.cs#L54-L109 - // One judgement per normal note. Two judgements per hold note (head + tail). - var totalHits = hitObjectCount + holdNoteCount; - - if (countMeh != null || countOk != null || countGood != null || countGreat != null) - { - int countPerfect = totalHits - (countMiss + (countMeh ?? 0) + (countOk ?? 0) + (countGood ?? 0) + (countGreat ?? 0)); - - return new Dictionary - { - [HitResult.Perfect] = countPerfect, - [HitResult.Great] = countGreat ?? 0, - [HitResult.Good] = countGood ?? 0, - [HitResult.Ok] = countOk ?? 0, - [HitResult.Meh] = countMeh ?? 0, - [HitResult.Miss] = countMiss - }; - } - - // Let Perfect=Great=6, Good=4, Ok=2, Meh=1, Miss=0. The total should be this. - var targetTotal = (int)Math.Round(targetAccuracy * totalHits * 6); - - // Start by assuming every non miss is a meh - // This is how much increase is needed by the rest - int tempMeh = totalHits - countMiss; - int remainingToFill = targetTotal - tempMeh; - - // Each great and perfect increases total by 5 (great-meh=5) - // There is no difference in accuracy between them, so just call them perfects. - int perfects = Math.Min(remainingToFill / 5, tempMeh); - remainingToFill -= perfects * 5; - tempMeh -= perfects; - - // Each good increases total by 3 (good-meh=3). - int goods = Math.Min(remainingToFill / 3, tempMeh); - remainingToFill -= goods * 3; - tempMeh -= goods; - - // Each ok increases total by 1 (ok-meh=1). - int oks = remainingToFill; - tempMeh -= oks; - - // Everything else is a meh, as initially assumed. - int mehs = tempMeh; + var countPerfect = hitResultCount - (countMiss + countMeh + countOk + countGood + countGreat); return new Dictionary { - { HitResult.Perfect, perfects }, - { HitResult.Great, 0 }, - { HitResult.Good, goods }, - { HitResult.Ok, oks }, - { HitResult.Meh, mehs }, - { HitResult.Miss, countMiss } + [HitResult.Perfect] = countPerfect, + [HitResult.Great] = countGreat, + [HitResult.Good] = countGood, + [HitResult.Ok] = countOk, + [HitResult.Meh] = countMeh, + [HitResult.Miss] = countMiss }; } diff --git a/Difficalcy.Osu.Tests/OsuCalculatorServiceTest.cs b/Difficalcy.Osu.Tests/OsuCalculatorServiceTest.cs index 53bbff9..115641f 100644 --- a/Difficalcy.Osu.Tests/OsuCalculatorServiceTest.cs +++ b/Difficalcy.Osu.Tests/OsuCalculatorServiceTest.cs @@ -29,18 +29,4 @@ public void TestAllParameters() }; base.TestGetCalculationReturnsCorrectValues(10.07270907570737d, 553.1423675531603d, score); } - - [Fact] - public void TestAccuracyParameter() - { - var score = new OsuScore - { - BeatmapId = "diffcalc-test", - Mods = 1112, // HD, HR, DT, FL - Accuracy = 0.9166666666666666, - Combo = 200, - Misses = 5, - }; - base.TestGetCalculationReturnsCorrectValues(10.07270907570737d, 553.1423675531603d, score); - } } diff --git a/Difficalcy.Osu/Models/OsuScore.cs b/Difficalcy.Osu/Models/OsuScore.cs index aebb4b3..3d404b5 100644 --- a/Difficalcy.Osu/Models/OsuScore.cs +++ b/Difficalcy.Osu/Models/OsuScore.cs @@ -6,26 +6,23 @@ namespace Difficalcy.Osu.Models { public record OsuScore : Score, IValidatableObject { - [Range(0, 1)] - public double? Accuracy { get; init; } - [Range(0, int.MaxValue)] public int? Combo { get; init; } [Range(0, int.MaxValue)] - public int? Misses { get; init; } + public int Misses { get; init; } = 0; [Range(0, int.MaxValue)] - public int? Mehs { get; init; } + public int Mehs { get; init; } = 0; [Range(0, int.MaxValue)] - public int? Oks { get; init; } + public int Oks { get; init; } = 0; public IEnumerable Validate(ValidationContext validationContext) { - if (Misses is not null && Combo is null) + if (Misses > 0 && Combo is null) { - yield return new ValidationResult("Combo must be specified if Misses are specified.", [nameof(Combo)]); + yield return new ValidationResult("Combo must be specified if Misses are greater than 0.", [nameof(Combo)]); } } } diff --git a/Difficalcy.Osu/Services/OsuCalculatorService.cs b/Difficalcy.Osu/Services/OsuCalculatorService.cs index e2cfc74..7e84b3e 100644 --- a/Difficalcy.Osu/Services/OsuCalculatorService.cs +++ b/Difficalcy.Osu/Services/OsuCalculatorService.cs @@ -51,7 +51,7 @@ protected override async Task EnsureBeatmap(string beatmapId) protected override (object, string) CalculateDifficultyAttributes(OsuScore score) { var workingBeatmap = getWorkingBeatmap(score.BeatmapId); - var mods = OsuRuleset.ConvertFromLegacyMods((LegacyMods)(score.Mods ?? 0)).ToArray(); + var mods = OsuRuleset.ConvertFromLegacyMods((LegacyMods)score.Mods).ToArray(); var difficultyCalculator = OsuRuleset.CreateDifficultyCalculator(workingBeatmap); var difficultyAttributes = difficultyCalculator.Calculate(mods) as OsuDifficultyAttributes; @@ -95,11 +95,11 @@ protected override object DeserialiseDifficultyAttributes(string difficultyAttri protected override OsuPerformance CalculatePerformance(OsuScore score, object difficultyAttributes) { var workingBeatmap = getWorkingBeatmap(score.BeatmapId); - var mods = OsuRuleset.ConvertFromLegacyMods((LegacyMods)(score.Mods ?? 0)).ToArray(); + var mods = OsuRuleset.ConvertFromLegacyMods((LegacyMods)score.Mods).ToArray(); var beatmap = workingBeatmap.GetPlayableBeatmap(OsuRuleset.RulesetInfo, mods); var combo = score.Combo ?? beatmap.HitObjects.Count + beatmap.HitObjects.OfType().Sum(s => s.NestedHitObjects.Count - 1); - var statistics = determineHitResults(score.Accuracy ?? 1, beatmap.HitObjects.Count, score.Misses ?? 0, score.Mehs, score.Oks); + var statistics = getHitResults(beatmap.HitObjects.Count, score.Misses, score.Mehs, score.Oks); var accuracy = calculateAccuracy(statistics); var scoreInfo = new ScoreInfo(beatmap.BeatmapInfo, OsuRuleset.RulesetInfo) @@ -138,37 +138,15 @@ private CalculatorWorkingBeatmap getWorkingBeatmap(string beatmapId) return new CalculatorWorkingBeatmap(OsuRuleset, beatmapStream, beatmapId); } - private Dictionary determineHitResults(double targetAccuracy, int hitResultCount, int countMiss, int? countMeh, int? countOk) + private Dictionary getHitResults(int hitResultCount, int countMiss, int countMeh, int countOk) { - // Adapted from https://github.com/ppy/osu-tools/blob/cf5410b04f4e2d1ed2c50c7263f98c8fc5f928ab/PerformanceCalculator/Simulate/OsuSimulateCommand.cs#L57-L91 - int countGreat; - - if (countMeh != null || countOk != null) - { - countGreat = hitResultCount - (countOk ?? 0) - (countMeh ?? 0) - countMiss; - } - else - { - // Let Great=6, Ok=2, Meh=1, Miss=0. The total should be this. - var targetTotal = (int)Math.Round(targetAccuracy * hitResultCount * 6); - - // Start by assuming every non miss is a meh - // This is how much increase is needed by greats and oks - var delta = targetTotal - (hitResultCount - countMiss); - - // Each great increases total by 5 (great-meh=5) - countGreat = delta / 5; - // Each ok increases total by 1 (ok-meh=1). Covers remaining difference. - countOk = delta % 5; - // Mehs are left over. Could be negative if impossible value of amountMiss chosen - countMeh = hitResultCount - countGreat - countOk - countMiss; - } + var countGreat = hitResultCount - countOk - countMeh - countMiss; return new Dictionary { { HitResult.Great, countGreat }, - { HitResult.Ok, countOk ?? 0 }, - { HitResult.Meh, countMeh ?? 0 }, + { HitResult.Ok, countOk }, + { HitResult.Meh, countMeh }, { HitResult.Miss, countMiss } }; } diff --git a/Difficalcy.Taiko.Tests/TaikoCalculatorServiceTest.cs b/Difficalcy.Taiko.Tests/TaikoCalculatorServiceTest.cs index 37c81af..5d75e09 100644 --- a/Difficalcy.Taiko.Tests/TaikoCalculatorServiceTest.cs +++ b/Difficalcy.Taiko.Tests/TaikoCalculatorServiceTest.cs @@ -28,18 +28,4 @@ public void TestAllParameters() }; base.TestGetCalculationReturnsCorrectValues(4.0789820318081444d, 176.94088597258678d, score); } - - [Fact] - public void TestAccuracyParameter() - { - var score = new TaikoScore - { - BeatmapId = "diffcalc-test", - Mods = 80, // HR, DT - Accuracy = 0.9675, - Combo = 150, - Misses = 5, - }; - base.TestGetCalculationReturnsCorrectValues(4.0789820318081444d, 176.94088597258678d, score); - } } diff --git a/Difficalcy.Taiko/Models/TaikoScore.cs b/Difficalcy.Taiko/Models/TaikoScore.cs index 4433797..25437a9 100644 --- a/Difficalcy.Taiko/Models/TaikoScore.cs +++ b/Difficalcy.Taiko/Models/TaikoScore.cs @@ -6,23 +6,20 @@ namespace Difficalcy.Taiko.Models { public record TaikoScore : Score, IValidatableObject { - [Range(0, 1)] - public double? Accuracy { get; init; } - [Range(0, int.MaxValue)] public int? Combo { get; init; } [Range(0, int.MaxValue)] - public int? Misses { get; init; } + public int Misses { get; init; } = 0; [Range(0, int.MaxValue)] - public int? Oks { get; init; } + public int Oks { get; init; } = 0; public IEnumerable Validate(ValidationContext validationContext) { - if (Misses is not null && Combo is null) + if (Misses > 0 && Combo is null) { - yield return new ValidationResult("Combo must be specified if Misses are specified.", [nameof(Combo)]); + yield return new ValidationResult("Combo must be specified if Misses are greater than 0.", [nameof(Combo)]); } } } diff --git a/Difficalcy.Taiko/Services/TaikoCalculatorService.cs b/Difficalcy.Taiko/Services/TaikoCalculatorService.cs index a3778cd..dfabf36 100644 --- a/Difficalcy.Taiko/Services/TaikoCalculatorService.cs +++ b/Difficalcy.Taiko/Services/TaikoCalculatorService.cs @@ -51,7 +51,7 @@ protected override async Task EnsureBeatmap(string beatmapId) protected override (object, string) CalculateDifficultyAttributes(TaikoScore score) { var workingBeatmap = getWorkingBeatmap(score.BeatmapId); - var mods = TaikoRuleset.ConvertFromLegacyMods((LegacyMods)(score.Mods ?? 0)).ToArray(); + var mods = TaikoRuleset.ConvertFromLegacyMods((LegacyMods)score.Mods).ToArray(); var difficultyCalculator = TaikoRuleset.CreateDifficultyCalculator(workingBeatmap); var difficultyAttributes = difficultyCalculator.Calculate(mods) as TaikoDifficultyAttributes; @@ -89,12 +89,12 @@ protected override object DeserialiseDifficultyAttributes(string difficultyAttri protected override TaikoPerformance CalculatePerformance(TaikoScore score, object difficultyAttributes) { var workingBeatmap = getWorkingBeatmap(score.BeatmapId); - var mods = TaikoRuleset.ConvertFromLegacyMods((LegacyMods)(score.Mods ?? 0)).ToArray(); + var mods = TaikoRuleset.ConvertFromLegacyMods((LegacyMods)score.Mods).ToArray(); var beatmap = workingBeatmap.GetPlayableBeatmap(TaikoRuleset.RulesetInfo, mods); var hitResultCount = beatmap.HitObjects.OfType().Count(); var combo = score.Combo ?? hitResultCount; - var statistics = determineHitResults(score.Accuracy ?? 1, hitResultCount, score.Misses ?? 0, score.Oks); + var statistics = getHitResults(hitResultCount, score.Misses, score.Oks); var accuracy = calculateAccuracy(statistics); var scoreInfo = new ScoreInfo(beatmap.BeatmapInfo, TaikoRuleset.RulesetInfo) @@ -131,28 +131,14 @@ private CalculatorWorkingBeatmap getWorkingBeatmap(string beatmapId) return new CalculatorWorkingBeatmap(TaikoRuleset, beatmapStream, beatmapId); } - private Dictionary determineHitResults(double targetAccuracy, int hitResultCount, int countMiss, int? countOk) + private Dictionary getHitResults(int hitResultCount, int countMiss, int countOk) { - // Adapted from https://github.com/ppy/osu-tools/blob/cf5410b04f4e2d1ed2c50c7263f98c8fc5f928ab/PerformanceCalculator/Simulate/TaikoSimulateCommand.cs#L53-L79 - int countGreat; - - if (countOk != null) - { - countGreat = (int)(hitResultCount - countOk - countMiss); - } - else - { - // Let Great=2, Good=1, Miss=0. The total should be this. - var targetTotal = (int)Math.Round(targetAccuracy * hitResultCount * 2); - - countGreat = targetTotal - (hitResultCount - countMiss); - countOk = hitResultCount - countGreat - countMiss; - } + var countGreat = hitResultCount - countOk - countMiss; return new Dictionary { { HitResult.Great, countGreat }, - { HitResult.Ok, (int)countOk }, + { HitResult.Ok, countOk }, { HitResult.Meh, 0 }, { HitResult.Miss, countMiss } }; diff --git a/Difficalcy.Tests/DummyCalculatorServiceTest.cs b/Difficalcy.Tests/DummyCalculatorServiceTest.cs index c26bd26..5846f63 100644 --- a/Difficalcy.Tests/DummyCalculatorServiceTest.cs +++ b/Difficalcy.Tests/DummyCalculatorServiceTest.cs @@ -35,7 +35,7 @@ public DummyCalculatorService(ICache cache) : base(cache) protected override (object, string) CalculateDifficultyAttributes(DummyScore score) { - var difficulty = score.Mods / 10.0 ?? 0; + var difficulty = score.Mods / 10.0; return (difficulty, difficulty.ToString()); } diff --git a/Difficalcy/Models/Score.cs b/Difficalcy/Models/Score.cs index 2120600..ef1e203 100644 --- a/Difficalcy/Models/Score.cs +++ b/Difficalcy/Models/Score.cs @@ -8,6 +8,6 @@ public abstract record Score public string BeatmapId { get; init; } [Range(0, int.MaxValue)] - public int? Mods { get; init; } + public int Mods { get; init; } = 0; } } diff --git a/Difficalcy/Services/CalculatorService.cs b/Difficalcy/Services/CalculatorService.cs index c7c8be7..6e00ba8 100644 --- a/Difficalcy/Services/CalculatorService.cs +++ b/Difficalcy/Services/CalculatorService.cs @@ -91,7 +91,7 @@ private async Task GetDifficultyAttributes(TScore score) await EnsureBeatmap(score.BeatmapId); var db = _cache.GetDatabase(); - var redisKey = $"difficalcy:{CalculatorDiscriminator}:{score.BeatmapId}:{score.Mods ?? 0}"; + var redisKey = $"difficalcy:{CalculatorDiscriminator}:{score.BeatmapId}:{score.Mods}"; var difficultyAttributesJson = await db.GetAsync(redisKey); object difficultyAttributes; diff --git a/docs/docs/api-reference/difficalcy-catch.json b/docs/docs/api-reference/difficalcy-catch.json index 67a5714..5ac4bbf 100644 --- a/docs/docs/api-reference/difficalcy-catch.json +++ b/docs/docs/api-reference/difficalcy-catch.json @@ -30,19 +30,12 @@ "CatchCalculator" ], "parameters": [ - { - "name": "Accuracy", - "in": "query", - "schema": { - "type": "number", - "format": "double", - "nullable": true - } - }, { "name": "Combo", "in": "query", "schema": { + "maximum": 2147483647, + "minimum": 0, "type": "integer", "format": "int32", "nullable": true @@ -52,24 +45,29 @@ "name": "Misses", "in": "query", "schema": { + "maximum": 2147483647, + "minimum": 0, "type": "integer", - "format": "int32", - "nullable": true + "format": "int32" } }, { - "name": "TinyDroplets", + "name": "SmallDroplets", "in": "query", "schema": { + "maximum": 2147483647, + "minimum": 0, "type": "integer", "format": "int32", "nullable": true } }, { - "name": "Droplets", + "name": "LargeDroplets", "in": "query", "schema": { + "maximum": 2147483647, + "minimum": 0, "type": "integer", "format": "int32", "nullable": true @@ -87,9 +85,10 @@ "name": "Mods", "in": "query", "schema": { + "maximum": 2147483647, + "minimum": 0, "type": "integer", - "format": "int32", - "nullable": true + "format": "int32" } } ], @@ -113,19 +112,12 @@ "CatchCalculator" ], "parameters": [ - { - "name": "Accuracy", - "in": "query", - "schema": { - "type": "number", - "format": "double", - "nullable": true - } - }, { "name": "Combo", "in": "query", "schema": { + "maximum": 2147483647, + "minimum": 0, "type": "integer", "format": "int32", "nullable": true @@ -135,24 +127,29 @@ "name": "Misses", "in": "query", "schema": { + "maximum": 2147483647, + "minimum": 0, "type": "integer", - "format": "int32", - "nullable": true + "format": "int32" } }, { - "name": "TinyDroplets", + "name": "SmallDroplets", "in": "query", "schema": { + "maximum": 2147483647, + "minimum": 0, "type": "integer", "format": "int32", "nullable": true } }, { - "name": "Droplets", + "name": "LargeDroplets", "in": "query", "schema": { + "maximum": 2147483647, + "minimum": 0, "type": "integer", "format": "int32", "nullable": true @@ -170,9 +167,10 @@ "name": "Mods", "in": "query", "schema": { + "maximum": 2147483647, + "minimum": 0, "type": "integer", - "format": "int32", - "nullable": true + "format": "int32" } } ], @@ -196,19 +194,12 @@ "CatchCalculator" ], "parameters": [ - { - "name": "Accuracy", - "in": "query", - "schema": { - "type": "number", - "format": "double", - "nullable": true - } - }, { "name": "Combo", "in": "query", "schema": { + "maximum": 2147483647, + "minimum": 0, "type": "integer", "format": "int32", "nullable": true @@ -218,24 +209,29 @@ "name": "Misses", "in": "query", "schema": { + "maximum": 2147483647, + "minimum": 0, "type": "integer", - "format": "int32", - "nullable": true + "format": "int32" } }, { - "name": "TinyDroplets", + "name": "SmallDroplets", "in": "query", "schema": { + "maximum": 2147483647, + "minimum": 0, "type": "integer", "format": "int32", "nullable": true } }, { - "name": "Droplets", + "name": "LargeDroplets", "in": "query", "schema": { + "maximum": 2147483647, + "minimum": 0, "type": "integer", "format": "int32", "nullable": true @@ -253,9 +249,10 @@ "name": "Mods", "in": "query", "schema": { + "maximum": 2147483647, + "minimum": 0, "type": "integer", - "format": "int32", - "nullable": true + "format": "int32" } } ], @@ -449,31 +446,34 @@ "type": "string" }, "mods": { + "maximum": 2147483647, + "minimum": 0, "type": "integer", - "format": "int32", - "nullable": true - }, - "accuracy": { - "type": "number", - "format": "double", - "nullable": true + "format": "int32" }, "combo": { + "maximum": 2147483647, + "minimum": 0, "type": "integer", "format": "int32", "nullable": true }, "misses": { + "maximum": 2147483647, + "minimum": 0, "type": "integer", - "format": "int32", - "nullable": true + "format": "int32" }, - "tinyDroplets": { + "smallDroplets": { + "maximum": 2147483647, + "minimum": 0, "type": "integer", "format": "int32", "nullable": true }, - "droplets": { + "largeDroplets": { + "maximum": 2147483647, + "minimum": 0, "type": "integer", "format": "int32", "nullable": true @@ -483,4 +483,4 @@ } } } -} +} \ No newline at end of file diff --git a/docs/docs/api-reference/difficalcy-mania.json b/docs/docs/api-reference/difficalcy-mania.json index 7e6f900..e300850 100644 --- a/docs/docs/api-reference/difficalcy-mania.json +++ b/docs/docs/api-reference/difficalcy-mania.json @@ -30,58 +30,54 @@ "ManiaCalculator" ], "parameters": [ - { - "name": "Accuracy", - "in": "query", - "schema": { - "type": "number", - "format": "double", - "nullable": true - } - }, { "name": "Misses", "in": "query", "schema": { + "maximum": 2147483647, + "minimum": 0, "type": "integer", - "format": "int32", - "nullable": true + "format": "int32" } }, { "name": "Mehs", "in": "query", "schema": { + "maximum": 2147483647, + "minimum": 0, "type": "integer", - "format": "int32", - "nullable": true + "format": "int32" } }, { "name": "Oks", "in": "query", "schema": { + "maximum": 2147483647, + "minimum": 0, "type": "integer", - "format": "int32", - "nullable": true + "format": "int32" } }, { "name": "Goods", "in": "query", "schema": { + "maximum": 2147483647, + "minimum": 0, "type": "integer", - "format": "int32", - "nullable": true + "format": "int32" } }, { "name": "Greats", "in": "query", "schema": { + "maximum": 2147483647, + "minimum": 0, "type": "integer", - "format": "int32", - "nullable": true + "format": "int32" } }, { @@ -96,9 +92,10 @@ "name": "Mods", "in": "query", "schema": { + "maximum": 2147483647, + "minimum": 0, "type": "integer", - "format": "int32", - "nullable": true + "format": "int32" } } ], @@ -122,58 +119,54 @@ "ManiaCalculator" ], "parameters": [ - { - "name": "Accuracy", - "in": "query", - "schema": { - "type": "number", - "format": "double", - "nullable": true - } - }, { "name": "Misses", "in": "query", "schema": { + "maximum": 2147483647, + "minimum": 0, "type": "integer", - "format": "int32", - "nullable": true + "format": "int32" } }, { "name": "Mehs", "in": "query", "schema": { + "maximum": 2147483647, + "minimum": 0, "type": "integer", - "format": "int32", - "nullable": true + "format": "int32" } }, { "name": "Oks", "in": "query", "schema": { + "maximum": 2147483647, + "minimum": 0, "type": "integer", - "format": "int32", - "nullable": true + "format": "int32" } }, { "name": "Goods", "in": "query", "schema": { + "maximum": 2147483647, + "minimum": 0, "type": "integer", - "format": "int32", - "nullable": true + "format": "int32" } }, { "name": "Greats", "in": "query", "schema": { + "maximum": 2147483647, + "minimum": 0, "type": "integer", - "format": "int32", - "nullable": true + "format": "int32" } }, { @@ -188,9 +181,10 @@ "name": "Mods", "in": "query", "schema": { + "maximum": 2147483647, + "minimum": 0, "type": "integer", - "format": "int32", - "nullable": true + "format": "int32" } } ], @@ -214,58 +208,54 @@ "ManiaCalculator" ], "parameters": [ - { - "name": "Accuracy", - "in": "query", - "schema": { - "type": "number", - "format": "double", - "nullable": true - } - }, { "name": "Misses", "in": "query", "schema": { + "maximum": 2147483647, + "minimum": 0, "type": "integer", - "format": "int32", - "nullable": true + "format": "int32" } }, { "name": "Mehs", "in": "query", "schema": { + "maximum": 2147483647, + "minimum": 0, "type": "integer", - "format": "int32", - "nullable": true + "format": "int32" } }, { "name": "Oks", "in": "query", "schema": { + "maximum": 2147483647, + "minimum": 0, "type": "integer", - "format": "int32", - "nullable": true + "format": "int32" } }, { "name": "Goods", "in": "query", "schema": { + "maximum": 2147483647, + "minimum": 0, "type": "integer", - "format": "int32", - "nullable": true + "format": "int32" } }, { "name": "Greats", "in": "query", "schema": { + "maximum": 2147483647, + "minimum": 0, "type": "integer", - "format": "int32", - "nullable": true + "format": "int32" } }, { @@ -280,9 +270,10 @@ "name": "Mods", "in": "query", "schema": { + "maximum": 2147483647, + "minimum": 0, "type": "integer", - "format": "int32", - "nullable": true + "format": "int32" } } ], @@ -480,39 +471,40 @@ "type": "string" }, "mods": { + "maximum": 2147483647, + "minimum": 0, "type": "integer", - "format": "int32", - "nullable": true - }, - "accuracy": { - "type": "number", - "format": "double", - "nullable": true + "format": "int32" }, "misses": { + "maximum": 2147483647, + "minimum": 0, "type": "integer", - "format": "int32", - "nullable": true + "format": "int32" }, "mehs": { + "maximum": 2147483647, + "minimum": 0, "type": "integer", - "format": "int32", - "nullable": true + "format": "int32" }, "oks": { + "maximum": 2147483647, + "minimum": 0, "type": "integer", - "format": "int32", - "nullable": true + "format": "int32" }, "goods": { + "maximum": 2147483647, + "minimum": 0, "type": "integer", - "format": "int32", - "nullable": true + "format": "int32" }, "greats": { + "maximum": 2147483647, + "minimum": 0, "type": "integer", - "format": "int32", - "nullable": true + "format": "int32" } }, "additionalProperties": false diff --git a/docs/docs/api-reference/difficalcy-osu.json b/docs/docs/api-reference/difficalcy-osu.json index c28cf6d..2b7d85d 100644 --- a/docs/docs/api-reference/difficalcy-osu.json +++ b/docs/docs/api-reference/difficalcy-osu.json @@ -30,19 +30,12 @@ "OsuCalculator" ], "parameters": [ - { - "name": "Accuracy", - "in": "query", - "schema": { - "type": "number", - "format": "double", - "nullable": true - } - }, { "name": "Combo", "in": "query", "schema": { + "maximum": 2147483647, + "minimum": 0, "type": "integer", "format": "int32", "nullable": true @@ -52,27 +45,30 @@ "name": "Misses", "in": "query", "schema": { + "maximum": 2147483647, + "minimum": 0, "type": "integer", - "format": "int32", - "nullable": true + "format": "int32" } }, { "name": "Mehs", "in": "query", "schema": { + "maximum": 2147483647, + "minimum": 0, "type": "integer", - "format": "int32", - "nullable": true + "format": "int32" } }, { "name": "Oks", "in": "query", "schema": { + "maximum": 2147483647, + "minimum": 0, "type": "integer", - "format": "int32", - "nullable": true + "format": "int32" } }, { @@ -87,9 +83,10 @@ "name": "Mods", "in": "query", "schema": { + "maximum": 2147483647, + "minimum": 0, "type": "integer", - "format": "int32", - "nullable": true + "format": "int32" } } ], @@ -113,19 +110,12 @@ "OsuCalculator" ], "parameters": [ - { - "name": "Accuracy", - "in": "query", - "schema": { - "type": "number", - "format": "double", - "nullable": true - } - }, { "name": "Combo", "in": "query", "schema": { + "maximum": 2147483647, + "minimum": 0, "type": "integer", "format": "int32", "nullable": true @@ -135,27 +125,30 @@ "name": "Misses", "in": "query", "schema": { + "maximum": 2147483647, + "minimum": 0, "type": "integer", - "format": "int32", - "nullable": true + "format": "int32" } }, { "name": "Mehs", "in": "query", "schema": { + "maximum": 2147483647, + "minimum": 0, "type": "integer", - "format": "int32", - "nullable": true + "format": "int32" } }, { "name": "Oks", "in": "query", "schema": { + "maximum": 2147483647, + "minimum": 0, "type": "integer", - "format": "int32", - "nullable": true + "format": "int32" } }, { @@ -170,9 +163,10 @@ "name": "Mods", "in": "query", "schema": { + "maximum": 2147483647, + "minimum": 0, "type": "integer", - "format": "int32", - "nullable": true + "format": "int32" } } ], @@ -196,19 +190,12 @@ "OsuCalculator" ], "parameters": [ - { - "name": "Accuracy", - "in": "query", - "schema": { - "type": "number", - "format": "double", - "nullable": true - } - }, { "name": "Combo", "in": "query", "schema": { + "maximum": 2147483647, + "minimum": 0, "type": "integer", "format": "int32", "nullable": true @@ -218,27 +205,30 @@ "name": "Misses", "in": "query", "schema": { + "maximum": 2147483647, + "minimum": 0, "type": "integer", - "format": "int32", - "nullable": true + "format": "int32" } }, { "name": "Mehs", "in": "query", "schema": { + "maximum": 2147483647, + "minimum": 0, "type": "integer", - "format": "int32", - "nullable": true + "format": "int32" } }, { "name": "Oks", "in": "query", "schema": { + "maximum": 2147483647, + "minimum": 0, "type": "integer", - "format": "int32", - "nullable": true + "format": "int32" } }, { @@ -253,9 +243,10 @@ "name": "Mods", "in": "query", "schema": { + "maximum": 2147483647, + "minimum": 0, "type": "integer", - "format": "int32", - "nullable": true + "format": "int32" } } ], @@ -477,34 +468,35 @@ "type": "string" }, "mods": { + "maximum": 2147483647, + "minimum": 0, "type": "integer", - "format": "int32", - "nullable": true - }, - "accuracy": { - "type": "number", - "format": "double", - "nullable": true + "format": "int32" }, "combo": { + "maximum": 2147483647, + "minimum": 0, "type": "integer", "format": "int32", "nullable": true }, "misses": { + "maximum": 2147483647, + "minimum": 0, "type": "integer", - "format": "int32", - "nullable": true + "format": "int32" }, "mehs": { + "maximum": 2147483647, + "minimum": 0, "type": "integer", - "format": "int32", - "nullable": true + "format": "int32" }, "oks": { + "maximum": 2147483647, + "minimum": 0, "type": "integer", - "format": "int32", - "nullable": true + "format": "int32" } }, "additionalProperties": false diff --git a/docs/docs/api-reference/difficalcy-taiko.json b/docs/docs/api-reference/difficalcy-taiko.json index 052a6d3..7613732 100644 --- a/docs/docs/api-reference/difficalcy-taiko.json +++ b/docs/docs/api-reference/difficalcy-taiko.json @@ -30,19 +30,12 @@ "TaikoCalculator" ], "parameters": [ - { - "name": "Accuracy", - "in": "query", - "schema": { - "type": "number", - "format": "double", - "nullable": true - } - }, { "name": "Combo", "in": "query", "schema": { + "maximum": 2147483647, + "minimum": 0, "type": "integer", "format": "int32", "nullable": true @@ -52,18 +45,20 @@ "name": "Misses", "in": "query", "schema": { + "maximum": 2147483647, + "minimum": 0, "type": "integer", - "format": "int32", - "nullable": true + "format": "int32" } }, { "name": "Oks", "in": "query", "schema": { + "maximum": 2147483647, + "minimum": 0, "type": "integer", - "format": "int32", - "nullable": true + "format": "int32" } }, { @@ -78,9 +73,10 @@ "name": "Mods", "in": "query", "schema": { + "maximum": 2147483647, + "minimum": 0, "type": "integer", - "format": "int32", - "nullable": true + "format": "int32" } } ], @@ -104,19 +100,12 @@ "TaikoCalculator" ], "parameters": [ - { - "name": "Accuracy", - "in": "query", - "schema": { - "type": "number", - "format": "double", - "nullable": true - } - }, { "name": "Combo", "in": "query", "schema": { + "maximum": 2147483647, + "minimum": 0, "type": "integer", "format": "int32", "nullable": true @@ -126,18 +115,20 @@ "name": "Misses", "in": "query", "schema": { + "maximum": 2147483647, + "minimum": 0, "type": "integer", - "format": "int32", - "nullable": true + "format": "int32" } }, { "name": "Oks", "in": "query", "schema": { + "maximum": 2147483647, + "minimum": 0, "type": "integer", - "format": "int32", - "nullable": true + "format": "int32" } }, { @@ -152,9 +143,10 @@ "name": "Mods", "in": "query", "schema": { + "maximum": 2147483647, + "minimum": 0, "type": "integer", - "format": "int32", - "nullable": true + "format": "int32" } } ], @@ -178,19 +170,12 @@ "TaikoCalculator" ], "parameters": [ - { - "name": "Accuracy", - "in": "query", - "schema": { - "type": "number", - "format": "double", - "nullable": true - } - }, { "name": "Combo", "in": "query", "schema": { + "maximum": 2147483647, + "minimum": 0, "type": "integer", "format": "int32", "nullable": true @@ -200,18 +185,20 @@ "name": "Misses", "in": "query", "schema": { + "maximum": 2147483647, + "minimum": 0, "type": "integer", - "format": "int32", - "nullable": true + "format": "int32" } }, { "name": "Oks", "in": "query", "schema": { + "maximum": 2147483647, + "minimum": 0, "type": "integer", - "format": "int32", - "nullable": true + "format": "int32" } }, { @@ -226,9 +213,10 @@ "name": "Mods", "in": "query", "schema": { + "maximum": 2147483647, + "minimum": 0, "type": "integer", - "format": "int32", - "nullable": true + "format": "int32" } } ], @@ -442,29 +430,29 @@ "type": "string" }, "mods": { + "maximum": 2147483647, + "minimum": 0, "type": "integer", - "format": "int32", - "nullable": true - }, - "accuracy": { - "type": "number", - "format": "double", - "nullable": true + "format": "int32" }, "combo": { + "maximum": 2147483647, + "minimum": 0, "type": "integer", "format": "int32", "nullable": true }, "misses": { + "maximum": 2147483647, + "minimum": 0, "type": "integer", - "format": "int32", - "nullable": true + "format": "int32" }, "oks": { + "maximum": 2147483647, + "minimum": 0, "type": "integer", - "format": "int32", - "nullable": true + "format": "int32" } }, "additionalProperties": false From 32c804fff65bc6585816ea2108b86130c2a4b444 Mon Sep 17 00:00:00 2001 From: Samuel Cattini-Schultz Date: Mon, 29 Apr 2024 23:13:12 +1000 Subject: [PATCH 3/6] Remove /difficulty and /performance The only benefit of /performance over /calculation is the tiny bit of saved serialisation. Not worth the extra api and code complexity. The only benefit of /difficulty over /calculation is avoiding the performance calculation, but performance calc is over 1000x faster than difficulty calculation. The only tangible benefit is when the difficulties have already been calculated and are in the cache, but I still don't think its worth the complexity of the extra api. Can add back later if requested. --- .../Services/CatchCalculatorService.cs | 43 +++++++------- .../Services/ManiaCalculatorService.cs | 45 +++++++------- .../Services/OsuCalculatorService.cs | 58 +++++++++---------- .../Services/TaikoCalculatorService.cs | 53 ++++++++--------- .../DummyCalculatorServiceTest.cs | 21 ++----- .../Controllers/CalculatorController.cs | 38 ------------ Difficalcy/Services/CalculatorService.cs | 36 +----------- 7 files changed, 109 insertions(+), 185 deletions(-) diff --git a/Difficalcy.Catch/Services/CatchCalculatorService.cs b/Difficalcy.Catch/Services/CatchCalculatorService.cs index c961b21..389025f 100644 --- a/Difficalcy.Catch/Services/CatchCalculatorService.cs +++ b/Difficalcy.Catch/Services/CatchCalculatorService.cs @@ -66,22 +66,15 @@ protected override (object, string) CalculateDifficultyAttributes(CatchScore sco })); } - protected override CatchDifficulty GetDifficultyFromDifficultyAttributes(object difficultyAttributes) - { - var catchDifficultyAttributes = (CatchDifficultyAttributes)difficultyAttributes; - return new CatchDifficulty() - { - Total = catchDifficultyAttributes.StarRating - }; - } - protected override object DeserialiseDifficultyAttributes(string difficultyAttributesJson) { return JsonSerializer.Deserialize(difficultyAttributesJson); } - protected override CatchPerformance CalculatePerformance(CatchScore score, object difficultyAttributes) + protected override CatchCalculation CalculatePerformance(CatchScore score, object difficultyAttributes) { + var catchDifficultyAttributes = (CatchDifficultyAttributes)difficultyAttributes; + var workingBeatmap = getWorkingBeatmap(score.BeatmapId); var mods = CatchRuleset.ConvertFromLegacyMods((LegacyMods)score.Mods).ToArray(); var beatmap = workingBeatmap.GetPlayableBeatmap(CatchRuleset.RulesetInfo, mods); @@ -99,20 +92,12 @@ protected override CatchPerformance CalculatePerformance(CatchScore score, objec }; var performanceCalculator = CatchRuleset.CreatePerformanceCalculator(); - var performanceAttributes = performanceCalculator.Calculate(scoreInfo, (CatchDifficultyAttributes)difficultyAttributes) as CatchPerformanceAttributes; - - return new CatchPerformance() - { - Total = performanceAttributes.Total - }; - } + var performanceAttributes = performanceCalculator.Calculate(scoreInfo, catchDifficultyAttributes) as CatchPerformanceAttributes; - protected override CatchCalculation GetCalculation(CatchDifficulty difficulty, CatchPerformance performance) - { return new CatchCalculation() { - Difficulty = difficulty, - Performance = performance + Difficulty = GetDifficultyFromDifficultyAttributes(catchDifficultyAttributes), + Performance = GetPerformanceFromPerformanceAttributes(performanceAttributes) }; } @@ -155,5 +140,21 @@ private double calculateAccuracy(Dictionary statistics) return hits / total; } + + private CatchDifficulty GetDifficultyFromDifficultyAttributes(CatchDifficultyAttributes difficultyAttributes) + { + return new CatchDifficulty() + { + Total = difficultyAttributes.StarRating + }; + } + + private CatchPerformance GetPerformanceFromPerformanceAttributes(CatchPerformanceAttributes performanceAttributes) + { + return new CatchPerformance() + { + Total = performanceAttributes.Total + }; + } } } diff --git a/Difficalcy.Mania/Services/ManiaCalculatorService.cs b/Difficalcy.Mania/Services/ManiaCalculatorService.cs index 664a461..0b27e9a 100644 --- a/Difficalcy.Mania/Services/ManiaCalculatorService.cs +++ b/Difficalcy.Mania/Services/ManiaCalculatorService.cs @@ -11,7 +11,6 @@ using osu.Game.Rulesets.Mania; using osu.Game.Rulesets.Mania.Difficulty; using osu.Game.Rulesets.Mania.Objects; -using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Scoring; using osu.Game.Scoring; @@ -66,22 +65,14 @@ protected override (object, string) CalculateDifficultyAttributes(ManiaScore sco })); } - protected override ManiaDifficulty GetDifficultyFromDifficultyAttributes(object difficultyAttributes) - { - var maniaDifficultyAttributes = (ManiaDifficultyAttributes)difficultyAttributes; - return new ManiaDifficulty() - { - Total = maniaDifficultyAttributes.StarRating - }; - } - protected override object DeserialiseDifficultyAttributes(string difficultyAttributesJson) { return JsonSerializer.Deserialize(difficultyAttributesJson); } - protected override ManiaPerformance CalculatePerformance(ManiaScore score, object difficultyAttributes) + protected override ManiaCalculation CalculatePerformance(ManiaScore score, object difficultyAttributes) { + var maniaDifficultyAttributes = (ManiaDifficultyAttributes)difficultyAttributes; var workingBeatmap = getWorkingBeatmap(score.BeatmapId); var mods = ManiaRuleset.ConvertFromLegacyMods((LegacyMods)score.Mods).ToArray(); var beatmap = workingBeatmap.GetPlayableBeatmap(ManiaRuleset.RulesetInfo, mods); @@ -100,21 +91,12 @@ protected override ManiaPerformance CalculatePerformance(ManiaScore score, objec }; var performanceCalculator = ManiaRuleset.CreatePerformanceCalculator(); - var performanceAttributes = performanceCalculator.Calculate(scoreInfo, (ManiaDifficultyAttributes)difficultyAttributes) as ManiaPerformanceAttributes; - - return new ManiaPerformance() - { - Total = performanceAttributes.Total, - Difficulty = performanceAttributes.Difficulty - }; - } + var performanceAttributes = performanceCalculator.Calculate(scoreInfo, maniaDifficultyAttributes) as ManiaPerformanceAttributes; - protected override ManiaCalculation GetCalculation(ManiaDifficulty difficulty, ManiaPerformance performance) - { return new ManiaCalculation() { - Difficulty = difficulty, - Performance = performance + Difficulty = GetDifficultyFromDifficultyAttributes(maniaDifficultyAttributes), + Performance = GetPerformanceFromPerformanceAttributes(performanceAttributes) }; } @@ -151,5 +133,22 @@ private double calculateAccuracy(Dictionary statistics) return (double)((6 * countPerfect) + (6 * countGreat) + (4 * countGood) + (2 * countOk) + countMeh) / (6 * total); } + + private ManiaDifficulty GetDifficultyFromDifficultyAttributes(ManiaDifficultyAttributes difficultyAttributes) + { + return new ManiaDifficulty() + { + Total = difficultyAttributes.StarRating + }; + } + + private ManiaPerformance GetPerformanceFromPerformanceAttributes(ManiaPerformanceAttributes performanceAttributes) + { + return new ManiaPerformance() + { + Total = performanceAttributes.Total, + Difficulty = performanceAttributes.Difficulty + }; + } } } diff --git a/Difficalcy.Osu/Services/OsuCalculatorService.cs b/Difficalcy.Osu/Services/OsuCalculatorService.cs index 7e84b3e..5cb2148 100644 --- a/Difficalcy.Osu/Services/OsuCalculatorService.cs +++ b/Difficalcy.Osu/Services/OsuCalculatorService.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Linq; using System.Reflection; @@ -75,25 +74,15 @@ protected override (object, string) CalculateDifficultyAttributes(OsuScore score })); } - protected override OsuDifficulty GetDifficultyFromDifficultyAttributes(object difficultyAttributes) - { - var osuDifficultyAttributes = (OsuDifficultyAttributes)difficultyAttributes; - return new OsuDifficulty() - { - Total = osuDifficultyAttributes.StarRating, - Aim = osuDifficultyAttributes.AimDifficulty, - Speed = osuDifficultyAttributes.SpeedDifficulty, - Flashlight = osuDifficultyAttributes.FlashlightDifficulty - }; - } - protected override object DeserialiseDifficultyAttributes(string difficultyAttributesJson) { return JsonSerializer.Deserialize(difficultyAttributesJson); } - protected override OsuPerformance CalculatePerformance(OsuScore score, object difficultyAttributes) + protected override OsuCalculation CalculatePerformance(OsuScore score, object difficultyAttributes) { + var osuDifficultyAttributes = (OsuDifficultyAttributes)difficultyAttributes; + var workingBeatmap = getWorkingBeatmap(score.BeatmapId); var mods = OsuRuleset.ConvertFromLegacyMods((LegacyMods)score.Mods).ToArray(); var beatmap = workingBeatmap.GetPlayableBeatmap(OsuRuleset.RulesetInfo, mods); @@ -111,24 +100,12 @@ protected override OsuPerformance CalculatePerformance(OsuScore score, object di }; var performanceCalculator = OsuRuleset.CreatePerformanceCalculator(); - var performanceAttributes = performanceCalculator.Calculate(scoreInfo, (OsuDifficultyAttributes)difficultyAttributes) as OsuPerformanceAttributes; - - return new OsuPerformance() - { - Total = performanceAttributes.Total, - Aim = performanceAttributes.Aim, - Speed = performanceAttributes.Speed, - Accuracy = performanceAttributes.Accuracy, - Flashlight = performanceAttributes.Flashlight - }; - } + var performanceAttributes = performanceCalculator.Calculate(scoreInfo, osuDifficultyAttributes) as OsuPerformanceAttributes; - protected override OsuCalculation GetCalculation(OsuDifficulty difficulty, OsuPerformance performance) - { return new OsuCalculation() { - Difficulty = difficulty, - Performance = performance + Difficulty = GetDifficultyFromDifficultyAttributes(osuDifficultyAttributes), + Performance = GetPerformanceFromPerformanceAttributes(performanceAttributes) }; } @@ -161,5 +138,28 @@ private double calculateAccuracy(Dictionary statistics) return (double)((6 * countGreat) + (2 * countOk) + countMeh) / (6 * total); } + + private OsuDifficulty GetDifficultyFromDifficultyAttributes(OsuDifficultyAttributes difficultyAttributes) + { + return new OsuDifficulty() + { + Total = difficultyAttributes.StarRating, + Aim = difficultyAttributes.AimDifficulty, + Speed = difficultyAttributes.SpeedDifficulty, + Flashlight = difficultyAttributes.FlashlightDifficulty + }; + } + + private OsuPerformance GetPerformanceFromPerformanceAttributes(OsuPerformanceAttributes performanceAttributes) + { + return new OsuPerformance() + { + Total = performanceAttributes.Total, + Aim = performanceAttributes.Aim, + Speed = performanceAttributes.Speed, + Accuracy = performanceAttributes.Accuracy, + Flashlight = performanceAttributes.Flashlight + }; + } } } diff --git a/Difficalcy.Taiko/Services/TaikoCalculatorService.cs b/Difficalcy.Taiko/Services/TaikoCalculatorService.cs index dfabf36..27d3c1d 100644 --- a/Difficalcy.Taiko/Services/TaikoCalculatorService.cs +++ b/Difficalcy.Taiko/Services/TaikoCalculatorService.cs @@ -69,25 +69,15 @@ protected override (object, string) CalculateDifficultyAttributes(TaikoScore sco })); } - protected override TaikoDifficulty GetDifficultyFromDifficultyAttributes(object difficultyAttributes) - { - var taikoDifficultyAttributes = (TaikoDifficultyAttributes)difficultyAttributes; - return new TaikoDifficulty() - { - Total = taikoDifficultyAttributes.StarRating, - Stamina = taikoDifficultyAttributes.StaminaDifficulty, - Rhythm = taikoDifficultyAttributes.RhythmDifficulty, - Colour = taikoDifficultyAttributes.ColourDifficulty - }; - } - protected override object DeserialiseDifficultyAttributes(string difficultyAttributesJson) { return JsonSerializer.Deserialize(difficultyAttributesJson); } - protected override TaikoPerformance CalculatePerformance(TaikoScore score, object difficultyAttributes) + protected override TaikoCalculation CalculatePerformance(TaikoScore score, object difficultyAttributes) { + var taikoDifficultyAttributes = (TaikoDifficultyAttributes)difficultyAttributes; + var workingBeatmap = getWorkingBeatmap(score.BeatmapId); var mods = TaikoRuleset.ConvertFromLegacyMods((LegacyMods)score.Mods).ToArray(); var beatmap = workingBeatmap.GetPlayableBeatmap(TaikoRuleset.RulesetInfo, mods); @@ -106,22 +96,12 @@ protected override TaikoPerformance CalculatePerformance(TaikoScore score, objec }; var performanceCalculator = TaikoRuleset.CreatePerformanceCalculator(); - var performanceAttributes = performanceCalculator.Calculate(scoreInfo, (TaikoDifficultyAttributes)difficultyAttributes) as TaikoPerformanceAttributes; - - return new TaikoPerformance() - { - Total = performanceAttributes.Total, - Difficulty = performanceAttributes.Difficulty, - Accuracy = performanceAttributes.Accuracy - }; - } + var performanceAttributes = performanceCalculator.Calculate(scoreInfo, taikoDifficultyAttributes) as TaikoPerformanceAttributes; - protected override TaikoCalculation GetCalculation(TaikoDifficulty difficulty, TaikoPerformance performance) - { return new TaikoCalculation() { - Difficulty = difficulty, - Performance = performance + Difficulty = GetDifficultyFromDifficultyAttributes(taikoDifficultyAttributes), + Performance = GetPerformanceFromPerformanceAttributes(performanceAttributes) }; } @@ -153,5 +133,26 @@ private double calculateAccuracy(Dictionary statistics) return (double)((2 * countGreat) + countOk) / (2 * total); } + + private TaikoDifficulty GetDifficultyFromDifficultyAttributes(TaikoDifficultyAttributes difficultyAttributes) + { + return new TaikoDifficulty() + { + Total = difficultyAttributes.StarRating, + Stamina = difficultyAttributes.StaminaDifficulty, + Rhythm = difficultyAttributes.RhythmDifficulty, + Colour = difficultyAttributes.ColourDifficulty + }; + } + + private TaikoPerformance GetPerformanceFromPerformanceAttributes(TaikoPerformanceAttributes performanceAttributes) + { + return new TaikoPerformance() + { + Total = performanceAttributes.Total, + Difficulty = performanceAttributes.Difficulty, + Accuracy = performanceAttributes.Accuracy + }; + } } } diff --git a/Difficalcy.Tests/DummyCalculatorServiceTest.cs b/Difficalcy.Tests/DummyCalculatorServiceTest.cs index 5846f63..dc7fc8d 100644 --- a/Difficalcy.Tests/DummyCalculatorServiceTest.cs +++ b/Difficalcy.Tests/DummyCalculatorServiceTest.cs @@ -39,27 +39,18 @@ protected override (object, string) CalculateDifficultyAttributes(DummyScore sco return (difficulty, difficulty.ToString()); } - protected override DummyPerformance CalculatePerformance(DummyScore score, object difficultyAttributes) => - new DummyPerformance { Total = (double)difficultyAttributes * 100 }; + protected override DummyCalculation CalculatePerformance(DummyScore score, object difficultyAttributes) => + new DummyCalculation() + { + Difficulty = new DummyDifficulty() { Total = (double)difficultyAttributes }, + Performance = new DummyPerformance() { Total = (double)difficultyAttributes * 100 } + }; protected override object DeserialiseDifficultyAttributes(string difficultyAttributesJson) => double.Parse(difficultyAttributesJson); protected override Task EnsureBeatmap(string beatmapId) => Task.FromResult(true); - - protected override DummyCalculation GetCalculation(DummyDifficulty difficulty, DummyPerformance performance) => - new DummyCalculation - { - Difficulty = difficulty, - Performance = performance - }; - - protected override DummyDifficulty GetDifficultyFromDifficultyAttributes(object difficultyAttributes) => - new DummyDifficulty - { - Total = (double)difficultyAttributes - }; } public record DummyScore : Score { } diff --git a/Difficalcy/Controllers/CalculatorController.cs b/Difficalcy/Controllers/CalculatorController.cs index 4b97c90..2f1f001 100644 --- a/Difficalcy/Controllers/CalculatorController.cs +++ b/Difficalcy/Controllers/CalculatorController.cs @@ -32,24 +32,6 @@ public ActionResult GetInfo() return Ok(calculatorService.Info); } - /// - /// Returns difficulty values for a score. - /// - [HttpGet("difficulty")] - public async Task> GetDifficulty([FromQuery] TScore score) - { - return Ok(await calculatorService.GetDifficulty(score)); - } - - /// - /// Returns performance values for a score. - /// - [HttpGet("performance")] - public async Task> GetPerformance([FromQuery] TScore score) - { - return Ok(await calculatorService.GetPerformance(score)); - } - /// /// Returns difficulty and performance values for a score. /// @@ -59,26 +41,6 @@ public async Task> GetCalculation([FromQuery] TScore return Ok(await calculatorService.GetCalculation(score)); } - /// - /// Returns difficulty values for a batch of scores. - /// - [HttpPost("batch/difficulty")] - [Consumes("application/json")] - public async Task> GetDifficultyBatch([FromBody] TScore[] scores) - { - return Ok(await Task.WhenAll(scores.Select(score => calculatorService.GetDifficulty(score)))); - } - - /// - /// Returns performance values for a batch of scores. - /// - [HttpPost("batch/performance")] - [Consumes("application/json")] - public async Task> GetPerformanceBatch([FromBody] TScore[] scores) - { - return Ok(await Task.WhenAll(scores.Select(score => calculatorService.GetPerformance(score)))); - } - /// /// Returns difficulty and performance values for a batch of scores. /// diff --git a/Difficalcy/Services/CalculatorService.cs b/Difficalcy/Services/CalculatorService.cs index 6e00ba8..9528995 100644 --- a/Difficalcy/Services/CalculatorService.cs +++ b/Difficalcy/Services/CalculatorService.cs @@ -37,11 +37,6 @@ public CalculatorService(ICache cache) /// protected abstract (object, string) CalculateDifficultyAttributes(TScore score); - /// - /// Returns the difficulty within a given difficulty attributes object. - /// - protected abstract TDifficulty GetDifficultyFromDifficultyAttributes(object difficultyAttributes); - /// /// Returns the deserialised object for a given JSON serialised difficulty attributes object. /// @@ -50,40 +45,15 @@ public CalculatorService(ICache cache) /// /// Runs the performance calculator on a given score with pre-calculated difficulty attributes and returns the performance. /// - protected abstract TPerformance CalculatePerformance(TScore score, object difficultyAttributes); - - /// - /// Returns a calculation object that contains the passed difficulty and performance. - /// - protected abstract TCalculation GetCalculation(TDifficulty difficulty, TPerformance performance); - - /// - /// Returns the difficulty of a given score. - /// - public async Task GetDifficulty(TScore score) - { - var difficultyAttributes = await GetDifficultyAttributes(score); - return GetDifficultyFromDifficultyAttributes(difficultyAttributes); - } - - /// - /// Returns the performance of a given score. - /// - public async Task GetPerformance(TScore score) - { - var difficultyAttributes = await GetDifficultyAttributes(score); - return CalculatePerformance(score, difficultyAttributes); - } + protected abstract TCalculation CalculatePerformance(TScore score, object difficultyAttributes); /// - /// Returns the difficulty and performance of a given score. + /// Returns the calculation of a given score. /// public async Task GetCalculation(TScore score) { var difficultyAttributes = await GetDifficultyAttributes(score); - var difficulty = GetDifficultyFromDifficultyAttributes(difficultyAttributes); - var performance = CalculatePerformance(score, difficultyAttributes); - return GetCalculation(difficulty, performance); + return CalculatePerformance(score, difficultyAttributes); } private async Task GetDifficultyAttributes(TScore score) From 961d4383c0e1a97a291560801800e79bbb3d2fab Mon Sep 17 00:00:00 2001 From: Samuel Cattini-Schultz Date: Mon, 29 Apr 2024 23:21:56 +1000 Subject: [PATCH 4/6] Add acc and combo to calculation --- Difficalcy.Catch/Models/CatchCalculation.cs | 2 ++ Difficalcy.Catch/Services/CatchCalculatorService.cs | 4 +++- Difficalcy.Mania/Models/ManiaCalculation.cs | 1 + Difficalcy.Mania/Services/ManiaCalculatorService.cs | 3 ++- Difficalcy.Osu/Models/OsuCalculation.cs | 2 ++ Difficalcy.Osu/Services/OsuCalculatorService.cs | 4 +++- Difficalcy.Taiko/Models/TaikoCalculation.cs | 2 ++ Difficalcy.Taiko/Services/TaikoCalculatorService.cs | 4 +++- 8 files changed, 18 insertions(+), 4 deletions(-) diff --git a/Difficalcy.Catch/Models/CatchCalculation.cs b/Difficalcy.Catch/Models/CatchCalculation.cs index 1c65b9c..1520a20 100644 --- a/Difficalcy.Catch/Models/CatchCalculation.cs +++ b/Difficalcy.Catch/Models/CatchCalculation.cs @@ -4,5 +4,7 @@ namespace Difficalcy.Catch.Models { public record CatchCalculation : Calculation { + public double Accuracy { get; init; } + public double Combo { get; init; } } } diff --git a/Difficalcy.Catch/Services/CatchCalculatorService.cs b/Difficalcy.Catch/Services/CatchCalculatorService.cs index 389025f..0bbbd77 100644 --- a/Difficalcy.Catch/Services/CatchCalculatorService.cs +++ b/Difficalcy.Catch/Services/CatchCalculatorService.cs @@ -97,7 +97,9 @@ protected override CatchCalculation CalculatePerformance(CatchScore score, objec return new CatchCalculation() { Difficulty = GetDifficultyFromDifficultyAttributes(catchDifficultyAttributes), - Performance = GetPerformanceFromPerformanceAttributes(performanceAttributes) + Performance = GetPerformanceFromPerformanceAttributes(performanceAttributes), + Accuracy = accuracy, + Combo = combo }; } diff --git a/Difficalcy.Mania/Models/ManiaCalculation.cs b/Difficalcy.Mania/Models/ManiaCalculation.cs index 3b7d023..ce2ce39 100644 --- a/Difficalcy.Mania/Models/ManiaCalculation.cs +++ b/Difficalcy.Mania/Models/ManiaCalculation.cs @@ -4,5 +4,6 @@ namespace Difficalcy.Mania.Models { public record ManiaCalculation : Calculation { + public double Accuracy { get; init; } } } diff --git a/Difficalcy.Mania/Services/ManiaCalculatorService.cs b/Difficalcy.Mania/Services/ManiaCalculatorService.cs index 0b27e9a..d34b19f 100644 --- a/Difficalcy.Mania/Services/ManiaCalculatorService.cs +++ b/Difficalcy.Mania/Services/ManiaCalculatorService.cs @@ -96,7 +96,8 @@ protected override ManiaCalculation CalculatePerformance(ManiaScore score, objec return new ManiaCalculation() { Difficulty = GetDifficultyFromDifficultyAttributes(maniaDifficultyAttributes), - Performance = GetPerformanceFromPerformanceAttributes(performanceAttributes) + Performance = GetPerformanceFromPerformanceAttributes(performanceAttributes), + Accuracy = accuracy }; } diff --git a/Difficalcy.Osu/Models/OsuCalculation.cs b/Difficalcy.Osu/Models/OsuCalculation.cs index 4d6f301..7c6aa11 100644 --- a/Difficalcy.Osu/Models/OsuCalculation.cs +++ b/Difficalcy.Osu/Models/OsuCalculation.cs @@ -4,5 +4,7 @@ namespace Difficalcy.Osu.Models { public record OsuCalculation : Calculation { + public double Accuracy { get; init; } + public double Combo { get; init; } } } diff --git a/Difficalcy.Osu/Services/OsuCalculatorService.cs b/Difficalcy.Osu/Services/OsuCalculatorService.cs index 5cb2148..e5cb2bd 100644 --- a/Difficalcy.Osu/Services/OsuCalculatorService.cs +++ b/Difficalcy.Osu/Services/OsuCalculatorService.cs @@ -105,7 +105,9 @@ protected override OsuCalculation CalculatePerformance(OsuScore score, object di return new OsuCalculation() { Difficulty = GetDifficultyFromDifficultyAttributes(osuDifficultyAttributes), - Performance = GetPerformanceFromPerformanceAttributes(performanceAttributes) + Performance = GetPerformanceFromPerformanceAttributes(performanceAttributes), + Accuracy = accuracy, + Combo = combo }; } diff --git a/Difficalcy.Taiko/Models/TaikoCalculation.cs b/Difficalcy.Taiko/Models/TaikoCalculation.cs index 5bcc43e..d745c1e 100644 --- a/Difficalcy.Taiko/Models/TaikoCalculation.cs +++ b/Difficalcy.Taiko/Models/TaikoCalculation.cs @@ -4,5 +4,7 @@ namespace Difficalcy.Taiko.Models { public record TaikoCalculation : Calculation { + public double Accuracy { get; init; } + public double Combo { get; init; } } } diff --git a/Difficalcy.Taiko/Services/TaikoCalculatorService.cs b/Difficalcy.Taiko/Services/TaikoCalculatorService.cs index 27d3c1d..f514b91 100644 --- a/Difficalcy.Taiko/Services/TaikoCalculatorService.cs +++ b/Difficalcy.Taiko/Services/TaikoCalculatorService.cs @@ -101,7 +101,9 @@ protected override TaikoCalculation CalculatePerformance(TaikoScore score, objec return new TaikoCalculation() { Difficulty = GetDifficultyFromDifficultyAttributes(taikoDifficultyAttributes), - Performance = GetPerformanceFromPerformanceAttributes(performanceAttributes) + Performance = GetPerformanceFromPerformanceAttributes(performanceAttributes), + Accuracy = accuracy, + Combo = combo }; } From 8c2f70050f8e2cd655bb0e80b7c8c745ca3f5531 Mon Sep 17 00:00:00 2001 From: Samuel Cattini-Schultz Date: Mon, 29 Apr 2024 23:26:28 +1000 Subject: [PATCH 5/6] Update docs --- docs/docs/api-reference/difficalcy-catch.json | 242 +---------------- docs/docs/api-reference/difficalcy-mania.json | 252 +----------------- docs/docs/api-reference/difficalcy-osu.json | 238 +---------------- docs/docs/api-reference/difficalcy-taiko.json | 218 +-------------- docs/docs/api-reference/index.md | 4 - docs/docs/getting-started.md | 20 +- docs/docs/index.md | 8 +- 7 files changed, 46 insertions(+), 936 deletions(-) diff --git a/docs/docs/api-reference/difficalcy-catch.json b/docs/docs/api-reference/difficalcy-catch.json index 5ac4bbf..5a9ec67 100644 --- a/docs/docs/api-reference/difficalcy-catch.json +++ b/docs/docs/api-reference/difficalcy-catch.json @@ -24,170 +24,6 @@ } } }, - "/api/difficulty": { - "get": { - "tags": [ - "CatchCalculator" - ], - "parameters": [ - { - "name": "Combo", - "in": "query", - "schema": { - "maximum": 2147483647, - "minimum": 0, - "type": "integer", - "format": "int32", - "nullable": true - } - }, - { - "name": "Misses", - "in": "query", - "schema": { - "maximum": 2147483647, - "minimum": 0, - "type": "integer", - "format": "int32" - } - }, - { - "name": "SmallDroplets", - "in": "query", - "schema": { - "maximum": 2147483647, - "minimum": 0, - "type": "integer", - "format": "int32", - "nullable": true - } - }, - { - "name": "LargeDroplets", - "in": "query", - "schema": { - "maximum": 2147483647, - "minimum": 0, - "type": "integer", - "format": "int32", - "nullable": true - } - }, - { - "name": "BeatmapId", - "in": "query", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "Mods", - "in": "query", - "schema": { - "maximum": 2147483647, - "minimum": 0, - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Success", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CatchDifficulty" - } - } - } - } - } - } - }, - "/api/performance": { - "get": { - "tags": [ - "CatchCalculator" - ], - "parameters": [ - { - "name": "Combo", - "in": "query", - "schema": { - "maximum": 2147483647, - "minimum": 0, - "type": "integer", - "format": "int32", - "nullable": true - } - }, - { - "name": "Misses", - "in": "query", - "schema": { - "maximum": 2147483647, - "minimum": 0, - "type": "integer", - "format": "int32" - } - }, - { - "name": "SmallDroplets", - "in": "query", - "schema": { - "maximum": 2147483647, - "minimum": 0, - "type": "integer", - "format": "int32", - "nullable": true - } - }, - { - "name": "LargeDroplets", - "in": "query", - "schema": { - "maximum": 2147483647, - "minimum": 0, - "type": "integer", - "format": "int32", - "nullable": true - } - }, - { - "name": "BeatmapId", - "in": "query", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "Mods", - "in": "query", - "schema": { - "maximum": 2147483647, - "minimum": 0, - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Success", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CatchPerformance" - } - } - } - } - } - } - }, "/api/calculation": { "get": { "tags": [ @@ -270,76 +106,6 @@ } } }, - "/api/batch/difficulty": { - "post": { - "tags": [ - "CatchCalculator" - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/CatchScore" - }, - "nullable": true - } - } - } - }, - "responses": { - "200": { - "description": "Success", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/CatchDifficulty" - } - } - } - } - } - } - } - }, - "/api/batch/performance": { - "post": { - "tags": [ - "CatchCalculator" - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/CatchScore" - }, - "nullable": true - } - } - } - }, - "responses": { - "200": { - "description": "Success", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/CatchPerformance" - } - } - } - } - } - } - } - }, "/api/batch/calculation": { "post": { "tags": [ @@ -432,6 +198,14 @@ }, "performance": { "$ref": "#/components/schemas/CatchPerformance" + }, + "accuracy": { + "type": "number", + "format": "double" + }, + "combo": { + "type": "number", + "format": "double" } }, "additionalProperties": false diff --git a/docs/docs/api-reference/difficalcy-mania.json b/docs/docs/api-reference/difficalcy-mania.json index e300850..b2d4338 100644 --- a/docs/docs/api-reference/difficalcy-mania.json +++ b/docs/docs/api-reference/difficalcy-mania.json @@ -24,184 +24,6 @@ } } }, - "/api/difficulty": { - "get": { - "tags": [ - "ManiaCalculator" - ], - "parameters": [ - { - "name": "Misses", - "in": "query", - "schema": { - "maximum": 2147483647, - "minimum": 0, - "type": "integer", - "format": "int32" - } - }, - { - "name": "Mehs", - "in": "query", - "schema": { - "maximum": 2147483647, - "minimum": 0, - "type": "integer", - "format": "int32" - } - }, - { - "name": "Oks", - "in": "query", - "schema": { - "maximum": 2147483647, - "minimum": 0, - "type": "integer", - "format": "int32" - } - }, - { - "name": "Goods", - "in": "query", - "schema": { - "maximum": 2147483647, - "minimum": 0, - "type": "integer", - "format": "int32" - } - }, - { - "name": "Greats", - "in": "query", - "schema": { - "maximum": 2147483647, - "minimum": 0, - "type": "integer", - "format": "int32" - } - }, - { - "name": "BeatmapId", - "in": "query", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "Mods", - "in": "query", - "schema": { - "maximum": 2147483647, - "minimum": 0, - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Success", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ManiaDifficulty" - } - } - } - } - } - } - }, - "/api/performance": { - "get": { - "tags": [ - "ManiaCalculator" - ], - "parameters": [ - { - "name": "Misses", - "in": "query", - "schema": { - "maximum": 2147483647, - "minimum": 0, - "type": "integer", - "format": "int32" - } - }, - { - "name": "Mehs", - "in": "query", - "schema": { - "maximum": 2147483647, - "minimum": 0, - "type": "integer", - "format": "int32" - } - }, - { - "name": "Oks", - "in": "query", - "schema": { - "maximum": 2147483647, - "minimum": 0, - "type": "integer", - "format": "int32" - } - }, - { - "name": "Goods", - "in": "query", - "schema": { - "maximum": 2147483647, - "minimum": 0, - "type": "integer", - "format": "int32" - } - }, - { - "name": "Greats", - "in": "query", - "schema": { - "maximum": 2147483647, - "minimum": 0, - "type": "integer", - "format": "int32" - } - }, - { - "name": "BeatmapId", - "in": "query", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "Mods", - "in": "query", - "schema": { - "maximum": 2147483647, - "minimum": 0, - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Success", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ManiaPerformance" - } - } - } - } - } - } - }, "/api/calculation": { "get": { "tags": [ @@ -291,76 +113,6 @@ } } }, - "/api/batch/difficulty": { - "post": { - "tags": [ - "ManiaCalculator" - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ManiaScore" - }, - "nullable": true - } - } - } - }, - "responses": { - "200": { - "description": "Success", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ManiaDifficulty" - } - } - } - } - } - } - } - }, - "/api/batch/performance": { - "post": { - "tags": [ - "ManiaCalculator" - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ManiaScore" - }, - "nullable": true - } - } - } - }, - "responses": { - "200": { - "description": "Success", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ManiaPerformance" - } - } - } - } - } - } - } - }, "/api/batch/calculation": { "post": { "tags": [ @@ -457,6 +209,10 @@ }, "performance": { "$ref": "#/components/schemas/ManiaPerformance" + }, + "accuracy": { + "type": "number", + "format": "double" } }, "additionalProperties": false diff --git a/docs/docs/api-reference/difficalcy-osu.json b/docs/docs/api-reference/difficalcy-osu.json index 2b7d85d..d336c37 100644 --- a/docs/docs/api-reference/difficalcy-osu.json +++ b/docs/docs/api-reference/difficalcy-osu.json @@ -24,166 +24,6 @@ } } }, - "/api/difficulty": { - "get": { - "tags": [ - "OsuCalculator" - ], - "parameters": [ - { - "name": "Combo", - "in": "query", - "schema": { - "maximum": 2147483647, - "minimum": 0, - "type": "integer", - "format": "int32", - "nullable": true - } - }, - { - "name": "Misses", - "in": "query", - "schema": { - "maximum": 2147483647, - "minimum": 0, - "type": "integer", - "format": "int32" - } - }, - { - "name": "Mehs", - "in": "query", - "schema": { - "maximum": 2147483647, - "minimum": 0, - "type": "integer", - "format": "int32" - } - }, - { - "name": "Oks", - "in": "query", - "schema": { - "maximum": 2147483647, - "minimum": 0, - "type": "integer", - "format": "int32" - } - }, - { - "name": "BeatmapId", - "in": "query", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "Mods", - "in": "query", - "schema": { - "maximum": 2147483647, - "minimum": 0, - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Success", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/OsuDifficulty" - } - } - } - } - } - } - }, - "/api/performance": { - "get": { - "tags": [ - "OsuCalculator" - ], - "parameters": [ - { - "name": "Combo", - "in": "query", - "schema": { - "maximum": 2147483647, - "minimum": 0, - "type": "integer", - "format": "int32", - "nullable": true - } - }, - { - "name": "Misses", - "in": "query", - "schema": { - "maximum": 2147483647, - "minimum": 0, - "type": "integer", - "format": "int32" - } - }, - { - "name": "Mehs", - "in": "query", - "schema": { - "maximum": 2147483647, - "minimum": 0, - "type": "integer", - "format": "int32" - } - }, - { - "name": "Oks", - "in": "query", - "schema": { - "maximum": 2147483647, - "minimum": 0, - "type": "integer", - "format": "int32" - } - }, - { - "name": "BeatmapId", - "in": "query", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "Mods", - "in": "query", - "schema": { - "maximum": 2147483647, - "minimum": 0, - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Success", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/OsuPerformance" - } - } - } - } - } - } - }, "/api/calculation": { "get": { "tags": [ @@ -264,76 +104,6 @@ } } }, - "/api/batch/difficulty": { - "post": { - "tags": [ - "OsuCalculator" - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/OsuScore" - }, - "nullable": true - } - } - } - }, - "responses": { - "200": { - "description": "Success", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/OsuDifficulty" - } - } - } - } - } - } - } - }, - "/api/batch/performance": { - "post": { - "tags": [ - "OsuCalculator" - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/OsuScore" - }, - "nullable": true - } - } - } - }, - "responses": { - "200": { - "description": "Success", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/OsuPerformance" - } - } - } - } - } - } - } - }, "/api/batch/calculation": { "post": { "tags": [ @@ -454,6 +224,14 @@ }, "performance": { "$ref": "#/components/schemas/OsuPerformance" + }, + "accuracy": { + "type": "number", + "format": "double" + }, + "combo": { + "type": "number", + "format": "double" } }, "additionalProperties": false diff --git a/docs/docs/api-reference/difficalcy-taiko.json b/docs/docs/api-reference/difficalcy-taiko.json index 7613732..29f25a6 100644 --- a/docs/docs/api-reference/difficalcy-taiko.json +++ b/docs/docs/api-reference/difficalcy-taiko.json @@ -24,146 +24,6 @@ } } }, - "/api/difficulty": { - "get": { - "tags": [ - "TaikoCalculator" - ], - "parameters": [ - { - "name": "Combo", - "in": "query", - "schema": { - "maximum": 2147483647, - "minimum": 0, - "type": "integer", - "format": "int32", - "nullable": true - } - }, - { - "name": "Misses", - "in": "query", - "schema": { - "maximum": 2147483647, - "minimum": 0, - "type": "integer", - "format": "int32" - } - }, - { - "name": "Oks", - "in": "query", - "schema": { - "maximum": 2147483647, - "minimum": 0, - "type": "integer", - "format": "int32" - } - }, - { - "name": "BeatmapId", - "in": "query", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "Mods", - "in": "query", - "schema": { - "maximum": 2147483647, - "minimum": 0, - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Success", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TaikoDifficulty" - } - } - } - } - } - } - }, - "/api/performance": { - "get": { - "tags": [ - "TaikoCalculator" - ], - "parameters": [ - { - "name": "Combo", - "in": "query", - "schema": { - "maximum": 2147483647, - "minimum": 0, - "type": "integer", - "format": "int32", - "nullable": true - } - }, - { - "name": "Misses", - "in": "query", - "schema": { - "maximum": 2147483647, - "minimum": 0, - "type": "integer", - "format": "int32" - } - }, - { - "name": "Oks", - "in": "query", - "schema": { - "maximum": 2147483647, - "minimum": 0, - "type": "integer", - "format": "int32" - } - }, - { - "name": "BeatmapId", - "in": "query", - "required": true, - "schema": { - "type": "string" - } - }, - { - "name": "Mods", - "in": "query", - "schema": { - "maximum": 2147483647, - "minimum": 0, - "type": "integer", - "format": "int32" - } - } - ], - "responses": { - "200": { - "description": "Success", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TaikoPerformance" - } - } - } - } - } - } - }, "/api/calculation": { "get": { "tags": [ @@ -234,76 +94,6 @@ } } }, - "/api/batch/difficulty": { - "post": { - "tags": [ - "TaikoCalculator" - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/TaikoScore" - }, - "nullable": true - } - } - } - }, - "responses": { - "200": { - "description": "Success", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/TaikoDifficulty" - } - } - } - } - } - } - } - }, - "/api/batch/performance": { - "post": { - "tags": [ - "TaikoCalculator" - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/TaikoScore" - }, - "nullable": true - } - } - } - }, - "responses": { - "200": { - "description": "Success", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/TaikoPerformance" - } - } - } - } - } - } - } - }, "/api/batch/calculation": { "post": { "tags": [ @@ -416,6 +206,14 @@ }, "performance": { "$ref": "#/components/schemas/TaikoPerformance" + }, + "accuracy": { + "type": "number", + "format": "double" + }, + "combo": { + "type": "number", + "format": "double" } }, "additionalProperties": false diff --git a/docs/docs/api-reference/index.md b/docs/docs/api-reference/index.md index b6ecbc3..510a215 100644 --- a/docs/docs/api-reference/index.md +++ b/docs/docs/api-reference/index.md @@ -14,9 +14,5 @@ In general, each calculator exposes: | Endpoint | Description | | ----------------------------- | ----------------------------------------------------- | | `GET /api/info` | Returns details of the running calculation engine | -| `GET /api/difficulty` | Calculates difficulty of a beatmap | -| `GET /api/performance` | Calculates performance of a score | | `GET /api/calculation` | Calculates both difficulty and performance of a score | -| `POST /api/batch/difficulty` | Calculates a batch of difficulties | -| `POST /api/batch/performance` | Calculates a batch of performances | | `POST /api/batch/calculation` | Calculates a batch of difficulties and performances | diff --git a/docs/docs/getting-started.md b/docs/docs/getting-started.md index 1f57341..0e41bfe 100644 --- a/docs/docs/getting-started.md +++ b/docs/docs/getting-started.md @@ -86,11 +86,13 @@ curl "localhost:5000/api/calculation?BeatmapId=658127" ```json { + "accuracy": 1, + "combo": 2402, "difficulty": { - "aim": 3.471503344019442, + "aim": 3.4715033440194416, "speed": 3.4738667283055444, - "flashlight": 4.58994045567377, - "total": 7.255439646986892 + "flashlight": 0, + "total": 7.25543964698689 }, "performance": { "aim": 220.83646290283872, @@ -110,11 +112,13 @@ curl "localhost:5000/api/calculation?BeatmapId=658127&Mods=24" ```json { + "accuracy": 1, + "combo": 2402, "difficulty": { "aim": 3.765456925600854, "speed": 3.72396422087254, - "flashlight": 6.263638574855112, - "total": 7.824058505624836 + "flashlight": 0, + "total": 7.824058505624834 }, "performance": { "aim": 307.7860998424521, @@ -134,11 +138,13 @@ curl "localhost:5000/api/calculation?BeatmapId=658127&Mods=24&Oks=24&Misses=2&Co ```json { + "accuracy": 0.9908768373035985, + "combo": 2364, "difficulty": { "aim": 3.765456925600854, "speed": 3.72396422087254, - "flashlight": 6.263638574855112, - "total": 7.824058505624836 + "flashlight": 0, + "total": 7.824058505624834 }, "performance": { "aim": 287.9789267544456, diff --git a/docs/docs/index.md b/docs/docs/index.md index dee5964..b51b432 100644 --- a/docs/docs/index.md +++ b/docs/docs/index.md @@ -20,11 +20,13 @@ Get your lazer powered calculations: ```json { + "accuracy": 1, + "combo": 2402, "difficulty": { - "aim": 3.471503344019442, + "aim": 3.4715033440194416, "speed": 3.4738667283055444, - "flashlight": 4.58994045567377, - "total": 7.255439646986892 + "flashlight": 0, + "total": 7.25543964698689 }, "performance": { "aim": 220.83646290283872, From 73b10f2397471ec13283120e80919e470a9a7761 Mon Sep 17 00:00:00 2001 From: Samuel Cattini-Schultz Date: Tue, 30 Apr 2024 00:06:17 +1000 Subject: [PATCH 6/6] Update syntax --- .../CatchCalculatorServiceTest.cs | 4 +- .../Services/CatchCalculatorService.cs | 36 +++++------- .../ManiaCalculatorServiceTest.cs | 4 +- .../Services/ManiaCalculatorService.cs | 24 ++++---- .../OsuCalculatorServiceTest.cs | 4 +- .../Services/OsuCalculatorService.cs | 56 +++++++++---------- .../TaikoCalculatorServiceTest.cs | 4 +- .../Services/TaikoCalculatorService.cs | 32 +++++------ Difficalcy/Services/CalculatorService.cs | 11 +--- 9 files changed, 78 insertions(+), 97 deletions(-) diff --git a/Difficalcy.Catch.Tests/CatchCalculatorServiceTest.cs b/Difficalcy.Catch.Tests/CatchCalculatorServiceTest.cs index 3f06f91..4c43b3e 100644 --- a/Difficalcy.Catch.Tests/CatchCalculatorServiceTest.cs +++ b/Difficalcy.Catch.Tests/CatchCalculatorServiceTest.cs @@ -13,7 +13,7 @@ public class CatchCalculatorServiceTest : CalculatorServiceTest base.TestGetCalculationReturnsCorrectValues(expectedDifficultyTotal, expectedPerformanceTotal, new CatchScore { BeatmapId = beatmapId, Mods = mods }); + => TestGetCalculationReturnsCorrectValues(expectedDifficultyTotal, expectedPerformanceTotal, new CatchScore { BeatmapId = beatmapId, Mods = mods }); [Fact] public void TestAllParameters() @@ -27,6 +27,6 @@ public void TestAllParameters() LargeDroplets = 18, SmallDroplets = 200, }; - base.TestGetCalculationReturnsCorrectValues(5.739025024925009d, 241.19384779497875d, score); + TestGetCalculationReturnsCorrectValues(5.739025024925009d, 241.19384779497875d, score); } } diff --git a/Difficalcy.Catch/Services/CatchCalculatorService.cs b/Difficalcy.Catch/Services/CatchCalculatorService.cs index 0bbbd77..29e4227 100644 --- a/Difficalcy.Catch/Services/CatchCalculatorService.cs +++ b/Difficalcy.Catch/Services/CatchCalculatorService.cs @@ -17,9 +17,8 @@ namespace Difficalcy.Catch.Services { - public class CatchCalculatorService : CalculatorService + public class CatchCalculatorService(ICache cache, IBeatmapProvider beatmapProvider) : CalculatorService(cache) { - private readonly IBeatmapProvider _beatmapProvider; private CatchRuleset CatchRuleset { get; } = new CatchRuleset(); public override CalculatorInfo Info @@ -39,19 +38,14 @@ public override CalculatorInfo Info } } - public CatchCalculatorService(ICache cache, IBeatmapProvider beatmapProvider) : base(cache) - { - _beatmapProvider = beatmapProvider; - } - protected override async Task EnsureBeatmap(string beatmapId) { - await _beatmapProvider.EnsureBeatmap(beatmapId); + await beatmapProvider.EnsureBeatmap(beatmapId); } protected override (object, string) CalculateDifficultyAttributes(CatchScore score) { - var workingBeatmap = getWorkingBeatmap(score.BeatmapId); + var workingBeatmap = GetWorkingBeatmap(score.BeatmapId); var mods = CatchRuleset.ConvertFromLegacyMods((LegacyMods)score.Mods).ToArray(); var difficultyCalculator = CatchRuleset.CreateDifficultyCalculator(workingBeatmap); @@ -60,9 +54,9 @@ protected override (object, string) CalculateDifficultyAttributes(CatchScore sco // Serialising anonymous object with same names because some properties can't be serialised, and the built-in JsonProperty fields aren't on all required fields return (difficultyAttributes, JsonSerializer.Serialize(new { - StarRating = difficultyAttributes.StarRating, - MaxCombo = difficultyAttributes.MaxCombo, - ApproachRate = difficultyAttributes.ApproachRate + difficultyAttributes.StarRating, + difficultyAttributes.MaxCombo, + difficultyAttributes.ApproachRate })); } @@ -75,13 +69,13 @@ protected override CatchCalculation CalculatePerformance(CatchScore score, objec { var catchDifficultyAttributes = (CatchDifficultyAttributes)difficultyAttributes; - var workingBeatmap = getWorkingBeatmap(score.BeatmapId); + var workingBeatmap = GetWorkingBeatmap(score.BeatmapId); var mods = CatchRuleset.ConvertFromLegacyMods((LegacyMods)score.Mods).ToArray(); var beatmap = workingBeatmap.GetPlayableBeatmap(CatchRuleset.RulesetInfo, mods); var combo = score.Combo ?? beatmap.HitObjects.Count(h => h is Fruit) + beatmap.HitObjects.OfType().SelectMany(j => j.NestedHitObjects).Count(h => !(h is TinyDroplet)); - var statistics = getHitResults(beatmap, score.Misses, score.LargeDroplets, score.SmallDroplets); - var accuracy = calculateAccuracy(statistics); + var statistics = GetHitResults(beatmap, score.Misses, score.LargeDroplets, score.SmallDroplets); + var accuracy = CalculateAccuracy(statistics); var scoreInfo = new ScoreInfo(beatmap.BeatmapInfo, CatchRuleset.RulesetInfo) { @@ -103,13 +97,13 @@ protected override CatchCalculation CalculatePerformance(CatchScore score, objec }; } - private CalculatorWorkingBeatmap getWorkingBeatmap(string beatmapId) + private CalculatorWorkingBeatmap GetWorkingBeatmap(string beatmapId) { - using var beatmapStream = _beatmapProvider.GetBeatmapStream(beatmapId); + using var beatmapStream = beatmapProvider.GetBeatmapStream(beatmapId); return new CalculatorWorkingBeatmap(CatchRuleset, beatmapStream, beatmapId); } - private Dictionary getHitResults(IBeatmap beatmap, int countMiss, int? countDroplet, int? countTinyDroplet) + private static Dictionary GetHitResults(IBeatmap beatmap, int countMiss, int? countDroplet, int? countTinyDroplet) { var maxTinyDroplets = beatmap.HitObjects.OfType().Sum(s => s.NestedHitObjects.OfType().Count()); var maxDroplets = beatmap.HitObjects.OfType().Sum(s => s.NestedHitObjects.OfType().Count()) - maxTinyDroplets; @@ -135,7 +129,7 @@ private Dictionary getHitResults(IBeatmap beatmap, int countMiss }; } - private double calculateAccuracy(Dictionary statistics) + private static double CalculateAccuracy(Dictionary statistics) { double hits = statistics[HitResult.Great] + statistics[HitResult.LargeTickHit] + statistics[HitResult.SmallTickHit]; double total = hits + statistics[HitResult.Miss] + statistics[HitResult.SmallTickMiss]; @@ -143,7 +137,7 @@ private double calculateAccuracy(Dictionary statistics) return hits / total; } - private CatchDifficulty GetDifficultyFromDifficultyAttributes(CatchDifficultyAttributes difficultyAttributes) + private static CatchDifficulty GetDifficultyFromDifficultyAttributes(CatchDifficultyAttributes difficultyAttributes) { return new CatchDifficulty() { @@ -151,7 +145,7 @@ private CatchDifficulty GetDifficultyFromDifficultyAttributes(CatchDifficultyAtt }; } - private CatchPerformance GetPerformanceFromPerformanceAttributes(CatchPerformanceAttributes performanceAttributes) + private static CatchPerformance GetPerformanceFromPerformanceAttributes(CatchPerformanceAttributes performanceAttributes) { return new CatchPerformance() { diff --git a/Difficalcy.Mania.Tests/ManiaCalculatorServiceTest.cs b/Difficalcy.Mania.Tests/ManiaCalculatorServiceTest.cs index f623b74..2b3de7f 100644 --- a/Difficalcy.Mania.Tests/ManiaCalculatorServiceTest.cs +++ b/Difficalcy.Mania.Tests/ManiaCalculatorServiceTest.cs @@ -13,7 +13,7 @@ public class ManiaCalculatorServiceTest : CalculatorServiceTest base.TestGetCalculationReturnsCorrectValues(expectedDifficultyTotal, expectedPerformanceTotal, new ManiaScore { BeatmapId = beatmapId, Mods = mods }); + => TestGetCalculationReturnsCorrectValues(expectedDifficultyTotal, expectedPerformanceTotal, new ManiaScore { BeatmapId = beatmapId, Mods = mods }); [Fact] public void TestAllParameters() @@ -28,6 +28,6 @@ public void TestAllParameters() Goods = 2, Greats = 1, }; - base.TestGetCalculationReturnsCorrectValues(2.797245912537965d, 43.17076331130473d, score); + TestGetCalculationReturnsCorrectValues(2.797245912537965d, 43.17076331130473d, score); } } diff --git a/Difficalcy.Mania/Services/ManiaCalculatorService.cs b/Difficalcy.Mania/Services/ManiaCalculatorService.cs index d34b19f..935a0ab 100644 --- a/Difficalcy.Mania/Services/ManiaCalculatorService.cs +++ b/Difficalcy.Mania/Services/ManiaCalculatorService.cs @@ -50,7 +50,7 @@ protected override async Task EnsureBeatmap(string beatmapId) protected override (object, string) CalculateDifficultyAttributes(ManiaScore score) { - var workingBeatmap = getWorkingBeatmap(score.BeatmapId); + var workingBeatmap = GetWorkingBeatmap(score.BeatmapId); var mods = ManiaRuleset.ConvertFromLegacyMods((LegacyMods)score.Mods).ToArray(); var difficultyCalculator = ManiaRuleset.CreateDifficultyCalculator(workingBeatmap); @@ -59,9 +59,9 @@ protected override (object, string) CalculateDifficultyAttributes(ManiaScore sco // Serialising anonymous object with same names because some properties can't be serialised, and the built-in JsonProperty fields aren't on all required fields return (difficultyAttributes, JsonSerializer.Serialize(new { - StarRating = difficultyAttributes.StarRating, - MaxCombo = difficultyAttributes.MaxCombo, - GreatHitWindow = difficultyAttributes.GreatHitWindow + difficultyAttributes.StarRating, + difficultyAttributes.MaxCombo, + difficultyAttributes.GreatHitWindow })); } @@ -73,14 +73,14 @@ protected override object DeserialiseDifficultyAttributes(string difficultyAttri protected override ManiaCalculation CalculatePerformance(ManiaScore score, object difficultyAttributes) { var maniaDifficultyAttributes = (ManiaDifficultyAttributes)difficultyAttributes; - var workingBeatmap = getWorkingBeatmap(score.BeatmapId); + var workingBeatmap = GetWorkingBeatmap(score.BeatmapId); var mods = ManiaRuleset.ConvertFromLegacyMods((LegacyMods)score.Mods).ToArray(); var beatmap = workingBeatmap.GetPlayableBeatmap(ManiaRuleset.RulesetInfo, mods); var hitObjectCount = beatmap.HitObjects.Count; var holdNoteTailCount = beatmap.HitObjects.OfType().Count(); - var statistics = getHitResults(hitObjectCount + holdNoteTailCount, score.Misses, score.Mehs, score.Oks, score.Goods, score.Greats); - var accuracy = calculateAccuracy(statistics); + var statistics = GetHitResults(hitObjectCount + holdNoteTailCount, score.Misses, score.Mehs, score.Oks, score.Goods, score.Greats); + var accuracy = CalculateAccuracy(statistics); var scoreInfo = new ScoreInfo(beatmap.BeatmapInfo, ManiaRuleset.RulesetInfo) { @@ -101,13 +101,13 @@ protected override ManiaCalculation CalculatePerformance(ManiaScore score, objec }; } - private CalculatorWorkingBeatmap getWorkingBeatmap(string beatmapId) + private CalculatorWorkingBeatmap GetWorkingBeatmap(string beatmapId) { using var beatmapStream = _beatmapProvider.GetBeatmapStream(beatmapId); return new CalculatorWorkingBeatmap(ManiaRuleset, beatmapStream, beatmapId); } - private Dictionary getHitResults(int hitResultCount, int countMiss, int countMeh, int countOk, int countGood, int countGreat) + private static Dictionary GetHitResults(int hitResultCount, int countMiss, int countMeh, int countOk, int countGood, int countGreat) { var countPerfect = hitResultCount - (countMiss + countMeh + countOk + countGood + countGreat); @@ -122,7 +122,7 @@ private Dictionary getHitResults(int hitResultCount, int countMi }; } - private double calculateAccuracy(Dictionary statistics) + private static double CalculateAccuracy(Dictionary statistics) { var countPerfect = statistics[HitResult.Perfect]; var countGreat = statistics[HitResult.Great]; @@ -135,7 +135,7 @@ private double calculateAccuracy(Dictionary statistics) return (double)((6 * countPerfect) + (6 * countGreat) + (4 * countGood) + (2 * countOk) + countMeh) / (6 * total); } - private ManiaDifficulty GetDifficultyFromDifficultyAttributes(ManiaDifficultyAttributes difficultyAttributes) + private static ManiaDifficulty GetDifficultyFromDifficultyAttributes(ManiaDifficultyAttributes difficultyAttributes) { return new ManiaDifficulty() { @@ -143,7 +143,7 @@ private ManiaDifficulty GetDifficultyFromDifficultyAttributes(ManiaDifficultyAtt }; } - private ManiaPerformance GetPerformanceFromPerformanceAttributes(ManiaPerformanceAttributes performanceAttributes) + private static ManiaPerformance GetPerformanceFromPerformanceAttributes(ManiaPerformanceAttributes performanceAttributes) { return new ManiaPerformance() { diff --git a/Difficalcy.Osu.Tests/OsuCalculatorServiceTest.cs b/Difficalcy.Osu.Tests/OsuCalculatorServiceTest.cs index 115641f..80d131c 100644 --- a/Difficalcy.Osu.Tests/OsuCalculatorServiceTest.cs +++ b/Difficalcy.Osu.Tests/OsuCalculatorServiceTest.cs @@ -13,7 +13,7 @@ public class OsuCalculatorServiceTest : CalculatorServiceTest base.TestGetCalculationReturnsCorrectValues(expectedDifficultyTotal, expectedPerformanceTotal, new OsuScore { BeatmapId = beatmapId, Mods = mods }); + => TestGetCalculationReturnsCorrectValues(expectedDifficultyTotal, expectedPerformanceTotal, new OsuScore { BeatmapId = beatmapId, Mods = mods }); [Fact] public void TestAllParameters() @@ -27,6 +27,6 @@ public void TestAllParameters() Mehs = 4, Oks = 3, }; - base.TestGetCalculationReturnsCorrectValues(10.07270907570737d, 553.1423675531603d, score); + TestGetCalculationReturnsCorrectValues(10.07270907570737d, 553.1423675531603d, score); } } diff --git a/Difficalcy.Osu/Services/OsuCalculatorService.cs b/Difficalcy.Osu/Services/OsuCalculatorService.cs index e5cb2bd..9b0ef46 100644 --- a/Difficalcy.Osu/Services/OsuCalculatorService.cs +++ b/Difficalcy.Osu/Services/OsuCalculatorService.cs @@ -15,9 +15,8 @@ namespace Difficalcy.Osu.Services { - public class OsuCalculatorService : CalculatorService + public class OsuCalculatorService(ICache cache, IBeatmapProvider beatmapProvider) : CalculatorService(cache) { - private readonly IBeatmapProvider _beatmapProvider; private OsuRuleset OsuRuleset { get; } = new OsuRuleset(); public override CalculatorInfo Info @@ -37,19 +36,14 @@ public override CalculatorInfo Info } } - public OsuCalculatorService(ICache cache, IBeatmapProvider beatmapProvider) : base(cache) - { - _beatmapProvider = beatmapProvider; - } - protected override async Task EnsureBeatmap(string beatmapId) { - await _beatmapProvider.EnsureBeatmap(beatmapId); + await beatmapProvider.EnsureBeatmap(beatmapId); } protected override (object, string) CalculateDifficultyAttributes(OsuScore score) { - var workingBeatmap = getWorkingBeatmap(score.BeatmapId); + var workingBeatmap = GetWorkingBeatmap(score.BeatmapId); var mods = OsuRuleset.ConvertFromLegacyMods((LegacyMods)score.Mods).ToArray(); var difficultyCalculator = OsuRuleset.CreateDifficultyCalculator(workingBeatmap); @@ -58,19 +52,19 @@ protected override (object, string) CalculateDifficultyAttributes(OsuScore score // Serialising anonymous object with same names because some properties can't be serialised, and the built-in JsonProperty fields aren't on all required fields return (difficultyAttributes, JsonSerializer.Serialize(new { - StarRating = difficultyAttributes.StarRating, - MaxCombo = difficultyAttributes.MaxCombo, - AimDifficulty = difficultyAttributes.AimDifficulty, - SpeedDifficulty = difficultyAttributes.SpeedDifficulty, - SpeedNoteCount = difficultyAttributes.SpeedNoteCount, - FlashlightDifficulty = difficultyAttributes.FlashlightDifficulty, - SliderFactor = difficultyAttributes.SliderFactor, - ApproachRate = difficultyAttributes.ApproachRate, - OverallDifficulty = difficultyAttributes.OverallDifficulty, - DrainRate = difficultyAttributes.DrainRate, - HitCircleCount = difficultyAttributes.HitCircleCount, - SliderCount = difficultyAttributes.SliderCount, - SpinnerCount = difficultyAttributes.SpinnerCount + difficultyAttributes.StarRating, + difficultyAttributes.MaxCombo, + difficultyAttributes.AimDifficulty, + difficultyAttributes.SpeedDifficulty, + difficultyAttributes.SpeedNoteCount, + difficultyAttributes.FlashlightDifficulty, + difficultyAttributes.SliderFactor, + difficultyAttributes.ApproachRate, + difficultyAttributes.OverallDifficulty, + difficultyAttributes.DrainRate, + difficultyAttributes.HitCircleCount, + difficultyAttributes.SliderCount, + difficultyAttributes.SpinnerCount })); } @@ -83,13 +77,13 @@ protected override OsuCalculation CalculatePerformance(OsuScore score, object di { var osuDifficultyAttributes = (OsuDifficultyAttributes)difficultyAttributes; - var workingBeatmap = getWorkingBeatmap(score.BeatmapId); + var workingBeatmap = GetWorkingBeatmap(score.BeatmapId); var mods = OsuRuleset.ConvertFromLegacyMods((LegacyMods)score.Mods).ToArray(); var beatmap = workingBeatmap.GetPlayableBeatmap(OsuRuleset.RulesetInfo, mods); var combo = score.Combo ?? beatmap.HitObjects.Count + beatmap.HitObjects.OfType().Sum(s => s.NestedHitObjects.Count - 1); - var statistics = getHitResults(beatmap.HitObjects.Count, score.Misses, score.Mehs, score.Oks); - var accuracy = calculateAccuracy(statistics); + var statistics = GetHitResults(beatmap.HitObjects.Count, score.Misses, score.Mehs, score.Oks); + var accuracy = CalculateAccuracy(statistics); var scoreInfo = new ScoreInfo(beatmap.BeatmapInfo, OsuRuleset.RulesetInfo) { @@ -111,13 +105,13 @@ protected override OsuCalculation CalculatePerformance(OsuScore score, object di }; } - private CalculatorWorkingBeatmap getWorkingBeatmap(string beatmapId) + private CalculatorWorkingBeatmap GetWorkingBeatmap(string beatmapId) { - using var beatmapStream = _beatmapProvider.GetBeatmapStream(beatmapId); + using var beatmapStream = beatmapProvider.GetBeatmapStream(beatmapId); return new CalculatorWorkingBeatmap(OsuRuleset, beatmapStream, beatmapId); } - private Dictionary getHitResults(int hitResultCount, int countMiss, int countMeh, int countOk) + private static Dictionary GetHitResults(int hitResultCount, int countMiss, int countMeh, int countOk) { var countGreat = hitResultCount - countOk - countMeh - countMiss; @@ -130,7 +124,7 @@ private Dictionary getHitResults(int hitResultCount, int countMi }; } - private double calculateAccuracy(Dictionary statistics) + private static double CalculateAccuracy(Dictionary statistics) { var countGreat = statistics[HitResult.Great]; var countOk = statistics[HitResult.Ok]; @@ -141,7 +135,7 @@ private double calculateAccuracy(Dictionary statistics) return (double)((6 * countGreat) + (2 * countOk) + countMeh) / (6 * total); } - private OsuDifficulty GetDifficultyFromDifficultyAttributes(OsuDifficultyAttributes difficultyAttributes) + private static OsuDifficulty GetDifficultyFromDifficultyAttributes(OsuDifficultyAttributes difficultyAttributes) { return new OsuDifficulty() { @@ -152,7 +146,7 @@ private OsuDifficulty GetDifficultyFromDifficultyAttributes(OsuDifficultyAttribu }; } - private OsuPerformance GetPerformanceFromPerformanceAttributes(OsuPerformanceAttributes performanceAttributes) + private static OsuPerformance GetPerformanceFromPerformanceAttributes(OsuPerformanceAttributes performanceAttributes) { return new OsuPerformance() { diff --git a/Difficalcy.Taiko.Tests/TaikoCalculatorServiceTest.cs b/Difficalcy.Taiko.Tests/TaikoCalculatorServiceTest.cs index 5d75e09..561f37c 100644 --- a/Difficalcy.Taiko.Tests/TaikoCalculatorServiceTest.cs +++ b/Difficalcy.Taiko.Tests/TaikoCalculatorServiceTest.cs @@ -13,7 +13,7 @@ public class TaikoCalculatorServiceTest : CalculatorServiceTest base.TestGetCalculationReturnsCorrectValues(expectedDifficultyTotal, expectedPerformanceTotal, new TaikoScore { BeatmapId = beatmapId, Mods = mods }); + => TestGetCalculationReturnsCorrectValues(expectedDifficultyTotal, expectedPerformanceTotal, new TaikoScore { BeatmapId = beatmapId, Mods = mods }); [Fact] public void TestAllParameters() @@ -26,6 +26,6 @@ public void TestAllParameters() Misses = 5, Oks = 3, }; - base.TestGetCalculationReturnsCorrectValues(4.0789820318081444d, 176.94088597258678d, score); + TestGetCalculationReturnsCorrectValues(4.0789820318081444d, 176.94088597258678d, score); } } diff --git a/Difficalcy.Taiko/Services/TaikoCalculatorService.cs b/Difficalcy.Taiko/Services/TaikoCalculatorService.cs index f514b91..425af53 100644 --- a/Difficalcy.Taiko/Services/TaikoCalculatorService.cs +++ b/Difficalcy.Taiko/Services/TaikoCalculatorService.cs @@ -50,7 +50,7 @@ protected override async Task EnsureBeatmap(string beatmapId) protected override (object, string) CalculateDifficultyAttributes(TaikoScore score) { - var workingBeatmap = getWorkingBeatmap(score.BeatmapId); + var workingBeatmap = GetWorkingBeatmap(score.BeatmapId); var mods = TaikoRuleset.ConvertFromLegacyMods((LegacyMods)score.Mods).ToArray(); var difficultyCalculator = TaikoRuleset.CreateDifficultyCalculator(workingBeatmap); @@ -59,13 +59,13 @@ protected override (object, string) CalculateDifficultyAttributes(TaikoScore sco // Serialising anonymous object with same names because some properties can't be serialised, and the built-in JsonProperty fields aren't on all required fields return (difficultyAttributes, JsonSerializer.Serialize(new { - StarRating = difficultyAttributes.StarRating, - MaxCombo = difficultyAttributes.MaxCombo, - StaminaDifficulty = difficultyAttributes.StaminaDifficulty, - RhythmDifficulty = difficultyAttributes.RhythmDifficulty, - ColourDifficulty = difficultyAttributes.ColourDifficulty, - PeakDifficulty = difficultyAttributes.PeakDifficulty, - GreatHitWindow = difficultyAttributes.GreatHitWindow + difficultyAttributes.StarRating, + difficultyAttributes.MaxCombo, + difficultyAttributes.StaminaDifficulty, + difficultyAttributes.RhythmDifficulty, + difficultyAttributes.ColourDifficulty, + difficultyAttributes.PeakDifficulty, + difficultyAttributes.GreatHitWindow })); } @@ -78,14 +78,14 @@ protected override TaikoCalculation CalculatePerformance(TaikoScore score, objec { var taikoDifficultyAttributes = (TaikoDifficultyAttributes)difficultyAttributes; - var workingBeatmap = getWorkingBeatmap(score.BeatmapId); + var workingBeatmap = GetWorkingBeatmap(score.BeatmapId); var mods = TaikoRuleset.ConvertFromLegacyMods((LegacyMods)score.Mods).ToArray(); var beatmap = workingBeatmap.GetPlayableBeatmap(TaikoRuleset.RulesetInfo, mods); var hitResultCount = beatmap.HitObjects.OfType().Count(); var combo = score.Combo ?? hitResultCount; - var statistics = getHitResults(hitResultCount, score.Misses, score.Oks); - var accuracy = calculateAccuracy(statistics); + var statistics = GetHitResults(hitResultCount, score.Misses, score.Oks); + var accuracy = CalculateAccuracy(statistics); var scoreInfo = new ScoreInfo(beatmap.BeatmapInfo, TaikoRuleset.RulesetInfo) { @@ -107,13 +107,13 @@ protected override TaikoCalculation CalculatePerformance(TaikoScore score, objec }; } - private CalculatorWorkingBeatmap getWorkingBeatmap(string beatmapId) + private CalculatorWorkingBeatmap GetWorkingBeatmap(string beatmapId) { using var beatmapStream = _beatmapProvider.GetBeatmapStream(beatmapId); return new CalculatorWorkingBeatmap(TaikoRuleset, beatmapStream, beatmapId); } - private Dictionary getHitResults(int hitResultCount, int countMiss, int countOk) + private static Dictionary GetHitResults(int hitResultCount, int countMiss, int countOk) { var countGreat = hitResultCount - countOk - countMiss; @@ -126,7 +126,7 @@ private Dictionary getHitResults(int hitResultCount, int countMi }; } - private double calculateAccuracy(Dictionary statistics) + private static double CalculateAccuracy(Dictionary statistics) { var countGreat = statistics[HitResult.Great]; var countOk = statistics[HitResult.Ok]; @@ -136,7 +136,7 @@ private double calculateAccuracy(Dictionary statistics) return (double)((2 * countGreat) + countOk) / (2 * total); } - private TaikoDifficulty GetDifficultyFromDifficultyAttributes(TaikoDifficultyAttributes difficultyAttributes) + private static TaikoDifficulty GetDifficultyFromDifficultyAttributes(TaikoDifficultyAttributes difficultyAttributes) { return new TaikoDifficulty() { @@ -147,7 +147,7 @@ private TaikoDifficulty GetDifficultyFromDifficultyAttributes(TaikoDifficultyAtt }; } - private TaikoPerformance GetPerformanceFromPerformanceAttributes(TaikoPerformanceAttributes performanceAttributes) + private static TaikoPerformance GetPerformanceFromPerformanceAttributes(TaikoPerformanceAttributes performanceAttributes) { return new TaikoPerformance() { diff --git a/Difficalcy/Services/CalculatorService.cs b/Difficalcy/Services/CalculatorService.cs index 9528995..683d384 100644 --- a/Difficalcy/Services/CalculatorService.cs +++ b/Difficalcy/Services/CalculatorService.cs @@ -3,7 +3,7 @@ namespace Difficalcy.Services { - public abstract class CalculatorService + public abstract class CalculatorService(ICache cache) where TScore : Score where TDifficulty : Difficulty where TPerformance : Performance @@ -20,13 +20,6 @@ public abstract class CalculatorService public string CalculatorDiscriminator => $"{Info.CalculatorPackage}:{Info.CalculatorVersion}"; - private readonly ICache _cache; - - public CalculatorService(ICache cache) - { - _cache = cache; - } - /// /// Ensures the beatmap with the given ID is available locally. /// @@ -60,7 +53,7 @@ private async Task GetDifficultyAttributes(TScore score) { await EnsureBeatmap(score.BeatmapId); - var db = _cache.GetDatabase(); + var db = cache.GetDatabase(); var redisKey = $"difficalcy:{CalculatorDiscriminator}:{score.BeatmapId}:{score.Mods}"; var difficultyAttributesJson = await db.GetAsync(redisKey);