xapijs / cmi5 Goto Github PK
View Code? Open in Web Editor NEWCommunicate over the xAPI cmi5 profile using JavaScript.
Home Page: https://www.xapijs.dev/cmi5-profile-library
License: MIT License
Communicate over the xAPI cmi5 profile using JavaScript.
Home Page: https://www.xapijs.dev/cmi5-profile-library
License: MIT License
Most of the time when we make an assignable unit, the devs don't care about xapi or cmi5 and they just want to know how to send results when their lesson content is complete.
Cmi5 on the other side, has a whole end sequence for assignable units and it needs to be done correctly and completely.
So to simplify for the above use case, it would be good to have a function like moveOn
that handles all the COMPLETED, PASSED
|FAILED
and terminated messages the boilerplate way for the caller, something like:
interface MoveOnOptions extends ... {
disableSendTerminate: boolean;
}
async function moveOn(score: number|ResultScore, options: MoveOnOptions): Promise<string[]> {
// check launchData moveOn and masteryScore and send COMPLETED and/or PASSED|FAILED
// send TERMINATED unless disabled in params
}
...if this sounds good, I can send as a PR
I do not believe that this library fulfils the following requirement from the cmi5 quartz specification:
The AU MUST assign a statement id property in UUID format (as defined in the xAPI specification) for all statements it issues.
Forgive me if I have missed something.
The code seems very clear and easy to follow.
We are building a CMI5 course using vue and vue router. The router uses the # in the url to pass it's urls. The LMS adds the query parameters at the correct position, before the "#". Here's an example (edited for brevity and privacy):
The registration parameter ends up incorrect, it contains the "#/".
I looked at
private getLaunchParametersFromLMS(): LaunchParameters { return XAPI.getSearchQueryParamsAsObject( window.location.href ) as LaunchParameters; }
and it uses window.location.href and then the method string split's by "?"- i would suggest to use window.location.search if possible. I have a pull request ready, if interested.
And thanks for all the work!
-Felix
Currently, information like the fetch token and other data needed to hydrate a Cmi5 instance is are private, which makes implementing cmi5 Best Practice # 17 difficult to achieve without significantly extending/overriding the Cmi5 class.
It would be nice if you could obtain a JSON-able object from the API (storable in e.g. SessionStorage) that includes all the necessary information to instantiate a Cmi5 object without having to go through initialize(), and then be able to supply that information to the constructor or a static factory function in order to recover a session from a browser refresh, as indicated in the Best Practice (provided below):
There are certain situations, such as browser window refresh, that may inadvertently cause cmi5 errors related to operations that must occur only once in a session. To prevent such issues, AUโs should be designed to use non-volatile storage (local to AU) to preserve the state of following operations that have been performed during the session:
This lib should only be used in client-side code, so its unnecessary to export for commonjs with browser: false
for node environments.
connection
was a legacy variable name and never got around to changing it to xapi
.
Is there a way to search in the LRS with this package? I use every other part of this library, I just need the ability to load my learners previous activities to the package. Do you have any solutions?
let's say i publish content as xapi from adobe captivate and the zip file is uploaded to lms. How to implement this in the whole process.
e.g. Cmi5.get()
or Cmi5.instance()
Anywhere that we currently use cmi5 libs in assignable-unit apps, we really just want to access the global cmi5 singleton. Without static-singleton access, it puts extra burden on client code to figure out where to initialize the cmi5 instance and then how to make it accessible in different places in the code.
I can add this as a quick PR if you approve
First off, thanks for making this library!
I've been working on various projects that use xapi/cmi5 and we've built a couple versions of js libraries to support it, but I'd like to switch to your lib.
The main blocker for us making that switch is that we have some apps that depend on passing result extensions with pass/fail/complete statements, and the signatures for those functions in this lib don't support passing extensions.
Would you be open to that feature in principal? If you are, we can make a fork, do the work and PR back to you.
I'm imagining the best and most general purpose way to handle this would be an optional callback function that transforms xapi statments before send, e.g.
// a function that can apply an arbitrary transform
// to an xapi Statement, e.g. add extensions
interface StatementTransformFunction {
transform: (s: Statement) => Statement;
}
// a catch-all for options that might be
// passed to cmi-send-statement functions
interface SendCmiStatementOptions {
transform?: StatementTransformFunction;
}
class Cmi5 {
public complete(s: Partial<Statement>, options: SendCmiStatementOptions = {}) : AxiosPromise<string[]> {
...
this. sendCmi5DefinedStatement({...}, options)
}
public sendCmi5AllowedStatement(
statement: Partial<Statement>,
options: SendCmiStatementOptions = {}): AxiosPromise<string[]> {
...
const mergedStatement: Statement = deepmerge.all([cmi5AllowedStatementRequirements, statement]) as Statement;
const sendStatement = (options.transform)
? options.transform(mergedStatement)
: mergedStatement;
return this.connection.sendStatement(sendStatement);
}
}
For motivation, the custom extension we most commonly use is one that supplies granular 'skill' scores to the result of an assignable unit. For example, in some interactive-training assignable units we have, the result might look like this:
{
"result": {
"score": { "scaled": 0.8 },
"extensions": {
"https://ict.usc.edu/xapi/result/extension/skills": {
"asks": 0.2,
"evaluates": 0.9,
"listens": 0.5,
}
}
}
}
Curious if you know of a a more standards-based way to do the equivalent?
The last thing I want to add is that the cmi5 libraries we've developed inhouse have a suite of tests. Since they're testing cmi implementation over axios (via spies), should be not too hard to port our tests over to your library. Would you want those basic tests as a (separate) PR?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.