diff --git a/db.py b/db.py index 7613e1e..4fd3099 100644 --- a/db.py +++ b/db.py @@ -5,7 +5,8 @@ import collections USER_ID_TO_EMAIL_MAPPING = {} USER_ID_TO_AUTHKEY_MAPPING = {} -ALL_EXERCICES = [] +ALL_EXERCISES = [] +SELECTED_EXERCISES = [] INJECT_BY_UUID = {} INJECT_SEQUENCE_BY_INJECT_UUID = {} INJECT_REQUIREMENTS_BY_INJECT_UUID = {} diff --git a/exercise.py b/exercise.py index c2fc478..ad1684b 100644 --- a/exercise.py +++ b/exercise.py @@ -14,11 +14,9 @@ ACTIVE_EXERCISES_DIR = "active_exercises" def load_exercises() -> bool: - db.ALL_EXERCICES = read_exercise_dir() + db.ALL_EXERCISES = read_exercise_dir() init_inject_flow() init_exercises_tasks() - # mark_task_completed(10, "4703a4b2-0ae4-47f3-9dc3-91250be60156", "e2216993-6192-4e7c-ae30-97cfe9de61b4") # filtering - past 48h - # mark_task_completed(10, "29324587-db6c-4a73-a209-cf8c79871629", "a6b5cf88-ba93-4c3f-8265-04e00d53778e") # Data - Event creation return True @@ -35,12 +33,12 @@ def read_exercise_dir(): def init_inject_flow(): - for exercise in db.ALL_EXERCICES: + for exercise in db.ALL_EXERCISES: for inject in exercise['injects']: inject['exercise_uuid'] = exercise['exercise']['uuid'] db.INJECT_BY_UUID[inject['uuid']] = inject - for exercise in db.ALL_EXERCICES: + for exercise in db.ALL_EXERCISES: for inject_flow in exercise['inject_flow']: db.INJECT_REQUIREMENTS_BY_INJECT_UUID[inject_flow['inject_uuid']] = inject_flow['requirements'] db.INJECT_SEQUENCE_BY_INJECT_UUID[inject_flow['inject_uuid']] = [] @@ -49,7 +47,7 @@ def init_inject_flow(): def init_exercises_tasks(): - for exercise in db.ALL_EXERCICES: + for exercise in db.ALL_EXERCISES: tasks = {} for inject in exercise['injects']: tasks[inject['uuid']] = { @@ -65,8 +63,8 @@ def init_exercises_tasks(): def get_exercises(): - exercices = [] - for exercise in db.ALL_EXERCICES: + exercises = [] + for exercise in db.ALL_EXERCISES: tasks = [] for inject in exercise['injects']: score = 0 @@ -82,7 +80,7 @@ def get_exercises(): "score": score, } ) - exercices.append( + exercises.append( { "name": exercise['exercise']['name'], "uuid": exercise['exercise']['uuid'], @@ -92,8 +90,28 @@ def get_exercises(): "tasks": tasks, } ) - exercices = sorted(exercices, key=lambda d: d['priority']) - return exercices + exercises = sorted(exercises, key=lambda d: d['priority']) + return exercises + + +def get_selected_exercises(): + return db.SELECTED_EXERCISES + + +def change_exercise_selection(exercise_uuid: str, selected: bool): + if selected: + if exercise_uuid not in db.SELECTED_EXERCISES: + db.SELECTED_EXERCISES.append(exercise_uuid) + else: + if exercise_uuid in db.SELECTED_EXERCISES: + db.SELECTED_EXERCISES.remove(exercise_uuid) + + +def resetAllExerciseProgress(): + for user_id in db.USER_ID_TO_EMAIL_MAPPING.keys(): + for exercise_status in db.EXERCISES_STATUS.values(): + for task in exercise_status['tasks'].values(): + mark_task_incomplete(user_id, exercise_status['uuid'], task['uuid']) def get_completed_tasks_for_user(user_id: int): @@ -338,6 +356,9 @@ def check_active_tasks(user_id: int, data: dict, context: dict) -> bool: available_tasks = get_available_tasks_for_user(user_id) for task_uuid in available_tasks: inject = db.INJECT_BY_UUID[task_uuid] + if inject['exercise_uuid'] not in db.SELECTED_EXERCISES: + print(f'exercise not active for this inject {inject['name']}') + continue print(f'checking: {inject['name']}') completed = check_inject(user_id, inject, data, context) if completed: diff --git a/package-lock.json b/package-lock.json index 1ff5dff..7d68106 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,6 +20,7 @@ "@vitejs/plugin-vue": "^5.0.5", "@vue/eslint-config-prettier": "^9.0.0", "autoprefixer": "^10.4.19", + "daisyui": "^4.12.10", "eslint": "^8.57.0", "eslint-plugin-vue": "^9.23.0", "postcss": "^8.4.38", @@ -1419,6 +1420,16 @@ "node": ">= 8" } }, + "node_modules/css-selector-tokenizer": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.8.0.tgz", + "integrity": "sha512-Jd6Ig3/pe62/qe5SBPTN8h8LeUg/pT4lLgtavPf7updwwHpvFzxvOQBHYj2LZDMjUnBzgvIUSjRcf6oT5HzHFg==", + "dev": true, + "dependencies": { + "cssesc": "^3.0.0", + "fastparse": "^1.1.2" + } + }, "node_modules/cssesc": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", @@ -1436,6 +1447,34 @@ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" }, + "node_modules/culori": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/culori/-/culori-3.3.0.tgz", + "integrity": "sha512-pHJg+jbuFsCjz9iclQBqyL3B2HLCBF71BwVNujUYEvCeQMvV97R59MNK3R2+jgJ3a1fcZgI9B3vYgz8lzr/BFQ==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "node_modules/daisyui": { + "version": "4.12.10", + "resolved": "https://registry.npmjs.org/daisyui/-/daisyui-4.12.10.tgz", + "integrity": "sha512-jp1RAuzbHhGdXmn957Z2XsTZStXGHzFfF0FgIOZj3Wv9sH7OZgLfXTRZNfKVYxltGUOBsG1kbWAdF5SrqjebvA==", + "dev": true, + "dependencies": { + "css-selector-tokenizer": "^0.8", + "culori": "^3", + "picocolors": "^1", + "postcss-js": "^4" + }, + "engines": { + "node": ">=16.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/daisyui" + } + }, "node_modules/debug": { "version": "4.3.5", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", @@ -1856,6 +1895,12 @@ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "dev": true }, + "node_modules/fastparse": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/fastparse/-/fastparse-1.1.2.tgz", + "integrity": "sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ==", + "dev": true + }, "node_modules/fastq": { "version": "1.17.1", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", diff --git a/package.json b/package.json index aedda8e..1420ec6 100644 --- a/package.json +++ b/package.json @@ -23,6 +23,7 @@ "@vitejs/plugin-vue": "^5.0.5", "@vue/eslint-config-prettier": "^9.0.0", "autoprefixer": "^10.4.19", + "daisyui": "^4.12.10", "eslint": "^8.57.0", "eslint-plugin-vue": "^9.23.0", "postcss": "^8.4.38", diff --git a/server.py b/server.py index a4c0f9e..2eabae0 100755 --- a/server.py +++ b/server.py @@ -40,6 +40,14 @@ def disconnect(sid): def get_exercises(sid): return exercise_model.get_exercises() +@sio.event +def get_selected_exercises(sid): + return exercise_model.get_selected_exercises() + +@sio.event +def change_exercise_selection(sid, payload): + return exercise_model.change_exercise_selection(payload['exercise_uuid'], payload['selected']) + @sio.event def get_progress(sid): return exercise_model.get_progress() @@ -50,11 +58,15 @@ def get_notifications(sid): @sio.event def mark_task_completed(sid, payload): - return exercise_model.mark_task_completed(payload['user_id'], payload['exercise_uuid'], payload['task_uuid']) + return exercise_model.mark_task_completed(int(payload['user_id']), payload['exercise_uuid'], payload['task_uuid']) @sio.event def mark_task_incomplete(sid, payload): - return exercise_model.mark_task_incomplete(payload['user_id'], payload['exercise_uuid'], payload['task_uuid']) + return exercise_model.mark_task_incomplete(int(payload['user_id']), payload['exercise_uuid'], payload['task_uuid']) + +@sio.event +def reset_all_exercise_progress(sid): + return exercise_model.resetAllExerciseProgress() @sio.on('*') def any_event(event, sid, data={}): diff --git a/src/App.vue b/src/App.vue index 18f2d62..65747c5 100644 --- a/src/App.vue +++ b/src/App.vue @@ -1,8 +1,9 @@ + + diff --git a/src/components/TheLiveLogs.vue b/src/components/TheLiveLogs.vue index ae539bb..293e248 100644 --- a/src/components/TheLiveLogs.vue +++ b/src/components/TheLiveLogs.vue @@ -57,7 +57,7 @@ - + POST + PUT - import { exercises, progresses } from "@/socket"; + import { computed } from "vue"; + import { active_exercises as exercises, progresses, setCompletedState } from "@/socket"; import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome' import { faCheck, faTimes, faGraduationCap } from '@fortawesome/free-solid-svg-icons' - function toggle_completed(completed, user_id, exec_uuid, task_uuid) { - const payload = { - user_id: user_id, - exercise_uuid: exec_uuid, - task_uuid: task_uuid, - } - const event_name = !completed ? "mark_task_completed": "mark_task_incomplete" - socket.emit(event_name, payload, () => { - socket.emit("get_progress", (all_progress) => { - socketState.progresses = all_progress - }) - }) + function toggleCompleted(completed, user_id, exec_uuid, task_uuid) { + setCompletedState(completed, user_id, exec_uuid, task_uuid) } + const hasExercises = computed(() => exercises.value.length > 0) + const hasProgress = computed(() => Object.keys(progresses.value).length > 0) +