grading
Version:
Grading of student submissions, in particular programming tests.
432 lines (424 loc) • 23.9 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const commander_1 = require("commander");
const cmdCheck_1 = require("./cli/cmdCheck");
const cmdCompare_1 = require("./cli/cmdCompare");
const cmdConclude_1 = require("./cli/cmdConclude");
const cmdGrade_1 = require("./cli/cmdGrade");
const cmdInit_1 = require("./cli/cmdInit");
const cmdPDF_1 = require("./cli/cmdPDF");
const cmdPrepare_1 = require("./cli/cmdPrepare");
const cmdSelected_1 = require("./cli/cmdSelected");
const settings_1 = require("./cli/settings");
const cmdDiff_1 = require("./cli/cmdDiff");
const cmdPrepareAsPrevious_1 = require("./cli/cmdPrepareAsPrevious");
const cmdSummary_1 = require("./cli/cmdSummary");
const colorHelp = `
Colors:
Color Foreground/Background Code
Black - 30/40 | Red - 31/41 | Green: 31/42 | Yellow: 33/43
Blue: 34/44 | Magenta: 35/45 | Cyan: 36/46 | L.Gray: 37/47
Gray: 90/100 | L.Red: 91/101 | L.Green: 92/102 | L.Yellow: 93/103
L.Blue: 94/104 | L.Magenta: 95/105 | L.Cyan: 96/106 | White: 97/107
Stype Code Description
Reset/Normal: 0 | Bold text: 1 | Faint text: 2 | Italics: 3 | Underlined: 4
Color is set in escape sequence, in the color setting, only the numbers are given, e.g. '1;31' for bold red.
Additionally, colors can be set in output by '<<color:XXXX>>', e.g. '<<color:1;31>>' for bold red.
This setting is resetted whenever a new section is started or via '<<color:reset>>'.
The explicit color will be prefixed to the computed color, which enables light colors by setting '<<color:2>>' for example.
`;
globalThis.SEP = '------------------------------------------------------------------';
globalThis.program = new commander_1.Command();
async function run() {
globalThis.settings = await (0, settings_1.readSettings)(); // some things are only defined in the settings and not in on the command line
program.name('grading')
.description('Automatically grade submissions in the context of Moodle and programming classes.')
.version('1.0.19')
.addHelpText('after', colorHelp);
program.command('init')
.description('Create check folder with default docker script and latex template')
.addOption(settings.noFolders.toOption())
.addOption(settings.noGitignore.toOption())
.addOption(settings.stdInFolder.toOption())
.addOption(settings.stdOutFolder.toOption())
.addOption(settings.gradingSchemaFile.toOption())
.addOption(settings.checkDir.toOption())
.addOption(settings.generateSettings.toOption())
.addOption(settings.generateCorrectionsFile.toOption())
.addOption(settings.taskInGeneratedCorrectionsFile.toOption())
.addOption(settings.manualCorrectionsFile.toOption())
.addOption(settings.resultsDir.toOption())
.addOption(settings.generateManualConclusionFile.toOption())
.addOption(settings.manualConclusionFile.toOption())
.addOption(settings.resultFile.toOption())
.addOption(settings.encoding.toOption())
.addOption(settings.resultCSVDelimiter.toOption())
.addOption(settings.quiet.toOption())
.addOption(settings.verbose.toOption())
.addOption(settings.debug.toOption())
.action(cmdInit_1.cmdInit);
program.command('check')
.description('Starts docker container for each student and runs students and check tests to create reports')
.argument('[zipFile]', 'zip file containing submissions as downloaded from Moodle, if omitted, zip file from standard in folder is used (Alle Abgaben Anzeigen/Bewertungsvorgang/Alle Abgaben herunterladen). Hint: Use folder gradingIn, as this is added to .gitignore in init by default.')
.addOption(settings.stdInFolder.toOption())
.addOption(settings.selected.toOption())
.addOption(settings.max.toOption())
.addOption(settings.fromSubmission.toOption())
.addOption(settings.toSubmission.toOption())
.addOption(settings.selectPatched.toOption())
.addOption(settings.skipPrepareSubmission.toOption())
.addOption(settings.onlyPrepareSubmission.toOption())
.addOption(settings.patch.toOption())
.addOption(settings.patch.toNoOption())
.addOption(settings.patchFolder.toOption())
.addOption(settings.patchGradingBranch.toOption())
.addOption(settings.skipStudentTests.toOption())
.addOption(settings.preCheckScript.toOption())
.addOption(settings.postCheckScript.toOption())
.addOption(settings.dockerImage.toOption())
.addOption(settings.dockerUserDir.toOption())
.addOption(settings.dockerWorkDir.toOption())
.addOption(settings.dockerShellCmd.toOption())
.addOption(settings.dockerScript.toOption())
.addOption(settings.dockerArgs.toOption())
.addOption(settings.timeoutPerDockerRun.toOption())
.addOption(settings.dry.toOption())
.addOption(settings.submissionsDir.toOption())
.addOption(settings.reportsDir.toOption())
.addOption(settings.checkDir.toOption())
.addOption(settings.npmCacheDir.toOption())
.addOption(settings.cacheDir.toOption())
.addOption(settings.clipDir.toOption())
.addOption(settings.volumes.toOption())
.addOption(settings.projectFile.toOption())
.addOption(settings.prepareSubmissionCmd.toOption())
.addOption(settings.ignoredDirs.toOption())
.addOption(settings.cleanBefore.toOption())
.addOption(settings.quiet.toOption())
.addOption(settings.verbose.toOption())
.addOption(settings.debug.toOption())
.addOption(settings.logOutput.toOption())
.addOption(settings.colored.toOption())
.addOption(settings.colorSection.toOption())
.addOption(settings.colorSubsection.toOption())
.addOption(settings.colorPre.toOption())
.addOption(settings.colorPost.toOption())
.addOption(settings.colorError.toOption())
.action(cmdCheck_1.cmdCheckAction);
program.command('grade')
.description('Grades submissions based on grading schema, submissions and unit reports previously created via check.')
.argument('[moodleFile]', 'Moodle grading CSV file, if omitted, csv file from standard in folder is used (Alle Abgaben Anzeigen/Bewertungsvorgang: Bewertungstabelle herunterladen), required if Moodle CSV result is to be created. Hint: Use folder gradingIn, as this is added to .gitignore in init by default.', '')
.addOption(settings.stdInFolder.toOption())
.addOption(settings.gradingSchemaFile.toOption())
.addOption(settings.gradingValue.toOption())
.addOption(settings.manualCorrectionsFile.toOption())
.addOption(settings.submissionsDir.toOption())
.addOption(settings.reportsDir.toOption())
.addOption(settings.noLatex.toOption())
.addOption(settings.latexFragmentFile.toOption())
.addOption(settings.workDir.toOption())
.addOption(settings.patchFolder.toOption())
.addOption(settings.noResultCSV.toOption())
.addOption(settings.resultFile.toOption())
.addOption(settings.encoding.toOption())
.addOption(settings.resultCSVDelimiter.toOption())
.addOption(settings.compareResults.toOption())
.addOption(settings.noMoodleCSV.toOption())
.addOption(settings.gradedMoodleFile.toOption())
.addOption(settings.noStatisticsCSV.toOption())
.addOption(settings.statisticsFile.toOption())
.addOption(settings.testOutputStartMarker.toOption())
.addOption(settings.testOutputEndMarker.toOption())
.addOption(settings.quiet.toOption())
.addOption(settings.verbose.toOption())
.addOption(settings.debug.toOption())
.addOption(settings.dry.toOption())
.addOption(settings.colored.toOption())
.addOption(settings.colorSection.toOption())
.addOption(settings.colorSubsection.toOption())
.addOption(settings.colorPre.toOption())
.addOption(settings.colorPost.toOption())
.addOption(settings.colorError.toOption())
.action(cmdGrade_1.cmdGrade);
program.command('pdf')
.description('Create PDF reports using LaTeX based on results previously created via grade.')
.addOption(settings.pdfDir.toOption())
.addOption(settings.submissionsDir.toOption())
.addOption(settings.pdfZipFile.toOption())
.addOption(settings.noPDFZip.toOption())
.addOption(settings.latexMainFile.toOption())
.addOption(settings.latexMainFolderCopy.toOption())
.addOption(settings.latexFragmentFile.toOption())
.addOption(settings.latex.toOption())
.addOption(settings.latexConsole.toOption())
.addOption(settings.workDir.toOption())
.addOption(settings.selected.toOption())
.addOption(settings.max.toOption())
.addOption(settings.selectPatched.toOption())
.addOption(settings.patchFolder.toOption())
.addOption(settings.clean.toOption())
.addOption(settings.quiet.toOption())
.addOption(settings.verbose.toOption())
.addOption(settings.debug.toOption())
.addOption(settings.colored.toOption())
.addOption(settings.colorSection.toOption())
.addOption(settings.colorSubsection.toOption())
.addOption(settings.colorPre.toOption())
.addOption(settings.colorPost.toOption())
.addOption(settings.colorError.toOption())
.action(cmdPDF_1.cmdPDF);
program.command('prepare')
.description('Prepare grading based on solution.')
.argument('[solutionFolder]', 'Folder with solution, should match structure of a submission', '.')
.addOption(settings.reportsDirSolution.toOption())
.addOption(settings.checkDir.toOption())
.addOption(settings.npmCacheDir.toOption())
.addOption(settings.cacheDir.toOption())
.addOption(settings.clipDir.toOption())
.addOption(settings.volumes.toOption())
.addOption(settings.gradingSchemaFile.toOption())
.addOption(settings.createGradingFile.toOption())
.addOption(settings.projectFile.toOption())
.addOption(settings.skipDocker.toOption())
.addOption(settings.skipPDF.toOption())
.addOption(settings.ignoredDirs.toOption())
.addOption(settings.submissionsDir.toOption())
.addOption(settings.preCheckScript.toOption())
.addOption(settings.postCheckScript.toOption())
.addOption(settings.dockerImage.toOption())
.addOption(settings.dockerUserDir.toOption())
.addOption(settings.dockerWorkDir.toOption())
.addOption(settings.dockerShellCmd.toOption())
.addOption(settings.dockerArgs.toOption())
.addOption(settings.dockerScript.toOption())
.addOption(settings.preserveContainer.toOption())
.addOption(settings.timeoutPerDockerRun.toOption())
.addOption(settings.pdfDirSolution.toOption())
.addOption(settings.latexMainFile.toOption())
.addOption(settings.latexMainFolderCopy.toOption())
.addOption(settings.latexFragmentFileSolution.toOption())
.addOption(settings.patchFolder.toOption())
.addOption(settings.workDir.toOption())
.addOption(settings.latex.toOption())
.addOption(settings.latexConsole.toOption())
.addOption(settings.validateOnly.toOption())
.addOption(settings.testOutputStartMarker.toOption())
.addOption(settings.testOutputEndMarker.toOption())
.addOption(settings.quiet.toOption())
.addOption(settings.verbose.toOption())
.addOption(settings.debug.toOption())
.addOption(settings.dry.toOption())
.addOption(settings.colored.toOption())
.addOption(settings.colorSection.toOption())
.addOption(settings.colorSubsection.toOption())
.addOption(settings.colorPre.toOption())
.addOption(settings.colorPost.toOption())
.addOption(settings.colorError.toOption())
.addHelpText("after", `
Ensure that the submissions, which may be found in gradingIn, are ignored when running tests and coverage.
I.e. you may want to add these folders ("<rootDir>/gradingIn/", "<rootDir>/gradingOut/") to
testPathIgnorePatterns, coveragePathIgnorePatterns, and modulePathIgnorePatterns in the jest.config of
your solution project.
Also ensure that check tests are not overwritten in solution project, which may happen in docker run.
The default docker script takes special care for that case.
The lecturer has name "lecturer" and submission id "solution", which may be used in the scripts (submission id is available
via environment variable SUBMISSIONID).`)
.action(cmdPrepare_1.cmdPrepare);
program.command('selected')
.description('Grade selected submissions, similar to using check, grade and pdf with selected option.')
.argument('<selected...>', 'IDs of submissions (or names of students, values are matched like prefixes) to grade')
.option('--zipFile]', 'zip file containing submissions as downloaded from Moodle, if omitted, zip file from standard in folder is used.', "")
.option('--moodleFile]', 'Moodle grading CSV file, if omitted, csv file from standard in folder is used.', "")
// all
.addOption(settings.submissionsDir.toOption())
// check & grade
.addOption(settings.stdInFolder.toOption())
.addOption(settings.reportsDir.toOption())
// check
.addOption(settings.preCheckScript.toOption())
.addOption(settings.postCheckScript.toOption())
.addOption(settings.dockerImage.toOption())
.addOption(settings.dockerUserDir.toOption())
.addOption(settings.dockerWorkDir.toOption())
.addOption(settings.dockerShellCmd.toOption())
.addOption(settings.dockerScript.toOption())
.addOption(settings.dockerArgs.toOption())
.addOption(settings.timeoutPerDockerRun.toOption())
.addOption(settings.checkDir.toOption())
.addOption(settings.npmCacheDir.toOption())
.addOption(settings.cacheDir.toOption())
.addOption(settings.clipDir.toOption())
.addOption(settings.volumes.toOption())
.addOption(settings.projectFile.toOption())
.addOption(settings.prepareSubmissionCmd.toOption())
.addOption(settings.skipPrepareSubmission.toOption())
.addOption(settings.onlyPrepareSubmission.toOption())
.addOption(settings.patch.toOption())
.addOption(settings.patch.toNoOption())
.addOption(settings.patchFolder.toOption())
.addOption(settings.patchGradingBranch.toOption())
.addOption(settings.ignoredDirs.toOption())
.addOption(settings.cleanBefore.toOption())
// grade & pdf
.addOption(settings.latexFragmentFile.toOption())
.addOption(settings.latexMainFolderCopy.toOption())
// grade
.addOption(settings.gradingSchemaFile.toOption())
.addOption(settings.gradingValue.toOption())
.addOption(settings.manualCorrectionsFile.toOption())
.addOption(settings.resultFile.toOption())
.addOption(settings.resultCSVDelimiter.toOption())
.addOption(settings.compareResults.toOption())
.addOption(settings.gradedMoodleFile.toOption())
.addOption(settings.noStatisticsCSV.toOption())
.addOption(settings.statisticsFile.toOption())
.addOption(settings.encoding.toOption())
.addOption(settings.testOutputStartMarker.toOption())
.addOption(settings.testOutputEndMarker.toOption())
// pdf
.addOption(settings.pdfDir.toOption())
.addOption(settings.pdfZipFile.toOption())
.addOption(settings.noPDFZip.toOption())
.addOption(settings.latexMainFile.toOption())
.addOption(settings.latex.toOption())
.addOption(settings.latexConsole.toOption())
.addOption(settings.workDir.toOption())
// all
.addOption(settings.quiet.toOption())
.addOption(settings.verbose.toOption())
.addOption(settings.debug.toOption())
.addOption(settings.dry.toOption())
.addOption(settings.colored.toOption())
.addOption(settings.colorSection.toOption())
.addOption(settings.colorSubsection.toOption())
.addOption(settings.colorPre.toOption())
.addOption(settings.colorPost.toOption())
.addOption(settings.colorError.toOption())
//
.addHelpText("after", `
This command is to be used for two cases:
- submissions submitted after a deadline
- submissions which are to be graded again because of problems in the grading process (wrong tests, wrong grading schema, etc.)
Grading submissions after the fact is dangerous, because when tests or other things have been changed, the results for other students may have changed as well.
Therefore, it is recommended to use this command only for submissions which have been submitted after the deadline.
In any case, check and pdf are called with the given filters. Grade however is called without selected so that the statistics are updated for all submissions.
It is recommended to use compare to compare the results of this command with the results of the normal grading process.`)
.action(cmdSelected_1.cmdSelected);
// program.command('clean')
// .description('Removes all folders and files created during check')
// .addOption(optSubmissionsDir)
// .addOption(optReportsDir)
// .option('-f, --full', 'also removes generated reports')
// .addOption(optQuiet)
// .addOption(optVerbose)
// .action(cmdClean);
program.command('compare')
.description('Compares two result showing changes in grading.')
.argument('<oldCSV>', '1st (old) result table (created with grade)')
.argument('<newCSV>', '2nd (new) result table (created with grade)')
.addOption(settings.summaryOnly.toOption())
.addOption(settings.showUnchanged.toOption())
.addOption(settings.encoding.toOption())
.addOption(settings.resultCSVDelimiter.toOption())
.addOption(settings.selected.toOption())
.addOption(settings.max.toOption())
.addOption(settings.quiet.toOption())
.addOption(settings.verbose.toOption())
.addOption(settings.debug.toOption())
.addOption(settings.colored.toOption())
.addOption(settings.colorSection.toOption())
.addOption(settings.colorSubsection.toOption())
.addOption(settings.colorPre.toOption())
.addOption(settings.colorPost.toOption())
.addOption(settings.colorError.toOption())
.action(cmdCompare_1.cmdCompare);
program.command('diff')
.description(`Uses git diff to create patch files from the diff between the submitter's branch and a branch created by the lecturer. Theses patch files can be then applied later on when the submission is checked again, i.e. after the submission has been recreated from the submissions zip file. In order to work, the submissions must have been prepared and the lecturer must have created a branch with the changes. This feature only works if submissions include a git repository.`)
.addOption(settings.submissionsDir.toOption())
.addOption(settings.patchFolder.toOption())
.addOption(settings.patchSubmissionBranches.toOption())
.addOption(settings.patchGradingBranch.toOption())
.addOption(settings.selected.toOption())
.addOption(settings.quiet.toOption())
.addOption(settings.verbose.toOption())
.addOption(settings.debug.toOption())
.addOption(settings.dry.toOption())
.action(cmdDiff_1.cmdDiff);
program.command('conclude')
.description('Concludes final results from multiple exam results.')
.addOption(settings.resultsDir.toOption())
.addOption(settings.resultFile.toOption())
.addOption(settings.stdInFolder.toOption())
.addOption(settings.deprecatedResultsDir.toOption())
.addOption(settings.autoCopyResult.toOption())
.addOption(settings.autoCopyConclusion.toOption())
.addOption(settings.keepOldResult.toOption())
.addOption(settings.conclusionFile.toOption())
.addOption(settings.manualConclusionFile.toOption())
.addOption(settings.selectBest.toOption())
.addOption(settings.totalExams.toOption())
.addOption(settings.maxFailed.toOption())
.addOption(settings.noFinalGradeBefore.toOption())
.addOption(settings.encoding.toOption())
.addOption(settings.resultCSVDelimiter.toOption())
.addOption(settings.quiet.toOption())
.addOption(settings.verbose.toOption())
.addOption(settings.debug.toOption())
.addOption(settings.dry.toOption())
.addOption(settings.colored.toOption())
.addOption(settings.colorSection.toOption())
.addOption(settings.colorSubsection.toOption())
.addOption(settings.colorPre.toOption())
.addOption(settings.colorPost.toOption())
.addOption(settings.colorError.toOption())
.action(cmdConclude_1.cmdConclude);
program.command('summary')
.description('Creates summary reports, only possible in last exam.')
.addOption(settings.resultsDir.toOption())
.addOption(settings.encoding.toOption())
.addOption(settings.resultCSVDelimiter.toOption())
.addOption(settings.selectBest.toOption())
.addOption(settings.totalExams.toOption())
.addOption(settings.maxFailed.toOption())
.addOption(settings.noFinalGradeBefore.toOption())
.addOption(settings.manualConclusionFile.toOption())
.addOption(settings.stdInFolder.toOption())
.addOption(settings.thisPartDescription.toOption())
.addOption(settings.summariesLatexFragmentFile.toOption())
.addOption(settings.summaryLatexMainFile.toOption())
.addOption(settings.latexMainFolderCopy.toOption())
.addOption(settings.latex.toOption())
.addOption(settings.gradingSchemaFile.toOption())
.addOption(settings.pdfSummariesDir.toOption())
.addOption(settings.workDir.toOption())
.addOption(settings.latexConsole.toOption())
.addOption(settings.noSummaryPDFZip.toOption())
.addOption(settings.summaryPDFZipFile.toOption())
.addOption(settings.clean.toOption())
.addOption(settings.max.toOption())
.addOption(settings.dry.toOption())
.addOption(settings.quiet.toOption())
.addOption(settings.verbose.toOption())
.addOption(settings.debug.toOption())
.addOption(settings.colored.toOption())
.addOption(settings.colorSection.toOption())
.addOption(settings.colorSubsection.toOption())
.addOption(settings.colorPre.toOption())
.addOption(settings.colorPost.toOption())
.addOption(settings.colorError.toOption())
.action(cmdSummary_1.cmdSummary);
program.command("prepareAsPrevious")
.description("Extracts submissions from zip file and prepares them to be used as previous submissions in plagiary tool.")
.argument('<zip>', 'Zipfile containing (previous) submissions.')
.addOption(settings.prevProjectsDir.toOption())
.addOption(settings.projectFile.toOption())
.addOption(settings.prepareSubmissionCmd.toOption())
.addOption(settings.ignoredDirs.toOption())
.addOption(settings.quiet.toOption())
.addOption(settings.verbose.toOption())
.addOption(settings.debug.toOption())
.action(cmdPrepareAsPrevious_1.cmdPrepareAsPrevious);
program.parse();
}
run();
//# sourceMappingURL=cli.js.map