mirror of
https://gitcode.com/gh_mirrors/hy/Hydro.git
synced 2026-10-20 01:38:19 +08:00
core: sort for ProblemFiles
This commit is contained in:
1 parent
6542e63e5b
commit
dcc6a27bbc
6 files changed
+37
-6
No files matched your search
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "hydrooj",
|
"name": "hydrooj",
|
||||||
"version": "2.24.15",
|
"version": "2.24.16",
|
||||||
"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",
|
||||||
@@ -11,7 +11,7 @@
|
|||||||
"node": ">=14"
|
"node": ">=14"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@hydrooj/utils": "^1.0.7",
|
"@hydrooj/utils": "^1.0.11",
|
||||||
"adm-zip": "^0.5.5",
|
"adm-zip": "^0.5.5",
|
||||||
"ansi_up": "^5.0.1",
|
"ansi_up": "^5.0.1",
|
||||||
"cookies": "^0.8.0",
|
"cookies": "^0.8.0",
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
import { isSafeInteger, flatten } from 'lodash';
|
import { isSafeInteger, flatten } from 'lodash';
|
||||||
import { FilterQuery, ObjectID } from 'mongodb';
|
import { FilterQuery, ObjectID } from 'mongodb';
|
||||||
import AdmZip from 'adm-zip';
|
import AdmZip from 'adm-zip';
|
||||||
|
import { sortFiles } from '@hydrooj/utils/lib/utils';
|
||||||
import {
|
import {
|
||||||
NoProblemError, PermissionError, ValidationError,
|
NoProblemError, PermissionError, ValidationError,
|
||||||
SolutionNotFoundError, ProblemNotFoundError, BadRequestError,
|
SolutionNotFoundError, ProblemNotFoundError, BadRequestError,
|
||||||
|
ForbiddenError,
|
||||||
} from '../error';
|
} from '../error';
|
||||||
import {
|
import {
|
||||||
Pdoc, User, Rdoc, PathComponent, ProblemStatusDoc,
|
Pdoc, User, Rdoc, PathComponent, ProblemStatusDoc,
|
||||||
@@ -380,8 +382,8 @@ export class ProblemFilesHandler extends ProblemDetailHandler {
|
|||||||
@param('additional_file', Types.Boolean)
|
@param('additional_file', Types.Boolean)
|
||||||
async get(domainId: string, getTestdata = true, getAdditionalFile = true) {
|
async get(domainId: string, getTestdata = true, getAdditionalFile = true) {
|
||||||
const canReadData = !this.user.own(this.pdoc) || this.user.hasPerm(PERM.PERM_READ_PROBLEM_DATA);
|
const canReadData = !this.user.own(this.pdoc) || this.user.hasPerm(PERM.PERM_READ_PROBLEM_DATA);
|
||||||
this.response.body.testdata = (getTestdata && canReadData) ? this.pdoc.data : [];
|
this.response.body.testdata = (getTestdata && canReadData) ? sortFiles(this.pdoc.data) : [];
|
||||||
this.response.body.additional_file = (getAdditionalFile ? this.pdoc.additional_file : []);
|
this.response.body.additional_file = getAdditionalFile ? sortFiles(this.pdoc.additional_file) : [];
|
||||||
this.response.template = 'problem_files.html';
|
this.response.template = 'problem_files.html';
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -405,9 +407,12 @@ export class ProblemFilesHandler extends ProblemDetailHandler {
|
|||||||
@post('filename', Types.Name, true)
|
@post('filename', Types.Name, true)
|
||||||
@post('type', Types.Range(['testdata', 'additional_file']), true)
|
@post('type', Types.Range(['testdata', 'additional_file']), true)
|
||||||
async postUploadFile(domainId: string, filename: string, type = 'testdata') {
|
async postUploadFile(domainId: string, filename: string, type = 'testdata') {
|
||||||
|
if (this.pdoc.data.length + this.pdoc.additional_file.length >= system.get('limit.problem_files_max')) {
|
||||||
|
throw new ForbiddenError('File limit exceeded.');
|
||||||
|
}
|
||||||
if (!this.request.files.file) throw new ValidationError('file');
|
if (!this.request.files.file) throw new ValidationError('file');
|
||||||
if (!filename) filename = this.request.files.file.name || String.random(16);
|
if (!filename) filename = this.request.files.file.name || String.random(16);
|
||||||
if (filename.includes('/')) throw new ValidationError('filename', 'Bad filename');
|
if (filename.includes('/') || filename.includes('..')) throw new ValidationError('filename', 'Bad filename');
|
||||||
if (!this.user.own(this.pdoc)) this.checkPerm(PERM.PERM_EDIT_PROBLEM);
|
if (!this.user.own(this.pdoc)) this.checkPerm(PERM.PERM_EDIT_PROBLEM);
|
||||||
if (filename.endsWith('.zip')) {
|
if (filename.endsWith('.zip')) {
|
||||||
const zip = new AdmZip(this.request.files.file.path);
|
const zip = new AdmZip(this.request.files.file.path);
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ export interface SystemKeys {
|
|||||||
'server.worker': number,
|
'server.worker': number,
|
||||||
'server.port': number,
|
'server.port': number,
|
||||||
'server.language': string,
|
'server.language': string,
|
||||||
|
'limit.problem_files_max': number,
|
||||||
'problem.categories': string,
|
'problem.categories': string,
|
||||||
'session.keys': string[],
|
'session.keys': string[],
|
||||||
'session.secure': boolean,
|
'session.secure': boolean,
|
||||||
|
|||||||
@@ -162,6 +162,7 @@ SystemSetting(
|
|||||||
Setting('setting_server', 'server.xhost', null, 'text', 'server.xhost', 'Hostname Header'),
|
Setting('setting_server', 'server.xhost', null, 'text', 'server.xhost', 'Hostname Header'),
|
||||||
Setting('setting_server', 'server.language', 'zh_CN', langRange, 'server.language', 'Default display language'),
|
Setting('setting_server', 'server.language', 'zh_CN', langRange, 'server.language', 'Default display language'),
|
||||||
Setting('setting_server', 'server.login', true, 'boolean', 'server.login', 'Allow builtin-login'),
|
Setting('setting_server', 'server.login', true, 'boolean', 'server.login', 'Allow builtin-login'),
|
||||||
|
Setting('setting_limits', 'limit.problem_files_max', 100, 'number', 'limit.problem_files_max', 'Max files per problem'),
|
||||||
Setting('setting_basic', 'default.priv', builtin.PRIV.PRIV_DEFAULT, 'number', 'default.priv', 'Default Privilege'),
|
Setting('setting_basic', 'default.priv', builtin.PRIV.PRIV_DEFAULT, 'number', 'default.priv', 'Default Privilege'),
|
||||||
Setting('setting_basic', 'problem.categories', builtin.CATEGORIES, 'yaml', 'problem.categories', 'Problem Categories'),
|
Setting('setting_basic', 'problem.categories', builtin.CATEGORIES, 'yaml', 'problem.categories', 'Problem Categories'),
|
||||||
Setting('setting_basic', 'lang.texts', builtin.LANG_TEXTS, 'yaml', 'lang.texts', 'LANG_TEXTS'),
|
Setting('setting_basic', 'lang.texts', builtin.LANG_TEXTS, 'yaml', 'lang.texts', 'LANG_TEXTS'),
|
||||||
|
|||||||
@@ -390,3 +390,27 @@ export function CallableInstance(property = '__call__') {
|
|||||||
}
|
}
|
||||||
|
|
||||||
CallableInstance.prototype = Object.create(Function.prototype);
|
CallableInstance.prototype = Object.create(Function.prototype);
|
||||||
|
|
||||||
|
const fSortR = /[^\d]+|\d+/g;
|
||||||
|
export function sortFiles(files: { _id: string }[] | string[]) {
|
||||||
|
const isString = typeof files[0] === 'string';
|
||||||
|
const result = files
|
||||||
|
.map((i) => (isString ? { name: i, weights: i.match(fSortR) } : { ...i, weights: i.match(fSortR) }))
|
||||||
|
.sort((a, b) => {
|
||||||
|
let pos = 0;
|
||||||
|
const weightsA = a.weights;
|
||||||
|
const weightsB = b.weights;
|
||||||
|
let weightA = weightsA[pos];
|
||||||
|
let weightB = weightsB[pos];
|
||||||
|
while (weightA && weightB) {
|
||||||
|
const v = weightA - weightB;
|
||||||
|
if (!Number.isNaN(v) && v !== 0) return v;
|
||||||
|
if (weightA !== weightB) return weightA > weightB ? 1 : -1;
|
||||||
|
pos += 1;
|
||||||
|
weightA = weightsA[pos];
|
||||||
|
weightB = weightsB[pos];
|
||||||
|
}
|
||||||
|
return weightA ? 1 : -1;
|
||||||
|
});
|
||||||
|
return isString ? result.map((x) => x.name) : result;
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@hydrooj/utils",
|
"name": "@hydrooj/utils",
|
||||||
"version": "1.0.10",
|
"version": "1.0.11",
|
||||||
"description": "hydrooj utils",
|
"description": "hydrooj utils",
|
||||||
"main": "package.json",
|
"main": "package.json",
|
||||||
"repository": "https://github.com/hydro-dev/Hydro.git",
|
"repository": "https://github.com/hydro-dev/Hydro.git",
|
||||||
|
|||||||
Reference in new issue
Block a user