Skip to content

String pid #514

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 30 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
fac3a93
String PID support
undefined-moe May 13, 2019
316f5ce
fix spaces
undefined-moe May 13, 2019
a6c531a
String PID validator
undefined-moe May 13, 2019
0515be6
Help-Wanted:
undefined-moe May 13, 2019
68ce0c9
Fix tests
undefined-moe May 13, 2019
43755a0
UnittestFix1
undefined-moe May 13, 2019
38b7ec0
This is a backup version and it's **not** finished
undefined-moe May 14, 2019
d3bdbc8
0x02
undefined-moe May 14, 2019
536dc33
0x03
undefined-moe May 14, 2019
e5af567
0x04
undefined-moe May 14, 2019
fde8f43
0x05
undefined-moe May 14, 2019
bbbedc5
Merge branch 'master' into stringPID
undefined-moe May 14, 2019
7778e02
0x06
undefined-moe May 14, 2019
10b3ecd
0x07
undefined-moe May 14, 2019
60e6374
0x08
undefined-moe May 14, 2019
35e4aef
0x09
undefined-moe May 15, 2019
7a8bd75
0x0a
undefined-moe May 15, 2019
c1d83c3
Merge branch 'master' into stringPID
undefined-moe May 15, 2019
6c2fd17
0x0b
undefined-moe May 15, 2019
2d66a76
0x0c
undefined-moe May 15, 2019
a18e83a
0x0d
undefined-moe May 16, 2019
c6cf315
fix solution
undefined-moe May 24, 2019
e3e2e6f
bug fix
undefined-moe May 27, 2019
523cf83
Merge pull request #1 from vijos/master
undefined-moe May 27, 2019
8e9b68c
Merge branch 'master' into stringPID
undefined-moe May 29, 2019
3132019
to lowercase
undefined-moe May 29, 2019
69e7e62
Merge branch 'stringPID' of https://github.com/masnn0/vj4 into stringPID
undefined-moe May 29, 2019
c2838e9
Merge branch 'master' into stringPID
undefined-moe May 31, 2019
35c7080
Merge pull request #3 from vijos/master
undefined-moe May 31, 2019
27da508
Merge pull request #4 from masnn0/master
undefined-moe May 31, 2019
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
16 changes: 8 additions & 8 deletions vj4/handler/contest.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
from vj4.util import pagination


@app.route('/contest', 'contest_main')
@app.route('/c', 'contest_main')
class ContestMainHandler(contest.ContestMixin, base.Handler):
CONTESTS_PER_PAGE = 20

Expand All @@ -47,7 +47,7 @@ async def get(self, *, rule: int=0, page: int=1):
tdocs=tdocs, tsdict=tsdict)


@app.route('/contest/{tid:\w{24}}', 'contest_detail')
@app.route('/c/{tid:\w{24}}', 'contest_detail')
class ContestDetailHandler(contest.ContestMixin, base.OperationHandler):
DISCUSSIONS_PER_PAGE = 15

Expand Down Expand Up @@ -105,7 +105,7 @@ async def post_attend(self, *, tid: objectid.ObjectId):
self.json_or_redirect(self.url)


@app.route('/contest/{tid:\w{24}}/code', 'contest_code')
@app.route('/c/{tid:\w{24}}/code', 'contest_code')
class ContestCodeHandler(base.OperationHandler):
@base.limit_rate('contest_code', 3600, 60)
@base.route_argument
Expand All @@ -132,7 +132,7 @@ async def get(self, *, tid: objectid.ObjectId):
file_name='{}.zip'.format(tdoc['title']))


@app.route('/contest/{tid}/{pid:-?\d+|\w{24}}', 'contest_detail_problem')
@app.route('/c/{tid}/p/{pid:[a-zA-Z0-9]+}', 'contest_detail_problem')
class ContestDetailProblemHandler(contest.ContestMixin, base.Handler):
@base.route_argument
@base.require_perm(builtin.PERM_VIEW_CONTEST)
Expand Down Expand Up @@ -163,7 +163,7 @@ async def get(self, *, tid: objectid.ObjectId, pid: document.convert_doc_id):
page_title=pdoc['title'], path_components=path_components)


