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')
|
period_end = data.get('period_end')
|
||||||
stats = (data.get('data') or {})
|
stats = (data.get('data') or {})
|
||||||
# Title and subheader
|
# Title and subheader
|
||||||
escaped_username = StatsFormatter._escape_md(username)
|
|
||||||
if games_count >= 1000:
|
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')
|
earliest_ts = data.get('earliest_game_ts')
|
||||||
if isinstance(earliest_ts, int):
|
if isinstance(earliest_ts, int):
|
||||||
earliest = datetime.fromtimestamp(earliest_ts).strftime("%d.%m.%Y")
|
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:
|
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'
|
# Use earliest actual game date instead of naive 'year ago'
|
||||||
earliest_ts = data.get('earliest_game_ts', period_start)
|
earliest_ts = data.get('earliest_game_ts', period_start)
|
||||||
if isinstance(earliest_ts, int) and isinstance(period_end, int):
|
if isinstance(earliest_ts, int) and isinstance(period_end, int):
|
||||||
start_str = datetime.fromtimestamp(earliest_ts).strftime("%d.%m.%Y")
|
start_str = datetime.fromtimestamp(earliest_ts).strftime("%d.%m.%Y")
|
||||||
end_str = datetime.fromtimestamp(period_end).strftime("%d.%m.%Y")
|
end_str = datetime.fromtimestamp(period_end).strftime("%d.%m.%Y")
|
||||||
header += f"\n\n\nPeriod: {start_str}–{end_str}"
|
header += f"\n\nPeriod: {start_str}–{end_str}"
|
||||||
# Body per mode
|
|
||||||
lines = []
|
# Collect per-mode rows
|
||||||
|
rows = []
|
||||||
for mode in ["bullet", "blitz", "rapid", "classical", "correspondence"]:
|
for mode in ["bullet", "blitz", "rapid", "classical", "correspondence"]:
|
||||||
mode_stats = stats.get(mode)
|
mode_stats = stats.get(mode)
|
||||||
if not mode_stats:
|
if not mode_stats:
|
||||||
|
|
@ -404,28 +404,50 @@ class StatsFormatter:
|
||||||
games_played = mode_stats.get('games_played', 0)
|
games_played = mode_stats.get('games_played', 0)
|
||||||
if games_played == 0:
|
if games_played == 0:
|
||||||
continue
|
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)
|
wins = mode_stats.get('wins', 0)
|
||||||
losses = mode_stats.get('losses', 0)
|
losses = mode_stats.get('losses', 0)
|
||||||
draws = mode_stats.get('draws', 0)
|
draws = mode_stats.get('draws', 0)
|
||||||
rating_change = mode_stats.get('rating_change', 0)
|
rating_change = mode_stats.get('rating_change', 0)
|
||||||
rating_change_str = StatsFormatter._format_rating_change(rating_change)
|
|
||||||
rating = mode_stats.get('rating')
|
rating = mode_stats.get('rating')
|
||||||
rating_str = rating if rating is not None else "—"
|
accuracy_str = "-"
|
||||||
line = f"{emoji} {mode.title()}: {games_played} Δ {rating_change_str} R {rating_str} ✅ {wins} ❌ {losses} 🤝 {draws}"
|
|
||||||
if mode in ("blitz", "rapid", "classical"):
|
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)
|
lines.append(line)
|
||||||
# Join lines with newlines between each mode
|
|
||||||
# Between regular modes: one empty line (\n\n)
|
body = "\n".join(lines)
|
||||||
# Before last mode: two empty lines (\n\n\n)
|
return f"{header}\n\n```\n{body}\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}"
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue