Class: BracketTree::Bracket::Base

Inherits:
Object
  • Object
show all
Includes:
Enumerable
Defined in:
lib/bracket_tree/bracket/base.rb

Overview

Basic bracketing functionality. If you wish to create a custom bracket type, inherit from this class to provide easy access to bracketing.

Example:

class MLGDouble < BracketTree::Bracket::Base
template BracketTree::Template::DoubleElimination
end

bracket = MLGDouble.by_size 8

This creates a bracket based on the standard double elimination template class. The template parameter can be any class that inherits from BracketTree::Template::Base, though.

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

Direct Known Subclasses

DoubleElimination, SingleElimination

Defined Under Namespace

Classes: NoTemplateError

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ Base

Returns a new instance of Base.



60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/bracket_tree/bracket/base.rb', line 60

def initialize options = {}
  @insertion_order = []
  @matches = []
  @depth = {
    total: 0,
    left: 0,
    right: 0
  }

  if options[:matches]
    options[:matches].each do |m|
      @matches << Match.new(m)
    end
  end

  @seed_order = options[:seed_order] if options[:seed_order]
end

Instance Attribute Details

#depthObject

Returns the value of attribute depth.



58
59
60
# File 'lib/bracket_tree/bracket/base.rb', line 58

def depth
  @depth
end

#insertion_orderObject

Returns the value of attribute insertion_order.



58
59
60
# File 'lib/bracket_tree/bracket/base.rb', line 58

def insertion_order
  @insertion_order
end

#matchesObject

Returns the value of attribute matches.



58
59
60
# File 'lib/bracket_tree/bracket/base.rb', line 58

def matches
  @matches
end

#rootObject

Returns the value of attribute root.



58
59
60
# File 'lib/bracket_tree/bracket/base.rb', line 58

def root
  @root
end

#seed_orderObject

Returns the value of attribute seed_order.



58
59
60
# File 'lib/bracket_tree/bracket/base.rb', line 58

def seed_order
  @seed_order
end

Class Method Details

.by_size(size, options = {}) ⇒ Object



30
31
32
# File 'lib/bracket_tree/bracket/base.rb', line 30

def by_size size, options = {}
  generate_from_template @template, size
end

.generate_from_template(template, size) ⇒ Object

Generates a blank bracket object from the passed Template class for the passed size

Parameters:

  • BracketTree::Template::Base

    template - the Template the bracket is based on

  • Fixnum

    size - bracket size

Returns:

  • BracketTree::Bracket::Base bracket - a blank bracket with hash placeholders



45
46
47
48
49
50
51
52
53
54
# File 'lib/bracket_tree/bracket/base.rb', line 45

def generate_from_template template, size
  template = template.by_size size
  bracket = new(matches: template.matches, seed_order: template.seed_order)

  template.seats.each do |position|
    bracket.add position, {}
  end

  bracket
end

.template(class_name) ⇒ Object



34
35
36
# File 'lib/bracket_tree/bracket/base.rb', line 34

def template class_name
  @template = class_name
end

Instance Method Details

#add(position, data) ⇒ Object

Adds a Node at the given position, setting the data as the payload. Maps to binary tree under the hood. The data can be any serializable object.

Parameters:

  • Fixnum

    position - Seat position to add

  • Object

    data - the player object to store in the Seat position



83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# File 'lib/bracket_tree/bracket/base.rb', line 83

def add position, data
  node = Node.new position, data
  @insertion_order << position

  if @root.nil?
    @root = node
    @depth[:total] = 1
    @depth[:left] = 1
    @depth[:right] = 1
  else
    current = @root
    current_depth = 2
    loop do
      if node.position < current.position
        if current.left.nil?
          node.depth = current_depth
          current.left = node

          depth_check current_depth, node.position
          break
        else
          current = current.left
          current_depth += 1
        end
      elsif node.position > current.position
        if current.right.nil?
          node.depth = current_depth
          current.right = node

          depth_check current_depth, node.position
          break
        else
          current = current.right
          current_depth += 1
        end
      else
        break
      end
    end
  end
end

#at(position) ⇒ Object



188
189
190
# File 'lib/bracket_tree/bracket/base.rb', line 188

def at position
  find { |n| n.position == position }
end

#depth_check(depth, position) ⇒ Object



