Skip to content

Instantly share code, notes, and snippets.

@handy-man
Last active August 29, 2015 14:20
Show Gist options
  • Save handy-man/f3ce5a7d86427d5037c3 to your computer and use it in GitHub Desktop.
Save handy-man/f3ce5a7d86427d5037c3 to your computer and use it in GitHub Desktop.
/**
* http://stackoverflow.com/questions/8355264/tournament-bracket-placement-algorithm
* Author: DarkAngel
*
* Simply ensures that the top player (first player) is seeded/ ordered against the worst player.
* 1 vs 8, 4 vs 5, 2 vs 7, 3 vs 6 <-- Typical seeding outcome from this sorting.
*
* @param $players
* @return array
*/
public function SeedOrderStandard($players)
{
$count = count($players);
for ($i = 0; $i < log($count / 2, 2); $i++) {
$out = array();
foreach ($players as $player) {
$splice = pow(2, $i);
$out = array_merge($out, array_splice($players, 0, $splice));
$out = array_merge($out, array_splice($players, -$splice));
}
$players = $out;
}
return $players;
}
/**
* Primary function when dealing with the tournamnet, calls many other functions that take care of our seeding, and sorting of seeded data.
*
* @param $tournament
*/
public function buildBracket($tournament)
{
$numberOfLevels = $this->getLevels($tournament);
$this->createLevels($numberOfLevels, $tournament);
$playersToMatch = $this->SeedSteam($tournament);
$playersToMatch = $this->SeedOrderStandard($playersToMatch);
$this->SortedSeededPlayerStorage($tournament, $playersToMatch);
for ($x = 0; $x < count($playersToMatch); $x++) {
if ($x % 2 == 0) {
$match = new match();
$match->tournament_id = $tournament->id;
$level_id = $tournament->levels->first();
$match->level_id = $level_id->id;
$match->save();
$match->players()->attach(array_values($playersToMatch)[$x]['id']);
} else {
$match->players()->attach(array_values($playersToMatch)[$x]['id']);
}
}
}
/**
* The primary function for seeding users based on genre, this uses steam but also if no steam exists will use regular points by genre.
* The tournament is passed into the function, from the tournament we can get the relations of players taking part.
* We first loop through the array of players, inside that foreach loop we do all of our points assignment.
*
*
* @param $tournament
* @return array
*/
public function SeedSteam($tournament)
{
$players = $tournament->playersDesc;
$genre = $tournament->genre;
$total = 0;
$newPlayers = array();
foreach ($players as $player) {
$points_total = 0;
$appids = array();
$gameids = array();
$userid = $player->id;
$player_data = Steam::where('user_id', '=', $userid)->first();
foreach(point::where('user_id', '=', $userid)->GenreSpecific($genre)->get() as $point){
$points_total = $points_total + $point->amount;
}
if (is_null($player_data)) {
array_push($newPlayers, array('points' => $points_total, 'id' => $player->id));
continue;
}
$steamid = $player_data->steamid;
if (is_null($steamid)) {
continue;//No steamID lets leave
}
$apps = steam_games_genre::where('steam_games_genre_id', '=', $genre)->get();
foreach ($apps as $app) {
array_push($gameids, $app->steam_games_id);
}
foreach ($gameids as $game) {
array_push($appids, steam_games::find($game)->app_id);
}
$steam_data = SteamApi::player($steamid)->getownedgames(true, true, $appids);
foreach ($steam_data as $steam) {
$total = $total + $steam->playtimeForever;
}
$total = $total + $points_total;
array_push($newPlayers, array('points' => $total, 'id' => $player->id));
$total = 0;
}
$arraysize = count($newPlayers);
if ((($arraysize - 1) & $arraysize) == 0) {
//Power of 2, YAY!
}
else
{
$newPlayers = $this->ByeSystem($newPlayers, $arraysize);
}
arsort($newPlayers);
$this->StoreSeedData($tournament, $newPlayers);
return $newPlayers;
}
/**
* When an odd number of players exists we need to implement a bye system (adding fake results) ID#9 is the ID of my player called "bye" in the test data
* This is technically a bad implementation and was required due to a missing feature in the JS library being unable to deal with lack of power of 2.
* This looks worst when there are 9 players (needing to add 7 bye's until next power of 2) will look better visually the closer we are.
*
* @param $newPlayers
* @return mixed
*/
public function ByeSystem($newPlayers, $arraysize)
{
$user = User::where('displayname', '=', 'Bye')->get();
$nextPower = pow(2, ceil(log($arraysize) / log(2)));
$differnce = $nextPower - $arraysize;
for ($i = 0; $differnce > $i; $i++) {
array_push($newPlayers, array('points' => -1, 'id' => $user->id));
}
return $newPlayers;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment