npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

grading

v1.0.10

Published

Grading of student submissions, in particular programming tests.

Downloads

209

Readme

npm pipeline status coverage

logo grading

Automatische Überprüfung von Programmieraufgaben, die über Moodle abgegeben wurden.

[[TOC]]

Situation

Unter Moodle wurde eine Aufgabe erstellt, die die Studenten lösen müssen. Die Lösung ist eine Zip-Datei, die über Moodle hochgeladen wird. Die Lösungen sollen nun irgendwie automatisch, meist mittels Tests, korrigiert werden und die Ergebnisse zu Punkten bzw. Noten umgerechnet werden. Die Bewertung soll dann in Form von Bewertungstabellen und PDFs wieder in Moodle den Studenten bereitgestellt werden.

Voraussetzungen

Die Durchführung der Korrektur und die Bewertung sind Programmiersprachen unabhängig. Lediglich folgende Voraussetzungen müssen erfüllt sein:

  • die Ergebnisse der automatisierten Tests, also die eigentliche Korrektur, muss als unit.xml-Datei exportiert werden können.
  • falls eine Code-Coverage verwendet werden soll, muss diese im Clover-Format vorliegen.

Folgende Tools müssen vorliegen:

  • Das Grading-Tool selbst benötigt JavaScript mit Node.js.
  • Zur Erstellung der PDF-Reports muss LaTeX installiert sein.

Das Tool geht davon aus, dass die eigentliche Korrektur einer Docker-Umgebungen durchgeführt wird, da so eindeutige Bedingungen geschaffen werden können und Zugriff des studentischen Codes auf das System des Korrektors verhindert wird. Falls Docker verwendet wird, sollte mind. Version 20 eingesetzt werden, da ansonsten Probleme beim Mounten der Verzeichnisse (mit Leerzeichen) auftreten können.

Das Tool trifft weitere Annahmen, die aber über Konfigurationseinstellungen geändert werden können:

  • Die Abgabe ist ein gezipptes Git-Repository.
  • Das Grading wird im Projektordner der Musterlösung durchgeführt.
  • Die Bewertung wird mit automatisierten Tests vorgenommen, die in einem Ordner check/tests der Musterlösung liegen.
  • Die Bewertungstests werden mit Docker ausgeführt, die Ergebnisse werden in Form von JUnit-XML-Reports übermittelt (und ggf. Coverage.xml)
  • Das Bewertungsschema liegt unter check/exam.grading.json

Installation des Tools

Es gibt drei Möglichkeiten:

  1. Grading global installieren: npm install --global grading. Nun kann Grading einfach über grading aufgerufen werden. Falls Grading aktualisiert wurde, kann das Update mit npm update -g grading installiert werden.

  2. Grading direkt ausführen über npx grading

  3. Grading klonen und im Verzeichnis des Klons (also grading)

    npm run build

    und

    npm link

    aufrufen. Nun kann Grading einfach über grading aufgerufen werden. Diese Variante ist sinnvoll, wenn an Grading selbst Änderungen durchgeführt werden sollen.

    Falls der Ordner des Klons gelöscht wurde oder grading nicht mehr global erreichbar sein soll, kann dies mit npm unlink -g grading gelöscht werden (unlink ist ein Alias für rm bzw uninstall).

Im Folgenden wird davon ausgegangen, dass Grading mittels grading aufgerufen werden kann.

Vorbereitung

Von Moodle beim der Aufgabe (unter "Alle Abgaben anzeigen" > "Bewertungsvorgang") folgende Dateien laden:

  • alle Abgaben (zip-Datei)
  • Bewertungstabelle (csv-Datei)

Achtung: Die Bewertungstabelle enthält je nach Konfiguration der Aufgabe unterschiedliche Spalten. Es ist wichtig, dass die Bewertungseinstellung wie folgt konfiguriert ist:

  • Feedback-Typen: alle Typen ausschalten, folgende Typen einschalten:
    • Feedbackdateien
    • Offline-Bewertungstabelle

Beide Dateien am besten nach gradingIn verschieben.

Zur initialen Erstellung des Bewertungsschemas und der Ordnerstruktur für die Tests kann

grading init

aufgerufen werden.

Im allgemein ist der letzte Schritt nicht notwendig, da man meist die Dateien aus einem vorherigen Aufgabenblatt übernimmt.

