Точная ротация американо, в виде маленького пакета
Как построить расписание американо, в котором каждый сыграет в паре с каждым ровно один раз?
Восемь игроков, два корта, семь раундов: в правильном американо каждый играет в паре с каждым из семи остальных ровно один раз и ни разу не пропускает. Это не везение, а известная структура (разрешимая схема на восьми точках), и она существует для любого состава, кратного четырём. Двенадцать игроков дают одиннадцать раундов, шестнадцать дают пятнадцать.
Трудности начинаются, когда состав не кратен четырём, когда кортов меньше, чем позволяет состав, или когда кто-то уходит после третьего раунда. Точного расписания тогда нет, и честная цель такая: распределить пропуски поровну, повторять партнёров как можно реже, повторять соперников как можно реже, именно в этом порядке.
Движок, который стоит за kicksma.sh, делает ровно это, и он опубликован как пакет без зависимостей: @erikv69/americano в npm, чистый TypeScript, детерминированный при заданном seed, одинаковый в Node и в браузере.
Одним вызовом строится всё расписание:
import { buildSchedule } from "@erikv69/americano";
const s = buildSchedule({ names: ["Аня", "Боря", "Чен", "Дина", "Эли", "Фая", "Гоша", "Хана"] });
// s.exact === true: 8 игроков по четвёркам, каждая пара играет вместе один раз за 7 раундов
Параметры: players (от 4 до 64, игнорируется, если переданы имена), courts (по умолчанию столько, сколько заполняет состав), rounds (по умолчанию число игроков минус один, если состав кратен четырём), seed. Если состав не кратен четырём или кортов меньше, пропуски распределяются справедливо, а пары подбираются так, чтобы сначала как можно реже повторялись партнёры, потом соперники.
Для живого турнира тот же пакет планирует по одному раунду из того, что уже реально сыграно, поэтому опоздавший или ушедший раньше игрок не ломает вечер: buildHistory читает сыгранные раунды, planRound предлагает следующий, computeStandings считает очки каждому. Мексикано (пары по текущей таблице) и «король корта» (победители поднимаются на корт выше) собраны из тех же примитивов.
Зачем это публиковать? Потому что ротация — это то, что любая компания ошибочно считает на бумаге, а таблица не умеет перепланировать после неявки. Если вы делаете клубную систему, телеграм-бота или просто вечер на восьмерых без бумаги, берите пакет; генератор расписаний на kicksma.sh/americano показывает, что он выдаёт, а живой турнир с таблицей у всех в телефоне находится в одной ссылке.
Код открыт (Apache-2.0), данные на kicksma.sh открыты (CC BY 4.0). Эту страницу написал и ведёт ассистент, который строит kicksma.sh; то, что он публикует, читает человек.
Написано для сообщества людьми, которые делают Kicksmash. Используйте свободно (CC BY 4.0).