sports-manager 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. checksums.yaml +7 -0
  2. data/.rspec +1 -0
  3. data/.rubocop.yml +32 -0
  4. data/CODE_OF_CONDUCT.md +132 -0
  5. data/CONTRIBUTING.md +72 -0
  6. data/MIT-LICENSE +20 -0
  7. data/README.md +419 -0
  8. data/Rakefile +4 -0
  9. data/lib/sports-manager.rb +59 -0
  10. data/lib/sports_manager/algorithms/filtering/no_overlap.rb +52 -0
  11. data/lib/sports_manager/algorithms/ordering/multiple_matches_participant.rb +78 -0
  12. data/lib/sports_manager/bye_match.rb +62 -0
  13. data/lib/sports_manager/constraint_builder.rb +30 -0
  14. data/lib/sports_manager/constraints/all_different_constraint.rb +24 -0
  15. data/lib/sports_manager/constraints/match_constraint.rb +37 -0
  16. data/lib/sports_manager/constraints/multi_category_constraint.rb +49 -0
  17. data/lib/sports_manager/constraints/next_round_constraint.rb +48 -0
  18. data/lib/sports_manager/constraints/no_overlapping_constraint.rb +55 -0
  19. data/lib/sports_manager/double_team.rb +7 -0
  20. data/lib/sports_manager/group.rb +42 -0
  21. data/lib/sports_manager/group_builder.rb +72 -0
  22. data/lib/sports_manager/helper.rb +228 -0
  23. data/lib/sports_manager/json_helper.rb +129 -0
  24. data/lib/sports_manager/match.rb +91 -0
  25. data/lib/sports_manager/match_builder.rb +112 -0
  26. data/lib/sports_manager/matches/algorithms/single_elimination_algorithm.rb +94 -0
  27. data/lib/sports_manager/matches/next_round.rb +38 -0
  28. data/lib/sports_manager/matches_generator.rb +33 -0
  29. data/lib/sports_manager/nil_team.rb +24 -0
  30. data/lib/sports_manager/participant.rb +23 -0
  31. data/lib/sports_manager/single_team.rb +7 -0
  32. data/lib/sports_manager/solution_drawer/cli/solution_table.rb +38 -0
  33. data/lib/sports_manager/solution_drawer/cli/table.rb +94 -0
  34. data/lib/sports_manager/solution_drawer/cli.rb +75 -0
  35. data/lib/sports_manager/solution_drawer/mermaid/bye_node.rb +39 -0
  36. data/lib/sports_manager/solution_drawer/mermaid/gantt.rb +126 -0
  37. data/lib/sports_manager/solution_drawer/mermaid/graph.rb +111 -0
  38. data/lib/sports_manager/solution_drawer/mermaid/node.rb +55 -0
  39. data/lib/sports_manager/solution_drawer/mermaid/node_style.rb +89 -0
  40. data/lib/sports_manager/solution_drawer/mermaid/solution_gantt.rb +57 -0
  41. data/lib/sports_manager/solution_drawer/mermaid/solution_graph.rb +76 -0
  42. data/lib/sports_manager/solution_drawer/mermaid.rb +65 -0
  43. data/lib/sports_manager/solution_drawer.rb +23 -0
  44. data/lib/sports_manager/team.rb +47 -0
  45. data/lib/sports_manager/team_builder.rb +31 -0
  46. data/lib/sports_manager/timeslot.rb +37 -0
  47. data/lib/sports_manager/timeslot_builder.rb +50 -0
  48. data/lib/sports_manager/tournament/setting.rb +45 -0
  49. data/lib/sports_manager/tournament.rb +69 -0
  50. data/lib/sports_manager/tournament_builder.rb +123 -0
  51. data/lib/sports_manager/tournament_day/validator.rb +69 -0
  52. data/lib/sports_manager/tournament_day.rb +50 -0
  53. data/lib/sports_manager/tournament_generator.rb +183 -0
  54. data/lib/sports_manager/tournament_problem_builder.rb +106 -0
  55. data/lib/sports_manager/tournament_solution/bye_fixture.rb +21 -0
  56. data/lib/sports_manager/tournament_solution/fixture.rb +39 -0
  57. data/lib/sports_manager/tournament_solution/serializer.rb +107 -0
  58. data/lib/sports_manager/tournament_solution/solution.rb +85 -0
  59. data/lib/sports_manager/tournament_solution.rb +34 -0
  60. data/lib/sports_manager/version.rb +5 -0
  61. data/sports-manager.gemspec +35 -0
  62. metadata +120 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: c758d344e9f382f5f1490e5a561b9985bac567cab55277644a0ae48374150f43
