Code Monkey home page Code Monkey logo

bracket_tree's Introduction

BracketTree Build Status

BracketTree is a bracketing system built around the BracketTree Data Specification, which uses a three-section data structure built on top of JSON to convey the visual representation, progression logic, and seed mapping in a serializable format. For more information on the data specification, please read the BracketTree Data Specification.

BracketTree builds upon the specification by providing Ruby classes for programmatically generating templates for brackets and generating brackets from those templates. It also contains a number of common bracket template types like Single Elimination and Double Elimination, with the ability to put your own extensions on their logic and representation.

BracketTree is broken into two fundamental components: Templates and Brackets.

BracketTree Templates

Templates in BracketTree are the instructions on how a Bracket is to be constructed, containing the three components of a BracketTree specification:

  • starting_seats
  • seats
  • nodes

BracketTree comes with a number of default templates included. To access one, call the by_size method on the template class. For example, to generate an eight-player, double-elimination bracket template:

template = BracketTree::Template::DoubleElimination.by_size(8)

The resulting BracketTree::Template::DoubleElimination object contains the necessary details to create a bracket using its information.

If you need to make customizations, you can manipulate the template per object, like in this example where we reverse the seed order of the template:

template = BracketTree::Template::DoubleElimination.by_size(8)
template.starting_seats # => [1,3,5,7,9,11,13,15]
template.starting_seats = [15,13,11,9,7,5,3,1]

However, you may wish to generate your own Template class. To do so, subclass the BracketTree::Template::Base class and define location to be the location of the JSON files that conform to the BracketTree Data Specification. In this example, we create a class for the MLG Double Elimination format, where the templates are located in the mlg_double directory:

class BracketTree::Template::MLGDouble < BracketTree::Template::Base
  def location ; File.join File.dirname(__FILE__), 'mlg_double' ; end
end

If you happen to have the JSON already stored as a hash and want to create a Template from that, you can use the from_json method to generate a new template:

hash = {
  'startingSeats' => [1,3,5,7],
  'seats' => [
    { 'position' => 4 },
    { 'position' => 2 },
    { 'position' => 6 },
    { 'position' => 1 },
    { 'position' => 3 },
    { 'position' => 5 },
    { 'position' => 7 }
  ],
  'nodes' => []
}

template = BracketTree::Template::Base.from_json hash

BracketTree Brackets

Brackets are derived from BracketTree::Bracket::Base or its sub-classes. BracketTree provides two subclasses, BracketTree::Bracket::SingleElimination and BracketTree::Bracket::DoubleElimination, to quickly generate blank brackets based on the popular standard formats:

single_elim_bracket = BracketTree::Bracket::SingleElimination.by_size 4
double_elim_bracket = BracketTree::Bracket::DoubleElimination.by_size 64

For those who wish to create a custom bracket Template class, doing so is straightforward. Create a subclass of BracketTree::Bracket::Base and use the template method to specify your template class, like the below MLGDouble bracket:

class MLGDoubleTemplate < BracketTree::Template::Base
  def self.location
    File.join File.dirname(__FILE__), 'templates', 'mlg_double'
  end
end

class MLGDouble < BracketTree::Bracket::Base
  template MLGDoubleTemplate
end

Once we've generated a bracket from a template, we're able to start populating and controlling the bracket information. All bracket objects derive from BracketTree::Bracket::Base. If you generate a bracket from this class, it will have a blank binary tree. If you happen to know the math involved in hand-crafting a binary tree reflective of your particular tournament type, then you could use add to start adding nodes in the bracket:

bracket = BracketTree::Bracket::Base.new
bracket.add 2, { player: 'player1' }
bracket.add 1, { player: 'player1' }
bracket.add 3, { player: 'player2' }

While this is not the most difficult thing to do on a small scale, doing this for larger tournaments is extremely cumbersome, so we generate Brackets from Templates instead. Please review 'BracketTree Templates' for more information on this.

When you generate a blank bracket from a template, it adds empty hashes as placeholders for all of the seats in the Bracket. To replace these placeholders, use the replace method with the seat position and the object you would like to replace it with.

In this example, we handle seeding a two-player, single elimination bracket:

bracket = BracketTree::Bracket::SingleElimination.by_size 2
bracket.replace 1, { player: 'player1' }
bracket.replace 3, { player: 'player3' }

Again, this is not the most difficult thing to do, but seeding is a pretty common thing. For actions like this, use the seed method.

Under the hood, each seat position in the Bracket is held as the payload of a Node object. This contains the binary tree traversal controls, as well as a payload property that contains the object being stored at the node. When using any iterator methods from Enumerable on a bracket, know that they are in the context of a Node rather than whatever you have chosen to store inside the Node. This allows the following:

bracket = BracketTree::Bracket::SingleElimination.by_size 2
bracket.replace 2, { player: 'player1 }

node = bracket.at(2)
node.payload # => { player: 'player1' }
node.payload[:seed_value] = 3

Example

Below is an example of creating a 32-player, double elimination tournament bracket template, generating a blank bracket, seeding from an array of players, and filling some results from round 1:

players = []
32.times do |n| 
  players << { login: "Player#{n}", seed_value: n }
end

bracket = BracketTree::Bracket::DoubleElimination.by_size 32
bracket.seed players

# Player1 wins Rd 1
bracket.match_winner(1)
bracket.at(1).payload[:winner] = true

# Player3 wins Rd 1
bracket.match_winner(5)
bracket.at(1).payload[:winner] = true

Contributions

Contributions are awesome. Feature branch pull requests are the preferred method.

Author

Written by Andrew Nordman

bracket_tree's People

Contributors

cadwallion avatar czarneckid avatar hypomodern avatar spaghetticode avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.