add WL to tss scoreboards (#1345)
This commit is contained in:
+51
-16
@@ -225,14 +225,20 @@ def _create_scoreboard_sync(model: dict[str, Any], output_path: str, bar_color:
|
||||
name_x = start_x if not flipped else start_x + section_width - name_w
|
||||
draw.text((name_x, header_y), team_name, font=fonts["team"], fill=header_fill)
|
||||
|
||||
# W/L slot — only drawn once real per-tournament standings exist (stub returns
|
||||
# None today, so nothing renders under the team name).
|
||||
standings = get_tss_standings(team.get("team_id"))
|
||||
# W/L slot — per-tournament record under the team name. Coloured exactly like
|
||||
# SREBOT: green W · grey dash · red L · grey dash · win-rate% on a red→green
|
||||
# gradient. Placed below the team name's full glyph box (descender-inclusive)
|
||||
# so names with p/g/y descenders don't clip into the record line.
|
||||
standings = get_tss_standings(team.get("team_id"), model.get("tournament_id"))
|
||||
if standings:
|
||||
wl_text = f"{standings['wins']}W - {standings['losses']}L"
|
||||
wb = draw.textbbox((0, 0), wl_text, font=fonts["sub"])
|
||||
wl_x = start_x if not flipped else start_x + section_width - (wb[2] - wb[0])
|
||||
draw.text((wl_x, header_y + (nb[3] - nb[1]) + 18), wl_text, font=fonts["sub"], fill=GREY_FILL)
|
||||
wl_segs = _winloss_segments(standings)
|
||||
seg_w = _segments_width(draw, wl_segs, fonts["sub"])
|
||||
wl_x = start_x if not flipped else start_x + section_width - seg_w
|
||||
# Sit halfway between the original (descender-clipping) baseline and a
|
||||
# full descender-clear drop — enough to clear p/g/y, no more.
|
||||
name_full_h = fonts["team"].getbbox("ApgjyQ")[3]
|
||||
wl_y = header_y + ((nb[3] - nb[1] + 18) + (name_full_h + 10)) // 2
|
||||
_draw_segments(draw, wl_x, wl_y, wl_segs, fonts["sub"])
|
||||
|
||||
# Stat columns (rating now lives inline next to the player name).
|
||||
col_labels = ["Air", "Ground", "Assists", "Deaths", "Caps"]
|
||||
@@ -270,7 +276,7 @@ def _create_scoreboard_sync(model: dict[str, Any], output_path: str, bar_color:
|
||||
pass
|
||||
|
||||
# Player rows. Layout per row:
|
||||
# top line — player name + inline (rating ±delta) at the column edge; stats
|
||||
# top line — player name + inline (rating) at the column edge; stats
|
||||
# lower line — vehicle icons next to their translated names
|
||||
body = fonts["body"]
|
||||
small = fonts["veh"]
|
||||
@@ -287,7 +293,7 @@ def _create_scoreboard_sync(model: dict[str, Any], output_path: str, bar_color:
|
||||
veh_y = line_y + name_h + 12 # vehicle line (icons + names together)
|
||||
vname_y = veh_y + (veh_icon - small_h) // 2
|
||||
name_w = draw.textbbox((0, 0), name, font=body)[2]
|
||||
rating_segs = _rating_segments(p.get("pvp_ratio"), p.get("pvp_ratio_delta"))
|
||||
rating_segs = _rating_segments(p.get("pvp_ratio"))
|
||||
rating_w = _segments_width(draw, rating_segs, body)
|
||||
|
||||
if not flipped:
|
||||
@@ -342,16 +348,45 @@ def _create_scoreboard_sync(model: dict[str, Any], output_path: str, bar_color:
|
||||
RATING_FILL = (170, 200, 255, 255)
|
||||
|
||||
|
||||
def _rating_segments(rating, delta):
|
||||
"""Build colored (text, fill) segments for the inline ``(1468 +2)`` rating.
|
||||
# W/L record colours — matched exactly to SREBOT's scoreboard.
|
||||
WL_WIN_FILL = (0, 255, 0, 255)
|
||||
WL_LOSS_FILL = (255, 60, 60, 255)
|
||||
WL_DASH_FILL = (200, 200, 200, 255)
|
||||
|
||||
``delta`` is a signed change vs the player's previous rating; it's ``None`` until
|
||||
rating history is tracked (see wl.py), so for now only the current value shows.
|
||||
|
||||
def _winrate_gradient(win_rate: float) -> tuple:
|
||||
"""Red→yellow→green gradient for a win-rate percentage (SREBOT's get_gradient_color).
|
||||
|
||||
0% = red (255,0,0), 50% = yellow (255,255,0), 100% = green (0,255,0).
|
||||
"""
|
||||
win_rate = max(0.0, min(100.0, win_rate))
|
||||
if win_rate <= 50:
|
||||
return (255, int(255 * (win_rate / 50)), 0, 255)
|
||||
return (int(255 * (1 - (win_rate - 50) / 50)), 255, 0, 255)
|
||||
|
||||
|
||||
def _winloss_segments(standings: dict[str, int]) -> list[tuple[str, tuple]]:
|
||||
"""Colored ``3W - 2L - 60%`` segments for the per-tournament record line.
|
||||
|
||||
Win count + 'W' green, ' - ' grey, loss count + 'L' red, ' - ' grey, then the
|
||||
win-rate% on the red→green gradient — mirroring SREBOT's _draw_winloss.
|
||||
"""
|
||||
wins = int(standings.get("wins") or 0)
|
||||
losses = int(standings.get("losses") or 0)
|
||||
total = wins + losses
|
||||
pct = (wins / total) * 100 if total else 0.0
|
||||
return [
|
||||
(f"{wins}W", WL_WIN_FILL),
|
||||
(" - ", WL_DASH_FILL),
|
||||
(f"{losses}L", WL_LOSS_FILL),
|
||||
(" - ", WL_DASH_FILL),
|
||||
(f"{pct:.0f}%", _winrate_gradient(pct)),
|
||||
]
|
||||
|
||||
|
||||
def _rating_segments(rating):
|
||||
"""Build colored (text, fill) segments for the inline ``(1468)`` rating."""
|
||||
rating_str = f"{int(round(rating))}" if isinstance(rating, (int, float)) else "—"
|
||||
if isinstance(delta, (int, float)) and delta != 0:
|
||||
dcol = WIN_FILL if delta > 0 else LOSS_FILL
|
||||
return [(f"({rating_str} ", RATING_FILL), (f"{'+' if delta > 0 else ''}{int(delta)}", dcol), (")", RATING_FILL)]
|
||||
return [(f"({rating_str})", RATING_FILL)]
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user