Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

sports-manager

Package Overview
Dependencies
Maintainers
2
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

sports-manager

  • 0.0.3
  • Rubygems
  • Socket score

Version published
Maintainers
2
Created
Source

Sports Manager Gem

The sports-manager gem is a powerful tool designed to generate and manage tournament schedules. It handles complex scheduling tasks, considering various constraints such as court availability, game length, rest breaks, and participant availability. Under the hood, it leverages the csp-resolver gem to solve these complex Constraint Satisfaction Problems (CSPs).

Getting Started

Requirements

  • Ruby >= 2.5.8

Installing

You can install using the following command:

gem install "sports-manager"

Or add the following line to your Gemfile:

gem "sports-manager"

Then install it:

$ bundle install

Usage

Setting Up a Tournament

To set up a tournament, you need to provide the following information:

require 'sports-manager'

days = {
  '2023-09-09': { start: 9, end: 20 },
  '2023-09-10': { start: 9, end: 13 }
}

courts = 2
game_length = 60
rest_break = 30
single_day_matches = false
subscriptions = {
  mens_single: [
    { id: 1, name: 'João' },      { id: 2, name: 'Marcelo' },
    { id: 3, name: 'José' },      { id: 4, name: 'Pedro' },
    { id: 5, name: 'Carlos' },    { id: 6, name: 'Leandro' },
    { id: 7, name: 'Leonardo' },  { id: 8, name: 'Cláudio' },
    { id: 9, name: 'Alexandre' }, { id: 10, name: 'Daniel' },
    { id: 11, name: 'Marcos' },   { id: 12, name: 'Henrique' },
    { id: 13, name: 'Joaquim' },  { id: 14, name: 'Alex' },
    { id: 15, name: 'Bruno' },    { id: 16, name: 'Fábio' }
  ]
}
matches = {
  mens_single: [
    [1, 16],
    [2, 15],
    [3, 14],
    [4, 13],
    [5, 12],
    [6, 11],
    [7, 10],
    [8, 9]
  ]
}

solution = SportsManager::TournamentGenerator.new(format: :cli)
  .add_days(days)
  .add_courts(courts)
  .add_game_length(game_length)
  .add_rest_break(rest_break)
  .enable_single_day_matches(single_day_matches)
  .add_subscriptions(subscriptions)
  .single_elimination_algorithm
  .add_matches(matches)

You can also pass already generated matches to the generator, it's useful when your already have the matches generated by another system, but you still want to generate the schedule.

params = {
  when: {
    '2023-09-09': { start: 9, end: 20 },
    '2023-09-10': { start: 9, end: 13 }
  },
  courts: 2,
  game_length: 60,
  rest_brake: 30,
  single_day_matches: false,
  subscriptions: {
    mens_single: [
      { id: 1, name: 'João' },      { id: 2, name: 'Marcelo' },
      { id: 3, name: 'José' },      { id: 4, name: 'Pedro' },
      { id: 5, name: 'Carlos' },    { id: 6, name: 'Leandro' },
      { id: 7, name: 'Leonardo' },  { id: 8, name: 'Cláudio' },
      { id: 9, name: 'Alexandre' }, { id: 10, name: 'Daniel' },
      { id: 11, name: 'Marcos' },   { id: 12, name: 'Henrique' },
      { id: 13, name: 'Joaquim' },  { id: 14, name: 'Alex' },
      { id: 15, name: 'Bruno' },    { id: 16, name: 'Fábio' }
    ]
  },
  matches: {
    mens_single: [
      { id: 1, participants: [1, 16], },
      { id: 2, participants: [2, 15], },
      { id: 3, participants: [3, 14], },
      { id: 4, participants: [4, 13], },
      { id: 5, participants: [5, 12], },
      { id: 6, participants: [6, 11], },
      { id: 7, participants: [7, 10], },
      { id: 8, participants: [8, 9], },
      { id: 9, depends_on: [1, 2], round: 1 },
      { id: 10, depends_on: [3, 4], round: 1 },
      { id: 11, depends_on: [5, 6], round: 1 },
      { id: 12, depends_on: [7, 8], round: 1 },
      { id: 13, depends_on: [9, 10], round: 2 },
      { id: 14, depends_on: [11, 12], round: 2},
      { id: 15, depends_on: [13, 14],  round: 2},
    ]
  }
}
Configuration methods
  • add_days(days): Adds the tournament days.
  • add_day(day, start, end): Adds a single tournament day.
  • add_courts(courts): Adds the number of available courts.
  • add_game_length(game_length): Adds the duration of each game in minutes.
  • add_rest_break(rest_break): Adds the rest time between player matches in minutes.
  • enable_single_day_matches(single_day_matches): Sets if all matches should be on the same day.
  • add_subscriptions(subscriptions): Adds the players or teams participating in each category.
  • add_subscription(category, subscription): Adds a single player or team to a category.
  • add_subscriptions_per_category(subscriptions_per_category): Adds the players or teams participating per category.
  • add_matches(matches): Adds the first matchups for each category.
  • add_match(category, match): Adds a single match to a category.
  • add_matches_per_category(category, matches_per_category): Adds the first matchups per category.
  • single_elimination_algorithm: Sets the single elimination algorithm(this option is already default).

