Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extend Functionality to Non-Powers of 2 #8

Closed
thesupremecommander opened this issue Aug 14, 2013 · 31 comments
Closed

Extend Functionality to Non-Powers of 2 #8

thesupremecommander opened this issue Aug 14, 2013 · 31 comments
Assignees

Comments

@thesupremecommander
Copy link

Currently, bracket generation is limited to powers of 2. However, the ability to produce brackets that were not perfect would be useful.

This could be accomplished by allowing the script to continue to operate on the premise of a power of 2. Non-powers of 2 would be accommodated by padding the seeded list with "null seeds" until the next-largest power of 2 was reached (e.g. a 9-player tournament would get 7 "null seeds" to get 16 seeds). The tournament would then be run on the premise that any match against a "null seed" would result in a victory for the real seed (i.e. a bye).

This setup would apply to most if not all tournaments, and would not require a very vast change as far as data handling and tournament structure goes. All that would be required is setting a value that signals a "null seed" (e.g. null), and not visibly rendering a match that has a team with that value.

Would it be possible to implement this?

@teijo
Copy link
Owner

teijo commented Aug 16, 2013

This is definitely something that has been on the top of my list of things to improve. So far everyone has had to invent their own "BYE" team to get over this limitation.

The implementation should also prevent users from creating BYE vs BYE matches as that would mean either: a) bracket is not balanced and some participant may get too many default wins (bracket size 8, 5 participants, 2 matches in first round -> participant left out in round 1 gets default twice and gets directly to finals); b) selected bracket size is too large for the number of participants.

@teijo teijo mentioned this issue Aug 16, 2013
@thesupremecommander
Copy link
Author

BYE vs. BYE in the upper bracket, however, is an indication of imbalance as you demonstrated. However, BYE vs. BYE matches should be expected in the lower bracket of a double elimination tournament - since the lower half of the tournament may be almost (but not completely) filled with BYE seeds, those matches should be possible in the lower bracket and should be compensated for.

On a side note, clux/tournament is a node module which can generate non-perfect brackets, so that might be useful for you if you're trying to test an implementation.

@thestamp
Copy link

I too am running into this. Having any number of teams would be very beneficial. The way I handle odd number of teams is to break a node to go more level deeper (to add the extra contender slot), and add the odd contender in. Every other contender essentially gets a bye. Then as more teams are added, the other nodes are broken up in sequence until the entire new row of nodes is fully filled.

So, if theres 17 teams, Teams 1 to 15 get a bye. 16 & 17 are a match, the winner proceeding to the same node level as everyone else.

If you would like an illustration, I can render you a gif of my existing software so you can see the pattern. Challonge can also illustrate this.

@arsenetoumani
Copy link

Hmm, I need this feature too.. Might have to write it myself

@LittleLama
Copy link

I really need it too.
Would be so great to have a cleaned bracket without BYE vs BYE matchs.

@Dibort
Copy link

Dibort commented Jul 9, 2014

It'll be awesome to have this. Any news?

@thecodeassassin
Copy link

I am currently looking into this. teijo , can you give me a tip?

@teijo
Copy link
Owner

teijo commented Apr 22, 2015

Unfortunately I haven't worked with the codebase in a long time so it's quite difficult to give any substantial pointers, sorry :/

@handy-man
Copy link

The lack of Bye's is an issue I have come across in this library, to sort this I went around it in the server-side code as my JavaScript game is weak.

I parse in my "teams" from the serverside as users sign themselves up to tournaments, then given lets say 9 users I find the next power of 2 and fill the rest of the array with users with the name "bye" and (for now) manually process all bye games as automatic wins.

This was the easiest solution to do in a few lines of code in the server side.

@LittleLama
Copy link

Good game !
I think it´s the best solution for now.

Le mardi 5 mai 2015, Nathan Hand notifications@github.com a écrit :

The lack of Bye's is an issue I have come across in this library, to sort
this I went around it in the server-side code as my JavaScript game is weak.

I parse in my "teams" from the serverside as users sign themselves up to
tournaments, then given lets say 9 users I find the next power of 2 and
fill the rest of the array with users with the name "bye" and (for now)
manually process all bye games as automatic wins.

This was the easiest solution to do in a few lines of code in the server
side.


Reply to this email directly or view it on GitHub
#8 (comment).

@thecodeassassin
Copy link

I have a good solution for handling BYE's written in PHP. I might make a library, anybody interested? @handy-man @LittleLama

@thecodeassassin
Copy link

i might extend the init function to autocreate BYE on init. Is that a good idea?

@handy-man
Copy link

