Pull to refresh

Формирование турнирных таблиц, stored procedures SQL

Reading time3 min
Views9K
На днях прочитал пост об автоматизированном формирование футбольных чемпионатов и решил поделится своим решением данной задачи, которое использовал для небольшой игры. Реализация жеребьевки сделана не стандартным подходом, при помощи хранимых процедур MS SQL Server.

В итоге у меня получилась структура базы данных и хранимые процедуры, которые позволяют формировать таблицу игр между командами(выполнять жеребьевку) и обрабатывать результаты чемпионата. Все скрипты можно скачать с репозитория на github.

Таблица игр чемпионата


Основная хранимая процедура — это процедура формирования игр чемпионата между командами. При формировании я придерживался основных правил турнира:
  • Количество команд участвующих в турнире должно быть четным;
  • Каждая команда должна сыграть с другой 2 раза — на своем стадионе и на стадионе соперников;
  • В одном туре одна и та же команда может играть лишь один раз;
  • За победу в матче команда получает — 2 очка, за ничью — 1 очко, а за проигрыш соответственно — 0.

Давайте поэтапно рассмотрим алгоритм формирования таблицы игр. Логику буду стараться описывать детально, не скучно и с демонстрацией схем. Как пример давайте возьмем чемпионат в котором участвуют 4 команды, хотя алгоритм может работать с любым четным количеством команд. Условно давайте обозначим наши команды под номерами 1, 2, 3 и 4, которые в моей реализации являются их прямыми ID.

Первое что необходимо было сделать — это вычислить количество турниров чемпионата и сформировать пары команд для игр. Количество турниров зависит от количества команд, поскольку одна команда с другой может сыграть в одном туре лишь один раз и она не должна играть сама с собой. Вычисляется это по формуле:

@TournamentsCnt = (@TeamsCnt * (@TeamsCnt - 1) * 2) / @TeamsCnt


После этого мы формируем список пар команд для всех игр чемпионата. Для этого можно считать что у нас есть 2 списка с идентичными номерами всех команд чемпионата.


Каждая команда первого списка, должна сыграть с каждой командой второго списка один раз, исключая команду с таким же номером(саму себя). В результате у нас получится список пар команд чемпионата следующего вида.


После того как мы получил список пар команд нам необходимо распределить их по турах не забывая об условии: одна команда может играть только один раз за тур и две команды могут играть только дважды друг с другом за чемпионат на домашнем и гостевом стадионах.

Количество игр, которые происходят за один тур равны общему количеству команд чемпионата. Для формирования тура берется самая первая пара команд из ранее сформированного списка, номера команд записываются в игру тура и во временный массив, а из списка пар команд удаляются. Для формирования остальных игр тура будет использоваться такая же логика, только теперь пары команд номера которых есть во временном массиве будут пропускаться, таким образом за один тур не смогут играть две одинаковых команды, но и ни одна команда не останется без дела. По завершению временный массив очищается и данный алгоритм будет повторятся пока все туры не будут заполнены.


По окончанию выполнения алгоритма список всех пар команд чемпионата будет пустым, игры будут сформированы и все туры заполнены играми — все соответствует правилам проведения чемпионата.

Основной алгоритм, которым я хотел поделится описан, в подробности синтаксиса хранимых процедур SQL я не вдавался, поскольку это уже другая тема и другой пост. Все скрипты с реализацией примера можно найти в репозитории на github. На данный момент скрипты работают и проверены на MS SQL Server, если для вас это интересно, то перепишу под СУБД, которую вы используете. В проекте также находятся хранимые процедуры для вычисления лучшего голкипера, бомбардира, «Путь чемпиона» и несколько других для взаимодействия с данными чемпионата.

Для корректной работы скриптов необходимо создать сперва базу данных FootballTournament. Для работы хранимых процедур подсчета лучше бомбардира, голкипера и других вспомогательных хранимых процедур должны быть выполнены первые две: формирование турниров и генерирования случайных данных результатов игр.

Скрипты с примера запускать в следующем порядке:
  1. Формирование схемы базы данных 'schema.sql'.
  2. Заполнение таблиц игроками, командами, тренерами и их стадионами 'fillTestData.sql'.
  3. Создание хранимых процедур 'storedProcedurs.sql'.
  4. Вызов хранимых процедур 'execute.sql'.

Благодарю всех кому было интересно дочитали до конца.

Ссылка на репозиторий проекта на github
Tags:
Hubs:
Rating0
Comments0

Articles