Skip to content

Commit

Permalink
Question interface (#134)
Browse files Browse the repository at this point in the history
* User Submission History and User Stats

User Submission History and User Stats

* Updated to include new db changes and user specific data

Updated to include new db changes and user specific data

* Updated Code

Updated Code

* Updated as per comments

Updated to check user session cookie, get count from already read database and directly convert to list

* Updated to handle Session changes

Updated to handle statsitics even if the session changes

* Updated as per @rishabhKalakoti and @ theSage21 comments

Updated as per @rishabhKalakoti and @ theSage21 comments

* Formatted code

Formatted code

* Included enchancement to submit questions through the web interface

Included enchancement to submit questions through the web interface

* Updated to remove the existing table and replace it with the new table

Updated to remove the existing table and replace it with the new table

* Updated as per changes

Updated to  move the dummy code to another file
Updated to add proper exceptions
Upudated to adddeafult date/time
Updated to refer session variable directly

* Updated to add support for adding Contests

Updated to add support for adding Contests

* Updated insert_dummy.py file

Updated file to populate test data without database call and directly through POST method
  • Loading branch information
rsvarma95 authored and theSage21 committed Jun 3, 2019
1 parent bd2336d commit 67730ed
Show file tree
Hide file tree
Showing 8 changed files with 313 additions and 60 deletions.
70 changes: 70 additions & 0 deletions insert_dummy.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import requests
import datetime
import os


path = os.path.abspath(__file__)
dir_path = os.path.dirname(path)
question_dir = "files/questions"

with requests.Session() as session:
register = session.post(
"http://localhost:8080/register", data={"username": "test", "password": "test"}
)

login = session.post(
"http://localhost:8080/login", data={"username": "test", "password": "test"}
)

for i in range(1, 7, 1):
Question1 = session.post(
"http://localhost:8080/questionInput",
files={
"question": open(
os.path.join(question_dir, str(i), "inputs.txt"), "rb"
),
"answer": open(os.path.join(question_dir, str(i), "output.txt"), "rb"),
},
data={"statement": str(i)},
)

Contest1 = session.post(
"http://localhost:8080/contestInput",
data={
"code": "PRACTICE",
"description": "practice questions",
"start_time": datetime.datetime(day=1, month=1, year=1),
"end_time": datetime.datetime(day=1, month=1, year=9999),
"selection": [1, 2],
},
)
Contest2 = session.post(
"http://localhost:8080/contestInput",
data={
"code": "PASTCONTEST",
"description": "somewhere in the past",
"start_time": datetime.datetime(day=1, month=11, year=2018),
"end_time": datetime.datetime(day=1, month=12, year=2018),
"selection": [1, 2],
},
)
Contest3 = session.post(
"http://localhost:8080/contestInput",
data={
"code": "ONGOINGCONTEST",
"description": "somewhere in the present",
"start_time": datetime.datetime(day=1, month=4, year=2019),
"end_time": datetime.datetime(day=1, month=6, year=2019),
"selection": [3, 4],
},
)
Contest4 = session.post(
"http://localhost:8080/contestInput",
data={
"code": "FUTURECONTEST",
"description": "somewhere in the future",
"start_time": datetime.datetime(day=1, month=1, year=2020),
"end_time": datetime.datetime(day=1, month=10, year=2020),
"selection": [5, 6],
},
)
174 changes: 116 additions & 58 deletions server.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,19 @@ class Contest(Model):
description = CharField()
start_time = DateTimeField()
end_time = DateTimeField()
creator = ForeignKeyField(User)
created_date_time = DateTimeField(default=datetime.datetime.now)

class Meta:
database = db


class Question(Model):
q_no = IntegerField(unique=True)
test_case_input = TextField()
test_case_output = TextField()
question_statement = CharField()
author = ForeignKeyField(User)
created_date_time = DateTimeField(default=datetime.datetime.now)

class Meta:
database = db
Expand Down Expand Up @@ -73,50 +78,6 @@ class Meta:
db.connect()
db.create_tables([User, Session, Submission, ContestProblems, Contest, Question])

# dummy contest data
practiceContest = Contest.get_or_create(
code="PRACTICE",
description="practice questions",
start_time=datetime.datetime(day=1, month=1, year=1),
end_time=datetime.datetime(day=1, month=1, year=9999),
)
pastContest = Contest.get_or_create(
code="PASTCONTEST",
description="somewhere in the past",
start_time=datetime.datetime(day=1, month=11, year=2018),
end_time=datetime.datetime(day=1, month=12, year=2018),
)
ongoingContest = Contest.get_or_create(
code="ONGOINGCONTEST",
description="somewhere in the present",
start_time=datetime.datetime(day=1, month=4, year=2019),
end_time=datetime.datetime(day=1, month=6, year=2019),
)
futureContest = Contest.get_or_create(
code="FUTURECONTEST",
description="somewhere in the future",
start_time=datetime.datetime(day=1, month=1, year=2020),
end_time=datetime.datetime(day=1, month=10, year=2020),
)

test = User.get_or_create(username="test", password="test")

q1 = Question.get_or_create(q_no=1, author=test[0])
q2 = Question.get_or_create(q_no=2, author=test[0])
q3 = Question.get_or_create(q_no=3, author=test[0])
q4 = Question.get_or_create(q_no=4, author=test[0])
q5 = Question.get_or_create(q_no=5, author=test[0])
q6 = Question.get_or_create(q_no=6, author=test[0])

ContestProblems.get_or_create(contest=practiceContest[0], question=q1[0])
ContestProblems.get_or_create(contest=practiceContest[0], question=q2[0])
ContestProblems.get_or_create(contest=pastContest[0], question=q1[0])
ContestProblems.get_or_create(contest=pastContest[0], question=q2[0])
ContestProblems.get_or_create(contest=ongoingContest[0], question=q3[0])
ContestProblems.get_or_create(contest=ongoingContest[0], question=q4[0])
ContestProblems.get_or_create(contest=futureContest[0], question=q5[0])
ContestProblems.get_or_create(contest=futureContest[0], question=q6[0])


def login_required(function):
def login_redirect(*args, **kwargs):
Expand Down Expand Up @@ -175,22 +136,106 @@ def statistics():
)


