ManagerAPI::game PHP Method

game() protected method

Allow workers to post the result of their game
protected game ( )
    protected function game()
    {
        var_dump($_FILES);
        var_dump($_POST);
        // Each user in users must have a rank, playerIndex, mu, sigma, and userID
        if (isset($_POST['users']) && count($_FILES) > 0) {
            $this->insert("UPDATE Worker SET numGames=numGames+1 WHERE apiKey=" . $this->mysqli->real_escape_string($this->apiKey));
            $mapWidth = $_POST['mapWidth'];
            $mapHeight = $_POST['mapHeight'];
            $users = json_decode($_POST['users']);
            $storedUsers = array();
            // Throw out the game if it is using an old version of a person's bot
            foreach ($users as $user) {
                $storedUser = $this->select("SELECT * FROM User WHERE userID=" . $this->mysqli->real_escape_string($user->userID));
                array_push($storedUsers, $storedUser);
                if (intval($storedUser['numSubmissions']) != intval($user->numSubmissions)) {
                    return null;
                }
            }
            // Store replay file and error logs
            $replayName = null;
            $s3Client = $this->loadAwsSdk()->createS3();
            foreach ($_FILES as $fileKey => $file) {
                $pathParts = pathinfo($file['name']);
                $args = ['Key' => $pathParts['basename'], 'Body' => file_get_contents($file['tmp_name'])];
                if (strcmp('hlt', $pathParts['extension']) == 0) {
                    $replayName = $pathParts['basename'];
                    $args["Bucket"] = REPLAY_BUCKET;
                    $args["ContentEncoding"] = "gzip";
                } else {
                    $args["Bucket"] = ERROR_LOG_BUCKET;
                }
                $s3Client->putObject($args);
            }
            // Check that we arent stoing too many games in db
            $numAllowed = 100000;
            $res = mysqli_query($this->mysqli, "SELECT * FROM Game");
            $numRows = $res->num_rows;
            $numToDelete = $numRows - $numAllowed;
            if ($numToDelete > 0) {
                $gamesToDelete = $this->selectMultiple("SELECT gameID FROM Game ORDER BY gameID LIMIT {$numToDelete}");
                foreach ($gamesToDelete as $game) {
                    $this->insert("DELETE FROM GameUser WHERE gameID={$game['gameID']}");
                    $this->insert("DELETE FROM Game WHERE gameID={$game['gameID']}");
                }
            }
            // Store game information in db
            $this->insert("INSERT INTO Game (replayName, mapWidth, mapHeight, timestamp) VALUES ('" . $this->mysqli->real_escape_string($replayName) . "', " . $this->mysqli->real_escape_string($mapWidth) . ", " . $this->mysqli->real_escape_string($mapHeight) . ", NOW())");
            $gameID = $this->mysqli->insert_id;
            // Update each participant's stats
            for ($a = 0; $a < count($users); $a++) {
                $timeoutInt = $users[$a]->didTimeout ? 1 : 0;
                $errorLogName = $users[$a]->errorLogName == NULL ? "NULL" : "'" . $this->mysqli->real_escape_string($users[$a]->errorLogName) . "'";
                $this->insert("INSERT INTO GameUser (gameID, userID, errorLogName, rank, playerIndex, didTimeout, versionNumber) VALUES ({$gameID}, " . $this->mysqli->real_escape_string($users[$a]->userID) . ", {$errorLogName}, " . $this->mysqli->real_escape_string($users[$a]->rank) . ", " . $this->mysqli->real_escape_string($users[$a]->playerTag) . ", {$timeoutInt}, {$storedUsers[$a]['numSubmissions']})");
                // Increment number of games
                $this->insert("UPDATE User SET numGames=numGames+1 WHERE userID=" . $users[$a]->userID);
            }
            // Send first game email and first timeout email
            foreach ($users as $user) {
                $storedUser = $this->select("SELECT * FROM User WHERE userID=" . $user->userID);
                if ($user->didTimeout && mysqli_query($this->mysqli, "SELECT * from GameUser WHERE didTimeout = 1 and versionNumber = {$storedUser['numSubmissions']} and userID={$user->userID}")->num_rows == 1) {
                    $errorLogContents = NULL;
                    foreach ($_FILES as $file) {
                        if ($file['name'] == $user->errorLogName) {
                            $errorLogContents = file_get_contents($file['tmp_name']);
                            break;
                        }
                    }
                    if ($errorLogContents == NULL) {
                        continue;
                    }
                    $message = "<p>Your bot timed out in a game for the first time. This happens when your bot doesn't respond in 15 seconds of a game's start or 1 second of a turn's start. A timeout may be the result of a runtime error in your bot. When your bot times out, its pieces become part of the map and it is ejected from the game.</p> <p><a href='" . WEB_DOMAIN . "game.php?replay={$replayName}'>Here</a> is a visualization of the game in which your bot timed out.</p> <p><a href='" . WEB_DOMAIN . "api/web/errorLog?errorLogName={$user->errorLogName}'>Here</a> is your bot's error log. An error log contains your bot's output (from stdout and stderr) and the time it took per turn.</p>";
                    $this->sendNotification($storedUser, "First Bot Timeout/Error", $message, -1);
                }
            }
            // Update mu and sigma for the players
            usort($users, function ($a, $b) {
                return $a->rank > $b->rank;
            });
            $rankings = array();
            foreach ($users as $user) {
                array_push($rankings, $user->mu);
                array_push($rankings, $user->sigma);
            }
            exec("python3 updateTrueskill.py " . implode(' ', $rankings), $lines);
            var_dump($lines);
            for ($a = 0; $a < count($users); $a++) {
                $components = explode(' ', $lines[$a]);
                $this->insert("UPDATE User SET mu=" . $this->mysqli->real_escape_string($components[0]) . ", sigma=" . $this->mysqli->real_escape_string($components[1]) . " WHERE userID=" . $this->mysqli->real_escape_string($users[$a]->userID));
            }
            // Update overall rank of everyone
            $allUsers = $this->selectMultiple("SELECT * FROM User where isRunning=1");
            usort($allUsers, function ($a, $b) {
                return $a['mu'] - 3 * $a['sigma'] < $b['mu'] - 3 * $b['sigma'];
            });
            for ($userIndex = 0; $userIndex < count($allUsers); $userIndex++) {
                $rank = $userIndex + 1;
                $this->insert("UPDATE User SET rank={$rank} WHERE userID={$allUsers[$userIndex]['userID']}");
            }
        }
    }