diff --git a/src/collect-code-from-firebase-dump.js b/src/collect-code-from-firebase-dump.js new file mode 100755 index 0000000..ea5f4d1 --- /dev/null +++ b/src/collect-code-from-firebase-dump.js @@ -0,0 +1,26 @@ +// Extracts students' code submissions from a single JSON firebase dump +// and returns them as a JSON array of `file` entries, +// for evaluate-plagiarism-post.js to consume. + +const fs = require('fs'); + +const SUBMISSIONS_DUMP_FILE = './exam-data/eemi-own-exam-export.json'; +const EXERCISE_IDENTIFIER = 'code11'; + +// returns [ { name, content, type } ] +async function parse(file) { + const { submissions } = require(`./${file}`); // await fs.promises.readFile(`${path}/${dirent.name}`); + return Object.keys(submissions).map(name => { + const submission = submissions[name]; + return { + name, + contents: submission[EXERCISE_IDENTIFIER], // code + type: 'js' + }; + }); +} + +console.warn(`Parsing code submissions from ${SUBMISSIONS_DUMP_FILE}...`) +parse(SUBMISSIONS_DUMP_FILE) + .then(files => console.log(JSON.stringify(files, null, 2))) + .catch(console.error); diff --git a/src/collect-code-from-json-files.js b/src/collect-code-from-json-files.js new file mode 100644 index 0000000..02b47c4 --- /dev/null +++ b/src/collect-code-from-json-files.js @@ -0,0 +1,28 @@ +// Extracts students' code submissions from ./students/*.json +// and returns them as a JSON array of `file` entries, +// for evaluate-plagiarism-post.js to consume. + +const fs = require('fs'); + +const SUBMISSIONS_DIRECTORY = './students'; +const EXERCISE_IDENTIFIER = 'code11'; + +// returns [ { name, content, type } ] +async function ls(path) { + const dir = await fs.promises.opendir(path); + const files = []; // structure: [ { name, content, type } ] + for await (const dirent of dir) { + const submission = await fs.promises.readFile(`${path}/${dirent.name}`); + files.push({ + name: `${dirent.name.split('@')[0]}.js`, // extract student name from email address, and add .js file extension + contents: JSON.parse(submission)[EXERCISE_IDENTIFIER], // code + type: 'js' + }); + } + return files; +} + +console.warn(`Parsing code submissions from ${SUBMISSIONS_DIRECTORY}...`) +ls(SUBMISSIONS_DIRECTORY) + .then(files => console.log(JSON.stringify(files, null, 2))) + .catch(console.error); diff --git a/src/evaluate-plagiarism-post.js b/src/evaluate-plagiarism-post.js new file mode 100644 index 0000000..bab92ee --- /dev/null +++ b/src/evaluate-plagiarism-post.js @@ -0,0 +1,45 @@ +// Reads students' code submissions from ./student-code-entries.json +// (generated by collect-code-from-*.js from ./students/*.json) +// and POSTs them to Zino's plagiarism detection API. + +const fs = require('fs'); +const https = require('https'); + +const ENTRIES_FILE = './student-code-entries.json'; +const SUBMIT_URL = 'https://plagiat.krugazor.eu/api/submit'; + +// test: +// $ curl -v -X POST --header "Content-Type: application/json" --header "P-Token: ${PLAGIAT_TOKEN}" --data "{\"files\":[]}" https://plagiat.krugazor.eu/api/submit +// $ curl -v -X POST --header "Content-Type: application/json" --header "P-Token: ${PLAGIAT_TOKEN}" --data '{"files":[{"name":"1.js","contents":"console.log(\"a\");"},{"name":"2.js","contents":"console.log(\"b\");"}]}' https://plagiat.krugazor.eu/api/submit + +const post = (body) => new Promise((resolve, reject) => { + const data = JSON.stringify(body); + const options = { + method: 'POST', + hostname: 'plagiat.krugazor.eu', + port: 443, + path: '/api/submit', + headers: { + 'Content-Type': 'application/json', + 'Content-Length': data.length, + 'P-Token': process.env.PLAGIAT_TOKEN // secret + } + }; + const req = https.request(options, res => { + console.log(`statusCode: ${res.statusCode}`); + res.on('data', responseData => resolve(responseData.toString('utf8'))); + }) + req.on('error', reject); + req.write(data); + req.end(); +}); + +async function submitEntries(entriesFile) { + const files = await fs.promises.readFile(entriesFile, { encoding: 'utf8' }); + return await post({ files }); +} + +console.warn(`Sending code submissions from ${ENTRIES_FILE} to ${SUBMIT_URL}...`) +submitEntries(ENTRIES_FILE) + .then(result => console.log(result)) + .catch(console.error);