php – 双重淘汰锦标赛时间表

我正在尝试创建一些逻辑来生成double-elimination tournament bracket中的事件计划.

以下是一个示例8团队支架:

rd1 quarter    semi    finals
A───┐
  0 ├───────A┐
B───┘        │
           4 ├────────A┐
C───┐        │         │
  1 ├───────C┘         │
D───┘                  │
                    10 ├──────A┐
E───┐                  │       │
  2 ├───────E┐         │       │
F───┘        │         │       │
           5 ├────────E┘       │
G───┐        │              13 ├───= Champ
  3 ├───────G┘                 │
H───┘                          │
                    E────┐     │
         C───┐           │     │
    B───┐  8 ├────C┐  12 ├────E┘
      6 ├B───┘     │     │
    D───┘       11 ├C────┘
         G───┐     │
    F───┐  9 ├────G┘
      7 ├F───┘
    H───┘

数字代表匹配数组中的索引,这是所需的输出.例如,索引0将代表第1组与第8组(使用种子系统),索引4将代表索引0的获胜者与索引1的获胜者.

失败者的支架来自赢家支架的输家,其中指数6是指数0的输家与指数1的输家,指数8是指数4的输家与指数6的赢家.

在视觉示例中,您可以看到按字母标记的团队,并且每次都显示获胜团队在顶部分支上的明确示例,并且失败团队位于底部分支上.指数0代表A队与B队,指数4代表指数0(A)与指数1(C)的胜者的胜者.指数6是指数0(B)与指数1(D)的输家的输家,指数8是指数4(C)与指数6(B)的赢家的输家

有一个明显的模式出现了,但是当我尝试适应不同数量的竞争对手时,我的逻辑变得混乱和混乱.为了简单起见,我将支架修改为只有2个团队的力量.我能够编写所有内容来为8个团队创建一个匹配数组,但是我对自己的代码感到迷茫,因为它似乎不具备可扩展性.

// round one
for( $i = 0; $i < log( count( $competitors ), 2 ); $i++ )
{
    $seeded = array( );
    foreach( $competitors as $competitor )
    {
        $splice = pow( 2, $i );

        $seeded = array_merge( $seeded, array_splice( $competitors, 0, $splice ) );
        $seeded = array_merge( $seeded, array_splice( $competitors, -$splice ) );
    }
    $competitors = $seeded;
}

$events = array_chunk( $seeded, 2 );

// quarter finals
for( $i = 0; $i < count( $competitors ) / 2; $i++ )
{
    array_push( $events, array(
        array( 'from_event_index' => $i, 'from_event_rank' => 1 ), // rank 1 = winner
        array( 'from_event_index' => ++$i, 'from_event_rank' => 1 )
    ) );
}

$round_matchups = array( );
for( $i = 0; $i < count( $competitors ) / 2; $i++ )
{
    array_push( $round_matchups, array(
        array( 'from_event_index' => $i, 'from_event_rank' => 2 ), // rank 2 = loser
        array( 'from_event_index' => ++$i, 'from_event_rank' => 2 )
    ) );
}
$events = array_merge( $events, $round_matchups );

for( $i = 0; $i < count( $round_matchups ); $i++ )
{
    array_push( $events, array(
        array( 'from_event_index' => $i + count( $competitors ) / 2, 'from_event_rank' => 2 ),
        array( 'from_event_index' => $i + count( $competitors ) / 2 + count( $competitors ) / 2 / 2, 'from_event_rank' => 1 )
    ) );
}

// semi finals
for( $i = 0; $i < count( $competitors ) / 2 / 2; $i++ )
{
    array_push( $events, array(
        array( 'from_event_index' => $i + count( $competitors ) / 2, 'from_event_rank' => 1 ),
        array( 'from_event_index' => ++$i + count( $competitors ) / 2, 'from_event_rank' => 1 )
    ) );
}

$round_matchups = array( );
for( $i = 0; $i < count( $competitors ) / 2 / 2; $i++ )
{
    array_push( $round_matchups, array(
        array( 'from_event_index' => $i + count( $competitors ), 'from_event_rank' => 1 ),
        array( 'from_event_index' => ++$i + count( $competitors ), 'from_event_rank' => 1 )
    ) );
}
$events = array_merge( $events, $round_matchups );

