Drarig29 / brackets-manager.js

A simple library to manage tournament brackets (round-robin, single elimination, double elimination).
https://drarig29.github.io/brackets-docs
MIT License
245 stars 38 forks source link

Couple more questions on getting started #156

Closed GrimLothar closed 1 year ago

GrimLothar commented 1 year ago

Hey @Drarig29 ! Thank you again for your response on #144 it was super helpful and I'm so much closer to a working prototype. Since you left the door open to keep asking questions, here I am :D

So basically, on my use case I'm making single_elimination tournament with a consolationFinal. Basically like the football world cup, so I can get 1st to 4th place.

I was able to create the tournament no problem with this:

await manager.create({
        name: 'And so it begins...',
        tournamentId: 0, // 
        type: 'single_elimination',
        settings: { consolationFinal: true },
        seeding: [
            'Team 1',
            'Team 2',
            'Team 3',
            'Team 4',
            'Team 5',
            'Team 6',
            'Team 7',
            'Team 8',
        ],
    })

And been checking currentRound, and isRoundCompleted as i've been marking matches as complete. Everything progressed nicely until I updated the final match before the finals. This is the code that I'm running:

    const currentStage = await manager.get.currentStage(tournamentId)
    console.log(`current stage: ${currentStage.name}`)
    const currentRound = await manager.get.currentRound(currentStage.id)
    console.log(`current round: ${currentRound.number}`)
    const currentRoundMatches = await manager.storage.select('match', { round_id: currentRound.id })
    console.log(currentRoundMatches)
    const isFinished = helpers.isRoundCompleted(currentRoundMatches)
    console.log(`Is current round finished?: ${isFinished}`)

And I'm seeing this back:

current stage: And so it begins...
current round: 3
[
  {
    id: 23,
    child_count: 0,
    round_id: 12,
    stage_id: 4,
    group_id: 6,
    number: 1,
    opponent1: { id: 29 },
    opponent2: { id: 27 },
    status: 2
  }
]
Is current round finished?: false

So how come am I not seeing both games? The final and the consolation final?

Also, after I set the winner for that match and I run the code again, I now see:

current round: 1
[
  {
    id: 24,
    created_at: '2023-01-02T20:31:46.394078',
    child_count: 0,
    round_id: 13,
    stage_id: 4,
    group_id: 7,
    number: 1,
    opponent1: { id: 26, position: 1 },
    opponent2: { id: 28, position: 2 },
    status: 2
  }
]
Is current round finished?: false

Looks like this is now the final and the previous one was the consolation final? Only reason i'm assuming that is because i see those position: 1 and 2 in there. But those are not the ones I set as winners before. So i'm confused on how this part works...

I guess the question is, how do I know when I'm on a final match (or a consolation final).

And also, once I update that match, how do I know who is the tournamente winner? Or even better, is it possible to get back a list of all the players ranked by their final position in the tournament?

Thanks!

Drarig29 commented 1 year ago

Hi! Spoiler: you found a bug in get.currentRound() 😎

So how come am I not seeing both games? The final and the consolation final?

You can't see both games because they are put in different rounds (and even different groups, actually).

That's how it's designed.

It becomes clearer when you look at the visual representation of your tournament stage:

image

