Skip to main content

Generate optimal schedules for your time-relaxed double round-robin (2RR) sports leagues

Project description

⚽📅 2RR League Planner

PyPI Python CI License: MIT Streamlit App PyPI - Downloads

If you are looking to schedule a sports league with at least the following constraints...

  • Everyone plays 1 home game and 1 away game against each other (double round-robin)
  • Home games are played on reserved dates
  • Away games are not played on unavailable dates
  • No team plays 2 games on the same day
  • The calendar is spread out such that teams have enough rest days between games

... then the leagueplanner Python package will help you!

[!NOTE] Plan/schedule/calendar is used interchangeably. The output of the planner is a calendar (or schedule) of games.

Installation

Install from PyPI:

pip install leagueplanner

Or with uv:

uv add leagueplanner

For development, clone the repository and run:

uv venv
uv sync

Usage

Input

The Excel file example/input.xlsx contains an example of the input data. The input should always, in the exact format as in the example, include the reserved dates (together with location and time) and unavailable dates of all teams from a single league.

One sheet corresponds to one league.

A typical league could consist of 10 teams, each with around 15 reserved dates and a number of unavailable dates (e.g. during holidays).

Output

The generated output for a single league is a solutions matrix X that can easily be converted into a clear DataFrame calendar, and stored as an Excel file.

The calendar includes the date, time, location, home team and away team for each game. The unplanned games are put at the bottom.

Scheduling

CLI

You can use the planner from the command line as follows:

2rr \
--input_file "example/input.xlsx" \
--output_folder "example/output" \
--seed 321 \
--n_iterations 500

The above example can also be run with make example.

See 2rr --help (and the research paper mentioned at the top) for more information about all the available arguments.

Classes

To more freely play around, you can import the core classes in your own Python script or notebook.

Here's a minimal example with default parameters:

from leagueplanner import InputParser, LeaguePlanner

# load input data with teams and their reserved/unavailable dates
input = InputParser(input_file)
input.from_excel(sheet_name=input.sheet_names[0])
input.parse()

# run the optimizer to find a good schedule
planner = LeaguePlanner(input=input)
planner.construction_phase()
planner.tabu_phase()

# convert the schedule into a usable Excel file
df = planner.create_calendar()
planner.store_calendar(df, file="out/calendar.xlsx")

Type help(LeaguePlanner) to show the full documentation.

Web application

The league planner is also made available through a hosted Streamlit application.

It has a more limited set of parameters (namely m, r_max, n_iterations, and penalties) but can be used out of the box yet without logging.

Additionally, the output file includes for every league and by team the distribution of the number of adjusted rest days between games (meaning that unavailable dates by that team are not considered in the count of the rest days), as well as the unused home time slots per team. This facilitates post-analysis of the quality of the generated calendar.

If the app sleeps due to inactivity 😴, just wake it back up. You can run the app locally with make web.

Algorithm

The optimizer implements constrained time-relaxed double round-robin (2RR) sports league scheduling using the tabu search based heuristic algorithm described in the paper Scheduling a non-professional indoor football league by Van Bulck, Goosens and Spieksma (2019).

The used meta-algorithm heavily relies on the Hungarian algorithm to recurrently solve the transportation problem. We include some additional internal tricks, especially to minimize excessive rest days (fixed at 28) between consecutive games of the same team.

Timings

How long does the planner take? This table sheds some baseline light for a league of 13 teams (156 games):

Iterations Time
10 <1s
100 <1s
1k <1s
10k ~3s
100k ~25s
1M ~230s

Run on a few years old Windows 10 Pro machine with Intel i7–7700HQ CPU and 32GB RAM.

A few 100(0)s iterations are typically sufficient to arrive at a good schedule.

Quite fast, thanks to Ra-Ra-Rust via this own repo's custom Transportation Problem Solver fasttps! 🦀

Feedback?

Let me know if you have any feedback or suggestions for improvement!

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

leagueplanner-0.1.0.tar.gz (22.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

leagueplanner-0.1.0-py3-none-any.whl (21.3 kB view details)

Uploaded Python 3

File details

Details for the file leagueplanner-0.1.0.tar.gz.

File metadata

  • Download URL: leagueplanner-0.1.0.tar.gz
  • Upload date:
  • Size: 22.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.10.7 {"installer":{"name":"uv","version":"0.10.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for leagueplanner-0.1.0.tar.gz
Algorithm Hash digest
SHA256 51d11975baf9584153d1237fec73b4c3ea1655a46ca0f1b6d9ea951f2f0b24b2
MD5 8da8964f3332595e4cb64049445bf0f9
BLAKE2b-256 78aae0b6ab07da387af569e87f538c158807ff7033c58ecb6426bd5049e5a96e

See more details on using hashes here.

File details

Details for the file leagueplanner-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: leagueplanner-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 21.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.10.7 {"installer":{"name":"uv","version":"0.10.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for leagueplanner-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 855c46cb9af78e898ec6c19c7ce3a5a220d2c6137184b93022c3d1f5e3aeefc3
MD5 70a35205f5574e9dd08f7af64a320245
BLAKE2b-256 088ab192c0dbe848ad1715ac397b95e520c9f04f7054d98519f2227dc8c46291

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page