Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add code formatter #97

Merged
merged 2 commits into from
Nov 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .config/dotnet-tools.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@
"commands": [
"swagger"
]
},
"csharpier": {
"version": "0.29.2",
"commands": [
"dotnet-csharpier"
]
}
}
}
6 changes: 6 additions & 0 deletions .github/workflows/test-on-push.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,9 @@ jobs:
steps:
- uses: actions/checkout@v4
- run: make build-docs

check-formatting:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- run: make check-formatting
41 changes: 31 additions & 10 deletions Difficalcy.Catch.Tests/CatchCalculatorServiceTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,32 +6,53 @@

namespace Difficalcy.Catch.Tests;

public class CatchCalculatorServiceTest : CalculatorServiceTest<CatchScore, CatchDifficulty, CatchPerformance, CatchCalculation>
public class CatchCalculatorServiceTest
: CalculatorServiceTest<CatchScore, CatchDifficulty, CatchPerformance, CatchCalculation>
{
protected override CalculatorService<CatchScore, CatchDifficulty, CatchPerformance, CatchCalculation> CalculatorService { get; } = new CatchCalculatorService(new InMemoryCache(), new TestBeatmapProvider(typeof(CatchCalculatorService).Assembly.GetName().Name));
protected override CalculatorService<
CatchScore,
CatchDifficulty,
CatchPerformance,
CatchCalculation
> CalculatorService { get; } =
new CatchCalculatorService(
new InMemoryCache(),
new TestBeatmapProvider(typeof(CatchCalculatorService).Assembly.GetName().Name)
);

[Theory]
[InlineData(4.0505463516206195d, 164.5770866821372d, "diffcalc-test", new string[] { })]
[InlineData(5.1696411260785498d, 291.43480971713944d, "diffcalc-test", new string[] { "DT" })]
public void Test(double expectedDifficultyTotal, double expectedPerformanceTotal, string beatmapId, string[] mods)
=> TestGetCalculationReturnsCorrectValues(expectedDifficultyTotal, expectedPerformanceTotal, new CatchScore { BeatmapId = beatmapId, Mods = mods.Select(m => new Mod { Acronym = m }).ToArray() });
public void Test(
double expectedDifficultyTotal,
double expectedPerformanceTotal,
string beatmapId,
string[] mods
) =>
TestGetCalculationReturnsCorrectValues(
expectedDifficultyTotal,
expectedPerformanceTotal,
new CatchScore
{
BeatmapId = beatmapId,
Mods = mods.Select(m => new Mod { Acronym = m }).ToArray(),
}
);

[Fact]
public void TestAllParameters()
{
var score = new CatchScore
{
BeatmapId = "diffcalc-test",
Mods = [
Mods =
[
new Mod() { Acronym = "HR" },
new Mod()
{
Acronym = "DT",
Settings = new Dictionary<string, string>
{
{ "speed_change", "2" }
}
}
Settings = new Dictionary<string, string> { { "speed_change", "2" } },
},
],
Combo = 100,
Misses = 5,
Expand Down
2 changes: 1 addition & 1 deletion Difficalcy.Catch.Tests/Usings.cs
Original file line number Diff line number Diff line change
@@ -1 +1 @@
global using Xunit;
global using Xunit;
13 changes: 9 additions & 4 deletions Difficalcy.Catch/Controllers/CatchCalculatorController.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
using Difficalcy.Controllers;
using Difficalcy.Catch.Models;
using Difficalcy.Catch.Services;
using Difficalcy.Controllers;

namespace Difficalcy.Catch.Controllers
{
public class CatchCalculatorController(CatchCalculatorService calculatorService) : CalculatorController<CatchScore, CatchDifficulty, CatchPerformance, CatchCalculation, CatchCalculatorService>(calculatorService)
{
}
public class CatchCalculatorController(CatchCalculatorService calculatorService)
: CalculatorController<
CatchScore,
CatchDifficulty,
CatchPerformance,
CatchCalculation,
CatchCalculatorService
>(calculatorService) { }
}
4 changes: 1 addition & 3 deletions Difficalcy.Catch/Models/CatchDifficulty.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,5 @@

namespace Difficalcy.Catch.Models
{
public record CatchDifficulty : Difficulty
{
}
public record CatchDifficulty : Difficulty { }
}
4 changes: 1 addition & 3 deletions Difficalcy.Catch/Models/CatchPerformance.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,5 @@

namespace Difficalcy.Catch.Models
{
public record CatchPerformance : Performance
{
}
public record CatchPerformance : Performance { }
}
5 changes: 4 additions & 1 deletion Difficalcy.Catch/Models/CatchScore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,10 @@ public IEnumerable<ValidationResult> Validate(ValidationContext validationContex
{
if (Misses > 0 && Combo is null)
{
yield return new ValidationResult("Combo must be specified if Misses are greater than 0.", [nameof(Combo)]);
yield return new ValidationResult(
"Combo must be specified if Misses are greater than 0.",
[nameof(Combo)]
);
}
}
}
Expand Down
15 changes: 12 additions & 3 deletions Difficalcy.Catch/Services/CalculatorWorkingBeatmap.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,19 @@ public class CalculatorWorkingBeatmap : WorkingBeatmap
{
private readonly Beatmap _beatmap;

public CalculatorWorkingBeatmap(Ruleset ruleset, Stream beatmapStream) : this(ruleset, ReadFromStream(beatmapStream)) { }
public CalculatorWorkingBeatmap(Ruleset ruleset, Stream beatmapStream)
: this(ruleset, ReadFromStream(beatmapStream)) { }

private CalculatorWorkingBeatmap(Ruleset ruleset, Beatmap beatmap) : base(beatmap.BeatmapInfo, null)
private CalculatorWorkingBeatmap(Ruleset ruleset, Beatmap beatmap)
: base(beatmap.BeatmapInfo, null)
{
_beatmap = beatmap;

// Only valid maps will be either osu! converts or osu!catch maps
_beatmap.BeatmapInfo.Ruleset = beatmap.BeatmapInfo.Ruleset.OnlineID == 0 ? new OsuRuleset().RulesetInfo : ruleset.RulesetInfo;
_beatmap.BeatmapInfo.Ruleset =
beatmap.BeatmapInfo.Ruleset.OnlineID == 0
? new OsuRuleset().RulesetInfo
: ruleset.RulesetInfo;
}

private static Beatmap ReadFromStream(Stream stream)
Expand All @@ -31,9 +36,13 @@ private static Beatmap ReadFromStream(Stream stream)
}

protected override IBeatmap GetBeatmap() => _beatmap;

public override Texture GetBackground() => null;

protected override Track GetBeatmapTrack() => null;

protected override ISkin GetSkin() => null;

public override Stream GetStream(string storagePath) => null;
}
}
108 changes: 76 additions & 32 deletions Difficalcy.Catch/Services/CatchCalculatorService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@

namespace Difficalcy.Catch.Services
{
public class CatchCalculatorService(ICache cache, IBeatmapProvider beatmapProvider) : CalculatorService<CatchScore, CatchDifficulty, CatchPerformance, CatchCalculation>(cache)
public class CatchCalculatorService(ICache cache, IBeatmapProvider beatmapProvider)
: CalculatorService<CatchScore, CatchDifficulty, CatchPerformance, CatchCalculation>(cache)
{
private CatchRuleset CatchRuleset { get; } = new CatchRuleset();

Expand All @@ -28,14 +29,18 @@ public override CalculatorInfo Info
get
{
var packageName = Assembly.GetAssembly(typeof(CatchRuleset)).GetName().Name;
var packageVersion = Assembly.GetAssembly(typeof(CatchRuleset)).GetName().Version.ToString();
var packageVersion = Assembly
.GetAssembly(typeof(CatchRuleset))
.GetName()
.Version.ToString();
return new CalculatorInfo
{
RulesetName = CatchRuleset.Description,
CalculatorName = "Official osu!catch",
CalculatorPackage = packageName,
CalculatorVersion = packageVersion,
CalculatorUrl = $"https://nuget.org/packages/ppy.{packageName}/{packageVersion}"
CalculatorUrl =
$"https://nuget.org/packages/ppy.{packageName}/{packageVersion}",
};
}
}
Expand All @@ -45,57 +50,82 @@ protected override async Task EnsureBeatmap(string beatmapId)
await beatmapProvider.EnsureBeatmap(beatmapId);
}

protected override (object, string) CalculateDifficultyAttributes(string beatmapId, Mod[] mods)
protected override (object, string) CalculateDifficultyAttributes(
string beatmapId,
Mod[] mods
)
{
var workingBeatmap = GetWorkingBeatmap(beatmapId);
var lazerMods = mods.Select(ModToLazerMod).ToArray();

var difficultyCalculator = CatchRuleset.CreateDifficultyCalculator(workingBeatmap);
var difficultyAttributes = difficultyCalculator.Calculate(lazerMods) as CatchDifficultyAttributes;
var difficultyAttributes =
difficultyCalculator.Calculate(lazerMods) as CatchDifficultyAttributes;

// 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
{
difficultyAttributes.StarRating,
difficultyAttributes.MaxCombo,
difficultyAttributes.ApproachRate
}));
return (
difficultyAttributes,
JsonSerializer.Serialize(
new
{
difficultyAttributes.StarRating,
difficultyAttributes.MaxCombo,
difficultyAttributes.ApproachRate,
}
)
);
}

