<commit_before><?php

use Aws\Sdk;
require __DIR__ . '/../../vendor/autoload.php';

require_once '../API.class.php';

define("COMPILE_PATH", "../../../storage/compile/");
define("BOTS_PATH", "../../../storage/bots/");
define("INI_FILE", "../../../halite.ini");

ini_set('upload_max_filesize', '50M');
ini_set('post_max_size', '50M');
ini_set('max_input_time', 90);
ini_set('max_execution_time', 90);
ini_set('display_errors', 1);
error_reporting(E_ALL ^ E_NOTICE);

class ManagerAPI extends API{
    private $apiKey = NULL;

    // Init database, sanitize parameters, and check if worker is valid
    public function __construct($request) {
        $this->loadConfig();
        $this->initDB();

        if($this->isValidWorker() == false) {
            echo "Not valid worker";
            exit(1);
        } else {
            $this->insert("UPDATE Worker SET lastRequestTime = now() WHERE apiKey = {$this->apiKey}");
        }
        parent::__construct($request);
    }

    private function getAPIKey() {
        $this->apiKey = NULL;
        if(isset($_GET['apiKey'])) $this->apiKey = $_GET['apiKey'];
        else if(isset($_POST['apiKey'])) $this->apiKey = $_POST['apiKey'];
    }

    // Checks HTTP parameters and request IP to make sure that the client provided a valid API key
    private function isValidWorker() {
        // Get apiKey
        $this->getAPIKey();
        if($this->apiKey == NULL) return false;

        // Get ip
        $ipAddress = $_SERVER['REMOTE_ADDR'];

        if(count($this->select("SELECT ipAddress FROM Worker WHERE ipAddress = '".$this->mysqli->real_escape_string($ipAddress)."' and apiKey = ".$this->mysqli->real_escape_string($this->apiKey))) > 0) {
            return true;
        } else {
            return false;
        }
    }

    private function getTrueskillMatchQuality($rankingValues) {
        usort($rankingValues, function($a, $b) {
            return $a['rank'] < $b['rank'];
        });
        $rankings = array();
        foreach($rankingValues as $user) {
            array_push($rankings, $user['mu']);
            array_push($rankings, $user['sigma']);
        }
        exec("python3 trueskillMatchQuality.py ".implode(' ', $rankings), $lines);
        return floatval($lines[0]);
    }


    /////////////////////////API ENDPOINTS\\\\\\\\\\\\\\\\\\\\\\\\\\\\

    // Delegate a task to a workers
    protected function task() {
        if($this->method == 'GET') {
            // Check for compile tasks
            $needToBeCompiled = $this->select("SELECT * FROM User WHERE compileStatus=1 ORDER BY userID ASC");
            if(count($needToBeCompiled) > 0) {
                $this->insert("UPDATE User SET compileStatus = 2 WHERE userID = ".$needToBeCompiled['userID']);
                return array(
                    "type" => "compile",
                    "user" => $needToBeCompiled);
                }

                // Assign a run game tasks
                $possibleNumPlayers = array(2, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 5, 5, 6);
                $numPlayers = $possibleNumPlayers[array_rand($possibleNumPlayers)];

                $users = $this->selectMultiple("SELECT * FROM User WHERE isRunning=1 ORDER BY rand()");
                $seedPlayer = $this->select("select * from User where isRunning=1 and (numGames < 20 or didTimeout < 0.9) order by rand()*-pow(sigma, 2)");

                if(count($seedPlayer) < 1) {
                    $oldestGameTime = time();
                    foreach($users as $user) {
                        $latestGameTime = strtotime($this->select("select timestamp from Game inner join GameUser on Game.gameID = GameUser.gameID and GameUser.userID={$user['userID']} order by timestamp DESC limit 1")['timestamp']);
                        if($latestGameTime < $oldestGameTime) {
                            $seedPlayer = $user;
                            $oldestGameTime = $latestGameTime;
                        }
                    }
                }
                if(count($seedPlayer) < 1) return null;
                $players = $this->selectMultiple("SELECT * FROM User WHERE isRunning=1 and ABS(rank-{$seedPlayer['rank']}) < (5 / pow(rand(), 0.65)) and userID <> {$seedPlayer['userID']} ORDER BY rand() LIMIT ".($numPlayers-1));
                array_push($players, $seedPlayer);

                // Pick map size
                $sizes = array(20, 25, 25, 30, 30, 30, 35, 35, 35, 35, 40, 40, 40, 45, 45, 50);
                $size = $sizes[array_rand($sizes)];

                // Send game task
                if(count($players) == $numPlayers) {
                    return array(
                        "type" => "game",
                        "width" => $size,
                        "height" => $size,
                        "users" => $players
                    );
                }
            }
        }

