MOBILE-4616 scorm: Move scorm constants to a file

main
Pau Ferrer Ocaña 2024-07-11 22:43:55 +02:00
parent c2caa15175
commit c0856c0c97
13 changed files with 217 additions and 150 deletions

View File

@ -19,10 +19,16 @@ import {
AddonModScormCommonEventData,
AddonModScormDataEntry,
AddonModScormDataValue,
AddonModScormProvider,
AddonModScormScorm,
AddonModScormUserDataMap,
} from '../services/scorm';
import {
ADDON_MOD_SCORM_UPDATE_TOC_EVENT,
ADDON_MOD_SCORM_LAUNCH_NEXT_SCO_EVENT,
ADDON_MOD_SCORM_LAUNCH_PREV_SCO_EVENT,
ADDON_MOD_SCORM_GO_OFFLINE_EVENT,
AddonModScormMode,
} from '../constants';
// Standard Data Type Definition.
let CMI_STRING_256 = '^[\\u0000-\\uFFFF]{0,255}$';
@ -110,7 +116,7 @@ export class AddonModScormDataModel12 {
protected scoId: number,
protected attempt: number,
protected userData: AddonModScormUserDataMap,
protected mode = AddonModScormProvider.MODENORMAL,
protected mode = AddonModScormMode.NORMAL,
protected offline = false,
protected canSaveTracks = true,
) {
@ -595,7 +601,7 @@ export class AddonModScormDataModel12 {
}
// Define mode and credit.
this.currentUserData[scoId].userdata['cmi.core.credit'] = this.mode == AddonModScormProvider.MODENORMAL ?
this.currentUserData[scoId].userdata['cmi.core.credit'] = this.mode === AddonModScormMode.NORMAL ?
'credit' :
'no-credit';
this.currentUserData[scoId].userdata['cmi.core.lesson_mode'] = this.mode;
@ -620,7 +626,7 @@ export class AddonModScormDataModel12 {
const result = this.storeData(false);
// Trigger TOC update.
this.triggerEvent(AddonModScormProvider.UPDATE_TOC_EVENT);
this.triggerEvent(ADDON_MOD_SCORM_UPDATE_TOC_EVENT);
this.errorCode = result ? '0' : '101';
@ -652,20 +658,20 @@ export class AddonModScormDataModel12 {
const result = this.storeData(true);
if (this.getEl('nav.event') != '') {
if (this.getEl('nav.event') == 'continue') {
this.triggerEvent(AddonModScormProvider.LAUNCH_NEXT_SCO_EVENT);
this.triggerEvent(ADDON_MOD_SCORM_LAUNCH_NEXT_SCO_EVENT);
} else {
this.triggerEvent(AddonModScormProvider.LAUNCH_PREV_SCO_EVENT);
this.triggerEvent(ADDON_MOD_SCORM_LAUNCH_PREV_SCO_EVENT);
}
} else {
if (this.scorm.auto) {
this.triggerEvent(AddonModScormProvider.LAUNCH_NEXT_SCO_EVENT);
this.triggerEvent(ADDON_MOD_SCORM_LAUNCH_NEXT_SCO_EVENT);
}
}
this.errorCode = result ? '0' : '101';
// Trigger TOC update.
this.triggerEvent(AddonModScormProvider.UPDATE_TOC_EVENT);
this.triggerEvent(ADDON_MOD_SCORM_UPDATE_TOC_EVENT);
// Conver to string representing a boolean.
return result ? 'true' : 'false';
@ -986,8 +992,8 @@ export class AddonModScormDataModel12 {
this.setEl('cmi.core.lesson_status', 'completed');
}
if (this.getEl('cmi.core.lesson_mode') == AddonModScormProvider.MODENORMAL) {
if (this.getEl('cmi.core.credit') == 'credit') {
if (this.getEl('cmi.core.lesson_mode') === AddonModScormMode.NORMAL) {
if (this.getEl('cmi.core.credit') === 'credit') {
if (this.getEl('cmi.student_data.mastery_score') !== '' && this.getEl('cmi.core.score.raw') !== '') {
if (parseFloat(<string> this.getEl('cmi.core.score.raw')) >=
parseFloat(<string> this.getEl('cmi.student_data.mastery_score'))) {
@ -999,7 +1005,7 @@ export class AddonModScormDataModel12 {
}
}
if (this.getEl('cmi.core.lesson_mode') == AddonModScormProvider.MODEBROWSE) {
if (this.getEl('cmi.core.lesson_mode') === AddonModScormMode.BROWSE) {
if (this.dataModel[this.scoId]['cmi.core.lesson_status'].defaultvalue == '' &&
this.getEl('cmi.core.lesson_status') == 'not attempted') {
this.setEl('cmi.core.lesson_status', 'browsed');
@ -1020,7 +1026,7 @@ export class AddonModScormDataModel12 {
// Failure storing data in online. Go offline.
this.offline = true;
this.triggerEvent(AddonModScormProvider.GO_OFFLINE_EVENT);
this.triggerEvent(ADDON_MOD_SCORM_GO_OFFLINE_EVENT);
return AddonModScorm.saveTracksSync(this.scoId, this.attempt, tracks, this.scorm, this.offline, this.currentUserData);

View File

@ -25,7 +25,6 @@ import { CoreDomUtils } from '@services/utils/dom';
import { CoreUtils } from '@services/utils/utils';
import { Translate } from '@singletons';
import { CoreEventObserver, CoreEvents } from '@singletons/events';
import { AddonModScormModuleHandlerService } from '../../services/handlers/module';
import { AddonModScormPrefetchHandler } from '../../services/handlers/prefetch';
import {
AddonModScorm,
@ -33,16 +32,23 @@ import {
AddonModScormGetScormAccessInformationWSResponse,
AddonModScormAttemptGrade,
AddonModScormOrganization,
AddonModScormProvider,
AddonModScormScorm,
} from '../../services/scorm';
import { AddonModScormHelper, AddonModScormTOCScoWithIcon } from '../../services/scorm-helper';
import {
AddonModScormAutoSyncEventData,
AddonModScormSync,
AddonModScormSyncProvider,
AddonModScormSyncResult,
} from '../../services/scorm-sync';
import {
ADDON_MOD_SCORM_COMPONENT,
AddonModScormForceAttempt,
AddonModScormMode,
AddonModScormSkipView,
ADDON_MOD_SCORM_DATA_SENT_EVENT,
ADDON_MOD_SCORM_DATA_AUTO_SYNCED,
ADDON_MOD_SCORM_PAGE_NAME,
} from '../../constants';
/**
* Component that displays a SCORM entry page.
@ -56,7 +62,7 @@ export class AddonModScormIndexComponent extends CoreCourseModuleMainActivityCom
@Input() autoPlayData?: AddonModScormAutoPlayData; // Data to use to play the SCORM automatically.
component = AddonModScormProvider.COMPONENT;
component = ADDON_MOD_SCORM_COMPONENT;
pluginName = 'scorm';
scorm?: AddonModScormScorm; // The SCORM object.
@ -90,7 +96,7 @@ export class AddonModScormIndexComponent extends CoreCourseModuleMainActivityCom
gradesExpanded = false;
protected fetchContentDefaultError = 'addon.mod_scorm.errorgetscorm'; // Default error to show when loading contents.
protected syncEventName = AddonModScormSyncProvider.AUTO_SYNCED;
protected syncEventName = ADDON_MOD_SCORM_DATA_AUTO_SYNCED;
protected attempts?: AddonModScormAttemptCountResult; // Data about online and offline attempts.
protected lastAttempt?: number; // Last attempt.
protected lastIsOffline = false; // Whether the last attempt is offline.
@ -201,8 +207,8 @@ export class AddonModScormIndexComponent extends CoreCourseModuleMainActivityCom
||
(
this.accessInfo.canskipview && !this.accessInfo.canviewreport &&
(this.scorm.skipview ?? 0) >= AddonModScormProvider.SKIPVIEW_FIRST &&
(this.scorm.skipview === AddonModScormProvider.SKIPVIEW_ALWAYS || this.lastAttempt === 0)
(this.scorm.skipview ?? 0) >= AddonModScormSkipView.FIRST &&
(this.scorm.skipview === AddonModScormSkipView.ALWAYS || this.lastAttempt === 0)
)
);
}
@ -241,7 +247,7 @@ export class AddonModScormIndexComponent extends CoreCourseModuleMainActivityCom
this.gradeMethodReadable = AddonModScorm.getScormGradeMethod(scorm);
this.attemptsLeft = AddonModScorm.countAttemptsLeft(scorm, this.attempts.lastAttempt.num);
if (scorm.forcenewattempt === AddonModScormProvider.SCORM_FORCEATTEMPT_ALWAYS ||
if (scorm.forcenewattempt === AddonModScormForceAttempt.ALWAYS ||
(scorm.forcenewattempt && !this.incomplete)) {
this.startNewAttempt = true;
}
@ -550,7 +556,7 @@ export class AddonModScormIndexComponent extends CoreCourseModuleMainActivityCom
// Detect if anything was sent to server.
this.dataSentObserver?.off();
this.dataSentObserver = CoreEvents.on(AddonModScormProvider.DATA_SENT_EVENT, (data) => {
this.dataSentObserver = CoreEvents.on(ADDON_MOD_SCORM_DATA_SENT_EVENT, (data) => {
if (data.scormId === this.scorm?.id) {
this.dataSent = true;
@ -562,10 +568,10 @@ export class AddonModScormIndexComponent extends CoreCourseModuleMainActivityCom
}, this.siteId);
CoreNavigator.navigateToSitePath(
`${AddonModScormModuleHandlerService.PAGE_NAME}/${this.courseId}/${this.module.id}/player`,
`${ADDON_MOD_SCORM_PAGE_NAME}/${this.courseId}/${this.module.id}/player`,
{
params: {
mode: autoPlayData?.mode ?? (preview ? AddonModScormProvider.MODEBROWSE : AddonModScormProvider.MODENORMAL),
mode: autoPlayData?.mode ?? (preview ? AddonModScormMode.BROWSE : AddonModScormMode.NORMAL),
moduleUrl: this.module.url,
newAttempt: autoPlayData?.newAttempt ?? this.startNewAttempt,
organizationId: autoPlayData?.organizationId ?? this.currentOrganization.identifier,
@ -608,7 +614,7 @@ export class AddonModScormIndexComponent extends CoreCourseModuleMainActivityCom
throw new CoreError('Cannot sync without a scorm.');
}
if (CoreSync.isBlocked(AddonModScormProvider.COMPONENT, this.scorm.id) && retries < 5) {
if (CoreSync.isBlocked(ADDON_MOD_SCORM_COMPONENT, this.scorm.id) && retries < 5) {
// Sync is currently blocked, this can happen when SCORM player is left. Retry in a bit.
await CoreUtils.wait(400);

View File

@ -14,8 +14,9 @@
import { Component, Input, OnInit } from '@angular/core';
import { ModalController } from '@singletons';
import { AddonModScormGetScormAccessInformationWSResponse, AddonModScormProvider } from '../../services/scorm';
import { AddonModScormGetScormAccessInformationWSResponse } from '../../services/scorm';
import { AddonModScormTOCScoWithIcon } from '../../services/scorm-helper';
import { AddonModScormMode } from '../../constants';
/**
* Modal to display the TOC of a SCORM.
@ -41,8 +42,8 @@ export class AddonModScormTocComponent implements OnInit {
* @inheritdoc
*/
ngOnInit(): void {
this.isBrowse = this.mode === AddonModScormProvider.MODEBROWSE;
this.isReview = this.mode === AddonModScormProvider.MODEREVIEW;
this.isBrowse = this.mode === AddonModScormMode.BROWSE;
this.isReview = this.mode === AddonModScormMode.REVIEW;
}
/**

View File

@ -0,0 +1,67 @@
// (C) Copyright 2015 Moodle Pty Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
export const ADDON_MOD_SCORM_COMPONENT = 'mmaModScorm';
export const ADDON_MOD_SCORM_PAGE_NAME = 'mod_scorm';
// Public constants.
/**
* Grading method.
* The grading method defines how the grade for a single attempt of the activity is determined.
*/
export const enum AddonModScormGradingMethod {
GRADESCOES = 0,
GRADEHIGHEST = 1,
GRADEAVERAGE = 2,
GRADESUM = 3,
}
/**
* Attempts grading methods.
* If multiple attempts are allowed, this setting specifies whether the highest, average (mean), first or last completed attempt
* is recorded in the gradebook.
*/
export const enum AddonModScormAttemptsGradingMethod {
HIGHESTATTEMPT = 0,
AVERAGEATTEMPT = 1,
FIRSTATTEMPT = 2,
LASTATTEMPT = 3,
}
export const enum AddonModScormMode {
BROWSE = 'browse',
NORMAL = 'normal',
REVIEW = 'review',
}
export const enum AddonModScormForceAttempt {
NO = 0,
ONCOMPLETE = 1,
ALWAYS = 2,
}
export const enum AddonModScormSkipView {
NEVER = 0,
FIRST = 1,
ALWAYS = 2,
}
// Events.
export const ADDON_MOD_SCORM_LAUNCH_NEXT_SCO_EVENT = 'addon_mod_scorm_launch_next_sco';
export const ADDON_MOD_SCORM_LAUNCH_PREV_SCO_EVENT = 'addon_mod_scorm_launch_prev_sco';
export const ADDON_MOD_SCORM_UPDATE_TOC_EVENT = 'addon_mod_scorm_update_toc';
export const ADDON_MOD_SCORM_GO_OFFLINE_EVENT = 'addon_mod_scorm_go_offline';
export const ADDON_MOD_SCORM_DATA_SENT_EVENT = 'addon_mod_scorm_data_sent';
export const ADDON_MOD_SCORM_DATA_AUTO_SYNCED = 'addon_mod_scorm_autom_synced';

View File

@ -28,7 +28,6 @@ import {
AddonModScorm,
AddonModScormAttemptCountResult,
AddonModScormGetScormAccessInformationWSResponse,
AddonModScormProvider,
AddonModScormScorm,
AddonModScormScoWithData,
AddonModScormUserDataMap,
@ -36,6 +35,14 @@ import {
import { AddonModScormHelper, AddonModScormTOCScoWithIcon } from '../../services/scorm-helper';
import { AddonModScormSync } from '../../services/scorm-sync';
import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics';
import {
ADDON_MOD_SCORM_COMPONENT,
AddonModScormMode,
ADDON_MOD_SCORM_GO_OFFLINE_EVENT,
ADDON_MOD_SCORM_LAUNCH_NEXT_SCO_EVENT,
ADDON_MOD_SCORM_LAUNCH_PREV_SCO_EVENT,
ADDON_MOD_SCORM_UPDATE_TOC_EVENT,
} from '../../constants';
/**
* Page that allows playing a SCORM.
@ -63,7 +70,7 @@ export class AddonModScormPlayerPage implements OnInit, OnDestroy {
navigationItems: CoreNavigationBarItem<AddonModScormTOCScoWithIcon>[] = [];
protected siteId!: string;
protected mode!: string; // Mode to play the SCORM.
protected mode!: AddonModScormMode; // Mode to play the SCORM.
protected moduleUrl!: string; // Module URL.
protected newAttempt = false; // Whether to start a new attempt.
protected organizationId?: string; // Organization ID to load.
@ -92,7 +99,7 @@ export class AddonModScormPlayerPage implements OnInit, OnDestroy {
try {
this.cmId = CoreNavigator.getRequiredRouteNumberParam('cmId');
this.courseId = CoreNavigator.getRequiredRouteNumberParam('courseId');
this.mode = CoreNavigator.getRouteParam('mode') || AddonModScormProvider.MODENORMAL;
this.mode = CoreNavigator.getRouteParam('mode') || AddonModScormMode.NORMAL;
this.moduleUrl = CoreNavigator.getRouteParam('moduleUrl') || '';
this.newAttempt = !!CoreNavigator.getRouteBooleanParam('newAttempt');
this.organizationId = CoreNavigator.getRouteParam('organizationId');
@ -150,7 +157,7 @@ export class AddonModScormPlayerPage implements OnInit, OnDestroy {
});
// Block the SCORM so it cannot be synchronized.
CoreSync.blockOperation(AddonModScormProvider.COMPONENT, this.scorm.id, 'player');
CoreSync.blockOperation(ADDON_MOD_SCORM_COMPONENT, this.scorm.id, 'player');
// We use SCORM name at start, later we'll use the SCO title.
this.title = this.scorm.name;
@ -169,7 +176,7 @@ export class AddonModScormPlayerPage implements OnInit, OnDestroy {
}
// Listen for events to update the TOC, navigate through SCOs and go offline.
this.tocObserver = CoreEvents.on(AddonModScormProvider.UPDATE_TOC_EVENT, (data) => {
this.tocObserver = CoreEvents.on(ADDON_MOD_SCORM_UPDATE_TOC_EVENT, (data) => {
if (data.scormId !== this.scorm.id) {
return;
}
@ -182,7 +189,7 @@ export class AddonModScormPlayerPage implements OnInit, OnDestroy {
}
}, this.siteId);
this.launchNextObserver = CoreEvents.on(AddonModScormProvider.LAUNCH_NEXT_SCO_EVENT, (data) => {
this.launchNextObserver = CoreEvents.on(ADDON_MOD_SCORM_LAUNCH_NEXT_SCO_EVENT, (data) => {
if (data.scormId === this.scorm.id && this.currentSco) {
const nextSco = AddonModScormHelper.getNextScoFromToc(this.toc, this.currentSco.id);
if (nextSco) {
@ -191,7 +198,7 @@ export class AddonModScormPlayerPage implements OnInit, OnDestroy {
}
}, this.siteId);
this.launchPrevObserver = CoreEvents.on(AddonModScormProvider.LAUNCH_PREV_SCO_EVENT, (data) => {
this.launchPrevObserver = CoreEvents.on(ADDON_MOD_SCORM_LAUNCH_PREV_SCO_EVENT, (data) => {
if (data.scormId === this.scorm.id && this.currentSco) {
const previousSco = AddonModScormHelper.getPreviousScoFromToc(this.toc, this.currentSco.id);
if (previousSco) {
@ -200,7 +207,7 @@ export class AddonModScormPlayerPage implements OnInit, OnDestroy {
}
}, this.siteId);
this.goOfflineObserver = CoreEvents.on(AddonModScormProvider.GO_OFFLINE_EVENT, (data) => {
this.goOfflineObserver = CoreEvents.on(ADDON_MOD_SCORM_GO_OFFLINE_EVENT, (data) => {
if (data.scormId !== this.scorm.id || this.offline) {
return;
}
@ -605,7 +612,7 @@ export class AddonModScormPlayerPage implements OnInit, OnDestroy {
}, 500);
// Unblock the SCORM so it can be synced.
CoreSync.unblockOperation(AddonModScormProvider.COMPONENT, this.scorm.id, 'player');
CoreSync.unblockOperation(ADDON_MOD_SCORM_COMPONENT, this.scorm.id, 'player');
}
}

View File

@ -42,4 +42,4 @@ const routes: Routes = [
AddonModScormPlayerPage,
],
})
export class AddonModScormLazyModule {}
export default class AddonModScormLazyModule {}

View File

@ -26,17 +26,17 @@ import { OFFLINE_SITE_SCHEMA } from './services/database/scorm';
import { AddonModScormGradeLinkHandler } from './services/handlers/grade-link';
import { AddonModScormIndexLinkHandler } from './services/handlers/index-link';
import { AddonModScormListLinkHandler } from './services/handlers/list-link';
import { AddonModScormModuleHandler, AddonModScormModuleHandlerService } from './services/handlers/module';
import { AddonModScormModuleHandler } from './services/handlers/module';
import { AddonModScormPlayerLinkHandler } from './services/handlers/player-link';
import { AddonModScormPluginFileHandler } from './services/handlers/pluginfile';
import { AddonModScormPrefetchHandler } from './services/handlers/prefetch';
import { AddonModScormSyncCronHandler } from './services/handlers/sync-cron';
import { AddonModScormProvider } from './services/scorm';
import { ADDON_MOD_SCORM_COMPONENT, ADDON_MOD_SCORM_PAGE_NAME } from './constants';
const routes: Routes = [
{
path: AddonModScormModuleHandlerService.PAGE_NAME,
loadChildren: () => import('./scorm-lazy.module').then(m => m.AddonModScormLazyModule),
path: ADDON_MOD_SCORM_PAGE_NAME,
loadChildren: () => import('./scorm-lazy.module'),
},
];
@ -63,7 +63,7 @@ const routes: Routes = [
CoreContentLinksDelegate.registerHandler(AddonModScormPlayerLinkHandler.instance);
CorePluginFileDelegate.registerHandler(AddonModScormPluginFileHandler.instance);
CoreCourseHelper.registerModuleReminderClick(AddonModScormProvider.COMPONENT);
CoreCourseHelper.registerModuleReminderClick(ADDON_MOD_SCORM_COMPONENT);
},
},
],

View File

@ -17,6 +17,7 @@ import { Injectable, Type } from '@angular/core';
import { CoreModuleHandlerBase } from '@features/course/classes/module-base-handler';
import { CoreCourseModuleHandler } from '@features/course/services/module-delegate';
import { makeSingleton } from '@singletons';
import { ADDON_MOD_SCORM_PAGE_NAME } from '../../constants';
/**
* Handler to support SCORM modules.
@ -24,11 +25,9 @@ import { makeSingleton } from '@singletons';
@Injectable({ providedIn: 'root' })
export class AddonModScormModuleHandlerService extends CoreModuleHandlerBase implements CoreCourseModuleHandler {
static readonly PAGE_NAME = 'mod_scorm';
name = 'AddonModScorm';
modName = 'scorm';
protected pageName = AddonModScormModuleHandlerService.PAGE_NAME;
protected pageName = ADDON_MOD_SCORM_PAGE_NAME;
supportedFeatures = {
[CoreConstants.FEATURE_GROUPS]: true,

View File

@ -24,8 +24,9 @@ import { CoreSites, CoreSitesReadingStrategy } from '@services/sites';
import { CoreUtils } from '@services/utils/utils';
import { CoreWSFile } from '@services/ws';
import { makeSingleton, Translate } from '@singletons';
import { AddonModScorm, AddonModScormProvider, AddonModScormScorm } from '../scorm';
import { AddonModScorm, AddonModScormScorm } from '../scorm';
import { AddonModScormSync } from '../scorm-sync';
import { ADDON_MOD_SCORM_COMPONENT } from '../../constants';
/**
* Handler to prefetch SCORMs.
@ -35,7 +36,7 @@ export class AddonModScormPrefetchHandlerService extends CoreCourseActivityPrefe
name = 'AddonModScorm';
modName = 'scorm';
component = AddonModScormProvider.COMPONENT;
component = ADDON_MOD_SCORM_COMPONENT;
updatesNames = /^configuration$|^.*files$|^tracks$/;
/**

View File

@ -25,7 +25,6 @@ import {
AddonModScormAttemptCountResult,
AddonModScormDataValue,
AddonModScormGetScosWithDataOptions,
AddonModScormProvider,
AddonModScormScoIcon,
AddonModScormScorm,
AddonModScormScoWithData,
@ -33,6 +32,7 @@ import {
AddonModScormUserDataMap,
} from './scorm';
import { AddonModScormOffline } from './scorm-offline';
import { AddonModScormMode } from '../constants';
// List of elements we want to ignore when copying attempts (they're calculated).
const elementsToIgnore = [
@ -229,8 +229,8 @@ export class AddonModScormHelperProvider {
options: AddonModScormGetFirstScoOptions = {},
): Promise<AddonModScormScoWithData | undefined> {
const mode = options.mode || AddonModScormProvider.MODENORMAL;
const isNormalMode = mode === AddonModScormProvider.MODENORMAL;
const mode = options.mode || AddonModScormMode.NORMAL;
const isNormalMode = mode === AddonModScormMode.NORMAL;
let scos = options.toc;
if (!scos || !scos.length) {

View File

@ -35,7 +35,6 @@ import {
import {
AddonModScormDataEntry,
AddonModScormDataValue,
AddonModScormProvider,
AddonModScormScorm,
AddonModScormScoUserData,
AddonModScormUserDataMap,
@ -45,6 +44,7 @@ import { lazyMap, LazyMap } from '@/core/utils/lazy-map';
import { asyncInstance, AsyncInstance } from '@/core/utils/async-instance';
import { CoreDatabaseTable } from '@classes/database/database-table';
import { CoreDatabaseCachingStrategy } from '@classes/database/database-table-proxy';
import { ADDON_MOD_SCORM_COMPONENT } from '../constants';
/**
* Service to handle offline SCORM.
@ -120,7 +120,7 @@ export class AddonModScormOfflineProvider {
this.logger.debug(`Change attempt number from ${attempt} to ${newAttempt} in SCORM ${scormId}`);
// Block the SCORM so it can't be synced.
CoreSync.blockOperation(AddonModScormProvider.COMPONENT, scormId, 'changeAttemptNumber', site.id);
CoreSync.blockOperation(ADDON_MOD_SCORM_COMPONENT, scormId, 'changeAttemptNumber', site.id);
try {
const currentAttemptConditions = {
@ -161,7 +161,7 @@ export class AddonModScormOfflineProvider {
}
} finally {
// Unblock the SCORM.
CoreSync.unblockOperation(AddonModScormProvider.COMPONENT, scormId, 'changeAttemptNumber', site.id);
CoreSync.unblockOperation(ADDON_MOD_SCORM_COMPONENT, scormId, 'changeAttemptNumber', site.id);
}
}
@ -191,7 +191,7 @@ export class AddonModScormOfflineProvider {
this.logger.debug(`Creating new offline attempt ${attempt} in SCORM ${scorm.id}`);
// Block the SCORM so it can't be synced.
CoreSync.blockOperation(AddonModScormProvider.COMPONENT, scorm.id, 'createNewAttempt', site.id);
CoreSync.blockOperation(ADDON_MOD_SCORM_COMPONENT, scorm.id, 'createNewAttempt', site.id);
// Create attempt in DB.
const entry: AddonModScormAttemptDBRecord = {
@ -230,7 +230,7 @@ export class AddonModScormOfflineProvider {
await Promise.all(promises);
} finally {
// Unblock the SCORM.
CoreSync.unblockOperation(AddonModScormProvider.COMPONENT, scorm.id, 'createNewAttempt', site.id);
CoreSync.unblockOperation(ADDON_MOD_SCORM_COMPONENT, scorm.id, 'createNewAttempt', site.id);
}
}
@ -872,7 +872,7 @@ export class AddonModScormOfflineProvider {
userId = userId || site.getUserId();
// Block the SCORM so it can't be synced.
CoreSync.blockOperation(AddonModScormProvider.COMPONENT, scorm.id, 'saveTracksOffline', siteId);
CoreSync.blockOperation(ADDON_MOD_SCORM_COMPONENT, scorm.id, 'saveTracksOffline', siteId);
try {
// Insert all the tracks.
@ -889,7 +889,7 @@ export class AddonModScormOfflineProvider {
)));
} finally {
// Unblock the SCORM operation.
CoreSync.unblockOperation(AddonModScormProvider.COMPONENT, scorm.id, 'saveTracksOffline', siteId);
CoreSync.unblockOperation(ADDON_MOD_SCORM_COMPONENT, scorm.id, 'saveTracksOffline', siteId);
}
}

View File

@ -27,11 +27,11 @@ import {
AddonModScorm,
AddonModScormAttemptCountResult,
AddonModScormDataEntry,
AddonModScormProvider,
AddonModScormScorm,
AddonModScormUserDataMap,
} from './scorm';
import { AddonModScormOffline } from './scorm-offline';
import { ADDON_MOD_SCORM_COMPONENT, ADDON_MOD_SCORM_DATA_AUTO_SYNCED } from '../constants';
/**
* Service to sync SCORMs.
@ -39,8 +39,6 @@ import { AddonModScormOffline } from './scorm-offline';
@Injectable({ providedIn: 'root' })
export class AddonModScormSyncProvider extends CoreCourseActivitySyncBaseProvider<AddonModScormSyncResult> {
static readonly AUTO_SYNCED = 'addon_mod_scorm_autom_synced';
protected componentTranslatableString = 'scorm';
constructor() {
@ -464,7 +462,7 @@ export class AddonModScormSyncProvider extends CoreCourseActivitySyncBaseProvide
// Sync all SCORMs that haven't been synced for a while and that aren't attempted right now.
await Promise.all(attempts.map(async (attempt) => {
if (treated[attempt.scormid] || CoreSync.isBlocked(AddonModScormProvider.COMPONENT, attempt.scormid, siteId)) {
if (treated[attempt.scormid] || CoreSync.isBlocked(ADDON_MOD_SCORM_COMPONENT, attempt.scormid, siteId)) {
return;
}
@ -478,7 +476,7 @@ export class AddonModScormSyncProvider extends CoreCourseActivitySyncBaseProvide
if (data !== undefined) {
// We tried to sync. Send event.
CoreEvents.trigger(AddonModScormSyncProvider.AUTO_SYNCED, {
CoreEvents.trigger(ADDON_MOD_SCORM_DATA_AUTO_SYNCED, {
scormId: scorm.id,
attemptFinished: data.attemptFinished,
warnings: data.warnings,
@ -586,7 +584,7 @@ export class AddonModScormSyncProvider extends CoreCourseActivitySyncBaseProvide
}
// Verify that SCORM isn't blocked.
if (CoreSync.isBlocked(AddonModScormProvider.COMPONENT, scorm.id, siteId)) {
if (CoreSync.isBlocked(ADDON_MOD_SCORM_COMPONENT, scorm.id, siteId)) {
this.logger.debug('Cannot sync SCORM ' + scorm.id + ' because it is blocked.');
throw new CoreError(Translate.instant('core.errorsyncblocked', { $a: this.componentTranslate }));
@ -612,7 +610,7 @@ export class AddonModScormSyncProvider extends CoreCourseActivitySyncBaseProvide
let lastOnlineWasFinished = false;
// Sync offline logs.
await CoreUtils.ignoreErrors(CoreCourseLogHelper.syncActivity(AddonModScormProvider.COMPONENT, scorm.id, siteId));
await CoreUtils.ignoreErrors(CoreCourseLogHelper.syncActivity(ADDON_MOD_SCORM_COMPONENT, scorm.id, siteId));
// Get attempts data. We ignore cache for online attempts, so this call will fail if offline or server down.
const attemptsData = await AddonModScorm.getAttemptCount(scorm.id, {

View File

@ -30,8 +30,21 @@ import { makeSingleton, Translate } from '@singletons';
import { CoreEvents } from '@singletons/events';
import { CorePath } from '@singletons/path';
import { AddonModScormOffline } from './scorm-offline';
import { AddonModScormAutoSyncEventData, AddonModScormSyncProvider } from './scorm-sync';
import { AddonModScormAutoSyncEventData } from './scorm-sync';
import { CoreSiteWSPreSets } from '@classes/sites/authenticated-site';
import {
ADDON_MOD_SCORM_COMPONENT,
AddonModScormForceAttempt,
AddonModScormGradingMethod,
AddonModScormMode,
AddonModScormAttemptsGradingMethod,
ADDON_MOD_SCORM_DATA_SENT_EVENT,
ADDON_MOD_SCORM_GO_OFFLINE_EVENT,
ADDON_MOD_SCORM_LAUNCH_NEXT_SCO_EVENT,
ADDON_MOD_SCORM_LAUNCH_PREV_SCO_EVENT,
ADDON_MOD_SCORM_UPDATE_TOC_EVENT,
ADDON_MOD_SCORM_DATA_AUTO_SYNCED,
} from '../constants';
// Private constants.
const VALID_STATUSES = ['notattempted', 'passed', 'completed', 'failed', 'incomplete', 'browsed', 'suspend'];
@ -65,7 +78,6 @@ const STATUS_TO_ICON = {
suspend: 'fas-pause',
wait: 'far-clock',
};
const ROOT_CACHE_KEY = 'mmaModScorm:';
/**
* Service that provides some features for SCORM.
@ -73,37 +85,7 @@ const ROOT_CACHE_KEY = 'mmaModScorm:';
@Injectable({ providedIn: 'root' })
export class AddonModScormProvider {
static readonly COMPONENT = 'mmaModScorm';
// Public constants.
static readonly GRADESCOES = 0;
static readonly GRADEHIGHEST = 1;
static readonly GRADEAVERAGE = 2;
static readonly GRADESUM = 3;
static readonly HIGHESTATTEMPT = 0;
static readonly AVERAGEATTEMPT = 1;
static readonly FIRSTATTEMPT = 2;
static readonly LASTATTEMPT = 3;
static readonly MODEBROWSE = 'browse';
static readonly MODENORMAL = 'normal';
static readonly MODEREVIEW = 'review';
static readonly SCORM_FORCEATTEMPT_NO = 0;
static readonly SCORM_FORCEATTEMPT_ONCOMPLETE = 1;
static readonly SCORM_FORCEATTEMPT_ALWAYS = 2;
static readonly SKIPVIEW_NEVER = 0;
static readonly SKIPVIEW_FIRST = 1;
static readonly SKIPVIEW_ALWAYS = 2;
// Events.
static readonly LAUNCH_NEXT_SCO_EVENT = 'addon_mod_scorm_launch_next_sco';
static readonly LAUNCH_PREV_SCO_EVENT = 'addon_mod_scorm_launch_prev_sco';
static readonly UPDATE_TOC_EVENT = 'addon_mod_scorm_update_toc';
static readonly GO_OFFLINE_EVENT = 'addon_mod_scorm_go_offline';
static readonly DATA_SENT_EVENT = 'addon_mod_scorm_data_sent';
protected static readonly ROOT_CACHE_KEY = 'mmaModScorm:';
/**
* Calculates the SCORM grade based on the grading method and the list of attempts scores.
@ -119,10 +101,10 @@ export class AddonModScormProvider {
}
switch (scorm.whatgrade) {
case AddonModScormProvider.FIRSTATTEMPT:
case AddonModScormAttemptsGradingMethod.FIRSTATTEMPT:
return onlineAttempts[1] ? onlineAttempts[1].score : -1;
case AddonModScormProvider.LASTATTEMPT: {
case AddonModScormAttemptsGradingMethod.LASTATTEMPT: {
// Search the last completed attempt number.
let lastCompleted = 0;
for (const attemptNumber in onlineAttempts) {
@ -141,7 +123,7 @@ export class AddonModScormProvider {
return -1;
}
case AddonModScormProvider.HIGHESTATTEMPT: {
case AddonModScormAttemptsGradingMethod.HIGHESTATTEMPT: {
// Search the highest grade.
let grade = 0;
for (const attemptNumber in onlineAttempts) {
@ -151,7 +133,7 @@ export class AddonModScormProvider {
return grade;
}
case AddonModScormProvider.AVERAGEATTEMPT: {
case AddonModScormAttemptsGradingMethod.AVERAGEATTEMPT: {
// Calculate the average.
let sumGrades = 0;
let total = 0;
@ -217,24 +199,24 @@ export class AddonModScormProvider {
*/
determineAttemptAndMode(
scorm: AddonModScormScorm,
mode: string,
mode: AddonModScormMode,
attempt: number,
newAttempt?: boolean,
incomplete?: boolean,
canSaveTracks = true,
): {mode: string; attempt: number; newAttempt: boolean} {
): {mode: AddonModScormMode; attempt: number; newAttempt: boolean} {
if (!canSaveTracks) {
return {
mode: scorm.hidebrowse ? AddonModScormProvider.MODENORMAL : mode,
mode: scorm.hidebrowse ? AddonModScormMode.NORMAL : mode,
attempt,
newAttempt: false,
};
}
if (mode == AddonModScormProvider.MODEBROWSE) {
if (mode == AddonModScormMode.BROWSE) {
if (scorm.hidebrowse) {
// Prevent Browse mode if hidebrowse is set.
mode = AddonModScormProvider.MODENORMAL;
mode = AddonModScormMode.NORMAL;
} else {
// We don't need to check attempts as browse mode is set.
if (attempt == 0) {
@ -250,10 +232,10 @@ export class AddonModScormProvider {
}
}
if (scorm.forcenewattempt == AddonModScormProvider.SCORM_FORCEATTEMPT_ALWAYS) {
if (scorm.forcenewattempt === AddonModScormForceAttempt.ALWAYS) {
// This SCORM is configured to force a new attempt on every re-entry.
return {
mode: AddonModScormProvider.MODENORMAL,
mode: AddonModScormMode.NORMAL,
attempt: attempt + 1,
newAttempt: true,
};
@ -273,14 +255,14 @@ export class AddonModScormProvider {
if (newAttempt && (!scorm.maxattempt || attempt < scorm.maxattempt)) {
// Create a new attempt. Force mode normal.
attempt++;
mode = AddonModScormProvider.MODENORMAL;
mode = AddonModScormMode.NORMAL;
} else {
if (incomplete) {
// We can't review an incomplete attempt.
mode = AddonModScormProvider.MODENORMAL;
mode = AddonModScormMode.NORMAL;
} else {
// We aren't starting a new attempt and the current one is complete, force review mode.
mode = AddonModScormProvider.MODEREVIEW;
mode = AddonModScormMode.REVIEW;
}
}
@ -415,7 +397,7 @@ export class AddonModScormProvider {
return Translate.instant('core.none');
}
if (scorm.grademethod !== AddonModScormProvider.GRADESCOES && scorm.maxgrade) {
if (scorm.grademethod !== AddonModScormGradingMethod.GRADESCOES && scorm.maxgrade) {
grade = (grade / scorm.maxgrade) * 100;
return Translate.instant('core.percentagenumber', { $a: CoreTextUtils.roundToDecimals(grade, 2) });
@ -473,7 +455,7 @@ export class AddonModScormProvider {
};
const preSets: CoreSiteWSPreSets = {
cacheKey: this.getAccessInformationCacheKey(scormId),
component: AddonModScormProvider.COMPONENT,
component: ADDON_MOD_SCORM_COMPONENT,
componentId: options.cmId,
...CoreSites.getReadingStrategyPreSets(options.readingStrategy), // Include reading strategy preSets.
};
@ -488,7 +470,7 @@ export class AddonModScormProvider {
* @returns Cache key.
*/
protected getAccessInformationCacheKey(scormId: number): string {
return ROOT_CACHE_KEY + 'accessInfo:' + scormId;
return AddonModScormProvider.ROOT_CACHE_KEY + 'accessInfo:' + scormId;
}
/**
@ -558,7 +540,7 @@ export class AddonModScormProvider {
* @returns Cache key.
*/
protected getAttemptCountCacheKey(scormId: number, userId: number): string {
return ROOT_CACHE_KEY + 'attemptcount:' + scormId + ':' + userId;
return AddonModScormProvider.ROOT_CACHE_KEY + 'attemptcount:' + scormId + ':' + userId;
}
/**
@ -580,7 +562,7 @@ export class AddonModScormProvider {
const preSets: CoreSiteWSPreSets = {
cacheKey: this.getAttemptCountCacheKey(scormId, userId),
updateFrequency: CoreSite.FREQUENCY_SOMETIMES,
component: AddonModScormProvider.COMPONENT,
component: ADDON_MOD_SCORM_COMPONENT,
componentId: options.cmId,
...CoreSites.getReadingStrategyPreSets(options.readingStrategy), // Include reading strategy preSets.
};
@ -641,11 +623,11 @@ export class AddonModScormProvider {
let score = 0;
switch (scorm.grademethod) {
case AddonModScormProvider.GRADEHIGHEST:
case AddonModScormGradingMethod.GRADEHIGHEST:
score = attemptScore.max;
break;
case AddonModScormProvider.GRADEAVERAGE:
case AddonModScormGradingMethod.GRADEAVERAGE:
if (attemptScore.values > 0) {
score = attemptScore.sum / attemptScore.values;
} else {
@ -653,11 +635,11 @@ export class AddonModScormProvider {
}
break;
case AddonModScormProvider.GRADESUM:
case AddonModScormGradingMethod.GRADESUM:
score = attemptScore.sum;
break;
case AddonModScormProvider.GRADESCOES:
case AddonModScormGradingMethod.GRADESCOES:
score = attemptScore.scos;
break;
@ -797,7 +779,7 @@ export class AddonModScormProvider {
* @returns Cache key.
*/
protected getScormUserDataCommonCacheKey(scormId: number): string {
return ROOT_CACHE_KEY + 'userdata:' + scormId;
return AddonModScormProvider.ROOT_CACHE_KEY + 'userdata:' + scormId;
}
/**
@ -821,7 +803,7 @@ export class AddonModScormProvider {
};
const preSets: CoreSiteWSPreSets = {
cacheKey: this.getScormUserDataCacheKey(scormId, attempt),
component: AddonModScormProvider.COMPONENT,
component: ADDON_MOD_SCORM_COMPONENT,
componentId: options.cmId,
...CoreSites.getReadingStrategyPreSets(options.readingStrategy), // Include reading strategy preSets.
};
@ -854,7 +836,7 @@ export class AddonModScormProvider {
* @returns Cache key.
*/
protected getScosCacheKey(scormId: number): string {
return ROOT_CACHE_KEY + 'scos:' + scormId;
return AddonModScormProvider.ROOT_CACHE_KEY + 'scos:' + scormId;
}
/**
@ -876,7 +858,7 @@ export class AddonModScormProvider {
const preSets: CoreSiteWSPreSets = {
cacheKey: this.getScosCacheKey(scormId),
updateFrequency: CoreSite.FREQUENCY_SOMETIMES,
component: AddonModScormProvider.COMPONENT,
component: ADDON_MOD_SCORM_COMPONENT,
componentId: options.cmId,
...CoreSites.getReadingStrategyPreSets(options.readingStrategy), // Include reading strategy preSets.
};
@ -1091,7 +1073,7 @@ export class AddonModScormProvider {
* @returns Cache key.
*/
protected getScormDataCacheKey(courseId: number): string {
return ROOT_CACHE_KEY + 'scorm:' + courseId;
return AddonModScormProvider.ROOT_CACHE_KEY + 'scorm:' + courseId;
}
/**
@ -1118,7 +1100,7 @@ export class AddonModScormProvider {
const preSets: CoreSiteWSPreSets = {
cacheKey: this.getScormDataCacheKey(courseId),
updateFrequency: CoreSite.FREQUENCY_RARELY,
component: AddonModScormProvider.COMPONENT,
component: ADDON_MOD_SCORM_COMPONENT,
...CoreSites.getReadingStrategyPreSets(options.readingStrategy), // Include reading strategy preSets.
};
@ -1185,16 +1167,16 @@ export class AddonModScormProvider {
getScormGradeMethod(scorm: AddonModScormScorm): string {
if (scorm.maxattempt == 1) {
switch (scorm.grademethod) {
case AddonModScormProvider.GRADEHIGHEST:
case AddonModScormGradingMethod.GRADEHIGHEST:
return Translate.instant('addon.mod_scorm.gradehighest');
case AddonModScormProvider.GRADEAVERAGE:
case AddonModScormGradingMethod.GRADEAVERAGE:
return Translate.instant('addon.mod_scorm.gradeaverage');
case AddonModScormProvider.GRADESUM:
case AddonModScormGradingMethod.GRADESUM:
return Translate.instant('addon.mod_scorm.gradesum');
case AddonModScormProvider.GRADESCOES:
case AddonModScormGradingMethod.GRADESCOES:
return Translate.instant('addon.mod_scorm.gradescoes');
default:
return '';
@ -1202,16 +1184,16 @@ export class AddonModScormProvider {
}
switch (scorm.whatgrade) {
case AddonModScormProvider.HIGHESTATTEMPT:
case AddonModScormAttemptsGradingMethod.HIGHESTATTEMPT:
return Translate.instant('addon.mod_scorm.highestattempt');
case AddonModScormProvider.AVERAGEATTEMPT:
case AddonModScormAttemptsGradingMethod.AVERAGEATTEMPT:
return Translate.instant('addon.mod_scorm.averageattempt');
case AddonModScormProvider.FIRSTATTEMPT:
case AddonModScormAttemptsGradingMethod.FIRSTATTEMPT:
return Translate.instant('addon.mod_scorm.firstattempt');
case AddonModScormProvider.LASTATTEMPT:
case AddonModScormAttemptsGradingMethod.LASTATTEMPT:
return Translate.instant('addon.mod_scorm.lastattempt');
default:
return '';
@ -1279,7 +1261,7 @@ export class AddonModScormProvider {
await Promise.all([
this.invalidateAllScormData(scorm.id, siteId, userId),
CoreFilepool.invalidateFilesByComponent(siteId, AddonModScormProvider.COMPONENT, moduleId, true),
CoreFilepool.invalidateFilesByComponent(siteId, ADDON_MOD_SCORM_COMPONENT, moduleId, true),
]);
}
@ -1455,7 +1437,7 @@ export class AddonModScormProvider {
return CoreCourseLogHelper.log(
'mod_scorm_launch_sco',
params,
AddonModScormProvider.COMPONENT,
ADDON_MOD_SCORM_COMPONENT,
scormId,
siteId,
);
@ -1476,7 +1458,7 @@ export class AddonModScormProvider {
return CoreCourseLogHelper.log(
'mod_scorm_view_scorm',
params,
AddonModScormProvider.COMPONENT,
ADDON_MOD_SCORM_COMPONENT,
id,
siteId,
);
@ -1518,7 +1500,7 @@ export class AddonModScormProvider {
// Tracks have been saved, update cached user data.
this.updateUserDataAfterSave(scorm.id, attempt, tracks, { cmId: scorm.coursemodule, siteId });
CoreEvents.trigger(AddonModScormProvider.DATA_SENT_EVENT, {
CoreEvents.trigger(ADDON_MOD_SCORM_DATA_SENT_EVENT, {
scormId: scorm.id,
scoId: scoId,
attempt: attempt,
@ -1554,14 +1536,14 @@ export class AddonModScormProvider {
tracks: tracks,
};
CoreSync.blockOperation(AddonModScormProvider.COMPONENT, scormId, 'saveTracksOnline', site.id);
CoreSync.blockOperation(ADDON_MOD_SCORM_COMPONENT, scormId, 'saveTracksOnline', site.id);
try {
const response = await site.write<AddonModScormInsertScormTracksWSResponse>('mod_scorm_insert_scorm_tracks', params);
return response.trackids;
} finally {
CoreSync.unblockOperation(AddonModScormProvider.COMPONENT, scormId, 'saveTracksOnline', site.id);
CoreSync.unblockOperation(ADDON_MOD_SCORM_COMPONENT, scormId, 'saveTracksOnline', site.id);
}
}
@ -1596,7 +1578,7 @@ export class AddonModScormProvider {
// Tracks have been saved, update cached user data.
this.updateUserDataAfterSave(scorm.id, attempt, tracks, { cmId: scorm.coursemodule });
CoreEvents.trigger(AddonModScormProvider.DATA_SENT_EVENT, {
CoreEvents.trigger(ADDON_MOD_SCORM_DATA_SENT_EVENT, {
scormId: scorm.id,
scoId: scoId,
attempt: attempt,
@ -1658,7 +1640,7 @@ export class AddonModScormProvider {
async shouldDownloadMainFile(scorm: AddonModScormScorm, isOutdated?: boolean, siteId?: string): Promise<boolean> {
siteId = siteId || CoreSites.getCurrentSiteId();
const component = AddonModScormProvider.COMPONENT;
const component = ADDON_MOD_SCORM_COMPONENT;
if (isOutdated === undefined) {
// Calculate if it's outdated.
@ -1916,8 +1898,8 @@ export type AddonModScormScormWSData = {
packageurl?: string; // SCORM zip package URL.
version?: string; // SCORM version (SCORM_12, SCORM_13, SCORM_AICC).
maxgrade?: number; // Max grade.
grademethod?: number; // Grade method.
whatgrade?: number; // What grade.
grademethod?: AddonModScormGradingMethod; // Grade method.
whatgrade?: AddonModScormAttemptsGradingMethod; // What grade.
maxattempt?: number; // Maximum number of attemtps.
forcecompleted?: boolean; // Status current attempt is forced to "completed".
forcenewattempt?: number; // Controls re-entry behaviour.
@ -2100,12 +2082,12 @@ declare module '@singletons/events' {
* @see https://www.typescriptlang.org/docs/handbook/declaration-merging.html#module-augmentation
*/
export interface CoreEventsData {
[AddonModScormProvider.LAUNCH_NEXT_SCO_EVENT]: AddonModScormCommonEventData;
[AddonModScormProvider.LAUNCH_PREV_SCO_EVENT]: AddonModScormCommonEventData;
[AddonModScormProvider.UPDATE_TOC_EVENT]: AddonModScormCommonEventData;
[AddonModScormProvider.GO_OFFLINE_EVENT]: AddonModScormCommonEventData;
[AddonModScormProvider.DATA_SENT_EVENT]: AddonModScormCommonEventData;
[AddonModScormSyncProvider.AUTO_SYNCED]: AddonModScormAutoSyncEventData;
[ADDON_MOD_SCORM_LAUNCH_NEXT_SCO_EVENT]: AddonModScormCommonEventData;
[ADDON_MOD_SCORM_LAUNCH_PREV_SCO_EVENT]: AddonModScormCommonEventData;
[ADDON_MOD_SCORM_UPDATE_TOC_EVENT]: AddonModScormCommonEventData;
[ADDON_MOD_SCORM_GO_OFFLINE_EVENT]: AddonModScormCommonEventData;
[ADDON_MOD_SCORM_DATA_SENT_EVENT]: AddonModScormCommonEventData;
[ADDON_MOD_SCORM_DATA_AUTO_SYNCED]: AddonModScormAutoSyncEventData;
}
}