@app.get("/addQuestion")
@login_required
def addQuestion():
return bottle.template("addQuestion.html")


@app.post("/questionInput")
@login_required
def questionInput():
userid = bottle.request.session.user
uploaded_question = bottle.request.files.get("question").file.read()
uploaded_answer = bottle.request.files.get("answer").file.read()
uploaded_statement = bottle.request.forms.get("statement")
try:
Question.create(
test_case_input=uploaded_question,
test_case_output=uploaded_answer,
question_statement=uploaded_statement,
author=userid,
)
except Exception as e:
bottle.abort(500, str(e))
question_bank = (
Question.select(
Question.id,
Question.test_case_input,
Question.question_statement,
User.username,
Question.created_date_time,
)
.join(User, on=(Question.author == User.id))
.order_by(Question.created_date_time.desc())
.dicts()
)
return bottle.template("questionBank.html", question_bank=question_bank)


@app.get("/addContest")
@login_required
def addContest():
question_bank = (
Question.select(
Question.id,
Question.test_case_input,
Question.question_statement,
User.username,
Question.created_date_time,
)
.join(User, on=(Question.author == User.id))
.order_by(Question.created_date_time.desc())
.dicts()
)
return bottle.template("addContest.html", question_bank=question_bank)


@app.post("/contestInput")
@login_required
def contestInput():
userid = bottle.request.session.user
code = bottle.request.forms.get("code")
description = bottle.request.forms.get("description")
start_time = bottle.request.forms.get("start_time")
end_time = bottle.request.forms.get("end_time")
selection = bottle.request.forms.getall("selection")
try:
contest = Contest.get_or_create(
code=code,
description=description,
start_time=start_time,
end_time=end_time,
creator=userid,
)
except Exception as e:
bottle.abort(500, str(e))
for questions in selection:
ContestProblems.create(contest=contest[0], question=questions)
contests = Contest.select().order_by(Contest.start_time)
return bottle.template("dashboard.html", contests=contests)


@app.get("/contest/<code>/<number>")
@login_required
def question(code, number):
if (
not ContestProblems.select()
.where((Contest.code == code) & (Question.q_no == int(number)))
.where((Contest.code == code) & (Question.id == int(number)))
.join(Contest, on=(ContestProblems.contest == Contest.id))
.join(Question, on=(ContestProblems.question == Question.q_no))
.join(Question, on=(ContestProblems.question == Question.id))
.exists()
):
return bottle.abort(404, "no such contest problem")
contest = Contest.get(Contest.code == code)
if contest.start_time > datetime.datetime.now():
return "The contest had not started yet."
with open(os.path.join(question_dir, number, "statement.txt"), "rb") as fl:
statement = fl.read()
statement = (
Question.select(Question.question_statement)
.where(Question.id == number)
.dicts()
.get()
)
return bottle.template(
"question.html", question_number=number, contest=code, question=statement
)
Expand All @@ -208,9 +253,18 @@ def contest(code):
return bottle.template("contest.html", contest=contest, questions=contest.questions)