Normale Verwendung

Korrektur und Bewertung in 4 Schritten

Die automatische Überprüfung besteht aus drei bzw. vier Schritten:

Schritt 1: prepare

grading prepare

Damit wird die Musterlösung geprüft. Dies dient v.a. zum Test, ob generell eine Bewertung durchgeführt werden kann.

U.a. kann hier auch ein Cache erstellt werden, in diesem Fall ist dieser Schritt notwendig. So kann bspw. gradingOut/cache/node_modules in Docker gemounted werden (Setting ' --volumes'), womit man sich dann bei eigentlichen Check das npm install spart.

Schritt 2: check

grading check  «gradingIn/submissions.zip»

Wenn keine Zip-Datei angegeben wird, wird im Standard-Eingabeverzeichnis (gradingIn) automatisch eine Zip-Datei gesucht. Vorbereitung der Einreichung und Starten der Tests

  • Auspacken der Zip-Datei
  • für jede Einreichung:
    • Vorbereitung des Verzeichnisses, bspw. git reset --hard (prepareSubmission), ggf. Patch einspielen
    • Starten von Docker zum Testen der Einreichung
  • checkInDocker.sh Testen der Einreichung (in Docker) (vereinfacht)
    • npm install
    • npm build
    • npm test -- Tests in der Einreichung
    • npm test --config checks/jest.check.config.js -- Tests zum Grading
    • Reports sichern (junit.xml, coverage/clover.xml)

Da der Check sehr lange dauern kann (bspw. 30 Minuten bei 80 Einreichungen), sollte man dies unter macos mit dem Tool caffeinate starten, damit der Rechner in den 30 Minuten nicht in den Sleep-Mode geht. Also:

caffeinate grading check «gradingIn/submissions.zip»

Tipp: Zur Optimierung bietet es sich an, bspw. das node_modules-Verzeichnis beim Vorbereiten (grading prepare) zu erstellen und dann beim Check wiederzuverwenden. Dazu muss das Verzeichnis (am besten im Cache-Ordner von gradingOut) in Docker gemountet werden (mittels --volumes). Und natürlich muss als erstes grading prepare aufgerufen werden. In den Skripten kann die Phase mittels der Umgebungsvariablen PHASE abgefragt werden.

In jedem Fall wird unter gradingOut ein Log des Check-Laufs erstellt.

Schritt 3: grade

Bewerten (grading) der Einreichungen

grading grade

Wenn keine CSV-Datei angegeben wird, wird im Standard-Eingabeverzeichnis (gradingIn) automatisch eine SV-Datei gesucht.

  1. Einlesen der Moodle Bewertungsdatei, damit sind Abgaben definiert
  2. Einlesen des Exam-spezifischen Bewertungsschemas (GradingSchema)
  3. Validierung des GradingSchema
  4. Bewertung der Einreichungen, je Einreichung:
    1. Unit (student, check) und Coverage (student) Reports laden
    2. Für alle Tasks und darin für alle Tests: Preconditions auswerten, Testergebnis in Punkte umwandeln
    3. Gesamtbewertung berechnen
  5. Statistik erstellen
  6. Ergebnisse speichern:
    • als Latex-Fragment (für jede Einreichung einen Befehl) speichern
    • als Moodle-Bewertung-Datei (CSV)
    • CSV für eigene Semester-Bewertung (CSV)
    • CSV mit Statistik

Schritt 4: pdf

Mit Latex-Template und Latex-Fragment für jeden Studenten ein Ergebnis PDF erstellen.

grading pdf
  • PDF wird erstellt
  • Moodle-kompatible Verzeichnisstruktur wird gezippt.

Diese Schritte sind mit dem CLI-Tool grading alle auszuführen.

Obige Schritte können auch gezielt für eine Abgabe durchgeführt werden, siehe dazu unten unter Verwendung.

Nachbereitung

