Skip to content

Commit

Permalink
Merge pull request #193 from Syriiin/json-mods/frontend-support
Browse files Browse the repository at this point in the history
Support json mods for view parameters
  • Loading branch information
Syriiin authored Dec 22, 2024
2 parents 0789f31 + b5a4a27 commit f60bc71
Show file tree
Hide file tree
Showing 7 changed files with 122 additions and 49 deletions.
29 changes: 28 additions & 1 deletion common/osu/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
get_gamemode_string_from_gamemode,
get_json_mods,
get_length,
get_mod_acronyms,
get_mods_string,
get_mods_string_from_json_mods,
get_od,
Expand Down Expand Up @@ -147,6 +148,9 @@ def test_get_mods_string():
assert (
get_mods_string(Mods.HIDDEN + Mods.DOUBLETIME + Mods.SUDDEN_DEATH) == "HD,SD,DT"
)
assert (
get_mods_string(Mods.SUDDEN_DEATH + Mods.DOUBLETIME + Mods.HIDDEN) == "HD,SD,DT"
)


def test_get_mods_string_from_json_mods():
Expand All @@ -158,6 +162,12 @@ def test_get_mods_string_from_json_mods():
)
== "HD,SD,DT"
)
assert (
get_mods_string_from_json_mods(
{NewMods.SUDDEN_DEATH: {}, NewMods.DOUBLETIME: {}, NewMods.HIDDEN: {}}
)
== "HD,SD,DT"
)
assert (
get_mods_string_from_json_mods(
{
Expand All @@ -171,7 +181,7 @@ def test_get_mods_string_from_json_mods():
)


def test_get_json_object_mods():
def test_get_json_mods():
assert get_json_mods(Mods.HIDDEN + Mods.DOUBLETIME + Mods.SUDDEN_DEATH, True) == {
"HD": {},
"SD": {},
Expand All @@ -195,6 +205,23 @@ def test_get_json_object_mods():
}


def test_get_mod_acronyms():
assert get_mod_acronyms(Mods.HIDDEN + Mods.DOUBLETIME + Mods.SUDDEN_DEATH) == [
"HD",
"SD",
"DT",
]
assert get_mod_acronyms(Mods.SUDDEN_DEATH + Mods.DOUBLETIME + Mods.HIDDEN) == [
"HD",
"SD",
"DT",
]

assert get_mod_acronyms(
Mods.HARDROCK + Mods.NIGHTCORE + Mods.FLASHLIGHT + Mods.PERFECT
) == ["HR", "NC", "FL", "PF"]


def test_get_bitwise_mods():
assert (
get_bitwise_mods(["HD", "DT", "SD", "CL"])
Expand Down
2 changes: 1 addition & 1 deletion leaderboards/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ def send_leaderboard_top_score_notification(leaderboard_id: int, score_id: int):
leaderboard_link = f"{settings.FRONTEND_URL}/leaderboards/{get_leaderboard_type_string_from_leaderboard_access_type(leaderboard.access_type)}/{get_gamemode_string_from_gamemode(leaderboard.gamemode)}/{leaderboard.id}"

beatmap_details = f"[{score.beatmap}](https://osu.ppy.sh/beatmapsets/{score.beatmap.set_id}#{get_gamemode_string_from_gamemode(score.beatmap.gamemode)}/{score.beatmap.id})"
if score.mods != Mods.NONE:
if len(score.mods_json) != 0:
beatmap_details += f" +{get_mods_string_from_json_mods(score.mods_json)}"

performance_calculation = score.get_performance_calculation()
Expand Down
28 changes: 19 additions & 9 deletions leaderboards/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

from common.osu.difficultycalculator import get_default_difficulty_calculator_class
from common.osu.enums import Gamemode, Mods
from common.osu.utils import get_mod_acronyms
from common.osu.utils import get_bitwise_mods, get_mod_acronyms
from common.utils import parse_int_or_none
from leaderboards.enums import LeaderboardAccessType
from leaderboards.models import Invite, Leaderboard, Membership
Expand Down Expand Up @@ -129,6 +129,20 @@ def post(self, request, leaderboard_type, gamemode):
"primary_performance_value", "total"
)

if "required_mods_json" in score_filter_data:
required_mods_json = score_filter_data["required_mods_json"]
required_mods = get_bitwise_mods(required_mods_json)
else:
required_mods = score_filter_data.get("required_mods", Mods.NONE)
required_mods_json = get_mod_acronyms(required_mods)

if "disqualified_mods_json" in score_filter_data:
disqualified_mods_json = score_filter_data["disqualified_mods_json"]
disqualified_mods = get_bitwise_mods(disqualified_mods_json)
else:
disqualified_mods = score_filter_data.get("disqualified_mods", Mods.NONE)
disqualified_mods_json = get_mod_acronyms(disqualified_mods)

leaderboard = Leaderboard(
gamemode=gamemode,
score_set=score_set,
Expand All @@ -153,14 +167,10 @@ def post(self, request, leaderboard_type, gamemode):
highest_od=score_filter_data.get("highest_od"),
lowest_cs=score_filter_data.get("lowest_cs"),
highest_cs=score_filter_data.get("highest_cs"),
required_mods=score_filter_data.get("required_mods", Mods.NONE),
required_mods_json=get_mod_acronyms(
score_filter_data.get("required_mods", Mods.NONE)
),
disqualified_mods=score_filter_data.get("disqualified_mods", Mods.NONE),
disqualified_mods_json=get_mod_acronyms(
score_filter_data.get("disqualified_mods", Mods.NONE)
),
required_mods=required_mods,
required_mods_json=required_mods_json,
disqualified_mods=disqualified_mods,
disqualified_mods_json=disqualified_mods_json,
lowest_accuracy=score_filter_data.get("lowest_accuracy"),
highest_accuracy=score_filter_data.get("highest_accuracy"),
lowest_length=score_filter_data.get("lowest_length"),
Expand Down
2 changes: 1 addition & 1 deletion profiles/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ def user(self, obj: Score):

@admin.display(description="Mods")
def mods_display(self, obj: Score):
if obj.mods == Mods.NONE:
if len(obj.mods_json) == 0:
return None
return utils.get_mods_string_from_json_mods(obj.mods_json)

Expand Down
12 changes: 9 additions & 3 deletions profiles/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
get_default_difficulty_calculator_class,
get_difficulty_calculator_class_for_engine,
)
from common.osu.enums import BeatmapStatus, Gamemode, Mods
from common.osu.enums import BeatmapStatus, Gamemode, Mods, NewMods
from common.osu.osuapi import BeatmapData
from profiles.enums import AllowedBeatmapStatus, ScoreMutation, ScoreResult, ScoreSet

Expand Down Expand Up @@ -576,12 +576,18 @@ def get_nochoke_mutation(self):
gamemode=gamemode,
)
if score.accuracy == 1:
if score.mods & Mods.HIDDEN or score.mods & Mods.FLASHLIGHT:
if (
NewMods.HIDDEN in score.mods_json
or NewMods.FLASHLIGHT in score.mods_json
):
score.rank = "XH"
else:
score.rank = "X"
else:
if score.mods & Mods.HIDDEN or score.mods & Mods.FLASHLIGHT:
if (
NewMods.HIDDEN in score.mods_json
or NewMods.FLASHLIGHT in score.mods_json
):
score.rank = "SH"
else:
score.rank = "S"
Expand Down
42 changes: 27 additions & 15 deletions profiles/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from rest_framework.views import APIView

from common.osu.enums import Gamemode, Mods
from common.osu.utils import get_json_mods, get_mod_acronyms
from common.osu.utils import get_bitwise_mods, get_mod_acronyms
from common.utils import parse_float_or_none, parse_int_or_none
from leaderboards.models import Membership
from leaderboards.serialisers import UserMembershipSerialiser
Expand Down Expand Up @@ -97,12 +97,30 @@ def get(self, request, user_id, gamemode):
"""
Return Scores based on a user_id, gamemode, score_set, and various filters
"""
required_mods = parse_int_or_none(
request.query_params.get("required_mods", Mods.NONE)
)
disqualified_mods = parse_int_or_none(
request.query_params.get("disqualified_mods", Mods.NONE)
)
if "required_mods_json" in request.query_params:
required_mods_json = request.query_params["required_mods_json"]
required_mods = get_bitwise_mods(required_mods_json)
else:
required_mods = parse_int_or_none(
request.query_params.get("required_mods", Mods.NONE)
)
required_mods_json = (
get_mod_acronyms(required_mods) if required_mods is not None else []
)

if "disqualified_mods_json" in request.query_params:
disqualified_mods_json = request.query_params["disqualified_mods_json"]
disqualified_mods = get_bitwise_mods(disqualified_mods_json)
else:
disqualified_mods = parse_int_or_none(
request.query_params.get("disqualified_mods", Mods.NONE)
)
disqualified_mods_json = (
get_mod_acronyms(disqualified_mods)
if disqualified_mods is not None
else []
)

score_filter = ScoreFilter(
allowed_beatmap_status=parse_int_or_none(
request.query_params.get(
Expand All @@ -120,15 +138,9 @@ def get(self, request, user_id, gamemode):
lowest_cs=parse_float_or_none(request.query_params.get("lowest_cs")),
highest_cs=parse_float_or_none(request.query_params.get("highest_cs")),
required_mods=required_mods,
required_mods_json=(
get_mod_acronyms(required_mods) if required_mods is not None else []
),
required_mods_json=required_mods_json,
disqualified_mods=disqualified_mods,
disqualified_mods_json=(
get_mod_acronyms(disqualified_mods)
if disqualified_mods is not None
else []
),
disqualified_mods_json=disqualified_mods_json,
lowest_accuracy=parse_float_or_none(
request.query_params.get("lowest_accuracy")
),
Expand Down
56 changes: 37 additions & 19 deletions users/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from rest_framework.views import APIView

from common.osu.enums import Mods
from common.osu.utils import get_json_mods, get_mod_acronyms
from common.osu.utils import get_bitwise_mods, get_mod_acronyms
from leaderboards.models import Invite
from leaderboards.serialisers import UserInviteSerialiser
from osuauth.serialisers import UserSerialiser
Expand Down Expand Up @@ -74,6 +74,20 @@ def post(self, request):
if score_filter_data is None:
raise ParseError("Missing score_filter parameter.")

if "required_mods_json" in score_filter_data:
required_mods_json = score_filter_data["required_mods_json"]
required_mods = get_bitwise_mods(required_mods_json)
else:
required_mods = score_filter_data.get("required_mods", Mods.NONE)
required_mods_json = get_mod_acronyms(required_mods)

if "disqualified_mods_json" in score_filter_data:
disqualified_mods_json = score_filter_data["disqualified_mods_json"]
disqualified_mods = get_bitwise_mods(disqualified_mods_json)
else:
disqualified_mods = score_filter_data.get("disqualified_mods", Mods.NONE)
disqualified_mods_json = get_mod_acronyms(disqualified_mods)

score_filter_preset = ScoreFilterPreset.objects.create(
name=name,
user=request.user,
Expand All @@ -91,14 +105,10 @@ def post(self, request):
highest_od=score_filter_data.get("highest_od"),
lowest_cs=score_filter_data.get("lowest_cs"),
highest_cs=score_filter_data.get("highest_cs"),
required_mods=score_filter_data.get("required_mods", Mods.NONE),
required_mods_json=get_mod_acronyms(
score_filter_data.get("required_mods", Mods.NONE)
),
disqualified_mods=score_filter_data.get("disqualified_mods", Mods.NONE),
disqualified_mods_json=get_mod_acronyms(
score_filter_data.get("disqualified_mods", Mods.NONE)
),
required_mods=required_mods,
required_mods_json=required_mods_json,
disqualified_mods=disqualified_mods,
disqualified_mods_json=disqualified_mods_json,
lowest_accuracy=score_filter_data.get("lowest_accuracy"),
highest_accuracy=score_filter_data.get("highest_accuracy"),
lowest_length=score_filter_data.get("lowest_length"),
Expand Down Expand Up @@ -145,6 +155,20 @@ def put(self, request, score_filter_preset_id):
)
preset.name = name

if "required_mods_json" in score_filter_data:
required_mods_json = score_filter_data["required_mods_json"]
required_mods = get_bitwise_mods(required_mods_json)
else:
required_mods = score_filter_data.get("required_mods", Mods.NONE)
required_mods_json = get_mod_acronyms(required_mods)

if "disqualified_mods_json" in score_filter_data:
disqualified_mods_json = score_filter_data["disqualified_mods_json"]
disqualified_mods = get_bitwise_mods(disqualified_mods_json)
else:
disqualified_mods = score_filter_data.get("disqualified_mods", Mods.NONE)
disqualified_mods_json = get_mod_acronyms(disqualified_mods)

score_filter = preset.score_filter
score_filter.allowed_beatmap_status = score_filter_data.get(
"allowed_beatmap_status", AllowedBeatmapStatus.RANKED_ONLY
Expand All @@ -159,16 +183,10 @@ def put(self, request, score_filter_preset_id):
score_filter.highest_od = score_filter_data.get("highest_od")
score_filter.lowest_cs = score_filter_data.get("lowest_cs")
score_filter.highest_cs = score_filter_data.get("highest_cs")
score_filter.required_mods = score_filter_data.get("required_mods", Mods.NONE)
score_filter.required_mods_json = get_mod_acronyms(
score_filter_data.get("required_mods", Mods.NONE)
)
score_filter.disqualified_mods = score_filter_data.get(
"disqualified_mods", Mods.NONE
)
score_filter.disqualified_mods_json = get_mod_acronyms(
score_filter_data.get("disqualified_mods", Mods.NONE)
)
score_filter.required_mods = required_mods
score_filter.required_mods_json = required_mods_json
score_filter.disqualified_mods = disqualified_mods
score_filter.disqualified_mods_json = disqualified_mods_json
score_filter.lowest_accuracy = score_filter_data.get("lowest_accuracy")
score_filter.highest_accuracy = score_filter_data.get("highest_accuracy")
score_filter.lowest_length = score_filter_data.get("lowest_length")
Expand Down

0 comments on commit f60bc71

Please sign in to comment.