@app.get("/question/<path:path>")
def download(path):
return bottle.static_file(path, root=question_dir)
@app.get("/question/<id>")
def download(id):
try:
question_result = (
Question.select(Question.test_case_input)
.where(Question.id == id)
.dicts()
.get()
)
except:
bottle.abort(404, "No such question")
return question_result["test_case_input"]


@app.get("/static/<filepath:path>")
Expand Down Expand Up @@ -323,24 +377,28 @@ def file_upload(code, number):
try:
contestProblem = ContestProblems.get(
ContestProblems.contest == Contest.get(Contest.code == code),
ContestProblems.question == Question.get(Question.q_no == int(number)),
ContestProblems.question == Question.get(Question.id == int(number)),
)
except:
return bottle.abort(404, "no such contest problem")
user = Session.get(Session.token == bottle.request.get_cookie("s_id")).user
time = datetime.datetime.now()
uploaded = bottle.request.files.get("upload").file.read()
with open(os.path.join(question_dir, number, "output.txt"), "rb") as fl:
expected = fl.read()
expected = expected.strip()
expected = (
Question.select(Question.test_case_output)
.where(Question.id == number)
.dicts()
.get()
)
expected = expected["test_case_output"]
uploaded = uploaded.strip()
ans = uploaded == expected
try:
Submission.create(
user=user, contestProblem=contestProblem, time=time, is_correct=ans
)
except:
bottle.abort(500, "Error in inserting submission to database.")
except Exception as e:
bottle.abort(500, str(e))
if not ans:
return "Wrong Answer!!"
else:
Expand Down
58 changes: 58 additions & 0 deletions views/addContest.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
% include('base.html', title="Add Contest")
<body>
<header class="text-center">
<h1>Contest Creation Page</h1>
</header>
<div class="container">
</br>
</br>
<form action="/contestInput" method = "post" enctype = "multipart/form-data">
Contest Code : <br/>
<input type="text" name="code" required /><br/><br/>
Contest Description : <br/>
<textarea name="description" rows = "3" cols = "80" required>Enter Description</textarea>
<br/><br/>
Start Time : <br/>
<input name="start_time" type='date'/><br/><br/>
End Time : <br/>
<input name="end_time" type='date'/>
<br/>
<br/>
</div>
<div class="container text-center">
<table class="table">
<thead>
<tr>
<th class="d-flex justify-content-center justify-content-center">List Of Questions</th>
</tr>
</thead>
</table>
<table class="table">
<tbody style="height:20rem;display:inline-block;overflow-y:scroll">
<tr style="font-weight:bold;">
<td style="padding-right:10rem">Question</td>
<td style="padding-right:6rem">Question Statement</td>
<td style="padding-right:10rem">Author</td>
<td style="padding-right:8rem">Time submitted</td>
<td style="padding-right:8rem">Selection</td>
</tr>
% for question in question_bank :
<tr>
<td style="padding-right:10rem">
<a href="/question/{{question['id']}}" role="button" class="btn btn-primary">
Download Question
</a>
</td>
<td name="statement" style="padding-right:10rem">{{question["question_statement"]}}</td>
<td style="padding-right:10rem">{{question["username"]}}</td>
<td style="padding-right:8rem">{{question["created_date_time"].strftime("%d-%m-%Y %H:%M")}}</td>
<td style="padding-right:8rem"><input type="checkbox" name="selection" value="{{question['id']}}"></td>
</tr>
% end
</tbody>
</table>
<button class="btn btn-primary" type="submit">Upload</button>
</form>
</div>
</body>

20 changes: 20 additions & 0 deletions views/addQuestion.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
% include('base.html', title="Add Question")
<body>
<header class="text-center">
<h1>Question Upload Page</h1>
</header>
<div class="container">
</br>
</br>
<form action="/questionInput" method = "post" enctype = "multipart/form-data">Question Upload : <br/>
<input type="file" name="question" required /><br/><br/>
Answer Upload : <br/>
<input type="file" name="answer" required /><br/><br/>
Statement : <br/>
<textarea name="statement" rows = "3" cols = "80" required>Enter Statement</textarea>
<br/>
<br/>
<button class="btn btn-primary" type="submit">Upload</button>
</form>
</div>
</body>
Loading

0 comments on commit 67730ed

Please sign in to comment.