From ee52c414b65f2d62b652f874b5261ed1db8f9b35 Mon Sep 17 00:00:00 2001 From: Philippe Virouleau Date: Sat, 25 Nov 2023 15:27:19 +0100 Subject: [PATCH 1/3] Implement ExportWCIF --- .env.DEV | 1 + .gitignore | 1 + README.md | 4 ++-- functions/functions.js | 1 + functions/wcif.js | 31 +++++++++++++++++++++++++++++++ package.json | 1 + wcif_data/.keep | 0 7 files changed, 37 insertions(+), 2 deletions(-) create mode 100644 functions/wcif.js create mode 100644 wcif_data/.keep diff --git a/.env.DEV b/.env.DEV index 401cc7e..f0eb2cb 100644 --- a/.env.DEV +++ b/.env.DEV @@ -9,3 +9,4 @@ USE_CDN= API_KEY='example-application-id' API_SECRET='example-secret' COOKIE_SECRET='b8f6959746b617d9c9e90ce4a4b6e0' +WCIF_DATA_FOLDER=wcif_data diff --git a/.gitignore b/.gitignore index 8f5c99a..250d4ab 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ google-credentials.json .env.* !.env.DEV .wcif_cache +wcif_data # Logs logs diff --git a/README.md b/README.md index c651743..42b397b 100644 --- a/README.md +++ b/README.md @@ -10,10 +10,10 @@ Node must be installed on your machine. ``` $ npm install -$ ENV=DEV npx nodemon . +$ npm run dev-server ``` -`ENV=DEV` uses a dev WCA environment running on the same machine. If you would like to use the production WCA site, you need to: +Running the development server will use uses a dev WCA environment running on the same machine. If you would like to use the production WCA site, you need to: 1. Make an OAuth application [here](https://www.worldcubeassociation.org/oauth/applications). For "Scopes", use `public manage_competitions`; for "Callback Urls" use `http://localhost:3033/auth/oauth_response`. 2. Make a copy of the `.env.DEV` file, such as `.env.PROD`. This file should not be committed; `.gitignore` should automatically ignore it. diff --git a/functions/functions.js b/functions/functions.js index 1b0d44d..27a5abd 100644 --- a/functions/functions.js +++ b/functions/functions.js @@ -17,5 +17,6 @@ module.exports = { require('./tuple').functions, require('./udf').functions, require('./util').functions, + require('./wcif').functions, ) } diff --git a/functions/wcif.js b/functions/wcif.js new file mode 100644 index 0000000..3d1807d --- /dev/null +++ b/functions/wcif.js @@ -0,0 +1,31 @@ +const fs = require('fs') +const fse = require('fs-extra') + +const ExportWCIF = { + name: 'ExportWCIF', + docs: 'Export the WCIF to a json file', + args: [ + { + name: 'filename', + type: 'String', + docs: 'WCIF filename (emitted in WCIF_DATA_FOLDER/competitionId)', + defaultValue: 'wcif.json', + }, + ], + outputType: 'String', + usesContext: true, + implementation: (ctx, filename) => { + var folder = `${process.env.WCIF_DATA_FOLDER || '.'}/${ctx.competition.id}`; + var fullPath = `${folder}/${filename}` + fse.ensureDirSync(folder) + fs.writeFileSync( + fullPath, + JSON.stringify(ctx.competition, null, 2) + ) + return `WCIF saved to '${fullPath}'.` + } +} + +module.exports = { + functions: [ExportWCIF], +} diff --git a/package.json b/package.json index 466bc10..7476a54 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "version": "1.0.0", "main": "main.js", "scripts": { + "dev-server": "ENV=DEV npx nodemon -i wcif_data .", "test": "echo \"Error: no test specified\" && exit 1" }, "repository": { diff --git a/wcif_data/.keep b/wcif_data/.keep new file mode 100644 index 0000000..e69de29 From 2d2b2c194452595cb6f6e11c30b2bc1ad14da88e Mon Sep 17 00:00:00 2001 From: Philippe Virouleau Date: Sat, 25 Nov 2023 15:59:56 +0100 Subject: [PATCH 2/3] Implement ClearWCIF --- functions/wcif.js | 44 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/functions/wcif.js b/functions/wcif.js index 3d1807d..7831ba6 100644 --- a/functions/wcif.js +++ b/functions/wcif.js @@ -1,6 +1,48 @@ const fs = require('fs') const fse = require('fs-extra') +const ClearWCIF = { + name: 'ClearWCIF', + docs: 'Remove all childActivities keeping only the main schedule, remove all assignments, cleanup roles, cleanup NatsHelper extension data.', + args: [ + { + name: 'clearExternalExtensions', + type: 'Boolean', + docs: 'Also cleanup external tools extensions.', + defaultValue: false, + }, + ], + outputType: 'Void', + usesContext: true, + mutations: ['schedule', 'persons'], + implementation: (ctx, clearExternalExtensions) => { + const cleanupExtensions = (object) => { + if (clearExternalExtensions) { + object.extensions = [] + } else { + object.extensions = object.extensions.filter(({ id }) => !id.startsWith("org.cubingusa.natshelper")) + } + } + cleanupExtensions(competition) + ctx.competition.persons.forEach((person) => { + // Cleanup roles which are user-defined. + const immutableRoles = ['delegate', 'organizer', 'trainee-delegate'] + person.roles = person.roles.filter((r) => immutableRoles.includes(r)) + person.assignments = [] + cleanupExtensions(person) + }) + ctx.competition.schedule.venues.forEach((venue) => { + venue.rooms.forEach((room) => { + cleanupExtensions(room) + room.activities.forEach((activity) => { + cleanupExtensions(activity) + activity.childActivities = [] + }) + }) + }) + } +} + const ExportWCIF = { name: 'ExportWCIF', docs: 'Export the WCIF to a json file', @@ -27,5 +69,5 @@ const ExportWCIF = { } module.exports = { - functions: [ExportWCIF], + functions: [ClearWCIF, ExportWCIF], } From 3cf94e10d3ca350aae944641d4aa070fd41e1c48 Mon Sep 17 00:00:00 2001 From: Philippe Virouleau Date: Sat, 25 Nov 2023 16:08:05 +0100 Subject: [PATCH 3/3] Implement ImportWCIF --- functions/wcif.js | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/functions/wcif.js b/functions/wcif.js index 7831ba6..7b957fc 100644 --- a/functions/wcif.js +++ b/functions/wcif.js @@ -43,6 +43,29 @@ const ClearWCIF = { } } +const ImportWCIF = { + name: 'ImportWCIF', + docs: 'Import the WCIF from a json file', + args: [ + { + name: 'filename', + type: 'String', + docs: 'WCIF filename (relative to WCIF_DATA_FOLDER/competitionId)', + }, + ], + outputType: 'String', + usesContext: true, + implementation: (ctx, filename) => { + var fullPath = `${process.env.WCIF_DATA_FOLDER || '.'}/${ctx.competition.id}/${filename}` + var wcif = JSON.parse(fs.readFileSync(fullPath)) + if (wcif.id !== ctx.competition.id) { + throw new Error(`The WCIF is not for the correct competition (expected "${ctx.competition.id}", but got "${wcif.id})"`) + } + ctx.competition = wcif + return `Imported WCIF from '${fullPath}'.` + } +} + const ExportWCIF = { name: 'ExportWCIF', docs: 'Export the WCIF to a json file', @@ -69,5 +92,5 @@ const ExportWCIF = { } module.exports = { - functions: [ClearWCIF, ExportWCIF], + functions: [ClearWCIF, ExportWCIF, ImportWCIF], }