Running Example Tournaments

The gem comes with predefined example tournaments:

solution = SportsManager::TournamentGenerator.example(:simple)
solution = SportsManager::TournamentGenerator.example(:complex)
#complete, minimal, ...

Output Formats

You can choose different output formats:

# CLI format (default)
SportsManager::TournamentGenerator.new(format: :cli)

# Mermaid format (for visual diagrams)
SportsManager::TournamentGenerator.new(format: :mermaid)
Output examples
require 'sports-manager'

days = {
  '2023-09-09': { start: 9, end: 20 },
  '2023-09-10': { start: 9, end: 13 }
}

courts = 2
game_length = 60
rest_break = 30
single_day_matches = false
subscriptions = {
  mens_single: [
    { id: 1, name: 'João' },      { id: 2, name: 'Marcelo' },
    { id: 3, name: 'José' },      { id: 4, name: 'Pedro' },
    { id: 5, name: 'Carlos' },    { id: 6, name: 'Leandro' },
    { id: 7, name: 'Leonardo' },  { id: 8, name: 'Cláudio' },
    { id: 9, name: 'Alexandre' }, { id: 10, name: 'Daniel' },
    { id: 11, name: 'Marcos' },   { id: 12, name: 'Henrique' },
    { id: 13, name: 'Joaquim' },  { id: 14, name: 'Alex' },
    { id: 15, name: 'Bruno' },    { id: 16, name: 'Fábio' }
  ]
}
matches = {
  mens_single: [
    [1, 16],
    [2, 15],
    [3, 14],
    [4, 13],
    [5, 12],
    [6, 11],
    [7, 10],
    [8, 9]
  ]
}

 solution = SportsManager::TournamentGenerator.new(format: :cli)
  .add_days(days)
  .add_courts(courts)
  .add_game_length(game_length)
  .add_rest_break(rest_break)
  .enable_single_day_matches(single_day_matches)
  .add_subscriptions(subscriptions)
  .single_elimination_algorithm
  .add_matches(matches)
  .call
Tournament Timetable:

Solution 1
 category   | id | round |     participants      | court |      time     
