The cup board: the league ranks, the level breaks the tie
Oliver wanted to rank the level a league was taken at. The challenge held: xp comes only from playing, so a board that rewards a low level rewards not playing — it would pay you to avoid the three rooms the season leans on. It also inverts every other number in the game, freezes after five entries, and makes the player who played more look worse. So the league ranks and the level decides between everyone who got equally far, where "lower is better" reads naturally. BOARDS.u carries subLow; server rank_key is the other half, and the same key decides whether a submission beats the row already standing. The level is written once at the promotion — before the league moves, because it is the level that WON the cup — mirrored like the rest of the profile, and inscribed under the shield it belongs to. Earned shields smoulder while they are on screen: five CSS embers each, no loop. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
e96b4374d8
commit
80eb60d181
8 files changed
+226
-40
No files matched your search
@@ -34,7 +34,19 @@ NAME_MAX = 12
|
||||
# care what the numbers MEAN (see stats.BOARDS on the client); it sorts them within a mode and
|
||||
# nothing crosses. Rows written before the split carry no mode and ARE gore rows, which is why 'g'
|
||||
# is the default everywhere and no migration is needed.
|
||||
MODES = ('g', 'z', 'c')
|
||||
MODES = ('g', 'z', 'c', 'u')
|
||||
# THE CUP BOARD ('u', 2026-08-31) is the one board whose second column is better LOW: it ranks the
|
||||
# LEAGUE a player took and breaks ties on the LEVEL they took it at. The client says the same thing
|
||||
# in stats.BOARDS (subLow) — this is the other half of it, and the only place the sort differs.
|
||||
SUB_LOW = ('u',)
|
||||
|
||||
|
||||
def rank_key(m):
|
||||
"""Board order: score DESC always, then the sub column, then age."""
|
||||
low = m in SUB_LOW
|
||||
return lambda r: (-r.get('k', 0), r.get('g', 0) if low else -r.get('g', 0), r.get('t', 0))
|
||||
|
||||
|
||||
lock = threading.Lock()
|
||||
|
||||
# ---- THE PROFILE MIRROR (2026-08-29, the leagues). localStorage alone dies with cleared browser
|
||||
@@ -86,6 +98,17 @@ def clean_profile(payload):
|
||||
v = 0
|
||||
if v > 0:
|
||||
cups[str(lg)] = min(9, v)
|
||||
# ...and the INSCRIPTION: league -> the level you took its cup at (2026-08-31, the cup board)
|
||||
at = {}
|
||||
raw_at = p.get('at')
|
||||
if isinstance(raw_at, dict):
|
||||
for lg in range(1, 6):
|
||||
try:
|
||||
v = int(raw_at.get(str(lg), raw_at.get(lg, 0)))
|
||||
except (TypeError, ValueError):
|
||||
v = 0
|
||||
if v > 0:
|
||||
at[str(lg)] = min(50, v)
|
||||
try:
|
||||
out = {'v': 1,
|
||||
'xp': max(0, min(int(p.get('xp', 0)), 1_000_000_000)),
|
||||
@@ -94,6 +117,7 @@ def clean_profile(payload):
|
||||
'setup': 1 if p.get('setup') else 0,
|
||||
'cups': cups,
|
||||
'out': max(0, min(int(p.get('out', 0)), 99)),
|
||||
'at': at,
|
||||
'n': re.sub(r'[^A-Z0-9 ._-]', '', str(p.get('n', '')).upper()).strip()[:NAME_MAX],
|
||||
'tour': word('tour'), 'kit': word('kit'), 'skin': word('skin')}
|
||||
except (TypeError, ValueError):
|
||||
@@ -373,7 +397,10 @@ class Handler(SimpleHTTPRequestHandler):
|
||||
# per-device — the same player on a second phone starts from zero and posts worse runs,
|
||||
# so a weaker submission has to be dropped HERE rather than merely not sorted to the top.
|
||||
mine = [r for r in rows if r.get('n') == row['n'] and mode_of(r) == row['m']]
|
||||
if row['k'] > max((r.get('k', 0) for r in mine), default=-1):
|
||||
# "better" is the BOARD's own order, not a bare >: on the cup board the same league at
|
||||
# a lower level beats the row already standing there.
|
||||
key = rank_key(row['m'])
|
||||
if not mine or key(row)[:2] < min(key(r)[:2] for r in mine):
|
||||
rows = [r for r in rows
|
||||
if not (r.get('n') == row['n'] and mode_of(r) == row['m'])]
|
||||
rows.append(row)
|
||||
@@ -381,12 +408,12 @@ class Handler(SimpleHTTPRequestHandler):
|
||||
kept = []
|
||||
for m in MODES:
|
||||
rs = [r for r in rows if mode_of(r) == m]
|
||||
rs.sort(key=lambda r: (-r.get('k', 0), -r.get('g', 0), r.get('t', 0)))
|
||||
rs.sort(key=rank_key(m))
|
||||
kept += rs[:KEEP]
|
||||
rows = kept
|
||||
save(rows)
|
||||
board = [r for r in rows if mode_of(r) == row['m']]
|
||||
board.sort(key=lambda r: (-r.get('k', 0), -r.get('g', 0), r.get('t', 0)))
|
||||
board.sort(key=rank_key(row['m']))
|
||||
return self.reply(200, {'ok': True, 'm': row['m'],
|
||||
'rank': rank_of(board, row['n']), 'scores': public(board)})
|
||||
|
||||
|
||||
Reference in new issue
Block a user