Пробинг туров: если тур уже сыгран — продвигаемся дальше вместо остановки
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)
|
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):
|
async def handle_url(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||||
user = update.effective_user
|
user = update.effective_user
|
||||||
text = update.message.text.strip()
|
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'[&?]turdet=\w+', '', base_url)
|
||||||
base_url = re.sub(r'[&?]SNode=\w+', '', base_url)
|
base_url = re.sub(r'[&?]SNode=\w+', '', base_url)
|
||||||
next_rd = tournament['current_round'] + 1
|
next_rd = tournament['current_round'] + 1
|
||||||
|
initial_rd = next_rd
|
||||||
|
|
||||||
from swiss_calc.parser import fetch_url as _fetch_url, parse_round_pairings
|
from swiss_calc.parser import fetch_url as _fetch_url, parse_round_pairings
|
||||||
try:
|
try:
|
||||||
|
while next_rd <= tournament['num_rounds']:
|
||||||
rd_html = _fetch_url(f'{base_url}&art=2&rd={next_rd}&turdet=YES')
|
rd_html = _fetch_url(f'{base_url}&art=2&rd={next_rd}&turdet=YES')
|
||||||
rd_games = parse_round_pairings(rd_html, next_rd)
|
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)
|
played = any(g.get('white_score') is not None for g in rd_games if g)
|
||||||
if played:
|
if played:
|
||||||
await update.message.reply_text(
|
_apply_round_results(tournament, rd_games, next_rd)
|
||||||
f'⚠️ Тур {next_rd} уже сыгран — на сайте есть результаты\\.',
|
next_rd += 1
|
||||||
parse_mode=ParseMode.MARKDOWN_V2)
|
continue
|
||||||
record_request(user.id, url, tournament.get('name', ''), True)
|
|
||||||
return
|
|
||||||
if rd_games:
|
if rd_games:
|
||||||
await update.message.reply_text(
|
await update.message.reply_text(
|
||||||
f'⚠️ Жеребьёвка тура {next_rd} уже опубликована на chess\\-results\\.com\\.\n'
|
f'⚠️ Жеребьёвка тура {next_rd} уже опубликована на chess\\-results\\.com\\.\n'
|
||||||
'Я всё равно посчитаю, но пары могут незначительно отличаться '
|
'Я всё равно посчитаю, но пары могут незначительно отличаться '
|
||||||
'\\(разные редакции правил FIDE\\)\\.',
|
'\\(разные редакции правил FIDE\\)\\.',
|
||||||
parse_mode=ParseMode.MARKDOWN_V2)
|
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:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue