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

Documentation question: workflow after generating #18

Open
emersonthis opened this issue Nov 4, 2024 · 12 comments
Open

Documentation question: workflow after generating #18

emersonthis opened this issue Nov 4, 2024 · 12 comments

Comments

@emersonthis
Copy link
Contributor

The docs explain how to generate a round of matches for a tournament. This seems straightforward for creating the first round of matches in a new tournament. For most formats (other than round robin) the subsequent rounds depend on who wins in the previous. I'm trying to understand how the additional rounds are meant to be created. Is it expected for the application to run generate repeatedly after each match is completed?

@emersonthis
Copy link
Contributor Author

I also want to understand how the implementor is meant to associate the matches with one another and/or the overall tournament. For example, if the application has a page that shows the tournament bracket, how would the implementor know which match is in which round?

@emersonthis
Copy link
Contributor Author

For concreteness, here is the rspec test I'm writing while figuring out this library...

RSpec.describe PcslDriver, type: :model do
  let(:season) { create(:season) }
  let!(:team1) { Team.create!(name: 'Team 1', season:) }
  let!(:team2) { Team.create!(name: 'Team 2', season:) }
  let!(:team3) { Team.create!(name: 'Team 3', season:) }
  let!(:team4) { Team.create!(name: 'Team 4', season:) }

  fit 'creates matches' do
    driver = described_class.new season

    rounds_count = TournamentSystem::RoundRobin.total_rounds(driver)
    rounds_count.times do |i|
      TournamentSystem::RoundRobin.generate driver, { round: i }
      puts "Round #{i + 1}"
      season.team_matches.each do |match|
        puts "#{match.side_a.name} vs #{match.side_b.name}"
      end
    end

    expect(season.team_matches.count).to eq(5)
  end
end

This is the output I'm seeing:

Round 1
Team 1 vs Team 4
Team 2 vs Team 3
Round 2
Team 1 vs Team 4
Team 2 vs Team 3
Team 3 vs Team 1
Team 2 vs Team 4
Round 3
Team 1 vs Team 4
Team 2 vs Team 3
Team 3 vs Team 1
Team 2 vs Team 4
Team 1 vs Team 2
Team 3 vs Team 4

Is this close to how the generate class is intended to be used?

@BenjaminSchaaf
Copy link
Contributor

Yes that's the intended use. generate generates 1 round and it's up to you to keep track of any extra data (like which matches were generated in which round). The way I use it the list of matches is always empty ahead of calling generate.

@emersonthis
Copy link
Contributor Author

emersonthis commented Nov 7, 2024 via email

@BenjaminSchaaf
Copy link
Contributor

You only need them for the matches method on the driver, you don't necessarily need to hook that up with the build_match method. See for instance the TestDriver in spec/support/test_driver.rb, which has @matches and @created_matches (though do note that the driver isn't reused). But you don't need to follow that usage pattern; what you're already doing will work fine.

@emersonthis
Copy link
Contributor Author

Thanks!
I'll submit a PR with updates to the docs for this (and future) questions. Does that sound good? If so, I'll leave this open for now as a reminder and close it with the corresponding PR.

@emersonthis
Copy link
Contributor Author

One more follow-up question about this...

I am trying to plan how to associate matches with a specific round of a tournament. If I run TournamentSystem::RoundRobin.generate myDriver it creates the matches and returns nil. I don't see anywhere that the round option value is exposed to the drive. I'm envisioning a model structure in which Tournament has_many Round(s) and Round has_many Match(s). Is this architecture compatible with this library?

@BenjaminSchaaf
Copy link
Contributor

You'll need to put that into your driver yourself. You can use TournamentSystem::RoundRobin.guess_round myDriver to determine the round from the existing matches.

@emersonthis
Copy link
Contributor Author

emersonthis commented Nov 18, 2024

Thanks! I'm studying guess_round now... Are you suggesting something like this in the driver?

def build_match(home_team, away_team)
  current_round = TournamentSystem::RoundRobin.guess_round self
  @tournament.team_matches.create!(side_a: home_team, side_b: away_team, round: current_round)
end

(This ☝️ doesn't quite match the structure I described previously with a Round model. I simplified it for discussion purposes)

@BenjaminSchaaf
Copy link
Contributor

Definitely not. If you wanted to have it guess the round I'd do:

my_driver.round = TournamentSystem::RoundRobin.guess_round my_driver
TournamentSystem::RoundRobin.guess_round my_driver

It looks like you're using rails? Are you aware of citadel? You can find its driver here.

@emersonthis
Copy link
Contributor Author

Thanks. I think I understand now. Citadel is initializing the driver with the round info in advance. So no need for guess_round.

So if I follow this pattern, I think mine might look something like this...

my_driver = MyDriver.new
total_rounds_count = TournamentSystem::RoundRobin.total_rounds(my_driver)

total_rounds_count.times do |i|
  round = Round.create!(number: i, ...)
  my_driver.set_round_id round.id # build_match method will use this when creating a match
  TournamentSystem::RoundRobin.generate my_driver, { round: i }
end

Is this making sense?

@BenjaminSchaaf
Copy link
Contributor

Yep, that looks good.

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

No branches or pull requests

2 participants