Multi-Stage Tournaments #1

Closed
clux opened this Issue Nov 18, 2012 · 8 comments

Comments

Projects
None yet
1 participant
@clux
Owner

clux commented Nov 18, 2012

I need a good way to plumb different tournament types together.
I want to be able to create a, say, 32 player FFA elimination and forward the top 8 to a single elimination tournament (and auto create tiebreaker mini-groups when needed). Also, I may not necessarily want to finish the FFA elimination (but just stop when a top 8 has been determined if this is a good number to stop on).

trn.results() provides excellent statistics that should be sufficient figure out these things, but I can imagine it would get quite hairy if it's not been modeled properly.

The plumbing should work in a generic way between all the different tournament types that's serializable and deserializable into a wrapper type (or whatever works nicely).

@clux

This comment has been minimized.

Show comment Hide comment
@clux

clux Nov 20, 2012

Owner

I've come to the conclusion that it should be handled outside to an extent, but we can prepare for how many to extract inside each tournament.

Each tournament type should implement a limit parameter that it should be able to distinguish. I.e. if you set limit to 6 in a groupstage, then the group stage must generate tiebreakers if necessary to determine the top 6 and account for this in the ::isDone() members.

This way, at the start, modification of tournaments can be put in place from the beginning.
When the first stage is done, it's simply a matter of picking the top limit from ::results().
I may make another wrapper module to encapsulate this logic, but this is fundamentally simple stuff.

A few gotchas though;

  • the limit parameter cannot be inferred from matches when deserializing from DBs, so it's an extra thing to store
  • determining the top limit can sometimes be very tricky as in the case of group stages
  • only thing that separates prepared limits from unprepared ones (trying to get top X when there may be ties without having planned it) is that unprepared ones can be chosen unfairly
Owner

clux commented Nov 20, 2012

I've come to the conclusion that it should be handled outside to an extent, but we can prepare for how many to extract inside each tournament.

Each tournament type should implement a limit parameter that it should be able to distinguish. I.e. if you set limit to 6 in a groupstage, then the group stage must generate tiebreakers if necessary to determine the top 6 and account for this in the ::isDone() members.

This way, at the start, modification of tournaments can be put in place from the beginning.
When the first stage is done, it's simply a matter of picking the top limit from ::results().
I may make another wrapper module to encapsulate this logic, but this is fundamentally simple stuff.

A few gotchas though;

  • the limit parameter cannot be inferred from matches when deserializing from DBs, so it's an extra thing to store
  • determining the top limit can sometimes be very tricky as in the case of group stages
  • only thing that separates prepared limits from unprepared ones (trying to get top X when there may be ties without having planned it) is that unprepared ones can be chosen unfairly
@clux

This comment has been minimized.

Show comment Hide comment
@clux

clux Dec 8, 2012

Owner

FFA tournaments can set a limit now. High level usage:

var ffa = new t.FFA(16, [4,4], [2], {limit: 4}); // final round is actually 2 semis, and instead of a final determine top 4

// ..
// score all matches

// when everything is done:
ffa.isDone(); // true

// can now pick top 4 
var winners = ffa.results().slice(0, ffa.limit);

// get their seed numbers so they can be mapped by your application to the actual participant list
var topSeedNums = winners.map(function(w) { return w.seed });

Note that deserialization needs to pass in the opitons object ({limit:4}) to fromJSON as a 2nd parameter as this is irrecoverable by the deserializer.

Owner

clux commented Dec 8, 2012

FFA tournaments can set a limit now. High level usage:

var ffa = new t.FFA(16, [4,4], [2], {limit: 4}); // final round is actually 2 semis, and instead of a final determine top 4

// ..
// score all matches

// when everything is done:
ffa.isDone(); // true

// can now pick top 4 
var winners = ffa.results().slice(0, ffa.limit);

// get their seed numbers so they can be mapped by your application to the actual participant list
var topSeedNums = winners.map(function(w) { return w.seed });

Note that deserialization needs to pass in the opitons object ({limit:4}) to fromJSON as a 2nd parameter as this is irrecoverable by the deserializer.

@clux

This comment has been minimized.

Show comment Hide comment
@clux

clux Jan 17, 2013

Owner

Few pointers on this - there's not actually that desperately needs to be done:

  • KnockOut will never have this functionality as it can be emulated by just having fewer rounds / less knockouts in final round.
  • Duel may possibly have it, but it's far out. It's usually the ending tournament in multi stage anyway
  • GroupStage will get the big features it needs in the TieBreaker class (coming along nicely)
  • FFA limits work fine and will be a good starting point
