@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/cli.cjs CHANGED
@@ -3377,10 +3377,10 @@ function generateLrsBridgeCode(options) {
3377
3377
  var result = {
3378
3378
  completion: true,
3379
3379
  extensions: {
3380
- 'https://patch-adams.io/xapi/extensions/assessmentName': data.assessmentName || data.title || null,
3381
- 'https://patch-adams.io/xapi/extensions/lessonName': lessonInfo.name || null,
3382
- 'https://patch-adams.io/xapi/extensions/sectionName': lessonInfo.sectionName || null,
3383
- 'https://patch-adams.io/xapi/extensions/questionCount': data.questionCount || null
3380
+ 'https://w3id.org/xapi/acrossx/extensions/assessmentName': data.assessmentName || data.title || null,
3381
+ 'https://w3id.org/xapi/acrossx/extensions/lessonName': lessonInfo.name || null,
3382
+ 'https://w3id.org/xapi/acrossx/extensions/sectionName': lessonInfo.sectionName || null,
3383
+ 'https://w3id.org/xapi/acrossx/extensions/questionCount': data.questionCount || null
3384
3384
  }
3385
3385
  };
3386
3386
 
@@ -3424,13 +3424,13 @@ function generateLrsBridgeCode(options) {
3424
3424
  var result = {
3425
3425
  response: data.answer || data.response || '',
3426
3426
  extensions: {
3427
- 'https://patch-adams.io/xapi/extensions/questionNumber': data.questionNumber || null,
3428
- 'https://patch-adams.io/xapi/extensions/questionText': data.questionText || null,
3429
- 'https://patch-adams.io/xapi/extensions/answerText': data.answer || data.response || null,
3430
- 'https://patch-adams.io/xapi/extensions/correctAnswer': data.correctAnswer || null,
3431
- 'https://patch-adams.io/xapi/extensions/assessmentName': data.assessmentName || null,
3432
- 'https://patch-adams.io/xapi/extensions/lessonName': lessonInfo.lessonName || lessonInfo.name || null,
3433
- 'https://patch-adams.io/xapi/extensions/sectionName': lessonInfo.sectionName || null
3427
+ 'https://w3id.org/xapi/acrossx/extensions/questionNumber': data.questionNumber || null,
3428
+ 'https://w3id.org/xapi/acrossx/extensions/questionText': data.questionText || null,
3429
+ 'https://w3id.org/xapi/acrossx/extensions/answerText': data.answer || data.response || null,
3430
+ 'https://w3id.org/xapi/acrossx/extensions/correctAnswer': data.correctAnswer || null,
3431
+ 'https://w3id.org/xapi/acrossx/extensions/assessmentName': data.assessmentName || null,
3432
+ 'https://w3id.org/xapi/acrossx/extensions/lessonName': lessonInfo.lessonName || lessonInfo.name || null,
3433
+ 'https://w3id.org/xapi/acrossx/extensions/sectionName': lessonInfo.sectionName || null
3434
3434
  }
3435
3435
  };
3436
3436
 
@@ -3731,6 +3731,9 @@ function generateLrsBridgeCode(options) {
3731
3731
  function setupQuizInterceptors() {
3732
3732
  if (!TRACK_QUIZZES) return;
3733
3733
 
3734
+ // Set up Knowledge Check specific interceptors for Rise blocks
3735
+ setupKnowledgeCheckInterceptors();
3736
+
3734
3737
  var quizObserver = new MutationObserver(function(mutations) {
3735
3738
  mutations.forEach(function(mutation) {
3736
3739
  mutation.addedNodes.forEach(function(node) {
@@ -3935,6 +3938,162 @@ function generateLrsBridgeCode(options) {
3935
3938
  });
3936
3939
  }
3937
3940
 
3941
+ // Track submitted Knowledge Check blocks to avoid duplicates
3942
+ var submittedKnowledgeChecks = {};
3943
+
3944
+ /**
3945
+ * Set up interceptors specifically for Rise Knowledge Check blocks
3946
+ * These blocks have a different DOM structure than standard quiz results
3947
+ */
3948
+ function setupKnowledgeCheckInterceptors() {
3949
+ if (!TRACK_QUIZZES) return;
3950
+
3951
+ // Intercept submit button clicks on Knowledge Check blocks
3952
+ document.addEventListener('click', function(e) {
3953
+ var submitBtn = e.target.closest('.quiz-card__button');
3954
+ if (!submitBtn) return;
3955
+
3956
+ // Find the Knowledge Check block
3957
+ var kcBlock = submitBtn.closest('[data-test-id="block-kc-card"]') ||
3958
+ submitBtn.closest('.block-knowledge');
3959
+ if (!kcBlock) return;
3960
+
3961
+ // Wait for feedback to appear after submission
3962
+ setTimeout(function() {
3963
+ extractKnowledgeCheckResult(kcBlock);
3964
+ }, 500);
3965
+ }, true);
3966
+
3967
+ log('Knowledge Check interceptors set up');
3968
+ }
3969
+
3970
+ /**
3971
+ * Extract and send xAPI statement for a Knowledge Check submission
3972
+ */
3973
+ function extractKnowledgeCheckResult(kcBlock) {
3974
+ // Get block ID for deduplication
3975
+ var blockContainer = kcBlock.closest('[data-block-id]');
3976
+ var blockId = blockContainer ? blockContainer.getAttribute('data-block-id') : null;
3977
+
3978
+ // Get question ID from the title element
3979
+ var questionTitleEl = kcBlock.querySelector('.quiz-card__title');
3980
+ var questionId = questionTitleEl ? questionTitleEl.id : (blockId ? 'q-' + blockId : 'q-' + generateUUID());
3981
+
3982
+ // Check if we already processed this submission (avoid duplicates)
3983
+ var submissionKey = blockId || questionId;
3984
+ var feedbackLabel = kcBlock.querySelector('.quiz-card__feedback-label');
3985
+ if (!feedbackLabel) {
3986
+ log('Knowledge Check: No feedback visible yet');
3987
+ return;
3988
+ }
3989
+
3990
+ var feedbackText = feedbackLabel.textContent.trim().toLowerCase();
3991
+ var submissionId = submissionKey + '-' + feedbackText;
3992
+
3993
+ if (submittedKnowledgeChecks[submissionId]) {
3994
+ log('Knowledge Check: Already processed this submission');
3995
+ return;
3996
+ }
3997
+ submittedKnowledgeChecks[submissionId] = true;
3998
+
3999
+ // Get question text
4000
+ var questionText = '';
4001
+ var questionTextEl = kcBlock.querySelector('.quiz-card__title .fr-view, .quiz-card__title');
4002
+ if (questionTextEl) {
4003
+ questionText = questionTextEl.textContent.trim();
4004
+ }
4005
+
4006
+ // Determine question type from aria-label
4007
+ var wrapper = kcBlock.querySelector('[data-test-id="block-knowledge-wrapper"]');
4008
+ var ariaLabel = wrapper ? wrapper.getAttribute('aria-label') : '';
4009
+ var questionType = 'unknown';
4010
+ if (ariaLabel.indexOf('Multiple choice') > -1) questionType = 'multiple-choice';
4011
+ else if (ariaLabel.indexOf('Multiple response') > -1) questionType = 'multiple-response';
4012
+ else if (ariaLabel.indexOf('Fill in the blank') > -1) questionType = 'fill-in-blank';
4013
+ else if (ariaLabel.indexOf('Matching') > -1) questionType = 'matching';
4014
+
4015
+ // Get selected answer(s) based on question type
4016
+ var answerText = extractKnowledgeCheckAnswer(kcBlock, questionType);
4017
+
4018
+ // Get correct/incorrect from feedback
4019
+ var isCorrect = feedbackText === 'correct';
4020
+
4021
+ // Get lesson context
4022
+ var lessonInfo = getCachedLessonInfo();
4023
+
4024
+ log('Knowledge Check submitted:', {
4025
+ questionId: questionId,
4026
+ questionText: questionText.substring(0, 50) + '...',
4027
+ questionType: questionType,
4028
+ answer: answerText.substring(0, 50) + '...',
4029
+ correct: isCorrect
4030
+ });
4031
+
4032
+ // Send question answered statement using existing LRS method
4033
+ LRS.questionAnswered({
4034
+ questionId: questionId,
4035
+ questionGuid: blockId || generateUUID(),
4036
+ questionNumber: 1,
4037
+ questionText: questionText.substring(0, 500),
4038
+ questionType: questionType,
4039
+ answer: answerText.substring(0, 500),
4040
+ correct: isCorrect,
4041
+ result: isCorrect ? 'correct' : 'incorrect',
4042
+ assessmentName: 'Knowledge Check',
4043
+ lessonName: lessonInfo.name,
4044
+ sectionName: lessonInfo.sectionName
4045
+ });
4046
+ }
4047
+
4048
+ /**
4049
+ * Extract the selected answer text from a Knowledge Check block
4050
+ * based on the question type
4051
+ */
4052
+ function extractKnowledgeCheckAnswer(kcBlock, questionType) {
4053
+ var answerText = '';
4054
+
4055
+ if (questionType === 'multiple-choice') {
4056
+ // Find checked radio button
4057
+ var checkedInput = kcBlock.querySelector('.quiz-multiple-choice-option__input:checked');
4058
+ if (checkedInput) {
4059
+ var label = checkedInput.closest('.quiz-multiple-choice-option');
4060
+ var textEl = label ? label.querySelector('.quiz-multiple-choice-option__label .fr-view, .quiz-multiple-choice-option__label') : null;
4061
+ answerText = textEl ? textEl.textContent.trim() : '';
4062
+ }
4063
+ }
4064
+ else if (questionType === 'multiple-response') {
4065
+ // Find all checked checkboxes
4066
+ var checkedInputs = kcBlock.querySelectorAll('.quiz-multiple-response-option__input:checked');
4067
+ var answers = [];
4068
+ checkedInputs.forEach(function(input) {
4069
+ var label = input.closest('.quiz-multiple-response-option');
4070
+ var textEl = label ? label.querySelector('.quiz-multiple-response-option__text .fr-view, .quiz-multiple-response-option__text') : null;
4071
+ if (textEl) answers.push(textEl.textContent.trim());
4072
+ });
4073
+ answerText = answers.join('; ');
4074
+ }
4075
+ else if (questionType === 'fill-in-blank') {
4076
+ // Get text input value
4077
+ var textInput = kcBlock.querySelector('.quiz-fill__input');
4078
+ answerText = textInput ? textInput.value.trim() : '';
4079
+ }
4080
+ else if (questionType === 'matching') {
4081
+ // Extract matching pairs from the drop zones
4082
+ var dropZones = kcBlock.querySelectorAll('.matching-drop-zone');
4083
+ var pairs = [];
4084
+ dropZones.forEach(function(zone) {
4085
+ var prompt = zone.querySelector('.matching-prompt-content');
4086
+ var response = zone.querySelector('.matching-interaction-piece-content');
4087
+ if (prompt && response) {
4088
+ pairs.push(prompt.textContent.trim() + ' \u2192 ' + response.textContent.trim());
4089
+ }
4090
+ });
4091
+ answerText = pairs.length > 0 ? pairs.join('; ') : 'Matching submitted';
4092
+ }
4093
+
4094
+ return answerText;
4095
+ }
4096
+
3938
4097
  function setupInteractionInterceptors() {
3939
4098
  if (!TRACK_INTERACTIONS) return;
3940
4099