Archived
Bug Fixes & Features
This commit is contained in:
1 parent
0a46484d2f
commit
00bad205c2
4 files changed
+65
-31
No files matched your search
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "styleforces",
|
||||
"version": "2.0.1",
|
||||
"version": "2.0.2",
|
||||
"description": "The Codeforces toolkit to make life easier for teachers and worse for students.",
|
||||
"main": "./dist/index.js",
|
||||
"scripts": {
|
||||
|
||||
@@ -11,16 +11,17 @@ type SubmissionIndex = {
|
||||
};
|
||||
|
||||
export const HELP = `
|
||||
Usage: ${process.execPath} fetchOk [options...]
|
||||
Usage: ${process.execPath} fetch [options...]
|
||||
Options:
|
||||
--contest, -i (STRING) : Contest ID.
|
||||
--group, -g <STRING> : Group ID (if in group).
|
||||
--count, -c <INTEGER> : Positive amount of "OK" submissions to fetch. (default: 100)
|
||||
--count, -c <INTEGER> : Positive amount of submissions to fetch. (default: 100)
|
||||
--lookup, -l <INTEGER> : Positive amouut of submissions to lookup. (default: 200)
|
||||
--after, -a <INTEGER> : Positive amount of submissions to skip. (default: 1)
|
||||
--points, -p <INTEGER> : Positive amount of points to filter. (default: 100)
|
||||
--out-dir, -O <STRING> : Path to the directory to write submissions to. (default: './result')
|
||||
|
||||
Example: ${process.execPath} fetchOk -i someId -g anotherId -c 50 -l 100 -a 10 -o './result'
|
||||
Example: ${process.execPath} fetch -i someId -g anotherId -c 50 -l 100 -a 10 -o './result'
|
||||
`;
|
||||
|
||||
function error(msg: string) {
|
||||
@@ -36,6 +37,7 @@ export async function execute() {
|
||||
count: countArg,
|
||||
lookup: lookupArg,
|
||||
after: afterArg,
|
||||
points: pointsArg,
|
||||
"out-dir": outDirArg
|
||||
}
|
||||
} = parseArgs({
|
||||
@@ -60,6 +62,10 @@ export async function execute() {
|
||||
type: "string",
|
||||
short: "a"
|
||||
},
|
||||
points: {
|
||||
type: "string",
|
||||
short: "p"
|
||||
},
|
||||
"out-dir": {
|
||||
type: "string",
|
||||
short: "O"
|
||||
@@ -71,6 +77,7 @@ export async function execute() {
|
||||
const count = countArg && /^(0|[1-9]\d*)$/.test(countArg) ? parseInt(countArg) : 100;
|
||||
const lookup = lookupArg && /^(0|[1-9]\d*)$/.test(lookupArg) ? parseInt(lookupArg) : 200;
|
||||
const after = afterArg && /^(0|[1-9]\d*)$/.test(afterArg) ? parseInt(afterArg) : 1;
|
||||
const points = pointsArg && /^(0|[1-9]\d*)$/.test(pointsArg) ? parseInt(pointsArg) : 100;
|
||||
const outDir = outDirArg ?? "./result";
|
||||
|
||||
if (!contestId) {
|
||||
@@ -95,7 +102,10 @@ export async function execute() {
|
||||
}
|
||||
|
||||
const status = (await codeforces.methods.contestStatus(contestId, after, lookup))
|
||||
.filter((submission) => submission.verdict === "OK")
|
||||
.filter(
|
||||
(submission) =>
|
||||
submission.verdict === "OK" || (submission.points && submission.points >= points)
|
||||
)
|
||||
.slice(0, count);
|
||||
|
||||
for (const submission of status) {
|
||||
@@ -17,14 +17,15 @@ interface Output {
|
||||
}
|
||||
|
||||
export const HELP = `
|
||||
Usage: ${process.execPath} logSerializer [options...]
|
||||
Usage: ${process.execPath} log2StanD [options...]
|
||||
Options:
|
||||
--freeze, -f (INTEGER) : Freeze time counting from start in minutes.
|
||||
--lookup, -l (STRING) : Path to the contest log file.
|
||||
--domain, -d (STRING) : Path to the domain's users file.
|
||||
--out-file, -O <STRING> : Path to the resulted serialization. (default: './result.json')
|
||||
--freeze, -f (INTEGER) : Freeze time counting from start in minutes.
|
||||
--log, -l (STRING) : Path to the contest log file.
|
||||
--domain, -d (STRING) : Path to the domain's users file.
|
||||
--only-domain, -i : Ignore everyone not in domain.
|
||||
--out-file, -O <STRING> : Path to the resulted serialization. (default: './result.json')
|
||||
|
||||
Example: ${process.execPath} logSerializer -f 120 -l ./log.txt -d ./domain.txt -o ./result.json
|
||||
Example: ${process.execPath} log2StanD -f 120 -l ./log.txt -d ./domain.txt -o ./result.json
|
||||
`;
|
||||
|
||||
function error(msg: string) {
|
||||
@@ -34,7 +35,13 @@ function error(msg: string) {
|
||||
|
||||
export async function execute() {
|
||||
const {
|
||||
values: { freeze: freezeTime, log: logFile, domain: domainFile, "out-file": outFileArg }
|
||||
values: {
|
||||
freeze: freezeTime,
|
||||
log: logFile,
|
||||
domain: domainFile,
|
||||
"only-domain": onlyDomain,
|
||||
"out-file": outFileArg
|
||||
}
|
||||
} = parseArgs({
|
||||
options: {
|
||||
freeze: {
|
||||
@@ -49,6 +56,10 @@ export async function execute() {
|
||||
type: "string",
|
||||
short: "d"
|
||||
},
|
||||
"only-domain": {
|
||||
type: "boolean",
|
||||
short: "i"
|
||||
},
|
||||
"out-file": {
|
||||
type: "string",
|
||||
short: "O"
|
||||
@@ -95,6 +106,8 @@ export async function execute() {
|
||||
runs: []
|
||||
};
|
||||
|
||||
const ignored = new Set<number>();
|
||||
|
||||
for (const entry of log) {
|
||||
const cmd = entry.slice(0, entry.indexOf(" ")).trim();
|
||||
const csv = entry.slice(entry.indexOf(" ") + 1).trim();
|
||||
@@ -111,19 +124,30 @@ export async function execute() {
|
||||
}
|
||||
case "@t": {
|
||||
const values = csv.split(",");
|
||||
output.contestants.push(names[values[3].split("=")[1]]);
|
||||
const party = /^g\d+?=/.test(values[3]) ? values[3].split("=")[1] : values[3];
|
||||
|
||||
if (onlyDomain && !Object.hasOwn(names, party)) {
|
||||
ignored.add(ignored.size + output.contestants.length);
|
||||
continue;
|
||||
}
|
||||
|
||||
output.contestants.push(names[party] ?? party);
|
||||
break;
|
||||
}
|
||||
case "@s": {
|
||||
const values = csv.split(",");
|
||||
const run: Run = {
|
||||
contestant: output.contestants[parseInt(values[0]) - 1],
|
||||
problemLetter: values[1],
|
||||
timeMinutesFromStart: Math.floor(parseInt(values[3]) / 60),
|
||||
success: values[4] === "OK"
|
||||
};
|
||||
const contestantId = parseInt(values[0]) - 1;
|
||||
|
||||
if (!ignored.has(contestantId)) {
|
||||
const run: Run = {
|
||||
contestant: output.contestants[contestantId - ignored.size],
|
||||
problemLetter: values[1],
|
||||
timeMinutesFromStart: Math.floor(parseInt(values[3]) / 60),
|
||||
success: values[4] === "OK"
|
||||
};
|
||||
output.runs.push(run);
|
||||
}
|
||||
|
||||
output.runs.push(run);
|
||||
break;
|
||||
}
|
||||
}
|
||||
+11
-11
@@ -1,15 +1,15 @@
|
||||
import { parseArgs } from "util";
|
||||
|
||||
import * as copyDetect from "./command/copydetect.js";
|
||||
import * as fetchOK from "./command/fetchOk.js";
|
||||
import * as logSerializer from "./command/logSerializer.js";
|
||||
import * as fetchSubmissions from "./command/fetch.js";
|
||||
import * as log2stanD from "./command/log2StanD.js";
|
||||
|
||||
const HELP = `
|
||||
Usage: ... (command) [arguments...]
|
||||
Commands:
|
||||
- logSerializer : Convert contest log to JSON with freeze-time.
|
||||
- fetchOk : Fetch every "OK" submission from contest.
|
||||
- copydetect : Compare submissions and generate copy report of them. (requires copydetect)
|
||||
- log2StanD : Convert contest log to JSON with freeze-time.
|
||||
- fetch : Fetch submission from contest.
|
||||
- copydetect : Compare submissions and generate copy report of them. (requires copydetect)
|
||||
Environment:
|
||||
CF_KEY : Codeforces API Key.
|
||||
CF_SECRET : Codeforces API Secret.
|
||||
@@ -30,19 +30,19 @@ const {
|
||||
});
|
||||
|
||||
switch (process.argv[2]) {
|
||||
case "logSerializer":
|
||||
case "log2StanD":
|
||||
if (help) {
|
||||
console.log(logSerializer.HELP);
|
||||
console.log(log2stanD.HELP);
|
||||
break;
|
||||
}
|
||||
logSerializer.execute();
|
||||
log2stanD.execute();
|
||||
break;
|
||||
case "fetchOk":
|
||||
case "fetch":
|
||||
if (help) {
|
||||
console.log(fetchOK.HELP);
|
||||
console.log(fetchSubmissions.HELP);
|
||||
break;
|
||||
}
|
||||
fetchOK.execute();
|
||||
fetchSubmissions.execute();
|
||||
break;
|
||||
case "copydetect":
|
||||
if (help) {
|
||||
|
||||
Reference in new issue
Block a user