Skip to content

Commit

Permalink
Add basic cmi5 profile (#21)
Browse files Browse the repository at this point in the history
  • Loading branch information
Selindek authored Jul 18, 2023
1 parent 48d8e9d commit f1e7346
Show file tree
Hide file tree
Showing 9 changed files with 244 additions and 2 deletions.
1 change: 1 addition & 0 deletions projects/ngx-xapi/profiles/cmi5/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './src/public-api';
6 changes: 6 additions & 0 deletions projects/ngx-xapi/profiles/cmi5/ng-package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"dest": "../../../../dist/ngx-xapi/profiles/cmi5",
"lib": {
"entryFile": "src/public-api.ts"
}
}
180 changes: 180 additions & 0 deletions projects/ngx-xapi/profiles/cmi5/src/lib/cmi5-statements.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
import {
Activity,
Agent,
Extensions,
Statement,
Verb,
initialized,
launched,
} from '@berry-cloud/ngx-xapi/model';
import { v4 as uuidv4 } from 'uuid';
import { LaunchMode, MoveOn } from './launch-data';

export class Cmi5Statements {
static readonly cmi5: string =
'https://w3id.org/xapi/cmi5/context/categories/cmi5';

static readonly moveOn: string =
'https://w3id.org/xapi/cmi5/context/categories/moveon';

static readonly sessionId: string =
'https://w3id.org/xapi/cmi5/context/extensions/sessionid';

static readonly masteryScore: string =
'https://w3id.org/xapi/cmi5/context/extensions/masteryscore';

static readonly launchMode: string =
'https://w3id.org/xapi/cmi5/context/extensions/launchmode';

static readonly launchUrl: string =
'https://w3id.org/xapi/cmi5/context/extensions/launchurl';

static readonly launchParameters: string =
'https://w3id.org/xapi/cmi5/context/extensions/launchparameters';

/**
* Returns a cmi5 launched statement.
*
* @param agent that launched the activity
* @param activity that is being launched
* @param extensions of the statement
* @param publisherActivity of the activity that is being launched
* @param timestamp of when the activity was launched
* @param registration of activity that is being launched
* @returns a cmi5 launched statement
*/
static launched(
agent: Agent,
activity: Activity,
extensions: {
sessionId: string;
launchMode: LaunchMode;
launchUrl: string;
moveOn: MoveOn;
masteryScore?: number;
launchParameters?: string;
},
publisherActivity: Activity,
registration: string,
timestamp?: Date
): Statement {
return this.statement(
launched,
agent,
activity,
extensions,
publisherActivity,
registration,
timestamp
);
}

/**
* Returns a cmi5 initialized statement.
*
* @param agent that initialized the activity
* @param activity that has been initialized
* @param extensions of the statement
* @param publisherActivity of the activity that has been initialized
* @param timestamp of when the activity was initialized
* @param registration of activity that has been initialized
* @returns a cmi5 initialized statement
*/
static initialized(
agent: Agent,
activity: Activity,
extensions: {
sessionId: string;
masteryScore?: number;
},
publisherActivity: Activity,
registration: string,
timestamp?: Date
): Statement {
return this.statement(
initialized,
agent,
activity,
extensions,
publisherActivity,
registration,
timestamp
);
}

private static statement(
verb: Verb,
agent: Agent,
activity: Activity,
extensions: {
sessionId: string;
launchMode?: LaunchMode;
launchUrl?: string;
moveOn?: MoveOn;
masteryScore?: number;
launchParameters?: string;
},
publisherActivity: Activity,
registration: string,
timestamp?: Date
): Statement {
const statement: Statement = {
id: uuidv4().toString(),
actor: agent,
verb,
object: activity,
timestamp: timestamp?.toISOString() ?? new Date().toISOString(),

context: {
registration,

contextActivities: {
grouping: [publisherActivity],
category: [
{
objectType: 'Activity',
id: this.cmi5,
},
],
},

extensions: this.process(extensions),
},
};
return statement;
}

private static process(extensions: {
sessionId: string;
launchMode?: LaunchMode;
launchUrl?: string;
moveOn?: MoveOn;
masteryScore?: number;
launchParameters?: string;
}): Extensions {
// Session ID is the only mandatory extension
const temp: Extensions = { [this.sessionId]: extensions.sessionId };

if (extensions.launchMode) {
temp[this.launchMode] = extensions.launchMode;
}

if (extensions.launchUrl) {
temp[this.launchUrl] = extensions.launchUrl;
}

if (extensions.moveOn) {
temp[this.moveOn] = extensions.moveOn;
}

if (extensions.masteryScore) {
temp[this.masteryScore] = extensions.masteryScore;
}

if (extensions.launchParameters) {
temp[this.launchParameters] = extensions.launchParameters;
}

return temp;
}
}
31 changes: 31 additions & 0 deletions projects/ngx-xapi/profiles/cmi5/src/lib/launch-data.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { Context } from '@berry-cloud/ngx-xapi/model';

export interface LaunchData {
contextTemplate: Context;
launchMode: LaunchMode;
launchParameters?: string;
masteryScore?: number;
moveOn: MoveOn;
returnURL?: string;

/**
* Only if an entitlementKey is present in the Course Structure for the AU.
*/
entitlementKey?: EntitlementKey;
}

export type LaunchMode = 'Normal' | 'Browse' | 'Review';

export type MoveOn =
| 'Passed'
| 'Completed'
| 'CompletedAndPassed'
| 'CompletedOrPassed'
| 'NotApplicable';

export interface EntitlementKey {
courseStructure: string;
alternate?: string;
}

export type LaunchMethod = 'OwnWindow' | 'AnyWindow';
9 changes: 9 additions & 0 deletions projects/ngx-xapi/profiles/cmi5/src/lib/launch.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { Actor } from '@berry-cloud/ngx-xapi/model';

export interface Launch {
endpoint: string; // URL
fetch: string; // URL
actor: Actor; // Agent
registration: string; // UUID
activityId: string; // URL
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export interface LearnerPreferences {
languagePreference: string;
audioPreference?: 'on' | 'off';
}
8 changes: 8 additions & 0 deletions projects/ngx-xapi/profiles/cmi5/src/public-api.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/*
* Public API Surface of ngx-xapi/profile/cmi5
*/

export * from './lib/cmi5-statements';
export * from './lib/launch-data';
export * from './lib/launch';
export * from './lib/learner-preferences';
4 changes: 2 additions & 2 deletions sonar-project.properties
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ sonar.organization=berrycloud
#sonar.projectVersion=1.0

# Path is relative to the sonar-project.properties file. Replace "\" by "/" on Windows.
sonar.sources=projects/ngx-xapi/client/src,projects/ngx-xapi/model/src
sonar.tests=projects/ngx-xapi/client/src,projects/ngx-xapi/model/src
sonar.sources=projects/ngx-xapi/client/src,projects/ngx-xapi/model/src,projects/ngx-xapi/profiles/cmi5/src
sonar.tests=projects/ngx-xapi/client/src,projects/ngx-xapi/model/src,projects/ngx-xapi/profiles/cmi5/src

# Encoding of the source code. Default is default system encoding
#sonar.sourceEncoding=UTF-8
Expand Down
3 changes: 3 additions & 0 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
"noFallthroughCasesInSwitch": true,
"sourceMap": true,
"paths": {
"@berry-cloud/ngx-xapi/profiles/cmi5": [
"dist/ngx-xapi/profiles/cmi5"
],
"@berry-cloud/ngx-xapi/model": [
"dist/ngx-xapi/model"
],
Expand Down

0 comments on commit f1e7346

Please sign in to comment.