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
5 changes: 3 additions & 2 deletions website/api/manager/ManagerAPI.php
Original file line number Diff line number Diff line change
Expand Up @@ -131,11 +131,12 @@ protected function compile() {
if($didCompile == 1) { // Did succeed
$this->sendNotification($user, "Compilation Success", "<p>Your bot was sucessfully compiled on our servers as a program written in {$language}. Within a few minutes, your bot will begin playing games against other contestant's programs. Replays of these games will show up on your <a href='".WEB_DOMAIN."user.php'>homepage</a>.</p>", 1);

$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("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)."', compileTime = NOW() WHERE userID = ".$this->mysqli->real_escape_string($userID));

if(intval($user['numSubmissions']) != 0) {
$numActiveUsers = mysqli_query($this->mysqli, "SELECT userID FROM User WHERE isRunning=1")->num_rows;
$this->insert("INSERT INTO UserHistory (userID, versionNumber, lastRank, lastNumPlayers, lastNumGames) VALUES ({$user['userID']}, {$user['numSubmissions']}, {$user['rank']}, $numActiveUsers, {$user['numGames']})");
$compileTime = $user['compileTime'] == NULL ? 'NULL' : "'{$user['compileTime']}'";
$this->insert("INSERT INTO UserHistory (userID, versionNumber, compileTime, lastRank, lastNumPlayers, lastNumGames) VALUES ({$user['userID']}, {$user['numSubmissions']}, $compileTime, {$user['rank']}, $numActiveUsers, {$user['numGames']})");
}
} else { // Didnt succeed
$this->sendNotification($user, "Compilation Failure", "<p>The bot that you recently submitted to the Halite competition would not compile on our servers.</p><p>Our autocompile script <b>thought that your bot was written in \"{$language}\"</b>.</p><b>Here is a description of the compilation error</b>:<br><pre><code><br>{$_POST['errors']}</code></pre>", -1);
Expand Down
7 changes: 6 additions & 1 deletion website/api/web/WebsiteAPI.php
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,12 @@ protected function user() {
else if(isset($_GET['fields']) && isset($_GET['values'])) {
$limit = isset($_GET['limit']) ? intval($_GET['limit']) : 10;
$whereClauses = array_map(function($a) {
return $this->mysqli->real_escape_string($_GET['fields'][$a])." = '".$this->mysqli->real_escape_string($_GET['values'][$a])."'";
$allowedOps = array("=", "!=", ">", "<", ">=", "<=", "IS", "IS NOT");
$compOp = "=";
if(isset($_GET['comparison']) && in_array($_GET['comparison'][$a], $allowedOps)) {
$compOp = $_GET['comparison'][$a];
}
return $this->mysqli->real_escape_string($_GET['fields'][$a])." ".$compOp." '".$this->mysqli->real_escape_string($_GET['values'][$a])."'";
}, range(0, count($_GET['fields'])-1));
$orderBy = isset($_GET['orderBy']) ? $this->mysqli->real_escape_string($_GET['orderBy']) : 'rank';
$page = isset($_GET['page']) ? intval($_GET['page']) : 0;
Expand Down
50 changes: 50 additions & 0 deletions website/recent_submissions.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<!DOCTYPE html>
<html lang="en">

<head>
<?php include 'includes/header.php'; ?>

<title>Recent submissions</title>

<link href="lib/bootstrap.min.css" rel="stylesheet">
<link href="style/general.css" rel="stylesheet">
</head>

<body>
<div class="container">
<?php include 'includes/navbar.php'; ?>
<div class="pageContent">
<div class="row">
<div class="col-xl-12 col-lg-12 col-md-12">
<div class="text-center" style="display: none;" id="noBotsMessage">
<span class="glyphicon glyphicon-warning-sign" style="font-size: 8em;"></span>
<h3>There are no bots submitted yet.</h3>
</div>
<div id="submissionPanel" class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">Bot Submission Feed</h3>
</div>
<table class="table" id="submissionTable">
<thead>
<tr id="submissionTableHeader">
<th>Time</th><th>Player</th><th>Last Rank</th><th>Language</th><th>Version</th>
</tr>
</thead>
<tbody id="submissionTableBody">
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<script src="lib/xss.js"></script>
<script src="script/backend.js"></script>
<script src="script/general.js"></script>
<script src="script/recent_submissions.js"></script>
</body>

</html>
28 changes: 27 additions & 1 deletion website/script/backend.js
Original file line number Diff line number Diff line change
Expand Up @@ -262,9 +262,35 @@ function newEmail(email) {

function getGames(previousID) {
return $.ajax({
url: "api/web/game",
url: url+"game",
async: false,
method: "GET",
data: {previousID: previousID}
}).responseJSON;
}

function getRecentSubmissions(cutoffTime) {
var requestData = {
fields: ["isRunning"],
comparison: ["="],
values: ["1"],
orderBy: "compileTime DESC",
limit: 20
};
if(typeof(cutoffTime) !== "undefined") {
requestData["fields"].push("compileTime");
requestData["comparison"].push(">");
requestData["values"].push(cutoffTime);
}
var result = $.ajax({
url: url+"user",
async: false,
method: "GET",
data: requestData
});
var resp = result.responseJSON;
if(typeof(resp.users) === "undefined") {
return [];
}
return resp.users;
}
121 changes: 121 additions & 0 deletions website/script/recent_submissions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
$(function() {
var submissionTable = {
$alternateMessage: $("#noBotsMessage"),
$panel: $("#submissionPanel"),
$table: $("#submissionTable"),
$tableBody: $("#submissionTableBody"),
lastSubmissionTime: null,
init: function() {
var submissions = getRecentSubmissions();
submissions = this.prepSubmissions(submissions);
this.lastSubmissionTime = submissions[0].compileTime;

var schedCutoff = submissions.length > 1 ? 1 : 0;
var lastTime = submissions[0].date.valueOf();
while (schedCutoff < 15 &&
schedCutoff < submissions.length - 2 &&
lastTime - submissions[schedCutoff].date.valueOf() < 60000) {
schedCutoff += 1;
}

this.render(submissions.slice(schedCutoff));
var delay = 45000;
if(schedCutoff > 0) {
delay = this.scheduleSubmissions(submissions.slice(0, schedCutoff));
}
window.setTimeout(this.loadMore.bind(this), delay);
},
prepSubmissions: function(submissions) {
submissions.forEach(function(sub) {
if(sub.compileTime) {
var dateComponents = sub.compileTime.split(/[- :]/);
sub.date = new Date(Date.UTC(dateComponents[0], dateComponents[1]-1, dateComponents[2], dateComponents[3], dateComponents[4], dateComponents[5]));
} else {
sub.date = new Date(0);
}
if(sub.numSubmissions > 1) {
var history = getHistories(sub.userID);
if(history.length > 0) {
sub.lastRank = history[0].lastRank;
} else {
// This should only occur if there was a server error
// during the compilation posting.
sub.lastRank = 'Missing';
}
} else {
sub.lastRank = 'None';
}
});
return submissions;
},
render: function(submissions) {
if(submissions.length == 0) {
this.$alternateMessage.css("display", "block");
this.$panel.css("display", "none");
} else {
this.$tableBody.empty();
for(var a = 0; a < submissions.length; a++) {
this.$tableBody.append(this.getTableRow(submissions[a]));
}
}
},
getTableRow: function(user) {
var $row = $("<tr><td>"+user.date.toLocaleTimeString()+"</td><td><a href='user.php?userID="+user.userID+"'><img src='https://avatars1.githubusercontent.com/u/"+user.oauthID+"?s=20' style='border-radius: 2px; width: 20px; height: 20px; margin: 2px'>"+user.username+"</a></td><td>"+user.lastRank+"</td><td>"+user.language+"</td><td>"+user.numSubmissions+"</td></tr>");
return $row;
},
insertSubmission: function(submission) {
var $newrow = this.getTableRow(submission);
$newrow.children('td').css({"padding": "0"}).wrapInner('<div>');
$newrow.find("td > div").css({"padding": "8px"}).hide();
$newrow.prependTo(this.$tableBody)
$newrow.find("td > div").slideDown(800);

// Check for and remove submissions if there are more than 50
var $subrows = this.$tableBody.children("tr");
for (i = $subrows.length-1; i > 50; i--) {
$subrows[i].remove();
}
},
scheduleSubmissions: function(submissions) {
var last = submissions[submissions.length-1].date;
var nextSlot = 0;
var timeMultiple = 1;
var span = submissions[0].date.valueOf() - last.valueOf();
if(span < 55000) {
timeMultiple = 55000 / Math.max(span, 1);
}
for (i=submissions.length-1; i>=0; i--) {
var iSFunc = this.insertSubmission.bind(this);
function iSFactory(submission) {
return function() {
iSFunc(submission);
}
}
var callback = iSFactory(submissions[i]);
var delay = (submissions[i].date.valueOf() - last.valueOf()) * timeMultiple;
delay = Math.max(delay, nextSlot);
nextSlot = delay + 2000;
window.setTimeout(callback, delay);
}
console.log("Scheduled "+submissions.length+" subs for display in "+delay/1000);
return delay;
},
loadMore: function() {
var newsubs = getRecentSubmissions(this.lastSubmissionTime);
if(newsubs.length == 0) {
console.log("No more submissions available.");
window.setTimeout(this.loadMore.bind(this), 60000);
return
}
newsubs = this.prepSubmissions(newsubs);
var nextGet = this.scheduleSubmissions(newsubs);
nextGet = Math.max(nextGet, 60000);
this.lastSubmissionTime = newsubs[0].compileTime;

console.log("Next get in "+nextGet/1000);
window.setTimeout(this.loadMore.bind(this), nextGet);
}
}

submissionTable.init();
})
25 changes: 23 additions & 2 deletions website/script/user.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,18 @@ $(function() {
if(this.user['organization'] != 'Other') {
this.$secondaryInfo.append($("<span>Member of <a href='leaderboard.php?field=organization&heading="+encodeURIComponent(this.user['organization'])+"&value="+encodeURIComponent(this.user['organization'])+"'>"+this.user['organization']+ "</a></span>"));
this.$secondaryInfo.append($("<br>"));
}
}
if(this.user['compileTime']) {
var dateComponents = this.user['compileTime'].split(/[- :]/);
var date = new Date(Date.UTC(dateComponents[0], dateComponents[1]-1, dateComponents[2], dateComponents[3], dateComponents[4], dateComponents[5]));
var uploadDateStr = date.toLocaleDateString();
if(date.getTime() > Date.now() - (24 * 60 * 60 * 1000)) {
uploadDateStr = date.toLocaleTimeString();
}
this.$secondaryInfo.append($("<span>Uploaded at "+uploadDateStr+"</span>"));
this.$secondaryInfo.append($("<br>"));
}

this.$secondaryInfo.append($("<span>"+this.user['numSubmissions']+" "+(parseInt(this.user['numSubmissions']) == 1 ? "bot" : "bots")+" submitted</span>"));
this.$secondaryInfo.append($("<br>"));
this.$secondaryInfo.append($("<span>"+this.user['numGames']+" games played</span>"));
Expand All @@ -54,7 +65,17 @@ $(function() {
}
},
getTableRow: function(history) {
return "<tr><td>"+this.name+" v"+history.versionNumber+"</td><td>"+history.lastRank+" of "+history.lastNumPlayers+"</td><td>"+(history.lastNumGames != null ? history.lastNumGames : "Not Recorded")+"</td></tr>";
var uploadDateStr = "Unknown";
if(history.compileTime) {
var dateComponents = history.compileTime.split(/[- :]/);
var date = new Date(Date.UTC(dateComponents[0], dateComponents[1]-1, dateComponents[2], dateComponents[3], dateComponents[4], dateComponents[5]));
if(date.getTime() > Date.now() - (24 * 60 * 60 * 1000)) {
uploadDateStr = date.toLocaleTimeString();
} else {
uploadDateStr = date.toLocaleDateString();
}
}
return "<tr><td>"+this.name+" v"+history.versionNumber+"</td><td>"+uploadDateStr+"</td><td>"+history.lastRank+" of "+history.lastNumPlayers+"</td><td>"+(history.lastNumGames != null ? history.lastNumGames : "Not Recorded")+"</td></tr>";
}
}

Expand Down
2 changes: 2 additions & 0 deletions website/sql/schema.sql
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ CREATE TABLE `User` (
`numSubmissions` smallint(5) NOT NULL DEFAULT 0,
`numGames` smallint(5) NOT NULL DEFAULT 0,
`creationTime` datetime DEFAULT CURRENT_TIMESTAMP,
`compileTime` datetime,
`updateTime` datetime ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`userID`)
) ENGINE=InnoDB AUTO_INCREMENT=1000 DEFAULT CHARSET=latin1;
Expand All @@ -96,6 +97,7 @@ DROP TABLE IF EXISTS `UserHistory`;
CREATE TABLE `UserHistory` (
`userID` mediumint(8) unsigned NOT NULL,
`versionNumber` smallint(5) NOT NULL,
`compileTime` datetime,
`lastRank` smallint(5) NOT NULL,
`lastNumPlayers` smallint(5) NOT NULL,
`lastNumGames` smallint(5) DEFAULT NULL,
Expand Down
1 change: 1 addition & 0 deletions website/user.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
<thead>
<tr id="historyTableHeader">
<th>Version</th>
<th>Uploaded</th>
<th>Final Ranking</th>
<th>Games Played</th>
</tr>
Expand Down