So the same sort of results as I have here: http://imgur.com/FWYVRir I auto fill the BYE's using PHP essentially giving them -1 seed at the end of a sorted array and then parsing it into my perdictive power seeding function which produces this (9 players signed up, one real match and the rest are auto wins).

In terms of doing BYE's in the JS you need to take into account seeding, you either go for an implementation like I've got (creating another level of depth) or you need to allow for (when there are 12 players for example) moving forward seeds 1 - 4 in their respective matches to the semi finals and not have an ugly tree like I do.

@thecodeassassin
Copy link

@handy-man my code does somewhat the same thing but not with seeds. I'm curious about your code though. What would be the advantage of having seeding? For long running tournaments?

@handy-man
Copy link

The use of seeding is quite important, in fact I'm writing my dissertation which involves seeding players on SteamAPI data requests, genre's, playtime and locally recorded data.

Essentially seeding known as "predictive power" is there to ensure that the top two seeds do not face eachother in the first round and infact should (if they get that far) only face each other in the finals. This is done so that your first match isn't your expected final match and every subsequent match after that is pretty one sided and boring.

Suggested reading:
https://www.cerge-ei.cz/pdf/wp/Wp252.pdf

@thecodeassassin
Copy link

@handy-man is it possible for you to share your code? I would love to see how you implemented it.

@handy-man
Copy link

My code is part of a project written in Laravel, so there will be aspects that might not be fully understood without the context of the whole system and background knowledge of Laravel? But here it is if you have that knowledge/ want to have a look:

https://gist.github.com/handy-man/f3ce5a7d86427d5037c3

Understand that due to the design of my project I had to create a new dummy user called "bye" this is not ideal and given more time I would change this around.

Example seeded array:

[{"points":111224,"id":2},{"points":-1,"id":9},{"points":5564,"id":6},{"points":100,"id":11},{"points":55401,"id":8},{"points":-1,"id":9},{"points":40618,"id":4},{"points":-1,"id":9},{"points":93658,"id":3},{"points":-1,"id":9},{"points":11924,"id":5},{"points":-1,"id":9},{"points":67372,"id":1},{"points":-1,"id":9},{"points":28547,"id":7},{"points":-1,"id":9}]

^^This took an input of 9 users, so only 1 real match occurs in the first round seen as ID #6 and #11

As seen from the GIST this data is then taken in 2 at a time placing 2 users into a single match, that match data is later taken out of the database to change the user->id into the user object and insert the displayname into an array which is chunked by 2 which is what the JS Library expects.

@tfosm
Copy link

tfosm commented Jan 4, 2016

Hi Teijo,
Jquery-bracket is great and I would love to use it in my torunament webapp but i really need support for BYE. Could you take a look at the work rollingWolf did in #33 and use it in your official release? I tried to use his work but it seems like he didn't build the "dist" files and then I can't use it (I don't know how to). Please make me happy and add BYE support :-). Thank you for a really nice plugin anyway. /Micael

@teijo
Copy link
Owner

teijo commented Jan 4, 2016

Seems I've unfortunately failed to follow-up with #33 even though I've read and referenced it.

I feel the approach is a bit too inflexible as such as it reserves 'BYE' as a special team name and forces results to 1-0. I feel something more flexible would work better in the long run as you wouldn't have to break backwards compatibility after rolling back some earlier decision.

@tfosm if you feel that approach would still fit your needs, I recommend learning how to build your own version from the modified code. Check out "Building" from README. As it's not a CSS change, you can skip the ruby/compass part by removing 'shell' from Gruntfile.js default task.

P.S. I might address this functionality in near future as I'm working on a hobby project that uses the jQuery Bracket library.

@tfosm
Copy link

tfosm commented Jan 5, 2016

Hi again Teijo,
Thank you for your answer. I manged to compile rollingWolf's files to get jquery.bracket.js. 'uglify' and 'cssmin' failed due to an error [TypeError: Cannot assign to read only property 'warnings' of true] but now at least I have a .js file that works. I will use this file for now and hope that I don't need the bug fixes you have done in the main track.

I understand your concerns that reserving 'BYE' as a special team name is not optimal. Maybe you could use 'null' or any special signs instead to avoid this. Adding "team options" to the data structure could be another solution. I will keep an eye at future updates to see if you find time to add proper support for BYE. Thank's /Micael

@steakbbq
Copy link

Yea, Great library but unusable due to not having functionality for BYE, one of the most basic and essential tools of running a tournament.

@kpagcha
Copy link

kpagcha commented Sep 30, 2016

Ok I get that since this doesn't support non-power-of-two brackets we need to use bye teams. But just making up a score for actual teams vs bye teams so the team advances to the next round seems so wrong. Is there any other workaround?

