jclic 2.2.0 → 2.3.0

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.
Files changed (177) hide show
  1. package/README.md +5 -7
  2. package/dist-node/jclic-node.js +14157 -0
  3. package/dist-node/jclic-node.umd.cjs +530 -0
  4. package/package.json +38 -26
  5. package/.vscode/launch.json +0 -33
  6. package/.vscode/settings.json +0 -13
  7. package/CHANGELOG.md +0 -664
  8. package/TRANSLATIONS.md +0 -11
  9. package/build-locales.mjs +0 -82
  10. package/dist/jclic-node.js +0 -31678
  11. package/dist/jclic-node.js.map +0 -1
  12. package/dist/jclic.components.LICENSE +0 -2254
  13. package/dist/jclic.min.js +0 -27
  14. package/dist/jclic.min.js.map +0 -1
  15. package/eslint.config.mjs +0 -31
  16. package/jsdoc.config.js +0 -71
  17. package/locales/ar.po +0 -244
  18. package/locales/ast.po +0 -246
  19. package/locales/bs.po +0 -247
  20. package/locales/ca.po +0 -248
  21. package/locales/ca_ES@valencia.po +0 -248
  22. package/locales/cs.po +0 -244
  23. package/locales/da.po +0 -244
  24. package/locales/de.po +0 -246
  25. package/locales/el.po +0 -244
  26. package/locales/es.po +0 -248
  27. package/locales/eu.po +0 -244
  28. package/locales/fr.po +0 -244
  29. package/locales/gl.po +0 -244
  30. package/locales/he.po +0 -244
  31. package/locales/hr.po +0 -245
  32. package/locales/it.po +0 -246
  33. package/locales/ja.po +0 -242
  34. package/locales/jclic.js.pot +0 -241
  35. package/locales/nb_NO.po +0 -244
  36. package/locales/nl.po +0 -244
  37. package/locales/pl.po +0 -244
  38. package/locales/pt.po +0 -244
  39. package/locales/pt_BR.po +0 -248
  40. package/locales/ro.po +0 -248
  41. package/locales/ru.po +0 -245
  42. package/locales/ta.po +0 -244
  43. package/locales/tr.po +0 -246
  44. package/locales/uk.po +0 -247
  45. package/locales/vec.po +0 -244
  46. package/locales/zh_TW.po +0 -246
  47. package/patches/po2json+1.0.0-beta-3.patch +0 -12
  48. package/src/AWT.js +0 -2067
  49. package/src/Activity.js +0 -1311
  50. package/src/Deps.js +0 -232
  51. package/src/GlobalData.js +0 -5
  52. package/src/JClic.js +0 -196
  53. package/src/JClicPlayer.js +0 -1308
  54. package/src/PlayerHistory.js +0 -305
  55. package/src/Utils.js +0 -1355
  56. package/src/activities/associations/ComplexAssociation.js +0 -321
  57. package/src/activities/associations/SimpleAssociation.js +0 -519
  58. package/src/activities/memory/MemoryGame.js +0 -423
  59. package/src/activities/panels/Explore.js +0 -349
  60. package/src/activities/panels/Identify.js +0 -356
  61. package/src/activities/panels/InformationScreen.js +0 -262
  62. package/src/activities/panels/Menu.js +0 -209
  63. package/src/activities/panels/icons/ico00.png +0 -0
  64. package/src/activities/panels/icons/ico01.png +0 -0
  65. package/src/activities/panels/icons/ico02.png +0 -0
  66. package/src/activities/panels/icons/ico03.png +0 -0
  67. package/src/activities/panels/icons/icofolder.png +0 -0
  68. package/src/activities/puzzles/DoublePuzzle.js +0 -424
  69. package/src/activities/puzzles/ExchangePuzzle.js +0 -374
  70. package/src/activities/puzzles/HolePuzzle.js +0 -360
  71. package/src/activities/text/Complete.js +0 -127
  72. package/src/activities/text/Evaluator.js +0 -534
  73. package/src/activities/text/FillInBlanks.js +0 -426
  74. package/src/activities/text/IdentifyText.js +0 -253
  75. package/src/activities/text/OrderText.js +0 -421
  76. package/src/activities/text/TextActivityBase.js +0 -557
  77. package/src/activities/text/TextActivityDocument.js +0 -658
  78. package/src/activities/text/WrittenAnswer.js +0 -557
  79. package/src/activities/textGrid/CrossWord.js +0 -565
  80. package/src/activities/textGrid/WordSearch.js +0 -458
  81. package/src/activities/textGrid/icons/hIcon.svg +0 -3
  82. package/src/activities/textGrid/icons/vIcon.svg +0 -3
  83. package/src/automation/AutoContentProvider.js +0 -182
  84. package/src/automation/arith/Arith.js +0 -864
  85. package/src/bags/ActivitySequence.js +0 -318
  86. package/src/bags/ActivitySequenceElement.js +0 -161
  87. package/src/bags/ActivitySequenceJump.js +0 -140
  88. package/src/bags/ConditionalJumpInfo.js +0 -113
  89. package/src/bags/JumpInfo.js +0 -136
  90. package/src/bags/MediaBag.js +0 -215
  91. package/src/bags/MediaBagElement.js +0 -516
  92. package/src/boxes/AbstractBox.js +0 -699
  93. package/src/boxes/ActiveBagContent.js +0 -494
  94. package/src/boxes/ActiveBox.js +0 -810
  95. package/src/boxes/ActiveBoxBag.js +0 -357
  96. package/src/boxes/ActiveBoxContent.js +0 -484
  97. package/src/boxes/ActiveBoxGrid.js +0 -179
  98. package/src/boxes/BoxBag.js +0 -500
  99. package/src/boxes/BoxBase.js +0 -398
  100. package/src/boxes/BoxConnector.js +0 -325
  101. package/src/boxes/TextGrid.js +0 -887
  102. package/src/boxes/TextGridContent.js +0 -215
  103. package/src/init-jsdom.js +0 -65
  104. package/src/jclic-node.js +0 -219
  105. package/src/media/ActiveMediaBag.js +0 -145
  106. package/src/media/ActiveMediaPlayer.js +0 -297
  107. package/src/media/AudioBuffer.js +0 -219
  108. package/src/media/EventSounds.js +0 -169
  109. package/src/media/EventSoundsElement.js +0 -155
  110. package/src/media/MediaContent.js +0 -328
  111. package/src/media/MidiAudioPlayer.js +0 -254
  112. package/src/media/icons/audio.svg +0 -3
  113. package/src/media/icons/generic.svg +0 -3
  114. package/src/media/icons/mic.svg +0 -3
  115. package/src/media/icons/movie.svg +0 -3
  116. package/src/media/icons/music.svg +0 -3
  117. package/src/media/icons/url.svg +0 -3
  118. package/src/media/sounds/actionError.mp3 +0 -0
  119. package/src/media/sounds/actionOk.mp3 +0 -0
  120. package/src/media/sounds/click.mp3 +0 -0
  121. package/src/media/sounds/finishedError.mp3 +0 -0
  122. package/src/media/sounds/finishedOk.mp3 +0 -0
  123. package/src/media/sounds/start.mp3 +0 -0
  124. package/src/project/JClicProject.js +0 -282
  125. package/src/project/ProjectSettings.js +0 -273
  126. package/src/report/ActionReg.js +0 -123
  127. package/src/report/ActivityReg.js +0 -271
  128. package/src/report/EncryptMin.js +0 -210
  129. package/src/report/Reporter.js +0 -727
  130. package/src/report/SCORM.js +0 -272
  131. package/src/report/SequenceReg.js +0 -275
  132. package/src/report/SessionReg.js +0 -340
  133. package/src/report/SessionStorageReporter.js +0 -131
  134. package/src/report/TCPReporter.js +0 -628
  135. package/src/shapers/ClassicJigSaw.js +0 -138
  136. package/src/shapers/Holes.js +0 -77
  137. package/src/shapers/JigSaw.js +0 -161
  138. package/src/shapers/Rectangular.js +0 -78
  139. package/src/shapers/Shaper.js +0 -386
  140. package/src/shapers/TriangularJigSaw.js +0 -121
  141. package/src/skins/BlueSkin.js +0 -80
  142. package/src/skins/Counter.js +0 -152
  143. package/src/skins/CustomSkin.js +0 -412
  144. package/src/skins/DefaultSkin.js +0 -376
  145. package/src/skins/EmptySkin.js +0 -82
  146. package/src/skins/GreenSkin.js +0 -94
  147. package/src/skins/MiniSkin.js +0 -130
  148. package/src/skins/OrangeSkin.js +0 -78
  149. package/src/skins/SimpleSkin.js +0 -92
  150. package/src/skins/Skin.js +0 -1021
  151. package/src/skins/assets/actionsIcon.svg +0 -3
  152. package/src/skins/assets/appLogo.svg +0 -8
  153. package/src/skins/assets/basic.css +0 -41
  154. package/src/skins/assets/closeDialogIcon.svg +0 -3
  155. package/src/skins/assets/closeIcon.svg +0 -3
  156. package/src/skins/assets/copyIcon.svg +0 -3
  157. package/src/skins/assets/fullScreenExitIcon.svg +0 -3
  158. package/src/skins/assets/fullScreenIcon.svg +0 -3
  159. package/src/skins/assets/infoIcon.svg +0 -3
  160. package/src/skins/assets/main.css +0 -43
  161. package/src/skins/assets/mainHalf.css +0 -23
  162. package/src/skins/assets/mainTwoThirds.css +0 -23
  163. package/src/skins/assets/mini.css +0 -15
  164. package/src/skins/assets/nextIcon.svg +0 -3
  165. package/src/skins/assets/okDialogIcon.svg +0 -3
  166. package/src/skins/assets/prevIcon.svg +0 -3
  167. package/src/skins/assets/reports.css +0 -156
  168. package/src/skins/assets/reportsIcon.svg +0 -3
  169. package/src/skins/assets/scoreIcon.svg +0 -3
  170. package/src/skins/assets/simple.css +0 -16
  171. package/src/skins/assets/simpleHalf.css +0 -11
  172. package/src/skins/assets/simpleTwoThirds.css +0 -11
  173. package/src/skins/assets/timeIcon.svg +0 -4
  174. package/src/skins/assets/waitAnim.css +0 -54
  175. package/src/skins/assets/waitImgBig.svg +0 -3
  176. package/src/skins/assets/waitImgSmall.svg +0 -3
  177. package/webpack.config.mjs +0 -169
