@patch-adams/core 1.5.3 → 1.5.4
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 +143 -0
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +143 -0
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +143 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +143 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -3822,7 +3822,11 @@ function generateLrsBridgeCode(options) {
|
|
|
3822
3822
|
if (!TRACK_QUIZZES) return;
|
|
3823
3823
|
|
|
3824
3824
|
// Intercept submit button clicks on Knowledge Check blocks
|
|
3825
|
+
// NOTE: If the SCORM tracker is active, it handles quiz tracking via
|
|
3826
|
+
// cmi.interactions \u2014 skip DOM scraping to avoid duplicate statements
|
|
3825
3827
|
document.addEventListener('click', function(e) {
|
|
3828
|
+
if (scormTrackerActive) return; // SCORM tracker handles this
|
|
3829
|
+
|
|
3826
3830
|
var submitBtn = e.target.closest('.quiz-card__button');
|
|
3827
3831
|
if (!submitBtn) return;
|
|
3828
3832
|
|
|
@@ -3978,6 +3982,142 @@ function generateLrsBridgeCode(options) {
|
|
|
3978
3982
|
return answerText;
|
|
3979
3983
|
}
|
|
3980
3984
|
|
|
3985
|
+
// ========================================================================
|
|
3986
|
+
// SCORM INTERACTION TRACKER
|
|
3987
|
+
// Intercepts cmi.interactions.N.* SetValue calls to capture quiz answers
|
|
3988
|
+
// directly from the SCORM data model \u2014 works regardless of Rise UI format
|
|
3989
|
+
// (Knowledge Check blocks, quiz lessons, etc.)
|
|
3990
|
+
// ========================================================================
|
|
3991
|
+
var scormInteractions = {}; // Pending interactions keyed by index N
|
|
3992
|
+
var scormInteractionsSent = {}; // Track which interactions were already sent
|
|
3993
|
+
var scormTrackerActive = false; // Set true when SCORM tracker wraps SetValue \u2014 KC handler defers
|
|
3994
|
+
|
|
3995
|
+
function setupScormInteractionTracker() {
|
|
3996
|
+
if (!TRACK_QUIZZES) return;
|
|
3997
|
+
if (!LRS.scormApi) {
|
|
3998
|
+
log('SCORM Interaction Tracker: No SCORM API found, skipping');
|
|
3999
|
+
return;
|
|
4000
|
+
}
|
|
4001
|
+
|
|
4002
|
+
var api = LRS.scormApi;
|
|
4003
|
+
var apiType = LRS.scormApiType;
|
|
4004
|
+
|
|
4005
|
+
// Determine which SetValue function to wrap
|
|
4006
|
+
var setValueFn = apiType === '2004' ? 'SetValue' : 'LMSSetValue';
|
|
4007
|
+
var originalSetValue = api[setValueFn];
|
|
4008
|
+
|
|
4009
|
+
if (typeof originalSetValue !== 'function') {
|
|
4010
|
+
log('SCORM Interaction Tracker: No ' + setValueFn + ' function found');
|
|
4011
|
+
return;
|
|
4012
|
+
}
|
|
4013
|
+
|
|
4014
|
+
// SCORM 1.2 uses cmi.interactions.N.*, SCORM 2004 uses cmi.interactions.N.*
|
|
4015
|
+
var interactionPattern = /^cmi\\.interactions\\.(\\d+)\\.(.+)$/;
|
|
4016
|
+
|
|
4017
|
+
api[setValueFn] = function(key, value) {
|
|
4018
|
+
// Always call the original first
|
|
4019
|
+
var result = originalSetValue.apply(api, arguments);
|
|
4020
|
+
|
|
4021
|
+
// Check if this is an interaction data element
|
|
4022
|
+
if (typeof key === 'string') {
|
|
4023
|
+
var match = key.match(interactionPattern);
|
|
4024
|
+
if (match) {
|
|
4025
|
+
var idx = match[1];
|
|
4026
|
+
var field = match[2];
|
|
4027
|
+
|
|
4028
|
+
// Initialize interaction tracking for this index
|
|
4029
|
+
if (!scormInteractions[idx]) {
|
|
4030
|
+
scormInteractions[idx] = {};
|
|
4031
|
+
}
|
|
4032
|
+
|
|
4033
|
+
// Store the field value
|
|
4034
|
+
scormInteractions[idx][field] = value;
|
|
4035
|
+
|
|
4036
|
+
log('SCORM Interaction [' + idx + '].' + field + ' = ' + (value ? value.substring(0, 80) : value));
|
|
4037
|
+
|
|
4038
|
+
// When 'result' is set, the interaction is complete \u2014 fire xAPI statement
|
|
4039
|
+
if (field === 'result' && !scormInteractionsSent[idx]) {
|
|
4040
|
+
scormInteractionsSent[idx] = true;
|
|
4041
|
+
var interaction = scormInteractions[idx];
|
|
4042
|
+
|
|
4043
|
+
// Map SCORM interaction type to readable type
|
|
4044
|
+
var typeMap = {
|
|
4045
|
+
'choice': 'multiple-choice',
|
|
4046
|
+
'true-false': 'true-false',
|
|
4047
|
+
'fill-in': 'fill-in-blank',
|
|
4048
|
+
'matching': 'matching',
|
|
4049
|
+
'performance': 'performance',
|
|
4050
|
+
'sequencing': 'sequencing',
|
|
4051
|
+
'likert': 'likert',
|
|
4052
|
+
'numeric': 'numeric'
|
|
4053
|
+
};
|
|
4054
|
+
|
|
4055
|
+
var scormType = interaction.type || 'unknown';
|
|
4056
|
+
var questionType = typeMap[scormType] || scormType;
|
|
4057
|
+
|
|
4058
|
+
// Determine correctness from SCORM result value
|
|
4059
|
+
// SCORM 1.2: 'correct', 'wrong', 'unanticipated', 'neutral'
|
|
4060
|
+
// SCORM 2004: 'correct', 'incorrect', 'unanticipated', 'neutral'
|
|
4061
|
+
var isCorrect = value === 'correct';
|
|
4062
|
+
|
|
4063
|
+
// Get student response \u2014 for 'choice' type, this might be indices like '1,3'
|
|
4064
|
+
var studentResponse = interaction.student_response || interaction['student_response'] || '';
|
|
4065
|
+
|
|
4066
|
+
// Get correct response pattern
|
|
4067
|
+
var correctResponse = '';
|
|
4068
|
+
// SCORM 1.2: correct_responses.0.pattern
|
|
4069
|
+
// Check stored fields for correct_responses
|
|
4070
|
+
Object.keys(interaction).forEach(function(k) {
|
|
4071
|
+
if (k.indexOf('correct_responses') > -1 && k.indexOf('pattern') > -1) {
|
|
4072
|
+
correctResponse = interaction[k];
|
|
4073
|
+
}
|
|
4074
|
+
});
|
|
4075
|
+
|
|
4076
|
+
// Get interaction ID (Rise sets this to a unique question identifier)
|
|
4077
|
+
var interactionId = interaction.id || ('interaction-' + idx);
|
|
4078
|
+
|
|
4079
|
+
// Get lesson context
|
|
4080
|
+
var lessonInfo = getCachedLessonInfo();
|
|
4081
|
+
|
|
4082
|
+
// Increment question counter
|
|
4083
|
+
kcQuestionCounter++;
|
|
4084
|
+
|
|
4085
|
+
log('SCORM Interaction complete [' + idx + ']:', {
|
|
4086
|
+
id: interactionId,
|
|
4087
|
+
type: questionType,
|
|
4088
|
+
response: studentResponse,
|
|
4089
|
+
correctResponse: correctResponse,
|
|
4090
|
+
result: value,
|
|
4091
|
+
correct: isCorrect,
|
|
4092
|
+
questionNumber: kcQuestionCounter
|
|
4093
|
+
});
|
|
4094
|
+
|
|
4095
|
+
// Send xAPI answered statement
|
|
4096
|
+
LRS.questionAnswered({
|
|
4097
|
+
questionId: interactionId,
|
|
4098
|
+
questionGuid: interactionId,
|
|
4099
|
+
questionNumber: kcQuestionCounter,
|
|
4100
|
+
questionText: 'Question ' + kcQuestionCounter + ' (' + interactionId + ')',
|
|
4101
|
+
questionType: questionType,
|
|
4102
|
+
answer: studentResponse,
|
|
4103
|
+
correctAnswer: correctResponse,
|
|
4104
|
+
correct: isCorrect,
|
|
4105
|
+
result: isCorrect ? 'correct' : 'incorrect',
|
|
4106
|
+
assessmentName: lessonInfo.name || 'Quiz',
|
|
4107
|
+
lessonName: lessonInfo.name,
|
|
4108
|
+
sectionName: lessonInfo.sectionName
|
|
4109
|
+
});
|
|
4110
|
+
}
|
|
4111
|
+
}
|
|
4112
|
+
}
|
|
4113
|
+
|
|
4114
|
+
return result;
|
|
4115
|
+
};
|
|
4116
|
+
|
|
4117
|
+
scormTrackerActive = true;
|
|
4118
|
+
log('SCORM Interaction Tracker: Wrapped ' + setValueFn + ' (apiType=' + apiType + ') \u2014 KC DOM handler will defer to SCORM tracker');
|
|
4119
|
+
}
|
|
4120
|
+
|
|
3981
4121
|
function setupInteractionInterceptors() {
|
|
3982
4122
|
if (!TRACK_INTERACTIONS) return;
|
|
3983
4123
|
|
|
@@ -4196,6 +4336,9 @@ function generateLrsBridgeCode(options) {
|
|
|
4196
4336
|
LRS.scormApiFound = true;
|
|
4197
4337
|
LRS.scormApiType = result.type;
|
|
4198
4338
|
|
|
4339
|
+
// Wrap SCORM SetValue to intercept cmi.interactions for quiz tracking
|
|
4340
|
+
setupScormInteractionTracker();
|
|
4341
|
+
|
|
4199
4342
|
// Read learner_id for diagnostics
|
|
4200
4343
|
var scormLearnerId = 'n/a', scormLearnerName = 'n/a';
|
|
4201
4344
|
try {
|