    // Allow worker to post the result of their compilation
    protected function compile() {
        var_dump($_POST);
        if(isset($_POST['userID']) && isset($_POST['didCompile'])) {
            $this->insert("UPDATE Worker SET numCompiles=numCompiles+1 WHERE apiKey=".$this->mysqli->real_escape_string($this->apiKey));

            $userID = $_POST['userID'];
            $didCompile = $_POST['didCompile'];

            if($didCompile == 1) { // Did succeed
                $language = isset($_POST['language']) ? $_POST['language'] : "Other";
                $user = $this->select("SELECT * FROM User WHERE userID=".$this->mysqli->real_escape_string($userID));

                $numActiveUsers = mysqli_query($this->mysqli, "SELECT userID FROM User WHERE isRunning=1")->num_rows;
                
                $this->insert("UPDATE User SET numSubmissions=numSubmissions+1, numGames=0, mu = 25.000, sigma = 8.333, compileStatus = 0, isRunning = 1, language = '".$this->mysqli->real_escape_string($language)."' WHERE userID = ".$this->mysqli->real_escape_string($userID));

                $this->insert("INSERT INTO UserHistory (userID, versionNumber, lastRank, lastNumPlayers, lastNumGames) VALUES ({$user['userID']}, {$user['numSubmissions']}, {$user['rank']}, $numActiveUsers, {$user['numGames']})");
            } else { // Didnt succeed
                $this->insert("UPDATE User SET compileStatus = 0 WHERE userID = ".$this->mysqli->real_escape_string($userID));
            }
        }
    }

    // Allow workers to post the result of their 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();

