-
Notifications
You must be signed in to change notification settings - Fork 18
BracketTree Data Specification
The BracketTree Data Specification is a serializable bracketing data structure built on top of JSON that maintains a standard interface for designing and transporting brackets regardless of tournament structure. The specification has three core components: seats, matches, and starting seats. Each component provides a means of conveying the entirety of the tournament's current state, progression path, and seeding placement in a format that's easily transportable. This allows easy caching of the tournament as well as the means of passing different tournament types, game types, etc, to various renderers and languages that accept the standard.
At its core, BracketTree uses a binary tree to store the top/bottom seeds as left/right pointers in the tree. This allows the visual representation to match the binary tree, and provides the platform for progression; by using a binary tree, the system has created positional mappings to every point at which any given player can progress. This additionally allows the system to use the positional mappings to plot the win/loss progression state machine as a detached mechanism from the logic that determines win/loss, while simultaneously driving the visual representation in a 1:1 relationship. Finally, it provides a means of creating seeding strategies decoupled from the win/loss progression state machine with a minor translation of seed value to seat position on the binary tree.
Every valid BracketTree contains three components. These three components encompass the progression logic:
- seats
- matches
- starting_seats
Seats are the heart of the BracketTree representation. Every Seat in the BracketTree is a position in the bracket that a player may progress to/from, but also is used as a means of mapping the visual representation of the bracket data structure.
Every Seat MUST have a position attribute. This position attribute is the unique identifier of the Seat in the tree, determines its placement in the binary tree that drives BracketTree, and must be inserted in the proper order based on the intended tree structure.
Every Seat MAY have additional custom attributes to be used for identification of the player occupying the Seat. Additional custom attributes must not use the 'left', 'right', or 'position' attribute names at the root level of the Seat, however. It is recommended, but not required, that these attributes be contained within a 'payload' or equivalent namespace within the Seat.
Every Seat MUST have a unique value for a given position attribute within a given BracketTree. Duplicate position attribute values within a BracketTree will catastrophically destroy the BracketTree. To calculate the proper position attribute value for a given Seat, use a binary tree calculation algorithm to determine the placement for the intended visual representation that a given seat occupies.
The order in which every Seat is inserted into the 'seats' attribute of the Bracket is critical. Just as with calculating the proper position attribute value for a given Seat, so too must the insertion order of the Seat in the seats
attribute array.
Here is an example of a representation of a two-player bracket. Each seat sits within the 'seats' attribute of the root JSON:
{
'seats':[
{
'position': 2,
'payload': {
'username': 'Player#1',
'first_name': 'Test',
'last_name': 'Person'
}
},
{
'position': 1,
'payload': {
'username': 'TheDude',
'first_name': 'The',
'last_name': 'Dude'
}
},
{
'position': 3,
'payload': {
'username': 'Player#1',
'first_name': 'Test',
'last_name': 'Person',
'winner': 1
}
}
]
This results in a BracketTree with two Seats connected to a third Seat; Player#1 occupies Seat #2 and #3, indicating their progression. By using these values, we can determine that TheDude was the top seed and Player#1 was the bottom seed, and that Player#1 progressed to the next Seat. The information dictating progression of the state machine is covered in the next Section, Matches.
Matches in the BracketTree are the component dictating how progression from Seat to Seat travels. Note that this is progression in terms of Seat position, not the actual resolution of a given machine; BracketTree does not deal with win/loss resolution, just progression. It accomplishes this by using win and loss pointers that map to Seat position attribute values, and an array of applicable Seat position attribute values that dictate which positions are governed by the particular Match.
Every Match MUST contain a 'seats' attribute containing an pair of Seat positions. This pair does not need to be sorted in a particular fashion, but there MUST be two Seat positions. These determine what Seats are governed by this Match. No Match may use a Seat position that another Match in the Bracket is already using.
Every Match MUST have a 'winner_to' attribute, indicating the Seat the winner of the Match will progress to. This attribute MAY be set to a NULL value, but the attribute must be present.
Every Match MUST have a 'loser_to' attribute indicating the Seat the loser of the Match will progress to. This attribute MAY be set to a NULL value, but the attribute must be present.
Continuing from the Example in the previous section, Seats, here is the matches
section of the BracketTree:
{
'matches': [
{
'seats': [1,3],
'winner_to': 2,
'loser_to': null
}
]
}
We see that there is only one Match, and that it governs Seats 1 and 3. The winner progresses to Seat 2, while the loser does not progress.
Starting Seats are an ordered list of Seat positions within a BracketTree that are to be seeded for the bracket. This determines the origin of players within a bracket, from which the Matches will determine their progression in the Seats. The ordered list ranks from highest to lowest seed value, and should be used for seeding.
A starting_seats
attribute MUST be present as an ordered list of Seat positions in the Bracket, from highest to lowest seed value (not to be confused with Seat position value).
Each Seat position in the list MUST be unique.
Each Seat position in the list MUST match to a Seat in the seats
attribute of the BracketTree.
To conclude our previous examples, here is the Starting Seats of the two-player single-elimination bracket:
{
'starting_seats': [1,3]
}
This shows the highest seed will occupy Seat 1 and the lowest seed will occupy Seat 3.