Skip to content

Commit

Permalink
Fix pack pass check considering converted plays when pack is not asso…
Browse files Browse the repository at this point in the history
…ciated with a ruleset

Reported privately.

The corresponding web-10 query looks like this (somewhat abridged):

	SELECT COUNT(*) FROM (
        SELECT p.beatmapset_id FROM osu_beatmappacks_items p JOIN osu_beatmaps b USING (beatmapset_id) JOIN osu_scores_high s USING (beatmap_id) WHERE s.user_id = userId AND b.playmode = 0 AND pack_id = packId UNION DISTINCT
        SELECT p.beatmapset_id FROM osu_beatmappacks_items p JOIN osu_beatmaps b USING (beatmapset_id) JOIN osu_scores_taiko_high s USING (beatmap_id) WHERE s.user_id = userId AND b.playmode = 1 AND pack_id = packId UNION DISTINCT
        SELECT p.beatmapset_id FROM osu_beatmappacks_items p JOIN osu_beatmaps b USING (beatmapset_id) JOIN osu_scores_fruits_high s USING (beatmap_id) WHERE s.user_id = userId AND b.playmode = 2 AND pack_id = packId UNION DISTINCT
        SELECT p.beatmapset_id FROM osu_beatmappacks_items p JOIN osu_beatmaps b USING (beatmapset_id) JOIN osu_scores_mania_high s USING (beatmap_id) WHERE s.user_id =  userId} AND b.playmode = 3 AND pack_id = packId) a

If it is not immediately clear why the above disallows converts, then to
spell it out: it is the part that the query is split into four
`UNION`'d parts, each of which queries only one `scores_high` table for
each of the rulesets, and only includes the beatmaps in the pack which
have the same `playmode`.

For profiling purposes, here are two examples of query shapes after this
change, taken from the test:

	SELECT COUNT(distinct p.beatmapset_id)
	FROM osu_beatmappacks_items p
	JOIN osu_beatmaps b USING (beatmapset_id)
	JOIN scores s USING (beatmap_id)
	WHERE s.user_id = 2 AND s.passed = 1 AND s.preserve = 1 AND pack_id = 40 AND `s`.`ruleset_id` = `b`.`playmode`

	SELECT COUNT(distinct p.beatmapset_id)
	FROM osu_beatmappacks_items p
	JOIN osu_beatmaps b USING (beatmapset_id)
	JOIN scores s USING (beatmap_id)
	WHERE s.user_id = 2 AND s.passed = 1 AND s.preserve = 1 AND pack_id = 2036 AND `s`.`ruleset_id` = `b`.`playmode`
	AND json_search(data, 'one', 'EZ', null, '$.mods[*].acronym') IS NULL
	AND json_search(data, 'one', 'NF', null, '$.mods[*].acronym') IS NULL
	AND json_search(data, 'one', 'HT', null, '$.mods[*].acronym') IS NULL
	AND json_search(data, 'one', 'DC', null, '$.mods[*].acronym') IS NULL
	AND json_search(data, 'one', 'SO', null, '$.mods[*].acronym') IS NULL
	AND s.pp IS NOT NULL
  • Loading branch information
bdach committed Sep 6, 2024
1 parent 9ef3bb6 commit 6b66e9e
Showing 1 changed file with 5 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ public static bool IsPermittedInNoModContext(Mod m)
public static bool UserPassedPack(MedalAwarderContext context, bool noReductionMods, int packId)
{
string modsCriteria = string.Empty;
string rulesetCriteria = string.Empty;
string rulesetCriteria;

if (noReductionMods)
{
Expand All @@ -83,6 +83,10 @@ public static bool UserPassedPack(MedalAwarderContext context, bool noReductionM

rulesetCriteria = $"AND ruleset_id = {packRulesetId}";
}
else
{
rulesetCriteria = "AND `s`.`ruleset_id` = `b`.`playmode`";
}

// TODO: no index on (beatmap_id, user_id) may mean this is too slow.
// note that the `preserve = 1` condition relies on the flag being set before score processing (https://github.com/ppy/osu-web/pull/10946).
Expand Down

0 comments on commit 6b66e9e

Please sign in to comment.