            foreach($users as $user) {
                array_push($storedUsers, $this->select("SELECT * FROM User WHERE userID=".$this->mysqli->real_escape_string($user->userID)));<commit_msg>Fix to version number gameuser<commit_after><?php

use Aws\Sdk;
require __DIR__ . '/../../vendor/autoload.php';

require_once '../API.class.php';

define("COMPILE_PATH", "../../../storage/compile/");
define("BOTS_PATH", "../../../storage/bots/");
define("INI_FILE", "../../../halite.ini");

ini_set('upload_max_filesize', '50M');
ini_set('post_max_size', '50M');
ini_set('max_input_time', 90);
ini_set('max_execution_time', 90);
ini_set('display_errors', 1);
error_reporting(E_ALL ^ E_NOTICE);

class ManagerAPI extends API{
    private $apiKey = NULL;

    // Init database, sanitize parameters, and check if worker is valid
    public function __construct($request) {
        $this->loadConfig();
        $this->initDB();

        if($this->isValidWorker() == false) {
            echo "Not valid worker";
            exit(1);
        } else {
            $this->insert("UPDATE Worker SET lastRequestTime = now() WHERE apiKey = {$this->apiKey}");
        }
        parent::__construct($request);
    }

    private function getAPIKey() {
        $this->apiKey = NULL;
        if(isset($_GET['apiKey'])) $this->apiKey = $_GET['apiKey'];
        else if(isset($_POST['apiKey'])) $this->apiKey = $_POST['apiKey'];
    }

    // Checks HTTP parameters and request IP to make sure that the client provided a valid API key
    private function isValidWorker() {
        // Get apiKey
        $this->getAPIKey();
        if($this->apiKey == NULL) return false;

        // Get ip
        $ipAddress = $_SERVER['REMOTE_ADDR'];

        if(count($this->select("SELECT ipAddress FROM Worker WHERE ipAddress = '".$this->mysqli->real_escape_string($ipAddress)."' and apiKey = ".$this->mysqli->real_escape_string($this->apiKey))) > 0) {
            return true;
        } else {
            return false;
        }
    }

    private function getTrueskillMatchQuality($rankingValues) {
        usort($rankingValues, function($a, $b) {
            return $a['rank'] < $b['rank'];
        });
        $rankings = array();
        foreach($rankingValues as $user) {
            array_push($rankings, $user['mu']);
            array_push($rankings, $user['sigma']);
        }
        exec("python3 trueskillMatchQuality.py ".implode(' ', $rankings), $lines);
        return floatval($lines[0]);
    }


    /////////////////////////API ENDPOINTS\\\\\\\\\\\\\\\\\\\\\\\\\\\\

    // Delegate a task to a workers
    protected function task() {
        if($this->method == 'GET') {
            // Check for compile tasks
            $needToBeCompiled = $this->select("SELECT * FROM User WHERE compileStatus=1 ORDER BY userID ASC");
            if(count($needToBeCompiled) > 0) {
                $this->insert("UPDATE User SET compileStatus = 2 WHERE userID = ".$needToBeCompiled['userID']);
                return array(
                    "type" => "compile",
                    "user" => $needToBeCompiled);
                }

                // Assign a run game tasks
                $possibleNumPlayers = array(2, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 5, 5, 6);
                $numPlayers = $possibleNumPlayers[array_rand($possibleNumPlayers)];

                $users = $this->selectMultiple("SELECT * FROM User WHERE isRunning=1 ORDER BY rand()");
                $seedPlayer = $this->select("select * from User where isRunning=1 and (numGames < 20 or didTimeout < 0.9) order by rand()*-pow(sigma, 2)");

                if(count($seedPlayer) < 1) {
                    $oldestGameTime = time();
                    foreach($users as $user) {
                        $latestGameTime = strtotime($this->select("select timestamp from Game inner join GameUser on Game.gameID = GameUser.gameID and GameUser.userID={$user['userID']} order by timestamp DESC limit 1")['timestamp']);
                        if($latestGameTime < $oldestGameTime) {
                            $seedPlayer = $user;
                            $oldestGameTime = $latestGameTime;
                        }
                    }
                }
                if(count($seedPlayer) < 1) return null;
                $players = $this->selectMultiple("SELECT * FROM User WHERE isRunning=1 and ABS(rank-{$seedPlayer['rank']}) < (5 / pow(rand(), 0.65)) and userID <> {$seedPlayer['userID']} ORDER BY rand() LIMIT ".($numPlayers-1));
                array_push($players, $seedPlayer);

                // Pick map size
                $sizes = array(20, 25, 25, 30, 30, 30, 35, 35, 35, 35, 40, 40, 40, 45, 45, 50);
                $size = $sizes[array_rand($sizes)];

                // Send game task
                if(count($players) == $numPlayers) {
                    return array(
                        "type" => "game",
                        "width" => $size,
                        "height" => $size,
                        "users" => $players
                    );
                }
            }
        }

    // Allow worker to post the result of their compilation
    protected function compile() {
        var_dump($_POST);
        if(isset($_POST['userID']) && isset($_POST['didCompile'])) {
            $this->insert("UPDATE Worker SET numCompiles=numCompiles+1 WHERE apiKey=".$this->mysqli->real_escape_string($this->apiKey));

            $userID = $_POST['userID'];
            $didCompile = $_POST['didCompile'];

            if($didCompile == 1) { // Did succeed
                $language = isset($_POST['language']) ? $_POST['language'] : "Other";
                $user = $this->select("SELECT * FROM User WHERE userID=".$this->mysqli->real_escape_string($userID));

                $numActiveUsers = mysqli_query($this->mysqli, "SELECT userID FROM User WHERE isRunning=1")->num_rows;
                
                $this->insert("UPDATE User SET numSubmissions=numSubmissions+1, numGames=0, mu = 25.000, sigma = 8.333, compileStatus = 0, isRunning = 1, language = '".$this->mysqli->real_escape_string($language)."' WHERE userID = ".$this->mysqli->real_escape_string($userID));

                $this->insert("INSERT INTO UserHistory (userID, versionNumber, lastRank, lastNumPlayers, lastNumGames) VALUES ({$user['userID']}, {$user['numSubmissions']}, {$user['rank']}, $numActiveUsers, {$user['numGames']})");
            } else { // Didnt succeed
                $this->insert("UPDATE User SET compileStatus = 0 WHERE userID = ".$this->mysqli->real_escape_string($userID));
            }
        }
    }

    // Allow workers to post the result of their 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();

            foreach($users as $user) {
                $storedUser = $this->select("SELECT * FROM User WHERE userID=".$this->mysqli->real_escape_string($user->userID));
                array_push($storedUsers, $storedUser);
{'fraction_non_alphanumeric': 0.16000557025483916, 'fraction_numerical': 0.013647124355939285, 'mean_word_length': 2.145641699518178, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 121, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 8, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3812286', 'n_tokens_mistral': 4345, 'n_tokens_neox': 4005, 'n_words': 959}