protected override object DeserialiseDifficultyAttributes(string difficultyAttributesJson)
{
return JsonSerializer.Deserialize<CatchDifficultyAttributes>(difficultyAttributesJson);
}

protected override CatchCalculation CalculatePerformance(CatchScore score, object difficultyAttributes)
protected override CatchCalculation CalculatePerformance(
CatchScore score,
object difficultyAttributes
)
{
var catchDifficultyAttributes = (CatchDifficultyAttributes)difficultyAttributes;

var workingBeatmap = GetWorkingBeatmap(score.BeatmapId);
var mods = score.Mods.Select(ModToLazerMod).ToArray();
var beatmap = workingBeatmap.GetPlayableBeatmap(CatchRuleset.RulesetInfo, mods);

var combo = score.Combo ?? beatmap.HitObjects.Count(h => h is Fruit) + beatmap.HitObjects.OfType<JuiceStream>().SelectMany(j => j.NestedHitObjects).Count(h => !(h is TinyDroplet));
var statistics = GetHitResults(beatmap, score.Misses, score.LargeDroplets, score.SmallDroplets);
var combo =
score.Combo
?? beatmap.HitObjects.Count(h => h is Fruit)
+ beatmap
.HitObjects.OfType<JuiceStream>()
.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)
{
Accuracy = accuracy,
MaxCombo = combo,
Statistics = statistics,
Mods = mods
Mods = mods,
};