for( $i = 0; $i < count( $round_matchups ); $i++ )
{
    array_push( $events, array(
        array( 'from_event_index' => $i + count( $competitors ) + count( $competitors ) / 2 - 2, 'from_event_rank' => 2 ),
        array( 'from_event_index' => $i + count( $competitors ) + count( $competitors ) / 2 - 1, 'from_event_rank' => 1 )
    ) );
}

// finals
for( $i = 0; $i < count( $competitors ) / 2 / 2 / 2; $i++ )
{
    array_push( $events, array(
        array( 'from_event_index' => $i + count( $competitors ) / 2 * 3 - 2, 'from_event_rank' => 1 ),
        array( 'from_event_index' => ++$i + count( $competitors ) / 2 * 3 - 1, 'from_event_rank' => 1 )
    ) );
}

输出上面的代码:

$events = array(14) {
  [0]=>
  array(2) {
    [0]=>
    array(4) {
      ["team"]=>int(1)
    }
    [1]=>
    array(4) {
      ["team"]=>int(8)
    }
  }
  [1]=>
  array(2) {
    [0]=>
    array(4) {
      ["team"]=>int(4)
    }
    [1]=>
    array(4) {
      ["team"]=>int(5)
    }
  }
  [2]=>
  array(2) {
    [0]=>
    array(4) {
      ["team"]=>int(2)
    }
    [1]=>
    array(4) {
      ["team"]=>int(7)
    }
  }
  [3]=>
  array(2) {
    [0]=>
    array(4) {
      ["team"]=>int(3)
    }
    [1]=>
    array(4) {
      ["team"]=>int(6)
    }
  }
  [4]=>
  array(2) {
    [0]=>
    array(2) {
      ["from_event_index"]=>int(0)
      ["from_event_rank"]=>int(1)
    }
    [1]=>
    array(2) {
      ["from_event_index"]=>int(1)
      ["from_event_rank"]=>int(1)
    }
  }
  [5]=>
  array(2) {
    [0]=>
    array(2) {
      ["from_event_index"]=>int(2)
      ["from_event_rank"]=>int(1)
    }
    [1]=>
    array(2) {
      ["from_event_index"]=>int(3)
      ["from_event_rank"]=>int(1)
    }
  }
  [6]=>
  array(2) {
    [0]=>
    array(2) {
      ["from_event_index"]=>int(0)
      ["from_event_rank"]=>int(2)
    }
    [1]=>
    array(2) {
      ["from_event_index"]=>int(1)
      ["from_event_rank"]=>int(2)
    }
  }
  [7]=>
  array(2) {
    [0]=>
    array(2) {
      ["from_event_index"]=>int(2)
      ["from_event_rank"]=>int(2)
    }
    [1]=>
    array(2) {
      ["from_event_index"]=>int(3)
      ["from_event_rank"]=>int(2)
    }
  }
  [8]=>
  array(2) {
    [0]=>
    array(2) {
      ["from_event_index"]=>int(4)
      ["from_event_rank"]=>int(2)
    }
    [1]=>
    array(2) {
      ["from_event_index"]=>int(6)
      ["from_event_rank"]=>int(1)
    }
  }
  [9]=>
  array(2) {
    [0]=>
    array(2) {
      ["from_event_index"]=>int(5)
      ["from_event_rank"]=>int(2)
    }
    [1]=>
    array(2) {
      ["from_event_index"]=>int(7)
      ["from_event_rank"]=>int(1)
    }
  }
  [10]=>
  array(2) {
    [0]=>
    array(2) {
      ["from_event_index"]=>int(4)
      ["from_event_rank"]=>int(1)
    }
    [1]=>
    array(2) {
      ["from_event_index"]=>int(5)
      ["from_event_rank"]=>int(1)
    }
  }
  [11]=>
  array(2) {
    [0]=>
    array(2) {
      ["from_event_index"]=>int(8)
      ["from_event_rank"]=>int(1)
    }
    [1]=>
    array(2) {
      ["from_event_index"]=>int(9)
      ["from_event_rank"]=>int(1)
    }
  }
  [12]=>
  array(2) {
    [0]=>
    array(2) {
      ["from_event_index"]=>int(10)
      ["from_event_rank"]=>int(2)
    }
    [1]=>
    array(2) {
      ["from_event_index"]=>int(11)
      ["from_event_rank"]=>int(1)
    }
  }
  [13]=>
  array(2) {
    [0]=>
    array(2) {
      ["from_event_index"]=>int(10)
      ["from_event_rank"]=>int(1)
    }
    [1]=>
    array(2) {
      ["from_event_index"]=>int(12)
      ["from_event_rank"]=>int(1)
    }
  }
}