------------|----|-------|-----------------------|-------|---------------
mens_single | 1  | 0     | João vs. Fábio        | 0     | 09/09 at 09:00
mens_single | 2  | 0     | Marcelo vs. Bruno     | 1     | 09/09 at 09:00
mens_single | 3  | 0     | José vs. Alex         | 0     | 09/09 at 10:00
mens_single | 4  | 0     | Pedro vs. Joaquim     | 1     | 09/09 at 10:00
mens_single | 5  | 0     | Carlos vs. Henrique   | 0     | 09/09 at 11:00
mens_single | 6  | 0     | Leandro vs. Marcos    | 1     | 09/09 at 11:00
mens_single | 7  | 0     | Leonardo vs. Daniel   | 0     | 09/09 at 12:00
mens_single | 8  | 0     | Cláudio vs. Alexandre | 1     | 09/09 at 12:00
mens_single | 9  | 1     | M1 vs. M2             | 0     | 09/09 at 13:00
mens_single | 10 | 1     | M3 vs. M4             | 1     | 09/09 at 13:00
mens_single | 11 | 1     | M5 vs. M6             | 0     | 09/09 at 14:00
mens_single | 12 | 1     | M7 vs. M8             | 1     | 09/09 at 14:00
mens_single | 13 | 2     | M9 vs. M10            | 0     | 09/09 at 15:00
mens_single | 14 | 2     | M11 vs. M12           | 1     | 09/09 at 15:30
mens_single | 15 | 2     | M13 vs. M14           | 0     | 09/09 at 17:00

Total solutions: 1
require 'sports-manager'

days = {
  '2023-09-09': { start: 9, end: 20 },
  '2023-09-10': { start: 9, end: 13 }
}

courts = 2
game_length = 60
rest_break = 30
single_day_matches = false
subscriptions = {
  mens_single: [
    { id: 1, name: 'João' },      { id: 2, name: 'Marcelo' },
    { id: 3, name: 'José' },      { id: 4, name: 'Pedro' },
    { id: 5, name: 'Carlos' },    { id: 6, name: 'Leandro' },
    { id: 7, name: 'Leonardo' },  { id: 8, name: 'Cláudio' },
    { id: 9, name: 'Alexandre' }, { id: 10, name: 'Daniel' },
    { id: 11, name: 'Marcos' },   { id: 12, name: 'Henrique' },
    { id: 13, name: 'Joaquim' },  { id: 14, name: 'Alex' },
    { id: 15, name: 'Bruno' },    { id: 16, name: 'Fábio' }
  ]
}
matches = {
  mens_single: [
    [1, 16],
    [2, 15],
    [3, 14],
    [4, 13],
    [5, 12],
    [6, 11],
    [7, 10],
    [8, 9]
  ]
}

 solution = SportsManager::TournamentGenerator.new(format: :mermaid)
  .add_days(days)
  .add_courts(courts)
  .add_game_length(game_length)
  .add_rest_break(rest_break)
  .enable_single_day_matches(single_day_matches)
  .add_subscriptions(subscriptions)
  .single_elimination_algorithm
  .add_matches(matches)
  .call
Solutions:
--------------------------------------------------------------------------------
Solutions 1
Gantt:
---
displayMode: compact
---
gantt
  title Tournament Schedule
  dateFormat DD/MM HH:mm
  axisFormat %H:%M
  tickInterval 1hour

  section 0
    MS M1: 09/09 09:00, 1h
    MS M3: 09/09 10:00, 1h
    MS M5: 09/09 11:00, 1h
    MS M7: 09/09 12:00, 1h
    MS M9: 09/09 13:00, 1h
    MS M11: 09/09 14:00, 1h
    MS M13: 09/09 15:00, 1h
    MS M15: 09/09 17:00, 1h
  section 1
    MS M2: 09/09 09:00, 1h
    MS M4: 09/09 10:00, 1h
    MS M6: 09/09 11:00, 1h
    MS M8: 09/09 12:00, 1h
    MS M10: 09/09 13:00, 1h
    MS M12: 09/09 14:00, 1h
    MS M14: 09/09 15:30, 1h
Graph:
graph LR
classDef court0 fill:#A9F9A9, color:#000000
classDef court1 fill:#4FF7DE, color:#000000
subgraph colorscheme
  direction LR

  COURT0:::court0
  COURT1:::court1
