core: 支持限制题目的提交语言

This commit is contained in:
undefined committed 2021-05-18 23:38:58 +08:00
1 parent f33d440b68
commit 75429bb43b
10 files changed
+44 -25

No files matched your search

+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "hydrooj", "name": "hydrooj",
"version": "2.26.12", "version": "2.26.13",
"bin": "bin/hydrooj.js", "bin": "bin/hydrooj.js",
"main": "dist/loader.js", "main": "dist/loader.js",
"typings": "dist/loader.d.ts", "typings": "dist/loader.d.ts",
+4 -1
View File
@@ -4,7 +4,7 @@ import AdmZip from 'adm-zip';
import { isSafeInteger } from 'lodash'; import { isSafeInteger } from 'lodash';
import { import {
ContestNotLiveError, ValidationError, ProblemNotFoundError, ContestNotLiveError, ValidationError, ProblemNotFoundError,
ContestNotAttendedError, PermissionError, ContestNotAttendedError, PermissionError, BadRequestError,
} from '../error'; } from '../error';
import { ProblemDoc, Tdoc, User } from '../interface'; import { ProblemDoc, Tdoc, User } from '../interface';
import paginate from '../lib/paginate'; import paginate from '../lib/paginate';
@@ -344,6 +344,9 @@ class ContestDetailProblemSubmitHandler extends ContestProblemHandler {
@param('lang', Types.Name) @param('lang', Types.Name)
@param('code', Types.Content) @param('code', Types.Content)
async post(domainId: string, tid: ObjectID, lang: string, code: string) { async post(domainId: string, tid: ObjectID, lang: string, code: string) {
if (this.response.body.pdoc.config.langs && !this.response.body.pdoc.config.langs.includes('lang')) {
throw new BadRequestError('Language not allowed.');
}
await this.limitRate('add_record', 60, 10); await this.limitRate('add_record', 60, 10);
const rid = await record.add(domainId, this.pdoc.docId, this.user._id, lang, code, true, { const rid = await record.add(domainId, this.pdoc.docId, this.user._id, lang, code, true, {
type: document.TYPE_CONTEST, type: document.TYPE_CONTEST,
+3
View File
@@ -264,6 +264,9 @@ export class ProblemSubmitHandler extends ProblemDetailHandler {
@param('lang', Types.Name) @param('lang', Types.Name)
@param('code', Types.Content) @param('code', Types.Content)
async post(domainId: string, lang: string, code: string) { async post(domainId: string, lang: string, code: string) {
if (this.response.body.pdoc.config.langs && !this.response.body.pdoc.config.langs.includes('lang')) {
throw new BadRequestError('Language not allowed.');
}
await this.limitRate('add_record', 60, 5); await this.limitRate('add_record', 60, 5);
const rid = await record.add(domainId, this.pdoc.docId, this.user._id, lang, code, true); const rid = await record.add(domainId, this.pdoc.docId, this.user._id, lang, code, true);
const [rdoc] = await Promise.all([ const [rdoc] = await Promise.all([
+14 -13
View File
@@ -143,19 +143,20 @@ export interface SubtaskConfig {
} }
export interface ProblemConfig { export interface ProblemConfig {
type?: ProblemType, type?: ProblemType;
score?: number, score?: number;
time?: string, time?: string;
memory?: string, memory?: string;
filename?: string, filename?: string;
checker_type?: string, checker_type?: string;
checker?: string, checker?: string;
interactor?: string, interactor?: string;
user_extra_files?: string[], user_extra_files?: string[];
judge_extra_files?: string[], judge_extra_files?: string[];
outputs?: [string, number][], outputs?: [string, number][];
cases?: TestCaseConfig[], cases?: TestCaseConfig[];
subtasks?: SubtaskConfig[], subtasks?: SubtaskConfig[];
langs?: string[];
} }
export interface PlainContentNode { export interface PlainContentNode {
+7 -5
View File
@@ -3,11 +3,12 @@ import { load } from 'js-yaml';
import type { ProblemConfig } from '../interface'; import type { ProblemConfig } from '../interface';
interface ParseResult { interface ParseResult {
count: number, count: number;
memoryMax: number, memoryMax: number;
memoryMin: number, memoryMin: number;
timeMax: number, timeMax: number;
timeMin: number, timeMin: number;
langs?: string[];
} }
export async function parseConfig(config: string | ProblemConfig = {}) { export async function parseConfig(config: string | ProblemConfig = {}) {
@@ -40,6 +41,7 @@ export async function parseConfig(config: string | ProblemConfig = {}) {
if (result.timeMax < result.timeMin) { if (result.timeMax < result.timeMin) {
result.timeMax = result.timeMin = 1000; result.timeMax = result.timeMin = 1000;
} }
if (cfg.langs) result.langs = cfg.langs;
return result; return result;
} }
+2 -1
View File
@@ -284,7 +284,8 @@ const t = Math.exp(-0.15);
async function updateSort() { async function updateSort() {
const cursor = document.coll.find({ docType: document.TYPE_DISCUSSION }); const cursor = document.coll.find({ docType: document.TYPE_DISCUSSION });
while (cursor.hasNext()) { // eslint-disable-next-line no-await-in-loop
while (await cursor.hasNext()) {
// eslint-disable-next-line no-await-in-loop // eslint-disable-next-line no-await-in-loop
const data = await cursor.next(); const data = await cursor.next();
// eslint-disable-next-line no-await-in-loop // eslint-disable-next-line no-await-in-loop
@@ -78,6 +78,11 @@ export default connect(mapStateToProps, mapDispatchToProps)(class ScratchpadTool
} }
render() { render() {
const LANGS = {};
for (const key in window.LANGS) {
if (UiContext.pdoc.config.langs && !UiContext.pdoc.config.langs.includes(key)) continue;
LANGS[key] = window.LANGS[key];
}
return ( return (
<Toolbar> <Toolbar>
<ToolbarButton <ToolbarButton
@@ -136,7 +141,7 @@ export default connect(mapStateToProps, mapDispatchToProps)(class ScratchpadTool
value={this.props.editorLang} value={this.props.editorLang}
onChange={(ev) => this.props.setEditorLanguage(ev.target.value)} onChange={(ev) => this.props.setEditorLanguage(ev.target.value)}
> >
{_.map(window.LANGS, (val, key) => ( {_.map(LANGS, (val, key) => (
<option value={key} key={key}>{val.display}</option> <option value={key} key={key}>{val.display}</option>
))} ))}
</select> </select>
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "@hydrooj/ui-default", "name": "@hydrooj/ui-default",
"version": "4.8.25", "version": "4.8.26",
"author": "undefined <i@undefined.moe>", "author": "undefined <i@undefined.moe>",
"license": "AGPL-3.0", "license": "AGPL-3.0",
"main": "hydro.js", "main": "hydro.js",
@@ -15,12 +15,13 @@ const page = new NamedPage(['problem_submit', 'contest_detail_problem_submit'],
$('#codelang-main-select').on('change', function () { $('#codelang-main-select').on('change', function () {
const options = {}; const options = {};
for (const key in window.LANGS) { for (const key in window.LANGS) {
if (UiContext.pdocConfig.langs && !UiContext.pdocConfig.langs.includes(key)) continue;
if (key.startsWith(`${this.value}.`) && key !== this.value) options[key] = window.LANGS[key].display; if (key.startsWith(`${this.value}.`) && key !== this.value) options[key] = window.LANGS[key].display;
} }
if (Object.keys(options).length > 1) { if (Object.keys(options).length > 1) {
setOptions($('#codelang-sub-select'), options); setOptions($('#codelang-sub-select'), options);
$('#codelang-sub-container').show(); $('#codelang-sub-container').show();
$('[name="codeLang"]').val($('#codelang-sub-container').val()); $('[name="codeLang"]').val($('#codelang-sub-select').val());
} else { } else {
$('#codelang-sub-container').hide(); $('#codelang-sub-container').hide();
$('[name="codeLang"]').val(this.value); $('[name="codeLang"]').val(this.value);
@@ -31,6 +32,7 @@ const page = new NamedPage(['problem_submit', 'contest_detail_problem_submit'],
}); });
const main = {}; const main = {};
for (const key in window.LANGS) { for (const key in window.LANGS) {
if (UiContext.pdocConfig.langs && !UiContext.pdocConfig.langs.includes(key)) continue;
if (!key.includes('.')) main[key] = window.LANGS[key].display; if (!key.includes('.')) main[key] = window.LANGS[key].display;
} }
setOptions($('#codelang-main-select'), main); setOptions($('#codelang-main-select'), main);
@@ -38,7 +40,8 @@ const page = new NamedPage(['problem_submit', 'contest_detail_problem_submit'],
if (current.includes('.')) { if (current.includes('.')) {
const [m, s] = current.split('.'); const [m, s] = current.split('.');
$('#codelang-main-select').val(m); $('#codelang-main-select').val(m);
$('#codelang-sub-select').val(s).show(); $('#codelang-sub-select').val(s);
$('#codelang-sub-container').show();
} else $('#codelang-main-select').val(current); } else $('#codelang-main-select').val(current);
}); });
@@ -1,5 +1,6 @@
{% extends "layout/basic.html" %} {% extends "layout/basic.html" %}
{% block content %} {% block content %}
{{ set(UiContext, 'pdocConfig', pdoc.config) }}
<div class="row"> <div class="row">
<div class="medium-9 columns"> <div class="medium-9 columns">
{% if not tdoc or rdocs.length %} {% if not tdoc or rdocs.length %}