Repository navigation
Before you upgrade
Most of this release brings SCORM 2004 rollup in line with the SN book and the ADL reference sequencer. Courses that use local sequencing can report different completion, satisfaction or scores after the upgrade, so re-test the ones that depend on rolled-up results.
Other changes to check:
minimumPercentis read as a fraction (#1767). Values from 0 to 1 are fractions, as IMS SS manifests write them, so 0.5 means 50%. Values above 1 are still whole percents, so settings that pass 50 or 100 keep working. A value of exactly 1 now means 100%.Initializerestores unsynced offline data (#1774) for the current course and learner. See Offline support below.- TypeScript changes to
IOfflineStorageService(#1774).getOfflineData()can now return any commit payload shape, so code that narrows its result may need updating. There is a new optionalgetPendingOfflineData()method.BaseAPIhas two new protected methods,restoreOfflineData()andgetOfflineLearnerId(), which a subclass with the same names would override. onActivityUnloadon a same-activity resume (#1762) receives the activity after DB.2 has prepared it for the new delivery.
What's new
- Time conditions in rollup rules (#1763). Rollup rules now evaluate
timeLimitExceededandoutsideAvailableTimeRange. IMS SS lists both as rollup conditions, but a rollup rule using either never matched. They read the same clock as sequencing rules (nowandgetAttemptElapsedSeconds), and clock changes made withupdateConfiguration()reach rollup too.
Fixes
SCORM 2004 rollup
activityProgressKnownworks in rollup conditions (#1764). OnlyprogressKnownwas accepted, so a condition using the IMS SS name never matched, and with thenotoperator it always matched.- Read-mapped modules keep their status (#1765). An extra rollup pass across sibling clusters, which the spec does not have, rolled up a module from its children even when its status came from a global objective. A satisfied module could flip to not satisfied after the learner finished a sibling.
- Measure rollup follows RB.1.1 (#1766). Child weights no longer change with completion, attempt count or attempt limits. Every tracked child with an
objectiveMeasureWeightabove 0 adds its weight to the denominator, scored or not. Set the weight to 0 to leave a child out. Parent scores in existing courses can change. - Unknown stays unknown in rollup conditions (#1768). A rule such as "not satisfied if any child is not satisfied" fired for a child that had never been attempted. Conditions now use three-valued logic, as RB.1.4 does.
- No contributing child leaves completion unchanged (#1769). Default progress rollup set the parent to incomplete instead.
- Rollup reaches the root (#1771). Rollup stopped early when a parent changed from unknown to known not satisfied, or when only its completion amount changed. A course could stay unknown when it should have failed.
- One objective rollup method per pass (#1772). If
satisfiedByMeasureis set, the measure decides. Otherwise, if the activity has satisfied or not-satisfied rollup rules, the rules decide. Default rollup runs only when neither applies. Before, rules could override the measure, and default rollup could decide after the activity's own rules did not fire. When the rolled-up measure becomes unknown, the success status is now cleared too. - Default rollup filters children per action (#1773). A child had to pass both filters, such as
requiredForCompletedandrequiredForIncomplete, to count. Each check now uses its own filter. For example, a suspended, incomplete module withrequiredForIncomplete="ifNotSuspended"no longer lets its parent be reported completed. measureSatisfactionIfActiveapplies to the activity itself (#1779). It was applied to the activity's children. While an activity satisfied by measure is active and the setting is false, its satisfaction is now unknown, and a write map publishes the result only when the attempt ends.
Sequencing
- A resumed attempt keeps its clock (#1762). After a suspend and resume,
timeLimitExceededrules and the attempt duration limit started again from zero, and durations restored from saved state were overwritten. - Terminate from an unload handler (#1762). When the host navigated while a SCO was running and the SCO called
Terminatefrom its unload handler, scorm-again ran an exit on the newly delivered activity. The old SCO'sTerminatenow ends only its own session.
Offline support
- Every commit format is queued (#1774). An offline commit was queued only with
dataCommitFormat: "json"and no common commit fields. Every other setting returned"false"with error 101. - Unsynced data is restored (#1774). Restoring never worked.
Initializenow applies every queued commit for the course in order, so partial commits are not lost. It loads only values the SCO can write. Commits in theparamsformat are skipped with a warning. - The queue is scoped to the course and learner (#1774). On a shared device, one learner's queued data could be restored into another learner's session or sent to another course. Commits queued before this release are replayed for their own course but not restored.
- Replay matches live commits (#1774). Queued commits are sent with the same encoding and response handler as live commits, and the stored copy is removed once everything has synced.
- Sync events fire from every sync (#1776).
OfflineDataSyncingis now emitted.OfflineDataSyncedandOfflineDataSyncFailedalso fire for syncs started by theonlineevent or thescorm-again:network-statusevent. Going back online with nothing queued now logs at INFO, not as a "Sync failed" error.
Documentation and examples
- The six mobile guides now share one bridge script,
docs-site/examples/mobile-bridge.js, which CI runs in Chromium and Firefox (#1777). The old guide code did not work with the current library. - CI now checks code snippets in the docs and README for settings and events that do not exist (#1775). The docs used
ActivityDelivered, which is now corrected toActivityDelivery. - The React Native example moves to Expo SDK 58 and runs on the shared bridge (#1778). CI type-checks and bundles it, but it has not been tested on a device.