align /lastyear_or_1000games table into a single monospace code block
All checks were successful
CI/CD Pipeline / build-and-deploy (push) Successful in 29s
All checks were successful
CI/CD Pipeline / build-and-deploy (push) Successful in 29s
Column-align per-mode rows (games/rating change/rating/W-L-D/accuracy) same as the other stats commands, instead of loose free-text lines. Strip the invisible variation selector from bullet/classical emoji so it doesn't throw off column padding.
This commit is contained in:
parent
f154d3d7c3
commit
62cdd750f8
1 changed files with 47 additions and 25 deletions
|
|
@ -380,23 +380,23 @@ class StatsFormatter:
|
|||
period_end = data.get('period_end')
|
||||
stats = (data.get('data') or {})
|
||||
# Title and subheader
|
||||
escaped_username = StatsFormatter._escape_md(username)
|
||||
if games_count >= 1000:
|
||||
header = f"📈 {escaped_username}: last 1000 rated games"
|
||||
header = f"📈 {username}: last 1000 rated games"
|
||||
earliest_ts = data.get('earliest_game_ts')
|
||||
if isinstance(earliest_ts, int):
|
||||
earliest = datetime.fromtimestamp(earliest_ts).strftime("%d.%m.%Y")
|
||||
header += f"\n\n\nStart of these 1000 games: {earliest}"
|
||||
header += f"\n\nStart of these 1000 games: {earliest}"
|
||||
else:
|
||||
header = f"📈 {escaped_username}: last year (rated), games: {games_count}"
|
||||
header = f"📈 {username}: last year (rated), games: {games_count}"
|
||||
# Use earliest actual game date instead of naive 'year ago'
|
||||
earliest_ts = data.get('earliest_game_ts', period_start)
|
||||
if isinstance(earliest_ts, int) and isinstance(period_end, int):
|
||||
start_str = datetime.fromtimestamp(earliest_ts).strftime("%d.%m.%Y")
|
||||
end_str = datetime.fromtimestamp(period_end).strftime("%d.%m.%Y")
|
||||
header += f"\n\n\nPeriod: {start_str}–{end_str}"
|
||||
# Body per mode
|
||||
lines = []
|
||||
header += f"\n\nPeriod: {start_str}–{end_str}"
|
||||
|
||||
# Collect per-mode rows
|
||||
rows = []
|
||||
for mode in ["bullet", "blitz", "rapid", "classical", "correspondence"]:
|
||||
mode_stats = stats.get(mode)
|
||||
if not mode_stats:
|
||||
|
|
@ -404,28 +404,50 @@ class StatsFormatter:
|
|||
games_played = mode_stats.get('games_played', 0)
|
||||
if games_played == 0:
|
||||
continue
|
||||
emoji = StatsFormatter._get_game_type_emoji(mode)
|
||||
# Strip the variation selector some emoji include (e.g. bullet/classical) —
|
||||
# it's invisible but counts as an extra character, which would throw off
|
||||
# the column padding below even though it doesn't add any visual width.
|
||||
emoji = StatsFormatter._get_game_type_emoji(mode).replace('️', '')
|
||||
wins = mode_stats.get('wins', 0)
|
||||
losses = mode_stats.get('losses', 0)
|
||||
draws = mode_stats.get('draws', 0)
|
||||
rating_change = mode_stats.get('rating_change', 0)
|
||||
rating_change_str = StatsFormatter._format_rating_change(rating_change)
|
||||
rating = mode_stats.get('rating')
|
||||
rating_str = rating if rating is not None else "—"
|
||||
line = f"{emoji} {mode.title()}: {games_played} Δ {rating_change_str} R {rating_str} ✅ {wins} ❌ {losses} 🤝 {draws}"
|
||||
accuracy_str = "-"
|
||||
if mode in ("blitz", "rapid", "classical"):
|
||||
line += f" 🎯 {StatsFormatter._format_accuracy(mode_stats.get('accuracy'))}"
|
||||
accuracy_str = StatsFormatter._format_accuracy(mode_stats.get('accuracy'))
|
||||
rows.append((
|
||||
f"{emoji} {mode.title()}",
|
||||
str(games_played),
|
||||
StatsFormatter._format_rating_change(rating_change),
|
||||
str(rating) if rating is not None else "—",
|
||||
str(wins),
|
||||
str(losses),
|
||||
str(draws),
|
||||
accuracy_str,
|
||||
))
|
||||
|
||||
if not rows:
|
||||
return f"{header}\n\n📭 No data"
|
||||
|
||||
label_w = max(len(r[0]) for r in rows)
|
||||
games_w = max(len(r[1]) for r in rows)
|
||||
change_w = max(len(r[2]) for r in rows)
|
||||
rating_w = max(len(r[3]) for r in rows)
|
||||
wins_w = max(len(r[4]) for r in rows)
|
||||
losses_w = max(len(r[5]) for r in rows)
|
||||
draws_w = max(len(r[6]) for r in rows)
|
||||
acc_w = max((len(r[7]) for r in rows), default=0)
|
||||
|
||||
lines = []
|
||||
for label, games, change, rating, wins, losses, draws, acc in rows:
|
||||
line = (
|
||||
f"{label:<{label_w}} {games:>{games_w}} {change:<{change_w}} "
|
||||
f"R{rating:>{rating_w}} ✅{wins:>{wins_w}} ❌{losses:>{losses_w}} 🤝{draws:>{draws_w}}"
|
||||
)
|
||||
if acc_w:
|
||||
line += f" 🎯{acc:>{acc_w}}"
|
||||
lines.append(line)
|
||||
# Join lines with newlines between each mode
|
||||
# Between regular modes: one empty line (\n\n)
|
||||
# Before last mode: two empty lines (\n\n\n)
|
||||
if len(lines) == 0:
|
||||
body = ""
|
||||
elif len(lines) == 1:
|
||||
body = lines[0]
|
||||
else:
|
||||
# All modes except last joined with one empty line
|
||||
body = "\n\n".join(lines[:-1])
|
||||
# Add two empty lines before last mode
|
||||
body += "\n\n\n" + lines[-1]
|
||||
return f"{header}\n\n{body}"
|
||||
|
||||
body = "\n".join(lines)
|
||||
return f"{header}\n\n```\n{body}\n```"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue