@patch-adams/core 1.4.11 → 1.4.13

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/dist/index.cjs CHANGED
@@ -3041,10 +3041,10 @@ function generateLrsBridgeCode(options) {
3041
3041
  var result = {
3042
3042
  completion: true,
3043
3043
  extensions: {
3044
- 'https://patch-adams.io/xapi/extensions/assessmentName': data.assessmentName || data.title || null,
3045
- 'https://patch-adams.io/xapi/extensions/lessonName': lessonInfo.name || null,
3046
- 'https://patch-adams.io/xapi/extensions/sectionName': lessonInfo.sectionName || null,
3047
- 'https://patch-adams.io/xapi/extensions/questionCount': data.questionCount || null
3044
+ 'https://w3id.org/xapi/acrossx/extensions/assessmentName': data.assessmentName || data.title || null,
3045
+ 'https://w3id.org/xapi/acrossx/extensions/lessonName': lessonInfo.name || null,
3046
+ 'https://w3id.org/xapi/acrossx/extensions/sectionName': lessonInfo.sectionName || null,
3047
+ 'https://w3id.org/xapi/acrossx/extensions/questionCount': data.questionCount || null
3048
3048
  }
3049
3049
  };
3050
3050
 
@@ -3088,13 +3088,13 @@ function generateLrsBridgeCode(options) {
3088
3088
  var result = {
3089
3089
  response: data.answer || data.response || '',
3090
3090
  extensions: {
3091
- 'https://patch-adams.io/xapi/extensions/questionNumber': data.questionNumber || null,
3092
- 'https://patch-adams.io/xapi/extensions/questionText': data.questionText || null,
3093
- 'https://patch-adams.io/xapi/extensions/answerText': data.answer || data.response || null,
3094
- 'https://patch-adams.io/xapi/extensions/correctAnswer': data.correctAnswer || null,
3095
- 'https://patch-adams.io/xapi/extensions/assessmentName': data.assessmentName || null,
3096
- 'https://patch-adams.io/xapi/extensions/lessonName': lessonInfo.lessonName || lessonInfo.name || null,
3097
- 'https://patch-adams.io/xapi/extensions/sectionName': lessonInfo.sectionName || null
3091
+ 'https://w3id.org/xapi/acrossx/extensions/questionNumber': data.questionNumber || null,
3092
+ 'https://w3id.org/xapi/acrossx/extensions/questionText': data.questionText || null,
3093
+ 'https://w3id.org/xapi/acrossx/extensions/answerText': data.answer || data.response || null,
3094
+ 'https://w3id.org/xapi/acrossx/extensions/correctAnswer': data.correctAnswer || null,
3095
+ 'https://w3id.org/xapi/acrossx/extensions/assessmentName': data.assessmentName || null,
3096
+ 'https://w3id.org/xapi/acrossx/extensions/lessonName': lessonInfo.lessonName || lessonInfo.name || null,
3097
+ 'https://w3id.org/xapi/acrossx/extensions/sectionName': lessonInfo.sectionName || null
3098
3098
  }
3099
3099
  };
3100
3100
 
@@ -3395,6 +3395,9 @@ function generateLrsBridgeCode(options) {
3395
3395
  function setupQuizInterceptors() {
3396
3396
  if (!TRACK_QUIZZES) return;
3397
3397
 
3398
+ // Set up Knowledge Check specific interceptors for Rise blocks
3399
+ setupKnowledgeCheckInterceptors();
3400
+
3398
3401
  var quizObserver = new MutationObserver(function(mutations) {
3399
3402
  mutations.forEach(function(mutation) {
3400
3403
  mutation.addedNodes.forEach(function(node) {
@@ -3599,6 +3602,162 @@ function generateLrsBridgeCode(options) {
3599
3602
  });
3600
3603
  }
3601
3604
 
3605
+ // Track submitted Knowledge Check blocks to avoid duplicates
3606
+ var submittedKnowledgeChecks = {};
3607
+
3608
+ /**
3609
+ * Set up interceptors specifically for Rise Knowledge Check blocks
3610
+ * These blocks have a different DOM structure than standard quiz results
3611
+ */
3612
+ function setupKnowledgeCheckInterceptors() {
3613
+ if (!TRACK_QUIZZES) return;
3614
+
3615
+ // Intercept submit button clicks on Knowledge Check blocks
3616
+ document.addEventListener('click', function(e) {
3617
+ var submitBtn = e.target.closest('.quiz-card__button');
3618
+ if (!submitBtn) return;
3619
+
3620
+ // Find the Knowledge Check block
3621
+ var kcBlock = submitBtn.closest('[data-test-id="block-kc-card"]') ||
3622
+ submitBtn.closest('.block-knowledge');
3623
+ if (!kcBlock) return;
3624
+
3625
+ // Wait for feedback to appear after submission
3626
+ setTimeout(function() {
3627
+ extractKnowledgeCheckResult(kcBlock);
3628
+ }, 500);
3629
+ }, true);
3630
+
3631
+ log('Knowledge Check interceptors set up');
3632
+ }
3633
+
3634
+ /**
3635
+ * Extract and send xAPI statement for a Knowledge Check submission
3636
+ */
3637
+ function extractKnowledgeCheckResult(kcBlock) {
3638
+ // Get block ID for deduplication
3639
+ var blockContainer = kcBlock.closest('[data-block-id]');
3640
+ var blockId = blockContainer ? blockContainer.getAttribute('data-block-id') : null;
3641
+
3642
+ // Get question ID from the title element
3643
+ var questionTitleEl = kcBlock.querySelector('.quiz-card__title');
3644
+ var questionId = questionTitleEl ? questionTitleEl.id : (blockId ? 'q-' + blockId : 'q-' + generateUUID());
3645
+
3646
+ // Check if we already processed this submission (avoid duplicates)
3647
+ var submissionKey = blockId || questionId;
3648
+ var feedbackLabel = kcBlock.querySelector('.quiz-card__feedback-label');
3649
+ if (!feedbackLabel) {
3650
+ log('Knowledge Check: No feedback visible yet');
3651
+ return;
3652
+ }
3653
+
3654
+ var feedbackText = feedbackLabel.textContent.trim().toLowerCase();
3655
+ var submissionId = submissionKey + '-' + feedbackText;
3656
+
3657
+ if (submittedKnowledgeChecks[submissionId]) {
3658
+ log('Knowledge Check: Already processed this submission');
3659
+ return;
3660
+ }
3661
+ submittedKnowledgeChecks[submissionId] = true;
3662
+
3663
+ // Get question text
3664
+ var questionText = '';
3665
+ var questionTextEl = kcBlock.querySelector('.quiz-card__title .fr-view, .quiz-card__title');
3666
+ if (questionTextEl) {
3667
+ questionText = questionTextEl.textContent.trim();
3668
+ }
3669
+
3670
+ // Determine question type from aria-label
3671
+ var wrapper = kcBlock.querySelector('[data-test-id="block-knowledge-wrapper"]');
3672
+ var ariaLabel = wrapper ? wrapper.getAttribute('aria-label') : '';
3673
+ var questionType = 'unknown';
3674
+ if (ariaLabel.indexOf('Multiple choice') > -1) questionType = 'multiple-choice';
3675
+ else if (ariaLabel.indexOf('Multiple response') > -1) questionType = 'multiple-response';
3676
+ else if (ariaLabel.indexOf('Fill in the blank') > -1) questionType = 'fill-in-blank';
3677
+ else if (ariaLabel.indexOf('Matching') > -1) questionType = 'matching';
3678
+
3679
+ // Get selected answer(s) based on question type
3680
+ var answerText = extractKnowledgeCheckAnswer(kcBlock, questionType);
3681
+
3682
+ // Get correct/incorrect from feedback
3683
+ var isCorrect = feedbackText === 'correct';
3684
+
3685
+ // Get lesson context
3686
+ var lessonInfo = getCachedLessonInfo();
3687
+
3688
+ log('Knowledge Check submitted:', {
3689
+ questionId: questionId,
3690
+ questionText: questionText.substring(0, 50) + '...',
3691
+ questionType: questionType,
3692
+ answer: answerText.substring(0, 50) + '...',
3693
+ correct: isCorrect
3694
+ });
3695
+
3696
+ // Send question answered statement using existing LRS method
3697
+ LRS.questionAnswered({
3698
+ questionId: questionId,
3699
+ questionGuid: blockId || generateUUID(),
3700
+ questionNumber: 1,
3701
+ questionText: questionText.substring(0, 500),
3702
+ questionType: questionType,
3703
+ answer: answerText.substring(0, 500),
3704
+ correct: isCorrect,
3705
+ result: isCorrect ? 'correct' : 'incorrect',
3706
+ assessmentName: 'Knowledge Check',
3707
+ lessonName: lessonInfo.name,
3708
+ sectionName: lessonInfo.sectionName
3709
+ });
3710
+ }
3711
+
3712
+ /**
3713
+ * Extract the selected answer text from a Knowledge Check block
3714
+ * based on the question type
3715
+ */
3716
+ function extractKnowledgeCheckAnswer(kcBlock, questionType) {
3717
+ var answerText = '';
3718
+
3719
+ if (questionType === 'multiple-choice') {
3720
+ // Find checked radio button
3721
+ var checkedInput = kcBlock.querySelector('.quiz-multiple-choice-option__input:checked');
3722
+ if (checkedInput) {
3723
+ var label = checkedInput.closest('.quiz-multiple-choice-option');
3724
+ var textEl = label ? label.querySelector('.quiz-multiple-choice-option__label .fr-view, .quiz-multiple-choice-option__label') : null;
3725
+ answerText = textEl ? textEl.textContent.trim() : '';
3726
+ }
3727
+ }
3728
+ else if (questionType === 'multiple-response') {
3729
+ // Find all checked checkboxes
3730
+ var checkedInputs = kcBlock.querySelectorAll('.quiz-multiple-response-option__input:checked');
3731
+ var answers = [];
3732
+ checkedInputs.forEach(function(input) {
3733
+ var label = input.closest('.quiz-multiple-response-option');
3734
+ var textEl = label ? label.querySelector('.quiz-multiple-response-option__text .fr-view, .quiz-multiple-response-option__text') : null;
3735
+ if (textEl) answers.push(textEl.textContent.trim());
3736
+ });
3737
+ answerText = answers.join('; ');
3738
+ }
3739
+ else if (questionType === 'fill-in-blank') {
3740
+ // Get text input value
3741
+ var textInput = kcBlock.querySelector('.quiz-fill__input');
3742
+ answerText = textInput ? textInput.value.trim() : '';
3743
+ }
3744
+ else if (questionType === 'matching') {
3745
+ // Extract matching pairs from the drop zones
3746
+ var dropZones = kcBlock.querySelectorAll('.matching-drop-zone');
3747
+ var pairs = [];
3748
+ dropZones.forEach(function(zone) {
3749
+ var prompt = zone.querySelector('.matching-prompt-content');
3750
+ var response = zone.querySelector('.matching-interaction-piece-content');
3751
+ if (prompt && response) {
3752
+ pairs.push(prompt.textContent.trim() + ' \u2192 ' + response.textContent.trim());
3753
+ }
3754
+ });
3755
+ answerText = pairs.length > 0 ? pairs.join('; ') : 'Matching submitted';
3756
+ }
3757
+
3758
+ return answerText;
3759
+ }
3760
+
3602
3761
  function setupInteractionInterceptors() {
3603
3762
  if (!TRACK_INTERACTIONS) return;
3604
3763