I was looking to create a turn-based sports game which, inevitably, would include a playoffs simulator. This library provides a few, easy-to-use APIs to create, simulate, and complete a team & series-based tournament with one clear winner.
To install through Rubygems:
gem install playoffsYou can also add this to your Gemfile using:
bundle add playoffsCopy the executables locally:
bundle binstubs playoffsThis library comes with an executable which shows off the basics of consuming the underlying data structures. It is currently limited to supporting NBA-style playoffs (play-in games included). Let's say we are looking to model the 2024 NBA playoffs, we could run these commands to simulate step-by-step:
bin/playoffs 2024.yaml new BOS,NYK,MIL,CLE,ORL,IND,PHI,MIA,CHI,ATL,OKC,DEN,MIN,LAC,DAL,PHX,LAL,NO,SAC,GSNote(s):
- This will save a serialized tournament to
2024.yaml - The last argument is a comma-separated list of teams in ranked order per conference.
bin/playoffs 2024.yamlThis will output a tree-based text representation:
TBD
└ BestOf::7::Series::TBD::0::TBD::0
├ BestOf::7::Series::TBD::0::TBD::0
│ ├ BestOf::7::Series::TBD::0::TBD::0
│ │ ├ BestOf::7::Series::BOS::0::TBD::0
│ │ │ └ BestOf::1::Series::TBD::0::TBD::0
│ │ │ ├ BestOf::1::Series::PHI::0::MIA::0::LoserAdvances
│ │ │ └ BestOf::1::Series::CHI::0::ATL::0
│ │ └ BestOf::7::Series::CLE::0::ORL::0
│ └ BestOf::7::Series::TBD::0::TBD::0
│ ├ BestOf::7::Series::MIL::0::IND::0
│ └ BestOf::7::Series::NYK::0::TBD::0
│ └ BestOf::1::Series::PHI::0::MIA::0::WinnerAdvances
└ BestOf::7::Series::TBD::0::TBD::0
├ BestOf::7::Series::TBD::0::TBD::0
│ ├ BestOf::7::Series::OKC::0::TBD::0
│ │ └ BestOf::1::Series::TBD::0::TBD::0
│ │ ├ BestOf::1::Series::LAL::0::NO::0::LoserAdvances
│ │ └ BestOf::1::Series::SAC::0::GS::0::LoserAdvances
│ └ BestOf::7::Series::LAC::0::DAL::0
└ BestOf::7::Series::TBD::0::TBD::0
├ BestOf::7::Series::MIN::0::PHX::0
└ BestOf::7::Series::DEN::0::TBD::0
└ BestOf::1::Series::LAL::0::NO::0::WinnerAdvancesbin/playoffs 2024.yaml roundsThis will output all series, grouped by round:
BestOf::1::Series::PHI::0::MIA::0
BestOf::1::Series::CHI::0::ATL::0
BestOf::1::Series::LAL::0::NO::0
BestOf::1::Series::SAC::0::GS::0
BestOf::1::Series::TBD::0::TBD::0
BestOf::1::Series::PHI::0::MIA::0
BestOf::1::Series::TBD::0::TBD::0
BestOf::1::Series::LAL::0::NO::0
BestOf::7::Series::BOS::0::TBD::0
BestOf::7::Series::CLE::0::ORL::0
BestOf::7::Series::MIL::0::IND::0
BestOf::7::Series::NYK::0::TBD::0
BestOf::7::Series::OKC::0::TBD::0
BestOf::7::Series::LAC::0::DAL::0
BestOf::7::Series::MIN::0::PHX::0
BestOf::7::Series::DEN::0::TBD::0
BestOf::7::Series::TBD::0::TBD::0
BestOf::7::Series::TBD::0::TBD::0
BestOf::7::Series::TBD::0::TBD::0
BestOf::7::Series::TBD::0::TBD::0
BestOf::7::Series::TBD::0::TBD::0
BestOf::7::Series::TBD::0::TBD::0
BestOf::7::Series::TBD::0::TBD::0bin/playoffs 2024.yaml upThis will output the current round number and series (nothing if the tournament is over):
1
BestOf::1::Series::PHI::0::MIA::0Once you know which series is currently up, use this command to pick a winner:
bin/playoffs 2024.yaml win PHIThis will output the current series after the win:
BestOf::1::Series::PHI::1::MIA::0::DoneThe CLI example executable comes with a randomized simulator. This is where this library stops and the application should start: the consumer is responsible to actually deciding winners while this library is only focused on providing the state machine. Run this command to simulate the rest of the games and series:
bin/playoffs 2024.yaml simThis will output the number of games simulated and the winner:
97
DALbin/playoffs 2024.yaml winnerWill output the winner (nothing if the tournament is not over):
DALWhile the CLI executable exemplifies building a consumer app using the data structures provided here, the real power is extending yourself to fit your needs, specifically:
-
Subclassing
Playoffs::Teamto customize per your domain-specific needs -
Constructing your own tournament using the main
Playoffs::Seriesdata structure. ViewPlayoffs::Basketball#tournament_forto see how an NBA tournament is constructed. -
Interact with the tournament state machine directly, such as:
Playoffs::Tournament#up_next: Get the current series which needs a winner.Playoffs::Series#win: Log a winner for the current series.Playoffs::Tournament#winner: Get the winning team once there is no current series (series is over).
Basic steps to take to get this repository compiling:
- Install Ruby (check playoffs.gemspec for versions supported)
- Install bundler (gem install bundler)
- Clone the repository (git clone git@github.com:mattruggio/playoffs.git)
- Navigate to the root folder (cd playoffs)
- Install dependencies (bundle)
To execute the test suite run:
bin/rspec spec --format documentationAlternatively, you can have Guard watch for changes:
bin/guardAlso, do not forget to run Rubocop:
bin/rubocopAnd auditing the dependencies:
bin/bundler-audit check --updateAnd Sorbet:
bin/srbNote: ensure you have proper authorization before trying to publish new versions.
After code changes have successfully gone through the Pull Request review process then the following steps should be followed for publishing new versions:
- Merge Pull Request into main
- Update
version.rbusing semantic versioning - Install dependencies:
bundle - Update
CHANGELOG.mdwith release notes - Commit & push main to remote and ensure CI builds main successfully
- Run
bin/rake release, which will create a git tag for the version, push git commits and tags, and push the.gemfile to rubygems.org.
Everyone interacting in this codebase, issue trackers, chat rooms and mailing lists is expected to follow the code of conduct.
This project is MIT Licensed.