From 2f9131383e028a01e67cc7ea2c41d5a6c5a3216b Mon Sep 17 00:00:00 2001 From: Rishabh Kalakoti Date: Sun, 19 May 2019 11:16:55 +0530 Subject: [PATCH 01/17] databse for users --- .vscode/settings.json | 3 ++ Pipfile | 1 + Pipfile.lock | 64 +++++++++++++++++++++++++----------------- data.db | Bin 0 -> 12288 bytes server.py | 56 +++++++++++++++++++++++++----------- 5 files changed, 82 insertions(+), 42 deletions(-) create mode 100644 .vscode/settings.json create mode 100644 data.db diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..83ff203 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "python.pythonPath": "/home/percy/.local/share/virtualenvs/PyJudge-lGhU2Pov/bin/python" +} \ No newline at end of file diff --git a/Pipfile b/Pipfile index 67ada83..d7b51a6 100644 --- a/Pipfile +++ b/Pipfile @@ -8,6 +8,7 @@ bottle = "*" pip = "==18.0" pre-commit = "*" black = "*" +peewee = "*" [dev-packages] requests = "*" diff --git a/Pipfile.lock b/Pipfile.lock index c853808..464d309 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "609955005164d92d175b8f2b4f17a281870e7b835b9267bc3e9b79ebaef15356" + "sha256": "c2d78e0bf5fe824233f66af401871c1cab11b264303260a17b277bac99bddaa6" }, "pipfile-spec": 6, "requires": { @@ -69,17 +69,17 @@ }, "identify": { "hashes": [ - "sha256:244e7864ef59f0c7c50c6db73f58564151d91345cd9b76ed793458953578cadd", - "sha256:8ff062f90ad4b09cfe79b5dfb7a12e40f19d2e68a5c9598a49be45f16aba7171" + "sha256:432c548d6138cb57a3d8f62f079a025a29b8ae34a50dd3b496bbf661818f2bc0", + "sha256:d4401d60bf1938aa3074a352a5cc9044107edf11a6fedd3a1db172c141619b81" ], - "version": "==1.4.1" + "version": "==1.4.3" }, "importlib-metadata": { "hashes": [ - "sha256:46fc60c34b6ed7547e2a723fc8de6dc2e3a1173f8423246b3ce497f064e9c3de", - "sha256:bc136180e961875af88b1ab85b4009f4f1278f8396a60526c0009f503a1a96ca" + "sha256:2f2e54cbf6b06b16351e4c40a6adb0860cab6cfb95a0c0fcb58bb789c4b450f5", + "sha256:37bbea81dec44d1ff72d58a1b5c1599a9f3436537f33e9e26f276610064c4830" ], - "version": "==0.9" + "version": "==0.12" }, "importlib-resources": { "hashes": [ @@ -95,13 +95,20 @@ ], "version": "==1.3.3" }, + "peewee": { + "hashes": [ + "sha256:f0249be468e3b119a8ad83f686e7fe161303197e0534e3cdff8fa5a5417c01a5" + ], + "index": "pypi", + "version": "==3.9.5" + }, "pre-commit": { "hashes": [ - "sha256:75a9110eae00d009c913616c0fc8a6a02e7716c4a29a14cac9b313d2c7338ab0", - "sha256:f882c65316eb5b705fe4613e92a7c91055c1800102e4d291cfd18912ec9cf90e" + "sha256:6ca409d1f22d444af427fb023a33ca8b69625d508a50e1b7eaabd59247c93043", + "sha256:94dd519597f5bff06a4b0df194a79c524b78f4b1534c1ce63241a9d4fb23b926" ], "index": "pypi", - "version": "==1.15.1" + "version": "==1.16.1" }, "pyyaml": { "hashes": [ @@ -135,17 +142,17 @@ }, "virtualenv": { "hashes": [ - "sha256:6aebaf4dd2568a0094225ebbca987859e369e3e5c22dc7d52e5406d504890417", - "sha256:984d7e607b0a5d1329425dd8845bd971b957424b5ba664729fab51ab8c11bc39" + "sha256:99acaf1e35c7ccf9763db9ba2accbca2f4254d61d1912c5ee364f9cc4a8942a0", + "sha256:fe51cdbf04e5d8152af06c075404745a7419de27495a83f0d72518ad50be3ce8" ], - "version": "==16.4.3" + "version": "==16.6.0" }, "zipp": { "hashes": [ - "sha256:55ca87266c38af6658b84db8cfb7343cdb0bf275f93c7afaea0d8e7a209c7478", - "sha256:682b3e1c62b7026afe24eadf6be579fb45fec54c07ea218bded8092af07a68c4" + "sha256:46dfd547d9ccbf8bdc26ecea52818046bb28509f12bb6a0de1cd66ab06e9a9be", + "sha256:d7ac25f895fb65bff937b381353c14eb1fa23d35f40abd72a5342cd57eb57fd1" ], - "version": "==0.3.3" + "version": "==0.5.0" } }, "develop": { @@ -194,10 +201,10 @@ }, "pluggy": { "hashes": [ - "sha256:19ecf9ce9db2fce065a7a0586e07cfb4ac8614fe96edf628a264b1c70116cf8f", - "sha256:84d306a647cc805219916e62aab89caa97a33a1dd8c342e87a37f91073cd4746" + "sha256:25a1bc1d148c9a640211872b4ff859878d422bccb59c9965e04eed468a0aa180", + "sha256:964cedd2b27c492fbf0b7f58b3284a09cf7f99b0f715941fb24a439b3af1bd1a" ], - "version": "==0.9.0" + "version": "==0.11.0" }, "py": { "hashes": [ @@ -208,11 +215,11 @@ }, "pytest": { "hashes": [ - "sha256:13c5e9fb5ec5179995e9357111ab089af350d788cbc944c628f3cde72285809b", - "sha256:f21d2f1fb8200830dcbb5d8ec466a9c9120e20d8b53c7585d180125cce1d297a" + "sha256:1a8aa4fa958f8f451ac5441f3ac130d9fc86ea38780dd2715e6d5c5882700b24", + "sha256:b8bf138592384bd4e87338cb0f256bf5f615398a649d4bd83915f0e4047a5ca6" ], "index": "pypi", - "version": "==4.4.0" + "version": "==4.5.0" }, "requests": { "hashes": [ @@ -231,10 +238,17 @@ }, "urllib3": { "hashes": [ - "sha256:61bf29cada3fc2fbefad4fdf059ea4bd1b4a86d2b6d15e1c7c0b582b9752fe39", - "sha256:de9529817c93f27c8ccbfead6985011db27bd0ddfcdb2d86f3f663385c6a9c22" + "sha256:2393a695cd12afedd0dcb26fe5d50d0cf248e5a66f75dbd89a3d4eb333a61af4", + "sha256:a637e5fae88995b256e3409dc4d52c2e2e0ba32c42a6365fee8bbd2238de3cfb" + ], + "version": "==1.24.3" + }, + "wcwidth": { + "hashes": [ + "sha256:3df37372226d6e63e1b1e1eda15c594bca98a22d33a23832a90998faa96bc65e", + "sha256:f4ebe71925af7b40a864553f761ed559b43544f8f71746c2d756c7fe788ade7c" ], - "version": "==1.24.1" + "version": "==0.1.7" } } } diff --git a/data.db b/data.db new file mode 100644 index 0000000000000000000000000000000000000000..ba897f52e0a7e612e5174f87517ee7925625ec41 GIT binary patch literal 12288 zcmeI$%}T>S5C`zxq)-$jMJc@$9CERx;z8-%SQjnE)W%fWlcY4#rAyC=UIU4p@nC&JKwfWBTe*Qy!Yih1EKn_=ojR zOP%dipElI4W^6GdR0#nA2tWV=5P$##AOHafKmY;|_#Fa$tytM9^97f)QSfk^1o3s2 zW_}oCv)*!r)Nz)tOseHu*JO)Rx9ps@ z>gZWVws=1$N2coTi4)e;tBH=daq2nav`0uX=z1Rwwb2tWV=5P$##{;WWi7g%FEmdV&3jwk-q zpG2vY;WWCFGnuZddvW81seyn11Rwwb2tWV=5P$##AOHafK;S 0: + return bottle.template( + "home.html", message="Username already exists. Select a different username" + ) + User.create(username=username, password=password) return createSession(username) @@ -257,6 +278,7 @@ def file_upload(code, number): @app.error(404) def error404(error): - return template("error.html" ,errorcode=error.status_code , errorbody = error.body) + return template("error.html", errorcode=error.status_code, errorbody=error.body) + -bottle.run(app, host="localhost", port=8080) \ No newline at end of file +bottle.run(app, host="localhost", port=8080) From 3316416689aab8b9e5e5c3bf8967980fdffb203a Mon Sep 17 00:00:00 2001 From: Rishabh Kalakoti Date: Sun, 19 May 2019 11:18:37 +0530 Subject: [PATCH 02/17] minor update. --- .gitignore | 2 +- .vscode/settings.json | 3 --- server.py | 1 - 3 files changed, 1 insertion(+), 5 deletions(-) delete mode 100644 .vscode/settings.json diff --git a/.gitignore b/.gitignore index 3b01ea3..0040889 100644 --- a/.gitignore +++ b/.gitignore @@ -64,7 +64,7 @@ target/ .idea/ venv/ - +.vscode/ # Folder .pytest_cache diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index 83ff203..0000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "python.pythonPath": "/home/percy/.local/share/virtualenvs/PyJudge-lGhU2Pov/bin/python" -} \ No newline at end of file diff --git a/server.py b/server.py index 9793a2d..6de1c96 100644 --- a/server.py +++ b/server.py @@ -10,7 +10,6 @@ app = bottle.Bottle() database_path = "submission_record.db" -# user_db = "user_record.db" sessions_db = "session_record.db" DATABASE_NAME = "data.db" From 6db515cdcb8868bf43b813d88fcf63574b83c2ba Mon Sep 17 00:00:00 2001 From: Rishabh Kalakoti Date: Sun, 19 May 2019 12:52:10 +0530 Subject: [PATCH 03/17] exists and IntegrityError --- server.py | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/server.py b/server.py index 6de1c96..bf888e7 100644 --- a/server.py +++ b/server.py @@ -211,12 +211,9 @@ def login(): username = bottle.request.forms.get("username") password = bottle.request.forms.get("password") if ( - len( - User.select().where( - (User.username == username) & (User.password == password) - ) - ) - == 0 + not User.select() + .where((User.username == username) & (User.password == password)) + .exists() ): return bottle.template("home.html", message="Invalid credentials.") return createSession(username) @@ -226,11 +223,12 @@ def login(): def register(): username = bottle.request.forms.get("username") password = bottle.request.forms.get("password") - if len(User.select().where(User.username == username)) > 0: + try: + User.create(username=username, password=password) + except IntegrityError: return bottle.template( "home.html", message="Username already exists. Select a different username" ) - User.create(username=username, password=password) return createSession(username) From 46d0458a1b4408859c968332166c8b522dcdf3b2 Mon Sep 17 00:00:00 2001 From: Rishabh Kalakoti Date: Sun, 19 May 2019 15:05:07 +0530 Subject: [PATCH 04/17] session table done --- data.db | Bin 12288 -> 20480 bytes server.py | 28 ++++++++++++++++++---------- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/data.db b/data.db index ba897f52e0a7e612e5174f87517ee7925625ec41..bf3099971b82c4cee513e6c1bc998766b6665002 100644 GIT binary patch delta 274 zcmZojXjs5FL0XWVfq{V)h+%+bqK>gBJAjPQX z#1*9(OEdFQQY(s6i;FY!^Wrm8pe$DBAXmo_SA|eN&%jVu1y4U0*9ZkAgfb-se?K^1 zNkKy?Get?WfSFxfTAH!Zyd*IxCl#s~O0hr<3~_YwaRusBhS&(zsu1QFf delta 56 zcmZozz}S#5L0XWRfq?;pVSs6(jxkVBPi6xzP>6|Nn1Mf+UwE^iz+%45!u)R)0Ou75 A`Tzg` diff --git a/server.py b/server.py index bf888e7..3364ae9 100644 --- a/server.py +++ b/server.py @@ -10,7 +10,6 @@ app = bottle.Bottle() database_path = "submission_record.db" -sessions_db = "session_record.db" DATABASE_NAME = "data.db" @@ -33,8 +32,16 @@ class Meta: database = db +class Session(Model): + id = CharField(unique=True) + username = CharField() + + class Meta: + database = db + + db.connect() -db.create_tables([User]) +db.create_tables([User, Session]) # dummy contests contests["PRACTICE"] = Contest( @@ -188,8 +195,9 @@ def rankings(): def logggedIn(): if not bottle.request.get_cookie("s_id"): return False - with shelve.open(sessions_db) as sessions: - return bottle.request.get_cookie("s_id") in sessions + return ( + Session.select().where(Session.id == bottle.request.get_cookie("s_id")).exists() + ) def createSession(username): @@ -201,8 +209,10 @@ def createSession(username): session_id, expires=datetime.datetime.now() + datetime.timedelta(days=30), ) - with shelve.open(sessions_db) as sessions: - sessions[session_id] = username + try: + Session.create(id=session_id, username=username) + except IntegrityError: + return abort("Error! Please try again.") return bottle.redirect("/dashboard") @@ -234,8 +244,7 @@ def register(): @app.get("/logout") def logout(): - with shelve.open(sessions_db) as sessions: - del sessions[bottle.request.get_cookie("s_id")] + Session.delete().where(Session.id == bottle.request.get_cookie("s_id")).execute() bottle.response.delete_cookie("s_id") return bottle.redirect("/home") @@ -243,8 +252,7 @@ def logout(): @app.post("/check//") @login_required def file_upload(code, number): - with shelve.open(sessions_db) as sessions: - u_name = sessions[bottle.request.get_cookie("s_id")] + u_name = Session.get(Session.id == bottle.request.get_cookie("s_id")).username time = datetime.datetime.now() uploaded = bottle.request.files.get("upload").file.read() expected = questions[number].output From d878c97a1bd476ca30f981a2208bd8d0d7cd43c3 Mon Sep 17 00:00:00 2001 From: Rishabh Kalakoti Date: Sun, 19 May 2019 21:04:45 +0530 Subject: [PATCH 05/17] submissions table. --- .gitignore | 4 +- data.db | Bin 20480 -> 24576 bytes server.py | 109 +++++++++++++++++++++-------------------------------- 3 files changed, 45 insertions(+), 68 deletions(-) diff --git a/.gitignore b/.gitignore index 0040889..7886722 100644 --- a/.gitignore +++ b/.gitignore @@ -68,6 +68,4 @@ venv/ # Folder .pytest_cache -submission_record.db -user_record.db -session_record.db \ No newline at end of file +data.db \ No newline at end of file diff --git a/data.db b/data.db index bf3099971b82c4cee513e6c1bc998766b6665002..6262398029e86cd612703a1480f2f843a00175e4 100644 GIT binary patch delta 688 zcmZozz}Rqrae}lUF9QPu8xX?)>qH%6ab5;JnGGNrR^AW>{yu(dK1belydfJK@9`)^ zu(FG*i!wGcX6B`&R+JW}7R7^zyu{p85Y0B(nBRtxWpV+(2qWv{R{m<6#&TwMaYaSO zX3LVqq@2{^(xlwX;^NHwJOqoyImp#9#8n~0(aFbEK?xx-c{;ymeMx3+s*-{WP(g^N zud9Nee~5x#sE?11f>L2=YHPgI1upXIYe2(PnvvO5)Xdz|(jeI1&(f(h+{Cjg&A2GS4CFj6 zpdv>87YzI_HVZ1;;RoswXEx=;rWzC<%>3yL{KxpG^QQx?h~%%=V`gU%b!3#~1Q}&y zU}&jpV5)0qsbFMa1w!U}76wM<<`zr=L5|KLp3bhiOd$1~IMf>&>lvGy85$VFlv^;e zGiZa97iAV_Bqn8KC*~w(=a*!{Y*K?*WoTq&VyI_qVrXb$3eyU5EffD02L4Cgn|Dp{}Z6sZ}7`-FpDyRq?m-5wb5+^03Z&v1^@s6 delta 230 zcmZoTz}T>Wae}lUI|Bm)D-go~%S0VxQFaDBnGL)^Ar?MA2L4=rVZMcYewzgaZt*e& zvP`z+mtka`9K~/") @login_required -def contest(code, number): +def question(code, number): if not code in contests: return "Contest does not exist" if contests[code].start_time > datetime.datetime.now(): @@ -141,55 +149,36 @@ def server_static(filepath): @app.get("/ranking/") def contest_ranking(code): - with shelve.open(database_path) as submission_record: - order = [ - ( - user, - len( - set( - [ - attempt.question - for attempt in submissions - if ( - attempt.is_correct - and (int(attempt.question) in contests[code].questions) - and attempt.contest == code - and attempt.time <= contests[code].end_time - and attempt.time >= contests[code].start_time - ) - ] - ) - ), - ) - for user, submissions in submission_record.items() - ] - order.sort(key=lambda x: x[1], reverse=True) - order = [entry for entry in order if entry[1] > 0] - order = [(user, score, rank) for rank, (user, score) in enumerate(order, start=1)] + order = ( + Submission.select( + Submission.username, fn.count(Submission.question).alias("score") + ) + .where((Submission.is_correct == True) & (Submission.contest == code)) + .group_by(Submission.username) + .order_by(fn.count(Submission.question).desc()) + ) + order = [(x.username, x.score) for x in order] + order = [ + (username, score, rank) for rank, (username, score) in enumerate(order, start=1) + ] return bottle.template("rankings.html", people=order) @app.get("/ranking") def rankings(): - with shelve.open(database_path) as submission_record: - order = [ - ( - user, - len( - set( - [ - attempt.question - for attempt in submissions - if attempt.is_correct - ] - ) - ), - ) - for user, submissions in submission_record.items() - ] - order.sort(key=lambda x: x[1], reverse=True) - order = [(user, score, rank) for rank, (user, score) in enumerate(order, start=1)] - return template("rankings.html", people=order) + order = ( + Submission.select( + Submission.username, fn.count(Submission.question).alias("score") + ) + .where(Submission.is_correct == True) + .group_by(Submission.username) + .order_by(fn.count(Submission.question).desc()) + ) + order = [(x.username, x.score) for x in order] + order = [ + (username, score, rank) for rank, (username, score) in enumerate(order, start=1) + ] + return bottle.template("rankings.html", people=order) def logggedIn(): @@ -252,29 +241,19 @@ def logout(): @app.post("/check//") @login_required def file_upload(code, number): - u_name = Session.get(Session.id == bottle.request.get_cookie("s_id")).username + username = Session.get(Session.id == bottle.request.get_cookie("s_id")).username time = datetime.datetime.now() uploaded = bottle.request.files.get("upload").file.read() expected = questions[number].output expected = expected.strip() uploaded = uploaded.strip() ans = uploaded == expected - - with shelve.open(database_path) as submission_record: - submissions = ( - [] if u_name not in submission_record else submission_record[u_name] - ) - submissions.append( - Submission( - question=number, - time=time, - output=uploaded, - is_correct=ans, - contest=code, - ) + try: + Submission.create( + username=username, question=number, time=time, contest=code, is_correct=ans ) - submission_record[u_name] = submissions - + except: + abort("Error in inserting submission to database.") if not ans: return "Wrong Answer!!" else: From 0ac8205eaf4f928a1750208f76b51ba32185424c Mon Sep 17 00:00:00 2001 From: Rishabh Kalakoti Date: Sun, 19 May 2019 22:27:17 +0530 Subject: [PATCH 06/17] used tuples. --- data.db | Bin 24576 -> 24576 bytes server.py | 5 ++--- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/data.db b/data.db index 6262398029e86cd612703a1480f2f843a00175e4..fe82144f3e329de3a74e20b790b54d719ca992b8 100644 GIT binary patch delta 90 zcmZoTz}Rqrae_1>-$WT_M!t;+OZ0hI_$?UtkMU3EPv^JTEGVGCudmC(&LHZ@Da%=s uT3ljeU}&jpV5)0qsbFMeWoT(-WT9tnX>MR*84%>?9OCKhx;fo`rUC%&5Eb?S delta 40 wcmZoTz}Rqrae_1>??f4AM&6AHOZ2&z`O_KrkMU3EPv0yk5Xrwe-F~J50QVFN-~a#s diff --git a/server.py b/server.py index 2c46f65..c1cc347 100644 --- a/server.py +++ b/server.py @@ -2,7 +2,6 @@ import os, sys, datetime import string, random from collections import defaultdict, namedtuple -import shelve from peewee import * path = os.path.abspath(__file__) @@ -157,7 +156,7 @@ def contest_ranking(code): .group_by(Submission.username) .order_by(fn.count(Submission.question).desc()) ) - order = [(x.username, x.score) for x in order] + order = list(order.tuples()) order = [ (username, score, rank) for rank, (username, score) in enumerate(order, start=1) ] @@ -174,7 +173,7 @@ def rankings(): .group_by(Submission.username) .order_by(fn.count(Submission.question).desc()) ) - order = [(x.username, x.score) for x in order] + order = list(order.tuples()) order = [ (username, score, rank) for rank, (username, score) in enumerate(order, start=1) ] From bcf52f0f7b2c34f6b6a9583d023e0d8cfcf07f5b Mon Sep 17 00:00:00 2001 From: Rishabh Kalakoti Date: Sun, 19 May 2019 22:29:52 +0530 Subject: [PATCH 07/17] index for submission --- server.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/server.py b/server.py index c1cc347..15f4f65 100644 --- a/server.py +++ b/server.py @@ -45,6 +45,9 @@ class Submission(Model): class Meta: database = db + indexes = ( + (("username","time"), True), + ) db.connect() From 4cd7884eb1ed1cba89c26def43aeb2997db01fdd Mon Sep 17 00:00:00 2001 From: Rishabh Kalakoti Date: Mon, 20 May 2019 19:05:46 +0530 Subject: [PATCH 08/17] setup database for contest --- data.db | Bin 24576 -> 45056 bytes server.py | 111 ++++++++++++++++++++++++++++--------------- views/contest.html | 8 ++-- views/dashboard.html | 4 +- 4 files changed, 78 insertions(+), 45 deletions(-) diff --git a/data.db b/data.db index fe82144f3e329de3a74e20b790b54d719ca992b8..21513e3fb09c60c4c4dc29d389859749fb61e8fd 100644 GIT binary patch literal 45056 zcmeI*&2QUe90%~{u^lJr+tYP~9J(?$73!jp%FauZbecrgWh0_ZyENU)smfZ9nk`9* z6NZpDWV>G?f%(yX zrCc-Z+EKM~>#kX{_uBJ&AJloSRVfcFpIpyp(uIt+o6BC^&1l)&rOXX2Fc36UNI=`l z4MhdCbIyu^x3qw>!9cJP^1A(@5WPQLEAmPW6h1IJ(XLP-eQ_f*avRn`fY-B-xsu6i zxvheh+uhjEw)5G|bpEFHZssQ6cDu}gb}gM>eqs>I z_#nGhtk(8wR*4sMi60P!>}IAH%q$;_TN-Rgs@s2Ikv5`DGrNAPWZ5>~++N)_tL0+J zY_8hPcaJ3OF7IEj#o1jdP@ICrf!3^a@P^CnU-r=kZPr07@022D)RCL)3u|phWc6(! z*qBw^exHxtZ?&5U5N}t1i#h8Zqq#(=P#NDEM@8GdSE=#?edGZgY}}LG{>4T5Ak{pS zx;EV@rN4UJ1;;$5o?prF2TSMFA3D2^b8cGVpH{VM?$?IT^WarU^)JrTdh19tTZfr- zV7I2^k*(ZbxF?!M{NHNNw;_T@w0T-K5-rPCN$nVEK(V#ZAspE_d>5Z%7Zlg#lszH* zg#-ZzKmY;|fB*y_009U<00Izzz{wLh*RJwBmE*qEL^h@GY~@lH>(^u1k8ek-H&(^X zS<$Ia*&l?zkRSj72tWV=5P$##AOHafKmY;|IN<_*Iqn^G4?y()t24h5_9Od(y~mQw z%V&@v009U<00Izz00bZa0SG_<0w+cwth$LW?OpJSZtjR~q{4bU9MLr+wWi0`;>neS z9*ZZF+xhf*A-kRlyGDc?DJ>FNi|T7eVr4ZROQwuYxH2}JZy>@;Px10oPWXx}!fAhH zMCtmPcqLYndL)rZN=|%O8dH2T-iWS56RUO+sQ{tCoFOymfe|c(-_`QnQ@h zZf(hkti_C#Xv{ETac50&{V%a!3HzOYAVB~E5P$##AOHafKmY;|fB*y_aAE|eB!&2V z;o~ogKI_V3qDxKD5eK^ZWl2drH`!`~wLB5P$##AOHafKmY;|fB*y_0D%)L z;E{b)+zF88SAOHafKmY;|fB*y_009U<;FS_s zQuvqlpFMs+9f}zqG~gN&(>qc?85z?*JU|{F(-{&Vg%v&$V4%By{5Syd{eNZV2g1H( z@3YtW1QG-w009U<00Izz00bZa0SG|gB^B6KRI+?N8oj(**v)6wxA+fo?iB1w$-H-H zR!z++YqdlE6ZiF6y=q4Eh#uAr{?c@Pt@&zZ86vlnm6uf#ybz6U<*saHb63U{c~muR zv)q2TK&-cb)&=)!Z`OvSlBGm6x}DxBj4iO(d{jX)Yz)-U;8~I0(k@e#EEv4B_TvkV zs>S`9wQp+94<6dO-rUXJl~O$M`Q9wi|F5t|ggs(Ev#0Fem$ZpdEeJpW0uX=z1Rwwb z2tWV=5P-m|EO1I*rhT_PlsP#_`)^ywOkScrcO9fjdBN-4HxT{*9#$soZ}x$AOHafKmY;|fB*y_009U<00J*4Fy~Rozy-TH=N`&)omLexcp0ypb`59B zvx-9cukM-5bG$v*`_ue!fD6>Q;FqTO^8mZo|Dylj!zzS5U={W?{|&&$?0fbPo(1@V z4UE+w009U<00Izz00bZa0SG_<0z%-lvP}Cs>{ZWjp3D835~Ks&_=-9rQ+AzFmS|t^ czA~#Ud3$r@8D)Wov>OUH||9 delta 97 zcmZp8z|?Snae}lU9|Hpe8xX?)>qH%6aXtn;nGL)^Ay(cH2L3*NYd%Nbb-W>)1qJT$ rY!2bwpv1$%Z^6KSjDI?RI==-_Sc9KQmt``yz2xNDe4fqm_6rpNXDk#^ diff --git a/server.py b/server.py index 15f4f65..2ab7369 100644 --- a/server.py +++ b/server.py @@ -1,7 +1,6 @@ import bottle import os, sys, datetime import string, random -from collections import defaultdict, namedtuple from peewee import * path = os.path.abspath(__file__) @@ -9,17 +8,30 @@ app = bottle.Bottle() DATABASE_NAME = "data.db" - -questions = {} -contests = {} question_dir = "files/questions" -Question = namedtuple("Question", "output statement") -Contest = namedtuple("Contest", "description questions start_time end_time") - db = SqliteDatabase(DATABASE_NAME) +class Contest(Model): + code = CharField(unique=True) + description = CharField() + start_time = DateTimeField() + end_time = DateTimeField() + + class Meta: + database = db + + +class ContestProblems(Model): + contest = CharField() + question = IntegerField() + + class Meta: + database = db + indexes = ((("contest", "question"), True),) + + class User(Model): username = CharField(unique=True) password = CharField() @@ -45,48 +57,45 @@ class Submission(Model): class Meta: database = db - indexes = ( - (("username","time"), True), - ) + indexes = ((("username", "time"), True),) db.connect() -db.create_tables([User, Session, Submission]) +db.create_tables([User, Session, Submission, ContestProblems, Contest]) -# dummy contests -contests["PRACTICE"] = Contest( +# dummy contest data +Contest.get_or_create( + code="PRACTICE", description="practice questions", - questions=[1, 2], start_time=datetime.datetime(day=1, month=1, year=1), end_time=datetime.datetime(day=1, month=1, year=9999), ) -contests["PASTCONTEST"] = Contest( +Contest.get_or_create( + code="PASTCONTEST", description="somewhere in the past", - questions=[1, 2], start_time=datetime.datetime(day=1, month=11, year=2018), end_time=datetime.datetime(day=1, month=12, year=2018), ) -contests["ONGOINGCONTEST"] = Contest( +Contest.get_or_create( + code="ONGOINGCONTEST", description="somewhere in the present", - questions=[3, 4], start_time=datetime.datetime(day=1, month=4, year=2019), end_time=datetime.datetime(day=1, month=6, year=2019), ) -contests["FUTURECONTEST"] = Contest( +Contest.get_or_create( + code="FUTURECONTEST", description="somewhere in the future", - questions=[5, 6], start_time=datetime.datetime(day=1, month=1, year=2020), end_time=datetime.datetime(day=1, month=10, year=2020), ) - -for i in os.listdir(question_dir): - if not i.isdigit(): - continue - with open(os.path.join(question_dir, i, "output.txt"), "rb") as fl: - output = fl.read() - with open(os.path.join(question_dir, i, "statement.txt"), "r") as fl: - statement = fl.read() - questions[i] = Question(output=output, statement=statement) +ContestProblems.get_or_create(contest="PRACTICE", question=1) +ContestProblems.get_or_create(contest="PRACTICE", question=2) +ContestProblems.get_or_create(contest="PASTCONTEST", question=1) +ContestProblems.get_or_create(contest="PASTCONTEST", question=2) +ContestProblems.get_or_create(contest="ONGOINGCONTEST", question=3) +ContestProblems.get_or_create(contest="ONGOINGCONTEST", question=4) +ContestProblems.get_or_create(contest="FUTURECONTEST", question=5) +ContestProblems.get_or_create(contest="FUTURECONTEST", question=6) def login_required(function): @@ -113,17 +122,27 @@ def home(): @app.get("/dashboard") @login_required def dashboard(): + contests = Contest.select().order_by(Contest.start_time) return bottle.template("dashboard.html", contests=contests) @app.get("/contest//") @login_required def question(code, number): - if not code in contests: - return "Contest does not exist" - if contests[code].start_time > datetime.datetime.now(): + if ( + not ContestProblems.select() + .where( + (ContestProblems.contest == code) + & (ContestProblems.question == int(number)) + ) + .exists() + ): + return error404(404) + contest = Contest.get(Contest.code == code) + if contest.start_time > datetime.datetime.now(): return "The contest had not started yet." - statement = questions[number].statement + with open(os.path.join(question_dir, number, "statement.txt"), "rb") as fl: + statement = fl.read() return bottle.template( "question.html", question_number=number, contest=code, question=statement ) @@ -132,11 +151,15 @@ def question(code, number): @app.get("/contest/") @login_required def contest(code): - if not code in contests: - return "Contest does not exist" - if contests[code].start_time > datetime.datetime.now(): - return "The contest had not started yet." - return bottle.template("contest.html", code=code, contest=contests[code]) + if not Contest.select().where(Contest.code == code).exists(): + return error404(404) + contest = Contest.get(Contest.code == code) + questions = ( + ContestProblems.select(ContestProblems.question) + .where(ContestProblems.contest == code) + .tuples() + ) + return bottle.template("contest.html", contest=contest, questions=list(questions)) @app.get("/question/") @@ -243,10 +266,20 @@ def logout(): @app.post("/check//") @login_required def file_upload(code, number): + if ( + not ContestProblems.select() + .where( + (ContestProblems.contest == code) + & (ContestProblems.question == int(number)) + ) + .exists() + ): + return error404(404) username = Session.get(Session.id == bottle.request.get_cookie("s_id")).username time = datetime.datetime.now() uploaded = bottle.request.files.get("upload").file.read() - expected = questions[number].output + with open(os.path.join(question_dir, number, "output.txt"), "rb") as fl: + expected = fl.read() expected = expected.strip() uploaded = uploaded.strip() ans = uploaded == expected diff --git a/views/contest.html b/views/contest.html index c7a3f12..1a763ef 100644 --- a/views/contest.html +++ b/views/contest.html @@ -2,7 +2,7 @@
-