125
126
127
128
129
# File 'lib/bracket_tree/bracket/base.rb', line 125

def depth_check depth, position
  @depth[:total] = [depth, @depth[:total]].max
  @depth[:left]  = [depth, @depth[:left] ].max if position < @root.position
  @depth[:right] = [depth, @depth[:right]].max if position > @root.position
end

#each(&block) ⇒ Object



169
170
171
# File 'lib/bracket_tree/bracket/base.rb', line 169

def each(&block)
  in_order(@root, block)
end

#in_order(node, block) ⇒ Object



236
237
238
239
240
241
242
243
244
# File 'lib/bracket_tree/bracket/base.rb', line 236

def in_order(node, block)
  if node
    in_order(node.left, block) unless node.left.nil?

    block.call(node)

    in_order(node.right, block) unless node.right.nil?
  end
end

#match_loser(seat) ⇒ Object

Inverse of match_winner, progresses the bracket based on seat. See match_winner for more details

Parameters:

  • Fixnum

    seat - losing seat position

Returns:

  • Boolean result - result of progression



225
226
227
228
229
230
231
232
233
234
# File 'lib/bracket_tree/bracket/base.rb', line 225

def match_loser seat
  match = @matches.find { |m| m.include? seat }
  
  if match
    winning_seat = match.seats.find { |s| s != seat }
    match_winner winning_seat
  else
    return false
  end
end

#match_winner(seat) ⇒ Object

Progresses the bracket by using the stored matches to copy data to the winning and losing seats. This facilitates match progression without manually manipulating bracket positions

Parameters:

  • Fixnum

    seat - winning seat position

Returns:

  • Boolean result - result of progression



200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
# File 'lib/bracket_tree/bracket/base.rb', line 200

def match_winner seat
  match = @matches.find { |m| m.include? seat }

  if match
    losing_seat = match.seats.find { |s| s != seat }

    if match.winner_to
      replace match.winner_to, at(seat).payload
    end

    if match.loser_to
      replace match.loser_to, at(losing_seat).payload
    end

    return true
  else
    return false
  end
end

#replace(position, payload) ⇒ Object

Replaces the data at a given node position with new payload. This is useful for updating bracket data, replacing placeholders with actual data, seeding, etc..

Parameters:

  • position (Fixnum)
    • the node position to replace
  • payload
    • the new payload object to replace


137
138
139
140
141
142
143
144
145
# File 'lib/bracket_tree/bracket/base.rb', line 137

def replace position, payload
  node = at position
  if node
    node.payload = payload
    true
  else
    nil
  end
end

#seatsObject Also known as: to_a

Array of Seats mapping to the individual positions of the bracket tree. The order of the nodes is important, as insertion in this order maintains the binary tree

Returns:

  • Array seats



182
183
184
# File 'lib/bracket_tree/bracket/base.rb', line 182

def seats
  entries.sort_by { |node| @insertion_order.index(node.position) }
end

#seed(players) ⇒ Object

Seeds bracket based on seed_order value of bracket. Provide an iterator with players that will be inserted in the appropriate location. Will raise a SeedLimitExceededError if too many players are sent, and a NoSeedOrderError if the seed_order attribute is nil

Parameters:

  • players (Enumerable)
    • players to be seeded


153
154
155
156
157
158
159
160
161
162
163
# File 'lib/bracket_tree/bracket/base.rb', line 153

def seed players
  if @seed_order.nil?
    raise NoSeedOrderError, 'Bracket does not have a seed order.'
  elsif players.size > @seed_order.size
    raise SeedLimitExceededError, 'cannot seed more players than seed order list.'
  else
    @seed_order.each do |position|
      replace position, players.shift
    end
  end
end

#to_hObject



173
174
175
# File 'lib/bracket_tree/bracket/base.rb', line 173

def to_h
  @root.to_h
end

#top_down(node, &block) ⇒ Object



246
247
248
249
250
251
252
253
# File 'lib/bracket_tree/bracket/base.rb', line 246

def top_down(node, &block)
  if node
    block.call(node)

    top_down(node.left, &block) unless node.left.nil?
    top_down(node.right, &block) unless node.right.nil?
  end
end

#winnerObject



165
166
167
# File 'lib/bracket_tree/bracket/base.rb', line 165

def winner
  @root.payload
end