Implement problem viewing and problem submitting

This commit is contained in:
James Wang 2016-04-16 22:15:57 -04:00
parent bc6c1247e1
commit 34fe70600b
No known key found for this signature in database
GPG key ID: 5B80C0B3F263CD5B
5 changed files with 110 additions and 23 deletions

View file

@ -166,9 +166,8 @@ class Files(db.Model):
self.location = location self.location = location
class Solves(db.Model): class Solves(db.Model):
__table_args__ = (db.UniqueConstraint("pid", "tid"), {})
sid = db.Column(db.Integer, primary_key=True) sid = db.Column(db.Integer, primary_key=True)
pid = db.Column(db.Integer) pid = db.Column(db.String(32))
tid = db.Column(db.Integer) tid = db.Column(db.Integer)
date = db.Column(db.Integer, default=utils.get_time_since_epoch()) date = db.Column(db.Integer, default=utils.get_time_since_epoch())
correct = db.Column(db.Boolean) correct = db.Column(db.Boolean)
@ -214,7 +213,7 @@ class TeamInvitations(db.Model):
class Settings(db.Model): class Settings(db.Model):
sid = db.Column(db.Integer, primary_key=True) sid = db.Column(db.Integer, primary_key=True)
key = db.Column(db.Text, unique=True) key = db.Column(db.Text)
value = db.Column(db.Text) value = db.Column(db.Text)
def __init__(self, key, value): def __init__(self, key, value):

View file

@ -1,4 +1,5 @@
import hashlib import hashlib
import imp
import logger import logger
import os import os
import shutil import shutil
@ -115,38 +116,51 @@ def problem_submit():
problem = Problems.query.filter_by(pid=pid).first() problem = Problems.query.filter_by(pid=pid).first()
team = Teams.query.filter_by(tid=tid).first() team = Teams.query.filter_by(tid=tid).first()
solved = Solves.query.filter_by(pid=pid, tid=tid, correct=1).first()
if solved:
raise WebException("You already solved this problem.")
if problem: if problem:
if flag == problem.flag: grader = imp.load_source("grader.py", problem.grader)
solve = Solves(pid, tid) if grader.grade(flag):
team.score += problem.value solve = Solves(pid, tid, flag, True)
problem.solves += 1
db.session.add(solve) db.session.add(solve)
db.session.add(team)
db.session.add(problem)
db.session.commit() db.session.commit()
logger.log(__name__, logger.WARNING, "%s has solved %s by submitting %s" % (team.name, problem.title, flag)) logger.log(__name__, "%s has solved %s by submitting %s" % (team.teamname, problem.title, flag), level=logger.WARNING)
return { "success": 1, "message": "Correct!" } return { "success": 1, "message": "Correct!" }
else: else:
logger.log(__name__, logger.WARNING, "%s has incorrectly submitted %s to %s" % (team.name, flag, problem.title)) solve = Solves(pid, tid, flag, False)
db.session.add(solve)
db.session.commit()
logger.log(__name__, "%s has incorrectly submitted %s to %s" % (team.teamname, flag, problem.title), level=logger.WARNING)
raise WebException("Incorrect.") raise WebException("Incorrect.")
else: else:
raise WebException("Problem does not exist!") raise WebException("Problem does not exist!")
@blueprint.route("/data", methods=["POST"]) @blueprint.route("/data", methods=["GET"])
#@api_wrapper # Disable atm due to json serialization issues: will fix
@login_required @login_required
@api_wrapper
def problem_data(): def problem_data():
problems = Problems.query.add_columns("pid", "name", "category", "description", "hint", "value", "solves").order_by(Problems.value).filter_by(disabled=False).all() problems = Problems.query.order_by(Problems.value).all()
jason = [] problems_return = []
for problem in problems: for problem in problems:
problem_files = [ str(_file.location) for _file in Files.query.filter_by(pid=int(problem.pid)).all() ] solves = Solves.query.filter_by(pid=problem.pid, correct=1).count()
jason.append({"pid": problem[1], "title": problem[2] ,"category": problem[3], "description": problem[4], "hint": problem[5], "value": problem[6], "solves": problem[7], "files": problem_files}) solved = Solves.query.filter_by(pid=problem.pid, tid=session.get("tid", None), correct=1)
solved = ["Solved", "Unsolved"][solved is None]
return jsonify(data=jason) problems_return.append({
"pid": problem.pid,
"title": problem.title,
"category": problem.category,
"description": problem.description,
"hint": problem.hint,
"value": problem.value,
"solves": solves,
"solved": solved
})
return { "success": 1, "problems": problems_return }
def insert_problem(data, force=False): def insert_problem(data, force=False):
with app.app_context(): with app.app_context():

