Implement problem viewing and problem submitting
This commit is contained in:
parent
bc6c1247e1
commit
34fe70600b
5 changed files with 110 additions and 23 deletions
|
@ -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):
|
||||||
|
|
|
@ -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():
|
||||||
|
|
|
@ -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 = {};
|
||||||
|
|
|
@ -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>
|
||||||
|
|
Loading…
Reference in a new issue