Owner

clux commented Jan 17, 2013

Few pointers on this - there's not actually that desperately needs to be done:

  • KnockOut will never have this functionality as it can be emulated by just having fewer rounds / less knockouts in final round.
  • Duel may possibly have it, but it's far out. It's usually the ending tournament in multi stage anyway
  • GroupStage will get the big features it needs in the TieBreaker class (coming along nicely)
  • FFA limits work fine and will be a good starting point
@clux

This comment has been minimized.

Show comment Hide comment
@clux

clux Feb 4, 2013

Owner

GroupStage now works fine with the new TieBreaker class.

Thus, no tournament type now desperately need it as the remaining KnockOut and Duel is nicely tuned to the end-stage tournament anyway. That said, implementing it for these may not be that hard (at least KnockOut will be easy).

Owner

clux commented Feb 4, 2013

GroupStage now works fine with the new TieBreaker class.

Thus, no tournament type now desperately need it as the remaining KnockOut and Duel is nicely tuned to the end-stage tournament anyway. That said, implementing it for these may not be that hard (at least KnockOut will be easy).

@clux

This comment has been minimized.

Show comment Hide comment
@clux

clux Feb 4, 2013

Owner

Tagging with the unimplemented ones.

Owner

clux commented Feb 4, 2013

Tagging with the unimplemented ones.

@clux

This comment has been minimized.

Show comment Hide comment
@clux

clux Oct 25, 2013

Owner

While limits is a great idea, I think staging needs a better idea than just doing that.
TieBreaker does what you want for groupstage, but ideally there should be one class containing both.

Similarly, you should EASILY be able to make a class that contains to other tournaments and be able to turn those into a multi stage one. I have been experimenting in the groupstage repo locally by making a class containing both TieBreaker and GroupStage. This works by effectively freezing the GroupStage matches when the TieBreaker matches have been created.

There is ATM many things wrong with this approach:

  • matches must be merged (loose guarantees on match ids being unique - although works in the GS-TB scenario)
  • if the last match is mis-scored, you can't undo that (because it will force TB recreation)

So ideally, you need:

  • score to be able to defer to the tournament you want
  • there to be one external mechanism for locking down scoring of one stage before the second begins.
Owner

clux commented Oct 25, 2013

While limits is a great idea, I think staging needs a better idea than just doing that.
TieBreaker does what you want for groupstage, but ideally there should be one class containing both.

Similarly, you should EASILY be able to make a class that contains to other tournaments and be able to turn those into a multi stage one. I have been experimenting in the groupstage repo locally by making a class containing both TieBreaker and GroupStage. This works by effectively freezing the GroupStage matches when the TieBreaker matches have been created.

There is ATM many things wrong with this approach:

  • matches must be merged (loose guarantees on match ids being unique - although works in the GS-TB scenario)
  • if the last match is mis-scored, you can't undo that (because it will force TB recreation)

So ideally, you need:

  • score to be able to defer to the tournament you want
  • there to be one external mechanism for locking down scoring of one stage before the second begins.
@clux

This comment has been minimized.

Show comment Hide comment
@clux

clux Nov 1, 2013

Owner

An overridable Klass.from will be a receiver function in the future (you can send a finished tournament instance to it). Phasing out limits over better and more general tiebreaker support is the preferable approach, and it is my aim to implement this properly soon.

Owner

clux commented Nov 1, 2013

An overridable Klass.from will be a receiver function in the future (you can send a finished tournament instance to it). Phasing out limits over better and more general tiebreaker support is the preferable approach, and it is my aim to implement this properly soon.

@clux

This comment has been minimized.

Show comment Hide comment
@clux

clux Nov 4, 2013

Owner

This exists in 0.19.0 now. Works with most tournament types and is tested in trn.multi.test.js in this repo.
GroupStage still needs TieBreaker, and this is broken at the moment, but the plan is to extend TieBreaker so we can use TieBreaker.from(groupStageInstance, limit);

Owner

clux commented Nov 4, 2013

This exists in 0.19.0 now. Works with most tournament types and is tested in trn.multi.test.js in this repo.
GroupStage still needs TieBreaker, and this is broken at the moment, but the plan is to extend TieBreaker so we can use TieBreaker.from(groupStageInstance, limit);

@clux clux closed this Nov 4, 2013

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment