mirror of
https://gitcode.com/gh_mirrors/hy/Hydro.git
synced 2026-10-17 09:36:08 +08:00
record_main & record_detail
This commit is contained in:
1 parent
ffa193b5dd
commit
5b4f5b6520
37 files changed
+231
-275
No files matched your search
+2
-2
@@ -21,7 +21,7 @@ class ForbiddenError extends UserFacingError {
|
||||
}
|
||||
class NotFoundError extends UserFacingError {
|
||||
constructor(type) {
|
||||
super(type);
|
||||
super(type || 'NotFoundError');
|
||||
this.code = 404;
|
||||
}
|
||||
}
|
||||
@@ -107,7 +107,7 @@ class ContestNotFoundError extends NotFoundError {
|
||||
module.exports = {
|
||||
BadRequestError, ForbiddenError, NotFoundError,
|
||||
LoginError, UserAlreadyExistError, InvalidTokenError,
|
||||
UserNotFoundError, VerifyPasswordError,
|
||||
UserNotFoundError, VerifyPasswordError,
|
||||
OpcountExceededError, PermissionError, NoProblemError,
|
||||
ValidationError, ProblemNotFoundError, TrainingNotFoundError,
|
||||
ContestNotFoundError, RecordNotFoundError
|
||||
|
||||
@@ -44,6 +44,7 @@ MIDDLEWARE(async (ctx, next) => {
|
||||
}
|
||||
}
|
||||
};
|
||||
ctx.csrf_token = await token.add(token.TYPE_CSRF_TOKEN, 600, ctx.path);
|
||||
console.log(ctx.session.uid);
|
||||
await next();
|
||||
if (ctx.session.sid)
|
||||
|
||||
@@ -41,9 +41,18 @@ GET('/p/:pid', requirePerm(PERM_VIEW_PROBLEM), async ctx => {
|
||||
ctx.templateName = 'problem_detail.html';
|
||||
ctx.body = { pdoc, udoc, title: pdoc.title };
|
||||
});
|
||||
GET('/p/:pid/submit', requirePerm(PERM_SUBMIT_PROBLEM), async ctx => {
|
||||
let uid = ctx.state.user._id,
|
||||
pid = ctx.params.pid;
|
||||
let pdoc = await problem.get({ pid, uid });
|
||||
if (pdoc.hidden) ctx.checkPerm(PERM_VIEW_PROBLEM_HIDDEN);
|
||||
let udoc = await user.getById(pdoc.owner);
|
||||
ctx.templateName = 'problem_submit.html';
|
||||
ctx.body = { pdoc, udoc, title: pdoc.title };
|
||||
});
|
||||
POST('/p/:pid/submit', requirePerm(PERM_SUBMIT_PROBLEM), async ctx => {
|
||||
let rid = await record.add({
|
||||
creator: ctx.state.user._id,
|
||||
uid: ctx.state.user._id,
|
||||
lang: ctx.request.body.language,
|
||||
code: ctx.request.body.code,
|
||||
pid: ctx.params.pid
|
||||
|
||||
+11
-2
@@ -3,19 +3,28 @@ const
|
||||
{ constants } = require('../options'),
|
||||
{ GET } = require('../service/server'),
|
||||
record = require('../model/record'),
|
||||
user = require('../model/user'),
|
||||
problem = require('../model/problem'),
|
||||
{ PERM_READ_RECORD_CODE, PERM_VIEW_CONTEST_HIDDEN_SCOREBOARD } = require('../permission');
|
||||
|
||||
GET('/r', async ctx => {
|
||||
let q = {},
|
||||
page = ctx.query.page || 1;
|
||||
let rdocs = await record.getMany(q, { rid: 1 }, page, constants.RECORD_PER_PAGE);
|
||||
ctx.body = { page, rdocs };
|
||||
let pdict, udict;
|
||||
for (let rdoc in rdocs) {
|
||||
udict[rdoc.uid] = await user.getById(rdoc.uid);
|
||||
pdict[rdoc.pid] = await problem.get({ pid: rdoc.pid, uid: ctx.state.user._id });
|
||||
}
|
||||
ctx.templateName = 'record_main.html';
|
||||
ctx.body = { page, rdocs, pdict, udict };
|
||||
});
|
||||
GET('/r/:rid', async ctx => {
|
||||
let uid = ctx.state.user._id, rid = new bson.ObjectID(ctx.params.rid);
|
||||
let rdoc = await record.get(rid);
|
||||
if (rdoc.hidden) ctx.checkPerm(PERM_VIEW_CONTEST_HIDDEN_SCOREBOARD);
|
||||
if (rdoc.creator != uid && !ctx.state.user.hasPerm(PERM_READ_RECORD_CODE)) rdoc.code = null;
|
||||
if (rdoc.uid != uid && !ctx.state.user.hasPerm(PERM_READ_RECORD_CODE)) rdoc.code = null;
|
||||
ctx.templateName = 'record_detail.html';
|
||||
ctx.body = { rdoc };
|
||||
});
|
||||
|
||||
|
||||
+13
-9
@@ -70,7 +70,8 @@ MIDDLEWARE(async (ctx, next) => {
|
||||
ctx.render = async (name, context) => {
|
||||
ctx.user = ctx.state.user;
|
||||
ctx.translate = str => {
|
||||
return str.translate(ctx.state.user.language);
|
||||
if (!str) return '';
|
||||
return str.toString().translate(ctx.state.user.language);
|
||||
};
|
||||
ctx.has_perm = perm => ctx.state.user.hasPerm(perm);
|
||||
ctx.body = await new Promise((resolve, reject) => {
|
||||
@@ -87,15 +88,18 @@ MIDDLEWARE(async (ctx, next) => {
|
||||
try {
|
||||
try {
|
||||
await next();
|
||||
if (!ctx.body) throw new NotFoundError();
|
||||
if (ctx.query.template || ctx.templateName) {
|
||||
Object.assign(ctx.body, JSON.parse(ctx.query.data || '{}'));
|
||||
await ctx.render(ctx.query.template || ctx.templateName, ctx.body);
|
||||
} else if (ctx.setRedirect) {
|
||||
ctx.response.type = 'application/octet-stream';
|
||||
ctx.redirect(ctx.setRedirect);
|
||||
}
|
||||
if (ctx.body || ctx.templateName) {
|
||||
if (ctx.query.template || ctx.templateName) {
|
||||
ctx.body = ctx.body || {};
|
||||
Object.assign(ctx.body, JSON.parse(ctx.query.data || '{}'));
|
||||
await ctx.render(ctx.query.template || ctx.templateName, ctx.body);
|
||||
} else if (ctx.setRedirect) {
|
||||
ctx.response.type = 'application/octet-stream';
|
||||
ctx.redirect(ctx.setRedirect);
|
||||
}
|
||||
} else throw new NotFoundError();
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
if (error.toString().startsWith('Template render error')) throw error;
|
||||
await ctx.render('error.html', { error });
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
const
|
||||
{ GET, POST, CONTEXT } = require('../service/server.js'),
|
||||
{ GET, POST } = require('../service/server.js'),
|
||||
user = require('../model/user'),
|
||||
token = require('../model/token'),
|
||||
system = require('../model/system'),
|
||||
@@ -30,7 +30,8 @@ POST('/login', async ctx => {
|
||||
ctx.session.uid = udoc._id;
|
||||
ctx.session.rememberme = rememberme;
|
||||
ctx.body = {};
|
||||
ctx.setRedirect = ctx.request.headers.referer || '/';
|
||||
let referer = ctx.request.headers.referer || '/';
|
||||
ctx.setRedirect = referer.endsWith('/login') ? '/' : referer;
|
||||
});
|
||||
POST('/logout', requirePerm(PERM_LOGGEDIN), async ctx => {
|
||||
ctx.session = { uid: 1 };
|
||||
|
||||
+35
-1
@@ -177,6 +177,40 @@ const FOOTER_EXTRA_HTMLS = [];
|
||||
const VIEW_LANGS = [
|
||||
{ code: 'zh-CN', name: 'zh-CN' }
|
||||
];
|
||||
const LANGS = [
|
||||
{ id: 'cc', name: 'cpp' }
|
||||
];
|
||||
const LANG_TEXTS = {
|
||||
c: 'C',
|
||||
cc: 'C++',
|
||||
cs: 'C#',
|
||||
pas: 'Pascal',
|
||||
java: 'Java',
|
||||
py: 'Python',
|
||||
py3: 'Python 3',
|
||||
php: 'PHP',
|
||||
rs: 'Rust',
|
||||
hs: 'Haskell',
|
||||
js: 'JavaScript',
|
||||
go: 'Go',
|
||||
rb: 'Ruby',
|
||||
};
|
||||
const LANG_HIGHLIGHT_ID = {
|
||||
c: 'c',
|
||||
cc: 'cpp',
|
||||
cs: 'csharp',
|
||||
pas: 'pascal',
|
||||
java: 'java',
|
||||
py: 'python',
|
||||
py3: 'python',
|
||||
php: 'php',
|
||||
rs: 'rust',
|
||||
hs: 'haskell',
|
||||
js: 'javascript',
|
||||
go: 'go',
|
||||
rb: 'ruby',
|
||||
};
|
||||
module.exports = {
|
||||
BUILTIN_USERS, BUILTIN_ROLES, CATEGORIES, VIEW_LANGS, FOOTER_EXTRA_HTMLS
|
||||
BUILTIN_USERS, BUILTIN_ROLES, CATEGORIES, VIEW_LANGS, FOOTER_EXTRA_HTMLS, LANGS,
|
||||
LANG_TEXTS, LANG_HIGHLIGHT_ID
|
||||
};
|
||||
@@ -4,6 +4,7 @@ const
|
||||
|
||||
module.exports = {
|
||||
TYPE_SESSION: 0,
|
||||
TYPE_CSRF_TOKEN: 1,
|
||||
TYPE_REGISTER: 2,
|
||||
/**
|
||||
* Add a token.
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
{% macro form_begin(args) %}
|
||||
{% set label = args.pop('label') %}
|
||||
{% set columns = args.pop('columns') %}
|
||||
{% set last_column = args.pop('last_column', true) %}
|
||||
{% set required = args.pop('required', false) %}
|
||||
{% set hotkeys = args.pop('hotkeys', none) %}
|
||||
{% set row = args.pop('row', true) %}
|
||||
{% set no_label = args.pop('no_label', false) %}
|
||||
{% set label_wrap = args.pop('label_wrap', true) %}
|
||||
{% set label = args.label %}
|
||||
{% set columns = args.columns %}
|
||||
{% set last_column = args.last_column or true %}
|
||||
{% set required = args.required or false %}
|
||||
{% set hotkeys = args.hotkeys or none %}
|
||||
{% set row = args.row or true %}
|
||||
{% set no_label = args.no_label or false %}
|
||||
{% set label_wrap = args.label_wrap or true %}
|
||||
{% if row %}
|
||||
<div class="row">
|
||||
{% endif %}
|
||||
@@ -27,10 +27,10 @@
|
||||
{% endmacro %}
|
||||
|
||||
{% macro form_end(args) %}
|
||||
{% set help_text = args.pop('help_text', none) %}
|
||||
{% set row = args.pop('row', true) %}
|
||||
{% set no_label = args.pop('no_label', false) %}
|
||||
{% set label_wrap = args.pop('label_wrap', true) %}
|
||||
{% set help_text = args.help_text or none %}
|
||||
{% set row = args.row or true %}
|
||||
{% set no_label = args.no_label or false %}
|
||||
{% set label_wrap = args.label_wrap or true %}
|
||||
{% if not no_label and label_wrap %}
|
||||
</label>
|
||||
{% endif %}
|
||||
@@ -44,11 +44,11 @@
|
||||
{% endmacro %}
|
||||
|
||||
{% macro form_attr(form_class, args) %}
|
||||
{% set disabled = args.pop('disabled', false) %}
|
||||
{% set required = args.pop('required', false) %}
|
||||
{% set autofocus = args.pop('autofocus', false) %}
|
||||
{% set date = args.pop('date', false) %}
|
||||
{% set time = args.pop('time', false) %}
|
||||
{% set disabled = args.disabled or false %}
|
||||
{% set required = args.required or false %}
|
||||
{% set autofocus = args.autofocus or false %}
|
||||
{% set date = args.date or false %}
|
||||
{% set time = args.time or false %}
|
||||
class="{{ form_class }}{% if extra_class %} {{ extra_class }}{% endif %}"
|
||||
{% if disabled %}disabled{% endif %}
|
||||
{% if required %}required{% endif %}
|
||||
@@ -58,22 +58,22 @@
|
||||
{% endmacro %}
|
||||
|
||||
{% macro container_attr(container_class, args) %}
|
||||
{% set extra_class = args.pop('extra_class', none) %}
|
||||
{% set extra_class = args.extra_class or none %}
|
||||
class="{{ container_class }}{% if extra_class %} {{ extra_class }}{% endif %}"
|
||||
{% endmacro %}
|
||||
|
||||
{% macro select(options, name='', value='', args) %}
|
||||
{% macro select(args) %}
|
||||
<div
|
||||
name="form_item_{{ name }}"
|
||||
name="form_item_{{ args.name }}"
|
||||
{{ container_attr('select-container', args) }}
|
||||
>
|
||||
<select
|
||||
name="{{ name }}"
|
||||
name="{{ args.name }}"
|
||||
{{ form_attr('select', args) }}
|
||||
>
|
||||
{% for k, v in options %}
|
||||
<option value="{{ k }}"{% if value == k %} selected{% endif %}>
|
||||
{{ _(v) }}
|
||||
{% for item in args.options %}
|
||||
<option value="{{ item.id }}"{% if value == item.id %} selected{% endif %}>
|
||||
{{ _(item.name) }}
|
||||
</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
@@ -86,20 +86,20 @@
|
||||
{{ form_end({columns:columns}|assign(args)) }}
|
||||
{% endmacro %}
|
||||
|
||||
{% macro radio(options, name='', value='', args) %}
|
||||
{% macro radio(args) %}
|
||||
<div
|
||||
name="form_item_{{ name }}"
|
||||
name="form_item_{{ args.name }}"
|
||||
{{ container_attr('radiobox-container', args) }}
|
||||
>
|
||||
{% for k, v in options %}
|
||||
{% for item in options %}
|
||||
<label class="radiobox">
|
||||
<input
|
||||
value="{{ k }}"
|
||||
value="{{ item.id }}"
|
||||
type="radio"
|
||||
name="{{ name }}"
|
||||
name="{{ args.name }}"
|
||||
{{ form_attr('radiobox__input', args) }}
|
||||
{% if value == k %} checked{% endif %}
|
||||
/> {{ _(v) }}
|
||||
{% if value == args.id %} checked{% endif %}
|
||||
/> {{ _(item.name) }}
|
||||
</label>
|
||||
{% endfor %}
|
||||
</div>
|
||||
@@ -111,22 +111,22 @@
|
||||
{{ form_end({columns:columns, label_warp:false}|assign(args)) }}
|
||||
{% endmacro %}
|
||||
|
||||
{% macro image_radio(options, name='', value='', image_class='', args) %}
|
||||
{% macro image_radio(args) %}
|
||||
<div
|
||||
name="form_item_{{ name }}"
|
||||
name="form_item_{{ args.name }}"
|
||||
{{ container_attr('radiobox-container with-image', args) }}
|
||||
>
|
||||
{% for k, v in options %}
|
||||
{% for item in options %}
|
||||
<label class="radiobox with-image">
|
||||
<input
|
||||
value="{{ k }}"
|
||||
value="{{ item.id }}"
|
||||
type="radio"
|
||||
name="{{ name }}"
|
||||
{{ form_attr('radiobox__input', args) }}
|
||||
{% if value == k %} checked{% endif %}
|
||||
{% if value == item.id %} checked{% endif %}
|
||||
/>
|
||||
<div class="radiobox__image-container" data-tooltip="{{ _(v) }}">
|
||||
<div class="radiobox__image {{ image_class.format(k) }}"></div>
|
||||
<div class="radiobox__image-container" data-tooltip="{{ _(item.name) }}">
|
||||
<div class="radiobox__image {{ image_class.format(item.id) }}"></div>
|
||||
</div>
|
||||
</label>
|
||||
{% endfor %}
|
||||
@@ -139,16 +139,16 @@
|
||||
{{ form_end({columns:columns, label_warp:false}|assign(args)) }}
|
||||
{% endmacro %}
|
||||
|
||||
{% macro text(name='', value='', placeholder='', type='text', args) %}
|
||||
{% macro text(args) %}
|
||||
<div
|
||||
name="form_item_{{ name }}"
|
||||
name="form_item_{{ args.name }}"
|
||||
{{ container_attr('textbox-container', args) }}
|
||||
>
|
||||
<input
|
||||
type="{{ type }}"
|
||||
name="{{ name }}"
|
||||
value="{{ value }}"
|
||||
placeholder="{{ placeholder }}"
|
||||
type="{{ args.type or 'text' }}"
|
||||
name="{{ args.name }}"
|
||||
value="{{ args.value }}"
|
||||
placeholder="{{ args.placeholder }}"
|
||||
{{ form_attr('textbox', args) }}
|
||||
>
|
||||
</div>
|
||||
@@ -160,18 +160,18 @@
|
||||
{{ form_end({columns:columns}|assign(args)) }}
|
||||
{% endmacro %}
|
||||
|
||||
{% macro textarea(name='', value='', placeholder='', args) %}
|
||||
{% set markdown = args.pop('markdown', false) %}
|
||||
{% macro textarea(args) %}
|
||||
{% set markdown = args.markdown or false %}
|
||||
<div
|
||||
name="form_item_{{ name }}"
|
||||
name="form_item_{{ args.name }}"
|
||||
{{ container_attr('textarea-container', args) }}
|
||||
>
|
||||
<textarea
|
||||
name="{{ name }}"
|
||||
placeholder="{{ placeholder }}"
|
||||
name="{{ args.name }}"
|
||||
placeholder="{{ args.placeholder }}"
|
||||
{% if markdown %}data-markdown{% endif %}
|
||||
{{ form_attr('textbox', args) }}
|
||||
>{{ value }}</textarea>
|
||||
>{{ args.value }}</textarea>
|
||||
</div>
|
||||
{% endmacro %}
|
||||
|
||||
@@ -181,15 +181,15 @@
|
||||
{{ form_end({columns:columns}|assign(args)) }}
|
||||
{% endmacro %}
|
||||
|
||||
{% macro checkbox(label='', name='', value=false, args) %}
|
||||
{% macro checkbox(args) %}
|
||||
<div
|
||||
name="form_item_{{ name }}"
|
||||
name="form_item_{{ args.name }}"
|
||||
{{ container_attr('checkbox-container', args) }}
|
||||
>
|
||||
<label class="checkbox">
|
||||
<input type="checkbox" name="{{ name }}"{% if value %} checked{% endif %}
|
||||
<input type="checkbox" name="{{ args.name }}"{% if args.value %} checked{% endif %}
|
||||
{{ form_attr('checkbox', args) }}
|
||||
>{{ _(label) }}
|
||||
>{{ _(args.label) }}
|
||||
</label>
|
||||
</div>
|
||||
{% endmacro %}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
{% macro render_status_td(rdoc, rid_key='_id') %}
|
||||
<td class="col--status record-status--border {{ vj4.constant.record.STATUS_CODES[rdoc['status']] }}">
|
||||
<td class="col--status record-status--border {{ status.STATUS_CODES[rdoc['status']] }}">
|
||||
<div class="col--status__text">
|
||||
<span class="icon record-status--icon {{ vj4.constant.record.STATUS_CODES[rdoc['status']] }}"></span>
|
||||
<a href="{{ reverse_url('record_detail', rid=rdoc[rid_key], domain_id=rdoc['domain_id']) }}" class="record-status--text {{ vj4.constant.record.STATUS_CODES[rdoc['status']] }}">
|
||||
{{ vj4.constant.record.STATUS_TEXTS[rdoc['status']] }}
|
||||
<span class="icon record-status--icon {{ status.STATUS_CODES[rdoc['status']] }}"></span>
|
||||
<a href="{{ reverse_url('record_detail', rid=rdoc[rid_key], domain_id=rdoc['domain_id']) }}" class="record-status--text {{ status.STATUS_CODES[rdoc['status']] }}">
|
||||
{{ status.STATUS_TEXTS[rdoc['status']] }}
|
||||
</a>
|
||||
</div>
|
||||
{% if rdoc['status'] == vj4.constant.record.STATUS_JUDGING %}
|
||||
{% if rdoc['status'] == status.STATUS_JUDGING %}
|
||||
<div class="col--status__progress-container">
|
||||
<div class="col--status__progress" style="width: {{ rdoc['progress']|default(50)|int }}%"></div>
|
||||
</div>
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
</div>
|
||||
<div class="media__right middle">
|
||||
<div class="section__body">
|
||||
<a href="{{ reverse_url('contest_detail', tid=tdoc['doc_id']) }}" class="detail-button">{{ _('View Details') }}</a>
|
||||
<a href="/t/{{ tdoc._id }}" class="detail-button">{{ _('View Details') }}</a>
|
||||
<div class="typo text-center">
|
||||
{% if tsdict[tdoc['doc_id']]['attend'] == 1 %}
|
||||
<p><span class="icon icon-check"></span> {{ _('Attended') }}</p>
|
||||
@@ -87,7 +87,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="media__body medium">
|
||||
<h1 class="contest__title"><a href="{{ reverse_url('contest_detail', tid=tdoc['doc_id']) }}" data-emoji-enabled>{{ tdoc['title'] }}</a></h1>
|
||||
<h1 class="contest__title"><a href="/t/{{ tdoc._id }}" data-emoji-enabled>{{ tdoc['title'] }}</a></h1>
|
||||
<ul class="supplementary list">
|
||||
<li>
|
||||
<a href="?rule={{ tdoc['rule'] }}" class="contest-type-tag"><span class="icon icon-award"></span>{{ vj4.constant.contest.RULE_TEXTS[tdoc['rule']] }}</a>
|
||||
|
||||
@@ -101,7 +101,7 @@
|
||||
<div class="balancer sidebar-user-stat">
|
||||
<div class="balancer__body">
|
||||
<div class="numbox">
|
||||
<div class="numbox__num medium">{{ dudict[ddoc['owner_uid']]['num_accept'] or 0 }}</div>
|
||||
<div class="numbox__num medium">{{ dudict[ddoc['owner_uid']].nAccept or 0 }}</div>
|
||||
<div class="numbox__text">{{ _('Accepted') }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="media__body medium">
|
||||
<h1 class="contest__title"><a href="{{ reverse_url('contest_detail', tid=tdoc['doc_id']) }}" data-emoji-enabled>{{ tdoc['title'] }}</a></h1>
|
||||
<h1 class="contest__title"><a href="/t/{{ tdoc._id }}" data-emoji-enabled>{{ tdoc['title'] }}</a></h1>
|
||||
<ul class="supplementary list">
|
||||
<li>
|
||||
<a href="{{ reverse_url('contest_main') }}?rule={{ tdoc['rule'] }}" class="contest-type-tag"><span class="icon icon-award"></span>{{ vj4.constant.contest.RULE_TEXTS[tdoc['rule']] }}</a>
|
||||
|
||||
@@ -13,10 +13,8 @@
|
||||
{% block content %}{% endblock %}
|
||||
</div>
|
||||
|
||||
{% with show_topics = false %}
|
||||
{% include "partials/footer.html" %}
|
||||
{% endwith %}
|
||||
|
||||
{% set show_topics = false %}
|
||||
{% include "partials/footer.html" %}
|
||||
</div>
|
||||
|
||||
{% include "partials/login_dialog.html" %}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
{% import "components/contest.html" as contest with context %}
|
||||
<div class="section side">
|
||||
{% if page_name != 'contest_detail' %}
|
||||
<a class="contest-sidebar__bg" href="{{ reverse_url('contest_detail', tid=tdoc['doc_id']) }}">
|
||||
<a class="contest-sidebar__bg" href="/t/{{ tdoc._id }}">
|
||||
<div class="section__body">
|
||||
<h1>{{ tdoc['title'] }}</h1>
|
||||
<div class="contest-sidebar__status">
|
||||
@@ -34,14 +34,14 @@
|
||||
<li class="menu__seperator"></li>
|
||||
{% endif %}
|
||||
{% if page_name != 'contest_detail' %}
|
||||
<li class="menu__item"><a class="menu__link" href="{{ reverse_url('contest_detail', tid=tdoc['doc_id']) }}">
|
||||
<li class="menu__item"><a class="menu__link" href="/t/{{ tdoc._id }}">
|
||||
<span class="icon icon-award"></span> {{ _('View Contest') }}
|
||||
</a></li>
|
||||
{% endif %}
|
||||
{% if not attended and not handler.is_done(tdoc) %}
|
||||
<li class="menu__item">
|
||||
{% if handler.has_perm(perm.PERM_ATTEND_CONTEST) and handler.has_perm(perm.PERM_LOGGEDIN) %}
|
||||
<form action="{{ reverse_url('contest_detail', tid=tdoc['doc_id']) }}" method="POST">
|
||||
<form action="/t/{{ tdoc._id }}" method="POST">
|
||||
<input type="hidden" name="operation" value="attend">
|
||||
<input type="hidden" name="csrf_token" value="{{ handler.csrf_token }}">
|
||||
<button class="menu__link" type="submit">
|
||||
@@ -78,7 +78,7 @@
|
||||
<span class="icon icon-download"></span> {{ _('Export All Code') }}
|
||||
</a></li>
|
||||
{% endif %}
|
||||
<li class="menu__item"><a class="menu__link" href="{{ reverse_url('record_main') }}?tid={{ tdoc['doc_id'] }}">
|
||||
<li class="menu__item"><a class="menu__link" href="/r?tid={{ tdoc['doc_id'] }}">
|
||||
<span class="icon icon-flag"></span> {{ _('All Submissions') }}
|
||||
</a></li>
|
||||
<li class="menu__item"><a class="menu__link" href="{{ reverse_url('wiki_help') }}#contest">
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
</span>
|
||||
</h1>
|
||||
<div class="footer__category__expander"><ul class="footer__category__list">
|
||||
<li class="footer__category__item"><a href="{{ reverse_url('record_main') }}">{{ _('Judging Queue') }}</a></li>
|
||||
<li class="footer__category__item"><a href="/r">{{ _('Judging Queue') }}</a></li>
|
||||
<li class="footer__category__item"><a href="#">{{ _('Service Status') }}</a></li>
|
||||
</ul></div>
|
||||
</div>
|
||||
@@ -34,9 +34,6 @@
|
||||
</span>
|
||||
</h1>
|
||||
<div class="footer__category__expander"><ul class="footer__category__list">
|
||||
{% if domain_id != vj4.model.builtin.DOMAIN_ID_SYSTEM %}
|
||||
<li class="footer__category__item"><a href="{{ reverse_url('domain_main', domain_id=vj4.model.builtin.DOMAIN_ID_SYSTEM) }}">{{ _('Vijos') }}</a></li>
|
||||
{% endif %}
|
||||
<li class="footer__category__item"><a href="//vijos.github.io/about-vijos/">{{ _('Help') }}</a></li>
|
||||
<!--<li class="footer__category__item"><a href="#">{{ _('Blog') }}</a></li>-->
|
||||
<li class="footer__category__item"><a href="//vijos.github.io/about-vijos/about/contact-us/">{{ _('QQ Group') }}</a></li>
|
||||
|
||||
@@ -2,12 +2,7 @@
|
||||
<div class="header--mobile">
|
||||
<div class="row"><div class="columns clearfix">
|
||||
<div class="float-left">
|
||||
{% if domain_id == vj4.model.builtin.DOMAIN_ID_SYSTEM %}
|
||||
<a class="header--mobile__domain is--system" href="{{ reverse_url('domain_main', domain_id=vj4.model.builtin.DOMAIN_ID_SYSTEM) }}" target="_self"> </a>
|
||||
{% else %}
|
||||
<a class="header--mobile__domain" href="{{ reverse_url('domain_main') }}" target="_self">{{ domain['name'] }}</a>
|
||||
<a class="header--mobile__system" href="{{ reverse_url('domain_main', domain_id=vj4.model.builtin.DOMAIN_ID_SYSTEM) }}" target="_blank">Powered by Vijos</a>
|
||||
{% endif %}
|
||||
<a class="header--mobile__domain is--system" href="/" target="_self"> </a>
|
||||
</div>
|
||||
<div class="float-right">
|
||||
{% include "partials/hamburger.html" %}
|
||||
|
||||
@@ -63,7 +63,7 @@
|
||||
</a></li>
|
||||
{% endif %}
|
||||
{% if attended %}
|
||||
<li class="menu__item"><a class="menu__link" href="{{ reverse_url('record_main') }}?uid_or_name={{ handler.user['_id'] }}&tid={{ tdoc['doc_id'] }}">
|
||||
<li class="menu__item"><a class="menu__link" href="/r?uid_or_name={{ handler.user['_id'] }}&tid={{ tdoc['doc_id'] }}">
|
||||
<span class="icon icon-flag"></span> {{ _('My Recent Submissions') }}
|
||||
</a></li>
|
||||
{% endif %}
|
||||
|
||||
@@ -30,10 +30,10 @@
|
||||
{% endif %}
|
||||
{% if handler.own(pdoc, perm.PERM_EDIT_PROBLEM_SELF) or handler.has_perm(perm.PERM_EDIT_PROBLEM) %}
|
||||
<li class="menu__seperator"></li>
|
||||
<li class="menu__item"><a class="menu__link{% if page_name == 'problem_edit' %} active{% endif %}" href="{{ reverse_url('problem_edit', pid=pdoc['_id']) }}">
|
||||
<li class="menu__item"><a class="menu__link{% if page_name == 'problem_edit' %} active{% endif %}" href="/p/{{ pdoc.pid }}/edit">
|
||||
<span class="icon icon-edit"></span> {{ _('Edit') }}
|
||||
</a></li>
|
||||
<li class="menu__item"><a class="menu__link{% if page_name == 'problem_settings' %} active{% endif %}" href="{{ reverse_url('problem_settings', pid=pdoc['_id']) }}">
|
||||
<li class="menu__item"><a class="menu__link{% if page_name == 'problem_settings' %} active{% endif %}" href="/p/{{ pdoc.pid }}/settings">
|
||||
<span class="icon icon-wrench"></span> {{ _('Settings') }}
|
||||
</a></li>
|
||||
{% endif %}
|
||||
|
||||
@@ -30,10 +30,10 @@
|
||||
{% endif %}
|
||||
{% if handler.own(pdoc, perm.PERM_EDIT_PROBLEM_SELF) or handler.has_perm(perm.PERM_EDIT_PROBLEM) %}
|
||||
<li class="menu__seperator"></li>
|
||||
<li class="menu__item"><a class="menu__link{% if page_name == 'problem_edit' %} active{% endif %}" href="{{ reverse_url('problem_edit', pid=pdoc['_id']) }}">
|
||||
<li class="menu__item"><a class="menu__link{% if page_name == 'problem_edit' %} active{% endif %}" href="/p/{{ pdoc.pid }}/edit">
|
||||
<span class="icon icon-edit"></span> {{ _('Edit') }}
|
||||
</a></li>
|
||||
<li class="menu__item"><a class="menu__link{% if page_name == 'problem_settings' %} active{% endif %}" href="{{ reverse_url('problem_settings', pid=pdoc['_id']) }}">
|
||||
<li class="menu__item"><a class="menu__link{% if page_name == 'problem_settings' %} active{% endif %}" href="/p/{{ pdoc.pid }}/settings">
|
||||
<span class="icon icon-wrench"></span> {{ _('Settings') }}
|
||||
</a></li>
|
||||
{% endif %}
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
</a></li>
|
||||
{% endif %}
|
||||
{% if handler.has_perm(perm.PERM_SUBMIT_PROBLEM) %}
|
||||
<li class="menu__item scratchpad--hide"><a class="menu__link{% if page_name == 'problem_submit' %} active{% endif %}" href="{{ reverse_url('problem_submit', pid=pdoc['_id']) }}">
|
||||
<li class="menu__item scratchpad--hide"><a class="menu__link{% if page_name == 'problem_submit' %} active{% endif %}" href="/p/{{ pdoc.pid }}/submit">
|
||||
<span class="icon icon-send"></span> {{ _('Submit') }}
|
||||
</a></li>
|
||||
{% elif not handler.has_perm(perm.PERM_LOGGEDIN) %}
|
||||
@@ -60,7 +60,7 @@
|
||||
</a></li>
|
||||
{% endif %}
|
||||
{% if handler.has_perm(perm.PERM_VIEW_PROBLEM_SOLUTION) %}
|
||||
<li class="menu__item"><a class="menu__link{% if page_name == 'problem_solution' %} active{% endif %}" href="{{ reverse_url('problem_solution', pid=pdoc['_id']) }}">
|
||||
<li class="menu__item"><a class="menu__link{% if page_name == 'problem_solution' %} active{% endif %}" href="/p/{{ pdoc.pid }}/solution">
|
||||
<span class="icon icon-comment--text"></span> {{ _('Solutions') }}
|
||||
</a></li>
|
||||
{% endif %}
|
||||
@@ -72,10 +72,10 @@
|
||||
{% endif %}
|
||||
{% if handler.user._id == pdoc.owner or handler.has_perm(perm.PERM_EDIT_PROBLEM) %}
|
||||
<li class="menu__seperator"></li>
|
||||
<li class="menu__item"><a class="menu__link{% if page_name == 'problem_edit' %} active{% endif %}" href="{{ reverse_url('problem_edit', pid=pdoc['_id']) }}">
|
||||
<li class="menu__item"><a class="menu__link{% if page_name == 'problem_edit' %} active{% endif %}" href="/p/{{ pdoc.pid }}/edit">
|
||||
<span class="icon icon-edit"></span> {{ _('Edit') }}
|
||||
</a></li>
|
||||
<li class="menu__item"><a class="menu__link{% if page_name == 'problem_settings' %} active{% endif %}" href="{{ reverse_url('problem_settings', pid=pdoc['_id']) }}">
|
||||
<li class="menu__item"><a class="menu__link{% if page_name == 'problem_settings' %} active{% endif %}" href="/p/{{ pdoc.pid }}/settings">
|
||||
<span class="icon icon-wrench"></span> {{ _('Settings') }}
|
||||
</a></li>
|
||||
{% endif %}
|
||||
@@ -98,15 +98,15 @@
|
||||
<dt>{{ _('Submission') }}</dt>
|
||||
<dd>
|
||||
{% if pdoc['psdoc']['status'] %}
|
||||
<span class="icon record-status--icon {{ vj4.constant.record.STATUS_CODES[pdoc['psdoc']['status']] }}"></span>
|
||||
<a href="{{ reverse_url('record_detail', rid=pdoc['psdoc']['rid'], domain_id=pdoc['psdoc']['domain_id']) }}" class="record-status--text {{ vj4.constant.record.STATUS_CODES[pdoc['psdoc']['status']] }}">
|
||||
{{ vj4.constant.record.STATUS_TEXTS[pdoc['psdoc']['status']] }}
|
||||
<span class="icon record-status--icon {{ status.STATUS_CODES[pdoc['psdoc']['status']] }}"></span>
|
||||
<a href="/r/{{ pdoc['psdoc']['rid'] }}" class="record-status--text {{ status.STATUS_CODES[pdoc['psdoc']['status']] }}">
|
||||
{{ status.STATUS_TEXTS[pdoc['psdoc']['status']] }}
|
||||
</a>
|
||||
{% else %}
|
||||
{{ _('(None)') }}
|
||||
{% endif %}
|
||||
</dd>
|
||||
{% if pdoc['ac_msg'] and pdoc['psdoc']['status'] == vj4.constant.record.STATUS_ACCEPTED %}
|
||||
{% if pdoc['ac_msg'] and pdoc['psdoc']['status'] == status.STATUS_ACCEPTED %}
|
||||
<dt>{{ _('AC Message') }}</dt>
|
||||
<dd>{{ pdoc['ac_msg'] }}</dd>
|
||||
{% endif %}
|
||||
@@ -141,17 +141,17 @@
|
||||
{{ problem.render_problem_tags(pdoc, true) }}
|
||||
</dd>
|
||||
<dt>{{ _('# Submissions') }}</dt>
|
||||
<dd><a href="{{ reverse_url('record_main') }}?pid={{ pdoc['_id'] }}">{{ pdoc['num_submit'] }}</a></dd>
|
||||
<dd><a href="/r?pid={{ pdoc['_id'] }}">{{ pdoc.nSubmit }}</a></dd>
|
||||
{% if page_name != 'discussion_node' and page_name != 'discussion_detail' %}
|
||||
{% if handler.has_perm(perm.PERM_LOGGEDIN) %}
|
||||
<dt>{{ _('# My Submissions') }}</dt>
|
||||
<dd><a href="{{ reverse_url('record_main') }}?pid={{ pdoc['_id'] }}&uid_or_name={{ handler.user['_id'] }}">{{ pdoc['psdoc']['num_submit']|default(0) }}</a></dd>
|
||||
<dd><a href="/r?pid={{ pdoc['_id'] }}&uid_or_name={{ handler.user['_id'] }}">{{ pdoc['psdoc'].nSubmit|default(0) }}</a></dd>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
<dt>{{ _('Accepted') }}</dt>
|
||||
<dd>{{ pdoc['num_accept'] }}</dd>
|
||||
<dd>{{ pdoc.nAccept }}</dd>
|
||||
<dt>{{ _('Accepted Ratio') }}</dt>
|
||||
<dd>{% if pdoc['num_submit'] > 0 %}{{ (100 * pdoc['num_accept'] / pdoc['num_submit'])|round|int }}%{% else %}{{ _('?') }}{% endif %}</dd>
|
||||
<dd>{% if pdoc.nSubmit > 0 %}{{ (100 * pdoc.nAccept / pdoc.nSubmit)|round|int }}%{% else %}{{ _('?') }}{% endif %}</dd>
|
||||
{% if pdoc['num_be_copied'] %}
|
||||
<dt>{{ _('Be Copied') }}</dt>
|
||||
<dd>{{ pdoc['num_be_copied'] }}</dd>
|
||||
@@ -178,7 +178,7 @@
|
||||
{% if ctdocs %}
|
||||
<p>{{ _('In following contests') }}: </p>
|
||||
{% for tdoc in ctdocs %}
|
||||
<p><a href="{{ reverse_url('contest_detail', tid=tdoc['doc_id']) }}">{{ tdoc['title'] }}</a></p>
|
||||
<p><a href="/t/{{ tdoc._id }}">{{ tdoc['title'] }}</a></p>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if htdocs %}
|
||||
|
||||
@@ -59,7 +59,7 @@
|
||||
</div>
|
||||
<div class="medium-3 columns">
|
||||
{% if page_name == 'problem_edit' %}
|
||||
{% with owner_udoc=udoc, owner_dudoc=dudoc %}
|
||||
{% set owner_udoc=udoc %}{% set owner_dudoc=dudoc %}
|
||||
{% include "partials/problem_sidebar.html" %}
|
||||
{% endwith %}
|
||||
{% else %}
|
||||
|
||||
@@ -8,8 +8,8 @@
|
||||
<div class="row">
|
||||
<div class="medium-8 columns">
|
||||
<label>
|
||||
{{ _('Copy from') }}
|
||||
<input name="src_domain_id" placeholder="{{ _('Domain ID') }}" class="textbox" autocomplete="off">
|
||||
{{ _('Import from') }}
|
||||
<input name="src" placeholder="{{ _('Source') }}" class="textbox" autocomplete="off">
|
||||
</label>
|
||||
</div>
|
||||
<div class="medium-2 columns">
|
||||
@@ -17,7 +17,7 @@
|
||||
{{ _('Settings') }}
|
||||
<br>
|
||||
<label class="checkbox">
|
||||
<input type="checkbox" name="numeric_pid" value="on" checked>{{ _('Numeric PID') }}
|
||||
<input name="src" placeholder="{{ _('ProblemID') }}" class="textbox" autocomplete="off">
|
||||
</label>
|
||||
</label>
|
||||
</div>
|
||||
@@ -32,8 +32,8 @@
|
||||
</div>
|
||||
<div class="row"><div class="columns">
|
||||
<label>
|
||||
{{ _('Problem ID List') }}
|
||||
<textarea name="src_pids" class="textbox" style="height: 300px"></textarea>
|
||||
{{ _('Source URL') }}
|
||||
<textarea name="src" class="textbox" style="height: 300px"></textarea>
|
||||
</label>
|
||||
</div></div>
|
||||
<div class="row"><div class="columns">
|
||||
@@ -52,10 +52,10 @@
|
||||
<div class="medium-3 columns">
|
||||
<div class="section side">
|
||||
<div class="section__body typo">
|
||||
<h2>{{ _('What\'s this?') }}</h2>
|
||||
<p>{{ _('With this feature, you can copy problems that you can view from a domain to some other domain. Their title, content, tags and categories will be copied. However, their test data are not copied directly.') }}</p>
|
||||
<h2>{{ _('What is this?') }}</h2>
|
||||
<p>{{ _('With this feature, you can import problems that you can view from a site to here. Their title, content, tags and categories will be imported. However, their test data are not copied directly.') }}</p>
|
||||
<h2>{{ _('About test data') }}</h2>
|
||||
<p>{{ _('Instead of copying the test data directly, the test data of the copied problems will be linked to the test data of the source problems (called the source test data). Thus, the copied problems can observe the changes in the source test data. The permissions of the test data of the copied problems follow the source test data, e.g., you still might not download them but the judges can. By uploading some new test data, the link will be broken and the new test data will be used.') }}</p>
|
||||
<p>{{ _('Instead of copying the test data directly, the test data of the import problems will be linked to the test data of the source problems (called the source test data). Thus, the copied problems can observe the changes in the source test data. The permissions of the test data of the copied problems follow the source test data, e.g., you still might not download them but the judges can. By uploading some new test data, the link will be broken and the new test data will be used.') }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -10,7 +10,7 @@
|
||||
<iframe src="{{ reverse_url('problem_upload', pid=pdoc['_id']) }}" frameborder="0" style="width: 100%; height: 100px;"></iframe>
|
||||
<p class="help-text">{{ _('Hint') }}: <a href="{{ reverse_url('wiki_help') }}#upload">{{ _('Dataset Format') }}</a>, {{ _('An example of dataset') }}: <a href="https://github.com/vijos/jd4/blob/master/jd4/testdata/aplusb-legacy.zip?raw=true">{{ _('Download') }}</a></p>
|
||||
{% if pdoc and (handler.own(pdoc, perm.PERM_READ_PROBLEM_DATA_SELF) or handler.has_perm(perm.PERM_READ_PROBLEM_DATA) or handler.has_priv(vj4.model.builtin.PRIV_READ_PROBLEM_DATA)) %}
|
||||
<p><a href="{{ reverse_url('problem_data', pid=pdoc['_id']) }}" class="expanded button">{{ _('Download Dataset') }}</a></p>
|
||||
<p><a href="/p/{{ pdoc.pid }}/data" class="expanded button">{{ _('Download Dataset') }}</a></p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
@@ -65,7 +65,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="medium-3 columns">
|
||||
{% with owner_udoc=udoc, owner_dudoc=dudoc %}
|
||||
{% set owner_udoc=udoc %}{% set owner_dudoc=dudoc %}
|
||||
{% include "partials/problem_sidebar.html" %}
|
||||
{% endwith %}
|
||||
</div>
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="medium-3 columns">
|
||||
{% with owner_udoc=udoc, owner_dudoc=dudoc %}
|
||||
{% set owner_udoc=udoc %}{% set owner_dudoc=dudoc %}
|
||||
{% include "partials/problem_sidebar.html" %}
|
||||
{% endwith %}
|
||||
</div>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
{% set page_name = "problem_submit" %}
|
||||
{% extends "layout/basic.html" %}
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
@@ -44,7 +45,7 @@
|
||||
</div>
|
||||
<div class="section__body">
|
||||
<form method="post">
|
||||
{{ form.form_select(label='Code language', options=vj4.constant.language.LANG_TEXTS.items(), name='lang', value=handler.get_setting('code_lang')) }}
|
||||
{{ form.form_select(label='Code language', options=builtin.LANGS, name='lang', value=handler.user.codeLang) }}
|
||||
{{ form.form_textarea(label='Code', columns=12, name='code', extra_class='monospace', autofocus=true) }}
|
||||
<div class="row"><div class="columns">
|
||||
<input type="hidden" name="csrf_token" value="{{ handler.csrf_token }}">
|
||||
@@ -55,9 +56,8 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="medium-3 columns">
|
||||
{% with owner_udoc=udoc, owner_dudoc=dudoc %}
|
||||
{% set owner_udoc=udoc %}{% set owner_dudoc=dudoc %}
|
||||
{% include "partials/problem_sidebar.html" %}
|
||||
{% endwith %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -9,10 +9,10 @@
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="col--memory">
|
||||
{{ (rdoc['memory_kb'] / 1000)|round(0, 'ceil')|int }} MB
|
||||
{{ (rdoc.memory / 1000)|round(0, 'ceil')|int }} MB
|
||||
</td>
|
||||
<td class="col--time">
|
||||
{{ (rdoc['time_ms'] / 1000)|round(1) }}s
|
||||
{{ (rdoc.time / 1000)|round(1) }}s
|
||||
</td>
|
||||
<td class="col--submit-at">{{ datetime_span(rdoc['_id'].generation_time) }}</td>
|
||||
</tr>
|
||||
@@ -1,8 +1,8 @@
|
||||
{% extends 'layout/simple.html' %}
|
||||
{% block body %}
|
||||
<form method="post" enctype="multipart/form-data">
|
||||
{% if pdoc['data'] is mapping %}
|
||||
<p><b>{{ _('Current dataset comes from') }} <a href="{{ reverse_url('problem_detail', domain_id=pdoc['data']['domain'], pid=pdoc['data']['pid']) }}" target="_blank">{{ pdoc['data']['domain'] }}/{{ pdoc['data']['pid'] }}</a></b></p>
|
||||
{% if pdoc['data'].startsWith('from:') %}
|
||||
<p><b>{{ _('Current dataset comes from') }} <a href="{{ pdoc.data.split('from:')[1] }}" target="_blank">{{ pdoc.data.split('from:')[1] }}</a></b></p>
|
||||
{% else %}
|
||||
<p>{{ _('Current dataset: {0}').format(pdoc['data']|default(_('(None)'))) }}</p>
|
||||
<p>{{ _('MD5: {0}').format(md5|default(_('(None)'))) }}</p>
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
{% import "components/problem.html" as problem with context %}
|
||||
{% block content %}
|
||||
<script>
|
||||
var Context = {{ {
|
||||
'socketUrl': socket_url,
|
||||
}|json|safe }};
|
||||
var Context = {
|
||||
'socketUrl': "{{ socket_url }}",
|
||||
};
|
||||
</script>
|
||||
<div class="row">
|
||||
<div class="medium-9 columns">
|
||||
@@ -17,7 +17,7 @@
|
||||
<h1 class="section__title">{{ _('Code') }}</h1>
|
||||
</div>
|
||||
<div class="section__body" data-syntax-hl-show-line-number>
|
||||
<pre><code class="language-{{ vj4.constant.language.LANG_HIGHLIGHT_ID[rdoc['lang']] }}">{{ rdoc['code'] }}</code></pre>
|
||||
<pre><code class="language-{{ builtin.LANG_HIGHLIGHT_ID[rdoc['lang']] }}">{{ rdoc['code'] }}</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
@@ -31,7 +31,7 @@
|
||||
<div class="section__body no-padding">
|
||||
<ol class="menu">
|
||||
<li class="menu__item">
|
||||
<form method="post" action="{{ reverse_url('record_rejudge', rid=rdoc['_id']) }}">
|
||||
<form method="post" action="/r/{{ rdoc._id }}/rejudge">
|
||||
<input type="hidden" name="csrf_token" value="{{ handler.csrf_token }}">
|
||||
<button type="submit" class="menu__link">
|
||||
<span class="icon icon-refresh"></span> {{ _('Rejudge') }}
|
||||
@@ -39,7 +39,8 @@
|
||||
</form>
|
||||
</li>
|
||||
<li class="menu__item">
|
||||
<form method="post" action="{{ reverse_url('judge_score', rid=rdoc['_id']) }}">
|
||||
<form method="post" action="/judge/end">
|
||||
<input type="hidden" name="rid" value="{{ rdoc._id }}">
|
||||
<input type="hidden" name="csrf_token" value="{{ handler.csrf_token }}">
|
||||
<input type="hidden" name="score" value="0">
|
||||
<input type="hidden" name="message" value="{{ _('score canceled') }}">
|
||||
@@ -67,7 +68,7 @@
|
||||
{% if tdoc['doc_type'] == vj4.model.document.TYPE_CONTEST %}
|
||||
<dt>{{ _('Contest') }}</dt>
|
||||
<dd>
|
||||
<a href="{{ reverse_url('contest_detail', tid=tdoc['doc_id']) }}">{{ tdoc['title'] }}</a>
|
||||
<a href="/t/{{ tdoc._id }}">{{ tdoc['title'] }}</a>
|
||||
</dd>
|
||||
{% else %}{# tdoc['doc_type'] == vj4.model.document.TYPE_CONTEST #}
|
||||
<dt>{{ _('Homework') }}</dt>
|
||||
@@ -81,7 +82,7 @@
|
||||
<dd><a href="{{ reverse_url('record_pretest_data', rid=rdoc['_id']) }}"><span class="icon icon-download"></span> {{ _('Download') }}</a></dd>
|
||||
{% elif rdoc['type'] == vj4.constant.record.TYPE_SUBMISSION and pdoc and (handler.own(pdoc, perm.PERM_READ_PROBLEM_DATA_SELF) or handler.has_perm(perm.PERM_READ_PROBLEM_DATA) or handler.has_priv(vj4.model.builtin.PRIV_READ_PROBLEM_DATA)) %}
|
||||
<dt>{{ _('Problem Data') }}</dt>
|
||||
<dd><a href="{{ reverse_url('problem_data', pid=pdoc['_id']) }}"><span class="icon icon-download"></span> {{ _('Download') }}</a></dd>
|
||||
<dd><a href="/p/{{ pdoc.pid }}/data"><span class="icon icon-download"></span> {{ _('Download') }}</a></dd>
|
||||
{% endif %}
|
||||
<dt>{{ _('Language') }}</dt>
|
||||
<dd>
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
<div class="section visible" id="status">
|
||||
<div class="section__header">
|
||||
<h1 class="section__title">
|
||||
<span class="icon record-status--icon {{ vj4.constant.record.STATUS_CODES[rdoc['status']] }}"></span>
|
||||
<span class="record-status--text {{ vj4.constant.record.STATUS_CODES[rdoc['status']] }}">
|
||||
{{ vj4.constant.record.STATUS_TEXTS[rdoc['status']] }}
|
||||
<span class="icon record-status--icon {{ status.STATUS_CODES[rdoc['status']] }}"></span>
|
||||
<span class="record-status--text {{ status.STATUS_CODES[rdoc['status']] }}">
|
||||
{{ status.STATUS_TEXTS[rdoc['status']] }}
|
||||
</span>
|
||||
</h1>
|
||||
</div>
|
||||
<div class="section__body">
|
||||
<pre class="compiler-text">{{ rdoc['compiler_texts']|join('\n') }}</pre>
|
||||
<pre class="compiler-text">{{ rdoc.compilerTexts|join('\n') }}</pre>
|
||||
</div>
|
||||
{% if rdoc['judge_texts'] %}
|
||||
{% if rdoc.judgeTexts %}
|
||||
<div class="section__body">
|
||||
<pre class="judge-text">{{ rdoc['judge_texts']|join('\n') }}</pre>
|
||||
<pre class="judge-text">{{ rdoc.judgeTexts|join('\n') }}</pre>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if rdoc['cases'] %}
|
||||
@@ -35,19 +35,19 @@
|
||||
<tbody>
|
||||
{% for rcdoc in rdoc['cases'] %}
|
||||
<tr>
|
||||
<td class="col--case record-status--border {{ vj4.constant.record.STATUS_CODES[rcdoc['status']] }}">
|
||||
<td class="col--case record-status--border {{ status.STATUS_CODES[rcdoc['status']] }}">
|
||||
#{{ loop.index }}
|
||||
</td>
|
||||
<td class="col--status">
|
||||
<span class="icon record-status--icon {{ vj4.constant.record.STATUS_CODES[rcdoc['status']] }}"></span>
|
||||
<span class="record-status--text {{ vj4.constant.record.STATUS_CODES[rcdoc['status']] }}">
|
||||
{{ vj4.constant.record.STATUS_TEXTS[rcdoc['status']] }}
|
||||
<span class="icon record-status--icon {{ status.STATUS_CODES[rcdoc['status']] }}"></span>
|
||||
<span class="record-status--text {{ status.STATUS_CODES[rcdoc['status']] }}">
|
||||
{{ status.STATUS_TEXTS[rcdoc['status']] }}
|
||||
</span>
|
||||
<span>{{ rcdoc['judge_text'] }}</span>
|
||||
<a class="tool-button" href="{{ reverse_url('wiki_help') }}#status"><span class="icon icon-help"></span></a>
|
||||
</td>
|
||||
<td class="col--time">{% if rcdoc['status'] == vj4.constant.record.STATUS_TIME_LIMIT_EXCEEDED or rcdoc['status'] == vj4.constant.record.STATUS_MEMORY_LIMIT_EXCEEDED or rcdoc['status'] == vj4.constant.record.STATUS_OUTPUT_LIMIT_EXCEEDED %}≥{% endif %}{{ rcdoc['time_ms'] }}ms</td>
|
||||
<td class="col--memory">{% if rcdoc['status'] == vj4.constant.record.STATUS_TIME_LIMIT_EXCEEDED or rcdoc['status'] == vj4.constant.record.STATUS_MEMORY_LIMIT_EXCEEDED or rcdoc['status'] == vj4.constant.record.STATUS_OUTPUT_LIMIT_EXCEEDED %}≥{% endif %}{{ rcdoc['memory_kb']|format_size(1024) }}</td>
|
||||
<td class="col--time">{% if rcdoc['status'] == status.STATUS_TIME_LIMIT_EXCEEDED or rcdoc['status'] == status.STATUS_MEMORY_LIMIT_EXCEEDED or rcdoc['status'] == status.STATUS_OUTPUT_LIMIT_EXCEEDED %}≥{% endif %}{{ rcdoc['time_ms'] }}ms</td>
|
||||
<td class="col--memory">{% if rcdoc['status'] == status.STATUS_TIME_LIMIT_EXCEEDED or rcdoc['status'] == status.STATUS_MEMORY_LIMIT_EXCEEDED or rcdoc['status'] == status.STATUS_OUTPUT_LIMIT_EXCEEDED %}≥{% endif %}{{ rcdoc['memory_kb']|format_size(1024) }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<dd>{{ rdoc['score'] }}</dd>
|
||||
{% endif %}
|
||||
<dt>{{ _('Total Time') }}</dt>
|
||||
<dd>{% if rdoc['status'] == vj4.constant.record.STATUS_TIME_LIMIT_EXCEEDED or rdoc['status'] == vj4.constant.record.STATUS_MEMORY_LIMIT_EXCEEDED or rdoc['status'] == vj4.constant.record.STATUS_OUTPUT_LIMIT_EXCEEDED %}≥{% endif %}{{ rdoc['time_ms'] }}ms</dd>
|
||||
<dd>{% if rdoc['status'] == status.STATUS_TIME_LIMIT_EXCEEDED or rdoc['status'] == status.STATUS_MEMORY_LIMIT_EXCEEDED or rdoc['status'] == status.STATUS_OUTPUT_LIMIT_EXCEEDED %}≥{% endif %}{{ rdoc.time }}ms</dd>
|
||||
<dt>{{ _('Peak Memory') }}</dt>
|
||||
<dd>{% if rdoc['status'] == vj4.constant.record.STATUS_TIME_LIMIT_EXCEEDED or rdoc['status'] == vj4.constant.record.STATUS_MEMORY_LIMIT_EXCEEDED or rdoc['status'] == vj4.constant.record.STATUS_OUTPUT_LIMIT_EXCEEDED %}≥{% endif %}{{ rdoc['memory_kb']|format_size(1024) }}</dd>
|
||||
<dd>{% if rdoc['status'] == status.STATUS_TIME_LIMIT_EXCEEDED or rdoc['status'] == status.STATUS_MEMORY_LIMIT_EXCEEDED or rdoc['status'] == status.STATUS_OUTPUT_LIMIT_EXCEEDED %}≥{% endif %}{{ rdoc.memory|format_size(1024) }}</dd>
|
||||
</dl>
|
||||
@@ -1,9 +1,10 @@
|
||||
{% set page_name = "record_main" %}
|
||||
{% extends "layout/basic.html" %}
|
||||
{% block content %}
|
||||
<script>
|
||||
var Context = {{ {
|
||||
'socketUrl': socket_url,
|
||||
}|json|safe }};
|
||||
var Context = {
|
||||
'socketUrl': "/socket/{{ socket_url }}",
|
||||
};
|
||||
</script>
|
||||
<div class="row">
|
||||
<div class="medium-12 columns">
|
||||
@@ -13,7 +14,7 @@
|
||||
<h1 class="section__title">{{ _('Filter') }}</h1>
|
||||
<div class="section__tools">
|
||||
<button type="submit" class="primary button"><span class="icon icon-filter"></span> {{ _('Filter') }}</button>
|
||||
<a href="{{ reverse_url('record_main') }}" class="button">{{ _('Reset') }}</a>
|
||||
<a href="/r" class="button">{{ _('Reset') }}</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section__body">
|
||||
@@ -73,13 +74,13 @@
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for rdoc in rdocs %}
|
||||
{% with udoc = udict[rdoc['uid']], dudoc = dudict[rdoc['uid']], pdoc = pdict[(rdoc['domain_id'], rdoc['pid'])] %}
|
||||
{% set udoc = udict[rdoc['uid']] %}
|
||||
{% set pdoc = pdict[rdoc['pid']] %}
|
||||
{% include 'record_main_tr.html' %}
|
||||
{% endwith %}
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% if handler.has_priv(vj4.model.builtin.PRIV_VIEW_JUDGE_STATISTICS) %}
|
||||
{% if handler.has_perm(perm.PERM_VIEW_JUDGE_STATISTICS) %}
|
||||
<ul class="pager">
|
||||
<li>
|
||||
<a class="pager__item next link" href="?start={{ rdocs[-1]['_id'] }}&{{ query_string }}">{{ _('pager_next') }}</a>
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
<tr data-rid="{{ rdoc['_id'] }}">
|
||||
{{ record.render_status_td(rdoc) }}
|
||||
<td class="col--problem col--problem-name">
|
||||
{% if (rdoc['domain_id'] == handler.domain_id and handler.has_perm(perm.PERM_REJUDGE)) or handler.has_priv(vj4.model.builtin.PRIV_REJUDGE) %}
|
||||
<form class="form--inline" method="post" action="{{ reverse_url('record_rejudge', rid=rdoc['_id']) }}">
|
||||
{% if = handler.has_perm(perm.PERM_REJUDGE) %}
|
||||
<form class="form--inline" method="post" action="/r/{{ rdoc._id }}/rejudge">
|
||||
<input type="hidden" name="csrf_token" value="{{ handler.csrf_token }}">
|
||||
<button type="submit" class="link text-maroon lighter">
|
||||
<span class="icon icon-refresh"></span>
|
||||
@@ -15,23 +15,19 @@
|
||||
{% if rdoc['type'] == vj4.constant.record.TYPE_PRETEST %}
|
||||
({{ _('Pretest') }})
|
||||
{% endif %}
|
||||
{% if pdoc and (not pdoc['hidden'] or (pdoc['domain_id'] == handler.domain_id and handler.has_perm(perm.PERM_VIEW_PROBLEM_HIDDEN))) %}
|
||||
{% if pdoc and (not pdoc['hidden'] or handler.has_perm(perm.PERM_VIEW_PROBLEM_HIDDEN)) %}
|
||||
{{ problem.render_problem_title(pdoc, show_tags=false) }}
|
||||
{% else %}
|
||||
*
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="col--submit-by">
|
||||
<a href="{{ reverse_url('user_detail', uid=rdoc['uid']) }}">
|
||||
{% if dudoc['display_name'] %}
|
||||
{{ dudoc['display_name'] }} ({{ udoc['uname'] }})
|
||||
{% else %}
|
||||
{{ udoc['uname'] }}
|
||||
{% endif %}
|
||||
<a href="/u/{{ rdoc.uid }}">
|
||||
{{ udoc['uname'] }}
|
||||
</a>
|
||||
</td>
|
||||
<td class="col--time">{% if rdoc['status'] == vj4.constant.record.STATUS_TIME_LIMIT_EXCEEDED or rdoc['status'] == vj4.constant.record.STATUS_MEMORY_LIMIT_EXCEEDED or rdoc['status'] == vj4.constant.record.STATUS_OUTPUT_LIMIT_EXCEEDED %}≥{% endif %}{{ rdoc['time_ms'] }}ms</td>
|
||||
<td class="col--memory">{% if rdoc['status'] == vj4.constant.record.STATUS_TIME_LIMIT_EXCEEDED or rdoc['status'] == vj4.constant.record.STATUS_MEMORY_LIMIT_EXCEEDED or rdoc['status'] == vj4.constant.record.STATUS_OUTPUT_LIMIT_EXCEEDED %}≥{% endif %}{{ rdoc['memory_kb']|format_size(1024) }}</td>
|
||||
<td class="col--time">{% if rdoc['status'] == status.STATUS_TIME_LIMIT_EXCEEDED or rdoc['status'] == status.STATUS_MEMORY_LIMIT_EXCEEDED or rdoc['status'] == status.STATUS_OUTPUT_LIMIT_EXCEEDED %}≥{% endif %}{{ rdoc.time }}ms</td>
|
||||
<td class="col--memory">{% if rdoc['status'] == status.STATUS_TIME_LIMIT_EXCEEDED or rdoc['status'] == status.STATUS_MEMORY_LIMIT_EXCEEDED or rdoc['status'] == status.STATUS_OUTPUT_LIMIT_EXCEEDED %}≥{% endif %}{{ rdoc.memory|format_size(1024) }}</td>
|
||||
<td class="col--lang">{{ vj4.constant.language.LANG_TEXTS[rdoc['lang']] }}</td>
|
||||
<td class="col--submit-at">{{ datetime_span(rdoc['_id'].generation_time) }}</td>
|
||||
</tr>
|
||||
@@ -1,87 +0,0 @@
|
||||
{% macro form_begin(kwargs) %}
|
||||
{% set label = kwargs.pop('label') %}
|
||||
{% set columns = kwargs.pop('columns') %}
|
||||
{% set last_column = kwargs.pop('last_column', true) %}
|
||||
{% set required = kwargs.pop('required', false) %}
|
||||
{% set hotkeys = kwargs.pop('hotkeys', none) %}
|
||||
{% set row = kwargs.pop('row', true) %}
|
||||
{% set no_label = kwargs.pop('no_label', false) %}
|
||||
{% set label_wrap = kwargs.pop('label_wrap', true) %}
|
||||
{% if row %}
|
||||
<div class="row">
|
||||
{% endif %}
|
||||
<div
|
||||
class="{% if columns %}medium-{{ columns }} {% endif %}columns form__item{% if last_column %} end{% endif %}"
|
||||
{% if hotkeys %}data-hotkey="{{ hotkeys }}"{% endif %}
|
||||
>
|
||||
{% if not no_label %}
|
||||
<label>
|
||||
{{ _(label) }}
|
||||
{% if required %}
|
||||
({{ _('required') }})
|
||||
{% endif %}
|
||||
{% if not label_wrap %}
|
||||
</label>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endmacro %}
|
||||
|
||||
{% macro form_end(kwargs) %}
|
||||
{% set help_text = kwargs.pop('help_text', none) %}
|
||||
{% set row = kwargs.pop('row', true) %}
|
||||
{% set no_label = kwargs.pop('no_label', false) %}
|
||||
{% set label_wrap = kwargs.pop('label_wrap', true) %}
|
||||
{% if not no_label and label_wrap %}
|
||||
</label>
|
||||
{% endif %}
|
||||
{% if help_text %}
|
||||
<p class="help-text">{{ _(help_text)|safe }}</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% if row %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endmacro %}
|
||||
|
||||
{% macro form_attr(form_class, kwargs) %}
|
||||
{% set disabled = kwargs.pop('disabled', false) %}
|
||||
{% set required = kwargs.pop('required', false) %}
|
||||
{% set autofocus = kwargs.pop('autofocus', false) %}
|
||||
{% set date = kwargs.pop('date', false) %}
|
||||
{% set time = kwargs.pop('time', false) %}
|
||||
class="{{ form_class }}{% if extra_class %} {{ extra_class }}{% endif %}"
|
||||
{% if disabled %}disabled{% endif %}
|
||||
{% if required %}required{% endif %}
|
||||
{% if autofocus %}autofocus data-autofocus{% endif %}
|
||||
{% if date %}data-pick-date{% endif %}
|
||||
{% if time %}data-pick-time{% endif %}
|
||||
{% endmacro %}
|
||||
|
||||
{% macro container_attr(container_class, kwargs) %}
|
||||
{% set extra_class = kwargs.pop('extra_class', none) %}
|
||||
class="{{ container_class }}{% if extra_class %} {{ extra_class }}{% endif %}"
|
||||
{% endmacro %}
|
||||
|
||||
{% macro select(options, name='', value='', kwargs) %}
|
||||
<div
|
||||
name="form_item_{{ name }}"
|
||||
{{ container_attr('select-container', kwargs) }}
|
||||
>
|
||||
<select
|
||||
name="{{ name }}"
|
||||
{{ form_attr('select', kwargs) }}
|
||||
>
|
||||
{% for k, v in options %}
|
||||
<option value="{{ k }}"{% if value == k %} selected{% endif %}>
|
||||
{{ _(v) }}
|
||||
</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
{% endmacro %}
|
||||
|
||||
{% macro form_select(columns=5) %}
|
||||
{{ form_begin({columns:1, ...kwargs}, kwargs) }}
|
||||
{{ select(columns=columns, kwargs) }}
|
||||
{{ form_end(columns=columns, kwargs) }}
|
||||
{% endmacro %}
|
||||
@@ -126,11 +126,11 @@
|
||||
pdoc,
|
||||
invalid=not tsdoc['enroll'],
|
||||
show_tags=false,
|
||||
rp=vj4.job.rp.get_rp_expect(pdoc) if (not psdoc or psdoc['status'] != vj4.constant.record.STATUS_ACCEPTED) else none
|
||||
rp=vj4.job.rp.get_rp_expect(pdoc) if (not psdoc or psdoc['status'] != status.STATUS_ACCEPTED) else none
|
||||
) }}
|
||||
</td>
|
||||
<td class="col--submit_n">{{ pdoc['num_submit'] }}</td>
|
||||
<td class="col--ac_rate">{{ (100 * pdoc['num_accept'] / pdoc['num_submit'])|round|int if pdoc['num_submit'] > 0 else _('?') }}</td>
|
||||
<td class="col--submit_n">{{ pdoc.nSubmit }}</td>
|
||||
<td class="col--ac_rate">{{ (100 * pdoc.nAccept / pdoc.nSubmit)|round|int if pdoc.nSubmit > 0 else _('?') }}</td>
|
||||
<td class="col--difficulty">{{ pdoc['difficulty'] or _('(None)') }}</td>
|
||||
</tr>
|
||||
{% endwith %}
|
||||
|
||||
@@ -12,12 +12,7 @@
|
||||
</div>
|
||||
<div class="media__body profile-header__main">
|
||||
<h1>
|
||||
{% if dudoc['display_name'] %}
|
||||
{{ dudoc['display_name'] }}
|
||||
<small>{{ udoc['uname'] }}</small>
|
||||
{% else %}
|
||||
{{ udoc['uname'] }}
|
||||
{% endif %}
|
||||
{{ udoc['uname'] }}
|
||||
<small>({{ _('UID') }}: {{ udoc['_id'] }})</small>
|
||||
</h1>
|
||||
<p>
|
||||
@@ -29,14 +24,14 @@
|
||||
{{ _('currently offline') }}.
|
||||
{% endif %}
|
||||
</p>
|
||||
<p>{{ _('Solved {0} problems, RP: {1} (No. {2})').format(dudoc['num_accept']|default(0), dudoc['rp']|default(0.0)|round(2), dudoc['rank']|default('?')) }}</p>
|
||||
<p>{{ _('Solved {0} problems, RP: {1} (No. {2})').format(dudoc.nAccept|default(0), dudoc['rp']|default(0.0)|round(2), dudoc['rank']|default('?')) }}</p>
|
||||
<div class="profile-header__contact-bar">
|
||||
{% if is_self_profile %}
|
||||
<a class="profile-header__contact-item" href="{{ reverse_url('home_account') }}#setting_info" data-tooltip="{{ _('Edit Profile') }}">
|
||||
<span class="icon icon-edit"></span>
|
||||
</a>
|
||||
{% endif %}
|
||||
<a class="profile-header__contact-item" href="{{ reverse_url('home_messages') }}?target_uid={{ udoc['_id'] }}" target="_blank" data-tooltip="{{ _('Send Message') }}">
|
||||
<a class="profile-header__contact-item" href="/home/messages?target_uid={{ udoc['_id'] }}" target="_blank" data-tooltip="{{ _('Send Message') }}">
|
||||
<span class="icon icon-comment--multiple"></span>
|
||||
</a>
|
||||
{% if handler.can_view(udoc, 'mail') and udoc['mail'] %}
|
||||
@@ -137,7 +132,7 @@
|
||||
</div>
|
||||
</li>
|
||||
<li class="section__tab-item">
|
||||
<h1 class="section__tab-title">{{ _('Submissions') }} ({{ dudoc['num_submit']|default(0) }})</h1>
|
||||
<h1 class="section__tab-title">{{ _('Submissions') }} ({{ dudoc.nSubmit|default(0) }})</h1>
|
||||
<div class="section__tab-main">
|
||||
{% if not rdocs %}
|
||||
{{ nothing.render('Oh, the user hasn\'t submitted yet!') }}
|
||||
@@ -193,7 +188,7 @@
|
||||
<div class="balancer sidebar-user-stat">
|
||||
<div class="balancer__body">
|
||||
<div class="numbox">
|
||||
<div class="numbox__num medium">{{ dudoc['num_accept'] or 0 }}</div>
|
||||
<div class="numbox__num medium">{{ dudoc.nAccept or 0 }}</div>
|
||||
<div class="numbox__text">{{ _('Accepted') }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
{% set page_name = "user_login" %}
|
||||
{% extends "layout/immersive.html" %}
|
||||
{% block content %}
|
||||
<div class="row"><div class="columns">
|
||||
|
||||
Reference in new issue
Block a user