jclic 2.1.21 → 2.1.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +4 -0
- package/dist/jclic-node.js +1 -1
- package/dist/jclic-node.js.map +1 -1
- package/dist/jclic.min.js +2 -2
- package/dist/jclic.min.js.map +1 -1
- package/package.json +1 -1
- package/src/GlobalData.js +1 -1
- package/dist/1078.jclic-node.js +0 -282
- package/dist/1078.jclic-node.js.map +0 -1
- package/dist/1196.jclic-node.js +0 -808
- package/dist/1196.jclic-node.js.map +0 -1
- package/dist/1253.jclic-node.js +0 -1432
- package/dist/1253.jclic-node.js.map +0 -1
- package/dist/13.jclic-node.js +0 -103
- package/dist/13.jclic-node.js.map +0 -1
- package/dist/1567.jclic-node.js +0 -2313
- package/dist/1567.jclic-node.js.map +0 -1
- package/dist/1588.jclic-node.js +0 -602
- package/dist/1588.jclic-node.js.map +0 -1
- package/dist/1725.jclic-node.js +0 -836
- package/dist/1725.jclic-node.js.map +0 -1
- package/dist/1731.jclic-node.js +0 -438
- package/dist/1731.jclic-node.js.map +0 -1
- package/dist/1842.jclic-node.js +0 -651
- package/dist/1842.jclic-node.js.map +0 -1
- package/dist/2160.jclic-node.js +0 -1016
- package/dist/2160.jclic-node.js.map +0 -1
- package/dist/222.jclic-node.js +0 -129
- package/dist/222.jclic-node.js.map +0 -1
- package/dist/2316.jclic-node.js +0 -949
- package/dist/2316.jclic-node.js.map +0 -1
- package/dist/2355.jclic-node.js +0 -371
- package/dist/2355.jclic-node.js.map +0 -1
- package/dist/2366.jclic-node.js +0 -431
- package/dist/2366.jclic-node.js.map +0 -1
- package/dist/2379.jclic-node.js +0 -202
- package/dist/2379.jclic-node.js.map +0 -1
- package/dist/2437.jclic-node.js +0 -450
- package/dist/2437.jclic-node.js.map +0 -1
- package/dist/2531.jclic-node.js +0 -869
- package/dist/2531.jclic-node.js.map +0 -1
- package/dist/2608.jclic-node.js +0 -160
- package/dist/2608.jclic-node.js.map +0 -1
- package/dist/2715.jclic-node.js +0 -554
- package/dist/2715.jclic-node.js.map +0 -1
- package/dist/277.jclic-node.js +0 -22
- package/dist/277.jclic-node.js.map +0 -1
- package/dist/2921.jclic-node.js +0 -660
- package/dist/2921.jclic-node.js.map +0 -1
- package/dist/2952.jclic-node.js +0 -101
- package/dist/2952.jclic-node.js.map +0 -1
- package/dist/3018.jclic-node.js +0 -421
- package/dist/3018.jclic-node.js.map +0 -1
- package/dist/3019.jclic-node.js +0 -682
- package/dist/3019.jclic-node.js.map +0 -1
- package/dist/3231.jclic-node.js +0 -274
- package/dist/3231.jclic-node.js.map +0 -1
- package/dist/331.jclic-node.js +0 -115
- package/dist/331.jclic-node.js.map +0 -1
- package/dist/3391.jclic-node.js +0 -276
- package/dist/3391.jclic-node.js.map +0 -1
- package/dist/3502.jclic-node.js +0 -671
- package/dist/3502.jclic-node.js.map +0 -1
- package/dist/3653.jclic-node.js +0 -982
- package/dist/3653.jclic-node.js.map +0 -1
- package/dist/371.jclic.min.js +0 -2
- package/dist/371.jclic.min.js.map +0 -1
- package/dist/3856.jclic-node.js +0 -575
- package/dist/3856.jclic-node.js.map +0 -1
- package/dist/4112.jclic-node.js +0 -659
- package/dist/4112.jclic-node.js.map +0 -1
- package/dist/4123.jclic-node.js +0 -910
- package/dist/4123.jclic-node.js.map +0 -1
- package/dist/427.jclic-node.js +0 -894
- package/dist/427.jclic-node.js.map +0 -1
- package/dist/4483.jclic-node.js +0 -327
- package/dist/4483.jclic-node.js.map +0 -1
- package/dist/4548.jclic-node.js +0 -1078
- package/dist/4548.jclic-node.js.map +0 -1
- package/dist/466.jclic-node.js +0 -99
- package/dist/466.jclic-node.js.map +0 -1
- package/dist/485.jclic-node.js +0 -783
- package/dist/485.jclic-node.js.map +0 -1
- package/dist/4921.jclic-node.js +0 -500
- package/dist/4921.jclic-node.js.map +0 -1
- package/dist/5091.jclic-node.js +0 -239
- package/dist/5091.jclic-node.js.map +0 -1
- package/dist/520.jclic-node.js +0 -550
- package/dist/520.jclic-node.js.map +0 -1
- package/dist/5312.jclic-node.js +0 -1126
- package/dist/5312.jclic-node.js.map +0 -1
- package/dist/5338.jclic-node.js +0 -212
- package/dist/5338.jclic-node.js.map +0 -1
- package/dist/5344.jclic-node.js +0 -229
- package/dist/5344.jclic-node.js.map +0 -1
- package/dist/5550.jclic-node.js +0 -238
- package/dist/5550.jclic-node.js.map +0 -1
- package/dist/5626.jclic-node.js +0 -614
- package/dist/5626.jclic-node.js.map +0 -1
- package/dist/5977.jclic-node.js +0 -1081
- package/dist/5977.jclic-node.js.map +0 -1
- package/dist/6148.jclic-node.js +0 -345
- package/dist/6148.jclic-node.js.map +0 -1
- package/dist/6176.jclic-node.js +0 -481
- package/dist/6176.jclic-node.js.map +0 -1
- package/dist/6221.jclic-node.js +0 -1072
- package/dist/6221.jclic-node.js.map +0 -1
- package/dist/6238.jclic-node.js +0 -718
- package/dist/6238.jclic-node.js.map +0 -1
- package/dist/6454.jclic-node.js +0 -1413
- package/dist/6454.jclic-node.js.map +0 -1
- package/dist/6565.jclic-node.js +0 -294
- package/dist/6565.jclic-node.js.map +0 -1
- package/dist/6579.jclic-node.js +0 -719
- package/dist/6579.jclic-node.js.map +0 -1
- package/dist/6715.jclic-node.js +0 -148
- package/dist/6715.jclic-node.js.map +0 -1
- package/dist/6777.jclic-node.js +0 -171
- package/dist/6777.jclic-node.js.map +0 -1
- package/dist/6782.jclic-node.js +0 -1611
- package/dist/6782.jclic-node.js.map +0 -1
- package/dist/6847.jclic-node.js +0 -601
- package/dist/6847.jclic-node.js.map +0 -1
- package/dist/6856.jclic-node.js +0 -252
- package/dist/6856.jclic-node.js.map +0 -1
- package/dist/696.jclic-node.js +0 -1821
- package/dist/696.jclic-node.js.map +0 -1
- package/dist/698.jclic-node.js +0 -583
- package/dist/698.jclic-node.js.map +0 -1
- package/dist/704.jclic-node.js +0 -80
- package/dist/704.jclic-node.js.map +0 -1
- package/dist/7046.jclic-node.js +0 -735
- package/dist/7046.jclic-node.js.map +0 -1
- package/dist/7220.jclic-node.js +0 -156
- package/dist/7220.jclic-node.js.map +0 -1
- package/dist/7257.jclic-node.js +0 -931
- package/dist/7257.jclic-node.js.map +0 -1
- package/dist/743.jclic-node.js +0 -583
- package/dist/743.jclic-node.js.map +0 -1
- package/dist/757.jclic-node.js +0 -1072
- package/dist/757.jclic-node.js.map +0 -1
- package/dist/7781.jclic-node.js +0 -202
- package/dist/7781.jclic-node.js.map +0 -1
- package/dist/7912.jclic-node.js +0 -2103
- package/dist/7912.jclic-node.js.map +0 -1
- package/dist/827.jclic-node.js +0 -708
- package/dist/827.jclic-node.js.map +0 -1
- package/dist/8276.jclic-node.js +0 -409
- package/dist/8276.jclic-node.js.map +0 -1
- package/dist/8322.jclic-node.js +0 -498
- package/dist/8322.jclic-node.js.map +0 -1
- package/dist/8641.jclic-node.js +0 -360
- package/dist/8641.jclic-node.js.map +0 -1
- package/dist/8837.jclic-node.js +0 -651
- package/dist/8837.jclic-node.js.map +0 -1
- package/dist/8895.jclic-node.js +0 -151
- package/dist/8895.jclic-node.js.map +0 -1
- package/dist/9072.jclic-node.js +0 -1285
- package/dist/9072.jclic-node.js.map +0 -1
- package/dist/9078.jclic-node.js +0 -935
- package/dist/9078.jclic-node.js.map +0 -1
- package/dist/9103.jclic-node.js +0 -718
- package/dist/9103.jclic-node.js.map +0 -1
- package/dist/9359.jclic-node.js +0 -145
- package/dist/9359.jclic-node.js.map +0 -1
- package/dist/9409.jclic-node.js +0 -921
- package/dist/9409.jclic-node.js.map +0 -1
- package/dist/9513.jclic-node.js +0 -720
- package/dist/9513.jclic-node.js.map +0 -1
- package/dist/9704.jclic-node.js +0 -81
- package/dist/9704.jclic-node.js.map +0 -1
- package/dist/9950.jclic-node.js +0 -827
- package/dist/9950.jclic-node.js.map +0 -1
package/dist/6782.jclic-node.js
DELETED
|
@@ -1,1611 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
exports.id = 6782;
|
|
3
|
-
exports.ids = [6782,5344,6565,8641];
|
|
4
|
-
exports.modules = {
|
|
5
|
-
|
|
6
|
-
/***/ 5344:
|
|
7
|
-
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
8
|
-
|
|
9
|
-
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
10
|
-
/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
|
|
11
|
-
/* harmony export */ });
|
|
12
|
-
/* unused harmony export Encryption */
|
|
13
|
-
/**
|
|
14
|
-
* File : report/Encryption.js
|
|
15
|
-
* Created : 18/06/2015
|
|
16
|
-
* By : Francesc Busquets <francesc@gmail.com>
|
|
17
|
-
*
|
|
18
|
-
* JClic.js
|
|
19
|
-
* An HTML5 player of JClic activities
|
|
20
|
-
* https://projectestac.github.io/jclic.js
|
|
21
|
-
*
|
|
22
|
-
* @source https://github.com/projectestac/jclic.js
|
|
23
|
-
*
|
|
24
|
-
* @license EUPL-1.2
|
|
25
|
-
* @licstart
|
|
26
|
-
* (c) 2000-2020 Educational Telematic Network of Catalonia (XTEC)
|
|
27
|
-
*
|
|
28
|
-
* Licensed under the EUPL, Version 1.1 or -as soon they will be approved by
|
|
29
|
-
* the European Commission- subsequent versions of the EUPL (the "Licence");
|
|
30
|
-
* You may not use this work except in compliance with the Licence.
|
|
31
|
-
*
|
|
32
|
-
* You may obtain a copy of the Licence at:
|
|
33
|
-
* https://joinup.ec.europa.eu/software/page/eupl
|
|
34
|
-
*
|
|
35
|
-
* Unless required by applicable law or agreed to in writing, software
|
|
36
|
-
* distributed under the Licence is distributed on an "AS IS" basis, WITHOUT
|
|
37
|
-
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
38
|
-
* Licence for the specific language governing permissions and limitations
|
|
39
|
-
* under the Licence.
|
|
40
|
-
* @licend
|
|
41
|
-
* @module
|
|
42
|
-
*/
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
*
|
|
46
|
-
* Utilities to encrypt and decrypt strings using simple methods, just to avoid write
|
|
47
|
-
* passwords in plain text in data and configuration files. Do not use it as a
|
|
48
|
-
* secure cryptographic system!
|
|
49
|
-
*
|
|
50
|
-
* Based on {@link https://github.com/projectestac/jclic/blob/master/src/utilities/edu/xtec/util/Encryption.java Encryption}
|
|
51
|
-
* utilities, created by Albert Llastarri for {@link https://github.com/projectestac/jclic JClic}.
|
|
52
|
-
*
|
|
53
|
-
* IMPORTANT: This is a shortened version of Encryption with only the methods needed to decrypt
|
|
54
|
-
* stored passwords. Full version is on file `src/misc/encryption/Encryption.js`
|
|
55
|
-
*
|
|
56
|
-
* @abstract
|
|
57
|
-
*/
|
|
58
|
-
class Encryption {
|
|
59
|
-
/**
|
|
60
|
-
* Decrypts the given code
|
|
61
|
-
* @param {string} txt - Code to be decrypted
|
|
62
|
-
* @returns {string}
|
|
63
|
-
*/
|
|
64
|
-
static Decrypt(txt) {
|
|
65
|
-
if (txt === null || txt.length === 0)
|
|
66
|
-
return null;
|
|
67
|
-
const s = Encryption.decodify(txt);
|
|
68
|
-
return s === Encryption.BLANK ? '' : s;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* @param {string} cA (was char[])
|
|
73
|
-
* @param {number} fromIndex
|
|
74
|
-
* @returns {string} (was char)
|
|
75
|
-
*/
|
|
76
|
-
static hexCharArrayToChar(cA, fromIndex) {
|
|
77
|
-
let n = 0;
|
|
78
|
-
for (let i = 0; i <= 3; i++) {
|
|
79
|
-
const j = Number.parseInt(cA[fromIndex + i], 16);
|
|
80
|
-
if (isNaN(j))
|
|
81
|
-
throw 'Invalid expression!';
|
|
82
|
-
else
|
|
83
|
-
n = n * 16 + j;
|
|
84
|
-
}
|
|
85
|
-
return String.fromCharCode(n);
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* @param {string} cA - (was char[])
|
|
90
|
-
* @param {number} fromIndex
|
|
91
|
-
* @returns {number}
|
|
92
|
-
*/
|
|
93
|
-
static hexCharArrayToInt(cA, fromIndex) {
|
|
94
|
-
let n = 0;
|
|
95
|
-
for (let i = 0; i <= 1; i++) {
|
|
96
|
-
const j = Number.parseInt(cA[fromIndex + i], 16);
|
|
97
|
-
if (isNaN(j))
|
|
98
|
-
throw 'Invalid expression!';
|
|
99
|
-
else
|
|
100
|
-
n = n * 16 + j;
|
|
101
|
-
}
|
|
102
|
-
return n;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
/**
|
|
106
|
-
* @param {string} cA - (was char[])
|
|
107
|
-
* @returns {string}
|
|
108
|
-
*/
|
|
109
|
-
static decodifyZerosField(cA) {
|
|
110
|
-
let
|
|
111
|
-
sb = '',
|
|
112
|
-
num = Number.parseInt(cA[0], 32),
|
|
113
|
-
k = 0,
|
|
114
|
-
i = 0;
|
|
115
|
-
|
|
116
|
-
for (i = 0; num !== 0; i++) {
|
|
117
|
-
while (num > 0) {
|
|
118
|
-
sb = sb + cA[i * 3 + 1] + cA[i * 3 + 2];
|
|
119
|
-
num--;
|
|
120
|
-
k++;
|
|
121
|
-
}
|
|
122
|
-
if (cA.length > i * 3 + 3)
|
|
123
|
-
num = Number.parseInt(cA[i * 3 + 3], 32);
|
|
124
|
-
else
|
|
125
|
-
num = 0;
|
|
126
|
-
}
|
|
127
|
-
for (let j = i * 3 + 1; j < cA.length; j++)
|
|
128
|
-
sb = sb + cA[j];
|
|
129
|
-
|
|
130
|
-
return Number.parseInt(k, 32) + sb;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
/**
|
|
134
|
-
* @param {string} cA - (was char[])
|
|
135
|
-
* @returns {string} (was StringBuilder)
|
|
136
|
-
*/
|
|
137
|
-
static decompressZeros(cA) {
|
|
138
|
-
cA = Encryption.decodifyZerosField(cA);
|
|
139
|
-
let
|
|
140
|
-
numBytesZeros = Number.parseInt(cA[0], 32),
|
|
141
|
-
iniNoZeros = numBytesZeros * 2 + 1,
|
|
142
|
-
bFi = false,
|
|
143
|
-
sb = '';
|
|
144
|
-
|
|
145
|
-
for (let i = 0; i < numBytesZeros && !bFi; i++) {
|
|
146
|
-
const zeros = Encryption.hexCharArrayToInt(cA, 1 + i * 2);
|
|
147
|
-
let s = zeros.toString(2);
|
|
148
|
-
while (s.length < 8)
|
|
149
|
-
s = '0' + s;
|
|
150
|
-
for (let j = 0; j <= 7 && !bFi; j++) {
|
|
151
|
-
if (s[j] === '1')
|
|
152
|
-
sb = sb + '0';
|
|
153
|
-
else if (iniNoZeros < cA.length)
|
|
154
|
-
sb = sb + cA[iniNoZeros++];
|
|
155
|
-
else
|
|
156
|
-
bFi = true;
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
return sb;
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
/**
|
|
163
|
-
* @param {string} sb1 - (was StringBuilder)
|
|
164
|
-
* @returns {string}
|
|
165
|
-
*/
|
|
166
|
-
static decodifyFromHex(sb1) {
|
|
167
|
-
let sb = '', j = 0;
|
|
168
|
-
for (let i = 0; j < sb1.length; i++) {
|
|
169
|
-
const c = Encryption.hexCharArrayToChar(sb1, j);
|
|
170
|
-
sb = sb + c;
|
|
171
|
-
j += 4;
|
|
172
|
-
}
|
|
173
|
-
return sb;
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
/**
|
|
177
|
-
* @param {string} s
|
|
178
|
-
* @returns {string} (was char[])
|
|
179
|
-
*/
|
|
180
|
-
static unchangeOrder(s) {
|
|
181
|
-
let m = 0, n = s.length - 1;
|
|
182
|
-
const cA = [];
|
|
183
|
-
for (let p = 0; p < s.length; p++)
|
|
184
|
-
cA[p] = '';
|
|
185
|
-
for (let i = 0; i < s.length; i++)
|
|
186
|
-
if (i % 2 === 0)
|
|
187
|
-
cA[i] = s[m++];
|
|
188
|
-
else
|
|
189
|
-
cA[i] = s[n--];
|
|
190
|
-
return cA.join('');
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
/**
|
|
194
|
-
* @param {string} word
|
|
195
|
-
* @returns {string}
|
|
196
|
-
*/
|
|
197
|
-
static codify(word) {
|
|
198
|
-
if (word.length > 24)
|
|
199
|
-
throw 'Password is too large!';
|
|
200
|
-
return Encryption.changeOrder(Encryption.compressZeros(Encryption.codifyToHexWord(word)));
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
/**
|
|
204
|
-
* @param {string} word
|
|
205
|
-
* @returns {string}
|
|
206
|
-
*/
|
|
207
|
-
static decodify(word) {
|
|
208
|
-
try {
|
|
209
|
-
return Encryption.decodifyFromHex(Encryption.decompressZeros(Encryption.unchangeOrder(word)));
|
|
210
|
-
} catch (_ex) { //The supplied word was not codified using this system
|
|
211
|
-
return '';
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
/**
|
|
217
|
-
* Default bank password
|
|
218
|
-
* @type {string}
|
|
219
|
-
*/
|
|
220
|
-
Encryption.BLANK = '___blank___##';
|
|
221
|
-
|
|
222
|
-
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (Encryption);
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
/***/ }),
|
|
226
|
-
|
|
227
|
-
/***/ 6782:
|
|
228
|
-
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
229
|
-
|
|
230
|
-
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
231
|
-
/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
|
|
232
|
-
/* harmony export */ });
|
|
233
|
-
/* unused harmony exports Reporter, ReporterInfo */
|
|
234
|
-
/* harmony import */ var jquery__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(7750);
|
|
235
|
-
/* harmony import */ var jquery__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(jquery__WEBPACK_IMPORTED_MODULE_0__);
|
|
236
|
-
/* harmony import */ var _SessionReg_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(8641);
|
|
237
|
-
/* harmony import */ var _EncryptMin_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(5344);
|
|
238
|
-
/* harmony import */ var _SCORM_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(6565);
|
|
239
|
-
/* harmony import */ var _Utils_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(1253);
|
|
240
|
-
/**
|
|
241
|
-
* File : report/Reporter.js
|
|
242
|
-
* Created : 17/05/2016
|
|
243
|
-
* By : Francesc Busquets <francesc@gmail.com>
|
|
244
|
-
*
|
|
245
|
-
* JClic.js
|
|
246
|
-
* An HTML5 player of JClic activities
|
|
247
|
-
* https://projectestac.github.io/jclic.js
|
|
248
|
-
*
|
|
249
|
-
* @source https://github.com/projectestac/jclic.js
|
|
250
|
-
*
|
|
251
|
-
* @license EUPL-1.2
|
|
252
|
-
* @licstart
|
|
253
|
-
* (c) 2000-2020 Educational Telematic Network of Catalonia (XTEC)
|
|
254
|
-
*
|
|
255
|
-
* Licensed under the EUPL, Version 1.1 or -as soon they will be approved by
|
|
256
|
-
* the European Commission- subsequent versions of the EUPL (the "Licence");
|
|
257
|
-
* You may not use this work except in compliance with the Licence.
|
|
258
|
-
*
|
|
259
|
-
* You may obtain a copy of the Licence at:
|
|
260
|
-
* https://joinup.ec.europa.eu/software/page/eupl
|
|
261
|
-
*
|
|
262
|
-
* Unless required by applicable law or agreed to in writing, software
|
|
263
|
-
* distributed under the Licence is distributed on an "AS IS" basis, WITHOUT
|
|
264
|
-
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
265
|
-
* Licence for the specific language governing permissions and limitations
|
|
266
|
-
* under the Licence.
|
|
267
|
-
* @licend
|
|
268
|
-
* @module
|
|
269
|
-
*/
|
|
270
|
-
|
|
271
|
-
/* global Promise, window */
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
/**
|
|
280
|
-
* This class implements the basic operations related with the processing of times and scores
|
|
281
|
-
* done by users playing JClic activities. These operations include: identification of users,
|
|
282
|
-
* compilation of data coming from the activities, storage of this data for later use, and
|
|
283
|
-
* presentation of summarized results.
|
|
284
|
-
*/
|
|
285
|
-
class Reporter {
|
|
286
|
-
/**
|
|
287
|
-
* Reporter constructor
|
|
288
|
-
* @param {module:JClicPlayer.JClicPlayer} ps - The {@link module:JClicPlayer.JClicPlayer JClicPlayer} used to retrieve localized messages
|
|
289
|
-
*/
|
|
290
|
-
constructor(ps) {
|
|
291
|
-
this.ps = ps;
|
|
292
|
-
this.sessions = [];
|
|
293
|
-
this.started = new Date();
|
|
294
|
-
this.initiated = false;
|
|
295
|
-
this.info = new ReporterInfo(this);
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
/**
|
|
299
|
-
* Registers a new type of reporter
|
|
300
|
-
* @param {string} reporterName - The name used to identify this reporter
|
|
301
|
-
* @param {function} reporterClass - The reporter class, usually extending Reporter
|
|
302
|
-
* @returns {module:report/Reporter.Reporter} - The provided reporter class
|
|
303
|
-
*/
|
|
304
|
-
static registerClass(reporterName, reporterClass) {
|
|
305
|
-
Reporter.CLASSES[reporterName] = reporterClass;
|
|
306
|
-
return reporterClass;
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
/**
|
|
310
|
-
* Creates a new Reporter of the requested class
|
|
311
|
-
* The resulting object must be prepared to operate with a call to its `init` method.
|
|
312
|
-
* @param {string} className - Class name of the requested reporter. When `null`, a basic Reporter is created.
|
|
313
|
-
* @param {module:JClicPlayer.JClicPlayer} ps - The {@link module:JClicPlayer.JClicPlayer JClicPlayer} used to retrieve localized messages
|
|
314
|
-
* @returns {module:report/Reporter.Reporter}
|
|
315
|
-
*/
|
|
316
|
-
static getReporter(className, ps) {
|
|
317
|
-
let result = null;
|
|
318
|
-
if (className === null) {
|
|
319
|
-
className = 'Reporter';
|
|
320
|
-
if (ps.options.hasOwnProperty('reporter'))
|
|
321
|
-
className = ps.options.reporter;
|
|
322
|
-
}
|
|
323
|
-
if (Reporter.CLASSES.hasOwnProperty(className))
|
|
324
|
-
result = new Reporter.CLASSES[className](ps);
|
|
325
|
-
else
|
|
326
|
-
(0,_Utils_js__WEBPACK_IMPORTED_MODULE_4__/* .log */ .Rm)('error', 'Unknown reporter class: %s', className);
|
|
327
|
-
|
|
328
|
-
return result;
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
/**
|
|
332
|
-
* Returns the `info` element associated to this Reporter.
|
|
333
|
-
* @returns {module:report/Reporter.ReporterInfo}
|
|
334
|
-
*/
|
|
335
|
-
getInfo() {
|
|
336
|
-
return this.info.recalc();
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
/**
|
|
340
|
-
* Gets a specific property from this reporting system
|
|
341
|
-
* @param {string} key - Requested property
|
|
342
|
-
* @param {string}+ defaultValue - Default return value when requested property does not exist
|
|
343
|
-
* @returns {string}
|
|
344
|
-
*/
|
|
345
|
-
getProperty(key, defaultValue) {
|
|
346
|
-
return defaultValue;
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
/**
|
|
350
|
-
* Gets a specific boolean property from this reporting system
|
|
351
|
-
* @param {string} key - Requested property
|
|
352
|
-
* @param {boolean}+ defaultValue - Default return when requested property does not exist
|
|
353
|
-
* @returns {boolean}
|
|
354
|
-
*/
|
|
355
|
-
getBooleanProperty(key, defaultValue) {
|
|
356
|
-
const s = this.getProperty(key, defaultValue === true ? 'true' : 'false');
|
|
357
|
-
return key === null ? defaultValue : s === 'true' ? true : false;
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
/**
|
|
361
|
-
* Gets the list of groups or organizations currently registered in the system. This
|
|
362
|
-
* method should be implemented by classes derived of `Reporter`.
|
|
363
|
-
* @returns {external:Promise} - When fulfilled, an array of group data is returned as a result
|
|
364
|
-
*/
|
|
365
|
-
getGroups() {
|
|
366
|
-
return Promise.reject('No groups defined!');
|
|
367
|
-
}
|
|
368
|
-
|
|
369
|
-
/**
|
|
370
|
-
* Gets the list of users currently registered in the system, optionally filtered by
|
|
371
|
-
* a specific group ID. This method should be implemented by classes derived of `Reporter`.
|
|
372
|
-
* @param {string}+ groupId - Optional group ID to be used as a filter criteria
|
|
373
|
-
* @returns {external:Promise} - When fulfilled, an object with a collection of user data records
|
|
374
|
-
* is returned
|
|
375
|
-
*/
|
|
376
|
-
getUsers(groupId) {
|
|
377
|
-
return Promise.reject('No users defined in ' + groupId);
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
/**
|
|
381
|
-
* Gets extended data associated with a specific user. This is a method intended to be
|
|
382
|
-
* implemented in subclasses.
|
|
383
|
-
* @param {string} _userId - The requested user ID
|
|
384
|
-
* @returns {external:Promise} - When fulfilled, an object with user data is returned.
|
|
385
|
-
*/
|
|
386
|
-
getUserData(_userId) {
|
|
387
|
-
return Promise.reject('Unknown user!');
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
/**
|
|
391
|
-
* Gets extended data associated with a specific group or organization. This
|
|
392
|
-
* is a method intended to be implemented in subclasses.
|
|
393
|
-
* @param {string} _groupId - The requested group ID
|
|
394
|
-
* @returns {external:Promise} - When fulfilled, an object with group data is returned.
|
|
395
|
-
*/
|
|
396
|
-
getGroupData(_groupId) {
|
|
397
|
-
return Promise.reject('Unknown group!');
|
|
398
|
-
}
|
|
399
|
-
|
|
400
|
-
/**
|
|
401
|
-
* Checks if this reporting system manages its own database of users and groups. Defaults to `false`
|
|
402
|
-
* @returns {boolean}
|
|
403
|
-
*/
|
|
404
|
-
userBased() {
|
|
405
|
-
if (this.bUserBased === null)
|
|
406
|
-
this.bUserBased = this.getBooleanProperty('USER_TABLES', false);
|
|
407
|
-
return this.bUserBased;
|
|
408
|
-
}
|
|
409
|
-
|
|
410
|
-
/**
|
|
411
|
-
* Allows the current user to create a new group, and asks his name
|
|
412
|
-
* @returns {external:Promise} - When fulfilled, the chosen name for the new group is returned.
|
|
413
|
-
*/
|
|
414
|
-
promptForNewGroup() {
|
|
415
|
-
// TODO: Implement promptForNewGroup
|
|
416
|
-
return Promise.reject('Remote creation of groups not yet implemented!');
|
|
417
|
-
}
|
|
418
|
-
|
|
419
|
-
/**
|
|
420
|
-
* Allows the current user to create a new user ID, and asks his ID and password
|
|
421
|
-
* @returns {external:Promise} - When fulfilled, an object with the new user ID and password
|
|
422
|
-
* is returned.
|
|
423
|
-
*/
|
|
424
|
-
promptForNewUser() {
|
|
425
|
-
// TODO: Implement promptForNewUser
|
|
426
|
-
return Promise.reject('Remote creation of users not yet implemented!');
|
|
427
|
-
}
|
|
428
|
-
|
|
429
|
-
/**
|
|
430
|
-
* Allows the current user to select its group or organization from the current groups list
|
|
431
|
-
* @returns {external:Promise}
|
|
432
|
-
*/
|
|
433
|
-
promptGroupId() {
|
|
434
|
-
return new Promise((resolve, reject) => {
|
|
435
|
-
if (!this.userBased())
|
|
436
|
-
reject('This system does not manage users!');
|
|
437
|
-
else {
|
|
438
|
-
this.getGroups().then((groupList) => {
|
|
439
|
-
// Creation of new groups not yet implemented!
|
|
440
|
-
if (!groupList || groupList.length < 1)
|
|
441
|
-
reject('No groups defined!');
|
|
442
|
-
else {
|
|
443
|
-
let sel = 0;
|
|
444
|
-
const $groupSelect = jquery__WEBPACK_IMPORTED_MODULE_0___default()('<select/>').attr({ size: Math.max(3, Math.min(15, groupList.length)) });
|
|
445
|
-
groupList.forEach(g => $groupSelect.append(jquery__WEBPACK_IMPORTED_MODULE_0___default()('<option/>').attr({ value: g.id }).text(g.name)));
|
|
446
|
-
$groupSelect.change(ev => { sel = ev.target.selectedIndex; });
|
|
447
|
-
this.ps.skin.showDlg(true, {
|
|
448
|
-
main: [
|
|
449
|
-
jquery__WEBPACK_IMPORTED_MODULE_0___default()('<h2/>', { class: 'subtitle' }).html((0,_Utils_js__WEBPACK_IMPORTED_MODULE_4__/* .getMsg */ .qG)('Select group:')),
|
|
450
|
-
$groupSelect],
|
|
451
|
-
bottom: [
|
|
452
|
-
this.ps.skin.$okDlgBtn,
|
|
453
|
-
this.ps.skin.$cancelDlgBtn]
|
|
454
|
-
}).then(() => {
|
|
455
|
-
resolve(groupList[sel].id);
|
|
456
|
-
}).catch(reject);
|
|
457
|
-
}
|
|
458
|
-
}).catch(reject);
|
|
459
|
-
}
|
|
460
|
-
});
|
|
461
|
-
}
|
|
462
|
-
|
|
463
|
-
/**
|
|
464
|
-
* Asks for a valid user ID fulfilling the promise if found, rejecting it otherwise
|
|
465
|
-
* @param {boolean}+ forcePrompt - Prompt also if `userId` is already defined (default is `false`)
|
|
466
|
-
* @returns {external:Promise}
|
|
467
|
-
*/
|
|
468
|
-
promptUserId(forcePrompt) {
|
|
469
|
-
return new Promise((resolve, reject) => {
|
|
470
|
-
if (this.userId !== null && !forcePrompt)
|
|
471
|
-
resolve(this.userId);
|
|
472
|
-
else if (!this.userBased())
|
|
473
|
-
reject('This system does not manage users!');
|
|
474
|
-
else {
|
|
475
|
-
const $pwdInput = jquery__WEBPACK_IMPORTED_MODULE_0___default()('<input/>', { type: 'password', size: 8, maxlength: 64 });
|
|
476
|
-
if (this.getBooleanProperty('SHOW_USER_LIST', true)) {
|
|
477
|
-
this.promptGroupId().then(groupId => {
|
|
478
|
-
this.getUsers(groupId).then(userList => {
|
|
479
|
-
// Creation of new users not yet implemented
|
|
480
|
-
// let userCreationAllowed = this.getBooleanProperty('ALLOW_CREATE_USERS', false)
|
|
481
|
-
if (!userList || userList.length < 1)
|
|
482
|
-
reject('Group ' + groupId + ' has no users!');
|
|
483
|
-
else {
|
|
484
|
-
let sel = -1;
|
|
485
|
-
const $userSelect = jquery__WEBPACK_IMPORTED_MODULE_0___default()('<select/>').attr({ size: Math.max(3, Math.min(15, userList.length)) });
|
|
486
|
-
userList.forEach(u => $userSelect.append(jquery__WEBPACK_IMPORTED_MODULE_0___default()('<option/>').attr({ value: u.id }).text(u.name)));
|
|
487
|
-
$userSelect.change(ev => { sel = ev.target.selectedIndex; });
|
|
488
|
-
this.ps.skin.showDlg(true, {
|
|
489
|
-
main: [
|
|
490
|
-
jquery__WEBPACK_IMPORTED_MODULE_0___default()('<h2/>', { class: 'subtitle' }).html((0,_Utils_js__WEBPACK_IMPORTED_MODULE_4__/* .getMsg */ .qG)('Select user:')),
|
|
491
|
-
$userSelect,
|
|
492
|
-
jquery__WEBPACK_IMPORTED_MODULE_0___default()('<h2/>', { class: 'subtitle' }).html((0,_Utils_js__WEBPACK_IMPORTED_MODULE_4__/* .getMsg */ .qG)('Password:')).append($pwdInput)],
|
|
493
|
-
bottom: [
|
|
494
|
-
this.ps.skin.$okDlgBtn,
|
|
495
|
-
this.ps.skin.$cancelDlgBtn]
|
|
496
|
-
}).then(() => {
|
|
497
|
-
if (sel >= 0) {
|
|
498
|
-
if (userList[sel].pwd && _EncryptMin_js__WEBPACK_IMPORTED_MODULE_2__["default"].Decrypt(userList[sel].pwd) !== $pwdInput.val()) {
|
|
499
|
-
window.alert((0,_Utils_js__WEBPACK_IMPORTED_MODULE_4__/* .getMsg */ .qG)('Incorrect password'));
|
|
500
|
-
reject('Incorrect password');
|
|
501
|
-
} else {
|
|
502
|
-
this.userId = userList[sel].id;
|
|
503
|
-
resolve(this.userId);
|
|
504
|
-
}
|
|
505
|
-
} else
|
|
506
|
-
reject('No user has been selected');
|
|
507
|
-
}).catch(reject);
|
|
508
|
-
}
|
|
509
|
-
}).catch(reject);
|
|
510
|
-
}).catch(reject);
|
|
511
|
-
} else {
|
|
512
|
-
const $userInput = jquery__WEBPACK_IMPORTED_MODULE_0___default()('<input/>', { type: 'text', size: 8, maxlength: 64 });
|
|
513
|
-
this.ps.skin.showDlg(true, {
|
|
514
|
-
main: [
|
|
515
|
-
jquery__WEBPACK_IMPORTED_MODULE_0___default()('<div/>').css({ 'text-align': 'right' })
|
|
516
|
-
.append(jquery__WEBPACK_IMPORTED_MODULE_0___default()('<h2/>', { class: 'subtitle' }).html((0,_Utils_js__WEBPACK_IMPORTED_MODULE_4__/* .getMsg */ .qG)('User:'))
|
|
517
|
-
.append($userInput))
|
|
518
|
-
.append(jquery__WEBPACK_IMPORTED_MODULE_0___default()('<h2/>', { class: 'subtitle' }).html((0,_Utils_js__WEBPACK_IMPORTED_MODULE_4__/* .getMsg */ .qG)('Password:'))
|
|
519
|
-
.append($pwdInput))],
|
|
520
|
-
bottom: [
|
|
521
|
-
this.ps.skin.$okDlgBtn,
|
|
522
|
-
this.ps.skin.$cancelDlgBtn]
|
|
523
|
-
}).then(() => {
|
|
524
|
-
this.getUserData($userInput.val()).then(user => {
|
|
525
|
-
if (user.pwd && _EncryptMin_js__WEBPACK_IMPORTED_MODULE_2__["default"].Decrypt(user.pwd) !== $pwdInput.val()) {
|
|
526
|
-
window.alert((0,_Utils_js__WEBPACK_IMPORTED_MODULE_4__/* .getMsg */ .qG)('Incorrect password'));
|
|
527
|
-
reject('Incorrect password');
|
|
528
|
-
} else {
|
|
529
|
-
this.userId = user.id;
|
|
530
|
-
resolve(this.userId);
|
|
531
|
-
}
|
|
532
|
-
}).catch(reject);
|
|
533
|
-
}).catch(reject);
|
|
534
|
-
}
|
|
535
|
-
}
|
|
536
|
-
});
|
|
537
|
-
}
|
|
538
|
-
|
|
539
|
-
/**
|
|
540
|
-
* Builds a complex object containing all the results reported while playing activities
|
|
541
|
-
* @returns {object} - The current results
|
|
542
|
-
*/
|
|
543
|
-
getData() {
|
|
544
|
-
|
|
545
|
-
// Force the re-calculation of all scores
|
|
546
|
-
this.info.recalc();
|
|
547
|
-
|
|
548
|
-
const result = {
|
|
549
|
-
started: this.started.toISOString(),
|
|
550
|
-
descriptionKey: this.descriptionKey,
|
|
551
|
-
descriptionDetail: this.descriptionDetail,
|
|
552
|
-
projects: this.info.numSessions,
|
|
553
|
-
sequences: this.info.numSequences,
|
|
554
|
-
activitiesDone: this.info.nActivities,
|
|
555
|
-
playedOnce: this.info.nActPlayed,
|
|
556
|
-
reportable: this.info.reportableActs,
|
|
557
|
-
ratioPlayed: Math.round(this.info.ratioPlayed * 100),
|
|
558
|
-
activitiesSolved: this.info.nActSolved,
|
|
559
|
-
ratioSolved: Math.round(this.info.ratioSolved * 100),
|
|
560
|
-
actScore: this.info.nActScore,
|
|
561
|
-
partialScore: Math.round(this.info.partialScore * 100),
|
|
562
|
-
globalScore: Math.round(this.info.globalScore * 100),
|
|
563
|
-
time: Math.round(this.info.tTime / 10) / 100,
|
|
564
|
-
actions: this.info.nActions,
|
|
565
|
-
sessions: []
|
|
566
|
-
};
|
|
567
|
-
|
|
568
|
-
if (this.userId)
|
|
569
|
-
result.userId = this.userId;
|
|
570
|
-
else if (this.SCORM)
|
|
571
|
-
result.user = this.SCORM.studentName + (this.SCORM.studentId === '' ? '' : ` (${this.SCORM.studentId})`);
|
|
572
|
-
|
|
573
|
-
this.sessions.forEach(sr => {
|
|
574
|
-
if (sr.getInfo().numSequences > 0)
|
|
575
|
-
result.sessions.push(sr.getData(false, false));
|
|
576
|
-
});
|
|
577
|
-
|
|
578
|
-
return result;
|
|
579
|
-
}
|
|
580
|
-
|
|
581
|
-
/**
|
|
582
|
-
* Initializes this report system with an optional set of parameters.
|
|
583
|
-
* Returns a Promise, fulfilled when the reporter is fully initialized.
|
|
584
|
-
* @param {object} [options] - Initial settings passed to the reporting system
|
|
585
|
-
* @returns {external:Promise}
|
|
586
|
-
*/
|
|
587
|
-
init(options) {
|
|
588
|
-
if (!options)
|
|
589
|
-
options = this.ps.options;
|
|
590
|
-
this.userId = (0,_Utils_js__WEBPACK_IMPORTED_MODULE_4__/* .getVal */ .eH)(options.user);
|
|
591
|
-
this.sessionKey = (0,_Utils_js__WEBPACK_IMPORTED_MODULE_4__/* .getVal */ .eH)(options.key);
|
|
592
|
-
this.sessionContext = (0,_Utils_js__WEBPACK_IMPORTED_MODULE_4__/* .getVal */ .eH)(options.context);
|
|
593
|
-
this.groupCodeFilter = (0,_Utils_js__WEBPACK_IMPORTED_MODULE_4__/* .getVal */ .eH)(options.groupCodeFilter);
|
|
594
|
-
this.userCodeFilter = (0,_Utils_js__WEBPACK_IMPORTED_MODULE_4__/* .getVal */ .eH)(options.userCodeFilter);
|
|
595
|
-
if (options.SCORM !== false) {
|
|
596
|
-
this.SCORM = _SCORM_js__WEBPACK_IMPORTED_MODULE_3__["default"].getSCORM(this);
|
|
597
|
-
if (this.SCORM !== null && this.descriptionKey === Reporter.prototype.descriptionKey)
|
|
598
|
-
this.descriptionKey = this.SCORM.getScormType();
|
|
599
|
-
}
|
|
600
|
-
this.initiated = true;
|
|
601
|
-
(0,_Utils_js__WEBPACK_IMPORTED_MODULE_4__/* .log */ .Rm)('debug', 'Basic Reporter initialized');
|
|
602
|
-
return Promise.resolve(true);
|
|
603
|
-
}
|
|
604
|
-
|
|
605
|
-
/**
|
|
606
|
-
* Closes this reporting system
|
|
607
|
-
* @returns {external:Promise} - A Promise object to be fullfilled when all pending tasks are finished.
|
|
608
|
-
*/
|
|
609
|
-
end() {
|
|
610
|
-
(0,_Utils_js__WEBPACK_IMPORTED_MODULE_4__/* .log */ .Rm)('debug', 'Basic Reporter ending');
|
|
611
|
-
this.endSession();
|
|
612
|
-
return Promise.resolve(true);
|
|
613
|
-
}
|
|
614
|
-
|
|
615
|
-
/**
|
|
616
|
-
* Finalizes the current sequence
|
|
617
|
-
*/
|
|
618
|
-
endSequence() {
|
|
619
|
-
if (this.currentSession) {
|
|
620
|
-
this.currentSession.endSequence();
|
|
621
|
-
this.info.valid = false;
|
|
622
|
-
}
|
|
623
|
-
}
|
|
624
|
-
|
|
625
|
-
/**
|
|
626
|
-
* Finalizes the current session
|
|
627
|
-
*/
|
|
628
|
-
endSession() {
|
|
629
|
-
this.endSequence();
|
|
630
|
-
this.currentSession = null;
|
|
631
|
-
}
|
|
632
|
-
|
|
633
|
-
/**
|
|
634
|
-
* Creates a new group (method to be implemented in subclasses)
|
|
635
|
-
* @param {object} _gd
|
|
636
|
-
*/
|
|
637
|
-
newGroup(_gd) {
|
|
638
|
-
throw "No database!";
|
|
639
|
-
}
|
|
640
|
-
|
|
641
|
-
/**
|
|
642
|
-
* Creates a new user (method to be implemented in subclasses)
|
|
643
|
-
* @param {object} _ud
|
|
644
|
-
*/
|
|
645
|
-
newUser(_ud) {
|
|
646
|
-
throw "No database!";
|
|
647
|
-
}
|
|
648
|
-
|
|
649
|
-
/**
|
|
650
|
-
* This method should be invoked when a new session starts.
|
|
651
|
-
* @param {module:project/JClicProject.JClicProject} jcp - The {@link module:project/JClicProject.JClicProject JClicProject} this session refers to.
|
|
652
|
-
*/
|
|
653
|
-
newSession(jcp) {
|
|
654
|
-
this.endSession();
|
|
655
|
-
this.currentSession = new _SessionReg_js__WEBPACK_IMPORTED_MODULE_1__["default"](jcp);
|
|
656
|
-
this.sessions.push(this.currentSession);
|
|
657
|
-
this.info.valid = false;
|
|
658
|
-
}
|
|
659
|
-
|
|
660
|
-
/**
|
|
661
|
-
* This method should be invoked when a new sequence starts
|
|
662
|
-
* @param {module:bags/ActivitySequenceElement.ActivitySequenceElement} ase - The {@link module:bags/ActivitySequenceElement.ActivitySequenceElement ActivitySequenceElement} referenced by this sequence.
|
|
663
|
-
*/
|
|
664
|
-
newSequence(ase) {
|
|
665
|
-
if (this.currentSession) {
|
|
666
|
-
this.currentSession.newSequence(ase);
|
|
667
|
-
this.info.valid = false;
|
|
668
|
-
if (this.SCORM)
|
|
669
|
-
this.SCORM.commitInfo();
|
|
670
|
-
}
|
|
671
|
-
}
|
|
672
|
-
|
|
673
|
-
/**
|
|
674
|
-
* This method should be invoked when the user starts a new activity
|
|
675
|
-
* @param {module:Activity.Activity} act - The {@link module:Activity.Activity Activity} reporter has just started
|
|
676
|
-
*/
|
|
677
|
-
newActivity(act) {
|
|
678
|
-
if (this.currentSession) {
|
|
679
|
-
this.currentSession.newActivity(act);
|
|
680
|
-
this.info.valid = false;
|
|
681
|
-
}
|
|
682
|
-
}
|
|
683
|
-
|
|
684
|
-
/**
|
|
685
|
-
* This method should be called when the current activity finishes. Data about user's final results
|
|
686
|
-
* on the activity will then be saved.
|
|
687
|
-
* @param {number} score - The final score, usually in a 0-100 scale.
|
|
688
|
-
* @param {number} numActions - The total number of actions done by the user to solve the activity
|
|
689
|
-
* @param {boolean} solved - `true` if the activity was finally solved, `false` otherwise.
|
|
690
|
-
*/
|
|
691
|
-
endActivity(score, numActions, solved) {
|
|
692
|
-
if (this.currentSession) {
|
|
693
|
-
this.currentSession.endActivity(score, numActions, solved);
|
|
694
|
-
this.info.valid = false;
|
|
695
|
-
}
|
|
696
|
-
}
|
|
697
|
-
|
|
698
|
-
/**
|
|
699
|
-
* Reports a new action done by the user while playing the current activity
|
|
700
|
-
* @param {string} type - Type of action (`click`, `write`, `move`, `select`...)
|
|
701
|
-
* @param {string}+ source - Description of the object on which the action is done.
|
|
702
|
-
* @param {string}+ dest - Description of the object reporter acts as a target of the action (usually in pairings)
|
|
703
|
-
* @param {boolean} ok - `true` if the action was OK, `false`, `null` or `undefined` otherwhise
|
|
704
|
-
*/
|
|
705
|
-
newAction(type, source, dest, ok) {
|
|
706
|
-
if (this.currentSession) {
|
|
707
|
-
this.currentSession.newAction(type, source, dest, ok);
|
|
708
|
-
this.info.valid = false;
|
|
709
|
-
}
|
|
710
|
-
}
|
|
711
|
-
|
|
712
|
-
/**
|
|
713
|
-
* Gets information about the current sequence
|
|
714
|
-
* @returns {module:report/SequenceReg.SequenceRegInfo}
|
|
715
|
-
*/
|
|
716
|
-
getCurrentSequenceInfo() {
|
|
717
|
-
return this.currentSession === null ? null : this.currentSession.getCurrentSequenceInfo();
|
|
718
|
-
}
|
|
719
|
-
|
|
720
|
-
/**
|
|
721
|
-
* Gets the name of the current sequence
|
|
722
|
-
* @returns {string}
|
|
723
|
-
*/
|
|
724
|
-
getCurrentSequenceTag() {
|
|
725
|
-
return this.currentSession === null ? null : this.currentSession.getCurrentSequenceTag();
|
|
726
|
-
}
|
|
727
|
-
}
|
|
728
|
-
|
|
729
|
-
Object.assign(Reporter.prototype, {
|
|
730
|
-
/**
|
|
731
|
-
* The {@link module:report/Reporter.ReporterInfo ReporterInfo} used to calculate and store global results.
|
|
732
|
-
* @name module:report/Reporter.Reporter#info
|
|
733
|
-
* @type {module:report/Reporter.ReporterInfo} */
|
|
734
|
-
info: null,
|
|
735
|
-
/**
|
|
736
|
-
* The {@link module:JClicPlayer.JClicPlayer JClicPlayer} used to retrieve messages
|
|
737
|
-
* @name module:report/Reporter.Reporter#ps
|
|
738
|
-
* @type {module:JClicPlayer.JClicPlayer} */
|
|
739
|
-
ps: null,
|
|
740
|
-
/**
|
|
741
|
-
* A valid SCORM bridge, or `null` if no SCORM API detected.
|
|
742
|
-
* @name module:report/Reporter.Reporter#SCORM */
|
|
743
|
-
SCORM: null,
|
|
744
|
-
/**
|
|
745
|
-
* User ID currently associated with this reporting system
|
|
746
|
-
* @name module:report/Reporter.Reporter#userId
|
|
747
|
-
* @type {string} */
|
|
748
|
-
userId: null,
|
|
749
|
-
/**
|
|
750
|
-
* Optional key to be added as a field in session records
|
|
751
|
-
* @name module:report/Reporter.Reporter#sessionKey
|
|
752
|
-
* @type {string} */
|
|
753
|
-
sessionKey: null,
|
|
754
|
-
/**
|
|
755
|
-
* A second optional key to be reported as a field in session records
|
|
756
|
-
* @name module:report/Reporter.Reporter#sessionContext
|
|
757
|
-
* @type {string} */
|
|
758
|
-
sessionContext: null,
|
|
759
|
-
/**
|
|
760
|
-
* Optional filter key to be used in the group selection dialog
|
|
761
|
-
* @name module:report/Reporter.Reporter#groupCodeFilter
|
|
762
|
-
* @type {string} */
|
|
763
|
-
groupCodeFilter: null,
|
|
764
|
-
/**
|
|
765
|
-
* Another optional filter key to be used in the user selection dialog
|
|
766
|
-
* @name module:report/Reporter.Reporter#userCodeFilter
|
|
767
|
-
* @type {string} */
|
|
768
|
-
userCodeFilter: null,
|
|
769
|
-
/**
|
|
770
|
-
* Description of this reporting system
|
|
771
|
-
* @name module:report/Reporter.Reporter#descriptionKey
|
|
772
|
-
* @type {string} */
|
|
773
|
-
descriptionKey: 'Results are not currently being saved',
|
|
774
|
-
/**
|
|
775
|
-
* Additional info to display after the reporter's `description`
|
|
776
|
-
* @name module:report/Reporter.Reporter#descriptionDetail
|
|
777
|
-
* @type {string} */
|
|
778
|
-
descriptionDetail: '',
|
|
779
|
-
/**
|
|
780
|
-
* Starting date and time of this report
|
|
781
|
-
* @name module:report/Reporter.Reporter#started
|
|
782
|
-
* @type {external:Date} */
|
|
783
|
-
started: null,
|
|
784
|
-
/**
|
|
785
|
-
* Array of sessions included in this report
|
|
786
|
-
* @name module:report/Reporter.Reporter#sessions
|
|
787
|
-
* @type {module:report/SessionReg.SessionReg[]} */
|
|
788
|
-
sessions: [],
|
|
789
|
-
/**
|
|
790
|
-
* Currently active session
|
|
791
|
-
* @name module:report/Reporter.Reporter#currentSession
|
|
792
|
-
* @type {module:report/SessionReg.SessionReg} */
|
|
793
|
-
currentSession: null,
|
|
794
|
-
/**
|
|
795
|
-
* `true` if the system was successfully initiated, `false` otherwise
|
|
796
|
-
* @name module:report/Reporter.Reporter#initiated
|
|
797
|
-
* @type {boolean} */
|
|
798
|
-
initiated: false,
|
|
799
|
-
/**
|
|
800
|
-
* `true` if the system is connected to a database with user's data.
|
|
801
|
-
* When `false`, a generic ID will be used.
|
|
802
|
-
* @name module:report/Reporter.Reporter#bUserBased
|
|
803
|
-
* @type {boolean} */
|
|
804
|
-
bUserBased: null,
|
|
805
|
-
/**
|
|
806
|
-
* Maximum number of incorrect UserID attempts
|
|
807
|
-
* @name module:report/Reporter.Reporter#MAX_USERID_PROMPT_ATTEMPTS
|
|
808
|
-
* @type {number} */
|
|
809
|
-
MAX_USERID_PROMPT_ATTEMPTS: 3,
|
|
810
|
-
});
|
|
811
|
-
|
|
812
|
-
/**
|
|
813
|
-
* This object stores the global results of a {@link module:Reporter.Reporter Reporter}
|
|
814
|
-
*/
|
|
815
|
-
class ReporterInfo {
|
|
816
|
-
/**
|
|
817
|
-
* ReporterInfo constructor
|
|
818
|
-
* @param {module:report/Reporter.Reporter} rep - The {@link module:Reporter.Reporter Reporter} associated tho this `Info` object.
|
|
819
|
-
*/
|
|
820
|
-
constructor(rep) {
|
|
821
|
-
this.rep = rep;
|
|
822
|
-
}
|
|
823
|
-
|
|
824
|
-
/**
|
|
825
|
-
* Clears all data associated with this ReporterInfo
|
|
826
|
-
*/
|
|
827
|
-
clear() {
|
|
828
|
-
this.numSessions = this.numSequences = this.nActivities = this.reportableActs = this.nActSolved =
|
|
829
|
-
this.nActPlayed = this.nActScore = this.nActions = this.ratioSolved = this.ratioPlayed =
|
|
830
|
-
this.tScore = this.tTime = this.partialScore = this.globalScore = 0;
|
|
831
|
-
this.valid = false;
|
|
832
|
-
}
|
|
833
|
-
|
|
834
|
-
/**
|
|
835
|
-
* Computes the value of all global variables based on the data stored in `sessions`
|
|
836
|
-
* @returns {module:report/Reporter.ReporterInfo} - This "info" object
|
|
837
|
-
*/
|
|
838
|
-
recalc() {
|
|
839
|
-
if (!this.valid) {
|
|
840
|
-
this.clear();
|
|
841
|
-
this.rep.sessions.forEach(ses => {
|
|
842
|
-
const inf = ses.getInfo();
|
|
843
|
-
this.reportableActs += inf.sReg.reportableActs;
|
|
844
|
-
if (inf.numSequences > 0) {
|
|
845
|
-
this.numSessions++;
|
|
846
|
-
this.numSequences += inf.numSequences;
|
|
847
|
-
if (inf.nActivities > 0) {
|
|
848
|
-
this.nActivities += inf.nActivities;
|
|
849
|
-
this.nActPlayed += inf.sReg.actNames.length;
|
|
850
|
-
this.nActSolved += inf.nActSolved;
|
|
851
|
-
this.nActions += inf.nActions;
|
|
852
|
-
if (inf.nActScore > 0) {
|
|
853
|
-
this.tScore += inf.tScore * inf.nActScore;
|
|
854
|
-
this.nActScore += inf.nActScore;
|
|
855
|
-
}
|
|
856
|
-
this.tTime += inf.tTime;
|
|
857
|
-
}
|
|
858
|
-
}
|
|
859
|
-
});
|
|
860
|
-
if (this.nActivities > 0) {
|
|
861
|
-
this.ratioSolved = this.nActSolved / this.nActivities;
|
|
862
|
-
if (this.reportableActs > 0)
|
|
863
|
-
this.ratioPlayed = this.nActPlayed / this.reportableActs;
|
|
864
|
-
this.partialScore = this.tScore / (this.nActScore * 100);
|
|
865
|
-
this.globalScore = this.partialScore * this.ratioPlayed;
|
|
866
|
-
}
|
|
867
|
-
this.valid = true;
|
|
868
|
-
}
|
|
869
|
-
return this;
|
|
870
|
-
}
|
|
871
|
-
}
|
|
872
|
-
|
|
873
|
-
Object.assign(ReporterInfo.prototype, {
|
|
874
|
-
/**
|
|
875
|
-
* The Reporter linked to this Info object
|
|
876
|
-
* @name module:report/Reporter.ReporterInfo#rep
|
|
877
|
-
* @type {module:report/Reporter.Reporter}
|
|
878
|
-
*/
|
|
879
|
-
rep: null,
|
|
880
|
-
/**
|
|
881
|
-
* When `false`, data must be recalculated
|
|
882
|
-
* @name module:report/Reporter.ReporterInfo#valid
|
|
883
|
-
* @type {boolean} */
|
|
884
|
-
valid: false,
|
|
885
|
-
/**
|
|
886
|
-
* Number of sessions registered
|
|
887
|
-
* @name module:report/Reporter.ReporterInfo#numSessions
|
|
888
|
-
* @type {number} */
|
|
889
|
-
numSessions: 0,
|
|
890
|
-
/**
|
|
891
|
-
* Number of sequences played
|
|
892
|
-
* @name module:report/Reporter.ReporterInfo#numSequences
|
|
893
|
-
* @type {number} */
|
|
894
|
-
numSequences: 0,
|
|
895
|
-
/**
|
|
896
|
-
* Number of activities played
|
|
897
|
-
* @name module:report/Reporter.ReporterInfo#nActivities
|
|
898
|
-
* @type {number} */
|
|
899
|
-
nActivities: 0,
|
|
900
|
-
/**
|
|
901
|
-
* Number of activities in existing in the played projects suitable to be reported
|
|
902
|
-
* @name module:report/Reporter.ReporterInfo#reportableActs
|
|
903
|
-
* @type {number} */
|
|
904
|
-
reportableActs: 0,
|
|
905
|
-
/**
|
|
906
|
-
* Number of activities solved
|
|
907
|
-
* @name module:report/Reporter.ReporterInfo#nActSolved
|
|
908
|
-
* @type {number} */
|
|
909
|
-
nActSolved: 0,
|
|
910
|
-
/**
|
|
911
|
-
* Number of different activities played
|
|
912
|
-
* @name module:report/Reporter.ReporterInfo#nActPlayed
|
|
913
|
-
* @type {number} */
|
|
914
|
-
nActPlayed: 0,
|
|
915
|
-
/**
|
|
916
|
-
* Global score obtained in all sessions registered by this reporter
|
|
917
|
-
* @name module:report/Reporter.ReporterInfo#nActScore
|
|
918
|
-
* @type {number} */
|
|
919
|
-
nActScore: 0,
|
|
920
|
-
/**
|
|
921
|
-
* Number of actions done by the user while in this working session
|
|
922
|
-
* @name module:report/Reporter.ReporterInfo#nActions
|
|
923
|
-
* @type {number} */
|
|
924
|
-
nActions: 0,
|
|
925
|
-
/**
|
|
926
|
-
* Percentage of solved activities
|
|
927
|
-
* @name module:report/Reporter.ReporterInfo#ratioSolved
|
|
928
|
-
* @type {number} */
|
|
929
|
-
ratioSolved: 0,
|
|
930
|
-
/**
|
|
931
|
-
* Percentage of reportable activities played
|
|
932
|
-
* @name module:report/Reporter.ReporterInfo#ratioPlayed
|
|
933
|
-
* @type {number} */
|
|
934
|
-
ratioPlayed: 0,
|
|
935
|
-
/**
|
|
936
|
-
* Sum of the scores of all the activities played
|
|
937
|
-
* @name module:report/Reporter.ReporterInfo#tScore
|
|
938
|
-
* @type {number} */
|
|
939
|
-
tScore: 0,
|
|
940
|
-
/**
|
|
941
|
-
* Global score obtained
|
|
942
|
-
* @name module:report/Reporter.ReporterInfo#partialScore
|
|
943
|
-
* @type {number} */
|
|
944
|
-
partialScore: 0,
|
|
945
|
-
/**
|
|
946
|
-
* Sum of the playing time reported by each activity (not always equals to the sum of all session's time)
|
|
947
|
-
* @name module:report/Reporter.ReporterInfo#tTime
|
|
948
|
-
* @type {number} */
|
|
949
|
-
tTime: 0,
|
|
950
|
-
/**
|
|
951
|
-
* Final score based on the percent of reportable activities played. If the user plays all the
|
|
952
|
-
* activities, this result equals to `partialScore`.
|
|
953
|
-
* @name module:report/Reporter.ReporterInfo#globalScore
|
|
954
|
-
* @type {number} */
|
|
955
|
-
globalScore: 0,
|
|
956
|
-
});
|
|
957
|
-
|
|
958
|
-
Reporter.Info = ReporterInfo;
|
|
959
|
-
|
|
960
|
-
/**
|
|
961
|
-
* Static list of classes derived from Reporter. It should be filled by Reporter classes at declaration time.
|
|
962
|
-
* @type {object}
|
|
963
|
-
*/
|
|
964
|
-
Reporter.CLASSES = { 'Reporter': Reporter };
|
|
965
|
-
|
|
966
|
-
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (Reporter);
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
/***/ }),
|
|
970
|
-
|
|
971
|
-
/***/ 6565:
|
|
972
|
-
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
973
|
-
|
|
974
|
-
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
975
|
-
/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
|
|
976
|
-
/* harmony export */ });
|
|
977
|
-
/* unused harmony export SCORM */
|
|
978
|
-
/* harmony import */ var jquery__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(7750);
|
|
979
|
-
/* harmony import */ var jquery__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(jquery__WEBPACK_IMPORTED_MODULE_0__);
|
|
980
|
-
/* harmony import */ var _Utils_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(1253);
|
|
981
|
-
/**
|
|
982
|
-
* File : report/SCORM.js
|
|
983
|
-
* Created : 18/07/2016
|
|
984
|
-
* By : Francesc Busquets <francesc@gmail.com>
|
|
985
|
-
*
|
|
986
|
-
* JClic.js
|
|
987
|
-
* An HTML5 player of JClic activities
|
|
988
|
-
* https://projectestac.github.io/jclic.js
|
|
989
|
-
*
|
|
990
|
-
* @source https://github.com/projectestac/jclic.js
|
|
991
|
-
*
|
|
992
|
-
* @license EUPL-1.2
|
|
993
|
-
* @licstart
|
|
994
|
-
* (c) 2000-2020 Educational Telematic Network of Catalonia (XTEC)
|
|
995
|
-
*
|
|
996
|
-
* Licensed under the EUPL, Version 1.1 or -as soon they will be approved by
|
|
997
|
-
* the European Commission- subsequent versions of the EUPL (the "Licence");
|
|
998
|
-
* You may not use this work except in compliance with the Licence.
|
|
999
|
-
*
|
|
1000
|
-
* You may obtain a copy of the Licence at:
|
|
1001
|
-
* https://joinup.ec.europa.eu/software/page/eupl
|
|
1002
|
-
*
|
|
1003
|
-
* Unless required by applicable law or agreed to in writing, software
|
|
1004
|
-
* distributed under the Licence is distributed on an "AS IS" basis, WITHOUT
|
|
1005
|
-
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
1006
|
-
* Licence for the specific language governing permissions and limitations
|
|
1007
|
-
* under the Licence.
|
|
1008
|
-
* @licend
|
|
1009
|
-
* @module
|
|
1010
|
-
*/
|
|
1011
|
-
|
|
1012
|
-
/* global window */
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
/**
|
|
1018
|
-
* This class detects if JClic.js is running in an SCORM environment and, if true,
|
|
1019
|
-
* exposes the methods needed to notify the results of activities.
|
|
1020
|
-
* Both SCORM 1.2 and 2004 are supported.
|
|
1021
|
-
*/
|
|
1022
|
-
class SCORM {
|
|
1023
|
-
/**
|
|
1024
|
-
* SCORM constructor
|
|
1025
|
-
* @param {object} API - The global SCORM API object
|
|
1026
|
-
* @param {module:report/Reporter.Reporter} reporter - The {@link module:Reporter.Reporter Reporter} associated to this SCORM object
|
|
1027
|
-
*/
|
|
1028
|
-
constructor(API, reporter) {
|
|
1029
|
-
this.API = API;
|
|
1030
|
-
// Check if 'API' has a function named 'Initialized'
|
|
1031
|
-
if (typeof API.Initialize === 'function')
|
|
1032
|
-
this.is2004 = true;
|
|
1033
|
-
else {
|
|
1034
|
-
// SCORM 1.2
|
|
1035
|
-
this.prefix = 'LMS';
|
|
1036
|
-
this.core = 'cmi.core.';
|
|
1037
|
-
}
|
|
1038
|
-
this.reporter = reporter;
|
|
1039
|
-
}
|
|
1040
|
-
|
|
1041
|
-
/**
|
|
1042
|
-
* Recursive function used to find the SCORM "API" object
|
|
1043
|
-
* @param {object} win - The 'window' object to scan for global SCORM API objects
|
|
1044
|
-
* @param {number} tries - Recursive attempts currently achieved
|
|
1045
|
-
* @returns {object} - The global SCORM API object, or `null` if not found
|
|
1046
|
-
*/
|
|
1047
|
-
static scanForAPI(win, tries) {
|
|
1048
|
-
if (win.API_1484_11 && win.API_1184_11.Initialize && win.API_1184_11.SetValue && win.API_1184_11.Commit)
|
|
1049
|
-
return win.API_1184_11;
|
|
1050
|
-
else if (win.API && win.API.LMSInitialize && win.API.LMSSetValue && win.API.LMSCommit)
|
|
1051
|
-
return win.API;
|
|
1052
|
-
else if (win.parent && win.parent !== win && tries++ < SCORM.DISCOVER_MAX_TRIES)
|
|
1053
|
-
return SCORM.scanForAPI(win.parent, tries);
|
|
1054
|
-
else
|
|
1055
|
-
return null;
|
|
1056
|
-
}
|
|
1057
|
-
|
|
1058
|
-
/**
|
|
1059
|
-
* Checks for the presence of a SCORM API on the current browser session.
|
|
1060
|
-
* @param {module:report/Reporter.Reporter} reporter - The {@link module:Reporter.Reporter Reporter} linked to the requested SCORM object
|
|
1061
|
-
* @returns {module:report/SCORM.SCORM} - A valid SCORM object, or `null` if no SCORM API was found.
|
|
1062
|
-
*/
|
|
1063
|
-
static getSCORM(reporter) {
|
|
1064
|
-
let result = null;
|
|
1065
|
-
try {
|
|
1066
|
-
let api = SCORM.scanForAPI(window, 0);
|
|
1067
|
-
if (api === null && window.opener)
|
|
1068
|
-
api = SCORM.scanForAPI(window.opener, 0);
|
|
1069
|
-
|
|
1070
|
-
if (api) {
|
|
1071
|
-
result = new SCORM(api, reporter);
|
|
1072
|
-
if (!result.initialize())
|
|
1073
|
-
result = null;
|
|
1074
|
-
}
|
|
1075
|
-
} catch (ex) {
|
|
1076
|
-
result = null;
|
|
1077
|
-
(0,_Utils_js__WEBPACK_IMPORTED_MODULE_1__/* .log */ .Rm)('warn', 'Unable to use SCORM: %s', ex.toString());
|
|
1078
|
-
}
|
|
1079
|
-
return result;
|
|
1080
|
-
}
|
|
1081
|
-
|
|
1082
|
-
/**
|
|
1083
|
-
* Initializes communication with the SCORM API
|
|
1084
|
-
* @returns {boolean}
|
|
1085
|
-
*/
|
|
1086
|
-
initialize() {
|
|
1087
|
-
let result = false;
|
|
1088
|
-
try {
|
|
1089
|
-
result = this.API[this.prefix + 'Initialize']('');
|
|
1090
|
-
if (result) {
|
|
1091
|
-
this.studentId = this.getValue(this.core + (this.is2004 ? 'learner_id' : 'student_id'));
|
|
1092
|
-
this.studentName = this.getValue(this.core + (this.is2004 ? 'learner_name' : 'student_name'));
|
|
1093
|
-
this.setValue(this.core + 'score.min', 0);
|
|
1094
|
-
this.setValue(this.core + 'score.max', 100);
|
|
1095
|
-
jquery__WEBPACK_IMPORTED_MODULE_0___default()(window).on('unload', () => {
|
|
1096
|
-
this.commitInfo();
|
|
1097
|
-
this.terminate();
|
|
1098
|
-
this.API = null;
|
|
1099
|
-
});
|
|
1100
|
-
}
|
|
1101
|
-
(0,_Utils_js__WEBPACK_IMPORTED_MODULE_1__/* .log */ .Rm)('debug', 'SCORM initialized');
|
|
1102
|
-
} catch (ex) {
|
|
1103
|
-
(0,_Utils_js__WEBPACK_IMPORTED_MODULE_1__/* .log */ .Rm)('error', `Error initializing SCORM API: ${ex.message}`);
|
|
1104
|
-
}
|
|
1105
|
-
return result;
|
|
1106
|
-
}
|
|
1107
|
-
|
|
1108
|
-
/**
|
|
1109
|
-
* Terminates communication with the SCORM API
|
|
1110
|
-
* @returns {boolean}
|
|
1111
|
-
*/
|
|
1112
|
-
terminate() {
|
|
1113
|
-
let result = false;
|
|
1114
|
-
try {
|
|
1115
|
-
result = this.API[this.is2004 ? 'Terminate' : 'LMSFinish']('');
|
|
1116
|
-
} catch (ex) {
|
|
1117
|
-
(0,_Utils_js__WEBPACK_IMPORTED_MODULE_1__/* .log */ .Rm)('error', `Error terminating SCORM API: ${ex.message}`);
|
|
1118
|
-
}
|
|
1119
|
-
return result;
|
|
1120
|
-
}
|
|
1121
|
-
|
|
1122
|
-
/**
|
|
1123
|
-
* Commits the current information to the SCORM API
|
|
1124
|
-
*/
|
|
1125
|
-
commitInfo() {
|
|
1126
|
-
const
|
|
1127
|
-
info = this.reporter.getInfo(),
|
|
1128
|
-
score = Math.round(info.globalScore * 100),
|
|
1129
|
-
time = this.getTimeExpression(info.tTime);
|
|
1130
|
-
|
|
1131
|
-
this.setValue(this.core + 'score.raw', score);
|
|
1132
|
-
this.setValue(this.core + 'session_time', time);
|
|
1133
|
-
this.commit();
|
|
1134
|
-
(0,_Utils_js__WEBPACK_IMPORTED_MODULE_1__/* .log */ .Rm)('debug', `SCORM results reported: ${score} (${time})`);
|
|
1135
|
-
}
|
|
1136
|
-
|
|
1137
|
-
/**
|
|
1138
|
-
* Commits current pending data to the SCORM API
|
|
1139
|
-
* @returns {boolean}
|
|
1140
|
-
*/
|
|
1141
|
-
commit() {
|
|
1142
|
-
let result = false;
|
|
1143
|
-
try {
|
|
1144
|
-
result = this.API[this.prefix + 'Commit']('');
|
|
1145
|
-
} catch (ex) {
|
|
1146
|
-
(0,_Utils_js__WEBPACK_IMPORTED_MODULE_1__/* .log */ .Rm)('error', `Error commiting data to the SCORM API: ${ex.message}`);
|
|
1147
|
-
}
|
|
1148
|
-
return result;
|
|
1149
|
-
}
|
|
1150
|
-
|
|
1151
|
-
/**
|
|
1152
|
-
* Sends a specific value to the SCORM API
|
|
1153
|
-
* @param {string} key - A SCORM valid key
|
|
1154
|
-
* @param {string|number} value - The value associated with this key
|
|
1155
|
-
* @returns {string}
|
|
1156
|
-
*/
|
|
1157
|
-
setValue(key, value) {
|
|
1158
|
-
let result = false;
|
|
1159
|
-
try {
|
|
1160
|
-
result = this.API[this.prefix + 'SetValue'](key, value);
|
|
1161
|
-
} catch (ex) {
|
|
1162
|
-
(0,_Utils_js__WEBPACK_IMPORTED_MODULE_1__/* .log */ .Rm)('error', `Error setting value "${value}" to "${key}" in SCORM API: ${ex.message}`);
|
|
1163
|
-
}
|
|
1164
|
-
return result;
|
|
1165
|
-
}
|
|
1166
|
-
|
|
1167
|
-
/**
|
|
1168
|
-
* Gets a specific value from the SCORM API
|
|
1169
|
-
* @param {string} key - A SCORM valid key
|
|
1170
|
-
* @returns {string} - The value associated with the provided key, or `null` if not found
|
|
1171
|
-
*/
|
|
1172
|
-
getValue(key) {
|
|
1173
|
-
let result = false;
|
|
1174
|
-
try {
|
|
1175
|
-
result = this.API[this.prefix + 'GetValue'](key);
|
|
1176
|
-
} catch (ex) {
|
|
1177
|
-
(0,_Utils_js__WEBPACK_IMPORTED_MODULE_1__/* .log */ .Rm)('error', `Error retrieving "${key}" from SCORM API: ${ex.message}`);
|
|
1178
|
-
}
|
|
1179
|
-
return result;
|
|
1180
|
-
}
|
|
1181
|
-
|
|
1182
|
-
/**
|
|
1183
|
-
* Gets a string expression of the given time (in milliseconds) suitable for a SCORM transaction.
|
|
1184
|
-
* @see {@link http://www.ostyn.com/standards/scorm/samples/ISOTimeForSCORM.htm}
|
|
1185
|
-
* @param {number} millis - The amount of time, in milliseconds
|
|
1186
|
-
* @returns {string} - An ISO8601 valid expression
|
|
1187
|
-
*/
|
|
1188
|
-
getTimeExpression(millis) {
|
|
1189
|
-
const
|
|
1190
|
-
d = new Date(millis),
|
|
1191
|
-
h = d.getUTCHours(),
|
|
1192
|
-
m = d.getUTCMinutes(),
|
|
1193
|
-
s = d.getUTCSeconds();
|
|
1194
|
-
|
|
1195
|
-
return this.is2004 ?
|
|
1196
|
-
`PT${h}H${m}M${s}S` :
|
|
1197
|
-
`${('0000' + h).slice(-4)}:${('00' + m).slice(-2)}:${('00' + s).slice(-2)}`;
|
|
1198
|
-
}
|
|
1199
|
-
|
|
1200
|
-
/**
|
|
1201
|
-
* Gets the SCORM type of this SCORM object
|
|
1202
|
-
* @returns {string}
|
|
1203
|
-
*/
|
|
1204
|
-
getScormType() {
|
|
1205
|
-
return `SCORM ${this.is2004 ? '2004' : '1.2'}`;
|
|
1206
|
-
}
|
|
1207
|
-
}
|
|
1208
|
-
|
|
1209
|
-
Object.assign(SCORM.prototype, {
|
|
1210
|
-
/**
|
|
1211
|
-
* True when the API is of type SCORM 2004, false for SCORM 1.2
|
|
1212
|
-
* @name module:report/SCORM.SCORM#is2004
|
|
1213
|
-
* @type {boolean} */
|
|
1214
|
-
is2004: false,
|
|
1215
|
-
/**
|
|
1216
|
-
* The Reporter associated to this SCORM object
|
|
1217
|
-
* @name module:report/SCORM.SCORM#reporter
|
|
1218
|
-
* @type {module:report/Reporter.Reporter} */
|
|
1219
|
-
reporter: null,
|
|
1220
|
-
/**
|
|
1221
|
-
* Prefix to be used in SCORM function names. Should be 'LMS' for SCORM 1.2
|
|
1222
|
-
* @name module:report/SCORM.SCORM#prefix
|
|
1223
|
-
* @type {string} */
|
|
1224
|
-
prefix: '',
|
|
1225
|
-
/**
|
|
1226
|
-
* Prefix used in core SCORM keys. Should be 'cmi.core.' for 1.2 and 'cmi.' for 2004
|
|
1227
|
-
* @name module:report/SCORM.SCORM#core
|
|
1228
|
-
* @type {string} */
|
|
1229
|
-
core: 'cmi.',
|
|
1230
|
-
/**
|
|
1231
|
-
* SCORM API object used to communicate with the LMS
|
|
1232
|
-
* @name module:report/SCORM.SCORM#API
|
|
1233
|
-
* @type {object} */
|
|
1234
|
-
API: null,
|
|
1235
|
-
/**
|
|
1236
|
-
* The student ID retrieved from the SCORM API
|
|
1237
|
-
* @name module:report/SCORM.SCORM#studentId
|
|
1238
|
-
* @type {string} */
|
|
1239
|
-
studentId: '',
|
|
1240
|
-
/**
|
|
1241
|
-
* The student name retrieved from the SCORM API
|
|
1242
|
-
* @name module:report/SCORM.SCORM#studentName
|
|
1243
|
-
* @type {string} */
|
|
1244
|
-
studentName: '',
|
|
1245
|
-
});
|
|
1246
|
-
|
|
1247
|
-
/**
|
|
1248
|
-
* Maximum recursive attempts allowed to find the global SCORM API object
|
|
1249
|
-
* @type {number} */
|
|
1250
|
-
SCORM.DISCOVER_MAX_TRIES = 50;
|
|
1251
|
-
|
|
1252
|
-
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (SCORM);
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
/***/ }),
|
|
1256
|
-
|
|
1257
|
-
/***/ 8641:
|
|
1258
|
-
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
|
1259
|
-
|
|
1260
|
-
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
1261
|
-
/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
|
|
1262
|
-
/* harmony export */ });
|
|
1263
|
-
/* unused harmony exports SessionReg, SessionRegInfo */
|
|
1264
|
-
/* harmony import */ var _SequenceReg_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(6238);
|
|
1265
|
-
/**
|
|
1266
|
-
* File : report/SessionReg.js
|
|
1267
|
-
* Created : 17/05/2016
|
|
1268
|
-
* By : Francesc Busquets <francesc@gmail.com>
|
|
1269
|
-
*
|
|
1270
|
-
* JClic.js
|
|
1271
|
-
* An HTML5 player of JClic activities
|
|
1272
|
-
* https://projectestac.github.io/jclic.js
|
|
1273
|
-
*
|
|
1274
|
-
* @source https://github.com/projectestac/jclic.js
|
|
1275
|
-
*
|
|
1276
|
-
* @license EUPL-1.2
|
|
1277
|
-
* @licstart
|
|
1278
|
-
* (c) 2000-2020 Catalan Educational Telematic Network (XTEC)
|
|
1279
|
-
*
|
|
1280
|
-
* Licensed under the EUPL, Version 1.1 or -as soon they will be approved by
|
|
1281
|
-
* the European Commission- subsequent versions of the EUPL (the "Licence");
|
|
1282
|
-
* You may not use this work except in compliance with the Licence.
|
|
1283
|
-
*
|
|
1284
|
-
* You may obtain a copy of the Licence at:
|
|
1285
|
-
* https://joinup.ec.europa.eu/software/page/eupl
|
|
1286
|
-
*
|
|
1287
|
-
* Unless required by applicable law or agreed to in writing, software
|
|
1288
|
-
* distributed under the Licence is distributed on an "AS IS" basis, WITHOUT
|
|
1289
|
-
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
1290
|
-
* Licence for the specific language governing permissions and limitations
|
|
1291
|
-
* under the Licence.
|
|
1292
|
-
* @licend
|
|
1293
|
-
* @module
|
|
1294
|
-
*/
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
/**
|
|
1299
|
-
* This class encapsulates data of a user's working session, usually associated to a single {@link module:project/JClicProject.JClicProject JClicProject}
|
|
1300
|
-
* It's main component is `sequences`, an array of {@link module:report/SequenceReg.SequenceReg SequenceReg} objects.
|
|
1301
|
-
*/
|
|
1302
|
-
class SessionReg {
|
|
1303
|
-
/**
|
|
1304
|
-
* SessionReg constructor
|
|
1305
|
-
* @param {module:project/JClicProject.JClicProject} project - The JClicProject referenced by this session.
|
|
1306
|
-
* @param {string} [code] - Optional code to be used by this SessionReg
|
|
1307
|
-
*/
|
|
1308
|
-
constructor(project, code) {
|
|
1309
|
-
this.projectName = project.name;
|
|
1310
|
-
this.code = code || project.code;
|
|
1311
|
-
this.sequences = [];
|
|
1312
|
-
this.actNames = [];
|
|
1313
|
-
this.started = new Date();
|
|
1314
|
-
this.info = new SessionRegInfo(this);
|
|
1315
|
-
this.reportableActs = project.reportableActs;
|
|
1316
|
-
}
|
|
1317
|
-
|
|
1318
|
-
/**
|
|
1319
|
-
* Builds a complex object with the results of all activities done during this working session
|
|
1320
|
-
* @param {boolean} recalcInfo - When `true`, global variables (number of sequences, score, total time...)
|
|
1321
|
-
* will be recalculated from the data stored in the {@link module:report/SequenceReg.SequenceReg SequenceReg} objects.
|
|
1322
|
-
* @param {boolean} includeEmpty - When `true`, sequences without reported activities will be also included in the results
|
|
1323
|
-
* @returns {object} - An object containing the full session data
|
|
1324
|
-
*/
|
|
1325
|
-
getData(recalcInfo, includeEmpty) {
|
|
1326
|
-
if (recalcInfo)
|
|
1327
|
-
this.info.recalc();
|
|
1328
|
-
|
|
1329
|
-
const result = {
|
|
1330
|
-
projectName: this.projectName,
|
|
1331
|
-
played: this.info.nActivities,
|
|
1332
|
-
ratioPlayed: Math.round(this.info.ratioPlayed * 100),
|
|
1333
|
-
solved: this.info.nActSolved,
|
|
1334
|
-
ratioSolved: Math.round(this.info.ratioSolved * 100),
|
|
1335
|
-
actions: this.info.nActions,
|
|
1336
|
-
score: this.info.tScore,
|
|
1337
|
-
time: Math.round(this.info.tTime / 10) / 100,
|
|
1338
|
-
sequences: []
|
|
1339
|
-
};
|
|
1340
|
-
|
|
1341
|
-
this.sequences.forEach(s => {
|
|
1342
|
-
const seq = s.getData();
|
|
1343
|
-
if (includeEmpty || seq.activities.length > 0)
|
|
1344
|
-
result.sequences.push(seq);
|
|
1345
|
-
});
|
|
1346
|
-
return result;
|
|
1347
|
-
}
|
|
1348
|
-
|
|
1349
|
-
/**
|
|
1350
|
-
* Returns the `info` element associated to this SessionReg.
|
|
1351
|
-
* @returns {module:report/SessionReg.SessionRegInfo}
|
|
1352
|
-
*/
|
|
1353
|
-
getInfo() {
|
|
1354
|
-
return this.info.recalc();
|
|
1355
|
-
}
|
|
1356
|
-
|
|
1357
|
-
/**
|
|
1358
|
-
* Closes this session
|
|
1359
|
-
*/
|
|
1360
|
-
end() {
|
|
1361
|
-
this.endSequence();
|
|
1362
|
-
}
|
|
1363
|
-
|
|
1364
|
-
/**
|
|
1365
|
-
* This method should be called when the current working session finishes.
|
|
1366
|
-
*/
|
|
1367
|
-
endSequence() {
|
|
1368
|
-
if (this.currentSequence && this.currentSequence.totalTime === 0)
|
|
1369
|
-
this.currentSequence.endSequence();
|
|
1370
|
-
this.currentSequence = null;
|
|
1371
|
-
this.info.valid = false;
|
|
1372
|
-
}
|
|
1373
|
-
|
|
1374
|
-
/**
|
|
1375
|
-
* This method should be invoked when a new sequence starts
|
|
1376
|
-
* @param {module:bags/ActivitySequenceElement.ActivitySequenceElement} ase - The {@link module:bags/ActivitySequenceElement.ActivitySequenceElement ActivitySequenceElement} referenced by this sequence.
|
|
1377
|
-
*/
|
|
1378
|
-
newSequence(ase) {
|
|
1379
|
-
this.endSequence();
|
|
1380
|
-
this.currentSequence = new _SequenceReg_js__WEBPACK_IMPORTED_MODULE_0__["default"](ase);
|
|
1381
|
-
this.sequences.push(this.currentSequence);
|
|
1382
|
-
this.info.valid = false;
|
|
1383
|
-
}
|
|
1384
|
-
|
|
1385
|
-
/**
|
|
1386
|
-
* This method should be invoked when the user starts a new activity
|
|
1387
|
-
* @param {module:Activity.Activity} act - The {@link module:Activity.Activity Activity} that has just started
|
|
1388
|
-
*/
|
|
1389
|
-
newActivity(act) {
|
|
1390
|
-
if (this.currentSequence) {
|
|
1391
|
-
// Save activity name if not yet registered
|
|
1392
|
-
if (this.actNames.indexOf(act.name) === -1)
|
|
1393
|
-
this.actNames.push(act.name);
|
|
1394
|
-
this.currentSequence.newActivity(act);
|
|
1395
|
-
this.info.valid = false;
|
|
1396
|
-
}
|
|
1397
|
-
}
|
|
1398
|
-
|
|
1399
|
-
/**
|
|
1400
|
-
* This method should be called when the current activity finishes. Data about user's final results
|
|
1401
|
-
* on the activity will then be saved.
|
|
1402
|
-
* @param {number} score - The final score, usually in a 0-100 scale.
|
|
1403
|
-
* @param {number} numActions - The total number of actions done by the user to solve the activity
|
|
1404
|
-
* @param {boolean} solved - `true` if the activity was finally solved, `false` otherwise.
|
|
1405
|
-
*/
|
|
1406
|
-
endActivity(score, numActions, solved) {
|
|
1407
|
-
if (this.currentSequence) {
|
|
1408
|
-
this.currentSequence.endActivity(score, numActions, solved);
|
|
1409
|
-
this.info.valid = false;
|
|
1410
|
-
}
|
|
1411
|
-
}
|
|
1412
|
-
|
|
1413
|
-
/**
|
|
1414
|
-
* Reports a new action done by the user while playing the current activity
|
|
1415
|
-
* @param {string} type - Type of action (`click`, `write`, `move`, `select`...)
|
|
1416
|
-
* @param {string}+ source - Description of the object on which the action is done.
|
|
1417
|
-
* @param {string}+ dest - Description of the object that acts as a target of the action (used in pairings)
|
|
1418
|
-
* @param {boolean} ok - `true` if the action was OK, `false`, `null` or `undefined` otherwise
|
|
1419
|
-
*/
|
|
1420
|
-
newAction(type, source, dest, ok) {
|
|
1421
|
-
if (this.currentSequence) {
|
|
1422
|
-
this.currentSequence.newAction(type, source, dest, ok);
|
|
1423
|
-
this.info.valid = false;
|
|
1424
|
-
}
|
|
1425
|
-
}
|
|
1426
|
-
|
|
1427
|
-
/**
|
|
1428
|
-
* Gets the name of the current sequence
|
|
1429
|
-
* @returns {string}
|
|
1430
|
-
*/
|
|
1431
|
-
getCurrentSequenceTag() {
|
|
1432
|
-
return this.currentSequence ? this.currentSequence.name : null;
|
|
1433
|
-
}
|
|
1434
|
-
|
|
1435
|
-
/**
|
|
1436
|
-
* Gets information about the current sequence
|
|
1437
|
-
* @returns {module:report/SequenceReg.SequenceRegInfo}
|
|
1438
|
-
*/
|
|
1439
|
-
getCurrentSequenceInfo() {
|
|
1440
|
-
return this.currentSequence ? this.currentSequence.getInfo() : null;
|
|
1441
|
-
}
|
|
1442
|
-
}
|
|
1443
|
-
|
|
1444
|
-
Object.assign(SessionReg.prototype, {
|
|
1445
|
-
/**
|
|
1446
|
-
* Number of activities suitable to be reported in this session
|
|
1447
|
-
* @name module:report/SessionReg.SessionReg#reportableActs
|
|
1448
|
-
* @type {number} */
|
|
1449
|
-
reportableActs: 0,
|
|
1450
|
-
/**
|
|
1451
|
-
* Array with unique names of the activities being reported in this session
|
|
1452
|
-
* @name module:report/SessionReg.SessionReg#actNames
|
|
1453
|
-
* @type {string[]} */
|
|
1454
|
-
actNames: null,
|
|
1455
|
-
/**
|
|
1456
|
-
* List of sequences done in this session
|
|
1457
|
-
* @name module:report/SessionReg.SessionReg#sequences
|
|
1458
|
-
* @type {module:report/SequenceReg.SequenceReg[]} */
|
|
1459
|
-
sequences: null,
|
|
1460
|
-
/**
|
|
1461
|
-
* The sequence currently active
|
|
1462
|
-
* @name module:report/SessionReg.SessionReg#currentSequence
|
|
1463
|
-
* @type {module:report/SequenceReg.SequenceReg} */
|
|
1464
|
-
currentSequence: null,
|
|
1465
|
-
/**
|
|
1466
|
-
* Starting date and time of this session
|
|
1467
|
-
* @name module:report/SessionReg.SessionReg#started
|
|
1468
|
-
* @type {external:Date} */
|
|
1469
|
-
started: null,
|
|
1470
|
-
/**
|
|
1471
|
-
* Name of the {@link module:project/JClicProject.JClicProject JClicProject} associated to this session
|
|
1472
|
-
* @name module:report/SessionReg.SessionReg#projectName
|
|
1473
|
-
* @type {string} */
|
|
1474
|
-
projectName: '',
|
|
1475
|
-
/**
|
|
1476
|
-
* Current session info
|
|
1477
|
-
* @name module:report/SessionReg.SessionReg#info
|
|
1478
|
-
* @type {module:report/SessionReg.SessionRegInfo} */
|
|
1479
|
-
info: null,
|
|
1480
|
-
/**
|
|
1481
|
-
* Optional code to be used with this session
|
|
1482
|
-
* @name module:report/SessionReg.SessionReg#code
|
|
1483
|
-
* @type {string} */
|
|
1484
|
-
code: null,
|
|
1485
|
-
});
|
|
1486
|
-
|
|
1487
|
-
/**
|
|
1488
|
-
* This object stores the global results of a {@link module:report/SessionReg.SessionReg SessionReg}
|
|
1489
|
-
*/
|
|
1490
|
-
class SessionRegInfo {
|
|
1491
|
-
/**
|
|
1492
|
-
* SessionRegInfo constructor
|
|
1493
|
-
* @param {module:report/SessionReg.SessionReg} sReg - The {@link module:report/SessionReg.SessionReg SessionReg} associated tho this `Info` object.
|
|
1494
|
-
*/
|
|
1495
|
-
constructor(sReg) {
|
|
1496
|
-
this.sReg = sReg;
|
|
1497
|
-
}
|
|
1498
|
-
|
|
1499
|
-
/**
|
|
1500
|
-
* Clears all data associated with this working session
|
|
1501
|
-
*/
|
|
1502
|
-
clear() {
|
|
1503
|
-
this.numSequences = this.nActivities = this.nActSolved = this.nActScore = 0;
|
|
1504
|
-
this.ratioSolved = this.ratioPlayed = this.nActions = this.tScore = this.tTime = 0;
|
|
1505
|
-
this.valid = false;
|
|
1506
|
-
}
|
|
1507
|
-
|
|
1508
|
-
/**
|
|
1509
|
-
* Computes the value of all global variables based on the data stored in `sequences`
|
|
1510
|
-
* @returns {module:report/SessionReg.SessionRegInfo} - This "info" object
|
|
1511
|
-
*/
|
|
1512
|
-
recalc() {
|
|
1513
|
-
if (!this.valid) {
|
|
1514
|
-
this.clear();
|
|
1515
|
-
this.sReg.sequences.forEach(sr => {
|
|
1516
|
-
const sri = sr.getInfo();
|
|
1517
|
-
if (sri.nActivities > 0) {
|
|
1518
|
-
this.numSequences++;
|
|
1519
|
-
if (sri.nActClosed > 0) {
|
|
1520
|
-
this.nActivities += sri.nActClosed;
|
|
1521
|
-
this.nActions += sri.nActions;
|
|
1522
|
-
if (sri.nActScore > 0) {
|
|
1523
|
-
this.nActScore += sri.nActScore;
|
|
1524
|
-
this.tScore += sri.tScore * sri.nActScore;
|
|
1525
|
-
}
|
|
1526
|
-
this.tTime += sri.tTime;
|
|
1527
|
-
this.nActSolved += sri.nActSolved;
|
|
1528
|
-
}
|
|
1529
|
-
}
|
|
1530
|
-
});
|
|
1531
|
-
if (this.nActScore > 0)
|
|
1532
|
-
this.tScore = Math.round(this.tScore / this.nActScore);
|
|
1533
|
-
if (this.nActivities > 0) {
|
|
1534
|
-
this.ratioSolved = this.nActSolved / this.nActivities;
|
|
1535
|
-
if (this.sReg.reportableActs > 0)
|
|
1536
|
-
this.ratioPlayed = this.sReg.actNames.length / this.sReg.reportableActs;
|
|
1537
|
-
}
|
|
1538
|
-
this.valid = true;
|
|
1539
|
-
}
|
|
1540
|
-
return this;
|
|
1541
|
-
}
|
|
1542
|
-
}
|
|
1543
|
-
|
|
1544
|
-
Object.assign(SessionRegInfo.prototype, {
|
|
1545
|
-
/**
|
|
1546
|
-
* The SessionReg linked to this Info object
|
|
1547
|
-
* @name module:report/SessionReg.SessionRegInfo#sReg
|
|
1548
|
-
* @type {module:report/SessionReg.SessionReg} */
|
|
1549
|
-
sReg: null,
|
|
1550
|
-
/**
|
|
1551
|
-
* When `false`, this session info needs to be recalculated
|
|
1552
|
-
* @name module:report/SessionReg.SessionRegInfo#valid
|
|
1553
|
-
* @type {boolean} */
|
|
1554
|
-
valid: false,
|
|
1555
|
-
/**
|
|
1556
|
-
* Number of sequences played
|
|
1557
|
-
* @name module:report/SessionReg.SessionRegInfo#numSequences
|
|
1558
|
-
* @type {number} */
|
|
1559
|
-
numSequences: 0,
|
|
1560
|
-
/**
|
|
1561
|
-
* Number of activities played
|
|
1562
|
-
* @name module:report/SessionReg.SessionRegInfo#nActivities
|
|
1563
|
-
* @type {number} */
|
|
1564
|
-
nActivities: 0,
|
|
1565
|
-
/**
|
|
1566
|
-
* Number of activities solved
|
|
1567
|
-
* @name module:report/SessionReg.SessionRegInfo#nActSolved
|
|
1568
|
-
* @type {number} */
|
|
1569
|
-
nActSolved: 0,
|
|
1570
|
-
/**
|
|
1571
|
-
* Number of activities with score > 0
|
|
1572
|
-
* @name module:report/SessionReg.SessionRegInfo#nActScore
|
|
1573
|
-
* @type {number} */
|
|
1574
|
-
nActScore: 0,
|
|
1575
|
-
/**
|
|
1576
|
-
* Percentage of solved activities
|
|
1577
|
-
* @name module:report/SessionReg.SessionRegInfo#ratioSolved
|
|
1578
|
-
* @type {number} */
|
|
1579
|
-
ratioSolved: 0,
|
|
1580
|
-
/**
|
|
1581
|
-
* Percentage of reportable activities played
|
|
1582
|
-
* @name module:report/SessionReg.SessionRegInfo#ratioPlayed
|
|
1583
|
-
* @type {number} */
|
|
1584
|
-
ratioPlayed: 0,
|
|
1585
|
-
/**
|
|
1586
|
-
* Number of actions done by the user while in this working session
|
|
1587
|
-
* @name module:report/SessionReg.SessionRegInfo#nActions
|
|
1588
|
-
* @type {number} */
|
|
1589
|
-
nActions: 0,
|
|
1590
|
-
/**
|
|
1591
|
-
* Sum of the scores of all the activities played
|
|
1592
|
-
* @name module:report/SessionReg.SessionRegInfo#tScore
|
|
1593
|
-
* @type {number} */
|
|
1594
|
-
tScore: 0,
|
|
1595
|
-
/**
|
|
1596
|
-
* Sum of the playing time reported by each activity (not always equals to the session's total time)
|
|
1597
|
-
* @name module:report/SessionReg.SessionRegInfo#tTime
|
|
1598
|
-
* @type {number} */
|
|
1599
|
-
tTime: 0,
|
|
1600
|
-
});
|
|
1601
|
-
|
|
1602
|
-
SessionReg.Info = SessionRegInfo;
|
|
1603
|
-
|
|
1604
|
-
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (SessionReg);
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
/***/ })
|
|
1608
|
-
|
|
1609
|
-
};
|
|
1610
|
-
;
|
|
1611
|
-
//# sourceMappingURL=6782.jclic-node.js.map
|