4
+ data.tar.gz: 1e8f37239ca689cb3103112a868ec9add0e1b7e95f7fb14a291a80a70b2e856d
5
+ SHA512:
6
+ metadata.gz: 2d27aa5f4eb1b3ca85708b9f15139a73e31c5fabd35a47396caf7a59c51cfd0f04bb948d86f7cd57aa70de9436634f091472d75b6354b7e4946b895b4d980458
7
+ data.tar.gz: 742a411241704d99cbe9b4d6410ccf5a4d5dbb829a96210eac778dc9105ba31c0e1adafbe6308d05e257f50fef2ee0c4fccd5d0db222ec4fb43ead9545f87778
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --require spec_helper
data/.rubocop.yml ADDED
@@ -0,0 +1,32 @@
1
+ AllCops:
2
+ TargetRubyVersion: 2.5
3
+ NewCops: enable
4
+ SuggestExtensions: false
5
+ Metrics/BlockLength:
6
+ Exclude:
7
+ - spec/**/*.rb
8
+ Metrics/ClassLength:
9
+ Max: 200
10
+ Metrics/MethodLength:
11
+ Max: 20
12
+ Layout/FirstArrayElementIndentation:
13
+ EnforcedStyle: consistent
14
+ Layout/FirstHashElementIndentation:
15
+ EnforcedStyle: consistent
16
+ Layout/HashAlignment:
17
+ EnforcedLastArgumentHashStyle: always_inspect
18
+ Layout/MultilineMethodCallIndentation:
19
+ EnforcedStyle: indented
20
+ Style/Documentation:
21
+ Enabled: false
22
+ Layout/EndAlignment:
23
+ EnforcedStyleAlignWith: variable
24
+ Style/ObjectThen:
25
+ EnforcedStyle: yield_self
26
+ Naming/FileName:
27
+ Exclude:
28
+ - 'lib/sports-manager.rb'
29
+ Style/OpenStructUse:
30
+ Enabled: false
31
+ Gemspec/RequireMFA:
32
+ Enabled: false
@@ -0,0 +1,132 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ We as members, contributors, and leaders pledge to make participation in our
6
+ community a harassment-free experience for everyone, regardless of age, body
7
+ size, visible or invisible disability, ethnicity, sex characteristics, gender
8
+ identity and expression, level of experience, education, socio-economic status,
9
+ nationality, personal appearance, race, caste, color, religion, or sexual
10
+ identity and orientation.
11
+
12
+ We pledge to act and interact in ways that contribute to an open, welcoming,
13
+ diverse, inclusive, and healthy community.
14
+
15
+ ## Our Standards
16
+
17
+ Examples of behavior that contributes to a positive environment for our
18
+ community include:
19
+
20
+ * Demonstrating empathy and kindness toward other people
21
+ * Being respectful of differing opinions, viewpoints, and experiences
22
+ * Giving and gracefully accepting constructive feedback
23
+ * Accepting responsibility and apologizing to those affected by our mistakes,
24
+ and learning from the experience
25
+ * Focusing on what is best not just for us as individuals, but for the overall
26
+ community
27
+
28
+ Examples of unacceptable behavior include:
29
+
30
+ * The use of sexualized language or imagery, and sexual attention or advances of
31
+ any kind
32
+ * Trolling, insulting or derogatory comments, and personal or political attacks
33
+ * Public or private harassment
34
+ * Publishing others' private information, such as a physical or email address,
35
+ without their explicit permission
36
+ * Other conduct which could reasonably be considered inappropriate in a
37
+ professional setting
38
+
39
+ ## Enforcement Responsibilities
40
+
41
+ Community leaders are responsible for clarifying and enforcing our standards of
42
+ acceptable behavior and will take appropriate and fair corrective action in
43
+ response to any behavior that they deem inappropriate, threatening, offensive,
44
+ or harmful.
45
+
46
+ Community leaders have the right and responsibility to remove, edit, or reject
47
+ comments, commits, code, wiki edits, issues, and other contributions that are
48
+ not aligned to this Code of Conduct, and will communicate reasons for moderation
49
+ decisions when appropriate.
50
+
51
+ ## Scope
52
+
53
+ This Code of Conduct applies within all community spaces, and also applies when
54
+ an individual is officially representing the community in public spaces.
55
+ Examples of representing our community include using an official email address,
56
+ posting via an official social media account, or acting as an appointed
57
+ representative at an online or offline event.
58
+
59
+ ## Enforcement
60
+
61
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
62
+ reported to the community leaders responsible for enforcement at
63
+ devs@rebase.com.br.
64
+ All complaints will be reviewed and investigated promptly and fairly.
65
+
66
+ All community leaders are obligated to respect the privacy and security of the
67
+ reporter of any incident.
68
+
69
+ ## Enforcement Guidelines
70
+
71
+ Community leaders will follow these Community Impact Guidelines in determining
72
+ the consequences for any action they deem in violation of this Code of Conduct:
73
+
74
+ ### 1. Correction
75
+
76
+ **Community Impact**: Use of inappropriate language or other behavior deemed
77
+ unprofessional or unwelcome in the community.
78
+
79
+ **Consequence**: A private, written warning from community leaders, providing
80
+ clarity around the nature of the violation and an explanation of why the
81
+ behavior was inappropriate. A public apology may be requested.
82
+
83
+ ### 2. Warning
84
+
85
+ **Community Impact**: A violation through a single incident or series of
86
+ actions.
87
+
88
+ **Consequence**: A warning with consequences for continued behavior. No
89
+ interaction with the people involved, including unsolicited interaction with
90
+ those enforcing the Code of Conduct, for a specified period of time. This
91
+ includes avoiding interactions in community spaces as well as external channels
92
+ like social media. Violating these terms may lead to a temporary or permanent
93
+ ban.
94
+
95
+ ### 3. Temporary Ban
96
+
97
+ **Community Impact**: A serious violation of community standards, including
98
+ sustained inappropriate behavior.
99
+
100
+ **Consequence**: A temporary ban from any sort of interaction or public
101
+ communication with the community for a specified period of time. No public or
102
+ private interaction with the people involved, including unsolicited interaction
103
+ with those enforcing the Code of Conduct, is allowed during this period.
104
+ Violating these terms may lead to a permanent ban.
105
+
106
+ ### 4. Permanent Ban
107
+
108
+ **Community Impact**: Demonstrating a pattern of violation of community
109
+ standards, including sustained inappropriate behavior, harassment of an
110
+ individual, or aggression toward or disparagement of classes of individuals.
111
+
112
+ **Consequence**: A permanent ban from any sort of public interaction within the
113
+ community.
114
+
115
+ ## Attribution
116
+
117
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage],
118
+ version 2.1, available at
119
+ [https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].
120
+
121
+ Community Impact Guidelines were inspired by
122
+ [Mozilla's code of conduct enforcement ladder][Mozilla CoC].
123
+
124
+ For answers to common questions about this code of conduct, see the FAQ at
125
+ [https://www.contributor-covenant.org/faq][FAQ]. Translations are available at
126
+ [https://www.contributor-covenant.org/translations][translations].
127
+
128
+ [homepage]: https://www.contributor-covenant.org
129
+ [v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
130
+ [Mozilla CoC]: https://github.com/mozilla/diversity
131
+ [FAQ]: https://www.contributor-covenant.org/faq
132
+ [translations]: https://www.contributor-covenant.org/translations
data/CONTRIBUTING.md ADDED
@@ -0,0 +1,72 @@
1
+ # Contributing
2
+
3
+ Thank you for your interest in contributing! We welcome contributions of all kinds, including new features, bug fixes, and documentation improvements.
4
+
5
+ Please take a moment to review this document to make the contribution process easy and effective for everyone involved.
6
+
7
+ If you have any questions, feel free to reach out by opening an issue or contacting the maintainers directly.
8
+
9
+ ## Table of Contents
10
+ 1. [How to Report an Issue](#how-to-report-an-issue)
11
+ 2. [Submitting a Pull Request](#submitting-a-pull-request)
12
+ 3. [Coding Guidelines](#coding-guidelines)
13
+ 4. [Code of Conduct](#code-of-conduct)
14
+
15
+ ## How to Report an Issue
16
+
17
+ If you encounter any bugs or have feature requests, please create an issue on our GitHub repository.
18
+
19
+ 1. Go to the [Issues]((githubrepo)/issues) page.
20
+ 2. Click on "New Issue".
21
+ 3. Select the "Bug report" or "Feature request".
22
+ 4. Fill in the details as prompted by the template.
23
+
24
+ If your issue does not fit the provided templates, feel free to create an issue without following them. Provide as much detail as possible to help us understand and address your concern.
25
+
26
+ ## Submitting a Pull Request
27
+ To submit a pull request, please follow these steps:
28
+
29
+ 1. **Fork the Repository**:
30
+ - Navigate to the [repository]((githubrepo)).
31
+ - Click the "Fork" button in the top-right corner.
32
+ 2. **Clone the Forked Repository**:
33
+ ```sh
34
+ git clone (githubrepo)
35
+ cd sports-manager
36
+ ```
37
+ 3. **Create a Branch**:
38
+ ```sh
39
+ git checkout -b <your-branch-name>
40
+ ```
41
+ 4. **Make Your Changes**:
42
+ - Implement your feature, bug fix, or documentation improvement.
43
+ - If you're making changes to the code, write some tests.
44
+ - Ensure your code follows our [Coding Guidelines](#coding-guidelines).
45
+ 5. **Commit Your Changes**:
46
+ ```sh
47
+ git add .
48
+ git commit -m "Description of your changes"
49
+ ```
50
+ 6. **Push to Your Fork**:
51
+ ```sh
52
+ git push origin your-branch-name
53
+ ```
54
+ 7. **Create a Pull Request**:
55
+ - Go to your fork on GitHub.
56
+ - Click on the "Compare & pull request" button.
57
+ - Fill in the details of your pull request and submit.
58
+
59
+ We will review your pull request and provide feedback. Please be responsive to our comments and make the necessary adjustments.
60
+
61
+ ## Coding Guidelines
62
+
63
+ To ensure consistency and maintainability of the codebase, please adhere to the following guidelines:
64
+
65
+ - Follow the Ruby community's [style guide](https://rubystyle.guide/).
66
+ - Write tests for your changes.
67
+ - Ensure all tests pass before submitting a pull request.
68
+ - Document public methods and classes.
69
+
70
+ ## Code of Conduct
71
+
72
+ By participating in this project, you agree to abide by our [Code of Conduct](./CODE_OF_CONDUCT.md). Please be respectful and considerate in all interactions.
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2024 Rebase, André Benjamim, Gustavo Alberto.
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,419 @@
1
+ # Sports Manager Gem
2
+
3
+ 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`](https://github.com/Rebase-BR/csp-resolver) gem to solve these complex Constraint Satisfaction Problems (CSPs).
4
+
5
+ ## Getting Started
6
+
7
+ ### Requirements
8
+
9
+ - Ruby >= 2.5.8
10
+
11
+ ### Installing
12
+
13
+ You can install using the following command:
14
+
15
+ ```bash
16
+ gem install "sports-manager"
17
+ ```
18
+
19
+ Then install it:
20
+
21
+ ```bash
22
+ $ bundle install
23
+ ```
24
+
25
+ ## Usage
26
+
27
+ ### Setting Up a Tournament
28
+
29
+ To set up a tournament, you need to provide the following information:
30
+
31
+ ```ruby
32
+ require 'sports-manager'
33
+
34
+ days = {
35
+ '2023-09-09': { start: 9, end: 20 },
36
+ '2023-09-10': { start: 9, end: 13 }
37
+ }
38
+
39
+ courts = 2
40
+ game_length = 60
41
+ rest_break = 30
42
+ single_day_matches = false
43
+ subscriptions = {
44
+ mens_single: [
45
+ { id: 1, name: 'João' }, { id: 2, name: 'Marcelo' },
46
+ { id: 3, name: 'José' }, { id: 4, name: 'Pedro' },
47
+ { id: 5, name: 'Carlos' }, { id: 6, name: 'Leandro' },
48
+ { id: 7, name: 'Leonardo' }, { id: 8, name: 'Cláudio' },
49
+ { id: 9, name: 'Alexandre' }, { id: 10, name: 'Daniel' },
50
+ { id: 11, name: 'Marcos' }, { id: 12, name: 'Henrique' },
51
+ { id: 13, name: 'Joaquim' }, { id: 14, name: 'Alex' },
52
+ { id: 15, name: 'Bruno' }, { id: 16, name: 'Fábio' }
53
+ ]
54
+ }
55
+ matches = {
56
+ mens_single: [
57
+ [1, 16],
58
+ [2, 15],
59
+ [3, 14],
60
+ [4, 13],
61
+ [5, 12],
62
+ [6, 11],
63
+ [7, 10],
64
+ [8, 9]
65
+ ]
66
+ }
67
+
68
+ solution = SportsManager::TournamentGenerator.new(format: :cli)
69
+ .add_days(days)
70
+ .add_courts(courts)
71
+ .add_game_length(game_length)
72
+ .add_rest_break(rest_break)
73
+ .enable_single_day_matches(single_day_matches)
74
+ .add_subscriptions(subscriptions)
75
+ .single_elimination_algorithm
76
+ .add_matches(matches)
77
+ ```
78
+
79
+ You can also pass already generated matches to the generator,
80
+ it's useful when your already have the matches generated by another system,
81
+ but you still want to generate the schedule.
82
+
83
+ ```ruby
84
+ params = {
85
+ when: {
86
+ '2023-09-09': { start: 9, end: 20 },
87
+ '2023-09-10': { start: 9, end: 13 }
88
+ },
89
+ courts: 2,
90
+ game_length: 60,
91
+ rest_brake: 30,
92
+ single_day_matches: false,
93
+ subscriptions: {
94
+ mens_single: [
95
+ { id: 1, name: 'João' }, { id: 2, name: 'Marcelo' },
96
+ { id: 3, name: 'José' }, { id: 4, name: 'Pedro' },
97
+ { id: 5, name: 'Carlos' }, { id: 6, name: 'Leandro' },
98
+ { id: 7, name: 'Leonardo' }, { id: 8, name: 'Cláudio' },
99
+ { id: 9, name: 'Alexandre' }, { id: 10, name: 'Daniel' },
100
+ { id: 11, name: 'Marcos' }, { id: 12, name: 'Henrique' },
101
+ { id: 13, name: 'Joaquim' }, { id: 14, name: 'Alex' },
102
+ { id: 15, name: 'Bruno' }, { id: 16, name: 'Fábio' }
103
+ ]
104
+ },
105
+ matches: {
106
+ mens_single: [
107
+ { id: 1, participants: [1, 16], },
108
+ { id: 2, participants: [2, 15], },
109
+ { id: 3, participants: [3, 14], },
110
+ { id: 4, participants: [4, 13], },
111
+ { id: 5, participants: [5, 12], },
112
+ { id: 6, participants: [6, 11], },
113
+ { id: 7, participants: [7, 10], },
114
+ { id: 8, participants: [8, 9], },
115
+ { id: 9, depends_on: [1, 2], round: 1 },
116
+ { id: 10, depends_on: [3, 4], round: 1 },
117
+ { id: 11, depends_on: [5, 6], round: 1 },
118
+ { id: 12, depends_on: [7, 8], round: 1 },
119
+ { id: 13, depends_on: [9, 10], round: 2 },
120
+ { id: 14, depends_on: [11, 12], round: 2},
121
+ { id: 15, depends_on: [13, 14], round: 2},
122
+ ]
123
+ }
124
+ }
125
+ ```
126
+
127
+ #### Configuration methods
128
+
129
+ - `add_days(days)`: Adds the tournament days.
130
+ - `add_day(day, start, end)`: Adds a single tournament day.
131
+ - `add_courts(courts)`: Adds the number of available courts.
132
+ - `add_game_length(game_length)`: Adds the duration of each game in minutes.
133
+ - `add_rest_break(rest_break)`: Adds the rest time between player matches in minutes.
134
+ - `enable_single_day_matches(single_day_matches)`: Sets if all matches should be on the same day.
135
+ - `add_subscriptions(subscriptions)`: Adds the players or teams participating in each category.
136
+ - `add_subscription(category, subscription)`: Adds a single player or team to a category.
137
+ - `add_subscriptions_per_category(subscriptions_per_category)`: Adds the players or teams participating per category.
138
+ - `add_matches(matches)`: Adds the first matchups for each category.
139
+ - `add_match(category, match)`: Adds a single match to a category.
140
+ - `add_matches_per_category(category, matches_per_category)`: Adds the first matchups per category.
141
+ - `single_elimination_algorithm`: Sets the single elimination algorithm(this option is already default).
142
+
143
+
144
+ ### Running Example Tournaments
145
+
146
+ The gem comes with predefined example tournaments:
147
+
148
+ ```ruby
149
+ solution = SportsManager::TournamentGenerator.example(:simple)
150
+ solution = SportsManager::TournamentGenerator.example(:complex)
151
+ #complete, minimal, ...
152
+ ```
153
+
154
+ ### Output Formats
155
+
156
+ You can choose different output formats:
157
+
158
+ ```ruby
159
+ # CLI format (default)
160
+ SportsManager::TournamentGenerator.new(format: :cli)
161
+
162
+ # Mermaid format (for visual diagrams)
163
+ SportsManager::TournamentGenerator.new(format: :mermaid)
164
+ ```
165
+ #### Output examples
166
+
167
+ ```ruby
168
+ require 'sports-manager'
169
+
170
+ days = {
171
+ '2023-09-09': { start: 9, end: 20 },
172
+ '2023-09-10': { start: 9, end: 13 }
173
+ }
174
+
175
+ courts = 2
176
+ game_length = 60
177
+ rest_break = 30
178
+ single_day_matches = false
179
+ subscriptions = {
180
+ mens_single: [
181
+ { id: 1, name: 'João' }, { id: 2, name: 'Marcelo' },
182
+ { id: 3, name: 'José' }, { id: 4, name: 'Pedro' },
183
+ { id: 5, name: 'Carlos' }, { id: 6, name: 'Leandro' },
184
+ { id: 7, name: 'Leonardo' }, { id: 8, name: 'Cláudio' },
185
+ { id: 9, name: 'Alexandre' }, { id: 10, name: 'Daniel' },
186
+ { id: 11, name: 'Marcos' }, { id: 12, name: 'Henrique' },
187
+ { id: 13, name: 'Joaquim' }, { id: 14, name: 'Alex' },
188
+ { id: 15, name: 'Bruno' }, { id: 16, name: 'Fábio' }
189
+ ]
190
+ }
191
+ matches = {
192
+ mens_single: [
193
+ [1, 16],
194
+ [2, 15],
195
+ [3, 14],
196
+ [4, 13],
197
+ [5, 12],
198
+ [6, 11],
199
+ [7, 10],
200
+ [8, 9]
201
+ ]
202
+ }
203
+
204
+ solution = SportsManager::TournamentGenerator.new(format: :cli)
205
+ .add_days(days)
206
+ .add_courts(courts)
207
+ .add_game_length(game_length)
208
+ .add_rest_break(rest_break)
209
+ .enable_single_day_matches(single_day_matches)
210
+ .add_subscriptions(subscriptions)
211
+ .single_elimination_algorithm
212
+ .add_matches(matches)
213
+ .call
214
+ ```
215
+ ```bash
216
+ Tournament Timetable:
217
+
218
+ Solution 1
219
+ category | id | round | participants | court | time
220
+ ------------|----|-------|-----------------------|-------|---------------
221
+ mens_single | 1 | 0 | João vs. Fábio | 0 | 09/09 at 09:00
222
+ mens_single | 2 | 0 | Marcelo vs. Bruno | 1 | 09/09 at 09:00
223
+ mens_single | 3 | 0 | José vs. Alex | 0 | 09/09 at 10:00
224
+ mens_single | 4 | 0 | Pedro vs. Joaquim | 1 | 09/09 at 10:00
225
+ mens_single | 5 | 0 | Carlos vs. Henrique | 0 | 09/09 at 11:00
226
+ mens_single | 6 | 0 | Leandro vs. Marcos | 1 | 09/09 at 11:00
227
+ mens_single | 7 | 0 | Leonardo vs. Daniel | 0 | 09/09 at 12:00
228
+ mens_single | 8 | 0 | Cláudio vs. Alexandre | 1 | 09/09 at 12:00
229
+ mens_single | 9 | 1 | M1 vs. M2 | 0 | 09/09 at 13:00
230
+ mens_single | 10 | 1 | M3 vs. M4 | 1 | 09/09 at 13:00
231
+ mens_single | 11 | 1 | M5 vs. M6 | 0 | 09/09 at 14:00
232
+ mens_single | 12 | 1 | M7 vs. M8 | 1 | 09/09 at 14:00
233
+ mens_single | 13 | 2 | M9 vs. M10 | 0 | 09/09 at 15:00
234
+ mens_single | 14 | 2 | M11 vs. M12 | 1 | 09/09 at 15:30
235
+ mens_single | 15 | 2 | M13 vs. M14 | 0 | 09/09 at 17:00
236
+
237
+ Total solutions: 1
238
+ ```
239
+ ```ruby
240
+ require 'sports-manager'
241
+
242
+ days = {
243
+ '2023-09-09': { start: 9, end: 20 },
244
+ '2023-09-10': { start: 9, end: 13 }
245
+ }
246
+
247
+ courts = 2
248
+ game_length = 60
249
+ rest_break = 30
250
+ single_day_matches = false
251
+ subscriptions = {
252
+ mens_single: [
253
+ { id: 1, name: 'João' }, { id: 2, name: 'Marcelo' },
254
+ { id: 3, name: 'José' }, { id: 4, name: 'Pedro' },
255
+ { id: 5, name: 'Carlos' }, { id: 6, name: 'Leandro' },
256
+ { id: 7, name: 'Leonardo' }, { id: 8, name: 'Cláudio' },
257
+ { id: 9, name: 'Alexandre' }, { id: 10, name: 'Daniel' },
258
+ { id: 11, name: 'Marcos' }, { id: 12, name: 'Henrique' },
259
+ { id: 13, name: 'Joaquim' }, { id: 14, name: 'Alex' },
260
+ { id: 15, name: 'Bruno' }, { id: 16, name: 'Fábio' }
261
+ ]
262
+ }
263
+ matches = {
264
+ mens_single: [
265
+ [1, 16],
266
+ [2, 15],
267
+ [3, 14],
268
+ [4, 13],
269
+ [5, 12],
270
+ [6, 11],
271
+ [7, 10],
272
+ [8, 9]
273
+ ]
274
+ }
275
+
276
+ solution = SportsManager::TournamentGenerator.new(format: :mermaid)
277
+ .add_days(days)
278
+ .add_courts(courts)
279
+ .add_game_length(game_length)
280
+ .add_rest_break(rest_break)
281
+ .enable_single_day_matches(single_day_matches)
282
+ .add_subscriptions(subscriptions)
283
+ .single_elimination_algorithm
284
+ .add_matches(matches)
285
+ .call
286
+ ```
287
+ ```bash
288
+ Solutions:
289
+ --------------------------------------------------------------------------------
290
+ Solutions 1
291
+ Gantt:
292
+ ---
293
+ displayMode: compact
294
+ ---
295
+ gantt
296
+ title Tournament Schedule
297
+ dateFormat DD/MM HH:mm
298
+ axisFormat %H:%M
299
+ tickInterval 1hour
300
+
301
+ section 0
302
+ MS M1: 09/09 09:00, 1h
303
+ MS M3: 09/09 10:00, 1h
304
+ MS M5: 09/09 11:00, 1h
305
+ MS M7: 09/09 12:00, 1h
306
+ MS M9: 09/09 13:00, 1h
307
+ MS M11: 09/09 14:00, 1h
308
+ MS M13: 09/09 15:00, 1h
309
+ MS M15: 09/09 17:00, 1h
310
+ section 1
311
+ MS M2: 09/09 09:00, 1h
312
+ MS M4: 09/09 10:00, 1h
313
+ MS M6: 09/09 11:00, 1h
314
+ MS M8: 09/09 12:00, 1h
315
+ MS M10: 09/09 13:00, 1h
316
+ MS M12: 09/09 14:00, 1h
317
+ MS M14: 09/09 15:30, 1h
318
+ Graph:
319
+ graph LR
320
+ classDef court0 fill:#A9F9A9, color:#000000
321
+ classDef court1 fill:#4FF7DE, color:#000000
322
+ subgraph colorscheme
323
+ direction LR
324
+
325
+ COURT0:::court0
326
+ COURT1:::court1
327
+ end
328
+ subgraph mens_single
329
+ direction LR
330
+
331
+ mens_single_1[1\nJoão vs. Fábio\n09/09 09:00]:::court0
332
+ mens_single_2[2\nMarcelo vs. Bruno\n09/09 09:00]:::court1
333
+ mens_single_3[3\nJosé vs. Alex\n09/09 10:00]:::court0
334
+ mens_single_4[4\nPedro vs. Joaquim\n09/09 10:00]:::court1
335
+ mens_single_5[5\nCarlos vs. Henrique\n09/09 11:00]:::court0
336
+ mens_single_6[6\nLeandro vs. Marcos\n09/09 11:00]:::court1
337
+ mens_single_7[7\nLeonardo vs. Daniel\n09/09 12:00]:::court0
338
+ mens_single_8[8\nCláudio vs. Alexandre\n09/09 12:00]:::court1
339
+ mens_single_9[9\nM1 vs. M2\n09/09 13:00]:::court0
340
+ mens_single_10[10\nM3 vs. M4\n09/09 13:00]:::court1
341
+ mens_single_11[11\nM5 vs. M6\n09/09 14:00]:::court0
342
+ mens_single_12[12\nM7 vs. M8\n09/09 14:00]:::court1
343
+ mens_single_13[13\nM9 vs. M10\n09/09 15:00]:::court0
344
+ mens_single_14[14\nM11 vs. M12\n09/09 15:30]:::court1
345
+ mens_single_15[15\nM13 vs. M14\n09/09 17:00]:::court0
346
+ mens_single_1 --> mens_single_9
347
+ mens_single_2 --> mens_single_9
348
+ mens_single_3 --> mens_single_10
349
+ mens_single_4 --> mens_single_10
350
+ mens_single_5 --> mens_single_11
351
+ mens_single_6 --> mens_single_11
352
+ mens_single_7 --> mens_single_12
353
+ mens_single_8 --> mens_single_12
354
+ mens_single_9 --> mens_single_13
355
+ mens_single_10 --> mens_single_13
356
+ mens_single_11 --> mens_single_14
357
+ mens_single_12 --> mens_single_14
358
+ mens_single_13 --> mens_single_15
359
+ mens_single_14 --> mens_single_15
360
+ end
361
+ --------------------------------------------------------------------------------
362
+ Total solutions: 1
363
+ ```
364
+ ```mermaid
365
+ graph LR
366
+ classDef court0 fill:#A9F9A9, color:#000000
367
+ classDef court1 fill:#4FF7DE, color:#000000
368
+ subgraph colorscheme
369
+ direction LR
370
+
371
+ COURT0:::court0
372
+ COURT1:::court1
373
+ end
374
+ subgraph mens_single
375
+ direction LR
376
+
377
+ mens_single_1[1\nJoão vs. Fábio\n09/09 09:00]:::court0
378
+ mens_single_2[2\nMarcelo vs. Bruno\n09/09 09:00]:::court1
379
+ mens_single_3[3\nJosé vs. Alex\n09/09 10:00]:::court0
380
+ mens_single_4[4\nPedro vs. Joaquim\n09/09 10:00]:::court1
381
+ mens_single_5[5\nCarlos vs. Henrique\n09/09 11:00]:::court0
382
+ mens_single_6[6\nLeandro vs. Marcos\n09/09 11:00]:::court1
383
+ mens_single_7[7\nLeonardo vs. Daniel\n09/09 12:00]:::court0
384
+ mens_single_8[8\nCláudio vs. Alexandre\n09/09 12:00]:::court1
385
+ mens_single_9[9\nM1 vs. M2\n09/09 13:00]:::court0
386
+ mens_single_10[10\nM3 vs. M4\n09/09 13:00]:::court1
387
+ mens_single_11[11\nM5 vs. M6\n09/09 14:00]:::court0
388
+ mens_single_12[12\nM7 vs. M8\n09/09 14:00]:::court1
389
+ mens_single_13[13\nM9 vs. M10\n09/09 15:00]:::court0
390
+ mens_single_14[14\nM11 vs. M12\n09/09 15:30]:::court1
391
+ mens_single_15[15\nM13 vs. M14\n09/09 17:00]:::court0
392
+ mens_single_1 --> mens_single_9
393
+ mens_single_2 --> mens_single_9
394
+ mens_single_3 --> mens_single_10
395
+ mens_single_4 --> mens_single_10
396
+ mens_single_5 --> mens_single_11
397
+ mens_single_6 --> mens_single_11
398
+ mens_single_7 --> mens_single_12
399
+ mens_single_8 --> mens_single_12
400
+ mens_single_9 --> mens_single_13
401
+ mens_single_10 --> mens_single_13
402
+ mens_single_11 --> mens_single_14
403
+ mens_single_12 --> mens_single_14
404
+ mens_single_13 --> mens_single_15
405
+ mens_single_14 --> mens_single_15
406
+ end
407
+ ```
408
+
409
+ ## Contributing
410
+
411
+ See our [CONTRIBUTING](./CONTRIBUTING.md) guidelines.
412
+
413
+ ## Code of Conduct
414
+
415
+ We expect that everyone participating in any way with this project follows our [Code of Conduct](./CODE_OF_CONDUCT.md).
416
+
417
+ ## License
418
+
419
+ This project is licensed under the [MIT License](MIT-LICENSE).
data/Rakefile ADDED
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
4
+ task default: %i[]