chessCalc: парсер chess-results.com + FIDE Swiss + Docker
Принимает URL турнира, показывает пары следующего тура в Telegram-формате. - parser.py: парсинг chess-results.com - swiss.py: FIDE Dutch System - display.py: форматирование для Telegram - Docker: docker compose run --rm chess-calc 'URL'
This commit is contained in:
commit
cf7fafd2ba
10 changed files with 1093 additions and 0 deletions
84
swiss_calc/display.py
Normal file
84
swiss_calc/display.py
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
"""
|
||||
Output formatting for Telegram Markdown.
|
||||
"""
|
||||
|
||||
from .swiss import Player
|
||||
|
||||
|
||||
def format_pairings_table(pairings_data: dict, tournament_name: str) -> str:
|
||||
"""Format pairings as a Telegram-friendly markdown table.
|
||||
|
||||
Telegram auto-converts pipe tables to bullet lists, so we produce
|
||||
clean formatted output that works well.
|
||||
"""
|
||||
pairings = pairings_data['pairings']
|
||||
rnd = pairings_data['round']
|
||||
|
||||
lines = []
|
||||
lines.append(f"**{tournament_name}**")
|
||||
lines.append(f"📋 **Тур {rnd}** — пары")
|
||||
lines.append("")
|
||||
|
||||
board = 1
|
||||
for pairing in pairings:
|
||||
if len(pairing) == 3:
|
||||
p1, p2, color = pairing
|
||||
if color == 'w':
|
||||
white, black = p1, p2
|
||||
else:
|
||||
white, black = p2, p1
|
||||
elif len(pairing) == 5:
|
||||
# raw tuple: (sno1, name1, color, sno2, name2)
|
||||
sno1, name1, color, sno2, name2 = pairing
|
||||
if color == 'w':
|
||||
lines.append(f" {board}. {name1} 🏳️ — {name2}")
|
||||
else:
|
||||
lines.append(f" {board}. {name2} 🏳️ — {name1}")
|
||||
board += 1
|
||||
continue
|
||||
else:
|
||||
continue
|
||||
|
||||
w_name = white.name
|
||||
b_name = black.name
|
||||
w_pts = white.points
|
||||
b_pts = black.points
|
||||
w_rating = white.rating
|
||||
b_rating = black.rating
|
||||
|
||||
pts_str = f" ({w_pts}/{b_pts})" if w_pts or b_pts else ""
|
||||
rating_str = f" ⚡{w_rating}/{b_rating}" if w_rating or b_rating else ""
|
||||
|
||||
lines.append(f" {board}. {w_name} 🏳️ — {b_name}{pts_str}{rating_str}")
|
||||
|
||||
board += 1
|
||||
|
||||
lines.append("")
|
||||
lines.append(f"Всего пар: {len(pairings)}")
|
||||
if pairings_data.get('source') == 'chess_results_precalculated':
|
||||
lines.append("_пары с сайта chess-results.com_")
|
||||
|
||||
return '\n'.join(lines)
|
||||
|
||||
|
||||
def format_player_standings(tournament_data: dict, top_n: int = 10) -> str:
|
||||
"""Format top N players with their results."""
|
||||
standings = tournament_data['standings'][:top_n]
|
||||
if not standings:
|
||||
return "Нет данных"
|
||||
|
||||
lines = []
|
||||
lines.append(f"**{tournament_data['name']}**")
|
||||
lines.append(f"📊 Положение после тура {tournament_data['current_round']}")
|
||||
lines.append("")
|
||||
|
||||
for s in standings:
|
||||
rank = s['rank']
|
||||
name = s['name']
|
||||
pts = s['points']
|
||||
tb = s.get('tb', [])
|
||||
|
||||
tb_str = f" (Б: {tb[0]})" if tb else ""
|
||||
lines.append(f" {rank}. {name} — **{pts}** очк{tb_str}")
|
||||
|
||||
return '\n'.join(lines)
|
||||
Loading…
Add table
Add a link
Reference in a new issue