@playcademy/sandbox 0.5.1 → 0.5.2-beta.1
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.js +136 -26
- package/dist/server.js +136 -26
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -1078,7 +1078,7 @@ var package_default;
|
|
|
1078
1078
|
var init_package = __esm(() => {
|
|
1079
1079
|
package_default = {
|
|
1080
1080
|
name: "@playcademy/sandbox",
|
|
1081
|
-
version: "0.5.1",
|
|
1081
|
+
version: "0.5.2-beta.1",
|
|
1082
1082
|
description: "Local development server for Playcademy game development",
|
|
1083
1083
|
type: "module",
|
|
1084
1084
|
exports: {
|
|
@@ -31916,6 +31916,95 @@ class TimebackCacheManager {
|
|
|
31916
31916
|
this.enrollmentCache.cleanup();
|
|
31917
31917
|
}
|
|
31918
31918
|
}
|
|
31919
|
+
function computeMasteryPct(masteredUnits, masterableUnits) {
|
|
31920
|
+
if (masterableUnits <= 0) {
|
|
31921
|
+
return 0;
|
|
31922
|
+
}
|
|
31923
|
+
return masteredUnits / masterableUnits;
|
|
31924
|
+
}
|
|
31925
|
+
function clampMasteryPct(masteryPct) {
|
|
31926
|
+
return Math.min(1, Math.max(0, masteryPct));
|
|
31927
|
+
}
|
|
31928
|
+
function createMasteryWriteWarning({
|
|
31929
|
+
currentMasteredUnits,
|
|
31930
|
+
attemptedMasteredUnits,
|
|
31931
|
+
storedMasteredUnits,
|
|
31932
|
+
masterableUnits,
|
|
31933
|
+
effectiveDelta
|
|
31934
|
+
}) {
|
|
31935
|
+
let message;
|
|
31936
|
+
if (attemptedMasteredUnits < 0) {
|
|
31937
|
+
message = `Activity saved. Mastery was capped at the configured minimum: attempted ${attemptedMasteredUnits}/${masterableUnits}, applied ${effectiveDelta} units, stored ${storedMasteredUnits}/${masterableUnits}.`;
|
|
31938
|
+
} else if (storedMasteredUnits > masterableUnits) {
|
|
31939
|
+
message = `Activity saved. Mastery remains above the configured maximum: attempted ${attemptedMasteredUnits}/${masterableUnits}, applied ${effectiveDelta} units, stored ${storedMasteredUnits}/${masterableUnits}.`;
|
|
31940
|
+
} else {
|
|
31941
|
+
message = `Activity saved. Mastery was capped at the configured maximum: attempted ${attemptedMasteredUnits}/${masterableUnits}, applied ${effectiveDelta} units, stored ${storedMasteredUnits}/${masterableUnits}.`;
|
|
31942
|
+
}
|
|
31943
|
+
return {
|
|
31944
|
+
code: MASTERY_WRITE_CAPPED_WARNING_CODE,
|
|
31945
|
+
message,
|
|
31946
|
+
currentMasteredUnits,
|
|
31947
|
+
attemptedMasteredUnits,
|
|
31948
|
+
appliedMasteredUnits: effectiveDelta,
|
|
31949
|
+
storedMasteredUnits,
|
|
31950
|
+
masterableUnits
|
|
31951
|
+
};
|
|
31952
|
+
}
|
|
31953
|
+
function evaluateMasteryBounds({
|
|
31954
|
+
currentMasteredUnits,
|
|
31955
|
+
masterableUnits,
|
|
31956
|
+
masteredUnits = 0,
|
|
31957
|
+
masteredUnitsAbsolute
|
|
31958
|
+
}) {
|
|
31959
|
+
const attemptedMasteredUnits = masteredUnitsAbsolute === undefined ? currentMasteredUnits + masteredUnits : masteredUnitsAbsolute;
|
|
31960
|
+
const base = {
|
|
31961
|
+
currentMasteredUnits,
|
|
31962
|
+
attemptedMasteredUnits,
|
|
31963
|
+
masterableUnits
|
|
31964
|
+
};
|
|
31965
|
+
if (!Number.isFinite(currentMasteredUnits) || !Number.isFinite(masterableUnits) || !Number.isFinite(masteredUnits) || masteredUnitsAbsolute !== undefined && !Number.isFinite(masteredUnitsAbsolute) || !Number.isFinite(attemptedMasteredUnits)) {
|
|
31966
|
+
throw new Error("Mastery bounds evaluation requires finite numeric values.");
|
|
31967
|
+
}
|
|
31968
|
+
if (attemptedMasteredUnits < 0) {
|
|
31969
|
+
const storedMasteredUnits2 = 0;
|
|
31970
|
+
const effectiveDelta2 = storedMasteredUnits2 - currentMasteredUnits;
|
|
31971
|
+
return {
|
|
31972
|
+
...base,
|
|
31973
|
+
storedMasteredUnits: storedMasteredUnits2,
|
|
31974
|
+
effectiveDelta: effectiveDelta2,
|
|
31975
|
+
writeWarning: createMasteryWriteWarning({
|
|
31976
|
+
currentMasteredUnits,
|
|
31977
|
+
attemptedMasteredUnits,
|
|
31978
|
+
storedMasteredUnits: storedMasteredUnits2,
|
|
31979
|
+
masterableUnits,
|
|
31980
|
+
effectiveDelta: effectiveDelta2
|
|
31981
|
+
})
|
|
31982
|
+
};
|
|
31983
|
+
}
|
|
31984
|
+
if (masterableUnits > 0 && attemptedMasteredUnits > masterableUnits) {
|
|
31985
|
+
const storedMasteredUnits2 = currentMasteredUnits > masterableUnits ? Math.min(currentMasteredUnits, attemptedMasteredUnits) : masterableUnits;
|
|
31986
|
+
const effectiveDelta2 = storedMasteredUnits2 - currentMasteredUnits;
|
|
31987
|
+
return {
|
|
31988
|
+
...base,
|
|
31989
|
+
storedMasteredUnits: storedMasteredUnits2,
|
|
31990
|
+
effectiveDelta: effectiveDelta2,
|
|
31991
|
+
writeWarning: createMasteryWriteWarning({
|
|
31992
|
+
currentMasteredUnits,
|
|
31993
|
+
attemptedMasteredUnits,
|
|
31994
|
+
storedMasteredUnits: storedMasteredUnits2,
|
|
31995
|
+
masterableUnits,
|
|
31996
|
+
effectiveDelta: effectiveDelta2
|
|
31997
|
+
})
|
|
31998
|
+
};
|
|
31999
|
+
}
|
|
32000
|
+
const storedMasteredUnits = attemptedMasteredUnits;
|
|
32001
|
+
const effectiveDelta = storedMasteredUnits - currentMasteredUnits;
|
|
32002
|
+
return {
|
|
32003
|
+
...base,
|
|
32004
|
+
storedMasteredUnits,
|
|
32005
|
+
effectiveDelta
|
|
32006
|
+
};
|
|
32007
|
+
}
|
|
31919
32008
|
|
|
31920
32009
|
class MasteryTracker {
|
|
31921
32010
|
cacheManager;
|
|
@@ -31938,7 +32027,8 @@ class MasteryTracker {
|
|
|
31938
32027
|
courseId,
|
|
31939
32028
|
resourceId,
|
|
31940
32029
|
additionalMasteredUnits: hasAbsolute ? 0 : masteredUnits,
|
|
31941
|
-
absoluteMasteredUnits: hasAbsolute ? masteredUnitsAbsolute : undefined
|
|
32030
|
+
absoluteMasteredUnits: hasAbsolute ? masteredUnitsAbsolute : undefined,
|
|
32031
|
+
validateBounds: true
|
|
31942
32032
|
});
|
|
31943
32033
|
if (!status) {
|
|
31944
32034
|
return;
|
|
@@ -31948,13 +32038,15 @@ class MasteryTracker {
|
|
|
31948
32038
|
pctCompleteApp: status.pctCompleteApp,
|
|
31949
32039
|
masteryAchieved: !wasComplete && status.isComplete,
|
|
31950
32040
|
masteryRevoked: wasComplete && !status.isComplete,
|
|
31951
|
-
effectiveDelta: status.effectiveDelta
|
|
32041
|
+
effectiveDelta: status.effectiveDelta,
|
|
32042
|
+
...status.writeWarning ? { writeWarning: status.writeWarning } : {}
|
|
31952
32043
|
};
|
|
31953
32044
|
}
|
|
31954
32045
|
async getStatus(input) {
|
|
31955
32046
|
const status = await this.calculateStatus({
|
|
31956
32047
|
...input,
|
|
31957
|
-
additionalMasteredUnits: 0
|
|
32048
|
+
additionalMasteredUnits: 0,
|
|
32049
|
+
validateBounds: false
|
|
31958
32050
|
});
|
|
31959
32051
|
if (!status) {
|
|
31960
32052
|
return;
|
|
@@ -31971,7 +32063,8 @@ class MasteryTracker {
|
|
|
31971
32063
|
courseId,
|
|
31972
32064
|
resourceId,
|
|
31973
32065
|
additionalMasteredUnits,
|
|
31974
|
-
absoluteMasteredUnits
|
|
32066
|
+
absoluteMasteredUnits,
|
|
32067
|
+
validateBounds
|
|
31975
32068
|
}) {
|
|
31976
32069
|
const masterableUnits = await this.resolveMasterableUnits(resourceId);
|
|
31977
32070
|
if (!masterableUnits || masterableUnits <= 0) {
|
|
@@ -31984,24 +32077,38 @@ class MasteryTracker {
|
|
|
31984
32077
|
return;
|
|
31985
32078
|
}
|
|
31986
32079
|
const historicalMasteredUnits = this.sumAnalyticsMetric(facts, "masteredUnits");
|
|
31987
|
-
|
|
31988
|
-
|
|
31989
|
-
|
|
31990
|
-
|
|
31991
|
-
|
|
31992
|
-
}
|
|
31993
|
-
|
|
31994
|
-
|
|
32080
|
+
const bounds = validateBounds ? evaluateMasteryBounds({
|
|
32081
|
+
currentMasteredUnits: historicalMasteredUnits,
|
|
32082
|
+
masterableUnits,
|
|
32083
|
+
masteredUnits: additionalMasteredUnits,
|
|
32084
|
+
masteredUnitsAbsolute: absoluteMasteredUnits
|
|
32085
|
+
}) : {
|
|
32086
|
+
currentMasteredUnits: historicalMasteredUnits,
|
|
32087
|
+
attemptedMasteredUnits: historicalMasteredUnits,
|
|
32088
|
+
storedMasteredUnits: historicalMasteredUnits,
|
|
32089
|
+
masterableUnits,
|
|
32090
|
+
effectiveDelta: 0
|
|
32091
|
+
};
|
|
32092
|
+
if (validateBounds && bounds.writeWarning) {
|
|
32093
|
+
addEvent("timeback.mastery_write_capped", {
|
|
32094
|
+
"app.timeback.current_mastered_units": bounds.currentMasteredUnits,
|
|
32095
|
+
"app.timeback.attempted_mastered_units": bounds.attemptedMasteredUnits,
|
|
32096
|
+
"app.timeback.applied_mastered_units": bounds.effectiveDelta,
|
|
32097
|
+
"app.timeback.stored_mastered_units": bounds.storedMasteredUnits,
|
|
32098
|
+
"app.timeback.masterable_units": bounds.masterableUnits
|
|
32099
|
+
});
|
|
31995
32100
|
}
|
|
31996
|
-
const
|
|
31997
|
-
const
|
|
32101
|
+
const masteredUnits = bounds.storedMasteredUnits;
|
|
32102
|
+
const masteryPct = computeMasteryPct(masteredUnits, masterableUnits);
|
|
32103
|
+
const pctCompleteApp = Math.round(clampMasteryPct(masteryPct) * 100);
|
|
31998
32104
|
return {
|
|
31999
|
-
masteredUnits
|
|
32105
|
+
masteredUnits,
|
|
32000
32106
|
masterableUnits,
|
|
32001
32107
|
pctCompleteApp,
|
|
32002
|
-
isComplete:
|
|
32108
|
+
isComplete: masteredUnits >= masterableUnits,
|
|
32003
32109
|
historicalMasteredUnits,
|
|
32004
|
-
effectiveDelta
|
|
32110
|
+
effectiveDelta: bounds.effectiveDelta,
|
|
32111
|
+
...bounds.writeWarning ? { writeWarning: bounds.writeWarning } : {}
|
|
32005
32112
|
};
|
|
32006
32113
|
}
|
|
32007
32114
|
async createCompletionEntry(studentId, courseId, classId, appName) {
|
|
@@ -32200,8 +32307,6 @@ class ProgressRecorder {
|
|
|
32200
32307
|
xpEarned = 0,
|
|
32201
32308
|
attemptNumber
|
|
32202
32309
|
} = progressData;
|
|
32203
|
-
const actualLineItemId = await this.resolveAssessmentLineItem(activityId, activityName, progressData.classId, ids);
|
|
32204
|
-
const currentAttemptNumber = await this.resolveAttemptNumber(attemptNumber, score, studentId, actualLineItemId);
|
|
32205
32310
|
let extensions = progressData.extensions;
|
|
32206
32311
|
const masteryProgress = await this.masteryTracker.checkProgress({
|
|
32207
32312
|
studentId,
|
|
@@ -32215,6 +32320,7 @@ class ProgressRecorder {
|
|
|
32215
32320
|
let masteryAchieved = false;
|
|
32216
32321
|
let scoreStatus = SCORE_STATUS.fullyGraded;
|
|
32217
32322
|
const inProgress = "false";
|
|
32323
|
+
const warnings = masteryProgress?.writeWarning ? [masteryProgress.writeWarning] : undefined;
|
|
32218
32324
|
if (masteryProgress) {
|
|
32219
32325
|
masteryAchieved = masteryProgress.masteryAchieved;
|
|
32220
32326
|
pctCompleteApp = masteryProgress.pctCompleteApp;
|
|
@@ -32226,6 +32332,8 @@ class ProgressRecorder {
|
|
|
32226
32332
|
scoreStatus = SCORE_STATUS.fullyGraded;
|
|
32227
32333
|
}
|
|
32228
32334
|
}
|
|
32335
|
+
const actualLineItemId = await this.resolveAssessmentLineItem(activityId, activityName, progressData.classId, ids);
|
|
32336
|
+
const currentAttemptNumber = await this.resolveAttemptNumber(attemptNumber, score, studentId, actualLineItemId);
|
|
32229
32337
|
if (score !== undefined) {
|
|
32230
32338
|
await this.createGradebookEntry({
|
|
32231
32339
|
lineItemId: actualLineItemId,
|
|
@@ -32284,7 +32392,8 @@ class ProgressRecorder {
|
|
|
32284
32392
|
masteredUnitsApplied: effectiveMasteredUnits,
|
|
32285
32393
|
pctCompleteApp,
|
|
32286
32394
|
scoreStatus,
|
|
32287
|
-
inProgress
|
|
32395
|
+
inProgress,
|
|
32396
|
+
...warnings ? { warnings } : {}
|
|
32288
32397
|
};
|
|
32289
32398
|
}
|
|
32290
32399
|
async resolveContext(courseId, studentIdentifier, progressData) {
|
|
@@ -32970,7 +33079,7 @@ var __defProp2, __export2 = (target, all) => {
|
|
|
32970
33079
|
configurable: true,
|
|
32971
33080
|
set: (newValue) => all[name3] = () => newValue
|
|
32972
33081
|
});
|
|
32973
|
-
}, __esm2 = (fn, res) => () => (fn && (res = fn(fn = 0)), res), TIMEBACK_API_URLS, QTI_API_URL = "https://qti.alpha-1edtech.ai/api", TIMEBACK_AUTH_URLS, CALIPER_API_URLS, ONEROSTER_ENDPOINTS, QTI_ENDPOINTS, CALIPER_ENDPOINTS, CALIPER_CONSTANTS, TIMEBACK_EVENT_TYPES, TIMEBACK_ACTIONS, TIMEBACK_TYPES, ACTIVITY_METRIC_TYPES, TIME_METRIC_TYPES, TIMEBACK_SUBJECTS, TIMEBACK_GRADE_LEVELS, TIMEBACK_GRADE_LEVEL_LABELS, CALIPER_SUBJECTS, ONEROSTER_STATUS, SCORE_STATUS, ENV_VARS, HTTP_DEFAULTS, AUTH_DEFAULTS, CACHE_DEFAULTS, CONFIG_DEFAULTS, PLAYCADEMY_DEFAULTS, RESOURCE_DEFAULTS, HTTP_STATUS, ERROR_NAMES, init_constants4, exports_verify, init_verify, TimebackError, TimebackApiError, TimebackAuthenticationError, StudentNotFoundError, ConfigurationError, ResourceNotFoundError, SUBJECT_VALUES, GRADE_VALUES, TimebackAuthError, UUID_PATTERN, storage, EmailSchema, StudentSourcedIdSchema, StudentIdentifierSchema;
|
|
33082
|
+
}, __esm2 = (fn, res) => () => (fn && (res = fn(fn = 0)), res), TIMEBACK_API_URLS, QTI_API_URL = "https://qti.alpha-1edtech.ai/api", TIMEBACK_AUTH_URLS, CALIPER_API_URLS, ONEROSTER_ENDPOINTS, QTI_ENDPOINTS, CALIPER_ENDPOINTS, CALIPER_CONSTANTS, TIMEBACK_EVENT_TYPES, TIMEBACK_ACTIONS, TIMEBACK_TYPES, ACTIVITY_METRIC_TYPES, TIME_METRIC_TYPES, TIMEBACK_SUBJECTS, TIMEBACK_GRADE_LEVELS, TIMEBACK_GRADE_LEVEL_LABELS, CALIPER_SUBJECTS, ONEROSTER_STATUS, SCORE_STATUS, ENV_VARS, HTTP_DEFAULTS, AUTH_DEFAULTS, CACHE_DEFAULTS, CONFIG_DEFAULTS, PLAYCADEMY_DEFAULTS, RESOURCE_DEFAULTS, HTTP_STATUS, ERROR_NAMES, init_constants4, exports_verify, init_verify, TimebackError, TimebackApiError, TimebackAuthenticationError, StudentNotFoundError, ConfigurationError, ResourceNotFoundError, SUBJECT_VALUES, GRADE_VALUES, TimebackAuthError, UUID_PATTERN, storage, MASTERY_WRITE_CAPPED_WARNING_CODE = "MASTERY_WRITE_CAPPED", EmailSchema, StudentSourcedIdSchema, StudentIdentifierSchema;
|
|
32974
33083
|
var init_dist2 = __esm(() => {
|
|
32975
33084
|
init_src();
|
|
32976
33085
|
init_src();
|
|
@@ -34503,8 +34612,8 @@ var init_schemas4 = __esm(() => {
|
|
|
34503
34612
|
inactiveSeconds: exports_external.number().nonnegative().optional()
|
|
34504
34613
|
}).optional(),
|
|
34505
34614
|
xpEarned: exports_external.number(),
|
|
34506
|
-
masteredUnits: exports_external.number().optional(),
|
|
34507
|
-
masteredUnitsAbsolute: exports_external.number().
|
|
34615
|
+
masteredUnits: exports_external.number().finite().optional(),
|
|
34616
|
+
masteredUnitsAbsolute: exports_external.number().finite().int().optional(),
|
|
34508
34617
|
extensions: exports_external.record(exports_external.string(), exports_external.unknown()).optional()
|
|
34509
34618
|
}).refine((data) => !(data.masteredUnits !== undefined && data.masteredUnitsAbsolute !== undefined), {
|
|
34510
34619
|
message: "Cannot provide both masteredUnits and masteredUnitsAbsolute",
|
|
@@ -38605,7 +38714,8 @@ var init_timeback_service = __esm(() => {
|
|
|
38605
38714
|
masteredUnits: result.masteredUnitsApplied,
|
|
38606
38715
|
pctCompleteApp: result.pctCompleteApp,
|
|
38607
38716
|
scoreStatus: result.scoreStatus,
|
|
38608
|
-
inProgress: result.inProgress
|
|
38717
|
+
inProgress: result.inProgress,
|
|
38718
|
+
...result.warnings ? { warnings: result.warnings } : {}
|
|
38609
38719
|
};
|
|
38610
38720
|
}
|
|
38611
38721
|
async resolveActiveGameCourse({
|
|
@@ -98356,7 +98466,7 @@ var init_timeback7 = __esm(() => {
|
|
|
98356
98466
|
const seed3 = hashCode(`${e.grade}-${e.subject}`);
|
|
98357
98467
|
const masterableUnits = 5 + seed3 % 16;
|
|
98358
98468
|
const masteredUnits = seed3 % (masterableUnits + 1);
|
|
98359
|
-
const pctComplete = masterableUnits > 0 ? Math.round(masteredUnits / masterableUnits *
|
|
98469
|
+
const pctComplete = masterableUnits > 0 ? Math.round(masteredUnits / masterableUnits * 100) : 0;
|
|
98360
98470
|
return {
|
|
98361
98471
|
grade: e.grade,
|
|
98362
98472
|
subject: e.subject,
|
package/dist/server.js
CHANGED
|
@@ -1077,7 +1077,7 @@ var package_default;
|
|
|
1077
1077
|
var init_package = __esm(() => {
|
|
1078
1078
|
package_default = {
|
|
1079
1079
|
name: "@playcademy/sandbox",
|
|
1080
|
-
version: "0.5.1",
|
|
1080
|
+
version: "0.5.2-beta.1",
|
|
1081
1081
|
description: "Local development server for Playcademy game development",
|
|
1082
1082
|
type: "module",
|
|
1083
1083
|
exports: {
|
|
@@ -31915,6 +31915,95 @@ class TimebackCacheManager {
|
|
|
31915
31915
|
this.enrollmentCache.cleanup();
|
|
31916
31916
|
}
|
|
31917
31917
|
}
|
|
31918
|
+
function computeMasteryPct(masteredUnits, masterableUnits) {
|
|
31919
|
+
if (masterableUnits <= 0) {
|
|
31920
|
+
return 0;
|
|
31921
|
+
}
|
|
31922
|
+
return masteredUnits / masterableUnits;
|
|
31923
|
+
}
|
|
31924
|
+
function clampMasteryPct(masteryPct) {
|
|
31925
|
+
return Math.min(1, Math.max(0, masteryPct));
|
|
31926
|
+
}
|
|
31927
|
+
function createMasteryWriteWarning({
|
|
31928
|
+
currentMasteredUnits,
|
|
31929
|
+
attemptedMasteredUnits,
|
|
31930
|
+
storedMasteredUnits,
|
|
31931
|
+
masterableUnits,
|
|
31932
|
+
effectiveDelta
|
|
31933
|
+
}) {
|
|
31934
|
+
let message;
|
|
31935
|
+
if (attemptedMasteredUnits < 0) {
|
|
31936
|
+
message = `Activity saved. Mastery was capped at the configured minimum: attempted ${attemptedMasteredUnits}/${masterableUnits}, applied ${effectiveDelta} units, stored ${storedMasteredUnits}/${masterableUnits}.`;
|
|
31937
|
+
} else if (storedMasteredUnits > masterableUnits) {
|
|
31938
|
+
message = `Activity saved. Mastery remains above the configured maximum: attempted ${attemptedMasteredUnits}/${masterableUnits}, applied ${effectiveDelta} units, stored ${storedMasteredUnits}/${masterableUnits}.`;
|
|
31939
|
+
} else {
|
|
31940
|
+
message = `Activity saved. Mastery was capped at the configured maximum: attempted ${attemptedMasteredUnits}/${masterableUnits}, applied ${effectiveDelta} units, stored ${storedMasteredUnits}/${masterableUnits}.`;
|
|
31941
|
+
}
|
|
31942
|
+
return {
|
|
31943
|
+
code: MASTERY_WRITE_CAPPED_WARNING_CODE,
|
|
31944
|
+
message,
|
|
31945
|
+
currentMasteredUnits,
|
|
31946
|
+
attemptedMasteredUnits,
|
|
31947
|
+
appliedMasteredUnits: effectiveDelta,
|
|
31948
|
+
storedMasteredUnits,
|
|
31949
|
+
masterableUnits
|
|
31950
|
+
};
|
|
31951
|
+
}
|
|
31952
|
+
function evaluateMasteryBounds({
|
|
31953
|
+
currentMasteredUnits,
|
|
31954
|
+
masterableUnits,
|
|
31955
|
+
masteredUnits = 0,
|
|
31956
|
+
masteredUnitsAbsolute
|
|
31957
|
+
}) {
|
|
31958
|
+
const attemptedMasteredUnits = masteredUnitsAbsolute === undefined ? currentMasteredUnits + masteredUnits : masteredUnitsAbsolute;
|
|
31959
|
+
const base = {
|
|
31960
|
+
currentMasteredUnits,
|
|
31961
|
+
attemptedMasteredUnits,
|
|
31962
|
+
masterableUnits
|
|
31963
|
+
};
|
|
31964
|
+
if (!Number.isFinite(currentMasteredUnits) || !Number.isFinite(masterableUnits) || !Number.isFinite(masteredUnits) || masteredUnitsAbsolute !== undefined && !Number.isFinite(masteredUnitsAbsolute) || !Number.isFinite(attemptedMasteredUnits)) {
|
|
31965
|
+
throw new Error("Mastery bounds evaluation requires finite numeric values.");
|
|
31966
|
+
}
|
|
31967
|
+
if (attemptedMasteredUnits < 0) {
|
|
31968
|
+
const storedMasteredUnits2 = 0;
|
|
31969
|
+
const effectiveDelta2 = storedMasteredUnits2 - currentMasteredUnits;
|
|
31970
|
+
return {
|
|
31971
|
+
...base,
|
|
31972
|
+
storedMasteredUnits: storedMasteredUnits2,
|
|
31973
|
+
effectiveDelta: effectiveDelta2,
|
|
31974
|
+
writeWarning: createMasteryWriteWarning({
|
|
31975
|
+
currentMasteredUnits,
|
|
31976
|
+
attemptedMasteredUnits,
|
|
31977
|
+
storedMasteredUnits: storedMasteredUnits2,
|
|
31978
|
+
masterableUnits,
|
|
31979
|
+
effectiveDelta: effectiveDelta2
|
|
31980
|
+
})
|
|
31981
|
+
};
|
|
31982
|
+
}
|
|
31983
|
+
if (masterableUnits > 0 && attemptedMasteredUnits > masterableUnits) {
|
|
31984
|
+
const storedMasteredUnits2 = currentMasteredUnits > masterableUnits ? Math.min(currentMasteredUnits, attemptedMasteredUnits) : masterableUnits;
|
|
31985
|
+
const effectiveDelta2 = storedMasteredUnits2 - currentMasteredUnits;
|
|
31986
|
+
return {
|
|
31987
|
+
...base,
|
|
31988
|
+
storedMasteredUnits: storedMasteredUnits2,
|
|
31989
|
+
effectiveDelta: effectiveDelta2,
|
|
31990
|
+
writeWarning: createMasteryWriteWarning({
|
|
31991
|
+
currentMasteredUnits,
|
|
31992
|
+
attemptedMasteredUnits,
|
|
31993
|
+
storedMasteredUnits: storedMasteredUnits2,
|
|
31994
|
+
masterableUnits,
|
|
31995
|
+
effectiveDelta: effectiveDelta2
|
|
31996
|
+
})
|
|
31997
|
+
};
|
|
31998
|
+
}
|
|
31999
|
+
const storedMasteredUnits = attemptedMasteredUnits;
|
|
32000
|
+
const effectiveDelta = storedMasteredUnits - currentMasteredUnits;
|
|
32001
|
+
return {
|
|
32002
|
+
...base,
|
|
32003
|
+
storedMasteredUnits,
|
|
32004
|
+
effectiveDelta
|
|
32005
|
+
};
|
|
32006
|
+
}
|
|
31918
32007
|
|
|
31919
32008
|
class MasteryTracker {
|
|
31920
32009
|
cacheManager;
|
|
@@ -31937,7 +32026,8 @@ class MasteryTracker {
|
|
|
31937
32026
|
courseId,
|
|
31938
32027
|
resourceId,
|
|
31939
32028
|
additionalMasteredUnits: hasAbsolute ? 0 : masteredUnits,
|
|
31940
|
-
absoluteMasteredUnits: hasAbsolute ? masteredUnitsAbsolute : undefined
|
|
32029
|
+
absoluteMasteredUnits: hasAbsolute ? masteredUnitsAbsolute : undefined,
|
|
32030
|
+
validateBounds: true
|
|
31941
32031
|
});
|
|
31942
32032
|
if (!status) {
|
|
31943
32033
|
return;
|
|
@@ -31947,13 +32037,15 @@ class MasteryTracker {
|
|
|
31947
32037
|
pctCompleteApp: status.pctCompleteApp,
|
|
31948
32038
|
masteryAchieved: !wasComplete && status.isComplete,
|
|
31949
32039
|
masteryRevoked: wasComplete && !status.isComplete,
|
|
31950
|
-
effectiveDelta: status.effectiveDelta
|
|
32040
|
+
effectiveDelta: status.effectiveDelta,
|
|
32041
|
+
...status.writeWarning ? { writeWarning: status.writeWarning } : {}
|
|
31951
32042
|
};
|
|
31952
32043
|
}
|
|
31953
32044
|
async getStatus(input) {
|
|
31954
32045
|
const status = await this.calculateStatus({
|
|
31955
32046
|
...input,
|
|
31956
|
-
additionalMasteredUnits: 0
|
|
32047
|
+
additionalMasteredUnits: 0,
|
|
32048
|
+
validateBounds: false
|
|
31957
32049
|
});
|
|
31958
32050
|
if (!status) {
|
|
31959
32051
|
return;
|
|
@@ -31970,7 +32062,8 @@ class MasteryTracker {
|
|
|
31970
32062
|
courseId,
|
|
31971
32063
|
resourceId,
|
|
31972
32064
|
additionalMasteredUnits,
|
|
31973
|
-
absoluteMasteredUnits
|
|
32065
|
+
absoluteMasteredUnits,
|
|
32066
|
+
validateBounds
|
|
31974
32067
|
}) {
|
|
31975
32068
|
const masterableUnits = await this.resolveMasterableUnits(resourceId);
|
|
31976
32069
|
if (!masterableUnits || masterableUnits <= 0) {
|
|
@@ -31983,24 +32076,38 @@ class MasteryTracker {
|
|
|
31983
32076
|
return;
|
|
31984
32077
|
}
|
|
31985
32078
|
const historicalMasteredUnits = this.sumAnalyticsMetric(facts, "masteredUnits");
|
|
31986
|
-
|
|
31987
|
-
|
|
31988
|
-
|
|
31989
|
-
|
|
31990
|
-
|
|
31991
|
-
}
|
|
31992
|
-
|
|
31993
|
-
|
|
32079
|
+
const bounds = validateBounds ? evaluateMasteryBounds({
|
|
32080
|
+
currentMasteredUnits: historicalMasteredUnits,
|
|
32081
|
+
masterableUnits,
|
|
32082
|
+
masteredUnits: additionalMasteredUnits,
|
|
32083
|
+
masteredUnitsAbsolute: absoluteMasteredUnits
|
|
32084
|
+
}) : {
|
|
32085
|
+
currentMasteredUnits: historicalMasteredUnits,
|
|
32086
|
+
attemptedMasteredUnits: historicalMasteredUnits,
|
|
32087
|
+
storedMasteredUnits: historicalMasteredUnits,
|
|
32088
|
+
masterableUnits,
|
|
32089
|
+
effectiveDelta: 0
|
|
32090
|
+
};
|
|
32091
|
+
if (validateBounds && bounds.writeWarning) {
|
|
32092
|
+
addEvent("timeback.mastery_write_capped", {
|
|
32093
|
+
"app.timeback.current_mastered_units": bounds.currentMasteredUnits,
|
|
32094
|
+
"app.timeback.attempted_mastered_units": bounds.attemptedMasteredUnits,
|
|
32095
|
+
"app.timeback.applied_mastered_units": bounds.effectiveDelta,
|
|
32096
|
+
"app.timeback.stored_mastered_units": bounds.storedMasteredUnits,
|
|
32097
|
+
"app.timeback.masterable_units": bounds.masterableUnits
|
|
32098
|
+
});
|
|
31994
32099
|
}
|
|
31995
|
-
const
|
|
31996
|
-
const
|
|
32100
|
+
const masteredUnits = bounds.storedMasteredUnits;
|
|
32101
|
+
const masteryPct = computeMasteryPct(masteredUnits, masterableUnits);
|
|
32102
|
+
const pctCompleteApp = Math.round(clampMasteryPct(masteryPct) * 100);
|
|
31997
32103
|
return {
|
|
31998
|
-
masteredUnits
|
|
32104
|
+
masteredUnits,
|
|
31999
32105
|
masterableUnits,
|
|
32000
32106
|
pctCompleteApp,
|
|
32001
|
-
isComplete:
|
|
32107
|
+
isComplete: masteredUnits >= masterableUnits,
|
|
32002
32108
|
historicalMasteredUnits,
|
|
32003
|
-
effectiveDelta
|
|
32109
|
+
effectiveDelta: bounds.effectiveDelta,
|
|
32110
|
+
...bounds.writeWarning ? { writeWarning: bounds.writeWarning } : {}
|
|
32004
32111
|
};
|
|
32005
32112
|
}
|
|
32006
32113
|
async createCompletionEntry(studentId, courseId, classId, appName) {
|
|
@@ -32199,8 +32306,6 @@ class ProgressRecorder {
|
|
|
32199
32306
|
xpEarned = 0,
|
|
32200
32307
|
attemptNumber
|
|
32201
32308
|
} = progressData;
|
|
32202
|
-
const actualLineItemId = await this.resolveAssessmentLineItem(activityId, activityName, progressData.classId, ids);
|
|
32203
|
-
const currentAttemptNumber = await this.resolveAttemptNumber(attemptNumber, score, studentId, actualLineItemId);
|
|
32204
32309
|
let extensions = progressData.extensions;
|
|
32205
32310
|
const masteryProgress = await this.masteryTracker.checkProgress({
|
|
32206
32311
|
studentId,
|
|
@@ -32214,6 +32319,7 @@ class ProgressRecorder {
|
|
|
32214
32319
|
let masteryAchieved = false;
|
|
32215
32320
|
let scoreStatus = SCORE_STATUS.fullyGraded;
|
|
32216
32321
|
const inProgress = "false";
|
|
32322
|
+
const warnings = masteryProgress?.writeWarning ? [masteryProgress.writeWarning] : undefined;
|
|
32217
32323
|
if (masteryProgress) {
|
|
32218
32324
|
masteryAchieved = masteryProgress.masteryAchieved;
|
|
32219
32325
|
pctCompleteApp = masteryProgress.pctCompleteApp;
|
|
@@ -32225,6 +32331,8 @@ class ProgressRecorder {
|
|
|
32225
32331
|
scoreStatus = SCORE_STATUS.fullyGraded;
|
|
32226
32332
|
}
|
|
32227
32333
|
}
|
|
32334
|
+
const actualLineItemId = await this.resolveAssessmentLineItem(activityId, activityName, progressData.classId, ids);
|
|
32335
|
+
const currentAttemptNumber = await this.resolveAttemptNumber(attemptNumber, score, studentId, actualLineItemId);
|
|
32228
32336
|
if (score !== undefined) {
|
|
32229
32337
|
await this.createGradebookEntry({
|
|
32230
32338
|
lineItemId: actualLineItemId,
|
|
@@ -32283,7 +32391,8 @@ class ProgressRecorder {
|
|
|
32283
32391
|
masteredUnitsApplied: effectiveMasteredUnits,
|
|
32284
32392
|
pctCompleteApp,
|
|
32285
32393
|
scoreStatus,
|
|
32286
|
-
inProgress
|
|
32394
|
+
inProgress,
|
|
32395
|
+
...warnings ? { warnings } : {}
|
|
32287
32396
|
};
|
|
32288
32397
|
}
|
|
32289
32398
|
async resolveContext(courseId, studentIdentifier, progressData) {
|
|
@@ -32969,7 +33078,7 @@ var __defProp2, __export2 = (target, all) => {
|
|
|
32969
33078
|
configurable: true,
|
|
32970
33079
|
set: (newValue) => all[name3] = () => newValue
|
|
32971
33080
|
});
|
|
32972
|
-
}, __esm2 = (fn, res) => () => (fn && (res = fn(fn = 0)), res), TIMEBACK_API_URLS, QTI_API_URL = "https://qti.alpha-1edtech.ai/api", TIMEBACK_AUTH_URLS, CALIPER_API_URLS, ONEROSTER_ENDPOINTS, QTI_ENDPOINTS, CALIPER_ENDPOINTS, CALIPER_CONSTANTS, TIMEBACK_EVENT_TYPES, TIMEBACK_ACTIONS, TIMEBACK_TYPES, ACTIVITY_METRIC_TYPES, TIME_METRIC_TYPES, TIMEBACK_SUBJECTS, TIMEBACK_GRADE_LEVELS, TIMEBACK_GRADE_LEVEL_LABELS, CALIPER_SUBJECTS, ONEROSTER_STATUS, SCORE_STATUS, ENV_VARS, HTTP_DEFAULTS, AUTH_DEFAULTS, CACHE_DEFAULTS, CONFIG_DEFAULTS, PLAYCADEMY_DEFAULTS, RESOURCE_DEFAULTS, HTTP_STATUS, ERROR_NAMES, init_constants4, exports_verify, init_verify, TimebackError, TimebackApiError, TimebackAuthenticationError, StudentNotFoundError, ConfigurationError, ResourceNotFoundError, SUBJECT_VALUES, GRADE_VALUES, TimebackAuthError, UUID_PATTERN, storage, EmailSchema, StudentSourcedIdSchema, StudentIdentifierSchema;
|
|
33081
|
+
}, __esm2 = (fn, res) => () => (fn && (res = fn(fn = 0)), res), TIMEBACK_API_URLS, QTI_API_URL = "https://qti.alpha-1edtech.ai/api", TIMEBACK_AUTH_URLS, CALIPER_API_URLS, ONEROSTER_ENDPOINTS, QTI_ENDPOINTS, CALIPER_ENDPOINTS, CALIPER_CONSTANTS, TIMEBACK_EVENT_TYPES, TIMEBACK_ACTIONS, TIMEBACK_TYPES, ACTIVITY_METRIC_TYPES, TIME_METRIC_TYPES, TIMEBACK_SUBJECTS, TIMEBACK_GRADE_LEVELS, TIMEBACK_GRADE_LEVEL_LABELS, CALIPER_SUBJECTS, ONEROSTER_STATUS, SCORE_STATUS, ENV_VARS, HTTP_DEFAULTS, AUTH_DEFAULTS, CACHE_DEFAULTS, CONFIG_DEFAULTS, PLAYCADEMY_DEFAULTS, RESOURCE_DEFAULTS, HTTP_STATUS, ERROR_NAMES, init_constants4, exports_verify, init_verify, TimebackError, TimebackApiError, TimebackAuthenticationError, StudentNotFoundError, ConfigurationError, ResourceNotFoundError, SUBJECT_VALUES, GRADE_VALUES, TimebackAuthError, UUID_PATTERN, storage, MASTERY_WRITE_CAPPED_WARNING_CODE = "MASTERY_WRITE_CAPPED", EmailSchema, StudentSourcedIdSchema, StudentIdentifierSchema;
|
|
32973
33082
|
var init_dist2 = __esm(() => {
|
|
32974
33083
|
init_src();
|
|
32975
33084
|
init_src();
|
|
@@ -34502,8 +34611,8 @@ var init_schemas4 = __esm(() => {
|
|
|
34502
34611
|
inactiveSeconds: exports_external.number().nonnegative().optional()
|
|
34503
34612
|
}).optional(),
|
|
34504
34613
|
xpEarned: exports_external.number(),
|
|
34505
|
-
masteredUnits: exports_external.number().optional(),
|
|
34506
|
-
masteredUnitsAbsolute: exports_external.number().
|
|
34614
|
+
masteredUnits: exports_external.number().finite().optional(),
|
|
34615
|
+
masteredUnitsAbsolute: exports_external.number().finite().int().optional(),
|
|
34507
34616
|
extensions: exports_external.record(exports_external.string(), exports_external.unknown()).optional()
|
|
34508
34617
|
}).refine((data) => !(data.masteredUnits !== undefined && data.masteredUnitsAbsolute !== undefined), {
|
|
34509
34618
|
message: "Cannot provide both masteredUnits and masteredUnitsAbsolute",
|
|
@@ -38604,7 +38713,8 @@ var init_timeback_service = __esm(() => {
|
|
|
38604
38713
|
masteredUnits: result.masteredUnitsApplied,
|
|
38605
38714
|
pctCompleteApp: result.pctCompleteApp,
|
|
38606
38715
|
scoreStatus: result.scoreStatus,
|
|
38607
|
-
inProgress: result.inProgress
|
|
38716
|
+
inProgress: result.inProgress,
|
|
38717
|
+
...result.warnings ? { warnings: result.warnings } : {}
|
|
38608
38718
|
};
|
|
38609
38719
|
}
|
|
38610
38720
|
async resolveActiveGameCourse({
|
|
@@ -98355,7 +98465,7 @@ var init_timeback7 = __esm(() => {
|
|
|
98355
98465
|
const seed3 = hashCode(`${e.grade}-${e.subject}`);
|
|
98356
98466
|
const masterableUnits = 5 + seed3 % 16;
|
|
98357
98467
|
const masteredUnits = seed3 % (masterableUnits + 1);
|
|
98358
|
-
const pctComplete = masterableUnits > 0 ? Math.round(masteredUnits / masterableUnits *
|
|
98468
|
+
const pctComplete = masterableUnits > 0 ? Math.round(masteredUnits / masterableUnits * 100) : 0;
|
|
98359
98469
|
return {
|
|
98360
98470
|
grade: e.grade,
|
|
98361
98471
|
subject: e.subject,
|