@app.route('/contest/{tid}/{pid}/submit', 'contest_detail_problem_submit')
@app.route('/c/{tid}/p/{pid}/submit', 'contest_detail_problem_submit')
class ContestDetailProblemSubmitHandler(contest.ContestMixin, base.Handler):
@base.route_argument
@base.require_perm(builtin.PERM_VIEW_CONTEST)
Expand Down Expand Up @@ -233,7 +233,7 @@ async def post(self, *, tid: objectid.ObjectId, pid: document.convert_doc_id,
self.json_or_redirect(self.reverse_url('record_detail', rid=rid))


@app.route('/contest/{tid}/scoreboard', 'contest_scoreboard')
@app.route('/c/{tid}/scoreboard', 'contest_scoreboard')
class ContestScoreboardHandler(contest.ContestMixin, base.Handler):
@base.route_argument
@base.require_perm(builtin.PERM_VIEW_CONTEST)
Expand All @@ -251,7 +251,7 @@ async def get(self, *, tid: objectid.ObjectId):
page_title=page_title, path_components=path_components)


@app.route('/contest/{tid}/scoreboard/download/{ext}', 'contest_scoreboard_download')
@app.route('/c/{tid}/scoreboard/download/{ext}', 'contest_scoreboard_download')
class ContestScoreboardDownloadHandler(contest.ContestMixin, base.Handler):
def _export_status_as_csv(self, rows):
# \r\n for notepad compatibility
Expand Down Expand Up @@ -321,7 +321,7 @@ async def post(self, *, title: str, content: str, rule: int,
self.json_or_redirect(self.reverse_url('contest_detail', tid=tid))


@app.route('/contest/{tid}/edit', 'contest_edit')
@app.route('/c/{tid}/edit', 'contest_edit')
class ContestEditHandler(contest.ContestMixin, base.Handler):
@base.route_argument
@base.require_priv(builtin.PRIV_USER_PROFILE)
Expand Down
16 changes: 8 additions & 8 deletions vj4/handler/homework.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ def _format_penalty_rules_yaml(penalty_rules):
return yaml_doc


@app.route('/homework', 'homework_main')
@app.route('/h', 'homework_main')
class HomeworkMainHandler(contest.ContestMixin, base.Handler):
@base.require_perm(builtin.PERM_VIEW_HOMEWORK)
async def get(self):
Expand All @@ -72,7 +72,7 @@ async def get(self):
self.render('homework_main.html', tdocs=tdocs, calendar_tdocs=calendar_tdocs)


@app.route('/homework/{tid:\w{24}}', 'homework_detail')
@app.route('/h/{tid:\w{24}}', 'homework_detail')
class HomeworkDetailHandler(contest.ContestMixin, base.OperationHandler):
DISCUSSIONS_PER_PAGE = 15

Expand Down Expand Up @@ -130,7 +130,7 @@ async def post_attend(self, *, tid: objectid.ObjectId):
self.json_or_redirect(self.url)


@app.route('/homework/{tid:\w{24}}/code', 'homework_code')
@app.route('/h/{tid:\w{24}}/code', 'homework_code')
class HomeworkCodeHandler(base.OperationHandler):
@base.limit_rate('homework_code', 3600, 60)
@base.route_argument
Expand All @@ -157,7 +157,7 @@ async def get(self, *, tid: objectid.ObjectId):
file_name='{}.zip'.format(tdoc['title']))


@app.route('/homework/{tid}/{pid:-?\d+|\w{24}}', 'homework_detail_problem')
@app.route('/h/{tid}/p/{pid:[a-zA-Z0-9]+}', 'homework_detail_problem')
class HomeworkDetailProblemHandler(contest.ContestMixin, base.Handler):
@base.route_argument
@base.require_perm(builtin.PERM_VIEW_HOMEWORK)
Expand Down Expand Up @@ -188,7 +188,7 @@ async def get(self, *, tid: objectid.ObjectId, pid: document.convert_doc_id):
page_title=pdoc['title'], path_components=path_components)


@app.route('/homework/{tid}/{pid}/submit', 'homework_detail_problem_submit')
@app.route('/h/{tid}/p/{pid}/submit', 'homework_detail_problem_submit')
class HomeworkDetailProblemSubmitHandler(contest.ContestMixin, base.Handler):
@base.route_argument
@base.require_perm(builtin.PERM_VIEW_HOMEWORK)
Expand Down Expand Up @@ -257,7 +257,7 @@ async def post(self, *, tid: objectid.ObjectId, pid: document.convert_doc_id,
self.json_or_redirect(self.reverse_url('record_detail', rid=rid))


@app.route('/homework/{tid}/scoreboard', 'homework_scoreboard')
@app.route('/h/{tid}/scoreboard', 'homework_scoreboard')
class HomeworkScoreboardHandler(contest.ContestMixin, base.Handler):
@base.route_argument
@base.require_perm(builtin.PERM_VIEW_HOMEWORK)
Expand All @@ -275,7 +275,7 @@ async def get(self, *, tid: objectid.ObjectId):
page_title=page_title, path_components=path_components)


@app.route('/homework/{tid}/scoreboard/download/{ext}', 'homework_scoreboard_download')
@app.route('/h/{tid}/scoreboard/download/{ext}', 'homework_scoreboard_download')
class HomeworkScoreboardDownloadHandler(contest.ContestMixin, base.Handler):
def _export_status_as_csv(self, rows):
# \r\n for notepad compatibility
Expand Down Expand Up @@ -357,7 +357,7 @@ async def post(self, *, title: str, content: str,
self.json_or_redirect(self.reverse_url('homework_detail', tid=tid))


@app.route('/homework/{tid}/edit', 'homework_edit')
@app.route('/h/{tid}/edit', 'homework_edit')
class HomeworkEditHandler(contest.ContestMixin, base.Handler):
@base.require_priv(builtin.PRIV_USER_PROFILE)
@base.require_perm(builtin.PERM_EDIT_HOMEWORK)
Expand Down
17 changes: 7 additions & 10 deletions vj4/handler/problem.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ async def star_unstar(self, *, pid: document.convert_doc_id, star: bool):
post_unstar = functools.partialmethod(star_unstar, star=False)


@app.route('/p/random', 'problem_random')
@app.route('/problem/random', 'problem_random')
class ProblemRandomHandler(base.Handler):
@base.require_perm(builtin.PERM_VIEW_PROBLEM)
@base.route_argument
Expand Down Expand Up @@ -185,7 +185,7 @@ async def get(self, *, category: str):
self.json_or_redirect(self.referer_or_main)


@app.route('/p/{pid:-?\d+|\w{24}}', 'problem_detail')
@app.route('/p/{pid:[a-zA-Z0-9]+}', 'problem_detail')
class ProblemDetailHandler(base.OperationHandler):
async def _get_related_trainings(self, pid):
if self.has_perm(builtin.PERM_VIEW_TRAINING):
Expand Down Expand Up @@ -568,7 +568,7 @@ async def get(self, *, pid: document.convert_doc_id):
secret=fdoc['metadata']['secret']))


@app.route('/p/create', 'problem_create')
@app.route('/problem/create', 'problem_create')
class ProblemCreateHandler(base.Handler):
@base.require_priv(builtin.PRIV_USER_PROFILE)
@base.require_perm(builtin.PERM_CREATE_PROBLEM)
Expand All @@ -580,16 +580,13 @@ async def get(self):
@base.post_argument
@base.require_csrf_token
@base.sanitize
async def post(self, *, title: str, content: str, hidden: bool=False, numeric_pid: bool=False):
pid = None
if numeric_pid:
pid = await domain.inc_pid_counter(self.domain_id)
async def post(self, *, title: str, content: str, hidden: bool=False, pname: str=None):
pid = await problem.add(self.domain_id, title, content, self.user['_id'],
hidden=hidden, pid=pid)
hidden=hidden, pname=pname)
self.json_or_redirect(self.reverse_url('problem_settings', pid=pid))


@app.route('/p/copy', 'problem_copy')
@app.route('/problem/copy', 'problem_copy')
class ProblemCopyHandler(base.Handler):
MAX_PROBLEMS_PER_REQUEST = 20

Expand Down Expand Up @@ -791,7 +788,7 @@ async def get(self, *, pid: document.convert_doc_id):
page_title=pdoc['title'], path_components=path_components)


@app.route('/p/search', 'problem_search')
@app.route('/problem/search', 'problem_search')
class ProblemSearchHandler(base.Handler):
@base.get_argument
@base.route_argument
Expand Down
15 changes: 15 additions & 0 deletions vj4/handler/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from vj4.model.adaptor import discussion
from vj4.model.adaptor import problem
from vj4.model.adaptor import setting
from vj4.util import pagination
from vj4.util import misc
from vj4.util import options
from vj4.util import validator
Expand Down Expand Up @@ -253,3 +254,17 @@ async def get(self, *, q: str, exact_match: bool=False):
for i in range(len(udocs)):
self.modify_udoc(udocs, i)
self.json(udocs)


@app.route('/ranking', 'domain_ranking')
class RankHandler(base.Handler):
USERS_PER_PAGE = 100
@base.get_argument
@base.sanitize
async def get(self, *, domain_id: str="system", page: int=1):
udocs, uucount, ucount = await pagination.paginate(domain.get_multi_user(domain_id=domain_id).sort([('rp', -1)]),
page, self.USERS_PER_PAGE)
for udoc in udocs:
udoc['uname'] = await user.get_by_uid(udoc['uid'])
udoc['uname'] = udoc['uname']['uname']
self.render('ranking.html', page=page, uucount=uucount, ucount=ucount, udocs=udocs, **kwargs)
3 changes: 2 additions & 1 deletion vj4/locale/zh_CN.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -773,7 +773,8 @@ display_name: 显示名
home_domain_account: 当前域的设置
'The value `{1}` of {0} already exists.': '{0} 的值 `{1}` 已经存在。'
Display name {1} you want to set is used by others.: 您想要设置的显示名 {1} 已经被其他人使用了。
Numeric PID: 数字题号
Leave blank to use numeric pid.: 留空以使用数字题号
PNAME: 题号
Only {0} problems can be copied in one request, got {1}.: 一次请求只能复制 {0} 个题目,但是您输入了 {1} 个。
Problem is successfully copied.: 题目复制完成。
problem_copy: 复制题目
Expand Down
32 changes: 26 additions & 6 deletions vj4/model/adaptor/problem.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,22 @@ def get_categories():

