snes kall)))))))
This commit is contained in:
parent
71dc7ee569
commit
6710f2e54f
1 changed files with 0 additions and 180 deletions
180
divisions.py
180
divisions.py
|
|
@ -1,180 +0,0 @@
|
||||||
import sys # аргументы командной строки
|
|
||||||
import os # путь к main.py и имя csv-файла
|
|
||||||
import pandas as pd
|
|
||||||
import numpy as np
|
|
||||||
|
|
||||||
'''
|
|
||||||
Отдельный модуль: ДИВИЗИОНЫ и ПРАВИЛО ПОСЕВА победителей дивизионов.
|
|
||||||
|
|
||||||
Зачем он нужен.
|
|
||||||
Базовый main.py сортирует команды в конференции строго по проценту очков (%О)
|
|
||||||
и тай-брейкам. Но в части сезонов КХЛ в таблице конференции действовало правило:
|
|
||||||
ПОБЕДИТЕЛИ ДВУХ ДИВИЗИОНОВ получают места 1 и 2 в конференции, даже если по очкам
|
|
||||||
они не входят в топ-2. Из-за этого, например, в сезоне 2020/21 в Западной
|
|
||||||
конференции СКА (82 очка) стоит на сайте выше Динамо М (84) и Локомотива (83):
|
|
||||||
СКА выиграл дивизион Боброва, а те двое - из дивизиона Тарасова, который выиграл ЦСКА.
|
|
||||||
|
|
||||||
main.py этот посев не делает (в нём вообще нет деления на дивизионы, только
|
|
||||||
Запад/Восток), поэтому правило вынесено сюда, в отдельный файл, и main.py не трогается.
|
|
||||||
'''
|
|
||||||
|
|
||||||
|
|
||||||
'''
|
|
||||||
Расчёт таблицы берём из main.py, чтобы не дублировать логику (единственный источник
|
|
||||||
правды - там). main.py в конце сам вызывает main(), поэтому импортировать его напрямую
|
|
||||||
нельзя - он бы тут же попытался прочитать аргументы и упал. Поэтому читаем его исходник
|
|
||||||
и выполняем без последней строки `main()`: так получаем готовые функции build_standings
|
|
||||||
и словарь CONFERENCES, ничего при этом не запуская и не печатая.
|
|
||||||
'''
|
|
||||||
_main_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'main.py')
|
|
||||||
_src = open(_main_path, encoding='utf-8').read()
|
|
||||||
_src = _src.replace('\nmain()\n', '\n') # убираем автозапуск
|
|
||||||
_ns = {}
|
|
||||||
exec(compile(_src, 'main.py', 'exec'), _ns)
|
|
||||||
build_standings = _ns['build_standings']
|
|
||||||
CONFERENCES = _ns['CONFERENCES']
|
|
||||||
|
|
||||||
|
|
||||||
def make_div(bobrov, tarasov, kharlamov, chernyshev):
|
|
||||||
'''
|
|
||||||
Собрать словарь {команда -> дивизион} из четырёх списков команд.
|
|
||||||
|
|
||||||
Принимает: четыре списка - составы дивизионов Боброва и Тарасова (Запад),
|
|
||||||
Харламова и Чернышёва (Восток).
|
|
||||||
Возвращает: dict, где каждой команде сопоставлено название её дивизиона.
|
|
||||||
|
|
||||||
Аналог make_conf из main.py, только делений не два (Запад/Восток), а четыре.
|
|
||||||
'''
|
|
||||||
d = {}
|
|
||||||
d.update({t: 'Боброва' for t in bobrov}) # Запад
|
|
||||||
d.update({t: 'Тарасова' for t in tarasov}) # Запад
|
|
||||||
d.update({t: 'Харламова' for t in kharlamov}) # Восток
|
|
||||||
d.update({t: 'Чернышёва' for t in chernyshev}) # Восток
|
|
||||||
return d
|
|
||||||
|
|
||||||
|
|
||||||
'''
|
|
||||||
Состав дивизионов по сезонам (имена команд - ровно как в соответствующем csv).
|
|
||||||
Источники:
|
|
||||||
2020/21 - официальное распределение КХЛ;
|
|
||||||
2021/22 - Википедия "КХЛ в сезоне 2021/2022";
|
|
||||||
2018/19, 2019/20 - стандартная сетка дивизионов тех сезонов.
|
|
||||||
Для посева важен только победитель каждого дивизиона; выходные таблицы ниже
|
|
||||||
сверены с официальным сайтом КХЛ по всем четырём сезонам и совпадают.
|
|
||||||
'''
|
|
||||||
DIVISIONS = {
|
|
||||||
'2018_19': make_div(
|
|
||||||
bobrov=['СКА', 'Йокерит', 'Динамо М', 'Динамо Мн', 'Динамо Р', 'Слован'],
|
|
||||||
tarasov=['ЦСКА', 'Локомотив', 'ХК Сочи', 'Спартак', 'Витязь', 'Северсталь'],
|
|
||||||
kharlamov=['Автомобилист', 'Металлург Мг', 'Ак Барс', 'Трактор',
|
|
||||||
'Нефтехимик', 'Куньлунь РС', 'Адмирал'],
|
|
||||||
chernyshev=['Барыс', 'Авангард', 'Салават Юлаев', 'Сибирь',
|
|
||||||
'Торпедо НН', 'Амур'],
|
|
||||||
),
|
|
||||||
'2019_20': make_div(
|
|
||||||
bobrov=['СКА', 'Йокерит', 'Спартак', 'Динамо М', 'Динамо Мн', 'Динамо Р'],
|
|
||||||
tarasov=['ЦСКА', 'Локомотив', 'Витязь', 'Торпедо НН', 'ХК Сочи', 'Северсталь'],
|
|
||||||
kharlamov=['Ак Барс', 'Металлург Мг', 'Автомобилист', 'Нефтехимик',
|
|
||||||
'Трактор', 'Адмирал'],
|
|
||||||
chernyshev=['Авангард', 'Барыс', 'Салават Юлаев', 'Сибирь',
|
|
||||||
'Амур', 'Куньлунь РС'],
|
|
||||||
),
|
|
||||||
'2020_21': make_div(
|
|
||||||
bobrov=['СКА', 'Йокерит', 'Северсталь', 'Спартак', 'Витязь', 'ХК Сочи'],
|
|
||||||
tarasov=['ЦСКА', 'Динамо М', 'Локомотив', 'Динамо Мн', 'Динамо Р'],
|
|
||||||
kharlamov=['Автомобилист', 'Ак Барс', 'Металлург Мг', 'Нефтехимик',
|
|
||||||
'Трактор', 'Торпедо НН'],
|
|
||||||
chernyshev=['Авангард', 'Амур', 'Барыс', 'Куньлунь РС',
|
|
||||||
'Салават Юлаев', 'Сибирь'],
|
|
||||||
),
|
|
||||||
'2021_22': make_div(
|
|
||||||
bobrov=['Витязь', 'Йокерит', 'СКА', 'ХК Сочи', 'Торпедо', 'Спартак'],
|
|
||||||
tarasov=['Динамо М', 'Динамо Мн', 'Динамо Р', 'Локомотив', 'Северсталь', 'ЦСКА'],
|
|
||||||
kharlamov=['Автомобилист', 'Ак Барс', 'Куньлунь РС', 'Металлург Мг',
|
|
||||||
'Нефтехимик', 'Трактор'],
|
|
||||||
chernyshev=['Авангард', 'Амур', 'Барыс', 'Сибирь', 'Салават Юлаев', 'Адмирал'],
|
|
||||||
),
|
|
||||||
}
|
|
||||||
|
|
||||||
'''
|
|
||||||
В каких сезонах правило посева победителей дивизионов отражалось в таблице конференции.
|
|
||||||
2018/19, 2019/20, 2020/21 - да; в 2021/22 КХЛ перешла к чистому порядку по %О
|
|
||||||
(на сайте за 2021/22 победители дивизионов наверх НЕ поднимаются).
|
|
||||||
В сезонах 2018/19 и 2019/20 победители дивизионов и так были в топ-2 по очкам,
|
|
||||||
поэтому правило там виден результат не меняет - но оставляем его включённым,
|
|
||||||
чтобы логика была единой.
|
|
||||||
'''
|
|
||||||
SEED_BY_DIVISION = {
|
|
||||||
'2018_19': True,
|
|
||||||
'2019_20': True,
|
|
||||||
'2020_21': True,
|
|
||||||
'2021_22': False,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
def seed_conference(conf_table):
|
|
||||||
'''
|
|
||||||
conf_table - часть итоговой таблицы по одной конференции, УЖЕ отсортированная
|
|
||||||
по критериям КХЛ (%О, затем В, ВО, ВБ, Р, ГЗ) - так её отдаёт build_standings.
|
|
||||||
|
|
||||||
Берём лучшего из каждого дивизиона (это и есть победитель дивизиона, т.к. таблица
|
|
||||||
отсортирована) и ставим этих двоих на места 1-2; между собой они идут в том же
|
|
||||||
порядке сортировки. Остальные команды - следом, тоже в порядке сортировки.
|
|
||||||
'''
|
|
||||||
# head(1) внутри каждого дивизиона = первая (а значит, лучшая) команда дивизиона.
|
|
||||||
winners = conf_table.groupby('Див', sort=False).head(1)
|
|
||||||
rest = conf_table.drop(winners.index)
|
|
||||||
return pd.concat([winners, rest])
|
|
||||||
|
|
||||||
|
|
||||||
def show_table(table, title):
|
|
||||||
'''
|
|
||||||
Напечатать таблицу конференции в консоль.
|
|
||||||
|
|
||||||
То же, что show_table в main.py, но дополнительно выводит столбец 'Див'
|
|
||||||
(дивизион) - чтобы было видно, почему победители дивизионов оказались наверху.
|
|
||||||
Принимает: table - готовая (уже посеянная) таблица; title - заголовок.
|
|
||||||
Ничего не возвращает - только печатает.
|
|
||||||
'''
|
|
||||||
# Тот же набор колонок, что на сайте КХЛ, плюс столбец дивизиона.
|
|
||||||
cols = ['Див', 'И', 'В', 'ВО', 'ВБ', 'ПБ', 'ПО', 'П', 'ГЗ', 'ГП', 'Р', 'О', '%О']
|
|
||||||
view = table[cols].copy()
|
|
||||||
view.insert(0, 'Место', np.arange(1, len(view) + 1))
|
|
||||||
view.insert(1, 'Команда', view.index)
|
|
||||||
|
|
||||||
print('\n' + '=' * 86)
|
|
||||||
print(title)
|
|
||||||
print('=' * 86)
|
|
||||||
print(view.to_string(index=False))
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
'''
|
|
||||||
Точка входа. Шаги:
|
|
||||||
1) определить сезон по имени CSV-файла;
|
|
||||||
2) построить таблицу команд через build_standings (логика из main.py);
|
|
||||||
3) приписать каждой команде дивизион (столбец 'Див');
|
|
||||||
4) для каждой конференции при необходимости применить посев победителей
|
|
||||||
дивизионов (seed_conference) и напечатать результат.
|
|
||||||
Пример: python3 divisions.py khl_3/khl_2020_21.csv
|
|
||||||
'''
|
|
||||||
path = sys.argv[1]
|
|
||||||
name = os.path.basename(path)
|
|
||||||
season = name.replace('khl_', '').replace('.csv', '')
|
|
||||||
|
|
||||||
df = pd.read_csv(path)
|
|
||||||
table = build_standings(df, CONFERENCES[season])
|
|
||||||
|
|
||||||
# Подписываем каждой команде её дивизион.
|
|
||||||
table['Див'] = pd.Series(table.index, index=table.index).map(DIVISIONS[season])
|
|
||||||
|
|
||||||
use_seeding = SEED_BY_DIVISION[season]
|
|
||||||
for conf in ['Запад', 'Восток']:
|
|
||||||
part = table[table['Конф'] == conf]
|
|
||||||
if use_seeding:
|
|
||||||
part = seed_conference(part)
|
|
||||||
suffix = ' (посев по дивизионам)' if use_seeding else ' (по очкам, без посева)'
|
|
||||||
show_table(part, 'Конференция ' + conf + ' ' + season + suffix)
|
|
||||||
|
|
||||||
|
|
||||||
main()
|
|
||||||
Loading…
Reference in a new issue