@teijo
Copy link
Owner

teijo commented Sep 30, 2016

@kpagcha

Is there any other workaround?

Unfortunately no workaround without modifying the library. Depending on your needs, you might want to check out PR #60 which kinda resolves this issue.

@teijo
Copy link
Owner

teijo commented Oct 3, 2016

Started work on branch non-2-power-support to implement this functionality.

Should BYE be assigned if you just clear the team name field (or leave it empty)? That's my first approach.

What would be best way to indicate BYE in the data structure? null as team name?

One end-user challenge is the balancing of the tournament if there are multiple byes, i.e. no team should get two default wins until every other team has got a default win (at which point the tournament size can be reduced). Not sure if the library needs to give some help regarding this?

@teijo teijo self-assigned this Oct 3, 2016
@kpagcha
Copy link

kpagcha commented Oct 3, 2016

I think it'd be cool if you could pass an option to choose either if you want to display those dummy teams (which btw empty name or null seem both fine to me) as byes or not display them at all.

@teijo
Copy link
Owner

teijo commented Oct 4, 2016

One challenge from hiding comes if you want to replace a BYE with a team. E.g. you BYE a match in first round but then a team joins last minute. If you don't render the BYE, there's nowhere to click to add a team.

Could maybe leave the hiding as CSS override so user can implement for example a hover to reveal the BYE boxes?

Should it be possible to enter a score for a team that gets a default win, or should it be a configuration that a team getting a default win gets X points?

@kpagcha
Copy link

kpagcha commented Oct 4, 2016

One challenge from hiding comes if you want to replace a BYE with a team. E.g. you BYE a match in first round but then a team joins last minute. If you don't render the BYE, there's nowhere to click to add a team.

Yeah I get that but I don't know... if I new team just came the backend should take care of that and feed it into the data structure that the bracket plugin uses. But sticking to your way and allowing a user to click on a "BYE" team and replace it with an actual team, it is not incompatible with what I said. If the user is organizing an event where it is likely that newcomers are going to take place of "BYE" teams, then you just pass the "show BYEs" option I suggested and that's it.

Should it be possible to enter a score for a team that gets a default win, or should it be a configuration that a team getting a default win gets X points?

It doesn't make sense to me that a real team vs a "BYE" has a score, that should be disabled. What do you mean it gets X points? You mean a score?

@teijo
Copy link
Owner

teijo commented Oct 5, 2016

What do you mean it gets X points? You mean a score?

Yea, score. I'd imagine that in some tournament formats you get a score from win, regardless of how it's obtained. However, might be better to just implement it first in more strict way and see if someone actually needs a more complicated system.

@LittleLama
Copy link

I agree

Le 5 oct. 2016 9:44 PM, "Teijo Laine" notifications@github.com a écrit :

What do you mean it gets X points? You mean a score?

Yea, score. I'd imagine that in some tournament formats you get a score
from win, regardless of how it's obtained. However, might be better to just
implement it first in more strict way and see if someone actually needs a
more complicated system.


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
#8 (comment),
or mute the thread
https://github.com/notifications/unsubscribe-auth/AEwHD5Duad_qTGPU-PbwAdaFsY_qoqy_ks5qw_4TgaJpZM4A5qLQ
.

@teijo
Copy link
Owner

teijo commented Oct 9, 2016

I have merged the feature branch to master. I'll have to polish and test it a bit more before publishing a new version of the library but you can already try it out (npm install && grunt, see dist/). In general, everything should work.

How it now behaves:

  • Giving null instead of a team to init will indicate BYE
  • Matchups that don't yet have teams advanced to them show as BYE
  • Erasing a team name from any matchup will turn the team effectively into BYE / null and leads to recalculation of scores and team advancements
  • Adding a new team will recalculate advancements and reset them for affected teams, i.e. team that has got a default win will lose that win and get backed to where it meets the new team (that replaced the BYE)

NOTE: It's left to the user to create a balanced tournament with BYEs. E.g. if you have 5 team bracket and you assign all teams to first 5 spots, team 5 will get to finals without playing a match!

Next thing would be to switch upcoming matchups from BYE to TBD and also give customisation option for the text.

How it looks:

Single elimination

image

Double elimination

image

If you try it out, let me know if you spot any bugs or illogical behaviour, thanks!

@teijo
Copy link
Owner

teijo commented Oct 16, 2016

It's here! BYEs, and therefore non-2-powers, is now implemented and published. Get version 0.8.0 from npm and bower. Try out the new functionality with the save demo: http://www.aropupu.fi/bracket/#save

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

No branches or pull requests