show tracked player's piece color inline, drop redundant result text
All checks were successful
CI/CD Pipeline / build-and-deploy (push) Successful in 33s

Add a small circle (/) glued right after the tracked player's name
in the per-game table to show which color they played, since the
white/black split was no longer visible once the opponent's name was
dropped. Replace the '1-0'/'0-1'/'1/2-1/2' result text with a plain
'-' separator — the leading outcome circle already conveys win/loss/draw.
This commit is contained in:
vrubelroman 2026-07-03 10:12:45 +00:00
parent 26cb066515
commit e9516f8664

View file

@ -29,11 +29,6 @@ class StatsFormatter:
return "-"
return f"{accuracy:.0f}%"
@staticmethod
def _format_result(result: str) -> str:
"""Format a raw '1-0'/'0-1'/'1/2-1/2' result string for display"""
return "½-½" if result == "1/2-1/2" else result
@staticmethod
def _format_row_outcome_circle(row: dict) -> str:
"""
@ -51,10 +46,11 @@ class StatsFormatter:
def _format_game_rows_block(rows: list) -> str:
"""
Format a list of individual game rows as a column-aligned, monospace table:
outcome | accuracy(tracked) | name(tracked) | rating(tracked) | result | rating(opponent) | accuracy(opponent)
outcome | accuracy(tracked) | name(tracked)+color | rating(tracked) | vs | rating(opponent) | accuracy(opponent)
Only the tracked player is named the opponent is shown by rating/accuracy
only, keeping the line short enough for mobile screens.
only, keeping the line short enough for mobile screens. A small circle right
after the tracked player's name shows which color they played (⚪ white / ⚫ black).
Column widths are computed from the actual data so every column lines up
character-for-character. Caller is expected to wrap the result in a
@ -68,36 +64,36 @@ class StatsFormatter:
prepared = []
for row in rows:
circle = StatsFormatter._format_row_outcome_circle(row)
if row.get('tracked_is_white') is False:
tracked_name = row.get('black_name') or '?'
tracked_rating = row.get('black_rating')
tracked_accuracy = row.get('black_accuracy')
opp_rating = row.get('white_rating')
opp_accuracy = row.get('white_accuracy')
else:
tracked_is_white = row.get('tracked_is_white') is not False
color_marker = "" if tracked_is_white else ""
if tracked_is_white:
tracked_name = row.get('white_name') or '?'
tracked_rating = row.get('white_rating')
tracked_accuracy = row.get('white_accuracy')
opp_rating = row.get('black_rating')
opp_accuracy = row.get('black_accuracy')
tracked_name = tracked_name[:NAME_WIDTH]
else:
tracked_name = row.get('black_name') or '?'
tracked_rating = row.get('black_rating')
tracked_accuracy = row.get('black_accuracy')
opp_rating = row.get('white_rating')
opp_accuracy = row.get('white_accuracy')
name_field = f"{tracked_name[:NAME_WIDTH]}{color_marker}"
tr_str = str(tracked_rating) if tracked_rating is not None else "-"
or_str = str(opp_rating) if opp_rating is not None else "-"
ta = StatsFormatter._format_accuracy(tracked_accuracy)
oa = StatsFormatter._format_accuracy(opp_accuracy)
result = StatsFormatter._format_result(row.get('result', ''))
prepared.append((circle, ta, tracked_name, tr_str, result, or_str, oa))
prepared.append((circle, ta, name_field, tr_str, or_str, oa))
acc_width = max(max(len(p[1]), len(p[6])) for p in prepared)
name_width = NAME_WIDTH
rating_width = max(max(len(p[3]), len(p[5])) for p in prepared)
result_width = max(len(p[4]) for p in prepared)
acc_width = max(max(len(p[1]), len(p[5])) for p in prepared)
name_width = NAME_WIDTH + 1 # +1 for the color marker glued to the name
rating_width = max(max(len(p[3]), len(p[4])) for p in prepared)
lines = []
for circle, ta, tracked_name, tr_str, result, or_str, oa in prepared:
for circle, ta, name_field, tr_str, or_str, oa in prepared:
lines.append(
f"{circle} {ta:>{acc_width}} {tracked_name:<{name_width}} {tr_str:>{rating_width}} "
f"{result:^{result_width}} {or_str:>{rating_width}} {oa:>{acc_width}}"
f"{circle} {ta:>{acc_width}} {name_field:<{name_width}} {tr_str:>{rating_width}} "
f"- {or_str:>{rating_width}} {oa:>{acc_width}}"
)
return "\n".join(lines)