ChessCalcNextTour/test_all_rounds.py

104 lines
4 KiB
Python
Raw Normal View History

#!/usr/bin/env python3
"""End-to-end test: parse rounds 1-4, calculate round 5, compare with site."""
import sys
sys.path.insert(0, '.')
from swiss_calc.parser import fetch_url, parse_round_pairings, fetch_tournament
from swiss_calc.swiss import calculate_next_round
BASE = 'https://s1.chess-results.com/tnr1393124.aspx?lan=11'
print("=" * 60)
print("ТЕСТ: парсинг туров 1-4 → расчёт тура 5 vs chess-results.com")
print("=" * 60)
# 1. Parse tournament (rounds 1-4 from standings)
print("\n📥 Парсим турнир...")
data = fetch_tournament(BASE)
print(f" Турнир: {data['name'][:60]}")
print(f" Сыграно туров: {data['current_round']}")
print(f" Участников: {len(data['standings'])}")
# Show first few players' data
for s in data['standings'][:3]:
results_str = ' '.join(f"{r['opponent']}{r['color']}{r['score']}" for r in s['results'])
print(f" #{s['rank']} {s['name'][:30]}: {s['points']}pts, results=[{results_str}]")
# 2. Calculate round 5
print(f"\n🧮 Считаем тур {data['current_round'] + 1}...")
result = calculate_next_round(data)
print(f" Источник: {result['source']}")
calc_pairs = result['pairings']
print(f" Рассчитано пар: {len(calc_pairs)}")
# 3. Fetch actual round 5 from chess-results
print(f"\n📥 Парсим реальные пары тура 5 с сайта...")
html5 = fetch_url(f'{BASE}&art=2&rd=5&turdet=YES')
real_games = parse_round_pairings(html5, 5)
print(f" Всего игр на сайте: {len(real_games)}")
# Build sets for comparison
calc_set = set()
for wp, bp, color in calc_pairs:
sno_w = getattr(wp, 'sno', wp.get('starting_sno', 0)) if not hasattr(wp, 'sno') else wp.sno
sno_b = getattr(bp, 'sno', bp.get('starting_sno', 0)) if not hasattr(bp, 'sno') else bp.sno
calc_set.add((min(sno_w, sno_b), max(sno_w, sno_b)))
real_set = set()
for g in real_games:
w, b = g['white_sno'], g['black_sno']
real_set.add((min(w, b), max(w, b)))
# 4. Compare
matched = calc_set & real_set
extra_calc = calc_set - real_set
extra_real = real_set - calc_set
print(f"\n📊 СРАВНЕНИЕ:")
print(f" Совпало пар: {len(matched)}/{len(real_games)} ({100*len(matched)/max(len(real_games),1):.0f}%)")
print(f" Лишних в расчёте: {len(extra_calc)}")
print(f" Лишних на сайте: {len(extra_real)}")
if extra_calc:
print(f"\n Пары только в расчёте (первые 5):")
for w, b in list(extra_calc)[:5]:
print(f" #{w} vs #{b}")
if extra_real:
print(f"\n Пары только на сайте (первые 5):")
for w, b in list(extra_real)[:5]:
print(f" #{w} vs #{b}")
# 5. Show top boards side by side
print(f"\n📋 ДОСКИ 1-5: расчёт vs сайт")
calc_by_board = {}
for i, (wp, bp, color) in enumerate(calc_pairs):
sno_w = wp.sno
sno_b = bp.sno
calc_by_board[f"#{sno_w} #{wp.name[:20]}"] = f"#{sno_b} {bp.name[:20]}"
for g in real_games[:5]:
b = g['board']
w_name = g['white_name'][:25]
b_name = g['black_name'][:25]
ws, bs = g['white_sno'], g['black_sno']
# Find matching calc pair
pair_key = (min(ws, bs), max(ws, bs))
status = "" if pair_key in matched else ""
print(f" Доска {b}: #{ws} {w_name} vs #{bs} {b_name} {status}")
# 6. Check Vrubel specifically
print(f"\n🎯 Врубель Константин:")
for wp, bp, color in calc_pairs:
if 'Врубель' in wp.name:
print(f" Расчёт: #{wp.sno} {wp.name} (белые) vs #{bp.sno} {bp.name}")
break
for g in real_games:
if 'Врубель' in g.get('white_name', '') or 'Врубель' in g.get('black_name', ''):
if 'Врубель' in g['white_name']:
print(f" Сайт: #{g['white_sno']} {g['white_name']} (белые) vs #{g['black_sno']} {g['black_name']}")
else:
print(f" Сайт: #{g['black_sno']} {g['black_name']} (чёрные) vs #{g['white_sno']} {g['white_name']}")
break