@argmethod.wrap
async def add(domain_id: str, title: str, content: str, owner_uid: int,
pid: document.convert_doc_id=None, data: objectid.ObjectId=None,
pid: document.convert_doc_id=None, pname: str=None, data: objectid.ObjectId=None,
category: list=[], tag: list=[], hidden: bool=False):
validator.check_title(title)
validator.check_content(content)
if not pid:
pid = await domain.inc_pid_counter(domain_id)
if not pname:
try:
pid = int(pid)
pname = 'P' + str(pid)
except ValueError:
pass
else:
validator.check_string_pname(pname)
pid = await document.add(domain_id, content, owner_uid, document.TYPE_PROBLEM,
pid, title=title, data=data, category=category, tag=tag,
pid, pname=pname, title=title, data=data, category=category, tag=tag,
hidden=hidden, num_submit=0, num_accept=0)
await domain.inc_user(domain_id, owner_uid, num_problems=1)
return pid
Expand All @@ -65,10 +75,9 @@ async def copy(pdoc, dest_domain_id: str, owner_uid: int,

@argmethod.wrap
async def get(domain_id: str, pid: document.convert_doc_id, uid: int = None):
pdoc = await document.get(domain_id, document.TYPE_PROBLEM, pid)
if not pdoc:
raise error.ProblemNotFoundError(domain_id, pid)
# TODO(twd2): move out:
pid = await document.get_pid(domain_id, pid)
pdoc = await document.get(domain_id, document.TYPE_PROBLEM, pid)
if uid is not None:
pdoc['psdoc'] = await document.get_status(domain_id, document.TYPE_PROBLEM,
doc_id=pid, uid=uid)
Expand All @@ -79,6 +88,7 @@ async def get(domain_id: str, pid: document.convert_doc_id, uid: int = None):

@argmethod.wrap
async def edit(domain_id: str, pid: document.convert_doc_id, **kwargs):
pid = await document.get_pid(domain_id, pid)
if 'title' in kwargs:
validator.check_title(kwargs['title'])
if 'content' in kwargs:
Expand Down Expand Up @@ -134,12 +144,14 @@ async def get_dict_multi_domain(pdom_and_ids, *, fields=None):

@argmethod.wrap
async def get_status(domain_id: str, pid: document.convert_doc_id, uid: int, fields=None):
pid = await document.get_pid(domain_id, pid)
return await document.get_status(domain_id, document.TYPE_PROBLEM, pid, uid, fields=fields)


@argmethod.wrap
async def inc_status(domain_id: str, pid: document.convert_doc_id, uid: int,
key: str, value: int):
pid = await document.get_pid(domain_id, pid)
return await document.inc_status(domain_id, document.TYPE_PROBLEM, pid, uid, key, value)


Expand All @@ -159,12 +171,14 @@ async def get_dict_status(domain_id, uid, pids, *, fields=None):

@argmethod.wrap
async def set_star(domain_id: str, pid: document.convert_doc_id, uid: int, star: bool):
pid = await document.get_pid(domain_id, pid)
return await document.set_status(domain_id, document.TYPE_PROBLEM, pid, uid, star=star)


@argmethod.wrap
async def add_solution(domain_id: str, pid: document.convert_doc_id, uid: int, content: str):
validator.check_content(content)
pid = await document.get_pid(domain_id, pid)
return await document.add(domain_id, content, uid, document.TYPE_PROBLEM_SOLUTION, None,
document.TYPE_PROBLEM, pid, vote=0, reply=[])

Expand All @@ -186,7 +200,8 @@ async def set_solution(domain_id: str, psid: document.convert_doc_id, content: s
return psdoc


def get_multi_solution(domain_id: str, pid: document.convert_doc_id, fields=None):
async def get_multi_solution(domain_id: str, pid: document.convert_doc_id, fields=None):
pid = await document.get_pid(domain_id, pid)
return document.get_multi(domain_id=domain_id,
doc_type=document.TYPE_PROBLEM_SOLUTION,
parent_doc_type=document.TYPE_PROBLEM,
Expand Down Expand Up @@ -214,6 +229,7 @@ async def delete_solution(domain_id: str, psid: document.convert_doc_id):
@argmethod.wrap
async def get_list_solution(domain_id: str, pid: document.convert_doc_id,
fields=None, skip: int = 0, limit: int = 0):
pid = await document.get_pid(domain_id, pid)
return await document.get_multi(domain_id=domain_id,
doc_type=document.TYPE_PROBLEM_SOLUTION,
parent_doc_type=document.TYPE_PROBLEM,
Expand Down Expand Up @@ -293,6 +309,7 @@ async def get_data(pdoc):

@argmethod.wrap
async def set_data(domain_id: str, pid: document.convert_doc_id, data: objectid.ObjectId):
pid = await document.get_pid(domain_id, pid)
pdoc = await document.set(domain_id, document.TYPE_PROBLEM, pid, data=data)
if not pdoc:
raise error.DocumentNotFoundError(domain_id, document.TYPE_PROBLEM, pid)
Expand All @@ -302,6 +319,7 @@ async def set_data(domain_id: str, pid: document.convert_doc_id, data: objectid.

@argmethod.wrap
async def set_hidden(domain_id: str, pid: document.convert_doc_id, hidden: bool):
pid = await document.get_pid(domain_id, pid)
pdoc = await document.set(domain_id, document.TYPE_PROBLEM, pid, hidden=hidden)
if not pdoc:
raise error.DocumentNotFoundError(domain_id, document.TYPE_PROBLEM, pid)
Expand Down Expand Up @@ -329,12 +347,14 @@ async def get_data_list(last: int):

@argmethod.wrap
async def inc(domain_id: str, pid: document.convert_doc_id, key: str, value: int):
pid = await document.get_pid(domain_id, pid)
return await document.inc(domain_id, document.TYPE_PROBLEM, pid, key, value)


@argmethod.wrap
async def update_status(domain_id: str, pid: document.convert_doc_id, uid: int,
rid: objectid.ObjectId, status: int):
pid = await document.get_pid(domain_id, pid)
try:
return await document.set_if_not_status(domain_id, document.TYPE_PROBLEM, pid, uid,
'status', status, constant.record.STATUS_ACCEPTED,
Expand Down
Loading