GithubHelp home page GithubHelp logo

drarig29 / brackets-manager.js Goto Github PK

View Code? Open in Web Editor NEW
216.0 8.0 36.0 697 KB

A simple library to manage tournament brackets (round-robin, single elimination, double elimination).

Home Page: https://drarig29.github.io/brackets-docs

License: MIT License

TypeScript 52.33% JavaScript 47.67%
typescript mocha-tests tournament seeding matches round-robin group elimination bracket tournament-bracket

brackets-manager.js's Introduction

Corentin Girard (Drarig29)

overview languages

brackets-manager.js's People

Contributors

drarig29 avatar zestsystem avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

brackets-manager.js's Issues

double elimination byes propagation

Love the module, saved me a lot of time and mental health.

So what's the case:
If you create a double elimination from not a power of 2 participants, the loser bracket will not propagate byes

Reproduce steps:

  1. Create a stage with double elimination using seeding
  2. Seeding is an array of size 8, so it is a power of 2, but one of items is null. So we have one BYE
  3. Set match result in winner bracket 1.2
  4. Winner propagates in the winner bracket
  5. Loser goes into loser bracket as expected
  6. But! His opponent is BYE, but it doesn't propagate loser of first match further into loser bracket.
    image
    image
    2 screenshots of same bracket(they are both not really good - one is in russian, second has undefined as names :D)

Expected behaviour: Loser of first winner bracket match goes to LB round 2, skipping BYE in first round
Real behaviour: he is stuck with bye, and I can't manage to affect match(it has 'Waiting' status)

How to use this library?

can you please put an example in readme, how to use this library to generate tournament and matches etc?

Make participants optional when creating a stage

This should still be possible to make tests easier.

However, because participants are bound to a tournament and not a stage, the library should handle using already existing participants.

Add a method in BracketsManager to set participants in seedings.

Use size or participants in InputStage, but not both.

Support changing seeding even when one match is started

It would be useful to be able to edit the seeding for matches not started yet. Currently, if one match is started, an error is thrown and the update process is cancelled (which, by the way, is a bad behavior).

Example : for last minute changes like a cancelled bye...

Handle updating ordering for specific rounds

Can't update ordering at another level than round. If you need to do it for multiple rounds, you'll have to call update each time.

Can't update a round-robin's orderings, you need to re-create with another ordering.

Ability to set all the ordering at once

Currently, we need to use Update.roundOrdering() but it would be useful to be able to set them all at once with the same type of list which is given in a InputStage's settings.

Match update doesn't works

As title says match update doesn't works as expected .
match param is partial. It does have only user inputted properties , so it always throws "The match is locked".

Fix matchesToSeeding() with BYEs

Currently, matchesToSeeding() will sort all BYEs at the start the seeding. We want them to stay where they are but we don't have their position even though we are sorting by position...

We then need a sort function which has the following input and output:

Input: [null, {"id":2,"position":16}, null, null, null, null, {"id":2,"position":5}, null, null, null, null, null, {"id":4,"position":3}, null, {"id":4,"position":6}, null]

Output: [null, null, {"id":4,"position":3}, null, {"id":2,"position":5}, {"id":4,"position":6}, null, null, null, null, null, null, null, null, null, {"id":2,"position":16}]

A test should be added in general.spec.js.

Add linting

Use es-lint with typescript plugin. Main reasons are to maintain a good jsdoc with parameters which correctly correspond to the signature of the functions and to check the code style in general.

Do not order the last minor round of a loser bracket

Currently, the last minor round of a loser bracket is ordered - just as every minor round - even though it has only one match with one participant ordered, so it's useless to order it.

Here are the needed changes:

  • The last ordering of a double elimination stage which is persisted in the database should be of the penultimate minor round
  • Skip the last ordering during creation
  • Skip the last ordering during update
  • Make the last minor round unsupported to ordering
  • Add tests (check that the number of stored ordering is right, check that an unsupported round cannot be ordered)

For a double-elimination stage with 16 participants, there are 4 orderings:

  • For the first round of winner bracket (2 ordered participants per match)
  • For the first round of loser bracket (2 ordered participants per match, major round)
  • For the second round of loser bracket (1 ordered participant per match, minor round)
  • For the 4th round of loser bracket (same) (the penultimate minor round)
  • Not for the 6th (and last) minor round of loser bracket

Reduce number of requests during update

  • Optimize the requests by getting previous and next rounds only once.
  • Get all the needed info once and give it to the Update class, removing the storage field.

Is it possible to use for a not even number of teams?

Hello,
thank you for putting together this library. I used it to understand the rules of double elimination.
I also quickly tried to use it to see if it can solve the case for a number of teams that is not N^2.
I am new to terminology and saw in the readme that BYE is used only for seeding, but not sure if that means I can't calculate games and their order using this library.

Add the option to balance BYEs in the seeding

Add a function to prevent having BYE against BYE in matches. Maybe make it an argument in the stage creation process.

This function would favor having a team against a BYE in the first round over having it in the following rounds. It would be weird to win against someone and to be directly in semi-final or final because of a propagated BYE.

