diff --git a/PerformanceCalculator/Performance/ScorePerformanceCommand.cs b/PerformanceCalculator/Performance/ScorePerformanceCommand.cs index a657a5991..c8c6dbe7f 100644 --- a/PerformanceCalculator/Performance/ScorePerformanceCommand.cs +++ b/PerformanceCalculator/Performance/ScorePerformanceCommand.cs @@ -84,23 +84,41 @@ private DifficultyAttributes queryApiAttributes(int beatmapId, int rulesetId, Le { "mods", ((int)mods).ToString(CultureInfo.InvariantCulture) } }; + var beatmap = GetJsonFromApi($"beatmaps/{beatmapId}"); + switch (rulesetId) { case 0: - return GetJsonFromApi>($"beatmaps/{beatmapId}/attributes", HttpMethod.Post, parameters).Attributes; + return getMergedAttributes(beatmap); case 1: - return GetJsonFromApi>($"beatmaps/{beatmapId}/attributes", HttpMethod.Post, parameters).Attributes; + return getMergedAttributes(beatmap); case 2: - return GetJsonFromApi>($"beatmaps/{beatmapId}/attributes", HttpMethod.Post, parameters).Attributes; + return getMergedAttributes(beatmap); case 3: - return GetJsonFromApi>($"beatmaps/{beatmapId}/attributes", HttpMethod.Post, parameters).Attributes; + return getMergedAttributes(beatmap); default: throw new ArgumentOutOfRangeException(nameof(rulesetId)); } + + DifficultyAttributes getMergedAttributes(APIBeatmap apiBeatmap) + where TAttributes : DifficultyAttributes, new() + { + // the osu-web endpoint queries osu-beatmap-difficulty-cache, which in turn does not return the full set of attributes - + // it skips ones that are already present on `APIBeatmap` + // (https://github.com/ppy/osu-beatmap-difficulty-lookup-cache/blob/db2203368221109803f2031788da31deb94e0f11/BeatmapDifficultyLookupCache/DifficultyCache.cs#L125-L128). + // to circumvent this, do some manual grafting on our side to produce a fully populated set of attributes. + var databasedAttributes = GetJsonFromApi>($"beatmaps/{beatmapId}/attributes", HttpMethod.Post, parameters).Attributes; + var fullAttributes = new TAttributes(); + fullAttributes.FromDatabaseAttributes(databasedAttributes.ToDatabaseAttributes().ToDictionary( + pair => pair.attributeId, + pair => Convert.ToDouble(pair.value, CultureInfo.InvariantCulture) + ), apiBeatmap); + return fullAttributes; + } } [JsonObject(MemberSerialization.OptIn)]