Skip to content

Commit

Permalink
Merge pull request #97 from Syriiin/add-formatter
Browse files Browse the repository at this point in the history
Add code formatter
  • Loading branch information
Syriiin authored Nov 12, 2024
2 parents fc97196 + 941c2c0 commit fb487cd
Show file tree
Hide file tree
Showing 44 changed files with 779 additions and 287 deletions.
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

0 comments on commit fb487cd

Please sign in to comment.