Upload der Ergebnisse nach Moodle (ebenfalls unter (unter "Alle Abgaben anzeigen" > "Bewertungsvorgang")

  • Bewertungstabelle: gradingOut/Bewertungen-«Aufgabenname»_graded_«Zeitstempel».csv; Wichtig: Update von Datensatzen zulassen unbedingt im Moodle-Upload ankreuzen! Die Tabelle ist UTF-8 mit Komma getrennt.
  • Feedbackdateien: gradingOut/pdfReports_«Zeitstempel».zip

Korrektur und Bewertung definieren

Grading Schema

Zur Bewertung wird ein Grading-Schema benötigt. Dies muss in JSON spezifiziert werden. Mit

grading prepare -cg «somename.grading.json»

wird ein initiales Schema aus den Check-Tests erstellt.

Im Schema können Kommentare angegeben werden. Damit in VSCode der Editor dort keine Fehler anzeigt, empfiehlt sich die folgende Einstellung:

"files.associations": {
    "*.grading.json": "jsonc"
}
{
    "$schema": "https://gitlab.bht-berlin.de/nodepackages/grading/-/raw/main/src/grade/grading.schema.json",
    "course": "Web-Engineering 1",
    "term": "SS 2024",
    "exam": "Blatt 03",
    "points": 100,
    "minCoverageStatements": 95,
    "penaltiesCoverageMax": 15,
    "extraCoverageMax": 5,
    "tasks": [
        {
            "name": "inverseCaseSingleLetter",
            "suite": "inverseCaseSingleLetter.check.ts",
            "points": 20,
            "preconditions": [
                {
                    "test": "Funktion inverseCaseSingleLetter wurde implementiert",
                    "suite": "isImplemented.check.ts"
                }
            ],
            "grading": [
                {
                    "points": 15,
                    "text": "Positivtests für inverseCaseSingleLetter",
                    "tests": [
                        "A -> a",
                        "Z -> z",
                    ]
                },
                {
                    "points": 5,
                    "text": "Negativtests für inverseCaseSingleLetter",
                    "tests": [
                        "Fehler weil kein Zeichen",
                        "Fehler weil mehr als ein Zeichen"
                    ]
                }
            ],
            "penalties": [
                {
                    "points": -5,
                    "text": "Keine Verwendung von Arrays",
                    "suite": "implementationConstraintsInverseCase.check.ts",
                    "tests": [
                        "inverseCaseSingleLetter darf kein Array verwenden."
                    ]
                }
            ],
            "manual": false
        },
        ...
    ]
}

Manuelle Korrekturen

Zusätzlich können manuelle Korrekturen vorgenommen werden. Diese müssen ebenfalls in einer JSON-Datei angegeben werden.

Am besten sollte die Datei mit manuellen Korrekturen angelegt werden, wenn bereits ein Check und ein Grading gelaufen ist. Dann wird die Datei mit Einträgen für alle Abgaben vorgefüllt (ansonsten ist die Datei leer). Die Datei kann erzeugt werden mit

grading init --generateCorrectionsFile

In der Korrektur-Datei können Kommentare angegeben werden. Damit in VSCode der Editor dort keine Fehler anzeigt, empfiehlt sich die folgende Einstellung:

"files.associations": {
    "*.correction.json": "jsonc"
}

Die manuelle Korrektur sollte unter dem Namen manual.corrections.json abgelegt werden. Sie könnte bspw. so aussehen:

{
    "exam": "Blatt x",
    "course": "Web-Engineering",
    "term": "WS 2022/23",
    "corrections": [
        {
            "submissionID": "123456",
            "userName": "Some Name",
            "general": [
                {
                    "points": -5
                    "reason": "Die Formatierung des Codes ist insgesamt grauenhaft"
                }
            ],
            "tasks": [
                {
                    "name": "Some Task",
                    "points": 10
                    "reason": "Extrem elegante Lösung!"
                }
            ]
        }
    ]
}

Man kann bei den Punkten in General auch "absolute"=true angeben, um als Korrektor vollkommen manuell die Note zu setzen! Der Reason kann als einzelner String oder Array angeben werden -- dies ist aber nur zur besseren Lesbarkeit und hat ansonsten keine Auswirkungen.

{
    …
    "corrections": [
        {
            "submissionID": "123456",
            "userName": "Some Name",
            "general": [
                {
                    "points": 0,
                    "absolute": true,
                    "reason": "Plagiat erkannt"
                }
            ]
        },
        {
            "submissionID": "7891233",
            "userName": "Another Student",
            "general": [
                {
                    "points": 50,
                    "absolute": true,
                    "reason": [
                        "Nach manueller Sichtung gerade noch bestanden.",
                        "Task x wurde grundsätzlich schon gelöst, aber die Korrektur kann nicht ausgeführt werden."
                    ]
                }
            ]
        }
    ]
}

Es müssen keine Punkte angegeben werden, dann ist die manuelle Korrektur (reason) ein reiner Kommentar.

Patches

Manchmal ist es notwendig, eine Submission für die Korrektur leicht zu bearbeiten. Dies kann der Fall sein, wenn in der Submission irgendeine kleinere Sache bewirkt, dass die Korrektur nicht ausgeführt werden kann. Damit die Korrektur dokumentiert und reproduziert werden kann, muss diese irgendwie gespeichert werden.

Tatsächlich werden normalerweise bei jedem Aufruf von grading check die Projektverzeichnisse aller Abgaben gelöscht und neu erstellt. D.h. in diesem Fall geht eine Korrektur verloren.

Damit dies sinnvoll möglich ist, muss die Submission ein git-Repository sein. Nur so können die Änderungen sinnvoll verwaltet werden.

Wenn Korrekturen durch den Dozenten vorgenommen werden soll, ist wie folgt vorzugehen:

  1. Mittels grading check (evtl. auch einfach grading check --prepareSubmission) werden die Projektverzeichnisse der Submission erstellt.
  2. Korrekturen des Dozenten werden in einem eigenen Branch im Projektvereichnis einer Submission erstellt. Dieser kann mit --patchGradingBranch konfiguriert werden. Per Default ist dieser grading:
    git checkout -b grading
  3. Nun werden die Korrekturen durchgeführt. Um die Wirksamkeit zu testen, wird vermutlich zwischendurch ein Check durchgeführt. Hier gibt es zwei Möglichkeiten:
    1. Mit
      grading check --skipPrepareSubmission --selected ...
      wird ein Check-Lauf gestartet, wobei das Projektverzeichnis nicht verändert wird.
    2. Oder man testet die Änderungen lokal. Je nach Projekt ist dies unterschiedlich. Wenn man bspw. für die Check-Tests bei Jest eine Konfigurationsdatei hat, etwa mit
      jest --config check/tests/jest.check.config.js
  4. Damit die Korrekturen gesichert (und damit dokumentiert) werden können, müssen diese auf dem Grading-Branch eingespielt werden, also bspw.
    git commit -am "fixed something"
    Die Commit-Message erscheint nirgends und ist daher irrelevant. Natürlich können auch mehrere Commits durchgeführt werden.
  5. Nun können mit
    grading diff
    für alle Submissions Patch-Files erstellt werden. Diese werden per Default in gradingIn/patches erstellt, die kann mit patchFolder konfiguriert werden. Der Diff wird zwischen dem Branch der Submission, normalerweise main (konfigurierbar mit patchSubmissionBranches) und dem Grading-Branch berechnet.

Wenn bei grading check ein Patch für die Submission gefunden wird, wird diese automatisch angewendet. Falls dies nicht erfolgen soll, kann dies mit -no-patch ausgeschaltet werden. Tatsächlich wird der Patch auf den automatisch erstellen Grading-Branch angewendet und dort auch committed. Auf diese Weise können so bei Bedarf weitere Korrekturen nach obigem Schema durchgeführt werden.

Die Patches werden nicht automatisch beim Grading oder im Report berücksichtigt. Bei Bedarf ist im Korrektur-File ein Eintrag zu machen, dort können auch ggf. Punkte abgezogen werden.

Conclusion

Falls mehrere Abgaben in einem Semester erfolgen, sollen die Ergebnisse in einer Tabelle zusammengefasst werden. Dazu kann mit

grading conclude

eine Excel-Tabelle erstellt werden.

Dabei werden auch vorangegangene Ergebnisse berücksichtigt. Diese werden in einem Verzeichnis resultsDir gesucht. Dorthin wird dann auch das aktuelle Ergebnis sowie die Zusammenfassung kopiert.

Je nach Endung des conclusionFile wird eine CSV oder Excel-Tabelle erzeugt.

Mehr Hilfe findet man unter

grading conclude --help

Mit

grading init --generateManualConclusionFile

kann außerdem eine JSON-Datei mit manuellen Eintragungen für die Zusammenfassung erzeugt werden. In dieser Datei kann man manuell Noten eintragen (bspw. für Plagiate) oder Aliases erfassen (es kommt manchmal vor, dass in Moodle während des Semesters der Name von Studenten geändert wird).

{
    "course": "Web-Engineering 2",
    "term": "SS 2024",
    "conclusions": [
        // {"userName": "Max Muster", "totalGrading": 0.0, "gradingReason": "", "generalRemark": "" },
        // ...
        {
            "userName": "Mickey Mouse",
            "totalGrading": 5.0,
            "gradingReason": "Plagiate Blatt 06 und 07",
            "generalRemark": ""
        }
    ],
    "aliases": [ // for renamed students (or names changed otherwise, e.g., typos)
        [
            "Twix Sun",
            "Raider Sonne"
        ]
    ]
}

Allgemeine Verwendung und Settings

Verwendung

Grading bietet mehrere "Commands" an, jedes "Command" hat wieder eigene Optionen.

Die allgemeine Hilfe (siehe unten) kann mit

grading --help

ausgegeben werden.

Für jedes Command kann man eine eigene Hilfe ausgeben, bspw.

grading check --help
Usage: grading [options] [command]

Automatically grade submissions in the context of Moodle and programming classes.

Options:
  -V, --version                        output the version number
  -h, --help                           display help for command

Commands:
  init [options]                       Create check folder with default docker script and latex template
  check [options] [zipFile]            Starts docker container for each student and runs students and check tests to create reports
  grade [options] [moodleFile]         Grades submissions based on grading schema, submissions and unit reports previously created via check.
  pdf [options]                        Create PDF reports using LaTeX based on results previously created via grade.
  prepare [options] [solutionFolder]   Prepare grading based on solution.
  selected [options] <selected...>     Grade selected submissions, similar to using check, grade and pdf with selected option.
  compare [options] <oldCSV> <newCSV>  Compares two result showing changes in grading.
  diff [options]                       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.
  conclude [options]                   Concludes final results from multiple exam results.
  help [command]                       display help for command

Settings

Fast alle Einstellungen können über die Kommandozeile verändert werden. Alternativ können in einer Datei .grading/setting.json Einstellungen definiert werden. Diese Datei (bzw. der Ordner .grading) wird in der Verzeichnisstrutkur auch in darüber liegenden Verzeichnissen gesucht und die dortingen Einstellungen gemerged. Dadurch kann man bspw. im User-Verzeichnis persönliche Einstellungen speichern, im Kurshauptverzeichnis die meisten Einstellungen für den Kurs. Meistens benötigt man nicht mehr. Dann entfallen fast immer alle Kommandozeilenoptionen und man kann den ganzen Vorgang einfach durchführen mit

grading check
grading grade
grading pdf

Um eine Settings-Datei mit Hilfe zu erzeugen, einfach

grading init --generateSettings

aufrufen. Es wird dann im aktuellen Verzeichnis unter .grading/settings.json eine Datei erzeugt.

Achtung: Änderungen sind in neueren Versionen möglich.

{   /* Settings file for grading, values maybe overwritten in subfolder settings or command line arguments, overwrites values in parent folders. */

    /* init, check, grade, pdf, prepare, selected, compare, diff, conclude */
    // "debug": false,                                /* Emit debug messages (which may be different from verbose) (boolean)*/
    // "quiet": false,                                /* Quiet mode, emit only errors (boolean)*/
    // "verbose": false,                              /* Emit verbose messages (boolean)*/

    /* check, grade, pdf, prepare, selected, compare, conclude */
    // "colored": true,                               /* Use colored output (boolean)*/
    // "colorError": "3",                             /* Color for error output (string)*/
    // "colorPost": "35",                             /* Color for post script (string)*/
    // "colorPre": "34",                              /* Color for pre script (string)*/
    // "colorSection": "1;97;44",                     /* Color for heading (start of each submission) (string)*/
    // "colorSubsection": "1;34",                     /* Color for sub section, detected by ^[0-9]+. (string)*/

    /* check, grade, prepare, selected, diff, conclude */
    // "dry": false,                                  /* Dry run, do not write any files and do not start scripts (boolean)*/

    /* check, grade, pdf, selected, diff */
    // "submissionsDir": "./gradingOut/submissions",  /* submissions directory (where zip is extracted) (folder)*/

    /* init, grade, selected, compare, conclude */
    // "encoding": "macroman",                        /* Encoding used for reading and writing result, statistic files and conclusion file (see iconv - lite for encodings), e.g.UTF - 8 or macroman (name)*/
    // "resultCSVDelimiter": ";",                     /* Delimiter used in CSV with the results (and conclusion) (string)*/

    /* check, pdf, compare, diff */
    // "selected": [],                                /* Process only on given ids or students with given name (prefix). Existing files of other submitters are not overwritten (...string)*/

    /* check, pdf, selected, diff */
    // "patchFolder": "./gradingIn/patches",          /* Name of the folder in which patch files are searched or created. (folder)*/

    /* grade, pdf, prepare, selected */
    // "workDir": "./gradingOut/_working",            /* Name of working folder, this folder is cleaned before and after) (folder)*/

    /* init, check, grade, selected */
    // "stdInFolder": "gradingIn",                    /* Name of folder to be created for (moodle) input files(and added to.gitignore). (folder)*/

    /* init, check, prepare, selected */
    // "checkDir": "./check",                         /* Check tests folder, this is mounted in docker as /check (folder)*/

    /* init, grade, prepare, selected */
    // "gradingSchemaFile": "./check/exam.grading.json", /* JSON file with grading schema(*.grading.json) (file)*/

    /* init, grade, selected, conclude */
    // "resultFile": "./gradingOut/results_${examName}_${date}-${time}.csv", /* Name of the CSV (.csv) file with the results, with variables in ${..} (examName, date, time), used as pattern in some cases (file)*/

    /* check, grade, selected */
    // "reportsDir": "./gradingOut/reports",          /* folder for generated JUnit and coverage reports, mounted in docker as /reports (folder)*/

    /* check, pdf, compare */
    // "max": "0",                                    /* Maximal number of submissions to be processed, all others are skipped; use 0 for no limit. (int)*/

    /* check, prepare, selected */
    // "cacheDir": "./gradingOut/cache",              /* folder with cache (mounted as .cache if not "") (folder)*/
    // "clipDir": "./gradingOut/clip",                /* folder for temporarily stored files and folders, a subfolder with the submission id is mounted in docker as /clip. After check, this folder should be empty. (folder)*/
    // "dockerArgs": [],                              /* Additional arguments used to run docker (...string)*/
    // "dockerImage": "node:18.10-alpine",            /* Docker image name (name)*/
    // "dockerScript": "check/checkInDocker.sh",      /* Script to run in docker, this must be path in the vm (file)*/
    // "dockerShellCmd": "sh",                        /* Name of shell used to run in docker (name)*/
    // "dockerUserDir": "root",                       /* Docker user dir (used for npmcache folder) (folder)*/
    // "ignoredDirs": ["node_modules"],               /* Folders ignored when looking for project folder.Hidden folders(starting with ".") are ignored anyway. (...folder)*/
    // "npmCacheDir": "./gradingOut/npmcache",        /* folder with NPM cache (mounted as .npm if not "") (folder)*/
    // "postCheckScript": "check/postCheck.sh",       /* Script to run after docker has run. Environment variables: CLIP (if clipDir is set, this folder with submissionID), PROJECT (student project folder), CHECK (check folder) (file)*/
    // "preCheckScript": "check/preCheck.sh",         /* Script to run before docker is started. Environment variables: CLIP (if clipDir is set, this folder with submissionID), PROJECT (student project folder), CHECK (check folder) (file)*/
    // "projectFile": ".git",                         /* Project file to identify project folder, the project folder is mounted in docker as / testee (file)*/
    // "timeoutPerDockerRun": "300s",                 /* Timeout per docker run(for each submission) (string)*/
    // "volumes": [],                                 /* Additional volumes to be mounted in docker during check (besides submission, reports, clip, cache and npmCache), e.g. node_modules:/testee/node_modules. Host path is made absolut if specified relative to the project folder (...string)*/

    /* check, selected, diff */
    // "patchGradingBranch": "grading",               /* The name of the branch used by the grader (string)*/

    /* grade, pdf, selected */
    // "latexFragmentFile": "./gradingOut/reports/results.tex", /* Name of LaTeX fragment (previously created via grade) (file)*/

    /* grade, prepare, selected */
    // "testOutputEndMarker": "§§§",                  /* End marker containing text to be added to test line in output (string)*/
    // "testOutputStartMarker": "§§§",                /* Start marker containing text to be added to test line in output (string)*/

    /* init, grade, selected */
    // "manualCorrectionsFile": "./${stdInFolder}/manual.corrections.json", /* Name of the manual corrections JSON file; with variables in ${..} (stdInFolder). (file)*/

    /* pdf, prepare, selected */
    // "latex": "xelatex",                            /* Name of LaTeX tool (name)*/
    // "latexConsole": false,                         /* Show LaTex console output (boolean)*/
    // "latexMainFile": "check/latex/grading.tex",    /* Name of LaTeX main file(importing fragment via input) (file)*/

    /* check, pdf */
    // "selectPatched": false,                        /* Process only submission which have been patched (boolean)*/

    /* check, selected */
    // "cleanBefore": false,                          /* Enforce clean before running tests when selected is active. Warning: This removes all reports for existing submissions (boolean)*/
    // "onlyPrepareSubmission": false,                /* Do only run prepare submission, skip docker (boolean)*/
    // "patch": true,                                 /* Applies patch files in the patchFolder to student projects. If no diff file is found, nothing happens. If skipPrepareSubmission is true, no patches are applied (boolean)*/
    // "prepareSubmissionCmd": "git reset --hard",    /* Bash commands to prepare submission folder, one string that is split into command and args (string)*/
    // "skipPrepareSubmission": false,                /* Do not run prepare submission (use this in order to keep manual changes in submission (boolean)*/

    /* grade, selected */
    // "compareResults": true,                        /* When a new result file has been created, show comparison with previous one if found. (boolean)*/
    // "gradedMoodleFile": "./gradingOut/${moodleFile}_graded_${date}-${time}${selected}.csv", /* Name of the Moodle CSV file with the results; with variables in ${..} (moodleFile -- base name without extension, examName, date, time, selected-- add with preceding dot), just "${moodleFile} will override the exported Moodle file. (file)*/
    // "gradingValue": "points",                      /* Use either grade or points for grading in CSV file (grade or points) (string)*/
    // "noStatisticsCSV": false,                      /* Do not create statistics file. (boolean)*/
    // "statisticsFile": "./gradingOut/statistics_${examName}_${date}-${time}.csv", /* Name of the statistics CSV file; with variables in ${..} (examName, date, time). If result file is an Excel file, instead of a statistics file a worksheet in results is created (file)*/

    /* init, conclude */
    // "manualConclusionFile": "${resultsDir}/manual.conclusion.json", /* Name of the manual conclusion JSON file with total grades and aliases; with variables in ${..} (stdInFolder, resultsDir). (file)*/
    // "resultsDir": "./gradingOut",                  /* Path to folder with results to be concluded (folder)*/

    /* pdf, selected */
    // "noPDFZip": false,                             /* Do not zip PDF folder(required for upload) (boolean)*/
    // "pdfDir": "./gradingOut/pdfReports",           /* The folder into which the PDF report is generated (using Moodle's folder structure). (folder)*/
    // "pdfZipFile": "./gradingOut/pdfReports_${date}-${time}.zip", /* File name of created zip file to be uploaded to Moodle(Alle Abgaben Anzeigen / Bewertungsvorgang: Mehrere Feedbackdateien in einer Zip - Datei hochladen); with variables in ${..} (date, time). (file)*/

    /* check */
    // "fromSubmission": "0",                         /* Index (1-based) of submission (included) which is the first one to be checked (int)*/
    // "logOutput": "./gradingOut/check_${date}-${time}.log", /* Name of log file with complete output, no log is created if file is empty. Variables: with variables in ${..} (date, time) (file)*/
    // "skipStudentTests": false,                     /* Do not run student tests (SKIP_STUDENT_TESTS in env set to "true"), existing student test reports are not deleted (boolean)*/
    // "toSubmission": "0",                           /* Index (1-based) of submission (included) which is the last one to be checked. (int)*/

    /* compare */
    // "showUnchanged": false,                        /* Show also individual grading results which have not change (boolean)*/
    // "summaryOnly": false,                          /* Show only summary, no individual changes (boolean)*/

    /* conclude */
    // "autoCopyConclusion": true,                    /* Automatically copy conclusion file to results dir (boolean)*/
    // "autoCopyResult": true,                        /* Automatically copy result file to results dir (boolean)*/
    // "conclusionFile": "./gradingOut/conclusion_${date}-${time}_${firstExam}-${lastExam}.xlsx", /* Name of the concluded results CSV (.csv) or Excel (.xlsx), may use variables in ${..} (date, time, firstExam, lastExam) (file)*/
    // "deprecatedResultsDir": "${resultsDir}/deprecated", /* Path to folder with deprectated (old) result, may use variable ${resultsDir} (folder)*/
    // "keepOldResult": true,                         /* Automatically copy old result file to deprecated results dir (boolean)*/
    // "maxFailed": 3,                                /* Number of failed submissions (not submitted or 5) before total failure, if -1 this is ignored (number)*/
    // "noFinalGradeBefore": "Blatt 03",              /* Number of exam which means exam is started. That is, if only exams before that number are submitted, the final grade will be "-" (not participated). The exams before still count, though! If empty, this is ignored. (string)*/
    // "selectBest": 9,                               /* Select n best result for each student (number)*/
    // "totalExams": 11,                              /* Total number of exams per student at end of term (number)*/

    /* diff */
    // "patchSubmissionBranches": ["main","master"],  /* The names of the branches used in the submission, the first one found is used (...string)*/

    /* grade */
    // "noLatex": false,                              /* Do not create LaTeX fragment(required for PDF reports) (boolean)*/
    // "noMoodleCSV": false,                          /* Do not create Moodle grading file. (boolean)*/
    // "noResultCSV": false,                          /* Do not create CSV with results(for your own statistics) (boolean)*/

    /* init */
    // "generateCorrectionsFile": false,              /* If set to true, a correction file is created as well. It is created in the standard in folder. If a grading scheme already exists, nothing else is generated and the correction files uses information found in the grading schema. If results already exists, the file is populated with the students. (boolean)*/
    // "generateManualConclusionFile": false,         /* If set to true, a manual conclusion file is created as well. (boolean)*/
    // "generateSettings": false,                     /* Generate .grading/settings.json (boolean)*/
    // "noFolders": false,                            /* Do not create standard input folder (boolean)*/
    // "noGitignore": false,                          /* Do not add input and output folders to.gitignore (boolean)*/
    // "stdOutFolder": "gradingOut",                  /* Name of folder to be created for output files(and added to.gitignore). (folder)*/
    // "taskInGeneratedCorrectionsFile": false,       /* If set to true, templates for tasks are created in correction file as well. Usually this is not required. (boolean)*/

    /* pdf */
    // "clean": false,                                /* Automatically clean folder with PDFs (boolean)*/

    /* prepare */
    // "createGradingFile": "",                       /* If provided, instead of grading, create grading scheme based on checks run on solution (file)*/
    // "latexFragmentFileSolution": "./gradingOut/solution/reports/results.tex", /* Name of LaTeX fragment for solution(previously created via prepare) (file)*/
    // "pdfDirSolution": "./gradingOut/solution/pdfReport", /* The folder into which the PDF report for the solution is generated (using Moodle's folder structure). (folder)*/
    // "preserveContainer": false,                    /* Preserves the container after run, u.e. - rm is not passed to Docker (boolean)*/
    // "reportsDirSolution": "./gradingOut/solution/reports", /* folder for generated JUnit and coverage reports of solution, mounted in docker as / reports (folder)*/
    // "skipDocker": false,                           /* Do not run docker and tests, just adjust grading and report (boolean)*/
    // "validateOnly": false,                         /* Do not run tests, only validate grading schema (boolean)*/
}

Dockerfiles

Zum Erstellen der Dockerfiles, in Verzeichnis dockerfiles wechseln und Hinweisen in dortiger README.md folgen.

Tipps

Für Jest muss die Erweiterung jest-junit installiert werden, damit JUnit-kompatible Reports erstellt werden. Dort sollte folgende Konfiguration definiert werden:

reporters: [
    "default",
    ["jest-junit", { suiteNameTemplate: "{filename}", "classNameTemplate": "{filename}", "titleTemplate": "{title}" }],
  ],

License

This program and the accompanying materials are made available under the terms of the Eclipse Public License v. 2.0 which is available at https://www.eclipse.org/legal/epl-2.0.