关于我如何修改它以适用于4人团队,16人团队或2 ^ n团队支架的任何想法?我觉得“半决赛”标题下的逻辑应重复0次,但每次我尝试根据总轮数循环它时,它只重复与前一轮相同的匹配.

解决方法:

好吧,我一直在跋涉现有的逻辑,并能够为4,8,16和32团队双重消除括号生成时间表.逻辑不是必须简洁的,但至少可以让我理解发生了什么.在将来,我希望稍微修改和清理它,但是现在必须这样做.

$rounds = log( count( $competitors ), 2 ) + 1;

// round one
for( $i = 0; $i < log( count( $competitors ), 2 ); $i++ )
{
    $seeded = array( );
    foreach( $competitors as $competitor )
    {
        $splice = pow( 2, $i );

        $seeded = array_merge( $seeded, array_splice( $competitors, 0, $splice ) );
        $seeded = array_merge( $seeded, array_splice( $competitors, -$splice ) );
    }
    $competitors = $seeded;
}

$events = array_chunk( $seeded, 2 );

if( $rounds > 2 )
{
    $round_index = count( $events );

    // second round
    for( $i = 0; $i < count( $competitors ) / 2; $i++ )
    {
        array_push( $events, array(
            array( 'from_event_index' => $i, 'from_event_rank' => 1 ), // rank 1 = winner
            array( 'from_event_index' => ++$i, 'from_event_rank' => 1 )
        ) );
    }

    $round_matchups = array( );
    for( $i = 0; $i < count( $competitors ) / 2; $i++ )
    {
        array_push( $round_matchups, array(
            array( 'from_event_index' => $i, 'from_event_rank' => 2 ), // rank 2 = loser
            array( 'from_event_index' => ++$i, 'from_event_rank' => 2 )
        ) );
    }
    $events = array_merge( $events, $round_matchups );

    for( $i = 0; $i < count( $round_matchups ); $i++ )
    {
        array_push( $events, array(
            array( 'from_event_index' => $i + count( $competitors ) / 2, 'from_event_rank' => 2 ),
            array( 'from_event_index' => $i + count( $competitors ) / 2 + count( $competitors ) / 2 / 2, 'from_event_rank' => 1 )
        ) );
    }
}

if( $rounds > 3 )
{
    // subsequent rounds
    for( $i = 0; $i < $rounds - 3; $i++ )
    {
        $round_events = pow( 2, $rounds - 3 - $i );
        $total_events = count( $events );

        for( $j = 0; $j < $round_events; $j++ )
        {
            array_push( $events, array(
                array( 'from_event_index' => $j + $round_index, 'from_event_rank' => 1 ),
                array( 'from_event_index' => ++$j + $round_index, 'from_event_rank' => 1 )
            ) );
        }

        for( $j = 0; $j < $round_events; $j++ )
        {
            array_push( $events, array(
                array( 'from_event_index' => $j + $round_index + $round_events * 2, 'from_event_rank' => 1 ),
                array( 'from_event_index' => ++$j + $round_index + $round_events * 2, 'from_event_rank' => 1 )
            ) );
        }

        for( $j = 0; $j < $round_events / 2; $j++ )
        {
            array_push( $events, array(
                array( 'from_event_index' => $j + $total_events, 'from_event_rank' => 2 ),
                array( 'from_event_index' => $j + $total_events + $round_events / 2, 'from_event_rank' => 1 )
            ) );
        }

        $round_index = $total_events;
    }

}

if( $rounds > 1 )
{
    // finals
    array_push( $events, array(
        array( 'from_event_index' => count( $events ) - 3, 'from_event_rank' => 1 ),
        array( 'from_event_index' => count( $events ) - 1, 'from_event_rank' => 1 )
     ) );
}

我已经验证了最多32支队伍的结果(仅2的权力),并且能够生成64个团队的计划,这似乎是正确的.有时候,持久性会得到回报.

上一篇:分析平台Tableau推出数据和分析平台新功能


下一篇:数据分析必备可视化工具----Tableau