Пробинг туров: если тур уже сыгран — продвигаемся дальше вместо остановки
All checks were successful
CI/CD Pipeline / build-and-deploy (push) Successful in 4s
All checks were successful
CI/CD Pipeline / build-and-deploy (push) Successful in 4s
This commit is contained in:
parent
4b43432ecd
commit
e0a897fd67
1 changed files with 95 additions and 12 deletions
|
|
@ -191,6 +191,76 @@ async def start(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
|||
await update.message.reply_text(START_MSG, parse_mode=ParseMode.MARKDOWN_V2)
|
||||
|
||||
|
||||
def _apply_round_results(tournament, games, rd):
|
||||
standings = tournament['standings']
|
||||
sno_to_standing = {s['starting_sno']: s for s in standings if s.get('starting_sno')}
|
||||
name_to_standing = {
|
||||
re.sub(r'\s+', '', s['name'].lower()): s
|
||||
for s in standings
|
||||
}
|
||||
name_parts_to_standing: dict[str, list] = {}
|
||||
for s in standings:
|
||||
parts = re.sub(r'\s+', '', s['name'].lower()).split()
|
||||
for p in parts:
|
||||
name_parts_to_standing.setdefault(p, []).append(s)
|
||||
|
||||
def _find_player(sno, name_str):
|
||||
p = sno_to_standing.get(sno)
|
||||
if p:
|
||||
return p
|
||||
if name_str:
|
||||
norm = re.sub(r'\s+', '', name_str.lower())
|
||||
p = name_to_standing.get(norm)
|
||||
if p:
|
||||
return p
|
||||
parts = norm.split()
|
||||
for part in parts:
|
||||
candidates = name_parts_to_standing.get(part, [])
|
||||
if len(candidates) == 1:
|
||||
return candidates[0]
|
||||
return None
|
||||
|
||||
for g in games:
|
||||
if g is None:
|
||||
continue
|
||||
ws, bs = g['white_sno'], g['black_sno']
|
||||
ws_result = g.get('white_score')
|
||||
bs_result = g.get('black_score')
|
||||
|
||||
if ws_result is None:
|
||||
continue
|
||||
|
||||
ws_val = float(ws_result)
|
||||
bs_val = float(bs_result)
|
||||
|
||||
wp = _find_player(ws, g.get('white_name', ''))
|
||||
bp = _find_player(bs, g.get('black_name', ''))
|
||||
|
||||
if wp:
|
||||
opp_sno = bs if bs != 0 else (bp.get('starting_sno') if bp else 0)
|
||||
existing = [r for r in wp.get('results', []) if r.get('round') != rd]
|
||||
existing.append({'opponent': opp_sno, 'color': 'w', 'score': ws_val, 'round': rd})
|
||||
wp['results'] = existing
|
||||
|
||||
if bp:
|
||||
opp_sno = ws if ws != 0 else (wp.get('starting_sno') if wp else 0)
|
||||
existing = [r for r in bp.get('results', []) if r.get('round') != rd]
|
||||
existing.append({'opponent': opp_sno, 'color': 'b', 'score': bs_val, 'round': rd})
|
||||
bp['results'] = existing
|
||||
|
||||
for s in standings:
|
||||
sno = s.get('starting_sno')
|
||||
if sno and len(s.get('results', [])) < rd:
|
||||
orig_results = s.get('_orig_results', [])
|
||||
if len(orig_results) >= rd:
|
||||
res = orig_results[rd - 1]
|
||||
res['round'] = rd
|
||||
s['results'] = list(s.get('results', []))
|
||||
s['results'].append(res)
|
||||
|
||||
tournament['current_round'] = rd
|
||||
|
||||
|
||||
async def handle_url(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||
user = update.effective_user
|
||||
text = update.message.text.strip()
|
||||
|
|
@ -239,24 +309,37 @@ async def handle_url(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
|||
base_url = re.sub(r'[&?]turdet=\w+', '', base_url)
|
||||
base_url = re.sub(r'[&?]SNode=\w+', '', base_url)
|
||||
next_rd = tournament['current_round'] + 1
|
||||
initial_rd = next_rd
|
||||
|
||||
from swiss_calc.parser import fetch_url as _fetch_url, parse_round_pairings
|
||||
try:
|
||||
while next_rd <= tournament['num_rounds']:
|
||||
rd_html = _fetch_url(f'{base_url}&art=2&rd={next_rd}&turdet=YES')
|
||||
rd_games = parse_round_pairings(rd_html, next_rd)
|
||||
played = any(g.get('white_score') is not None for g in rd_games if g)
|
||||
if played:
|
||||
await update.message.reply_text(
|
||||
f'⚠️ Тур {next_rd} уже сыгран — на сайте есть результаты\\.',
|
||||
parse_mode=ParseMode.MARKDOWN_V2)
|
||||
record_request(user.id, url, tournament.get('name', ''), True)
|
||||
return
|
||||
_apply_round_results(tournament, rd_games, next_rd)
|
||||
next_rd += 1
|
||||
continue
|
||||
if rd_games:
|
||||
await update.message.reply_text(
|
||||
f'⚠️ Жеребьёвка тура {next_rd} уже опубликована на chess\\-results\\.com\\.\n'
|
||||
'Я всё равно посчитаю, но пары могут незначительно отличаться '
|
||||
'\\(разные редакции правил FIDE\\)\\.',
|
||||
parse_mode=ParseMode.MARKDOWN_V2)
|
||||
break
|
||||
else:
|
||||
await msg.edit_text('🏁 Турнир уже завершён\\. Жеребьёвки не будет\\.',
|
||||
parse_mode=ParseMode.MARKDOWN_V2)
|
||||
record_request(user.id, url, tournament.get('name', ''), True)
|
||||
return
|
||||
|
||||
if next_rd > initial_rd:
|
||||
await msg.edit_text(
|
||||
f'✅ *{_md_escape(tournament["name"])}*\n'
|
||||
f'📅 Сыграно туров: {tournament["current_round"]} из {tournament["num_rounds"]}\n'
|
||||
f'👥 Участников: {len(tournament["standings"])}',
|
||||
parse_mode=ParseMode.MARKDOWN_V2)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue