@@ -288,163 +288,7 @@ BEGIN
288288 -- Losers bracket uses separate group numbers to make it easier to reason about:
289289 -- For N winner groups (1..N), we create N loser groups (N+1..2N) with path='LB'.
290290 IF stage_type = ' DoubleElimination' THEN
291- RAISE NOTICE ' => Generating double elimination structure for stage %' , stage." order" ;
292- DECLARE
293- g int ;
294- loser_group_num int ;
295- wb_round_count int ;
296- r int ;
297- wb_round_matches int ;
298- lb_round_matches int ;
299- wb_match_ids uuid[];
300- lb_match_ids uuid[];
301- lb_prev_match_ids uuid[];
302- i int ;
303- j int ;
304- teams_advancing int ;
305- wb_final_id uuid;
306- lb_final_id uuid;
307- gf_id uuid;
308- BEGIN
309- -- Determine winners bracket round count
310- SELECT MAX (round) INTO wb_round_count
311- FROM tournament_brackets
312- WHERE tournament_stage_id = stage .id AND path = ' WB' ;
313-
314- RAISE NOTICE ' => Winners bracket has % rounds' , wb_round_count;
315-
316- -- Calculate teams advancing from this stage (WB champion + LB champion per group)
317- teams_advancing := 2 * stage .groups ;
318-
319- -- Build losers bracket per group (separate loser group id with path='LB')
320- FOR g IN 1 ..stage .groups LOOP
321- -- Loser group number: winners_group + stage.groups (e.g. WB group 1 -> LB group N+1)
322- loser_group_num := g + stage .groups ;
323- RAISE NOTICE ' => Creating loser group % for winners group %' , loser_group_num, g;
324-
325- lb_prev_match_ids := NULL ;
326-
327- -- Generate LB rounds (same number as WB rounds)
328- FOR r IN 1 ..wb_round_count LOOP
329- -- Get WB matches for this round
330- SELECT array_agg(id ORDER BY match_number ASC ) INTO wb_match_ids
331- FROM tournament_brackets
332- WHERE tournament_stage_id = stage .id AND path = ' WB' AND round = r AND " group" = g;
333-
334- wb_round_matches := COALESCE(array_length(wb_match_ids, 1 ), 0 );
335- IF wb_round_matches = 0 THEN
336- CONTINUE;
337- END IF;
338-
339- -- Calculate LB matches for this round
340- IF r = 1 THEN
341- -- LB Round 1: receives losers from WB Round 1 (paired 2 at a time)
342- lb_round_matches := wb_round_matches / 2 ;
343- ELSE
344- -- LB Round r: receives losers from WB Round r (1-to-1) + winners from LB Round (r-1)
345- lb_round_matches := wb_round_matches;
346- END IF;
347-
348- -- Create LB matches for this round in the loser group
349- lb_match_ids := ARRAY[]::uuid[];
350- FOR i IN 1 ..lb_round_matches LOOP
351- INSERT INTO tournament_brackets (round, tournament_stage_id, match_number, " group" , path )
352- VALUES (r, stage .id , i, loser_group_num, ' LB' )
353- RETURNING id INTO new_id;
354- lb_match_ids := lb_match_ids || new_id;
355- END LOOP;
356-
357- -- Link WB losers to LB matches in the loser group
358- IF r = 1 THEN
359- -- Pair WB Round 1 losers two-at-a-time into LB Round 1
360- FOR i IN 1 ..wb_round_matches LOOP
361- j := ((i - 1 ) / 2 ) + 1 ;
362- IF j <= lb_round_matches THEN
363- UPDATE tournament_brackets
364- SET loser_parent_bracket_id = lb_match_ids[j]
365- WHERE id = wb_match_ids[i];
366- END IF;
367- END LOOP;
368- ELSE
369- -- Map WB Round r losers one-to-one into LB Round r
370- FOR i IN 1 ..LEAST(wb_round_matches, lb_round_matches) LOOP
371- UPDATE tournament_brackets
372- SET loser_parent_bracket_id = lb_match_ids[i]
373- WHERE id = wb_match_ids[i];
374- END LOOP;
375- -- Note: LB round winners linking is handled by link_tournament_stage_matches
376- -- which uses 1-to-1 mapping by match number for LB paths
377- END IF;
378-
379- lb_prev_match_ids := lb_match_ids;
380- END LOOP;
381-
382- -- For stages that produce a single champion, create a consolidation final in LB
383- -- and a Grand Final in WB:
384- -- - LB extra round (round = wb_round_count + 1, path='LB'):
385- -- participants = loser of WB final + winner of LB final
386- -- - WB extra round (round = wb_round_count + 1, path='WB'):
387- -- participants = winner of WB final + winner of LB extra round
388- IF wb_round_count > 0 AND next_stage_max_teams = 1 THEN
389- -- Identify WB and LB finals (last round in each path for this group)
390- SELECT id INTO wb_final_id
391- FROM tournament_brackets
392- WHERE tournament_stage_id = stage .id AND path = ' WB' AND round = wb_round_count AND " group" = g
393- ORDER BY match_number ASC LIMIT 1 ;
394-
395- SELECT id INTO lb_final_id
396- FROM tournament_brackets
397- WHERE tournament_stage_id = stage .id AND path = ' LB' AND round = wb_round_count AND " group" = loser_group_num
398- ORDER BY match_number ASC LIMIT 1 ;
399-
400- IF wb_final_id IS NOT NULL AND lb_final_id IS NOT NULL THEN
401- -- Create LB consolidation final (extra LB round)
402- INSERT INTO tournament_brackets (round, tournament_stage_id, match_number, " group" , path )
403- VALUES (wb_round_count + 1 , stage .id , 1 , loser_group_num, ' LB' )
404- RETURNING id INTO gf_id;
405-
406- -- Winner of LB final advances to LB consolidation via parent_bracket_id
407- UPDATE tournament_brackets
408- SET parent_bracket_id = gf_id
409- WHERE id = lb_final_id;
410-
411- -- Loser of WB final drops into LB consolidation via loser_parent_bracket_id
412- UPDATE tournament_brackets
413- SET loser_parent_bracket_id = gf_id
414- WHERE id = wb_final_id;
415-
416- RAISE NOTICE ' => Created LB consolidation final for group % (round %, path LB)' , g, wb_round_count + 1 ;
417-
418- -- Create WB Grand Final as an extra WB round
419- INSERT INTO tournament_brackets (round, tournament_stage_id, match_number, " group" , path )
420- VALUES (wb_round_count + 1 , stage .id , 1 , g, ' WB' )
421- RETURNING id INTO gf_id;
422-
423- -- Winner of WB final advances to Grand Final
424- UPDATE tournament_brackets
425- SET parent_bracket_id = gf_id
426- WHERE id = wb_final_id;
427-
428- -- Winner of LB consolidation final advances to Grand Final
429- UPDATE tournament_brackets
430- SET parent_bracket_id = gf_id
431- WHERE id = (
432- SELECT id
433- FROM tournament_brackets
434- WHERE tournament_stage_id = stage .id
435- AND path = ' LB'
436- AND round = wb_round_count + 1
437- AND " group" = loser_group_num
438- ORDER BY match_number ASC LIMIT 1
439- );
440-
441- RAISE NOTICE ' => Created WB Grand Final for group % (round %, path WB)' , g, wb_round_count + 1 ;
442- END IF;
443- ELSE
444- RAISE NOTICE ' => Skipping Grand Final for group % (next_stage_max_teams=%, both WB and LB champions advance directly)' , g, next_stage_max_teams;
445- END IF;
446- END LOOP;
447- END;
291+ PERFORM generate_double_elimination_bracket(stage .id , teams_per_group, stage .groups , next_stage_max_teams);
448292 END IF;
449293
450294 RAISE NOTICE ' => Linking matches within stage %' , stage." order" ;
@@ -458,4 +302,4 @@ BEGIN
458302
459303 PERFORM calculate_tournament_bracket_start_times(_tournament_id);
460304END;
461- $$ LANGUAGE plpgsql;
305+ $$ LANGUAGE plpgsql;
0 commit comments