View file

@ -48,6 +48,10 @@ app.config(function($routeProvider, $locationProvider) {
templateUrl: "pages/settings.html", templateUrl: "pages/settings.html",
controller: "settingsController" controller: "settingsController"
}) })
.when("/problems", {
templateUrl: "pages/problems.html",
controller: "problemsController"
})
.when("/forgot", { .when("/forgot", {
templateUrl: "pages/forgot.html", templateUrl: "pages/forgot.html",
controller: "resetController" controller: "resetController"
@ -271,6 +275,16 @@ app.controller("settingsController", ["$controller", "$scope", "$http", function
}); });
}]); }]);
app.controller("problemsController", ["$controller", "$scope", "$http", function($controller, $scope, $http) {
$controller("loginController", { $scope: $scope });
api_call("GET", "/api/problem/data", {}, function(result) {
if (result["success"] == 1) {
$scope.problems = result["problems"];
}
$scope.$apply();
});
}]);
$.fn.serializeObject = function() { $.fn.serializeObject = function() {
var a, o; var a, o;
o = {}; o = {};

View file

@ -5,7 +5,67 @@
3) remove these instructions (:P) 3) remove these instructions (:P)
--> -->
<div class="fade_in"> <div class="fade_in">
<h1 class="heading1 text-center">Problems</h1> <h1 class="text-center">Problems</h1>
<div id="problems"></div> <div ng-repeat="problem in problems">
<div class="panel-group">
<div class="panel panel-default">
<div class="panel-heading" data-toggle="collapse" data-target="#{{ problem['pid'] }}_body">
<h4 class="panel-title">
{{ problem["title"] }} {{ problem["value"] }} points
<div class="pull-right">{{ problem["category"] }} - {{ problem["solved"] }} ({{ problem["solves"] }} {{ problem["solves"] === 1 ? "solve" : "solves" }})</div>
</h4>
</div>
<div id="{{ problem['pid'] }}_body" class="panel-collapse collapse">
<div class="panel-body">
<div hidden id="{{ problem['pid'] }}_hint">{{ problem['hint'] }}</div>
<div hidden id="{{ problem['pid'] }}_status"/>
{{ problem["description"] }}
</div>
<form id="{{ problem['pid'] }}_form" class="horizontal-form" onsubmit="submit_problem(this.id); return false;">
<div class="input-group">
<input hidden name="pid" value="{{ problem['pid'] }}"/>
<input class="form-control" name="flag" placeholder="Flag"/>
<span class="input-group-btn">
<input onclick="toggle_hint(this.closest('form').id); return false;" type="button" class="btn btn-success" value="Hint"/>
</span>
<span class="input-group-btn">
<input type="submit" class="btn btn-success" value="Submit"/>
</span>
</div>
</form>
</div>
</div>
</div>
</div>
</div> </div>
<script src="js/problems.js">
<script>
var toggle_hint = function(form) {
pid = form.split("_")[0];
$("#" + pid + "_hint").slideToggle("fast", function() {});
}
var submit_problem = function(form) {
var input = "#" + form + " input";
var data = $("#" + form).serializeObject();
pid = data["pid"];
$(input).attr("disabled", "disabed");
api_call("POST", "/api/problem/submit", data, function(result) {
if (result["success"] == 1) {
display_message(pid + "_status", "success", result["message"], function() {
$(input).removeAttr("disabled");
});
} else {
display_message(pid + "_status", "danger", result["message"], function() {
$(input).removeAttr("disabled");
});
}
console.log(result["error"]);
}, function(jqXHR, status, error) {
var result = jqXHR["responseText"];
display_message(pid + "_status", "danger", "Error " + jqXHR["status"] + ": " + result["message"], function() {
$(input).removeAttr("disabled");
});
});
}
</script>