Here would be the rules of such a method:

  • The function should ignore BYEs (null values of the seeding) and therefore, always have the same output for the same seeding (without taking BYEs and their position in the seeding into account).

  • The function should take the target size of the stage as an argument because the output seeding should have the same size as the stage.

  • Prefer [1, 2, 3, 4, 5, 6, 7, 8, 9, null, 10, null, 11, null, 12, null] to [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, null, null, null, null]

  • Edges cases

    • Prefer [1, null, 2, null, 3, null, 4, null, 5, null, 6, null, 7, null, 8, null] to [1, 2, 3, 4, 5, 6, 7, 8, null, null, null, null, null, null, null, null] because the number of participants (8) is equal to the half of the stage size (16), so we still prefer matches against BYE. The second round is a bracket with 8 participants.

    • Prefer [1, null, 2, null, 3, null, 4, null, 5, null, 6, null, 7, null, null, null,] to [1, 2, 3, 4, 5, 6, 7, null, null, null, null, null, null, null, null, null] because the round 2 acts just as bracket with 8 participants would have handled the case.

For example, this is not good at all since the final is useless:
image

But this is better:
image

In either way, the stage should rather have had 8 participants.

But the method should do what we ask to do.

Be able to set participants after a stage's creation

For now, it's not possible to set a participant list other than during a stage's creation.

It's possible to do it manually without using the library, by directly mutating the storage. But this won't handle BYEs as the library does.

Refactor to handle async SQL queries

Make an interface with functions used by the manager to get data from anywhere.

The manager shouldn't worry about the source of data. Therefore, it should async/await everything. (awaiting non-async functions is possible)

Correct updating next matches

  • updateNextMatch() shoud handle Loser Brackets
  • Update.match() shouldn't have a updateNext argument anymore.
  • Add locked to match status. Must be default when to be determined and updated with scores.

Add arguments to storage.select()

These arguments would be ids in an object (so that they can be named).
This would be used in SQL commands rather than getting all and filtering the results the JS way.

Stop merging data with node-json-db

For now, we merge composite JSON data thanks to node-json-db.

Example:

output.team2 = ({ result: 'win' } as any);

However, it won't be possible in SQL.
Therefore, we need to get the entry first, modify it and and overwrite it.

Throw an error if a new seeding doesn't match the size of the stage

Currently, when we use the Update.seeding() method, if the new seeding doesn't have the same size as the stage, it won't crash early and make some random error later.

It should be good to check and throw early. The issue #33 is related and could be implemented before, so that we can easily get the size of the stage.

Support 'Double Round-robin' for a round-robin stage

Each participant plays each opponent twice, once at home and once away.

Look at how to implement that. There is just twice the rounds and twice the matches per round, but you need to make a good distribution.

Say more about why targetting ES2019

Currently, it's because I'm still using Node.js 12, which doesn't support the optional chaining operator (?.).

    if (match.opponent1?.result === 'win')
                        ^
SyntaxError: Unexpected token '.'
    at wrapSafe (internal/modules/cjs/loader.js:931:16)
    at Module._compile (internal/modules/cjs/loader.js:979:27)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1035:10)
    at Module.load (internal/modules/cjs/loader.js:879:32)
    at Function.Module._load (internal/modules/cjs/loader.js:724:14)
    at Module.require (internal/modules/cjs/loader.js:903:19)
    at require (internal/modules/cjs/helpers.js:74:18)
    at Object.<anonymous> (/home/corentin/brackets-manager.js/test/helpers.spec.js:3:78)
    at Module._compile (internal/modules/cjs/loader.js:1015:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1035:10)

And it simplifies the code a lot, so I'm not dropping support for this operator.

Handle different tournaments

  • Give somewhere a tournament id when creating a stage, updating scores, etc.
  • Add tournament_id to Participant. Will be used in Create.registerParticipants().
  • Add a type Tournament (and a table) which contains:
    • id
    • name
    • status
    • scheduled_start_date
    • scheduled_end_date
    • size

Ability to reset the seeding of a stage

It could be useful to have the ability to reset the seeding of a stage.

It would consist in adding a resetSeeding(stageId) method in the Update class. We would pass the size of the stage instead of seeding in the Create constructor. Then this should work the same as Update.seeding().

Forbid stage size which is not a power of two

Currently, we can start the creation of a stage of any size but it will eventually crash somewhere.

Doing the check in the constructor of the Create class would be cool. By the way, there is already the helper function ensurePowerOfTwoSized() but it's not used yet.

Think about locked matches

What's the problem about updating a locked match, really?

  • Think about a bug where an automated way of updating scores forgets to set the winner of a match.
  • Then the next matches are locked and none of the update score notifications take effect?

Maybe it would be good to be less restrictive...

Implement the "Bracket optimized" group seed ordering

Adjacent

Seed numbers are distributed so as to fully fill groups in order.

image

Effort balanced

Seed numbers are distributed so as to balance the effort required by each seed number to win over the others. Note: this does not ensure a skill balance between groups.

image

Seed optimized (Snake)

Seed numbers are distributed so as to favor the highest seed numbers by grouping them with diametrically opposed seed numbers. Note: this method is also referred as 'snake' because the distribution process looks like a snake.

image

Bracket optimized

Seed numbers are distributed in the groups by avoiding grouping those that should normally meet in the bracket (ie. 1v8 2v7 3v6 4v5, ie. inner outer method). This preserves the classic bracket seeding and is optimal when directly followed by a single or double elimination bracket.

image

Store orderings in a new property in each match opponent

Store seeds and information about what match a participant comes from in a new property in ParticipantResult.

This will let us know the ordering method chosen by the organizer.

  • Update in brackets-model
  • Use in this project

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.