var performanceCalculator = CatchRuleset.CreatePerformanceCalculator();
var performanceAttributes = performanceCalculator.Calculate(scoreInfo, catchDifficultyAttributes) as CatchPerformanceAttributes;
var performanceAttributes =
performanceCalculator.Calculate(scoreInfo, catchDifficultyAttributes)
as CatchPerformanceAttributes;

return new CatchCalculation()
{
Difficulty = GetDifficultyFromDifficultyAttributes(catchDifficultyAttributes),
Performance = GetPerformanceFromPerformanceAttributes(performanceAttributes),
Accuracy = accuracy,
Combo = combo
Combo = combo,
};
}

Expand All @@ -114,11 +144,24 @@ private LazerMod ModToLazerMod(Mod mod)
return apiMod.ToMod(CatchRuleset);
}

private static Dictionary<HitResult, int> GetHitResults(IBeatmap beatmap, int countMiss, int? countDroplet, int? countTinyDroplet)
private static Dictionary<HitResult, int> GetHitResults(
IBeatmap beatmap,
int countMiss,
int? countDroplet,
int? countTinyDroplet
)
{
var maxTinyDroplets = beatmap.HitObjects.OfType<JuiceStream>().Sum(s => s.NestedHitObjects.OfType<TinyDroplet>().Count());
var maxDroplets = beatmap.HitObjects.OfType<JuiceStream>().Sum(s => s.NestedHitObjects.OfType<Droplet>().Count()) - maxTinyDroplets;
var maxFruits = beatmap.HitObjects.OfType<Fruit>().Count() + 2 * beatmap.HitObjects.OfType<JuiceStream>().Count() + beatmap.HitObjects.OfType<JuiceStream>().Sum(s => s.RepeatCount);
var maxTinyDroplets = beatmap
.HitObjects.OfType<JuiceStream>()
.Sum(s => s.NestedHitObjects.OfType<TinyDroplet>().Count());
var maxDroplets =
beatmap
.HitObjects.OfType<JuiceStream>()
.Sum(s => s.NestedHitObjects.OfType<Droplet>().Count()) - maxTinyDroplets;
var maxFruits =
beatmap.HitObjects.OfType<Fruit>().Count()
+ 2 * beatmap.HitObjects.OfType<JuiceStream>().Count()
+ beatmap.HitObjects.OfType<JuiceStream>().Sum(s => s.RepeatCount);

var countDroplets = countDroplet ?? maxDroplets;
var countTinyDroplets = countTinyDroplet ?? maxTinyDroplets;
Expand All @@ -142,7 +185,10 @@ private static Dictionary<HitResult, int> GetHitResults(IBeatmap beatmap, int co

private static double CalculateAccuracy(Dictionary<HitResult, int> statistics)
{
double hits = statistics[HitResult.Great] + statistics[HitResult.LargeTickHit] + statistics[HitResult.SmallTickHit];
double hits =
statistics[HitResult.Great]
+ statistics[HitResult.LargeTickHit]
+ statistics[HitResult.SmallTickHit];
double total = hits + statistics[HitResult.Miss] + statistics[HitResult.SmallTickMiss];

if (total == 0)
Expand All @@ -151,20 +197,18 @@ private static double CalculateAccuracy(Dictionary<HitResult, int> statistics)
return hits / total;
}

private static CatchDifficulty GetDifficultyFromDifficultyAttributes(CatchDifficultyAttributes difficultyAttributes)
private static CatchDifficulty GetDifficultyFromDifficultyAttributes(
CatchDifficultyAttributes difficultyAttributes
)
{
return new CatchDifficulty()
{
Total = difficultyAttributes.StarRating
};
return new CatchDifficulty() { Total = difficultyAttributes.StarRating };
}

private static CatchPerformance GetPerformanceFromPerformanceAttributes(CatchPerformanceAttributes performanceAttributes)
private static CatchPerformance GetPerformanceFromPerformanceAttributes(
CatchPerformanceAttributes performanceAttributes
)
{
return new CatchPerformance()
{
Total = performanceAttributes.Total
};
return new CatchPerformance() { Total = performanceAttributes.Total };
}
}
}
3 changes: 2 additions & 1 deletion Difficalcy.Catch/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ public class Startup(IConfiguration configuration) : DifficalcyStartup(configura

public override string OpenApiVersion => "v1";

protected override string TestBeatmapAssembly => Assembly.GetExecutingAssembly().GetName().Name;
protected override string TestBeatmapAssembly =>
Assembly.GetExecutingAssembly().GetName().Name;

public override void ConfigureCalculatorServices(IServiceCollection services)
{
Expand Down
Loading