Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 26 additions & 1 deletion website/api/manager/ManagerAPI.php
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,11 @@ private function getTrueskillMatchQuality($rankingValues) {
return floatval($lines[0]);
}

private function clearGameTask($gametaskID) {
$gametaskID = $this->mysqli->real_escape_string($gametaskID);
$this->insert("DELETE FROM GameTaskUser WHERE gametaskID={$gametaskID}");
$this->insert("DELETE FROM GameTask WHERE gametaskID={$gametaskID}");
}

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

Expand All @@ -88,7 +93,7 @@ protected function task() {
$seedPlayer = null;
$randValue = mt_rand() / mt_getrandmax();
if($randValue > 0.5) {
$seedPlayer = $this->select("SELECT * FROM User WHERE isRunning = 1 and numGames < 400 order by rand()*-pow(sigma, 2) LIMIT 1");
$seedPlayer = $this->select("SELECT u.* FROM (SELECT MAX(p.timestamp) as maxTime, pu.userID as userID from GameTaskUser pu INNER JOIN GameTask p ON p.gametaskID = pu.gametaskID GROUP BY pu.userID) temptable RIGHT JOIN User u on u.userID = temptable.userID WHERE (maxTime IS NULL OR maxTime < DATE_SUB(NOW(), INTERVAL 10 MINUTE)) AND isRunning = 1 and numGames < 400 order by rand()*-pow(sigma, 2) LIMIT 1");
}
if ($randValue > 0.25 && $randValue <= 0.5) {
$seedPlayer = $this->select("SELECT * FROM (SELECT u.* FROM (SELECT MAX(g.timestamp) as maxTime, gu.userID as userID FROM GameUser gu INNER JOIN Game g ON g.gameID=gu.gameID GROUP BY gu.userID) temptable INNER JOIN User u on u.userID = temptable.userID where numGames < 400 and isRunning = 1 order by maxTime ASC limit 15) orderedTable order by rand() limit 1;");
Expand All @@ -105,10 +110,23 @@ protected function task() {
$sizes = array(20, 25, 25, 30, 30, 30, 35, 35, 35, 35, 40, 40, 40, 45, 45, 50);
$size = $sizes[array_rand($sizes)];

// Record pairing
$worker = $this->select("SELECT * FROM Worker WHERE apiKey=".$this->mysqli->real_escape_string($this->apiKey)." LIMIT 1");
$this->insert("INSERT INTO GameTask (workerID) VALUES (".$worker["workerID"].")");
$gametaskID = $this->mysqli->insert_id;
$playerValues = array();
foreach($players as $player) {
$playerValues[] = "(".$gametaskID.", ".$player["userID"].")";
}
$playerValues = implode(",", $playerValues);
$playerInsert = "INSERT INTO GameTaskUser (gametaskID, userID) VALUES ".$playerValues;
$this->insert($playerInsert);

// Send game task
if(count($players) == $numPlayers) {
return array(
"type" => "game",
"gametaskID" => $gametaskID,
"width" => $size,
"height" => $size,
"users" => $players
Expand Down Expand Up @@ -161,6 +179,9 @@ protected function game() {
// Will need email credentials for email sending, numSubmissions for version checking, and mu + sigma so we can update trueskill
$storedUser = $this->select("SELECT userID, onEmailList, email, numSubmissions, mu, sigma FROM User WHERE userID=".$this->mysqli->real_escape_string($user['userID']));
if(intval($storedUser['numSubmissions']) != intval($user['numSubmissions'])) {
if(isset($_POST['gametaskID'])) {
$this->clearGameTask($_POST['gametaskID']);
}
return null;
}
$users[$key] = array_merge($user, $storedUser); // Second param overwrites first param
Expand Down Expand Up @@ -261,6 +282,10 @@ protected function game() {
}
$query .= " ELSE rank END;";
$this->insert($query);

if(isset($_POST['gametaskID'])) {
$this->clearGameTask($_POST['gametaskID']);
}
}
}

Expand Down
28 changes: 28 additions & 0 deletions website/sql/schema.sql
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,34 @@ CREATE TABLE `GameUser` (
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
/*!40101 SET character_set_client = @saved_cs_client */;

--
-- Table structure for table `GameTask`
--

DROP TABLE IF EXISTS `GameTask`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `GameTask` (
`gametaskID` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`workerID` mediumint(8) unsigned NOT NULL,
`timestamp` datetime DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`gametaskID`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1;
/*!40101 SET character_set_client = @saved_cs_client */;

--
-- Table structure for table `GameTaskUser`
--

DROP TABLE IF EXISTS `GameTaskUser`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `GameTaskUser` (
`gametaskID` mediumint(8) unsigned NOT NULL,
`userID` mediumint(8) unsigned NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
/*!40101 SET character_set_client = @saved_cs_client */;

--
-- Table structure for table `User`
--
Expand Down
6 changes: 3 additions & 3 deletions worker/backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,14 +86,14 @@ def compileResult(userID, didCompile, language, errors=None):
r = requests.post(MANAGER_URL+"compile", data={"apiKey": API_KEY, "userID": userID, "didCompile": int(didCompile), "language": language, "errors": errors})
print("Posting compile result %s\n" % r.text)

def gameResult(width, height, users, replayPath, errorPaths):
def gameResult(gametaskID, width, height, users, replayPath, errorPaths):
"""Posts the result of a game task"""
print("Posting game result %s (GMT)\n" % str(strftime("%Y-%m-%d %H:%M:%S", gmtime())))
files = {os.path.basename(replayPath): open(replayPath, "rb").read()}
for path in errorPaths:
files[os.path.basename(path)] = open(path, "rb").read()
r = requests.post(MANAGER_URL+"game", data={"apiKey": API_KEY, "mapWidth": str(width), "mapHeight": str(height), "users": json.dumps(users)}, files=files)
r = requests.post(MANAGER_URL+"game", data={"apiKey": API_KEY, "gametaskID": gametaskID, "mapWidth": str(width), "mapHeight": str(height), "users": json.dumps(users)}, files=files)
print("Got game result %s (GMT)\n" % str(strftime("%Y-%m-%d %H:%M:%S", gmtime())))
print("\n-------Game result:-----")
print(r.text)
print("------------------------\n")
print("------------------------\n")
13 changes: 9 additions & 4 deletions worker/worker.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,8 +142,11 @@ def parseGameOutput(output, users):

return width, height, users, replayPath, errorPaths

def executeGameTask(width, height, users, backend):
def executeGameTask(gameTask, backend):
"""Downloads compiled bots, runs a game, and posts the results of the game"""
width = int(gameTask["width"])
height = int(gameTask["height"])
users = gameTask["users"]
print("Running game with width %d, height %d\n" % (width, height))
print("Users objects %s\n" % (str(users)))

Expand All @@ -157,15 +160,15 @@ def executeGameTask(width, height, users, backend):
fIn.close()
fOut.close()

backend.gameResult(width, height, users, replayArchivePath, errorPaths)
backend.gameResult(gameTask["gametaskID"], width, height, users, replayArchivePath, errorPaths)
filelist = glob.glob("*.log")
for f in filelist:
os.remove(f)

os.remove(replayPath)
os.remove(replayArchivePath)

if __name__ == "__main__":
def main():
print("\n\n\n\nStarting up worker...\n\n\n")
while True:
try:
Expand All @@ -179,7 +182,7 @@ def executeGameTask(width, height, users, backend):
executeCompileTask(task["user"], backend)
else:
print("Running a game task...\n")
executeGameTask(int(task["width"]), int(task["height"]), task["users"], backend)
executeGameTask(task, backend)
else:
print("No task available at time %s (GMT). Sleeping...\n" % str(strftime("%Y-%m-%d %H:%M:%S", gmtime())))
sleep(2)
Expand All @@ -188,3 +191,5 @@ def executeGameTask(width, height, users, backend):
print("Sleeping...\n")
sleep(2)

if __name__ == "__main__":
main()