Skip to content

Commit e7177b7

Browse files
committed
Add /available_rulesets route
1 parent 6b66bed commit e7177b7

4 files changed

Lines changed: 114 additions & 2 deletions

File tree

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// Copyright (c) 2025 GooGuTeam
2+
// Licensed under the MIT Licence. See the LICENCE file in the repository root for full licence text.
3+
4+
using Microsoft.AspNetCore.Mvc;
5+
using PerformanceServer.Rulesets;
6+
7+
namespace PerformanceServer
8+
{
9+
[ApiController]
10+
[Route("available_rulesets")]
11+
public class AvailableRulesetController(IRulesetManager manager) : ControllerBase
12+
{
13+
[HttpGet]
14+
[Produces("application/json")]
15+
[ProducesResponseType(StatusCodes.Status200OK)]
16+
public async Task<ActionResult<string[]>> GetAvailableRulesets()
17+
{
18+
return await Task.FromResult(Ok(new Dictionary<string, string[]>
19+
{
20+
{
21+
"has_performance_calculator",
22+
manager.GetHasPerformCalculatorRulesets().Select(r => r.ShortName).ToArray()
23+
},
24+
{
25+
"has_difficulty_calculator",
26+
manager.GetHasDifficultyCalculatorRulesets().Select(r => r.ShortName).ToArray()
27+
},
28+
{ "loaded_rulesets", manager.GetRulesets().Select(r => r.ShortName).ToArray() }
29+
}));
30+
}
31+
}
32+
}

PerformanceServer/Rulesets/IRulesetManager.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,9 @@ public interface IRulesetManager
1010
public Ruleset GetRuleset(int rulesetId);
1111
public Ruleset GetRuleset(string shortName);
1212
public Ruleset GetRuleset(INeedsRuleset body, int defaultRulesetId = -1);
13+
14+
public IEnumerable<Ruleset> GetRulesets();
15+
public IEnumerable<Ruleset> GetHasPerformCalculatorRulesets();
16+
public IEnumerable<Ruleset> GetHasDifficultyCalculatorRulesets();
1317
}
1418
}

PerformanceServer/Rulesets/RulesetManager.cs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
using osu.Game.Rulesets;
55
using osu.Game.Rulesets.Catch;
6+
using osu.Game.Rulesets.Difficulty;
67
using osu.Game.Rulesets.Mania;
78
using osu.Game.Rulesets.Osu;
89
using osu.Game.Rulesets.Taiko;
@@ -18,6 +19,8 @@ public class RulesetManager : IRulesetManager
1819

1920
private readonly Dictionary<string, Ruleset> _rulesets = new();
2021
private readonly Dictionary<int, Ruleset> _rulesetsById = new();
22+
private readonly List<string> _hasPerformanceCalculatorRulesets = new();
23+
private readonly List<string> _hasDifficultyCalculatorRulesets = new();
2124

2225
public RulesetManager(ILogger<RulesetManager> logger)
2326
{
@@ -26,6 +29,22 @@ public RulesetManager(ILogger<RulesetManager> logger)
2629
LoadFromDisk();
2730
}
2831

32+
private static Tuple<bool, bool> GetAttributeTypesForRuleset(Ruleset ruleset)
33+
{
34+
bool hasPerformanceType = false;
35+
bool hasDifficultyType = false;
36+
37+
foreach (Type type in Assembly.GetAssembly(ruleset.GetType())!.GetTypes())
38+
{
39+
if (type.IsSubclassOf(typeof(PerformanceCalculator)))
40+
hasPerformanceType = true;
41+
else if (type.IsSubclassOf(typeof(DifficultyCalculator)))
42+
hasDifficultyType = true;
43+
}
44+
45+
return Tuple.Create(hasPerformanceType, hasDifficultyType);
46+
}
47+
2948
private void AddRuleset(Ruleset ruleset)
3049
{
3150
if (!_rulesets.TryAdd(ruleset.ShortName, ruleset))
@@ -34,6 +53,17 @@ private void AddRuleset(Ruleset ruleset)
3453
return;
3554
}
3655

56+
Tuple<bool, bool> performanceAndDifficultyTypes = GetAttributeTypesForRuleset(ruleset);
57+
if (performanceAndDifficultyTypes.Item1)
58+
{
59+
_hasPerformanceCalculatorRulesets.Add(ruleset.ShortName);
60+
}
61+
62+
if (performanceAndDifficultyTypes.Item2)
63+
{
64+
_hasDifficultyCalculatorRulesets.Add(ruleset.ShortName);
65+
}
66+
3767
if (ruleset is not ILegacyRuleset legacyRuleset)
3868
{
3969
return;
@@ -125,5 +155,20 @@ public Ruleset GetRuleset(INeedsRuleset body, int defaultRulesetId = -1)
125155

126156
return ruleset;
127157
}
158+
159+
public IEnumerable<Ruleset> GetRulesets()
160+
{
161+
return _rulesets.Values;
162+
}
163+
164+
public IEnumerable<Ruleset> GetHasPerformCalculatorRulesets()
165+
{
166+
return _hasPerformanceCalculatorRulesets.Select(shortName => _rulesets[shortName]);
167+
}
168+
169+
public IEnumerable<Ruleset> GetHasDifficultyCalculatorRulesets()
170+
{
171+
return _hasDifficultyCalculatorRulesets.Select(shortName => _rulesets[shortName]);
172+
}
128173
}
129174
}

README.md

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ A server for calculating osu! performance points (pp) and star ratings.
3434

3535
- `GET /` returns `{ "status": "ok", "time": "<UTC timestamp>" }` for readiness probes.
3636

37-
### POST /difficulty
37+
## POST /difficulty
3838

3939
Calculate difficulty attributes for a beatmap (star rating, etc.).
4040

@@ -77,7 +77,7 @@ Error Cases:
7777
- `400 Bad Request` – Internal calculation failed (rare / invalid input).
7878
- `503 Service Unavailable` – Remote fetch failed (e.g., beatmap not accessible online).
7979

80-
### POST /performance
80+
## POST /performance
8181

8282
Calculate performance attributes (pp) using both difficulty and supplied score context.
8383

@@ -129,6 +129,37 @@ Error Cases:
129129
- `400 Bad Request` – Calculation failed (e.g., malformed beatmap or inconsistent inputs).
130130
- `503 Service Unavailable` – Beatmap fetch failed.
131131

132+
## GET /available_rulesets
133+
134+
```bash
135+
curl -X GET "http://localhost:5225/available_rulesets"
136+
```
137+
138+
Response: `200 OK` with a JSON object like this:
139+
140+
```json
141+
{
142+
"has_performance_calculator": [
143+
"osu",
144+
"taiko",
145+
"fruits",
146+
"mania"
147+
],
148+
"has_difficulty_calculator": [
149+
"osu",
150+
"taiko",
151+
"fruits",
152+
"mania"
153+
],
154+
"loaded_rulesets": [
155+
"osu",
156+
"taiko",
157+
"fruits",
158+
"mania"
159+
]
160+
}
161+
```
162+
132163
## Curl Examples
133164

134165
```bash

0 commit comments

Comments
 (0)