Add large sync roundtrip coverage
This commit is contained in:
parent
5126e94c26
commit
e52fb2897a
|
|
@ -37,5 +37,166 @@ RSpec.describe TournamentSnapshotImporter do
|
|||
expect(follower.name).to eq('Newer name')
|
||||
expect(follower.sync_last_imported_snapshot_at).to eq(Time.zone.parse('2026-04-14T10:30:02Z'))
|
||||
end
|
||||
|
||||
it 'round-trips large leader tournament graph with mismatched ids, many groups, deciders and 64-team playoffs' do
|
||||
create_list(:tournament, 3)
|
||||
source = create_large_source_tournament!
|
||||
create_list(:tournament, 5)
|
||||
follower = create(:tournament, read_only_mode: true, sync_auth_token: 'shared-secret')
|
||||
|
||||
snapshot = TournamentSnapshotBuilder.build(source)
|
||||
|
||||
described_class.import!(tournament: follower, snapshot: snapshot)
|
||||
|
||||
follower.reload
|
||||
expect(follower.id).not_to eq(source.id)
|
||||
expect(sync_signature(follower)).to eq(sync_signature(source))
|
||||
expect(follower.teams.count).to eq(128)
|
||||
expect(follower.stages.where(level: -1).first.groups.count).to eq(32)
|
||||
expect(follower.stages.where('level >= 0').sum { |stage| stage.matches.count }).to eq(63)
|
||||
expect(follower.matches.select(&:decider?).count).to eq(source.matches.select(&:decider?).count)
|
||||
expect(follower.teams.pluck(:sync_source_id)).to match_array(source.teams.pluck(:id))
|
||||
expect(source.teams.pluck(:id) & follower.teams.pluck(:id)).not_to match_array(source.teams.pluck(:id))
|
||||
end
|
||||
end
|
||||
|
||||
def create_large_source_tournament!
|
||||
tournament = create(
|
||||
:tournament,
|
||||
teams_count: 0,
|
||||
name: 'Large Sync Source',
|
||||
playoff_teams_amount: 64,
|
||||
instant_finalists_amount: 64,
|
||||
intermediate_round_participants_amount: 0
|
||||
)
|
||||
|
||||
group_stage = Stage.create!(tournament: tournament, level: -1, state: :finished)
|
||||
advancing_teams = []
|
||||
|
||||
32.times do |group_index|
|
||||
group = Group.create!(stage: group_stage, number: group_index + 1)
|
||||
teams = 4.times.map do |seed_index|
|
||||
create(
|
||||
:team,
|
||||
tournament: tournament,
|
||||
name: "Leader-G#{group_index + 1}-S#{seed_index + 1}"
|
||||
)
|
||||
end
|
||||
|
||||
teams[0].update!(name: "#{teams[0].name} Renamed") if group_index.zero?
|
||||
teams[1].update!(name: "#{teams[1].name} Renamed") if group_index == 15
|
||||
|
||||
create_group_round_robin!(group: group, teams: teams)
|
||||
create_group_scores!(group: group, teams: teams)
|
||||
|
||||
if group_index < 3
|
||||
create_decider_match!(group: group, teams: teams.take(2), hidden_points: [8 - group_index, 4 + group_index])
|
||||
end
|
||||
|
||||
advancing_teams.concat(teams.take(2))
|
||||
end
|
||||
|
||||
result = AddPlayoffsToTournamentAndSave.call(tournament: tournament, teams: advancing_teams)
|
||||
expect(result).to be_a_success
|
||||
|
||||
tournament.reload
|
||||
play_some_playoff_matches!(tournament)
|
||||
tournament.reload
|
||||
end
|
||||
|
||||
def create_group_round_robin!(group:, teams:)
|
||||
pairings = [
|
||||
[0, 1, 2, 1],
|
||||
[2, 3, 3, 0],
|
||||
[0, 2, 4, 1],
|
||||
[1, 3, 2, 0],
|
||||
[0, 3, 5, 2],
|
||||
[1, 2, 4, 3]
|
||||
]
|
||||
|
||||
pairings.each_with_index do |(left_index, right_index, left_points, right_points), position|
|
||||
match = Match.create!(group: group, state: :finished, position: position, decider: false)
|
||||
MatchScore.create!(match: match, team: teams[left_index], points: left_points, hidden_points: 0)
|
||||
MatchScore.create!(match: match, team: teams[right_index], points: right_points, hidden_points: 0)
|
||||
end
|
||||
end
|
||||
|
||||
def create_decider_match!(group:, teams:, hidden_points:)
|
||||
match = Match.create!(group: group, state: :finished, position: 6, decider: true)
|
||||
MatchScore.create!(match: match, team: teams.first, points: 0, hidden_points: hidden_points.first)
|
||||
MatchScore.create!(match: match, team: teams.second, points: 0, hidden_points: hidden_points.last)
|
||||
end
|
||||
|
||||
def create_group_scores!(group:, teams:)
|
||||
teams.each_with_index do |team, index|
|
||||
GroupScore.create!(
|
||||
group: group,
|
||||
team: team,
|
||||
group_points: 9 - index,
|
||||
scored_points: 12 - index,
|
||||
received_points: index,
|
||||
position: index + 1
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
def play_some_playoff_matches!(tournament)
|
||||
initial_stage = tournament.stages.where('level >= 0').max_by(&:level)
|
||||
initial_stage.matches.sort_by(&:position).first(4).each_with_index do |match, index|
|
||||
match.update!(state: :finished)
|
||||
ordered_scores = match.match_scores.sort_by(&:id)
|
||||
ordered_scores.first.update!(points: 20 + index)
|
||||
ordered_scores.second.update!(points: index)
|
||||
PlayoffStageService.populate_match_below(match).uniq.each(&:save!)
|
||||
end
|
||||
end
|
||||
|
||||
def sync_signature(tournament)
|
||||
{
|
||||
name: tournament.name,
|
||||
public: tournament.public,
|
||||
playoff_teams_amount: tournament.playoff_teams_amount,
|
||||
instant_finalists_amount: tournament.instant_finalists_amount,
|
||||
intermediate_round_participants_amount: tournament.intermediate_round_participants_amount,
|
||||
timer_end: tournament.timer_end&.iso8601,
|
||||
teams: tournament.teams.order(:name).map { |team| team.name },
|
||||
stages: tournament.stages.order(level: :asc).map do |stage|
|
||||
{
|
||||
level: stage.level,
|
||||
state: stage.state,
|
||||
groups: stage.groups.order(:number).map do |group|
|
||||
{
|
||||
number: group.number,
|
||||
matches: group.matches.order(:position).map { |match| match_signature(match) },
|
||||
group_scores: group.group_scores.includes(:team).sort_by(&:position).map do |score|
|
||||
{
|
||||
team_name: score.team.name,
|
||||
position: score.position,
|
||||
group_points: score.group_points,
|
||||
scored_points: score.scored_points,
|
||||
received_points: score.received_points
|
||||
}
|
||||
end
|
||||
}
|
||||
end,
|
||||
matches: stage.matches.order(:position).map { |match| match_signature(match) }
|
||||
}
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
def match_signature(match)
|
||||
{
|
||||
state: match.state,
|
||||
position: match.position,
|
||||
decider: match.decider,
|
||||
scores: match.match_scores.includes(:team).sort_by { |score| score.team.name }.map do |score|
|
||||
{
|
||||
team_name: score.team.name,
|
||||
points: score.points,
|
||||
hidden_points: score.hidden_points
|
||||
}
|
||||
end
|
||||
}
|
||||
end
|
||||
end
|
||||
|
|
|
|||
Loading…
Reference in New Issue