How to display a JSON file like this - Use the [`JsonDatabase`](https://www.npmjs.com/package/brackets-json-db) to write the storage to the disk in JSON format. - Clone [brackets-viewer.js](https://github.com/Drarig29/brackets-viewer.js) and run `npm install && npm run build` to build the viewer. - Run `npx json-server --watch path/to/your/db.json` to serve a REST API from your JSON file. - Open in your browser the `demo/with-api.html` file that is located In your cloned `brackets-viewer.js` folder.

If you think the tree-like structure as one group and each column as a tree level (round), the 3 first rounds form a tree which is the first group and the last round is in another tree (another group).

Now that you know this, I realise that it might be too much external work to know that we're on a final match and get the current matches... I might create a function for this.

At first, I thought that the consolation final was required to be played after the final, but it's not the case: they can be played in parallel. So I imagine that's why you were assuming that you should see both games.


Also, after I set the winner for that match and I run the code again, I now see: <current round: 1>

What you are seeing is actually the "first" round... of the second group! (which contains the consolation final). And that's the bug coming from get.currentRound(). I need to fix it.


And also, once I update that match, how do I know who is the tournament winner? Or even better, is it possible to get back a list of all the players ranked by their final position in the tournament?

You already can, by using await manager.get.finalStandings(currentStage.id).

GrimLothar commented 1 year ago

AMAZING! Thank you for the thorough explanation and specially on the finalStandings method! I was looking at the helpers file. 🙈

And yes, I was expecting the Consolation to happen either in parallel or before the final. Thinking again like a world cup bracket, the match for the 3rd place happens the day prior to the gran final (which is the most important match and hence played last).

I guess the only qustion that I didn't see an answer to is how do I know when I'm on a final match (or a consolation final).

But I will play around with the brackets-viewer, since I see the headers there show which is which, so that will probably give me a clue.

FYI, i'm working on an implementation of CrudInterface to work with Supabase which is the DB i'm using.

I've got the base things working for now! Will def make a PR once it's ready

GrimLothar commented 1 year ago

FYI, I think I see a bug with finalStandings as well. After completing all the matches I'm seeing this:

[
  { id: 0, name: 'Team 1', rank: 1 },
  { id: 1, name: 'Team 2', rank: 2 },
  { id: 3, name: 'Team 4', rank: 3 },
  { id: 2, name: 'Team 3', rank: 3 },
  { id: 7, name: 'Team 8', rank: 4 },
  { id: 4, name: 'Team 5', rank: 4 },
  { id: 6, name: 'Team 7', rank: 4 },
  { id: 5, name: 'Team 6', rank: 4 }
]

But if 'Team 4' beat 'Team 3' in the consolation final, I would expect 'Team 4' to have rank 3 and 'Team 3' to have rank 4. Then the last 4 teams, which all lost on the first round, they would all have rank 5.

Drarig29 commented 1 year ago

FYI, I just released v1.5.4 with a new get.currentMatches() function, and a fix for get.finalStandings().

You could use it like this:

await manager.create({
    name: 'And so it begins...',
    tournamentId: 0, // 
    type: 'single_elimination',
    settings: { consolationFinal: true },
    seeding: [
        'Team 1',
        'Team 2',
        'Team 3',
        'Team 4',
        'Team 5',
        'Team 6',
        'Team 7',
        'Team 8',
    ],
});

const tournamentId = 0;

const currentStage = await manager.get.currentStage(tournamentId);
console.log(`current stage: ${currentStage.name}`);

// Rounds
await manager.update.match({ id: 0, opponent1: { result: 'win' } });
await manager.update.match({ id: 1, opponent1: { result: 'win' } });
await manager.update.match({ id: 2, opponent1: { result: 'win' } });
await manager.update.match({ id: 3, opponent1: { result: 'win' } });
await manager.update.match({ id: 4, opponent1: { result: 'win' } });
await manager.update.match({ id: 5, opponent1: { result: 'win' } });

console.log(await manager.get.currentMatches(currentStage.id));

// Final
await manager.update.match({ id: 6, opponent1: { result: 'win' } });

console.log('Is current round finished?', helpers.isRoundCompleted(
    await manager.get.currentMatches(currentStage.id),
));

// Consolation final
await manager.update.match({ id: 7, opponent1: { result: 'win' } });

console.log('Is current round finished?', helpers.isRoundCompleted(
    await manager.get.currentMatches(currentStage.id),
));

console.log(await manager.get.finalStandings(currentStage.id));
GrimLothar commented 1 year ago

you're the best!