I am in the process of converting my Tournament Organizer software, which allows the creation and manipulation of Double Elimination Tournaments, to use the MVVM design pattern so that it can be more easily tested. In doing so, I'm separating out the 'model' from some code in the UI that directly manipulates the bracket structure.
This will be the third iteration of software I've written to handle tournaments. The first was written in PHP and stored the data in a database. The second version is the WPF version I made, and it stores the data in memory, and then serializes it to an XML file. However, in both versions, there are aspects of the implementation that I feel aren't clean, and seem like they break the law of DRY.
If you were creating a data structure from scratch to handle double elimination brackets, how would you do it?
Note that it doesn't need to be able to automatically generate the brackets algorithmically (loading from a pre-made double-elimination with 4/8/16/32 people is how I'm doing it now), just the main use case of setting winners of matches and 'advancing' them through the bracket.
Edit: To make it clear, the data structure needs to handle double elimination tournaments, so potentially, the winner of one match could end up competing against the loser of another.
So, at the end points, you have 64 teams. So there's a collection, somehow, of 64 Teams.
But they're paired off, and for each pair, there's a winner. And in the middle brackets, that winner actually emerged from a bracket, so I think your bracket object actually looks like:
public class Bracket
{
Team winner; //if this is null or whatever, then we don't have a winner yet
Bracket topBracket;
Bracket bottomBracket;
}
...and when you're instantiating your ends, you'd just leave the two sub-Brackets null, with only a winner.
To handle double-elimination, there's a second bracket, which is a losers bracket. It would be nice if you could automatically handle the addition of losers into this bracket (design a bracket that starts with 32, who play down to 16, add in the 16 losers from winner bracket round 2, etc.) but that's all implementation. The data structure doesn't need to change to accommodate that, you just need more of them.
My solution to this was to have two sets of data structures. One for the bracket part, and one for the seats.
class Match
{
string Id;
MatchSeat red;
MatchSeat blue;
MatchSeat winner;
MatchSeat loser;
}
class MatchSeat
{
string Id;
Entry Entry;
}
And then to set it up, I made some helper functions that took the bracket information and built the structures.
{ "1", "seed1", "seed4", "W1", "L1" },
{ "2", "seed2", "seed3", "W2", "L2" },
{ "3", "W1", "W2", "W3", "L3" },
{ "4", "L1", "L2", "W4", "L4" },
{ "5", "W4", "L3", "W5", "L5" },
{ "F", "W3", "W5", "WF", "WF" }
Then when the seeds and winners/losers are filled out, the value only gets set in one place.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With