end
subgraph mens_single
  direction LR

  mens_single_1[1\nJoão vs. Fábio\n09/09 09:00]:::court0
  mens_single_2[2\nMarcelo vs. Bruno\n09/09 09:00]:::court1
  mens_single_3[3\nJosé vs. Alex\n09/09 10:00]:::court0
  mens_single_4[4\nPedro vs. Joaquim\n09/09 10:00]:::court1
  mens_single_5[5\nCarlos vs. Henrique\n09/09 11:00]:::court0
  mens_single_6[6\nLeandro vs. Marcos\n09/09 11:00]:::court1
  mens_single_7[7\nLeonardo vs. Daniel\n09/09 12:00]:::court0
  mens_single_8[8\nCláudio vs. Alexandre\n09/09 12:00]:::court1
  mens_single_9[9\nM1 vs. M2\n09/09 13:00]:::court0
  mens_single_10[10\nM3 vs. M4\n09/09 13:00]:::court1
  mens_single_11[11\nM5 vs. M6\n09/09 14:00]:::court0
  mens_single_12[12\nM7 vs. M8\n09/09 14:00]:::court1
  mens_single_13[13\nM9 vs. M10\n09/09 15:00]:::court0
  mens_single_14[14\nM11 vs. M12\n09/09 15:30]:::court1
  mens_single_15[15\nM13 vs. M14\n09/09 17:00]:::court0
  mens_single_1 --> mens_single_9
  mens_single_2 --> mens_single_9
  mens_single_3 --> mens_single_10
  mens_single_4 --> mens_single_10
  mens_single_5 --> mens_single_11
  mens_single_6 --> mens_single_11
  mens_single_7 --> mens_single_12
  mens_single_8 --> mens_single_12
  mens_single_9 --> mens_single_13
  mens_single_10 --> mens_single_13
  mens_single_11 --> mens_single_14
  mens_single_12 --> mens_single_14
  mens_single_13 --> mens_single_15
  mens_single_14 --> mens_single_15
end
--------------------------------------------------------------------------------
Total solutions: 1
graph LR
classDef court0 fill:#A9F9A9, color:#000000
classDef court1 fill:#4FF7DE, color:#000000
subgraph colorscheme
  direction LR

  COURT0:::court0
  COURT1:::court1
end
subgraph mens_single
  direction LR

  mens_single_1[1\nJoão vs. Fábio\n09/09 09:00]:::court0
  mens_single_2[2\nMarcelo vs. Bruno\n09/09 09:00]:::court1
  mens_single_3[3\nJosé vs. Alex\n09/09 10:00]:::court0
  mens_single_4[4\nPedro vs. Joaquim\n09/09 10:00]:::court1
  mens_single_5[5\nCarlos vs. Henrique\n09/09 11:00]:::court0
  mens_single_6[6\nLeandro vs. Marcos\n09/09 11:00]:::court1
  mens_single_7[7\nLeonardo vs. Daniel\n09/09 12:00]:::court0
  mens_single_8[8\nCláudio vs. Alexandre\n09/09 12:00]:::court1
  mens_single_9[9\nM1 vs. M2\n09/09 13:00]:::court0
  mens_single_10[10\nM3 vs. M4\n09/09 13:00]:::court1
  mens_single_11[11\nM5 vs. M6\n09/09 14:00]:::court0
  mens_single_12[12\nM7 vs. M8\n09/09 14:00]:::court1
  mens_single_13[13\nM9 vs. M10\n09/09 15:00]:::court0
  mens_single_14[14\nM11 vs. M12\n09/09 15:30]:::court1
  mens_single_15[15\nM13 vs. M14\n09/09 17:00]:::court0
  mens_single_1 --> mens_single_9
  mens_single_2 --> mens_single_9
  mens_single_3 --> mens_single_10
  mens_single_4 --> mens_single_10
  mens_single_5 --> mens_single_11
  mens_single_6 --> mens_single_11
  mens_single_7 --> mens_single_12
  mens_single_8 --> mens_single_12
  mens_single_9 --> mens_single_13
  mens_single_10 --> mens_single_13
  mens_single_11 --> mens_single_14
  mens_single_12 --> mens_single_14
  mens_single_13 --> mens_single_15
  mens_single_14 --> mens_single_15
end

Contributing

See our CONTRIBUTING guidelines.

Code of Conduct

We expect that everyone participating in any way with this project follows our Code of Conduct.

License

This project is licensed under the MIT License.

FAQs

Package last updated on 29 Aug 2024

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc