Skip to content
Open
Changes from 1 commit
Commits
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
69 changes: 69 additions & 0 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,74 @@ async def clear_scores() -> None:

print(f"Deleted all clearable scores in {time.time() - start_time:.2f} seconds")

CHAMPION_BADGE_ID = 67
FORMER_CHAMPION_BADGE_ID = 66

async def update_champion_badges() -> None:
for rx in (0, 1, 2):
if rx == 0:
redis_board = "leaderboard"
modes = ("std", "taiko", "ctb", "mania")
elif rx == 1:
redis_board = "relaxboard"
modes = ("std", "taiko", "ctb")
else: # rx == 2:
redis_board = "autoboard"
modes = ("std",)

for mode in modes:
mode_int = mode + (4 * rx)
Copy link

Copilot AI Jan 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Type error: attempting to concatenate string and integer. The variable mode is a string (e.g., "std", "taiko", "ctb", "mania") but the code attempts to add it to an integer. Based on line 100 in the codebase, this should be mode_int = STR_TO_INT_MODE[mode] + (4 * rx) to correctly calculate the mode integer value.

Suggested change
mode_int = mode + (4 * rx)
mode_int = STR_TO_INT_MODE[mode] + (4 * rx)

Copilot uses AI. Check for mistakes.
rank_key = f"ripple:{redis_board}:{mode}"

# this is updated in a cron so we need to also check current rank one
users_who_peaked_at_rank_one = list(
Comment thread
cmyui marked this conversation as resolved.
await db.fetchall(
"SELECT DISTINCT user_id FROM user_profile_history WHERE mode = %s AND `rank` = 1",
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you check how many users are going to receive a badge that don't currently have it, from the switch from manual -> auto based on user_profile_history data?

Copy link
Copy Markdown
Member

@cmyui cmyui Dec 9, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there's a bit to consider here re. cases where someone cheated their way to #1 then got banned/unbanned -- I think this system would grant them the "former champion" badge in that case?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there's a bit to consider here re. cases where someone cheated their way to #1 then got banned/unbanned

if we're not wiping this table when wiping a user for an unban then that's an issue in it's own way - that would mean their peak rank on their profile would already appear as whatever they peaked while cheating 😳

[mode_int]
)
)

current_rank_one_user_id = await redis.zrevrange(rank_key, 0, 0)
users_who_peaked_at_rank_one.append({"user_id": current_rank_one_user_id})
Copy link
Copy Markdown
Member

@cmyui cmyui Dec 9, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this fetched separately to guard against the case where the #1 is not yet inserted into user_profile_history? (iirc the job runs nightly?)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, the API endpoint that the website uses to fetch peak rank does similar functionality (fetches peak from database and also current, takes whichever is lower)

Comment on lines +562 to +563
Copy link

Copilot AI Jan 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The zrevrange command returns a list, but the code treats it as a single value. This should extract the first element from the returned list (if it exists) before appending. Consider using: current_rank_one_users = await redis.zrevrange(rank_key, 0, 0) followed by conditional logic to append only if the list is not empty, extracting the first element: if current_rank_one_users: users_who_peaked_at_rank_one.append({"user_id": current_rank_one_users[0]}).

Suggested change
current_rank_one_user_id = await redis.zrevrange(rank_key, 0, 0)
users_who_peaked_at_rank_one.append({"user_id": current_rank_one_user_id})
current_rank_one_users = await redis.zrevrange(rank_key, 0, 0)
if current_rank_one_users:
users_who_peaked_at_rank_one.append({"user_id": current_rank_one_users[0]})

Copilot uses AI. Check for mistakes.

for user in users_who_peaked_at_rank_one:
redis_rank = await redis.zrevrank(rank_key, user["user_id"])
current_rank = redis_rank + 1 if redis_rank is not None else None

if current_rank == 1:
await db.execute(
"DELETE FROM user_badges WHERE user = %s AND badge = %s",
[user["user_id"], FORMER_CHAMPION_BADGE_ID],
)

# user_badges has no unique key on (user, badge) so we have to check manually :(
existing_former_champion_badge = await db.fetch(
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

var is named former_champion but it's checking against CHAMPION_BADGE_ID?

Copy link
Copy Markdown
Member

@cmyui cmyui Dec 9, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: it's probably best to use INSERT INTO ... IF NOT EXISTS ... ELSE UPDATE or w/e to make it one query, if possible

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not possible due to the lack of unique constraint since that's how it decides if it "exists" or would conflict etc. - needs to be resolved on the table layer first

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

var is named former_champion but it's checking against CHAMPION_BADGE_ID?

note to self: don't trust F2

"SELECT 1 FROM user_badges WHERE user = %s AND badge = %s",
[user["user_id"], CHAMPION_BADGE_ID],
)

if not existing_former_champion_badge:
await db.execute(
"INSERT INTO user_badges (user, badge) (%s, %s)"
[user["user_id"], CHAMPION_BADGE_ID]
)
else:
await db.execute(
"DELETE FROM user_badges WHERE user = %s AND badge = %s",
[user["user_id"], CHAMPION_BADGE_ID],
)

# user_badges has no unique key on (user, badge) so we have to check manually :(
existing_former_champion_badge = await db.fetch(
"SELECT 1 FROM user_badges WHERE user = %s AND badge = %s",
[user["user_id"], FORMER_CHAMPION_BADGE_ID],
)

if not existing_former_champion_badge:
await db.execute(
"INSERT INTO user_badges (user, badge) (%s, %s)"
[user["user_id"], FORMER_CHAMPION_BADGE_ID]
)

async def main() -> None:
print("Starting Akatsuki cron")
Expand All @@ -335,6 +403,7 @@ async def main() -> None:
await fix_supporter_badges()
await update_total_submitted_score_counts()
await freeze_expired_freeze_timers()
await update_champion_badges()
# await clear_scores() # disabled as of 2022-07-19

await disconnect()
Expand Down