{{code}}

+

{{contest.code}}

@@ -10,11 +10,11 @@

{{code}}

- % for qno in range(len(contest.questions)): - {{qno+1}}
+ % for qno in range(len(questions)): + {{qno+1}}
% end
diff --git a/views/dashboard.html b/views/dashboard.html index 1349b5c..91974be 100644 --- a/views/dashboard.html +++ b/views/dashboard.html @@ -13,9 +13,9 @@

Contests

- % for code, contest in contests.items(): + % for contest in contests: - {{code}} + {{contest.code}} {{contest.start_time}} {{contest.end_time}} From d7c2c6a1f1723d0f09b5b8ab73d7992d1ee0d9c7 Mon Sep 17 00:00:00 2001 From: Rishabh Kalakoti <23037053+rishabhKalakoti@users.noreply.github.com> Date: Tue, 21 May 2019 07:43:17 +0530 Subject: [PATCH 09/17] Apply suggestions from code review Co-Authored-By: Arjoonn Sharma --- server.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server.py b/server.py index 2ab7369..deac0eb 100644 --- a/server.py +++ b/server.py @@ -137,7 +137,7 @@ def question(code, number): ) .exists() ): - return error404(404) + return bottle.abort(404, 'no such contest') contest = Contest.get(Contest.code == code) if contest.start_time > datetime.datetime.now(): return "The contest had not started yet." @@ -152,7 +152,7 @@ def question(code, number): @login_required def contest(code): if not Contest.select().where(Contest.code == code).exists(): - return error404(404) + return bottle.abort(404, 'no such contest') contest = Contest.get(Contest.code == code) questions = ( ContestProblems.select(ContestProblems.question) From a3c44ad1151af602a762f2d8f23a0360d15f446b Mon Sep 17 00:00:00 2001 From: Rishabh Kalakoti Date: Tue, 21 May 2019 08:08:55 +0530 Subject: [PATCH 10/17] removed db --- data.db | Bin 45056 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 data.db diff --git a/data.db b/data.db deleted file mode 100644 index 21513e3fb09c60c4c4dc29d389859749fb61e8fd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 45056 zcmeI*&2QUe90%~{u^lJr+tYP~9J(?$73!jp%FauZbecrgWh0_ZyENU)smfZ9nk`9* z6NZpDWV>G?f%(yX zrCc-Z+EKM~>#kX{_uBJ&AJloSRVfcFpIpyp(uIt+o6BC^&1l)&rOXX2Fc36UNI=`l z4MhdCbIyu^x3qw>!9cJP^1A(@5WPQLEAmPW6h1IJ(XLP-eQ_f*avRn`fY-B-xsu6i zxvheh+uhjEw)5G|bpEFHZssQ6cDu}gb}gM>eqs>I z_#nGhtk(8wR*4sMi60P!>}IAH%q$;_TN-Rgs@s2Ikv5`DGrNAPWZ5>~++N)_tL0+J zY_8hPcaJ3OF7IEj#o1jdP@ICrf!3^a@P^CnU-r=kZPr07@022D)RCL)3u|phWc6(! z*qBw^exHxtZ?&5U5N}t1i#h8Zqq#(=P#NDEM@8GdSE=#?edGZgY}}LG{>4T5Ak{pS zx;EV@rN4UJ1;;$5o?prF2TSMFA3D2^b8cGVpH{VM?$?IT^WarU^)JrTdh19tTZfr- zV7I2^k*(ZbxF?!M{NHNNw;_T@w0T-K5-rPCN$nVEK(V#ZAspE_d>5Z%7Zlg#lszH* zg#-ZzKmY;|fB*y_009U<00Izzz{wLh*RJwBmE*qEL^h@GY~@lH>(^u1k8ek-H&(^X zS<$Ia*&l?zkRSj72tWV=5P$##AOHafKmY;|IN<_*Iqn^G4?y()t24h5_9Od(y~mQw z%V&@v009U<00Izz00bZa0SG_<0w+cwth$LW?OpJSZtjR~q{4bU9MLr+wWi0`;>neS z9*ZZF+xhf*A-kRlyGDc?DJ>FNi|T7eVr4ZROQwuYxH2}JZy>@;Px10oPWXx}!fAhH zMCtmPcqLYndL)rZN=|%O8dH2T-iWS56RUO+sQ{tCoFOymfe|c(-_`QnQ@h zZf(hkti_C#Xv{ETac50&{V%a!3HzOYAVB~E5P$##AOHafKmY;|fB*y_aAE|eB!&2V z;o~ogKI_V3qDxKD5eK^ZWl2drH`!`~wLB5P$##AOHafKmY;|fB*y_0D%)L z;E{b)+zF88SAOHafKmY;|fB*y_009U<;FS_s zQuvqlpFMs+9f}zqG~gN&(>qc?85z?*JU|{F(-{&Vg%v&$V4%By{5Syd{eNZV2g1H( z@3YtW1QG-w009U<00Izz00bZa0SG|gB^B6KRI+?N8oj(**v)6wxA+fo?iB1w$-H-H zR!z++YqdlE6ZiF6y=q4Eh#uAr{?c@Pt@&zZ86vlnm6uf#ybz6U<*saHb63U{c~muR zv)q2TK&-cb)&=)!Z`OvSlBGm6x}DxBj4iO(d{jX)Yz)-U;8~I0(k@e#EEv4B_TvkV zs>S`9wQp+94<6dO-rUXJl~O$M`Q9wi|F5t|ggs(Ev#0Fem$ZpdEeJpW0uX=z1Rwwb z2tWV=5P-m|EO1I*rhT_PlsP#_`)^ywOkScrcO9fjdBN-4HxT{*9#$soZ}x$AOHafKmY;|fB*y_009U<00J*4Fy~Rozy-TH=N`&)omLexcp0ypb`59B zvx-9cukM-5bG$v*`_ue!fD6>Q;FqTO^8mZo|Dylj!zzS5U={W?{|&&$?0fbPo(1@V z4UE+w009U<00Izz00bZa0SG_<0z%-lvP}Cs>{ZWjp3D835~Ks&_=-9rQ+AzFmS|t^ czA~#Ud3$r@8D)Wov>OUH||9 From 962dc8cfec9981e82766167140e08bc6185c833d Mon Sep 17 00:00:00 2001 From: Rishabh Kalakoti Date: Tue, 21 May 2019 12:24:31 +0530 Subject: [PATCH 11/17] database completed. --- server.py | 145 ++++++++++++++++++++++++++++++++---------------------- 1 file changed, 86 insertions(+), 59 deletions(-) diff --git a/server.py b/server.py index deac0eb..2686b23 100644 --- a/server.py +++ b/server.py @@ -13,89 +13,109 @@ db = SqliteDatabase(DATABASE_NAME) -class Contest(Model): - code = CharField(unique=True) - description = CharField() - start_time = DateTimeField() - end_time = DateTimeField() +class User(Model): + username = CharField(unique=True) + password = CharField() class Meta: database = db -class ContestProblems(Model): - contest = CharField() - question = IntegerField() +class Session(Model): + id = CharField(unique=True) + user = ForeignKeyField(User) class Meta: database = db - indexes = ((("contest", "question"), True),) -class User(Model): - username = CharField(unique=True) - password = CharField() +class Contest(Model): + code = CharField(unique=True) + description = CharField() + start_time = DateTimeField() + end_time = DateTimeField() class Meta: database = db -class Session(Model): - id = CharField(unique=True) - username = CharField() +class Question(Model): + q_no = IntegerField(unique=True) + author = ForeignKeyField(User) + + class Meta: + database = db + + +class ContestProblems(Model): + contest = ForeignKeyField(Contest) + question = ForeignKeyField(Question) class Meta: database = db + indexes = ((("contest", "question"), True),) class Submission(Model): - username = CharField() + user = ForeignKeyField(User) time = DateTimeField() - question = IntegerField() - contest = CharField() + question = ForeignKeyField(Question) + contest = ForeignKeyField(Contest) is_correct = BooleanField() class Meta: database = db - indexes = ((("username", "time"), True),) + indexes = ((("user", "time"), True),) db.connect() -db.create_tables([User, Session, Submission, ContestProblems, Contest]) +db.create_tables([User, Session, Submission, ContestProblems, Contest, Question]) + # dummy contest data -Contest.get_or_create( +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), ) -Contest.get_or_create( +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), ) -Contest.get_or_create( +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), ) -Contest.get_or_create( +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), ) -ContestProblems.get_or_create(contest="PRACTICE", question=1) -ContestProblems.get_or_create(contest="PRACTICE", question=2) -ContestProblems.get_or_create(contest="PASTCONTEST", question=1) -ContestProblems.get_or_create(contest="PASTCONTEST", question=2) -ContestProblems.get_or_create(contest="ONGOINGCONTEST", question=3) -ContestProblems.get_or_create(contest="ONGOINGCONTEST", question=4) -ContestProblems.get_or_create(contest="FUTURECONTEST", question=5) -ContestProblems.get_or_create(contest="FUTURECONTEST", question=6) + +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): @@ -131,13 +151,12 @@ def dashboard(): def question(code, number): if ( not ContestProblems.select() - .where( - (ContestProblems.contest == code) - & (ContestProblems.question == int(number)) - ) + .where((Contest.code == code) & (Question.q_no == int(number))) + .join(Contest, on=(ContestProblems.contest == Contest.id)) + .join(Question, on=(ContestProblems.question == Question.q_no)) .exists() ): - return bottle.abort(404, 'no such contest') + 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." @@ -152,11 +171,12 @@ def question(code, number): @login_required def contest(code): if not Contest.select().where(Contest.code == code).exists(): - return bottle.abort(404, 'no such contest') + return bottle.abort(404, "no such contest") contest = Contest.get(Contest.code == code) questions = ( - ContestProblems.select(ContestProblems.question) - .where(ContestProblems.contest == code) + ContestProblems.select(Question.q_no) + .where(ContestProblems.contest == contest) + .join(Question, on=(ContestProblems.question == Question.q_no)) .tuples() ) return bottle.template("contest.html", contest=contest, questions=list(questions)) @@ -175,12 +195,13 @@ def server_static(filepath): @app.get("/ranking/") def contest_ranking(code): order = ( - Submission.select( - Submission.username, fn.count(Submission.question).alias("score") - ) - .where((Submission.is_correct == True) & (Submission.contest == code)) - .group_by(Submission.username) - .order_by(fn.count(Submission.question).desc()) + Submission.select(User.username, fn.count(Question.q_no).alias("score")) + .where((Submission.is_correct == True) & (Contest.code == code)) + .join(User, on=(Submission.user == User.id)) + .join(Question, on=(Submission.question == Question.q_no)) + .join(Contest, on=(Submission.contest == Contest.id)) + .group_by(Submission.user) + .order_by(fn.count(Question.q_no).desc()) ) order = list(order.tuples()) order = [ @@ -192,12 +213,13 @@ def contest_ranking(code): @app.get("/ranking") def rankings(): order = ( - Submission.select( - Submission.username, fn.count(Submission.question).alias("score") - ) + Submission.select(User.username, fn.count(Question.q_no).alias("score")) .where(Submission.is_correct == True) - .group_by(Submission.username) - .order_by(fn.count(Submission.question).desc()) + .join(User, on=(Submission.user == User.id)) + .switch() + .join(Question, on=(Submission.question == Question.q_no)) + .group_by(Submission.user) + .order_by(fn.count(Question.q_no).desc()) ) order = list(order.tuples()) order = [ @@ -224,7 +246,7 @@ def createSession(username): expires=datetime.datetime.now() + datetime.timedelta(days=30), ) try: - Session.create(id=session_id, username=username) + Session.create(id=session_id, user=User.get(User.username == username)) except IntegrityError: return abort("Error! Please try again.") return bottle.redirect("/dashboard") @@ -268,14 +290,15 @@ def logout(): def file_upload(code, number): if ( not ContestProblems.select() - .where( - (ContestProblems.contest == code) - & (ContestProblems.question == int(number)) - ) + .where((Contest.code == code) & (Question.q_no == int(number))) + .join(Contest, on=(ContestProblems.contest == Contest.id)) + .join(Question, on=(ContestProblems.question == Question.q_no)) .exists() ): - return error404(404) - username = Session.get(Session.id == bottle.request.get_cookie("s_id")).username + return bottle.abort(404, "no such contest problem") + username = Session.get( + Session.id == bottle.request.get_cookie("s_id") + ).user.username 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: @@ -285,7 +308,11 @@ def file_upload(code, number): ans = uploaded == expected try: Submission.create( - username=username, question=number, time=time, contest=code, is_correct=ans + user=User.get(User.username == username), + question=Question.get(Question.q_no == number), + time=time, + contest=Contest.get(Contest.code == code), + is_correct=ans, ) except: abort("Error in inserting submission to database.") From 20f8b3d3d63d05b3282707590e186a1c4b894e39 Mon Sep 17 00:00:00 2001 From: Rishabh Kalakoti Date: Tue, 21 May 2019 15:36:50 +0530 Subject: [PATCH 12/17] used backref and added token --- server.py | 35 +++++++++++++++-------------------- views/contest.html | 2 +- 2 files changed, 16 insertions(+), 21 deletions(-) diff --git a/server.py b/server.py index 2686b23..16cbfbe 100644 --- a/server.py +++ b/server.py @@ -22,7 +22,10 @@ class Meta: class Session(Model): - id = CharField(unique=True) + def random_token(): + return "".join([random.choice(string.ascii_letters) for _ in range(20)]) + + token = CharField(unique=True, default=random_token) user = ForeignKeyField(User) class Meta: @@ -48,7 +51,7 @@ class Meta: class ContestProblems(Model): - contest = ForeignKeyField(Contest) + contest = ForeignKeyField(Contest, backref="questions") question = ForeignKeyField(Question) class Meta: @@ -107,7 +110,6 @@ class Meta: 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]) @@ -173,13 +175,7 @@ def contest(code): if not Contest.select().where(Contest.code == code).exists(): return bottle.abort(404, "no such contest") contest = Contest.get(Contest.code == code) - questions = ( - ContestProblems.select(Question.q_no) - .where(ContestProblems.contest == contest) - .join(Question, on=(ContestProblems.question == Question.q_no)) - .tuples() - ) - return bottle.template("contest.html", contest=contest, questions=list(questions)) + return bottle.template("contest.html", contest=contest, questions=contest.questions) @app.get("/question/") @@ -232,23 +228,22 @@ def logggedIn(): if not bottle.request.get_cookie("s_id"): return False return ( - Session.select().where(Session.id == bottle.request.get_cookie("s_id")).exists() + Session.select() + .where(Session.token == bottle.request.get_cookie("s_id")) + .exists() ) def createSession(username): - session_id = "".join( - random.choice(string.ascii_letters + string.digits) for i in range(20) - ) + try: + session = Session.create(user=User.get(User.username == username)) + except IntegrityError: + return abort("Error! Please try again.") bottle.response.set_cookie( "s_id", - session_id, + session.token, expires=datetime.datetime.now() + datetime.timedelta(days=30), ) - try: - Session.create(id=session_id, user=User.get(User.username == username)) - except IntegrityError: - return abort("Error! Please try again.") return bottle.redirect("/dashboard") @@ -280,7 +275,7 @@ def register(): @app.get("/logout") def logout(): - Session.delete().where(Session.id == bottle.request.get_cookie("s_id")).execute() + Session.delete().where(Session.token == bottle.request.get_cookie("s_id")).execute() bottle.response.delete_cookie("s_id") return bottle.redirect("/home") diff --git a/views/contest.html b/views/contest.html index 1a763ef..ed2e653 100644 --- a/views/contest.html +++ b/views/contest.html @@ -14,7 +14,7 @@

{{contest.code}}

% for qno in range(len(questions)): - {{qno+1}}
+ {{qno+1}}
% end
From 1c82bdc75b911cf2b4dd4660f9fcee9af42fc0ea Mon Sep 17 00:00:00 2001 From: Rishabh Kalakoti Date: Wed, 22 May 2019 14:38:09 +0530 Subject: [PATCH 13/17] minor changes --- server.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/server.py b/server.py index 16cbfbe..200620c 100644 --- a/server.py +++ b/server.py @@ -172,9 +172,10 @@ def question(code, number): @app.get("/contest/") @login_required def contest(code): - if not Contest.select().where(Contest.code == code).exists(): + try: + contest = Contest.get(Contest.code == code) + except Contest.DoesNotExist: return bottle.abort(404, "no such contest") - contest = Contest.get(Contest.code == code) return bottle.template("contest.html", contest=contest, questions=contest.questions) @@ -238,7 +239,7 @@ def createSession(username): try: session = Session.create(user=User.get(User.username == username)) except IntegrityError: - return abort("Error! Please try again.") + return bottle.abort(500, "Error! Please try again.") bottle.response.set_cookie( "s_id", session.token, @@ -292,7 +293,7 @@ def file_upload(code, number): ): return bottle.abort(404, "no such contest problem") username = Session.get( - Session.id == bottle.request.get_cookie("s_id") + Session.token == bottle.request.get_cookie("s_id") ).user.username time = datetime.datetime.now() uploaded = bottle.request.files.get("upload").file.read() @@ -310,7 +311,7 @@ def file_upload(code, number): is_correct=ans, ) except: - abort("Error in inserting submission to database.") + bottle.abort(500, "Error in inserting submission to database.") if not ans: return "Wrong Answer!!" else: From 6077aac310eb513cc71069bba9f3c67700d389ba Mon Sep 17 00:00:00 2001 From: Rishabh Kalakoti Date: Wed, 22 May 2019 14:47:04 +0530 Subject: [PATCH 14/17] corrected coontest ranks and optimized submission --- server.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/server.py b/server.py index 200620c..dbf7018 100644 --- a/server.py +++ b/server.py @@ -193,7 +193,12 @@ def server_static(filepath): def contest_ranking(code): order = ( Submission.select(User.username, fn.count(Question.q_no).alias("score")) - .where((Submission.is_correct == True) & (Contest.code == code)) + .where( + (Submission.is_correct == True) + & (Contest.code == code) + & (Submission.time >= Contest.start_time) + & (Submission.time <= Contest.end_time) + ) .join(User, on=(Submission.user == User.id)) .join(Question, on=(Submission.question == Question.q_no)) .join(Contest, on=(Submission.contest == Contest.id)) @@ -292,9 +297,7 @@ def file_upload(code, number): .exists() ): return bottle.abort(404, "no such contest problem") - username = Session.get( - Session.token == bottle.request.get_cookie("s_id") - ).user.username + 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: @@ -304,7 +307,7 @@ def file_upload(code, number): ans = uploaded == expected try: Submission.create( - user=User.get(User.username == username), + user=user, question=Question.get(Question.q_no == number), time=time, contest=Contest.get(Contest.code == code), From bfac8d4b6fcd420e7709ca913c473af72aab0dab Mon Sep 17 00:00:00 2001 From: Rishabh Kalakoti Date: Wed, 22 May 2019 15:09:17 +0530 Subject: [PATCH 15/17] contestProblem made Foreign key in submission. TODO: rankings --- server.py | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/server.py b/server.py index dbf7018..4ac37b4 100644 --- a/server.py +++ b/server.py @@ -62,8 +62,9 @@ class Meta: class Submission(Model): user = ForeignKeyField(User) time = DateTimeField() - question = ForeignKeyField(Question) - contest = ForeignKeyField(Contest) + contestProblem = ForeignKeyField(ContestProblems) + #question = ForeignKeyField(Question) + #contest = ForeignKeyField(Contest) is_correct = BooleanField() class Meta: @@ -191,6 +192,7 @@ def server_static(filepath): @app.get("/ranking/") def contest_ranking(code): + ''' order = ( Submission.select(User.username, fn.count(Question.q_no).alias("score")) .where( @@ -200,8 +202,9 @@ def contest_ranking(code): & (Submission.time <= Contest.end_time) ) .join(User, on=(Submission.user == User.id)) - .join(Question, on=(Submission.question == Question.q_no)) - .join(Contest, on=(Submission.contest == Contest.id)) + .join(ContestProblems, on=(Submission.contestProblem == ContestProblems.id)) + #.join(Question, on=(Submission.question == Question.q_no)) + #.join(Contest, on=(Submission.contest == Contest.id)) .group_by(Submission.user) .order_by(fn.count(Question.q_no).desc()) ) @@ -210,10 +213,13 @@ def contest_ranking(code): (username, score, rank) for rank, (username, score) in enumerate(order, start=1) ] return bottle.template("rankings.html", people=order) + ''' + return "TODO" @app.get("/ranking") def rankings(): + ''' order = ( Submission.select(User.username, fn.count(Question.q_no).alias("score")) .where(Submission.is_correct == True) @@ -228,7 +234,8 @@ def rankings(): (username, score, rank) for rank, (username, score) in enumerate(order, start=1) ] return bottle.template("rankings.html", people=order) - + ''' + return "TODO" def logggedIn(): if not bottle.request.get_cookie("s_id"): @@ -289,13 +296,12 @@ def logout(): @app.post("/check//") @login_required def file_upload(code, number): - if ( - not ContestProblems.select() - .where((Contest.code == code) & (Question.q_no == int(number))) - .join(Contest, on=(ContestProblems.contest == Contest.id)) - .join(Question, on=(ContestProblems.question == Question.q_no)) - .exists() - ): + try: + contestProblem = ContestProblems.get( + ContestProblems.contest == Contest.get(Contest.code == code), + ContestProblems.question == Question.get(Question.q_no == 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() @@ -308,9 +314,8 @@ def file_upload(code, number): try: Submission.create( user=user, - question=Question.get(Question.q_no == number), + contestProblem = contestProblem, time=time, - contest=Contest.get(Contest.code == code), is_correct=ans, ) except: From d6e808f141720b881dce92d9b5467e65dbe80b60 Mon Sep 17 00:00:00 2001 From: Rishabh Kalakoti Date: Wed, 22 May 2019 15:21:51 +0530 Subject: [PATCH 16/17] ranking completed. correct scoring :) --- server.py | 38 ++++++++++++++------------------------ 1 file changed, 14 insertions(+), 24 deletions(-) diff --git a/server.py b/server.py index 4ac37b4..9121582 100644 --- a/server.py +++ b/server.py @@ -63,8 +63,6 @@ class Submission(Model): user = ForeignKeyField(User) time = DateTimeField() contestProblem = ForeignKeyField(ContestProblems) - #question = ForeignKeyField(Question) - #contest = ForeignKeyField(Contest) is_correct = BooleanField() class Meta: @@ -192,50 +190,45 @@ def server_static(filepath): @app.get("/ranking/") def contest_ranking(code): - ''' order = ( - Submission.select(User.username, fn.count(Question.q_no).alias("score")) + Submission.select( + User.username, fn.count(Submission.contestProblem.distinct()).alias("score") + ) .where( (Submission.is_correct == True) - & (Contest.code == code) - & (Submission.time >= Contest.start_time) - & (Submission.time <= Contest.end_time) + & (ContestProblems.contest == Contest.get(Contest.code == code)) ) .join(User, on=(Submission.user == User.id)) + .switch() .join(ContestProblems, on=(Submission.contestProblem == ContestProblems.id)) - #.join(Question, on=(Submission.question == Question.q_no)) - #.join(Contest, on=(Submission.contest == Contest.id)) .group_by(Submission.user) - .order_by(fn.count(Question.q_no).desc()) + .order_by(fn.count(Submission.contestProblem.distinct()).desc()) ) order = list(order.tuples()) order = [ (username, score, rank) for rank, (username, score) in enumerate(order, start=1) ] return bottle.template("rankings.html", people=order) - ''' - return "TODO" @app.get("/ranking") def rankings(): - ''' order = ( - Submission.select(User.username, fn.count(Question.q_no).alias("score")) - .where(Submission.is_correct == True) + Submission.select( + User.username, fn.count(Submission.contestProblem.distinct()).alias("score") + ) + .where((Submission.is_correct == True)) .join(User, on=(Submission.user == User.id)) .switch() - .join(Question, on=(Submission.question == Question.q_no)) + .join(ContestProblems, on=(Submission.contestProblem == ContestProblems.id)) .group_by(Submission.user) - .order_by(fn.count(Question.q_no).desc()) + .order_by(fn.count(Submission.contestProblem.distinct()).desc()) ) order = list(order.tuples()) order = [ (username, score, rank) for rank, (username, score) in enumerate(order, start=1) ] return bottle.template("rankings.html", people=order) - ''' - return "TODO" def logggedIn(): if not bottle.request.get_cookie("s_id"): @@ -299,7 +292,7 @@ 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.q_no == int(number)), ) except: return bottle.abort(404, "no such contest problem") @@ -313,10 +306,7 @@ def file_upload(code, number): ans = uploaded == expected try: Submission.create( - user=user, - contestProblem = contestProblem, - time=time, - is_correct=ans, + user=user, contestProblem=contestProblem, time=time, is_correct=ans ) except: bottle.abort(500, "Error in inserting submission to database.") From 167ed43c90335182592809889a56f871a98c9731 Mon Sep 17 00:00:00 2001 From: Rishabh Kalakoti Date: Wed, 22 May 2019 15:56:27 +0530 Subject: [PATCH 17/17] added contest not started in contest/code handler --- server.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/server.py b/server.py index 9121582..f1f874d 100644 --- a/server.py +++ b/server.py @@ -175,6 +175,8 @@ def contest(code): contest = Contest.get(Contest.code == code) except Contest.DoesNotExist: return bottle.abort(404, "no such contest") + if contest.start_time > datetime.datetime.now(): + return "The contest had not started yet." return bottle.template("contest.html", contest=contest, questions=contest.questions)