@@ -1,628 +0,0 @@
1
- /**
2
- * File : report/TCPReporter.js
3
- * Created : 08/06/2016
4
- * By : Francesc Busquets <francesc@gmail.com>
5
- *
6
- * JClic.js
7
- * An HTML5 player of JClic activities
8
- * https://projectestac.github.io/jclic.js
9
- *
10
- * @source https://github.com/projectestac/jclic.js
11
- *
12
- * @license EUPL-1.2
13
- * @licstart
14
- * (c) 2000-2020 Catalan Educational Telematic Network (XTEC)
15
- *
16
- * Licensed under the EUPL, Version 1.1 or -as soon they will be approved by
17
- * the European Commission- subsequent versions of the EUPL (the "Licence");
18
- * You may not use this work except in compliance with the Licence.
19
- *
20
- * You may obtain a copy of the Licence at:
21
- * https://joinup.ec.europa.eu/software/page/eupl
22
- *
23
- * Unless required by applicable law or agreed to in writing, software
24
- * distributed under the Licence is distributed on an "AS IS" basis, WITHOUT
25
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
26
- * Licence for the specific language governing permissions and limitations
27
- * under the Licence.
28
- * @licend
29
- * @module
30
- */
31
-
32
- /* global Promise, document, window, XMLSerializer */
33
-
34
- import $ from 'jquery';
35
- import Reporter from './Reporter.js';
36
- import { log, startsWith, getMsg } from '../Utils.js';
37
-
38
- /**
39
- * This special case of {@link module:Reporter.Reporter Reporter} connects with an external service reporter providing
40
- * the {@link https://github.com/projectestac/jclic/wiki/JClic-Reports-developers-guide JClic Reports API}.
41
- * Connection parameters to the reports server (`path`, `service`, `userId`, `key`, `context`...)
42
- * are passed through the `options` element of {@link module:JClicPlayer.JClicPlayer JClicPlayer} (acting as {@link module:JClicPlayer.JClicPlayer JClicPlayer}).
43
- * @extends module:reports/Reporter.Reporter
44
- */
45
- export class TCPReporter extends Reporter {
46
- /**
47
- * TCPReporter constructor
48
- * @param {module:JClicPlayer.JClicPlayer} ps - The {@link module:JClicPlayer.JClicPlayer JClicPlayer} used to retrieve settings and localized messages
49
- */
50
- constructor(ps) {
51
- super(ps);
52
- this.tasks = [];
53
- }
54
-
55
- /**
56
- * Gets a specific property from this reporting system
57
- * @override
58
- * @param {string} key - Requested property
59
- * @param {string}+ defaultValue - Default return value when requested property does not exist
60
- * @returns {string}
61
- */
62
- getProperty(key, defaultValue) {
63
- return this.dbProperties !== null && this.dbProperties.hasOwnProperty(key) ?
64
- this.dbProperties[key] :
65
- defaultValue;
66
- }
67
-
68
- /**
69
- * Adds a new element to the list of report beans pending to be transmitted.
70
- * @param {module:report/TCPReporter.ReportBean} bean
71
- */
72
- addTask(bean) {
73
- if (this.processingTasks) {
74
- if (this.waitingTasks === null)
75
- this.waitingTasks = [bean];
76
- else
77
- this.waitingTasks.push(bean);
78
- } else
79
- this.tasks.push(bean);
80
- }
81
-
82
- /**
83
- * Transmits all report beans currently stored in `tasks` to the reports server
84
- * @returns {external:Promise}
85
- */
86
- flushTasksPromise() {
87
- if (this.processingTasks || this.currentSessionId === null ||
88
- this.tasks.length === 0 || this.serviceUrl === null) {
89
- // The task list cannot be processed now. Pass and wait until the next timer cycle:
90
- if (this.processingTasks)
91
- this.forceFlush = true;
92
- return Promise.resolve(true);
93
- }
94
- else {
95
- // Set up the `processingTasks` flag to avoid re-entrant processing
96
- this.processingTasks = true;
97
-
98
- const reportBean = new ReportBean('multiple');
99
- for (let i = 0; i < this.tasks.length; i++)
100
- reportBean.appendData(this.tasks[i].$bean);
101
-
102
- log('debug', 'Reporting:', reportBean.$bean[0]);
103
-
104
- return new Promise((resolve, reject) => {
105
- this.transaction(reportBean.$bean)
106
- .done((_data, _textStatus, _jqXHR) => {
107
- // TODO: Check returned message for possible errors on the server side
108
- this.failCount = 0;
109
-
110
- // Clear waiting tasks
111
- if (this.waitingTasks) {
112
- this.tasks = this.waitingTasks;
113
- this.waitingTasks = null;
114
- }
115
- else {
116
- this.forceFlush = false;
117
- this.tasks = [];
118
- }
119
-
120
- if (this.forceFlush && this.tasks.length > 0) {
121
- this.forceFlush = false;
122
- this.processingTasks = false;
123
- this.flushTasksPromise().then(() => {
124
- resolve(true);
125
- });
126
- }
127
- else {
128
- this.forceFlush = false;
129
- resolve(true);
130
- this.processingTasks = false;
131
- }
132
- })
133
- .fail((jqXHR, textStatus, errorThrown) => {
134
- if (++this.failCount > this.maxFails)
135
- this.stopReporting().then();
136
- reject(`Error reporting results to ${this.serviceUrl} [${textStatus} ${errorThrown}]`);
137
- this.processingTasks = false;
138
- });
139
- });
140
- }
141
- }
142
-
143
- /**
144
- * Initializes this report system with an optional set of parameters.
145
- * Returns a Promise, fulfilled when the reporter is fully initialized.
146
- * @override
147
- * @param {object} [options] - Initial settings passed to the reporting system
148
- * @returns {external:Promise}
149
- */
150
- init(options) {
151
- if (typeof options === 'undefined' || options === null)
152
- options = this.ps.options;
153
- super.init(options);
154
- this.initiated = false;
155
- this.stopReporting();
156
-
157
- this.serverPath = options.path || this.DEFAULT_SERVER_PATH;
158
- this.descriptionDetail = this.serverPath;
159
- let serverService = options.service || this.DEFAULT_SERVER_SERVICE;
160
- if (!startsWith(serverService, '/'))
161
- serverService = `/${serverService}`;
162
- const serverProtocol = options.protocol || this.DEFAULT_SERVER_PROTOCOL;
163
- this.serviceUrl = `${serverProtocol}://${this.serverPath}${serverService}`;
164
-
165
- const bean = new ReportBean('get_properties');
166
- return new Promise((resolve, reject) => {
167
- this.transaction(bean.$bean)
168
- .done((data, _textStatus, _jqXHR) => {
169
- this.dbProperties = {};
170
- $(data).find('param').each((_n, param) => {
171
- const $param = $(param);
172
- this.dbProperties[$param.attr('name')] = $param.attr('value');
173
- });
174
- this.promptUserId(false).then(userId => {
175
- this.userId = userId;
176
- const tl = options.lap || this.getProperty('TIME_LAP', this.DEFAULT_TIMER_LAP);
177
- this.timerLap = Math.min(30, Math.max(1, parseInt(tl)));
178
- this.timer = window.setInterval(() => this.flushTasksPromise().then(), this.timerLap * 1000);
179
- // Warn before leaving the current page with unsaved data:
180
- this.beforeUnloadFunction = event => {
181
- if (this.serviceUrl !== null &&
182
- (this.tasks.length > 0 || this.processingTasks)) {
183
- this.flushTasksPromise().then();
184
- const result = getMsg('Please wait until the results of your activities are sent to the reports system');
185
- if (event)
186
- event.returnValue = result;
187
- return result;
188
- }
189
- };
190
- window.addEventListener('beforeunload', this.beforeUnloadFunction);
191
- this.initiated = true;
192
- resolve(true);
193
- }).catch(msg => {
194
- this.stopReporting();
195
- reject(`Error getting the user ID: ${msg}`);
196
- });
197
- })
198
- .fail((jqXHR, textStatus, errorThrown) => {
199
- this.stopReporting();
200
- reject(`Error initializing reports service ${this.serviceUrl} [${textStatus} ${errorThrown}]`);
201
- });
202
- });
203
- }
204
-
205
- /**
206
- * This method should be invoked when a new session starts.
207
- * @override
208
- * @param {module:project/JClicProject.JClicProject} jcp - The {@link module:project/JClicProject.JClicProject JClicProject} this session refers to.
209
- */
210
- newSession(jcp) {
211
- super.newSession(jcp);
212
- if (this.serviceUrl && this.userId !== null) {
213
- // Session ID will be obtained when reporting first activity
214
- this.currentSessionId = null;
215
- }
216
- }
217
-
218
- /**
219
- * Creates a new session in the remote database and records its ID for future use
220
- * @param {boolean} forceNewSession - When `true`, a new session will always be created.
221
- * @returns {external:Promise} - A Promise reporter will be successfully resolved
222
- * only when `currentSessionId` have a valid value.
223
- */
224
- createDBSession(forceNewSession) {
225
- if (this.currentSessionId !== null && !forceNewSession)
226
- // A valid session is available, so just return it
227
- return Promise.resolve(this.currentSessionId);
228
- else
229
- // A new session must be created:
230
- return new Promise((resolve, reject) => {
231
- if (this.initiated && this.userId !== null && this.currentSession !== null) {
232
- this.flushTasksPromise().then(() => {
233
- this.currentSessionId = null;
234
- const bean = new ReportBean('add session');
235
-
236
- bean.setParam('project', this.currentSession.projectName);
237
- bean.setParam('activities', Number(this.currentSession.reportableActs));
238
- bean.setParam('time', Number(this.currentSession.started));
239
- bean.setParam('code', this.currentSession.code);
240
- bean.setParam('user', this.userId);
241
- bean.setParam('key', this.sessionKey);
242
- bean.setParam('context', this.sessionContext);
243
-
244
- this.transaction(bean.$bean)
245
- .done((data, _textStatus, _jqXHR) => {
246
- this.currentSessionId = $(data).find('param[name="session"]').attr('value');
247
- resolve(this.currentSessionId);
248
- })
249
- .fail((jqXHR, textStatus, errorThrown) => {
250
- this.stopReporting();
251
- reject(`Error creating new reports session in ${this.serviceUrl} [${textStatus} ${errorThrown}]`);
252
- });
253
- });
254
- } else
255
- reject('Unable to start session in remote server!');
256
- });
257
- }
258
-
259
- /**
260
- * Closes this reporting system
261
- * @override
262
- * @returns {external:Promise} - A promise to be fullfilled when all pending tasks are finished, or _null_ if not active.
263
- */
264
- end() {
265
- this.reportActivity(true);
266
- return this.stopReporting().then(super.end());
267
- }
268
-
269
- /**
270
- * Performs a transaction on the remote server
271
- * @param {external:jQuery} $xml - The XML element to be transmited, wrapped into a jQuery object
272
- * @returns {external:jqXHR} - The {@link external:jqXHR} obtained as a result of a call to `$.ajax`.
273
- * This object should be treated as a Promise or
274
- * as a JQuery {@link https://api.jquery.com/category/deferred-object|Deferred} object.
275
- */
276
- transaction($xml) {
277
- return this.serviceUrl === null ?
278
- null :
279
- $.ajax({
280
- method: 'POST',
281
- url: this.serviceUrl,
282
- data: '<?xml version="1.0" encoding="UTF-8"?>' +
283
- (new XMLSerializer()).serializeToString($xml.get(0)).replace('minactions', 'minActions').replace('reportactions', 'reportActions'),
284
- contentType: 'text/xml',
285
- dataType: 'xml'
286
- });
287
- }
288
-
289
- /**
290
- * Gets the list of current groups or organizations registered on this reporting system.
291
- * @override
292
- * @returns {external:Promise} - When fulfilled, an array of group data is returned as a result
293
- */
294
- getGroups() {
295
- return new Promise((resolve, reject) => {
296
- if (!this.userBased())
297
- reject('This system does not manage users!');
298
- else {
299
- const bean = new ReportBean('get groups');
300
- this.transaction(bean.$bean)
301
- .done((data, _textStatus, _jqXHR) => {
302
- const currentGroups = [];
303
- $(data).find('group').each((_n, gr) => {
304
- const $group = $(gr);
305
- currentGroups.push({ id: $group.attr('id'), name: $group.attr('name') });
306
- });
307
- resolve(currentGroups);
308
- })
309
- .fail((jqXHR, textStatus, errorThrown) => {
310
- reject(`Error retrieving groups list from ${this.serviceUrl} [${textStatus} ${errorThrown}]`);
311
- });
312
- }
313
- });
314
- }
315
-
316
- /**
317
- * Gets the list of users currently registered in the system, optionally filtered by
318
- * a specific group ID.
319
- * @override
320
- * @param {string}+ groupId - Optional group ID to be used as a filter criteria
321
- * @returns {external:Promise} - When fulfilled, an object with a collection of user data records
322
- * is returned
323
- */
324
- getUsers(groupId) {
325
- return new Promise((resolve, reject) => {
326
- if (!this.userBased())
327
- reject('This system does not manage users!');
328
- else {
329
- const bean = new ReportBean('get users');
330
- if (typeof groupId !== 'undefined' && groupId !== null)
331
- bean.setParam('group', groupId);
332
- this.transaction(bean.$bean)
333
- .done((data, _textStatus, _jqXHR) => {
334
- const currentUsers = [];
335
- $(data).find('user').each((_n, usr) => {
336
- const $user = $(usr);
337
- const user = { id: $user.attr('id'), name: $user.attr('name') };
338
- if ($user.attr('pwd'))
339
- user.pwd = $user.attr('pwd');
340
- currentUsers.push(user);
341
- });
342
- resolve(currentUsers);
343
- })
344
- .fail((jqXHR, textStatus, errorThrown) => {
345
- reject(`Error retrieving users list from ${this.serviceUrl} [${textStatus} ${errorThrown}]`);
346
- });
347
- }
348
- });
349
- }
350
-
351
- /**
352
- * Gets extended data associated with a specific user.
353
- * @param {string} userId - The requested user ID
354
- * @returns {external:Promise} - When fulfilled, an object with user data is returned.
355
- */
356
- getUserData(userId) {
357
- return new Promise((resolve, reject) => {
358
- if (!this.userBased())
359
- reject('This system does not manage users!');
360
- else {
361
- const bean = new ReportBean('get user data');
362
-
363
- if (typeof userId !== 'undefined' && userId !== null)
364
- bean.setParam('user', userId);
365
- else
366
- reject('Invalid user ID');
367
-
368
- this.transaction(bean.$bean)
369
- .done((data, _textStatus, _jqXHR) => {
370
- const $user = $(data).find('user');
371
- if ($user.length !== 1) {
372
- window.alert(getMsg('Invalid user'));
373
- resolve('Invalid user ID');
374
- } else {
375
- const user = { id: $user.attr('id'), name: $user.attr('name') };
376
- if ($user.attr('pwd'))
377
- user.pwd = $user.attr('pwd');
378
- resolve(user);
379
- }
380
- })
381
- .fail((jqXHR, textStatus, errorThrown) => {
382
- reject(`Error retrieving user data from ${this.serviceUrl} [${textStatus} ${errorThrown}]`);
383
- });
384
- }
385
- });
386
- }
387
-
388
- /**
389
- * Stops the reporting system, usually as a result of repeated errors or because the player
390
- * shuts down.
391
- * @returns {external:Promise} - A promise to be fullfilled when all pending tasks are finished.
392
- */
393
- stopReporting() {
394
- let result = null;
395
- if (this.timer >= 0) {
396
- window.clearInterval(this.timer);
397
- this.timer = -1;
398
- }
399
- if (this.beforeUnloadFunction) {
400
- window.removeEventListener('beforeunload', this.beforeUnloadFunction);
401
- this.beforeUnloadFunction = null;
402
- }
403
- if (this.initiated) {
404
- result = this.flushTasksPromise().then(() => {
405
- this.serviceUrl = null;
406
- this.descriptionDetail = `${this.serverPath} (${getMsg('not connected')})`;
407
- this.initiated = false;
408
- });
409
- }
410
- return result || Promise.resolve(true);
411
- }
412
-
413
- /**
414
- * Prepares a {@link module:report/TCPReporter.ReportBean ReportBean} object with information related to the current
415
- * activity, and pushes it into the list of pending `tasks`, to be processed by the main `timer`.
416
- * @param {boolean} flushNow - When `true`, the activity data will be sent to server as soon as possible
417
- */
418
- reportActivity(flushNow) {
419
- if (this.lastActivity) {
420
- if (!this.lastActivity.closed)
421
- this.lastActivity.closeActivity();
422
- const
423
- actCount = this.actCount++,
424
- act = this.lastActivity;
425
- this.createDBSession(false).then(() => {
426
- const bean = new ReportBean('add activity');
427
- bean.setParam('session', this.currentSessionId);
428
- bean.setParam('num', actCount);
429
- bean.appendData(act.$getXML());
430
- this.addTask(bean);
431
- if (flushNow)
432
- this.flushTasksPromise().then();
433
- });
434
- }
435
- if (this.currentSession !== null &&
436
- this.currentSession.currentSequence !== null &&
437
- this.currentSession.currentSequence.currentActivity !== this.lastActivity) {
438
- this.lastActivity = this.currentSession.currentSequence.currentActivity;
439
- } else
440
- this.lastActivity = null;
441
- }
442
-
443
- /**
444
- * This method should be invoked when the user starts a new activity
445
- * @override
446
- * @param {module:Activity.Activity} act - The {@link module:Activity.Activity Activity} reporter has just started
447
- */
448
- newActivity(act) {
449
- super.newActivity(act);
450
- this.reportActivity(false);
451
- }
452
-
453
- /**
454
- * This method should be called when the current activity finishes. Data about user's final results
455
- * on the activity will then be saved.
456
- * @override
457
- * @param {number} score - The final score, usually in a 0-100 scale.
458
- * @param {number} numActions - The total number of actions done by the user to solve the activity
459
- * @param {boolean} solved - `true` if the activity was finally solved, `false` otherwise.
460
- */
461
- endActivity(score, numActions, solved) {
462
- super.endActivity(score, numActions, solved);
463
- this.reportActivity(true);
464
- }
465
- }
466
-
467
- Object.assign(TCPReporter.prototype, {
468
- /**
469
- * Description of this reporting system
470
- * @name module:report/TCPReporter.TCPReporter#descriptionKey
471
- * @override
472
- * @type {string} */
473
- descriptionKey: 'Reporting to remote server',
474
- /**
475
- * Additional info to display after the reporter's `description`
476
- * @name module:report/TCPReporter.TCPReporter#descriptionDetail
477
- * @override
478
- * @type {string} */
479
- descriptionDetail: '(not connected)',
480
- /**
481
- * Main path of the reports server (without protocol nor service)
482
- * @name module:report/TCPReporter.TCPReporter#serverPath
483
- * @type {string} */
484
- serverPath: '',
485
- /**
486
- * Function to be called by the browser before leaving the current page
487
- * @name module:report/TCPReporter.TCPReporter#beforeUnloadFunction
488
- * @type {function} */
489
- beforeUnloadFunction: null,
490
- /**
491
- * Identifier of the current session, provided by the server
492
- * @name module:report/TCPReporter.TCPReporter#currentSessionId
493
- * @type {string} */
494
- currentSessionId: '',
495
- /**
496
- * Last activity reported
497
- * @name module:report/TCPReporter.TCPReporter#lastActivity
498
- * @type {module:report/ActivityReg.ActivityReg} */
499
- lastActivity: null,
500
- /**
501
- * Number of activities processed
502
- * @name module:report/TCPReporter.TCPReporter#actCount
503
- * @type {number} */
504
- actCount: 0,
505
- /**
506
- * Service URL of the JClic Reports server
507
- * @name module:report/TCPReporter.TCPReporter#serviceUrl
508
- * @type {string} */
509
- serviceUrl: null,
510
- /**
511
- * Object used to store specific properties of the connected reports system
512
- * @name module:report/TCPReporter.TCPReporter#dbProperties
513
- * @type {object} */
514
- dbProperties: null,
515
- /**
516
- * List of {@link module:report/TCPReporter.ReportBean ReportBean} objects pending to be processed
517
- * @name module:report/TCPReporter.TCPReporter#tasks
518
- * @type {module:report/TCPReporter.ReportBean[]} */
519
- tasks: null,
520
- /**
521
- * Waiting list of tasks, to be used while `tasks` is being processed
522
- * @name module:report/TCPReporter.TCPReporter#waitingTasks
523
- * @type {module:report/TCPReporter.ReportBean[]} */
524
- waitingTasks: null,
525
- /**
526
- * Flag used to indicate if `transaction` is currently running
527
- * @name module:report/TCPReporter.TCPReporter#processingTasks
528
- * @type {boolean} */
529
- processingTasks: false,
530
- /**
531
- * Force processing of pending tasks as soon as possible
532
- * @name module:report/TCPReporter.TCPReporter#forceFlush
533
- * @type {boolean} */
534
- forceFlush: false,
535
- /**
536
- * Identifier of the background function obtained with a call to `window.setInterval`
537
- * @name module:report/TCPReporter.TCPReporter#timer
538
- * @type {number} */
539
- timer: -1,
540
- /**
541
- * Time between calls to the background function, in seconds
542
- * @name module:report/TCPReporter.TCPReporter#timerLap
543
- * @type {number} */
544
- timerLap: 5,
545
- /**
546
- * Counter of unsuccessful connection attempts with the report server
547
- * @name module:report/TCPReporter.TCPReporter#failCount
548
- * @type {number} */
549
- failCount: 0,
550
- /**
551
- * Maximum number of failed attempts allowed before disconnecting
552
- * @name module:report/TCPReporter.TCPReporter#maxFails
553
- * @type {number} */
554
- maxFails: 5,
555
- /**
556
- * Default path of JClic Reports Server
557
- * @name module:report/TCPReporter.TCPReporter#DEFAULT_SERVER_PATH
558
- * @type {string} */
559
- DEFAULT_SERVER_PATH: 'localhost:9000',
560
- /**
561
- * Default name for the reports service
562
- * @name module:report/TCPReporter.TCPReporter#DEFAULT_SERVER_SERVICE
563
- * @type {string} */
564
- DEFAULT_SERVER_SERVICE: '/JClicReportService',
565
- /**
566
- * Default server protocol
567
- * Use always 'https' except when in 'http' and protocol not set in options
568
- * @name module:report/TCPReporter.TCPReporter#DEFAULT_SERVER_PROTOCOL
569
- * @type {string} */
570
- DEFAULT_SERVER_PROTOCOL: (document && document.location && document.location.protocol === 'http:') ? 'http' : 'https',
571
- /**
572
- * Default lap between calls to `flushTasks`, in seconds
573
- * @name module:report/TCPReporter.TCPReporter#DEFAULT_TIMER_LAP
574
- * @type {number} */
575
- DEFAULT_TIMER_LAP: 20,
576
- });
577
-
578
- /**
579
- * This inner class encapsulates a chunk of information in XML format, ready to be
580
- * transmitted to the remote reports server.
581
- */
582
- export class ReportBean {
583
- /**
584
- * ReportBean constructor
585
- * @param id {string} - The main identifier of this ReportBean. Current valid values are:
586
- * `get property`, `get_properties`, `add session`, `add activity`, `get groups`, `get users`,
587
- * `get user data`, `get group data`, `new group`, `new user` and `multiple`.
588
- * @param $data {external:jQuery}+ - Optional XML data to be added to this bean
589
- */
590
- constructor(id, $data) {
591
- this.$bean = $('<bean/>').attr({ id: id });
592
- if ($data)
593
- this.appendData($data);
594
- }
595
-
596
- /**
597
- * Adds an XML element to the bean
598
- * @param {external:jQuery} $data - The XML element to be added to this bean
599
- */
600
- appendData($data) {
601
- if ($data) {
602
- this.$bean.append($data);
603
- }
604
- }
605
-
606
- /**
607
- * Adds an XML element of type `param` to this ReportBean
608
- * @param {string} name - The key name of the parameter
609
- * @param {string|number|boolean} value - The value of the parameter
610
- */
611
- setParam(name, value) {
612
- if (typeof value !== 'undefined' && value !== null)
613
- this.appendData($('<param/>').attr({ name: name, value: value }));
614
- }
615
- }
616
-
617
- Object.assign(ReportBean.prototype, {
618
- /**
619
- * The main jQuery XML object managed by this ReportBean
620
- * @name module:report/TCPReporter.ReportBean#$bean
621
- * @type {external:jQuery} */
622
- $bean: null,
623
- });
624
-
625
- TCPReporter.ReportBean = ReportBean;
626
-
627
- // Register class in Reporter.CLASSES
628
- export default Reporter.registerClass('TCPReporter', TCPReporter);