coursecode 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +322 -0
- package/THIRD_PARTY_NOTICES.md +22 -0
- package/bin/cli.js +331 -0
- package/framework/assets/logo-coursecode-black.svg +14 -0
- package/framework/assets/logo-coursecode-white.svg +14 -0
- package/framework/assets/logo-coursecode.svg +14 -0
- package/framework/css/01-base.css +160 -0
- package/framework/css/02-layout.css +499 -0
- package/framework/css/accessibility.css +834 -0
- package/framework/css/components/accordions.css +710 -0
- package/framework/css/components/assessments.css +520 -0
- package/framework/css/components/audio-player.css +570 -0
- package/framework/css/components/badges.css +80 -0
- package/framework/css/components/breadcrumbs.css +87 -0
- package/framework/css/components/buttons.css +707 -0
- package/framework/css/components/callouts.css +1280 -0
- package/framework/css/components/cards.css +475 -0
- package/framework/css/components/carousel.css +193 -0
- package/framework/css/components/checkbox-group.css +123 -0
- package/framework/css/components/checklist.css +203 -0
- package/framework/css/components/collapse.css +96 -0
- package/framework/css/components/comparison.css +33 -0
- package/framework/css/components/content-image.css +36 -0
- package/framework/css/components/document-gallery.css +425 -0
- package/framework/css/components/dropdown.css +115 -0
- package/framework/css/components/embed-frame.css +142 -0
- package/framework/css/components/engagement.css +412 -0
- package/framework/css/components/features.css +35 -0
- package/framework/css/components/flip-cards.css +253 -0
- package/framework/css/components/footer.css +353 -0
- package/framework/css/components/forms.css +294 -0
- package/framework/css/components/hero.css +216 -0
- package/framework/css/components/images.css +528 -0
- package/framework/css/components/interactive-timeline.css +274 -0
- package/framework/css/components/intro-cards.css +30 -0
- package/framework/css/components/lightbox.css +666 -0
- package/framework/css/components/loading.css +65 -0
- package/framework/css/components/modals.css +235 -0
- package/framework/css/components/notifications.css +107 -0
- package/framework/css/components/quote.css +150 -0
- package/framework/css/components/sidebar.css +684 -0
- package/framework/css/components/slide-header.css +52 -0
- package/framework/css/components/spinner.css +62 -0
- package/framework/css/components/stats.css +44 -0
- package/framework/css/components/steps.css +232 -0
- package/framework/css/components/tables.css +90 -0
- package/framework/css/components/tabs.css +347 -0
- package/framework/css/components/timeline.css +154 -0
- package/framework/css/components/toggle.css +95 -0
- package/framework/css/components/tooltip.css +226 -0
- package/framework/css/components/video-player.css +438 -0
- package/framework/css/design-tokens.css +707 -0
- package/framework/css/framework.css +86 -0
- package/framework/css/interactions/accessibility.css +75 -0
- package/framework/css/interactions/base.css +92 -0
- package/framework/css/interactions/drag-drop.css +295 -0
- package/framework/css/interactions/fill-in-the-blank.css +236 -0
- package/framework/css/interactions/hotspots.css +69 -0
- package/framework/css/interactions/index.css +45 -0
- package/framework/css/interactions/interactive-image.css +359 -0
- package/framework/css/interactions/likert.css +126 -0
- package/framework/css/interactions/matching.css +354 -0
- package/framework/css/interactions/numeric-input.css +78 -0
- package/framework/css/interactions/sequencing.css +378 -0
- package/framework/css/interactions/true-false.css +177 -0
- package/framework/css/layouts/article.css +258 -0
- package/framework/css/layouts/base.css +30 -0
- package/framework/css/layouts/canvas.css +38 -0
- package/framework/css/layouts/focused.css +236 -0
- package/framework/css/layouts/index.css +29 -0
- package/framework/css/layouts/presentation.css +191 -0
- package/framework/css/layouts/traditional.css +52 -0
- package/framework/css/responsive.css +439 -0
- package/framework/css/utilities/accessibility-utils.css +59 -0
- package/framework/css/utilities/animations.css +419 -0
- package/framework/css/utilities/borders.css +72 -0
- package/framework/css/utilities/colors.css +76 -0
- package/framework/css/utilities/container.css +46 -0
- package/framework/css/utilities/decorative.css +442 -0
- package/framework/css/utilities/display.css +257 -0
- package/framework/css/utilities/flexbox.css +80 -0
- package/framework/css/utilities/grid.css +69 -0
- package/framework/css/utilities/icons.css +534 -0
- package/framework/css/utilities/lists.css +190 -0
- package/framework/css/utilities/spacing.css +167 -0
- package/framework/css/utilities/tables.css +81 -0
- package/framework/css/utilities/typography.css +159 -0
- package/framework/css/utilities/visibility.css +117 -0
- package/framework/docs/COURSE_AUTHORING_GUIDE.md +1773 -0
- package/framework/docs/COURSE_OUTLINE_GUIDE.md +725 -0
- package/framework/docs/COURSE_OUTLINE_TEMPLATE.md +161 -0
- package/framework/docs/DATA_MODEL.md +409 -0
- package/framework/docs/FRAMEWORK_GUIDE.md +1088 -0
- package/framework/docs/USER_GUIDE.md +583 -0
- package/framework/docs/examples/cloudflare-channel-relay.js +169 -0
- package/framework/docs/examples/cloudflare-data-worker.js +102 -0
- package/framework/docs/examples/cloudflare-error-worker.js +228 -0
- package/framework/index.html +175 -0
- package/framework/js/app/AppActions.js +410 -0
- package/framework/js/app/AppState.js +225 -0
- package/framework/js/app/AppUI.js +616 -0
- package/framework/js/assessment/AssessmentActions.js +615 -0
- package/framework/js/assessment/AssessmentFactory.js +471 -0
- package/framework/js/assessment/AssessmentState.js +322 -0
- package/framework/js/assessment/AssessmentUI.js +451 -0
- package/framework/js/automation/api-engagement.js +196 -0
- package/framework/js/automation/api-interactions.js +167 -0
- package/framework/js/automation/api.js +242 -0
- package/framework/js/automation/index.js +41 -0
- package/framework/js/components/interactions/drag-drop.js +884 -0
- package/framework/js/components/interactions/fill-in.js +535 -0
- package/framework/js/components/interactions/hotspot.js +702 -0
- package/framework/js/components/interactions/interaction-base.js +511 -0
- package/framework/js/components/interactions/likert.js +301 -0
- package/framework/js/components/interactions/matching.js +699 -0
- package/framework/js/components/interactions/multiple-choice.js +377 -0
- package/framework/js/components/interactions/numeric.js +271 -0
- package/framework/js/components/interactions/sequencing.js +423 -0
- package/framework/js/components/interactions/true-false.js +241 -0
- package/framework/js/components/ui-components/accordion.js +442 -0
- package/framework/js/components/ui-components/alert.js +88 -0
- package/framework/js/components/ui-components/audio-player.js +1193 -0
- package/framework/js/components/ui-components/callout.js +121 -0
- package/framework/js/components/ui-components/carousel.js +145 -0
- package/framework/js/components/ui-components/checkbox-group.js +87 -0
- package/framework/js/components/ui-components/checklist.js +40 -0
- package/framework/js/components/ui-components/collapse.js +114 -0
- package/framework/js/components/ui-components/comparison.js +30 -0
- package/framework/js/components/ui-components/conditional-display.js +150 -0
- package/framework/js/components/ui-components/content-image.js +41 -0
- package/framework/js/components/ui-components/dropdown.js +262 -0
- package/framework/js/components/ui-components/embed-frame.js +274 -0
- package/framework/js/components/ui-components/features.js +33 -0
- package/framework/js/components/ui-components/flip-card.js +230 -0
- package/framework/js/components/ui-components/form-validator.js +76 -0
- package/framework/js/components/ui-components/hero.js +49 -0
- package/framework/js/components/ui-components/index.js +12 -0
- package/framework/js/components/ui-components/interactive-image.js +235 -0
- package/framework/js/components/ui-components/interactive-timeline.js +285 -0
- package/framework/js/components/ui-components/intro-cards.js +35 -0
- package/framework/js/components/ui-components/lightbox.js +652 -0
- package/framework/js/components/ui-components/modal.js +386 -0
- package/framework/js/components/ui-components/notifications.js +145 -0
- package/framework/js/components/ui-components/progress.js +88 -0
- package/framework/js/components/ui-components/quote.js +41 -0
- package/framework/js/components/ui-components/stats.js +33 -0
- package/framework/js/components/ui-components/steps.js +41 -0
- package/framework/js/components/ui-components/tabs.js +255 -0
- package/framework/js/components/ui-components/timeline.js +42 -0
- package/framework/js/components/ui-components/toggle-group.js +73 -0
- package/framework/js/components/ui-components/tooltip.js +458 -0
- package/framework/js/components/ui-components/value-display.js +133 -0
- package/framework/js/components/ui-components/video-player.js +686 -0
- package/framework/js/core/component-catalog.js +121 -0
- package/framework/js/core/event-bus.js +178 -0
- package/framework/js/core/interaction-catalog.js +149 -0
- package/framework/js/dev/runtime-linter.js +1725 -0
- package/framework/js/drivers/cmi5-driver.js +768 -0
- package/framework/js/drivers/driver-factory.js +77 -0
- package/framework/js/drivers/driver-interface.js +110 -0
- package/framework/js/drivers/http-driver-base.js +241 -0
- package/framework/js/drivers/lti-driver.js +508 -0
- package/framework/js/drivers/proxy-driver.js +444 -0
- package/framework/js/drivers/scorm-12-driver.js +560 -0
- package/framework/js/drivers/scorm-2004-driver.js +775 -0
- package/framework/js/drivers/scorm-driver-base.js +112 -0
- package/framework/js/engagement/engagement-manager.js +404 -0
- package/framework/js/engagement/engagement-progress.js +191 -0
- package/framework/js/engagement/engagement-trackers.js +215 -0
- package/framework/js/engagement/requirement-strategies.js +268 -0
- package/framework/js/main.js +727 -0
- package/framework/js/managers/accessibility-manager.js +499 -0
- package/framework/js/managers/assessment-manager.js +230 -0
- package/framework/js/managers/audio-manager.js +944 -0
- package/framework/js/managers/comment-manager.js +88 -0
- package/framework/js/managers/flag-manager.js +86 -0
- package/framework/js/managers/interaction-manager.js +254 -0
- package/framework/js/managers/interaction-registry.js +96 -0
- package/framework/js/managers/objective-manager.js +423 -0
- package/framework/js/managers/score-manager.js +441 -0
- package/framework/js/managers/video-manager.js +536 -0
- package/framework/js/navigation/Breadcrumbs.js +234 -0
- package/framework/js/navigation/NavigationActions.js +1132 -0
- package/framework/js/navigation/NavigationState.js +276 -0
- package/framework/js/navigation/NavigationUI.js +574 -0
- package/framework/js/navigation/document-gallery.js +357 -0
- package/framework/js/navigation/navigation-helpers.js +175 -0
- package/framework/js/navigation/navigation-validators.js +174 -0
- package/framework/js/state/index.js +8 -0
- package/framework/js/state/lms-connection.js +482 -0
- package/framework/js/state/lms-error-utils.js +58 -0
- package/framework/js/state/state-commits.js +200 -0
- package/framework/js/state/state-domains.js +86 -0
- package/framework/js/state/state-manager.js +502 -0
- package/framework/js/state/state-validation.js +311 -0
- package/framework/js/state/transaction-log.js +41 -0
- package/framework/js/state/xapi-statement-service.js +325 -0
- package/framework/js/utilities/access-control.js +99 -0
- package/framework/js/utilities/breakpoint-manager.js +315 -0
- package/framework/js/utilities/canvas-slide.js +35 -0
- package/framework/js/utilities/conditional-display.js +388 -0
- package/framework/js/utilities/course-channel.js +214 -0
- package/framework/js/utilities/course-helpers.js +420 -0
- package/framework/js/utilities/data-reporter.js +273 -0
- package/framework/js/utilities/error-reporter.js +313 -0
- package/framework/js/utilities/hotspot-helper.js +341 -0
- package/framework/js/utilities/icons.js +348 -0
- package/framework/js/utilities/logger.js +92 -0
- package/framework/js/utilities/markdown-renderer.js +45 -0
- package/framework/js/utilities/scroll-tracker.js +68 -0
- package/framework/js/utilities/ui-initializer.js +146 -0
- package/framework/js/utilities/utilities.js +293 -0
- package/framework/js/utilities/view-manager.js +227 -0
- package/framework/js/validation/html-validators.js +422 -0
- package/framework/js/validation/scorm-validators.js +438 -0
- package/framework/js/vendor/pipwerks.js +931 -0
- package/framework/scripts/generate-narration.js +629 -0
- package/framework/scripts/tts-providers/azure-provider.js +178 -0
- package/framework/scripts/tts-providers/base-provider.js +81 -0
- package/framework/scripts/tts-providers/deepgram-provider.js +135 -0
- package/framework/scripts/tts-providers/elevenlabs-provider.js +148 -0
- package/framework/scripts/tts-providers/google-provider.js +272 -0
- package/framework/scripts/tts-providers/index.js +158 -0
- package/framework/scripts/tts-providers/openai-provider.js +143 -0
- package/framework/version.json +63 -0
- package/lib/authoring-api.js +919 -0
- package/lib/build-linter.js +450 -0
- package/lib/build-packaging.js +186 -0
- package/lib/build.js +88 -0
- package/lib/cloud.js +691 -0
- package/lib/convert.js +341 -0
- package/lib/course-parser.js +936 -0
- package/lib/course-writer.js +258 -0
- package/lib/create.js +248 -0
- package/lib/css-index.js +237 -0
- package/lib/dev.js +51 -0
- package/lib/export-content.js +1246 -0
- package/lib/headless-browser.js +413 -0
- package/lib/import.js +377 -0
- package/lib/index.js +80 -0
- package/lib/info.js +79 -0
- package/lib/interaction-formatters.js +568 -0
- package/lib/manifest/cmi5-manifest.js +63 -0
- package/lib/manifest/lti-tool-config.js +53 -0
- package/lib/manifest/manifest-factory.js +99 -0
- package/lib/manifest/scorm-12-manifest.js +61 -0
- package/lib/manifest/scorm-2004-manifest.js +94 -0
- package/lib/manifest/scorm-proxy-manifest.js +104 -0
- package/lib/manifest-parser.js +96 -0
- package/lib/mcp-prompts.js +753 -0
- package/lib/mcp-server.js +316 -0
- package/lib/narration.js +53 -0
- package/lib/pdf-structure.js +142 -0
- package/lib/preview-export.js +231 -0
- package/lib/preview-routes-api.js +662 -0
- package/lib/preview-routes-editing.js +159 -0
- package/lib/preview-routes-lms.js +230 -0
- package/lib/preview-server.js +564 -0
- package/lib/project-utils.js +269 -0
- package/lib/proxy-templates/proxy.html +68 -0
- package/lib/proxy-templates/scorm-bridge.js +112 -0
- package/lib/scaffold.js +193 -0
- package/lib/schema-extractor.js +361 -0
- package/lib/slide-source-editor.js +586 -0
- package/lib/stub-player/app-viewer.js +195 -0
- package/lib/stub-player/app.js +370 -0
- package/lib/stub-player/catalog-panel.js +312 -0
- package/lib/stub-player/config-panel.js +1303 -0
- package/lib/stub-player/content-generator.js +586 -0
- package/lib/stub-player/content-viewer.js +173 -0
- package/lib/stub-player/debug-panel.js +420 -0
- package/lib/stub-player/edit-mode.js +922 -0
- package/lib/stub-player/edit-utils.js +400 -0
- package/lib/stub-player/header-bar.js +354 -0
- package/lib/stub-player/interaction-editor.js +210 -0
- package/lib/stub-player/interactions-panel.js +565 -0
- package/lib/stub-player/lms-api.js +1094 -0
- package/lib/stub-player/login-screen.js +74 -0
- package/lib/stub-player/outline-mode.js +689 -0
- package/lib/stub-player/styles/_assessments-panel.css +245 -0
- package/lib/stub-player/styles/_base.css +89 -0
- package/lib/stub-player/styles/_catalog-icons.css +96 -0
- package/lib/stub-player/styles/_catalog-panel.css +291 -0
- package/lib/stub-player/styles/_config-panel.css +636 -0
- package/lib/stub-player/styles/_content-viewer.css +834 -0
- package/lib/stub-player/styles/_debug-panel.css +576 -0
- package/lib/stub-player/styles/_edit-mode.css +128 -0
- package/lib/stub-player/styles/_header-bar.css +343 -0
- package/lib/stub-player/styles/_interaction-editor.css +140 -0
- package/lib/stub-player/styles/_interactions-panel.css +1038 -0
- package/lib/stub-player/styles/_login-screen.css +102 -0
- package/lib/stub-player/styles/_outline-mode.css +752 -0
- package/lib/stub-player/styles.css +15 -0
- package/lib/stub-player.js +160 -0
- package/lib/test-data-reporting.js +176 -0
- package/lib/test-error-reporting.js +146 -0
- package/lib/token.js +86 -0
- package/lib/upgrade.js +257 -0
- package/lib/validation-rules.js +517 -0
- package/lib/vite-plugin-content-discovery.js +296 -0
- package/package.json +108 -0
- package/schemas/XMLSchema.dtd +402 -0
- package/schemas/adlcp_v1p3.xsd +111 -0
- package/schemas/adlnav_v1p3.xsd +61 -0
- package/schemas/adlseq_v1p3.xsd +93 -0
- package/schemas/common/anyElement.xsd +27 -0
- package/schemas/common/dataTypes.xsd +138 -0
- package/schemas/common/elementNames.xsd +767 -0
- package/schemas/common/elementTypes.xsd +786 -0
- package/schemas/common/rootElement.xsd +31 -0
- package/schemas/common/vocabTypes.xsd +345 -0
- package/schemas/common/vocabValues.xsd +257 -0
- package/schemas/datatypes.dtd +203 -0
- package/schemas/ims_xml.xsd +35 -0
- package/schemas/imscp_v1p1.xsd +368 -0
- package/schemas/imsss_v1p0.xsd +67 -0
- package/schemas/imsss_v1p0auxresource.xsd +19 -0
- package/schemas/imsss_v1p0control.xsd +20 -0
- package/schemas/imsss_v1p0delivery.xsd +17 -0
- package/schemas/imsss_v1p0limit.xsd +47 -0
- package/schemas/imsss_v1p0objective.xsd +67 -0
- package/schemas/imsss_v1p0random.xsd +16 -0
- package/schemas/imsss_v1p0rollup.xsd +46 -0
- package/schemas/imsss_v1p0seqrule.xsd +108 -0
- package/schemas/imsss_v1p0util.xsd +94 -0
- package/schemas/license.txt +17 -0
- package/schemas/lom.xsd +102 -0
- package/schemas/lomCustom.xsd +62 -0
- package/schemas/lomLoose.xsd +62 -0
- package/schemas/lomStrict.xsd +62 -0
- package/schemas/xml.xsd +81 -0
- package/template/.env.example +92 -0
- package/template/course/assets/audio/example-intro.mp3 +0 -0
- package/template/course/assets/audio/example-ui-demo--compact-player.mp3 +0 -0
- package/template/course/assets/audio/example-ui-demo--demo-modal.mp3 +0 -0
- package/template/course/assets/audio/example-ui-demo--full-player.mp3 +0 -0
- package/template/course/assets/docs/example_md_1.md +39 -0
- package/template/course/assets/docs/example_md_2.md +41 -0
- package/template/course/assets/docs/example_pdf_1_thumbnail.png +0 -0
- package/template/course/assets/docs/example_pdf_2.pdf +0 -0
- package/template/course/assets/images/course-architecture.svg +36 -0
- package/template/course/assets/images/logo.svg +14 -0
- package/template/course/assets/widgets/counter-demo.html +190 -0
- package/template/course/assets/widgets/gravity-painter.html +384 -0
- package/template/course/course-config.js +539 -0
- package/template/course/icons.js +19 -0
- package/template/course/interactions/PLUGIN_GUIDE.md +97 -0
- package/template/course/slides/example-course-structure.js +138 -0
- package/template/course/slides/example-final-exam.js +144 -0
- package/template/course/slides/example-finishing.js +127 -0
- package/template/course/slides/example-interactions-showcase.js +615 -0
- package/template/course/slides/example-preview-tour.js +129 -0
- package/template/course/slides/example-remedial.js +143 -0
- package/template/course/slides/example-summary.js +103 -0
- package/template/course/slides/example-ui-showcase.js +1805 -0
- package/template/course/slides/example-welcome.js +123 -0
- package/template/course/slides/example-workflow.js +140 -0
- package/template/course/theme.css +165 -0
- package/template/eslint.config.js +47 -0
- package/template/package.json +28 -0
- package/template/vite.config.js +339 -0
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file assessment-manager.js
|
|
3
|
+
* @description Public API for the assessment system.
|
|
4
|
+
*
|
|
5
|
+
* This is the ONLY assessment file that course authors should import.
|
|
6
|
+
* It provides:
|
|
7
|
+
* - Factory function to create assessment instances
|
|
8
|
+
* - Query utilities to check assessment completion status
|
|
9
|
+
* - Helper functions for gating and course completion logic
|
|
10
|
+
*
|
|
11
|
+
* ARCHITECTURE NOTE:
|
|
12
|
+
* Unlike NavigationActions (singleton), assessments use a factory pattern
|
|
13
|
+
* because multiple assessment instances can exist per course, each with
|
|
14
|
+
* isolated state stored in separate `assessment_${id}` domains.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import { deepMerge } from '../utilities/utilities.js';
|
|
18
|
+
import stateManager from '../state/index.js';
|
|
19
|
+
import { createAssessmentInstance } from '../assessment/AssessmentFactory.js';
|
|
20
|
+
import { logger } from '../utilities/logger.js';
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Utility function to get domain key for an assessment.
|
|
24
|
+
* @param {string} assessmentId - The unique ID of the assessment
|
|
25
|
+
* @returns {string} The domain key for state manager
|
|
26
|
+
*/
|
|
27
|
+
function getAssessmentDomainKey(assessmentId) {
|
|
28
|
+
return `assessment_${assessmentId}`;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Creates an assessment instance with all required wiring.
|
|
33
|
+
*
|
|
34
|
+
* @param {Object} baseConfig - Base assessment configuration
|
|
35
|
+
* @param {string} baseConfig.id - Unique assessment ID (required)
|
|
36
|
+
* @param {string} baseConfig.title - Assessment title
|
|
37
|
+
* @param {Array} baseConfig.questions - Array of question configurations (required)
|
|
38
|
+
* @param {Object} baseConfig.settings - Assessment settings
|
|
39
|
+
* @param {number} baseConfig.settings.passingScore - Passing score percentage (default: 70)
|
|
40
|
+
* @param {boolean} baseConfig.settings.allowReview - Allow review before submit (default: true)
|
|
41
|
+
* @param {boolean} baseConfig.settings.showProgress - Show progress indicator (default: true)
|
|
42
|
+
* @param {boolean} baseConfig.settings.allowRetake - Allow retaking assessment (default: true)
|
|
43
|
+
* @param {Function} baseConfig.onComplete - Callback when assessment is submitted
|
|
44
|
+
* @param {Object} overrides - Optional configuration overrides (default: {})
|
|
45
|
+
*
|
|
46
|
+
* @returns {Object} Assessment instance with render() method
|
|
47
|
+
*
|
|
48
|
+
* @throws {Error} If baseConfig.id is missing
|
|
49
|
+
* @throws {Error} If baseConfig.questions is missing or empty
|
|
50
|
+
* @throws {Error} If stateManager is not available
|
|
51
|
+
* @throws {Error} If any question has invalid configuration
|
|
52
|
+
* @throws {Error} If settings contain invalid values
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* const assessment = createAssessment({
|
|
56
|
+
* id: 'final-exam',
|
|
57
|
+
* title: 'Final Exam',
|
|
58
|
+
* questions: [...],
|
|
59
|
+
* settings: { passingScore: 80 }
|
|
60
|
+
* });
|
|
61
|
+
* assessment.render(containerElement);
|
|
62
|
+
*/
|
|
63
|
+
export function createAssessment(baseConfig, overrides = {}) {
|
|
64
|
+
// Validate StateManager availability
|
|
65
|
+
if (!stateManager ||
|
|
66
|
+
typeof stateManager.getDomainState !== 'function' ||
|
|
67
|
+
typeof stateManager.setDomainState !== 'function') {
|
|
68
|
+
throw new Error('AssessmentManager: StateManager with domain persistence APIs is required');
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Merge configuration and delegate to factory (validation happens there)
|
|
72
|
+
const fullConfig = deepMerge({}, baseConfig, overrides);
|
|
73
|
+
return createAssessmentInstance(fullConfig);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Checks if a specific assessment has been passed.
|
|
78
|
+
*
|
|
79
|
+
* @param {string} assessmentId - The unique ID of the assessment
|
|
80
|
+
* @returns {boolean} True if the assessment has been submitted and passed, false if not initialized or not passed
|
|
81
|
+
* @throws {Error} If assessmentId is not provided
|
|
82
|
+
*
|
|
83
|
+
* @example
|
|
84
|
+
* if (hasPassedAssessment('final-exam')) {
|
|
85
|
+
* // Unlock next module
|
|
86
|
+
* }
|
|
87
|
+
*/
|
|
88
|
+
export function hasPassedAssessment(assessmentId) {
|
|
89
|
+
if (!assessmentId) {
|
|
90
|
+
const error = new Error('AssessmentManager.hasPassedAssessment: assessmentId is required');
|
|
91
|
+
logger.error(error.message, { domain: 'assessment', operation: 'hasPassedAssessment', stack: error.stack });
|
|
92
|
+
throw error;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const domainKey = getAssessmentDomainKey(assessmentId);
|
|
96
|
+
const assessmentDomain = stateManager.getDomainState(domainKey);
|
|
97
|
+
|
|
98
|
+
// Assessment hasn't been initialized yet (never visited) - cannot be passed
|
|
99
|
+
if (!assessmentDomain || !assessmentDomain.summary) {
|
|
100
|
+
return false;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const summary = assessmentDomain.summary;
|
|
104
|
+
return summary.submitted === true && summary.lastResults?.passed === true;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Checks if an assessment meets its completion requirements.
|
|
109
|
+
* Uses the completionRequirements configuration to determine what's needed.
|
|
110
|
+
*
|
|
111
|
+
* @param {string} assessmentId - The unique ID of the assessment
|
|
112
|
+
* @param {Object} completionRequirements - The completion requirements configuration
|
|
113
|
+
* @param {boolean} completionRequirements.requireSubmission - Whether submission is required
|
|
114
|
+
* @param {boolean} completionRequirements.requirePass - Whether passing is required
|
|
115
|
+
* @returns {boolean} True if the assessment meets its completion requirements, false if not initialized or requirements not met
|
|
116
|
+
* @throws {Error} If assessmentId is not provided
|
|
117
|
+
*
|
|
118
|
+
* @example
|
|
119
|
+
* const requirements = { requireSubmission: true, requirePass: true };
|
|
120
|
+
* if (meetsCompletionRequirements('quiz-1', requirements)) {
|
|
121
|
+
* // Allow navigation
|
|
122
|
+
* }
|
|
123
|
+
*/
|
|
124
|
+
export function meetsCompletionRequirements(assessmentId, completionRequirements = {}) {
|
|
125
|
+
if (!assessmentId) {
|
|
126
|
+
const error = new Error('AssessmentManager.meetsCompletionRequirements: assessmentId is required');
|
|
127
|
+
logger.error(error.message, { domain: 'assessment', operation: 'meetsCompletionRequirements', stack: error.stack });
|
|
128
|
+
throw error;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const domainKey = getAssessmentDomainKey(assessmentId);
|
|
132
|
+
const assessmentDomain = stateManager.getDomainState(domainKey);
|
|
133
|
+
|
|
134
|
+
// Assessment hasn't been initialized yet (never visited) - requirements cannot be met
|
|
135
|
+
if (!assessmentDomain || !assessmentDomain.summary) {
|
|
136
|
+
return false;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const summary = assessmentDomain.summary;
|
|
140
|
+
|
|
141
|
+
// Check submission requirement
|
|
142
|
+
if (completionRequirements.requireSubmission && !summary.submitted) {
|
|
143
|
+
return false;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// Check pass requirement
|
|
147
|
+
if (completionRequirements.requirePass) {
|
|
148
|
+
const passed = summary.lastResults?.passed === true;
|
|
149
|
+
if (!passed) {
|
|
150
|
+
return false;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
return true;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Checks if all assessments with completion requirements have met those requirements.
|
|
159
|
+
* Used for course completion evaluation.
|
|
160
|
+
*
|
|
161
|
+
* @param {Array<Object>} assessmentSlides - Array of assessment slide entries from CourseHelpers.getSlidesByType('assessment')
|
|
162
|
+
* @returns {boolean} True if all assessments meet their requirements
|
|
163
|
+
* @throws {Error} If assessmentSlides is not an array
|
|
164
|
+
*
|
|
165
|
+
* @example
|
|
166
|
+
* const assessmentSlides = await CourseHelpers.getSlidesByType('assessment');
|
|
167
|
+
* if (allAssessmentsMeetRequirements(assessmentSlides)) {
|
|
168
|
+
* // Course is complete
|
|
169
|
+
* }
|
|
170
|
+
*/
|
|
171
|
+
export function allAssessmentsMeetRequirements(assessmentSlides = []) {
|
|
172
|
+
if (!Array.isArray(assessmentSlides)) {
|
|
173
|
+
const error = new Error('AssessmentManager.allAssessmentsMeetRequirements: assessmentSlides must be an array');
|
|
174
|
+
logger.error(error.message, { domain: 'assessment', operation: 'allAssessmentsMeetRequirements', stack: error.stack });
|
|
175
|
+
throw error;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
if (assessmentSlides.length === 0) {
|
|
179
|
+
return true; // No assessments means this criteria is met
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// Filter to only assessments with completion requirements, then check if they meet them
|
|
183
|
+
const assessmentsWithRequirements = assessmentSlides.filter(slide => {
|
|
184
|
+
const reqs = slide.assessment?.completionRequirements;
|
|
185
|
+
return reqs && (reqs.requireSubmission || reqs.requirePass);
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
if (assessmentsWithRequirements.length === 0) {
|
|
189
|
+
return true; // No assessments with requirements
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
return assessmentsWithRequirements.every(slide =>
|
|
193
|
+
meetsCompletionRequirements(slide.assessmentId, slide.assessment.completionRequirements)
|
|
194
|
+
);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Gets the score percentage from a submitted assessment.
|
|
199
|
+
*
|
|
200
|
+
* @param {string} assessmentId - The unique ID of the assessment
|
|
201
|
+
* @returns {number|null} Score percentage (0-100) if assessment has been submitted, null otherwise
|
|
202
|
+
* @throws {Error} If assessmentId is not provided
|
|
203
|
+
*
|
|
204
|
+
* @example
|
|
205
|
+
* const score = getAssessmentScore('final-exam');
|
|
206
|
+
* if (score !== null) {
|
|
207
|
+
* console.log(`Score: ${score}%`);
|
|
208
|
+
* }
|
|
209
|
+
*/
|
|
210
|
+
export function getAssessmentScore(assessmentId) {
|
|
211
|
+
if (!assessmentId) {
|
|
212
|
+
const error = new Error('AssessmentManager.getAssessmentScore: assessmentId is required');
|
|
213
|
+
logger.error(error.message, { domain: 'assessment', operation: 'getAssessmentScore', stack: error.stack });
|
|
214
|
+
throw error;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
const domainKey = getAssessmentDomainKey(assessmentId);
|
|
218
|
+
const assessmentDomain = stateManager.getDomainState(domainKey);
|
|
219
|
+
|
|
220
|
+
// Assessment hasn't been initialized or submitted yet
|
|
221
|
+
if (!assessmentDomain?.summary?.lastResults) {
|
|
222
|
+
return null;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
const scorePercentage = assessmentDomain.summary.lastResults.scorePercentage;
|
|
226
|
+
if (typeof scorePercentage !== 'number' || isNaN(scorePercentage) || scorePercentage < 0 || scorePercentage > 100) {
|
|
227
|
+
return null;
|
|
228
|
+
}
|
|
229
|
+
return scorePercentage;
|
|
230
|
+
}
|