You have loads of existing SCORM content, but now you're ready to start using xAPI for getting a ton of data about your learners. But, you still need your content to be played securely in an LMS with their authorized learners. So how do you move from SCORM to xAPI while maintaining interoperability? If this sounds familiar, cmi5 could be your answer.
In this session, George Vilches talks briefly about what cmi5 is and when to use the specification before diving into converting legacy SCORM content to cmi5 using various approaches, including utilizing the cmi5 CATAPULT course templates and authoring tools or building custom courseware. He also discusses SCORM to cmi5 terminology, what happens through the lifecycle of a learner's course launch and using cmi5 with other xAPI Profiles, like the Video Profile.
Smelling what The Rock's cooking: Converting SCORM content to cmi5
1. Smelling What The Rock’s Cooking:
Converting SCORM Content to cmi5
George Vilches
xAPI Party - Fall 2021
2. What We Will be Talking About
● Brief cmi5 overview
● Comparison of standards
● cmi5 CATAPULT tools: Course templates &
Content Test Suite
● SCORM to cmi5 terminology
● Converting existing SCORM content to
cmi5
3. Background on cmi5
cmi5 is an “xAPI Profile”
● An extra set of rules called a “Profile”
● Ensures plug & play interoperability between learning content and LMSs
● Designed specifically for when a learner launches from the LMS user
interface
Components
● Course package/structure
● Learning Management System (LMS)
● Learning Record Store (LRS)
● Assignable Unit (AU)
4. Comparison of Key Features
Features SCORM xAPI cmi5
Defined content launch ✔ ✘ ✔
Track “anything” ✘ ✔ ✔
Normalized reporting ✔ ✘ ✔
Mobile applications ✘ ✔ ✔
Distributed content ✘ ✔* ✔
Data portability ✘ ✔ ✔
Extensibility ✘ ✔ ✔
Normalized completion criteria ✔ ✘ ✔
Multiple lesson support ✔ ✘ ✔
5. When to Migrate Legacy Content to cmi5
● Revising or updating existing content.
● Capturing more detailed learning data from existing courseware.
● Modernizing your training per the DoDI 1322.26 fungible resources.
● Avoiding pop up windows.
The best time is today! Let’s do it.
6. Use Your Tools
Is your content from an authoring tool?
Is your content based on a known
framework?
They might already publish to cmi5, just
use it.
12. “Tracking Plugin”, A Helper of Helpers
● Wraps raw functionality with common use cases
● Combines independent behaviors
● Adds functionality beyond cmi5 that courses often use
○ Bookmarks
○ Statement batching
● Handles boundary UI/standards cases that are tricky to get right
○ Initialization
○ Exit behavior
● Simplifies error handling
● Models statement generation for Video Profile
13. SCORM to cmi5 Terminology
SCORM cmi5
Activity (SCO) Identifier Publisher ID
Aggregation / Cluster Block
Launch Data launchParameters
Manifest Course Structure
Resource HREF AU URL
Rollup (partial) moveOn
SCO AU
17. The Hard Way Always Involves Javascript
SCORM Runtime Command cmi5 Verb
LMSInitialize("") Initialized
LMSSetValue("cmi.core. lesson_status", "completed") Completed
LMSSetValue("cmi.core.lesson_status", "passed") Passed
LMSSetValue("cmi.core.lesson_status", "failed") Failed
LMSFinish("") Terminated
LMSSetValue("cmi.suspend_data", "...")
LMSSetValue("cmi.core.lesson_ location", "...")
(set as Activity State)
18.
19. But First, The Front 9?
● The Venerable Golf Courses
● Examples of standard SCORM 1.2 /
2004 functionality
● Contains the wisdom of ancients
● Less interesting than rocks
20. Step By Step, Runtime
1. What SCORM version is the package?
a. Does it support multiple versions?
b. Can you put a cmi5 plugin next to it?
2. Find the SCORM commands.
a. Search for “API.LMS” or “API_1484_11.”
3. Create collection of SCORM get/set keys
a. These are (almost) all prefixed “cmi.”
4. Look up SCORM->cmi5 mappings
5. Replace with appropriate cmi5_course.js
tracking call.
a. Or add one if we didn’t already include it!
21. Inject cmi5 Tracking
SCORM cmi5
var currentPage = null;
var startTimeStamp = null;
var processedUnload = false;
var reachedEnd = false;
<script src="cmi5.min.js"
type="text/javascript"></script>
<script src="course_cmi5.js"
type="text/javascript"></script>
...
var currentPage = null;
var startTimeStamp = null;
var processedUnload = false;
var reachedEnd = false;
var trackingPlugin = new CourseCmi5Plugin();
22. Initialize
SCORM cmi5
function doStart(){
//get the iFrame sized correctly and set up
SetupIFrame();
//record the time that the learner started
the SCO so that we can report the total time
startTimeStamp = new Date();
//initialize communication with the LMS
API.LMSInitialize("");
//it's a best practice to set the lesson
status to incomplete when
//first launching the course (if the course
is not already completed)
var completionStatus =
ScormProcessGetValue("cmi.core.lesson_status");
if (completionStatus == "not attempted"){
...
function doStart() {
//get the iFrame sized correctly and set up
SetupIFrame();
//record the time that the learner started
the SCO so that we can report the total time
startTimeStamp = new Date();
//initialize communication with the LMS
trackingPlugin.initialize(postInit,
trackingActivityUpdate);
}
function postInit() {
...
23. Set Default Status
SCORM cmi5
//it's a best practice to set the lesson status to
incomplete when
//first launching the course (if the course is not
already completed)
var completionStatus =
ScormProcessGetValue("cmi.core.lesson_status");
if (completionStatus == "not attempted"){
ScormProcessSetValue("cmi.core.lesson_status",
"incomplete");
}
// Don’t set a default completion/success status
X
24. Fetch Bookmark
SCORM cmi5
var bookmark =
API.LMSGetValue("cmi.core.lesson_location");
//if there isn't a stored bookmark, start the user at the
first page
if (bookmark == ""){
currentPage = 0;
}
else{
//if there is a stored bookmark, prompt the user to
resume from the previous location
if (confirm("Would you like to resume from where you
previously left off?")){
currentPage = parseInt(bookmark, 10);
}
else{
currentPage = 0;
}
}
goToPage();
trackingPlugin.getBookmark().then(function(bookmark) {
//if there isn't a stored bookmark, start the user at
the first page
if (bookmark == ""){
currentPage = 0;
}
else{
//if there is a stored bookmark, prompt the user
to resume from the previous location
if (confirm("Would you like to resume from where
you previously left off?")){
currentPage = parseInt(bookmark, 10);
}
else{
currentPage = 0;
}
}
goToPage();
});
25. Save Bookmark
SCORM cmi5
//save the current location as the bookmark
API.LMSSetValue("cmi.core.lesson_location", currentPage);
//save the current location as the bookmark
trackingPlugin.setBookmark(currentPage);
26. Success / Score
SCORM cmi5
function RecordTest(score){
API.LMSSetValue("cmi.core.score.raw", score);
API.LMSSetValue("cmi.core.score.min", "0");
API.LMSSetValue("cmi.core.score.max", "100");
//if we get a test result, set the lesson status to
passed/failed instead of completed
//consider 70% to be passing
if (score >= 70){
API.LMSSetValue("cmi.core.lesson_status",
"passed");
}
else{
API.LMSSetValue("cmi.core.lesson_status",
"failed");
}
}
function RecordTest(score){
const scaledScore = score / 100.;
const scoreObj = {
scaled: scaledScore,
raw: score,
min: 0,
max: 100
};
//if we get a test result, set the lesson status to
passed/failed instead of completed
//consider 70% to be passing
if (score >= 70){
trackingPlugin.cmi5.passed(scoreObj);
}
else{
trackingPlugin.cmi5.failed(scoreObj);
}
}
28. Terminate / Exit Preparation
//note use of short-circuit AND. If the user
reached the end, don't prompt.
//just exit normally and submit the results.
if (reachedEnd == false && confirm("Would you
like to save your progress to resume later?")){
//set exit to suspend
API.LMSSetValue("cmi.core.exit", "suspend");
}
else{
//set exit to normal
API.LMSSetValue("cmi.core.exit", "");
}
//process the unload handler to close out the
session.
//the presense of an adl.nav.request will cause
the LMS to
//take the content away from the user.
doUnload(true);
SCORM cmi5
//note use of short-circuit AND. If the user
reached the end, don't prompt.
//just exit normally and submit the results.
if (reachedEnd == false && confirm("Would you
like to save your progress to resume later?")){
}
else{
trackingPlugin.setBookmark("");
}
//process the unload handler to close out the
session.
doUnload(true);
29. Terminate / Exit
//record the session time
var endTimeStamp = new Date();
var totalMilliseconds = (endTimeStamp.getTime() -
startTimeStamp.getTime());
var scormTime =
ConvertMilliSecondsToSCORMTime(totalMilliseconds, false);
API.LMSSetValue("cmi.core.session_time", scormTime);
//if the user just closes the browser, we will default to
saving
//their progress data. If the user presses exit, he is
prompted.
//If the user reached the end, the exit normall to submit
results.
if (pressedExit == false && reachedEnd == false){
API.LMSSetValue("cmi.core.exit", "suspend");
}
API.LMSFinish("");
SCORM cmi5
trackingPlugin.exit(false);
30. Let’s See the Fruit of Our Labor
The *cmi5* Golf Course
31. Special Conversion Quirks
● Passed / Completed / Failed repeats:
○ Okay in SCORM
○ BAD in cmi5 - no dupes, no failed after passed
● Mastery score
○ SCORM: Evaluates and overwrites status after usage
○ cmi5: Checks at status Statement time, MUST reject if mismatched
● Sequencing
○ SCORM: Only supported in 2004, manifest-based
○ cmi5: No manifest-based sequencing, can only be done at runtime
■ Extensions: “requires”, “equivalences”
32. CATAPULT Documentation
GitHub repository, course examples,
user guides, installation and deployment
instructions can be found at:
https://adlnet.github.io/CATAPULT/
cmi5 Best Practices Guide:
https://adlnet.gov/assets/uploads/cmi5%20
Best%20Practices%20Guide%20-%20From%2
0Conception%20to%20Conformance.pdf
33. Early cmi5 adopters that claim support for
cmi5 according to cmi5 working group.
Run your own CTS today!
● Use Docker***
● Use a cmi5 conformant LRS
How to pick an LRS:
● Check the cmi5 list of adopters
● Build your own!
What do you need to get started with cmi5
https://aicc.github.io/CMI-5_Spec_Current/adoption/
34. Resources
Keep up-to-date on cmi5 CATAPULT
https://adlnet.gov/projects/cmi5-CATAPULT/ & https://xapi.com/cmi5-project-catapult/
Visit ADL’s cmi5 page and xapi.com’s cmi5 page for more background
https://adlnet.gov/projects/cmi5-standard/ & https://xapi.com/cmi5/
View ADL’s cmi5 resources
https://adlnet.gov/resources/cmi5-resources/
Join the cmi5 weekly working group
http://aicc.github.io/CMI-5_Spec_Current/
35. Have questions? Ask us anything!
George Vilches
george.vilches@rusticisoftware.com
Email us:
info@rusticisoftware.com
Learn more:
rusticisoftware.com
scorm.com
xapi.com