Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: simplify !with command argument parsing #356

Closed
wants to merge 23 commits into from
Closed
Changes from 11 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
8965490
reworked !with command
minisbett Jan 9, 2023
b967689
Remove old parsing of !with
minisbett Jan 10, 2023
d37d112
Add acc validation
minisbett Jan 10, 2023
080cd56
Merge branch 'master' into with-rework
minisbett Jan 10, 2023
8ea50ab
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jan 10, 2023
a3f45b4
Merge branch 'osuAkatsuki:master' into with-rework
minisbett Jan 10, 2023
c3db130
Merge branch 'osuAkatsuki:master' into with-rework
minisbett Jan 13, 2023
7ff34ea
Fixed parameter handling in command
minisbett Jan 15, 2023
22f6346
Merge branch 'osuAkatsuki:master' into with-rework
minisbett Jan 15, 2023
e9799a5
Merge branch 'master' into with-rework
minisbett Jan 19, 2023
76a2fac
Merge branch 'master' into with-rework
NiceAesth Jan 31, 2023
643b029
Merge branch 'master' into with-rework
minisbett Sep 23, 2023
084d4ad
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Sep 23, 2023
f7b8dd0
Merge branch 'osuAkatsuki:master' into with-rework
minisbett Sep 25, 2023
5047a14
Add mods to playr.last_np
minisbett Sep 25, 2023
42701ee
Merge branch 'master' into add-mods-to-np
minisbett Sep 25, 2023
e723e7b
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Sep 25, 2023
4488574
Merge remote-tracking branch 'origin/add-mods-to-np' into with-rework
minisbett Sep 25, 2023
3fe2a99
Bring code up to date, do further refactoring, add player.last_np["mo…
minisbett Sep 25, 2023
4c3a5b4
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Sep 25, 2023
6934419
Remove debug print
minisbett Sep 25, 2023
8d47f3f
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Sep 25, 2023
05bdd3c
Merge branch 'master' into with-rework
NiceAesth Nov 9, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
114 changes: 33 additions & 81 deletions app/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -423,59 +423,6 @@ async def top(ctx: Context) -> Optional[str]:
# TODO: !compare (compare to previous !last/!top post's map)


class ParsingError(str):
...


def parse__with__command_args(
mode: int,
args: Sequence[str],
) -> Union[Mapping[str, Any], ParsingError]:
"""Parse arguments for the !with command."""

# tried to balance complexity vs correctness for this function
# TODO: it can surely be cleaned up further - need to rethink it?

if not args or len(args) > 4:
return ParsingError("Invalid syntax: !with <acc/nmiss/combo/mods ...>")

# !with 95% 1m 429x hddt
acc = mods = combo = nmiss = None

# parse acc, misses, combo and mods from arguments.
# tried to balance complexity vs correctness here
for arg in (str.lower(arg) for arg in args):
# mandatory suffix, combo & nmiss
if combo is None and arg.endswith("x") and arg[:-1].isdecimal():
combo = int(arg[:-1])
# if combo > bmap.max_combo:
# return "Invalid combo."
elif nmiss is None and arg.endswith("m") and arg[:-1].isdecimal():
nmiss = int(arg[:-1])
# TODO: store nobjects?
# if nmiss > bmap.combo:
# return "Invalid misscount."
else:
# optional prefix/suffix, mods & accuracy
arg_stripped = arg.removeprefix("+").removesuffix("%")
if mods is None and arg_stripped.isalpha() and len(arg_stripped) % 2 == 0:
mods = Mods.from_modstr(arg_stripped)
mods = mods.filter_invalid_combos(mode)
elif acc is None and arg_stripped.replace(".", "", 1).isdecimal():
acc = float(arg_stripped)
if not 0 <= acc <= 100:
return ParsingError("Invalid accuracy.")
else:
return ParsingError(f"Unknown argument: {arg}")

return {
"acc": acc,
"mods": mods,
"combo": combo,
"nmiss": nmiss,
}


@command(Privileges.UNRESTRICTED, aliases=["w"], hidden=True)
async def _with(ctx: Context) -> Optional[str]:
"""Specify custom accuracy & mod combinations with `/np`."""
Expand All @@ -491,44 +438,49 @@ async def _with(ctx: Context) -> Optional[str]:
if not await ensure_local_osu_file(osu_file_path, bmap.id, bmap.md5):
return "Mapfile could not be found; this incident has been reported."

mode_vn = ctx.player.last_np["mode_vn"]

command_args = parse__with__command_args(mode_vn, ctx.args)
if isinstance(command_args, ParsingError):
return str(command_args)

msg_fields = []

score_args = ScoreParams(mode=mode_vn)
score_args = ScoreParams(mode=ctx.player.last_np["mode_vn"])
attributes_table = {
"xgeki": "ngeki",
"xkatu": "nkatu",
"x100": "n100",
"x50": "n50",
"x": "combo",
"m": "nmiss",
"%": "acc",
}

mods = command_args["mods"]
if mods is not None:
score_args.mods = mods
msg_fields.append(f"{mods!r}")
for arg in (arg.lower() for arg in ctx.args):
try:
if arg.startswith("+"):
score_args.mods = Mods.from_modstr(arg[1:]).filter_invalid_combos(
ctx.player.last_np["mode_vn"],
)
continue

nmiss = command_args["nmiss"]
if nmiss:
score_args.nmiss = nmiss
msg_fields.append(f"{nmiss}m")
for (suffix, attribute) in attributes_table.items():
if arg.endswith(suffix):
value = None
if attribute == "acc":
value = float(arg[: -len(suffix)])
if not 0 <= value <= 100:
return "Invalid accuracy. (0-100%)"
else:
value = int(arg[: -len(suffix)])

combo = command_args["combo"]
if combo is not None:
score_args.combo = combo
msg_fields.append(f"{combo}x")
setattr(score_args, attribute, value)

acc = command_args["acc"]
if acc is not None:
score_args.acc = acc
msg_fields.append(f"{acc:.2f}%")
except ValueError as ex:
print(ex)
return f"Could not parse parameter '{arg}'."

result = app.usecases.performance.calculate_performances(
osu_file_path=str(osu_file_path),
scores=[score_args], # calculate one score
)

return "{msg}: {performance:.2f}pp ({star_rating:.2f}*)".format(
msg=" ".join(msg_fields), **result[0] # (first score result)
)
return "{performance:.2f}pp ({star_rating:.2f}*)".format(
**result[0]
) # (first score result)


@command(Privileges.UNRESTRICTED, aliases=["req"])
Expand Down