public static function generate(array $params) { $active = array_shift($params) !== 'past'; $brackets = Lib\Cache::fetch(function () use($active) { $allBrackets = Api\Bracket::getAll(); // Filter out active/completed brackets $brackets = []; foreach ($allBrackets as $bracket) { if ($active && ($bracket->state == BS_ELIMINATIONS || $bracket->state == BS_VOTING || $bracket->state == BS_NOMINATIONS)) { $bracket->title = Api\Round::getBracketTitleForActiveRound($bracket); $brackets[] = $bracket; } if (!$active && $bracket->state == BS_FINAL) { $brackets[] = $bracket; } } // Check for card images foreach ($brackets as $bracket) { if (is_readable('./images/bracket_' . $bracket->id . '_card.jpg')) { $bracket->cardImage = '/images/bracket_' . $bracket->id . '_card.jpg'; } else { $bracket->entrants = Api\Character::getRandomCharacters($bracket, 9); } } return $brackets; }, 'Controller::Brackets_displayBrackets_' . ($active ? 'active' : 'completed')); Lib\Display::addKey('page', 'brackets'); $title = $active ? 'Current Brackets' : 'Past Brackets'; Lib\Display::renderAndAddKey('content', 'bracketsView', ['brackets' => $brackets, 'title' => $title]); }
public static function generate(array $params) { $bracket = Api\Bracket::getBracketByPerma(array_shift($params)); if ($bracket) { Lib\Display::addKey('page', 'characters'); $content = Lib\Display::renderAndAddKey('content', 'characters', (object) ['bracket' => $bracket, 'characters' => Api\Character::getByBracketId($bracket->id)]); } }
public static function generate(array $params) { $bracket = Api\Bracket::getBracketByPerma(array_shift($params)); if ($bracket) { Lib\Display::addKey('page', 'characters'); Lib\Display::addKey('title', $bracket->name . ' Entrants' . DEFAULT_TITLE_SUFFIX); $hasSource = $bracket->hasSourceLabel(); $hasSeed = $bracket->state == BS_VOTING || $bracket->state == BS_FINAL; $content = Lib\Display::renderAndAddKey('content', 'characters', (object) ['bracket' => $bracket, 'characters' => Api\Character::getByBracketId($bracket->id), 'hasSource' => $hasSource, 'hasSeed' => $hasSeed, 'hasSorter' => $hasSource || $hasSeed]); } }
protected static function _main($message = null, $force = false) { $out = new stdClass(); $out->brackets = Api\Bracket::getUserOwnedBrackets(self::$_user, $force); // If there's no message passed directly, check for one from cache $message = !$message ? self::_getStashedMessage() : $message; if ($out->brackets) { // Check for card images foreach ($out->brackets as $bracket) { if (is_readable('./images/bracket_' . $bracket->id . '_card.jpg')) { $bracket->cardImage = '/images/bracket_' . $bracket->id . '_card.jpg'; } else { $bracket->entrants = Api\Character::getRandomCharacters($bracket, 9); } } // Sort the brackets by reverse date usort($out->brackets, function ($a, $b) { return $a->state == BS_FINAL || $a->state > $b->state ? 1 : -1; }); // Decorate each bracket with some information about what phase it can // safely move to. Mostly this is for eliminations foreach ($out->brackets as $bracket) { $bracket->title = Api\Round::getBracketTitleForActiveRound($bracket); $bracket->nextIsFinal = $bracket->title === 'Title Match'; // Get the title of the next round $nextRounds = Api\Round::getNextRounds($bracket); $bracket->nextTitle = null; if ($nextRounds) { $bracket->nextTitle = str_replace(['Voting - ', 'Eliminations - '], '', Api\Round::getBracketTitleForRound($bracket, $nextRounds[0])); } // This is a dumb catch all while I work out issues in the stored procedure $bracket->nextTitle = $bracket->nextTitle ?: 'Next Round'; if ($bracket->state == BS_ELIMINATIONS) { // Should query all the brackets at once, but I'm feeling lazy tonight... $result = Lib\Db::Query('SELECT MIN(round_group) AS current_group, MAX(round_group) AS last_group FROM `round` WHERE bracket_id = :bracketId AND round_final = 0', [':bracketId' => $bracket->id]); if ($result && $result->count) { $row = Lib\Db::Fetch($result); // If the eliminations are on the last group, don't show the // advance button if ($row->current_group == $row->last_group) { $bracket->showStart = true; } else { $bracket->showAdvance = true; } } } } } if ($message) { $out->message = $message; } Lib\Display::renderAndAddKey('content', 'admin/brackets', $out); }
/** * Gets all characters for a bracket */ public static function getByBracketId($bracketId) { $retVal = null; if (is_numeric($bracketId)) { $cacheKey = 'Character_getByBracketId_' . $bracketId; $retVal = Lib\Cache::Get($cacheKey); if (false === $retVal) { $retVal = null; // TODO - make order by column configurable $retVal = Character::queryReturnAll(['bracketId' => $bracketId], ['source' => 'ASC', 'name' => 'ASC']); Lib\Cache::Set($cacheKey, $retVal); } } return $retVal; }
/** * Generates a list of characters in a bracket (ordered by seed) and their performance * in said bracket */ public static function getEntrantPerformanceStats(Bracket $bracket, $force = false) { return Lib\Cache::fetchLongCache(function () use($bracket) { // Get all tourney rounds and characters for this bracket $characters = Character::queryReturnAll(['bracketId' => $bracket->id, 'seed' => ['null' => false]], ['seed' => 'asc']); $rounds = Round::queryReturnAll(['bracketId' => $bracket->id, 'final' => 1, 'tier' => ['gt' => 0]], ['id' => 'asc']); // Create a hash out of the characters $temp = []; foreach ($characters as $character) { $temp[$character->id] = $character; } $characters = $temp; // Sort the rounds out based on character for faster access later $characterRounds = []; foreach ($rounds as $round) { // Decorate the round with full character models $round->character1 = $characters[$round->character1Id]; $round->character2 = $characters[$round->character2Id]; self::_addRoundToCharacterRounds($round, $round->character1Id, $characterRounds); self::_addRoundToCharacterRounds($round, $round->character2Id, $characterRounds); } $retVal = []; foreach ($characters as $character) { $roundsForCharacter = array_values($characterRounds[$character->id]); $closestDiff = -1; $closestRound = null; $lostTo = null; $totalVotes = 0; foreach ($roundsForCharacter as $round) { // Heheheh... so gross $isCharacter1 = $round->character1Id == $character->id; $totalVotes += $isCharacter1 ? $round->character1Votes : $round->character2Votes; $diff = abs($round->character1Votes - $round->character2Votes); if ($diff < $closestDiff || $closestDiff === -1) { $closestDiff = $diff; // This case should be small enough that re-instantiating through a loop // shouldn't prove too much of a performance concern (especially since // it's generated only once per new round). Will monitor in production $closestRound = (object) ['character' => $isCharacter1 ? $round->character2 : $round->character1, 'difference' => $closestDiff, 'round' => $round]; } $lost = $isCharacter1 && $round->character1Votes < $round->character2Votes || !$isCharacter1 && $round->character2Votes < $round->character1Votes; $lostTo = $lost ? (object) ['character' => $isCharacter1 ? $round->character2 : $round->character1, 'lostBy' => $diff, 'round' => $round] : null; } $retVal[] = (object) ['character' => $character, 'closestRound' => $closestRound, 'lostTo' => $lostTo, 'totalVotes' => $totalVotes, 'group' => chr(65 + $roundsForCharacter[0]->group)]; } return $retVal; }, 'Stats::PerformanceStats_' . $bracket->id, $force); }
private static function _getSimilarCharacters($bracketId, $query) { $retVal = []; // Search for similar entered characters first $characters = Api\Character::searchBracketCharacters($query, $bracketId); if ($characters && count($characters)) { $retVal = $characters; } else { // Search nominees so that maybe we can prevent another similar character being nominated $nominees = Api\Nominee::searchBracketNominees($query, $bracketId); if ($nominees && count($nominees)) { $retVal = $nominees; } } return $retVal; }
private static function _getBracketCharacters() { $retVal = null; $bracketId = Lib\Url::GetInt('bracketId', null); $count = Lib\Url::GetInt('count', null); if ($bracketId) { //If $count has a value, get random characters from the given bracket if ($count) { $bracket = \Api\Bracket::getById($bracketId); if ($bracket) { //3 levels of IFs. This is getting rediculous $retVal = \Api\Character::getRandomCharacters($bracket, $count); } } else { $retVal = \Api\Character::getByBracketId($bracketId); } } return $retVal; }
private static function _updateCharacter(Api\Bracket $bracket) { $out = new stdClass(); $out->success = false; $id = Lib\Url::Post('characterId', true); $name = Lib\Url::Post('name'); $source = Lib\Url::Post('source'); $action = Lib\Url::Post('action'); if ($id && $name && $action) { $out->action = $action; $character = Api\Character::getById($id); if ($character && $character->bracketId == $bracket->id) { if ($action == 'update') { $character->name = $name; $character->source = $source; if ($character->sync()) { $out->success = true; } else { $out->message = 'Error updating database'; } } else { if ($action == 'delete') { if ($bracket->state == BS_NOMINATIONS || $bracket->state == BS_ELIMINATIONS) { if ($character->delete()) { $out->success = true; } else { $out->message = 'Delete failed'; } } else { $out->message = 'Cannot delete characters after voting has started'; } } else { $out->message = 'Unknown action'; } } } else { $out->message = 'Character does not belong to this bracket'; } } else { $out->message = 'Missing fields'; } Lib\Display::renderJson($out); }
/** * Gets a full dataset including characters for multiple rounds */ private static function _getRoundsAndCharacters($query, $params = null) { $retVal = null; $result = Lib\Db::Query($query, $params); if ($result && $result->count) { // This array will hold all unique character IDs (and later character objects) // to retrieve so we reduce the number of trips to the database. $characters = []; $retVal = []; while ($row = Lib\Db::Fetch($result)) { $round = new Round($row); $characters[$round->character1Id] = true; $characters[$round->character2Id] = true; $retVal[] = new Round($row); } // Now fetch the character objects $result = Character::query(['id' => ['in' => array_keys($characters)]]); if ($result && $result->count) { while ($row = Lib\Db::Fetch($result)) { $character = new Character($row); $characters[$character->id] = $character; } // Now, assign the character objects to their rounds for ($i = 0, $count = count($retVal); $i < $count; $i++) { $retVal[$i]->character1 = $characters[$retVal[$i]->character1Id]; $retVal[$i]->character2 = $characters[$retVal[$i]->character2Id]; } } } return $retVal; }
/** * Override for getAll to include the winner character object */ public static function getAll($force = false) { $cacheKey = 'Api:Bracket:getAll_' . BRACKET_SOURCE; $retVal = Lib\Cache::Get($cacheKey); if (false === $retVal || $force) { $brackets = parent::queryReturnAll(['source' => BRACKET_SOURCE, 'state' => ['ne' => BS_HIDDEN]], ['score' => 'desc', 'state' => 'desc', 'start' => 'desc']); $retVal = []; foreach ($brackets as $bracket) { if ($bracket->winnerCharacterId) { $bracket->winner = Character::getById($bracket->winnerCharacterId); } if ($bracket->start <= time() || $force) { $retVal[] = $bracket; } } Lib\Cache::Set($cacheKey, $retVal, 3600); } return $retVal; }