@contractspec/module.learning-journey 3.7.6 → 3.7.7
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/README.md +65 -188
- package/dist/browser/contracts/index.js +148 -148
- package/dist/browser/contracts/models.js +1 -1
- package/dist/browser/contracts/onboarding.js +5 -5
- package/dist/browser/contracts/operations.js +4 -4
- package/dist/browser/engines/index.js +173 -173
- package/dist/browser/engines/xp.js +18 -18
- package/dist/browser/events.js +1 -1
- package/dist/browser/i18n/catalogs/index.js +18 -18
- package/dist/browser/i18n/index.js +26 -26
- package/dist/browser/i18n/locale.js +2 -2
- package/dist/browser/i18n/messages.js +18 -18
- package/dist/browser/index.js +336 -335
- package/dist/contracts/index.d.ts +2 -2
- package/dist/contracts/index.js +148 -148
- package/dist/contracts/models.js +1 -1
- package/dist/contracts/onboarding.js +5 -5
- package/dist/contracts/operations.js +4 -4
- package/dist/engines/index.d.ts +1 -1
- package/dist/engines/index.js +173 -173
- package/dist/engines/xp.js +18 -18
- package/dist/events.js +1 -1
- package/dist/i18n/catalogs/index.d.ts +1 -1
- package/dist/i18n/catalogs/index.js +18 -18
- package/dist/i18n/index.d.ts +7 -7
- package/dist/i18n/index.js +26 -26
- package/dist/i18n/locale.d.ts +1 -1
- package/dist/i18n/locale.js +2 -2
- package/dist/i18n/messages.js +18 -18
- package/dist/index.d.ts +3 -3
- package/dist/index.js +336 -335
- package/dist/node/contracts/index.js +148 -148
- package/dist/node/contracts/models.js +1 -1
- package/dist/node/contracts/onboarding.js +5 -5
- package/dist/node/contracts/operations.js +4 -4
- package/dist/node/engines/index.js +173 -173
- package/dist/node/engines/xp.js +18 -18
- package/dist/node/events.js +1 -1
- package/dist/node/i18n/catalogs/index.js +18 -18
- package/dist/node/i18n/index.js +26 -26
- package/dist/node/i18n/locale.js +2 -2
- package/dist/node/i18n/messages.js +18 -18
- package/dist/node/index.js +336 -335
- package/package.json +4 -4
package/dist/engines/index.js
CHANGED
|
@@ -193,6 +193,161 @@ class SRSEngine {
|
|
|
193
193
|
}
|
|
194
194
|
var srsEngine = new SRSEngine;
|
|
195
195
|
|
|
196
|
+
// src/engines/streak.ts
|
|
197
|
+
var DEFAULT_STREAK_CONFIG = {
|
|
198
|
+
timezone: "UTC",
|
|
199
|
+
freezesPerMonth: 2,
|
|
200
|
+
maxFreezes: 5,
|
|
201
|
+
gracePeriodHours: 4
|
|
202
|
+
};
|
|
203
|
+
|
|
204
|
+
class StreakEngine {
|
|
205
|
+
config;
|
|
206
|
+
constructor(config = {}) {
|
|
207
|
+
this.config = { ...DEFAULT_STREAK_CONFIG, ...config };
|
|
208
|
+
}
|
|
209
|
+
update(state, now = new Date) {
|
|
210
|
+
const todayDate = this.getDateString(now);
|
|
211
|
+
const result = {
|
|
212
|
+
state: { ...state },
|
|
213
|
+
streakMaintained: false,
|
|
214
|
+
streakLost: false,
|
|
215
|
+
freezeUsed: false,
|
|
216
|
+
newStreak: false,
|
|
217
|
+
daysMissed: 0
|
|
218
|
+
};
|
|
219
|
+
if (!state.lastActivityDate) {
|
|
220
|
+
result.state.currentStreak = 1;
|
|
221
|
+
result.state.longestStreak = Math.max(1, state.longestStreak);
|
|
222
|
+
result.state.lastActivityAt = now;
|
|
223
|
+
result.state.lastActivityDate = todayDate;
|
|
224
|
+
result.newStreak = true;
|
|
225
|
+
result.streakMaintained = true;
|
|
226
|
+
return result;
|
|
227
|
+
}
|
|
228
|
+
if (state.lastActivityDate === todayDate) {
|
|
229
|
+
result.state.lastActivityAt = now;
|
|
230
|
+
result.streakMaintained = true;
|
|
231
|
+
return result;
|
|
232
|
+
}
|
|
233
|
+
const daysSinceActivity = this.getDaysBetween(state.lastActivityDate, todayDate);
|
|
234
|
+
if (daysSinceActivity === 1) {
|
|
235
|
+
result.state.currentStreak = state.currentStreak + 1;
|
|
236
|
+
result.state.longestStreak = Math.max(result.state.currentStreak, state.longestStreak);
|
|
237
|
+
result.state.lastActivityAt = now;
|
|
238
|
+
result.state.lastActivityDate = todayDate;
|
|
239
|
+
result.streakMaintained = true;
|
|
240
|
+
return result;
|
|
241
|
+
}
|
|
242
|
+
result.daysMissed = daysSinceActivity - 1;
|
|
243
|
+
const freezesNeeded = result.daysMissed;
|
|
244
|
+
if (freezesNeeded <= state.freezesRemaining) {
|
|
245
|
+
result.state.freezesRemaining = state.freezesRemaining - freezesNeeded;
|
|
246
|
+
result.state.freezeUsedAt = now;
|
|
247
|
+
result.state.currentStreak = state.currentStreak + 1;
|
|
248
|
+
result.state.longestStreak = Math.max(result.state.currentStreak, state.longestStreak);
|
|
249
|
+
result.state.lastActivityAt = now;
|
|
250
|
+
result.state.lastActivityDate = todayDate;
|
|
251
|
+
result.freezeUsed = true;
|
|
252
|
+
result.streakMaintained = true;
|
|
253
|
+
return result;
|
|
254
|
+
}
|
|
255
|
+
result.streakLost = true;
|
|
256
|
+
result.state.currentStreak = 1;
|
|
257
|
+
result.state.lastActivityAt = now;
|
|
258
|
+
result.state.lastActivityDate = todayDate;
|
|
259
|
+
result.newStreak = true;
|
|
260
|
+
return result;
|
|
261
|
+
}
|
|
262
|
+
checkStatus(state, now = new Date) {
|
|
263
|
+
if (!state.lastActivityDate) {
|
|
264
|
+
return {
|
|
265
|
+
isActive: false,
|
|
266
|
+
willExpireAt: null,
|
|
267
|
+
canUseFreeze: false,
|
|
268
|
+
daysUntilExpiry: 0
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
const todayDate = this.getDateString(now);
|
|
272
|
+
const daysSinceActivity = this.getDaysBetween(state.lastActivityDate, todayDate);
|
|
273
|
+
if (daysSinceActivity === 0) {
|
|
274
|
+
const tomorrow = this.addDays(now, 1);
|
|
275
|
+
tomorrow.setHours(23, 59, 59, 999);
|
|
276
|
+
return {
|
|
277
|
+
isActive: true,
|
|
278
|
+
willExpireAt: tomorrow,
|
|
279
|
+
canUseFreeze: state.freezesRemaining > 0,
|
|
280
|
+
daysUntilExpiry: 1
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
if (daysSinceActivity === 1) {
|
|
284
|
+
const endOfDay = new Date(now);
|
|
285
|
+
endOfDay.setHours(23 + this.config.gracePeriodHours, 59, 59, 999);
|
|
286
|
+
return {
|
|
287
|
+
isActive: true,
|
|
288
|
+
willExpireAt: endOfDay,
|
|
289
|
+
canUseFreeze: state.freezesRemaining > 0,
|
|
290
|
+
daysUntilExpiry: 0
|
|
291
|
+
};
|
|
292
|
+
}
|
|
293
|
+
const missedDays = daysSinceActivity - 1;
|
|
294
|
+
return {
|
|
295
|
+
isActive: missedDays <= state.freezesRemaining,
|
|
296
|
+
willExpireAt: null,
|
|
297
|
+
canUseFreeze: missedDays <= state.freezesRemaining,
|
|
298
|
+
daysUntilExpiry: -missedDays
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
useFreeze(state, now = new Date) {
|
|
302
|
+
if (state.freezesRemaining <= 0) {
|
|
303
|
+
return null;
|
|
304
|
+
}
|
|
305
|
+
return {
|
|
306
|
+
...state,
|
|
307
|
+
freezesRemaining: state.freezesRemaining - 1,
|
|
308
|
+
freezeUsedAt: now
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
awardMonthlyFreezes(state) {
|
|
312
|
+
return {
|
|
313
|
+
...state,
|
|
314
|
+
freezesRemaining: Math.min(state.freezesRemaining + this.config.freezesPerMonth, this.config.maxFreezes)
|
|
315
|
+
};
|
|
316
|
+
}
|
|
317
|
+
getInitialState() {
|
|
318
|
+
return {
|
|
319
|
+
currentStreak: 0,
|
|
320
|
+
longestStreak: 0,
|
|
321
|
+
lastActivityAt: null,
|
|
322
|
+
lastActivityDate: null,
|
|
323
|
+
freezesRemaining: this.config.freezesPerMonth,
|
|
324
|
+
freezeUsedAt: null
|
|
325
|
+
};
|
|
326
|
+
}
|
|
327
|
+
getMilestones(currentStreak) {
|
|
328
|
+
const milestones = [3, 7, 14, 30, 60, 90, 180, 365, 500, 1000];
|
|
329
|
+
const achieved = milestones.filter((m) => currentStreak >= m);
|
|
330
|
+
const next = milestones.find((m) => currentStreak < m) ?? null;
|
|
331
|
+
return { achieved, next };
|
|
332
|
+
}
|
|
333
|
+
getDateString(date) {
|
|
334
|
+
const year = date.getFullYear();
|
|
335
|
+
const month = String(date.getMonth() + 1).padStart(2, "0");
|
|
336
|
+
const day = String(date.getDate()).padStart(2, "0");
|
|
337
|
+
return `${year}-${month}-${day}`;
|
|
338
|
+
}
|
|
339
|
+
getDaysBetween(dateStr1, dateStr2) {
|
|
340
|
+
const date1 = new Date(dateStr1);
|
|
341
|
+
const date2 = new Date(dateStr2);
|
|
342
|
+
const diffTime = date2.getTime() - date1.getTime();
|
|
343
|
+
return Math.floor(diffTime / (1000 * 60 * 60 * 24));
|
|
344
|
+
}
|
|
345
|
+
addDays(date, days) {
|
|
346
|
+
return new Date(date.getTime() + days * 24 * 60 * 60 * 1000);
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
var streakEngine = new StreakEngine;
|
|
350
|
+
|
|
196
351
|
// src/i18n/catalogs/en.ts
|
|
197
352
|
import { defineTranslation } from "@contractspec/lib.contracts-spec/translations";
|
|
198
353
|
var enMessages = defineTranslation({
|
|
@@ -234,18 +389,18 @@ var enMessages = defineTranslation({
|
|
|
234
389
|
}
|
|
235
390
|
});
|
|
236
391
|
|
|
237
|
-
// src/i18n/catalogs/
|
|
392
|
+
// src/i18n/catalogs/es.ts
|
|
238
393
|
import { defineTranslation as defineTranslation2 } from "@contractspec/lib.contracts-spec/translations";
|
|
239
|
-
var
|
|
394
|
+
var esMessages = defineTranslation2({
|
|
240
395
|
meta: {
|
|
241
396
|
key: "learning-journey.messages",
|
|
242
397
|
version: "1.0.0",
|
|
243
398
|
domain: "learning-journey",
|
|
244
|
-
description: "XP source labels (
|
|
399
|
+
description: "XP source labels (Spanish)",
|
|
245
400
|
owners: ["platform"],
|
|
246
401
|
stability: "experimental"
|
|
247
402
|
},
|
|
248
|
-
locale: "
|
|
403
|
+
locale: "es",
|
|
249
404
|
fallback: "en",
|
|
250
405
|
messages: {
|
|
251
406
|
"xp.source.base": {
|
|
@@ -253,40 +408,40 @@ var frMessages = defineTranslation2({
|
|
|
253
408
|
description: "XP breakdown label for base XP"
|
|
254
409
|
},
|
|
255
410
|
"xp.source.scoreBonus": {
|
|
256
|
-
value: "
|
|
411
|
+
value: "Bonificaci\xF3n por puntuaci\xF3n",
|
|
257
412
|
description: "XP breakdown label for score-based bonus"
|
|
258
413
|
},
|
|
259
414
|
"xp.source.perfectScore": {
|
|
260
|
-
value: "
|
|
415
|
+
value: "Puntuaci\xF3n perfecta",
|
|
261
416
|
description: "XP breakdown label for perfect score bonus"
|
|
262
417
|
},
|
|
263
418
|
"xp.source.firstAttempt": {
|
|
264
|
-
value: "
|
|
419
|
+
value: "Primer intento",
|
|
265
420
|
description: "XP breakdown label for first attempt bonus"
|
|
266
421
|
},
|
|
267
422
|
"xp.source.retryPenalty": {
|
|
268
|
-
value: "
|
|
423
|
+
value: "Penalizaci\xF3n por reintento",
|
|
269
424
|
description: "XP breakdown label for retry penalty"
|
|
270
425
|
},
|
|
271
426
|
"xp.source.streakBonus": {
|
|
272
|
-
value: "
|
|
427
|
+
value: "Bonificaci\xF3n por racha",
|
|
273
428
|
description: "XP breakdown label for streak bonus"
|
|
274
429
|
}
|
|
275
430
|
}
|
|
276
431
|
});
|
|
277
432
|
|
|
278
|
-
// src/i18n/catalogs/
|
|
433
|
+
// src/i18n/catalogs/fr.ts
|
|
279
434
|
import { defineTranslation as defineTranslation3 } from "@contractspec/lib.contracts-spec/translations";
|
|
280
|
-
var
|
|
435
|
+
var frMessages = defineTranslation3({
|
|
281
436
|
meta: {
|
|
282
437
|
key: "learning-journey.messages",
|
|
283
438
|
version: "1.0.0",
|
|
284
439
|
domain: "learning-journey",
|
|
285
|
-
description: "XP source labels (
|
|
440
|
+
description: "XP source labels (French)",
|
|
286
441
|
owners: ["platform"],
|
|
287
442
|
stability: "experimental"
|
|
288
443
|
},
|
|
289
|
-
locale: "
|
|
444
|
+
locale: "fr",
|
|
290
445
|
fallback: "en",
|
|
291
446
|
messages: {
|
|
292
447
|
"xp.source.base": {
|
|
@@ -294,23 +449,23 @@ var esMessages = defineTranslation3({
|
|
|
294
449
|
description: "XP breakdown label for base XP"
|
|
295
450
|
},
|
|
296
451
|
"xp.source.scoreBonus": {
|
|
297
|
-
value: "
|
|
452
|
+
value: "Bonus de score",
|
|
298
453
|
description: "XP breakdown label for score-based bonus"
|
|
299
454
|
},
|
|
300
455
|
"xp.source.perfectScore": {
|
|
301
|
-
value: "
|
|
456
|
+
value: "Score parfait",
|
|
302
457
|
description: "XP breakdown label for perfect score bonus"
|
|
303
458
|
},
|
|
304
459
|
"xp.source.firstAttempt": {
|
|
305
|
-
value: "
|
|
460
|
+
value: "Premier essai",
|
|
306
461
|
description: "XP breakdown label for first attempt bonus"
|
|
307
462
|
},
|
|
308
463
|
"xp.source.retryPenalty": {
|
|
309
|
-
value: "
|
|
464
|
+
value: "P\xE9nalit\xE9 de r\xE9essai",
|
|
310
465
|
description: "XP breakdown label for retry penalty"
|
|
311
466
|
},
|
|
312
467
|
"xp.source.streakBonus": {
|
|
313
|
-
value: "
|
|
468
|
+
value: "Bonus de s\xE9rie",
|
|
314
469
|
description: "XP breakdown label for streak bonus"
|
|
315
470
|
}
|
|
316
471
|
}
|
|
@@ -507,161 +662,6 @@ function getXpSourceLabel(source, locale) {
|
|
|
507
662
|
return i18nKey ? i18n.t(i18nKey) : source;
|
|
508
663
|
}
|
|
509
664
|
var xpEngine = new XPEngine;
|
|
510
|
-
|
|
511
|
-
// src/engines/streak.ts
|
|
512
|
-
var DEFAULT_STREAK_CONFIG = {
|
|
513
|
-
timezone: "UTC",
|
|
514
|
-
freezesPerMonth: 2,
|
|
515
|
-
maxFreezes: 5,
|
|
516
|
-
gracePeriodHours: 4
|
|
517
|
-
};
|
|
518
|
-
|
|
519
|
-
class StreakEngine {
|
|
520
|
-
config;
|
|
521
|
-
constructor(config = {}) {
|
|
522
|
-
this.config = { ...DEFAULT_STREAK_CONFIG, ...config };
|
|
523
|
-
}
|
|
524
|
-
update(state, now = new Date) {
|
|
525
|
-
const todayDate = this.getDateString(now);
|
|
526
|
-
const result = {
|
|
527
|
-
state: { ...state },
|
|
528
|
-
streakMaintained: false,
|
|
529
|
-
streakLost: false,
|
|
530
|
-
freezeUsed: false,
|
|
531
|
-
newStreak: false,
|
|
532
|
-
daysMissed: 0
|
|
533
|
-
};
|
|
534
|
-
if (!state.lastActivityDate) {
|
|
535
|
-
result.state.currentStreak = 1;
|
|
536
|
-
result.state.longestStreak = Math.max(1, state.longestStreak);
|
|
537
|
-
result.state.lastActivityAt = now;
|
|
538
|
-
result.state.lastActivityDate = todayDate;
|
|
539
|
-
result.newStreak = true;
|
|
540
|
-
result.streakMaintained = true;
|
|
541
|
-
return result;
|
|
542
|
-
}
|
|
543
|
-
if (state.lastActivityDate === todayDate) {
|
|
544
|
-
result.state.lastActivityAt = now;
|
|
545
|
-
result.streakMaintained = true;
|
|
546
|
-
return result;
|
|
547
|
-
}
|
|
548
|
-
const daysSinceActivity = this.getDaysBetween(state.lastActivityDate, todayDate);
|
|
549
|
-
if (daysSinceActivity === 1) {
|
|
550
|
-
result.state.currentStreak = state.currentStreak + 1;
|
|
551
|
-
result.state.longestStreak = Math.max(result.state.currentStreak, state.longestStreak);
|
|
552
|
-
result.state.lastActivityAt = now;
|
|
553
|
-
result.state.lastActivityDate = todayDate;
|
|
554
|
-
result.streakMaintained = true;
|
|
555
|
-
return result;
|
|
556
|
-
}
|
|
557
|
-
result.daysMissed = daysSinceActivity - 1;
|
|
558
|
-
const freezesNeeded = result.daysMissed;
|
|
559
|
-
if (freezesNeeded <= state.freezesRemaining) {
|
|
560
|
-
result.state.freezesRemaining = state.freezesRemaining - freezesNeeded;
|
|
561
|
-
result.state.freezeUsedAt = now;
|
|
562
|
-
result.state.currentStreak = state.currentStreak + 1;
|
|
563
|
-
result.state.longestStreak = Math.max(result.state.currentStreak, state.longestStreak);
|
|
564
|
-
result.state.lastActivityAt = now;
|
|
565
|
-
result.state.lastActivityDate = todayDate;
|
|
566
|
-
result.freezeUsed = true;
|
|
567
|
-
result.streakMaintained = true;
|
|
568
|
-
return result;
|
|
569
|
-
}
|
|
570
|
-
result.streakLost = true;
|
|
571
|
-
result.state.currentStreak = 1;
|
|
572
|
-
result.state.lastActivityAt = now;
|
|
573
|
-
result.state.lastActivityDate = todayDate;
|
|
574
|
-
result.newStreak = true;
|
|
575
|
-
return result;
|
|
576
|
-
}
|
|
577
|
-
checkStatus(state, now = new Date) {
|
|
578
|
-
if (!state.lastActivityDate) {
|
|
579
|
-
return {
|
|
580
|
-
isActive: false,
|
|
581
|
-
willExpireAt: null,
|
|
582
|
-
canUseFreeze: false,
|
|
583
|
-
daysUntilExpiry: 0
|
|
584
|
-
};
|
|
585
|
-
}
|
|
586
|
-
const todayDate = this.getDateString(now);
|
|
587
|
-
const daysSinceActivity = this.getDaysBetween(state.lastActivityDate, todayDate);
|
|
588
|
-
if (daysSinceActivity === 0) {
|
|
589
|
-
const tomorrow = this.addDays(now, 1);
|
|
590
|
-
tomorrow.setHours(23, 59, 59, 999);
|
|
591
|
-
return {
|
|
592
|
-
isActive: true,
|
|
593
|
-
willExpireAt: tomorrow,
|
|
594
|
-
canUseFreeze: state.freezesRemaining > 0,
|
|
595
|
-
daysUntilExpiry: 1
|
|
596
|
-
};
|
|
597
|
-
}
|
|
598
|
-
if (daysSinceActivity === 1) {
|
|
599
|
-
const endOfDay = new Date(now);
|
|
600
|
-
endOfDay.setHours(23 + this.config.gracePeriodHours, 59, 59, 999);
|
|
601
|
-
return {
|
|
602
|
-
isActive: true,
|
|
603
|
-
willExpireAt: endOfDay,
|
|
604
|
-
canUseFreeze: state.freezesRemaining > 0,
|
|
605
|
-
daysUntilExpiry: 0
|
|
606
|
-
};
|
|
607
|
-
}
|
|
608
|
-
const missedDays = daysSinceActivity - 1;
|
|
609
|
-
return {
|
|
610
|
-
isActive: missedDays <= state.freezesRemaining,
|
|
611
|
-
willExpireAt: null,
|
|
612
|
-
canUseFreeze: missedDays <= state.freezesRemaining,
|
|
613
|
-
daysUntilExpiry: -missedDays
|
|
614
|
-
};
|
|
615
|
-
}
|
|
616
|
-
useFreeze(state, now = new Date) {
|
|
617
|
-
if (state.freezesRemaining <= 0) {
|
|
618
|
-
return null;
|
|
619
|
-
}
|
|
620
|
-
return {
|
|
621
|
-
...state,
|
|
622
|
-
freezesRemaining: state.freezesRemaining - 1,
|
|
623
|
-
freezeUsedAt: now
|
|
624
|
-
};
|
|
625
|
-
}
|
|
626
|
-
awardMonthlyFreezes(state) {
|
|
627
|
-
return {
|
|
628
|
-
...state,
|
|
629
|
-
freezesRemaining: Math.min(state.freezesRemaining + this.config.freezesPerMonth, this.config.maxFreezes)
|
|
630
|
-
};
|
|
631
|
-
}
|
|
632
|
-
getInitialState() {
|
|
633
|
-
return {
|
|
634
|
-
currentStreak: 0,
|
|
635
|
-
longestStreak: 0,
|
|
636
|
-
lastActivityAt: null,
|
|
637
|
-
lastActivityDate: null,
|
|
638
|
-
freezesRemaining: this.config.freezesPerMonth,
|
|
639
|
-
freezeUsedAt: null
|
|
640
|
-
};
|
|
641
|
-
}
|
|
642
|
-
getMilestones(currentStreak) {
|
|
643
|
-
const milestones = [3, 7, 14, 30, 60, 90, 180, 365, 500, 1000];
|
|
644
|
-
const achieved = milestones.filter((m) => currentStreak >= m);
|
|
645
|
-
const next = milestones.find((m) => currentStreak < m) ?? null;
|
|
646
|
-
return { achieved, next };
|
|
647
|
-
}
|
|
648
|
-
getDateString(date) {
|
|
649
|
-
const year = date.getFullYear();
|
|
650
|
-
const month = String(date.getMonth() + 1).padStart(2, "0");
|
|
651
|
-
const day = String(date.getDate()).padStart(2, "0");
|
|
652
|
-
return `${year}-${month}-${day}`;
|
|
653
|
-
}
|
|
654
|
-
getDaysBetween(dateStr1, dateStr2) {
|
|
655
|
-
const date1 = new Date(dateStr1);
|
|
656
|
-
const date2 = new Date(dateStr2);
|
|
657
|
-
const diffTime = date2.getTime() - date1.getTime();
|
|
658
|
-
return Math.floor(diffTime / (1000 * 60 * 60 * 24));
|
|
659
|
-
}
|
|
660
|
-
addDays(date, days) {
|
|
661
|
-
return new Date(date.getTime() + days * 24 * 60 * 60 * 1000);
|
|
662
|
-
}
|
|
663
|
-
}
|
|
664
|
-
var streakEngine = new StreakEngine;
|
|
665
665
|
export {
|
|
666
666
|
xpEngine,
|
|
667
667
|
streakEngine,
|
package/dist/engines/xp.js
CHANGED
|
@@ -40,18 +40,18 @@ var enMessages = defineTranslation({
|
|
|
40
40
|
}
|
|
41
41
|
});
|
|
42
42
|
|
|
43
|
-
// src/i18n/catalogs/
|
|
43
|
+
// src/i18n/catalogs/es.ts
|
|
44
44
|
import { defineTranslation as defineTranslation2 } from "@contractspec/lib.contracts-spec/translations";
|
|
45
|
-
var
|
|
45
|
+
var esMessages = defineTranslation2({
|
|
46
46
|
meta: {
|
|
47
47
|
key: "learning-journey.messages",
|
|
48
48
|
version: "1.0.0",
|
|
49
49
|
domain: "learning-journey",
|
|
50
|
-
description: "XP source labels (
|
|
50
|
+
description: "XP source labels (Spanish)",
|
|
51
51
|
owners: ["platform"],
|
|
52
52
|
stability: "experimental"
|
|
53
53
|
},
|
|
54
|
-
locale: "
|
|
54
|
+
locale: "es",
|
|
55
55
|
fallback: "en",
|
|
56
56
|
messages: {
|
|
57
57
|
"xp.source.base": {
|
|
@@ -59,40 +59,40 @@ var frMessages = defineTranslation2({
|
|
|
59
59
|
description: "XP breakdown label for base XP"
|
|
60
60
|
},
|
|
61
61
|
"xp.source.scoreBonus": {
|
|
62
|
-
value: "
|
|
62
|
+
value: "Bonificaci\xF3n por puntuaci\xF3n",
|
|
63
63
|
description: "XP breakdown label for score-based bonus"
|
|
64
64
|
},
|
|
65
65
|
"xp.source.perfectScore": {
|
|
66
|
-
value: "
|
|
66
|
+
value: "Puntuaci\xF3n perfecta",
|
|
67
67
|
description: "XP breakdown label for perfect score bonus"
|
|
68
68
|
},
|
|
69
69
|
"xp.source.firstAttempt": {
|
|
70
|
-
value: "
|
|
70
|
+
value: "Primer intento",
|
|
71
71
|
description: "XP breakdown label for first attempt bonus"
|
|
72
72
|
},
|
|
73
73
|
"xp.source.retryPenalty": {
|
|
74
|
-
value: "
|
|
74
|
+
value: "Penalizaci\xF3n por reintento",
|
|
75
75
|
description: "XP breakdown label for retry penalty"
|
|
76
76
|
},
|
|
77
77
|
"xp.source.streakBonus": {
|
|
78
|
-
value: "
|
|
78
|
+
value: "Bonificaci\xF3n por racha",
|
|
79
79
|
description: "XP breakdown label for streak bonus"
|
|
80
80
|
}
|
|
81
81
|
}
|
|
82
82
|
});
|
|
83
83
|
|
|
84
|
-
// src/i18n/catalogs/
|
|
84
|
+
// src/i18n/catalogs/fr.ts
|
|
85
85
|
import { defineTranslation as defineTranslation3 } from "@contractspec/lib.contracts-spec/translations";
|
|
86
|
-
var
|
|
86
|
+
var frMessages = defineTranslation3({
|
|
87
87
|
meta: {
|
|
88
88
|
key: "learning-journey.messages",
|
|
89
89
|
version: "1.0.0",
|
|
90
90
|
domain: "learning-journey",
|
|
91
|
-
description: "XP source labels (
|
|
91
|
+
description: "XP source labels (French)",
|
|
92
92
|
owners: ["platform"],
|
|
93
93
|
stability: "experimental"
|
|
94
94
|
},
|
|
95
|
-
locale: "
|
|
95
|
+
locale: "fr",
|
|
96
96
|
fallback: "en",
|
|
97
97
|
messages: {
|
|
98
98
|
"xp.source.base": {
|
|
@@ -100,23 +100,23 @@ var esMessages = defineTranslation3({
|
|
|
100
100
|
description: "XP breakdown label for base XP"
|
|
101
101
|
},
|
|
102
102
|
"xp.source.scoreBonus": {
|
|
103
|
-
value: "
|
|
103
|
+
value: "Bonus de score",
|
|
104
104
|
description: "XP breakdown label for score-based bonus"
|
|
105
105
|
},
|
|
106
106
|
"xp.source.perfectScore": {
|
|
107
|
-
value: "
|
|
107
|
+
value: "Score parfait",
|
|
108
108
|
description: "XP breakdown label for perfect score bonus"
|
|
109
109
|
},
|
|
110
110
|
"xp.source.firstAttempt": {
|
|
111
|
-
value: "
|
|
111
|
+
value: "Premier essai",
|
|
112
112
|
description: "XP breakdown label for first attempt bonus"
|
|
113
113
|
},
|
|
114
114
|
"xp.source.retryPenalty": {
|
|
115
|
-
value: "
|
|
115
|
+
value: "P\xE9nalit\xE9 de r\xE9essai",
|
|
116
116
|
description: "XP breakdown label for retry penalty"
|
|
117
117
|
},
|
|
118
118
|
"xp.source.streakBonus": {
|
|
119
|
-
value: "
|
|
119
|
+
value: "Bonus de s\xE9rie",
|
|
120
120
|
description: "XP breakdown label for streak bonus"
|
|
121
121
|
}
|
|
122
122
|
}
|
package/dist/events.js
CHANGED
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
var LEARNING_JOURNEY_OWNERS = ["modules.learning-journey"];
|
|
4
4
|
|
|
5
5
|
// src/events.ts
|
|
6
|
-
import { ScalarTypeEnum, defineSchemaModel } from "@contractspec/lib.schema";
|
|
7
6
|
import { defineEvent } from "@contractspec/lib.contracts-spec";
|
|
7
|
+
import { defineSchemaModel, ScalarTypeEnum } from "@contractspec/lib.schema";
|
|
8
8
|
var CoursePublishedPayload = defineSchemaModel({
|
|
9
9
|
name: "CoursePublishedEventPayload",
|
|
10
10
|
description: "Payload when a course is published",
|
|
@@ -40,18 +40,18 @@ var enMessages = defineTranslation({
|
|
|
40
40
|
}
|
|
41
41
|
});
|
|
42
42
|
|
|
43
|
-
// src/i18n/catalogs/
|
|
43
|
+
// src/i18n/catalogs/es.ts
|
|
44
44
|
import { defineTranslation as defineTranslation2 } from "@contractspec/lib.contracts-spec/translations";
|
|
45
|
-
var
|
|
45
|
+
var esMessages = defineTranslation2({
|
|
46
46
|
meta: {
|
|
47
47
|
key: "learning-journey.messages",
|
|
48
48
|
version: "1.0.0",
|
|
49
49
|
domain: "learning-journey",
|
|
50
|
-
description: "XP source labels (
|
|
50
|
+
description: "XP source labels (Spanish)",
|
|
51
51
|
owners: ["platform"],
|
|
52
52
|
stability: "experimental"
|
|
53
53
|
},
|
|
54
|
-
locale: "
|
|
54
|
+
locale: "es",
|
|
55
55
|
fallback: "en",
|
|
56
56
|
messages: {
|
|
57
57
|
"xp.source.base": {
|
|
@@ -59,40 +59,40 @@ var frMessages = defineTranslation2({
|
|
|
59
59
|
description: "XP breakdown label for base XP"
|
|
60
60
|
},
|
|
61
61
|
"xp.source.scoreBonus": {
|
|
62
|
-
value: "
|
|
62
|
+
value: "Bonificaci\xF3n por puntuaci\xF3n",
|
|
63
63
|
description: "XP breakdown label for score-based bonus"
|
|
64
64
|
},
|
|
65
65
|
"xp.source.perfectScore": {
|
|
66
|
-
value: "
|
|
66
|
+
value: "Puntuaci\xF3n perfecta",
|
|
67
67
|
description: "XP breakdown label for perfect score bonus"
|
|
68
68
|
},
|
|
69
69
|
"xp.source.firstAttempt": {
|
|
70
|
-
value: "
|
|
70
|
+
value: "Primer intento",
|
|
71
71
|
description: "XP breakdown label for first attempt bonus"
|
|
72
72
|
},
|
|
73
73
|
"xp.source.retryPenalty": {
|
|
74
|
-
value: "
|
|
74
|
+
value: "Penalizaci\xF3n por reintento",
|
|
75
75
|
description: "XP breakdown label for retry penalty"
|
|
76
76
|
},
|
|
77
77
|
"xp.source.streakBonus": {
|
|
78
|
-
value: "
|
|
78
|
+
value: "Bonificaci\xF3n por racha",
|
|
79
79
|
description: "XP breakdown label for streak bonus"
|
|
80
80
|
}
|
|
81
81
|
}
|
|
82
82
|
});
|
|
83
83
|
|
|
84
|
-
// src/i18n/catalogs/
|
|
84
|
+
// src/i18n/catalogs/fr.ts
|
|
85
85
|
import { defineTranslation as defineTranslation3 } from "@contractspec/lib.contracts-spec/translations";
|
|
86
|
-
var
|
|
86
|
+
var frMessages = defineTranslation3({
|
|
87
87
|
meta: {
|
|
88
88
|
key: "learning-journey.messages",
|
|
89
89
|
version: "1.0.0",
|
|
90
90
|
domain: "learning-journey",
|
|
91
|
-
description: "XP source labels (
|
|
91
|
+
description: "XP source labels (French)",
|
|
92
92
|
owners: ["platform"],
|
|
93
93
|
stability: "experimental"
|
|
94
94
|
},
|
|
95
|
-
locale: "
|
|
95
|
+
locale: "fr",
|
|
96
96
|
fallback: "en",
|
|
97
97
|
messages: {
|
|
98
98
|
"xp.source.base": {
|
|
@@ -100,23 +100,23 @@ var esMessages = defineTranslation3({
|
|
|
100
100
|
description: "XP breakdown label for base XP"
|
|
101
101
|
},
|
|
102
102
|
"xp.source.scoreBonus": {
|
|
103
|
-
value: "
|
|
103
|
+
value: "Bonus de score",
|
|
104
104
|
description: "XP breakdown label for score-based bonus"
|
|
105
105
|
},
|
|
106
106
|
"xp.source.perfectScore": {
|
|
107
|
-
value: "
|
|
107
|
+
value: "Score parfait",
|
|
108
108
|
description: "XP breakdown label for perfect score bonus"
|
|
109
109
|
},
|
|
110
110
|
"xp.source.firstAttempt": {
|
|
111
|
-
value: "
|
|
111
|
+
value: "Premier essai",
|
|
112
112
|
description: "XP breakdown label for first attempt bonus"
|
|
113
113
|
},
|
|
114
114
|
"xp.source.retryPenalty": {
|
|
115
|
-
value: "
|
|
115
|
+
value: "P\xE9nalit\xE9 de r\xE9essai",
|
|
116
116
|
description: "XP breakdown label for retry penalty"
|
|
117
117
|
},
|
|
118
118
|
"xp.source.streakBonus": {
|
|
119
|
-
value: "
|
|
119
|
+
value: "Bonus de s\xE9rie",
|
|
120
120
|
description: "XP breakdown label for streak bonus"
|
|
121
121
|
}
|
|
122
122
|
}
|
package/dist/i18n/index.d.ts
CHANGED
|
@@ -3,12 +3,12 @@
|
|
|
3
3
|
*
|
|
4
4
|
* @module i18n
|
|
5
5
|
*/
|
|
6
|
-
export { createLearningJourneyI18n, getDefaultI18n, resetI18nRegistry, } from './messages';
|
|
7
|
-
export type { LearningJourneyI18n } from './messages';
|
|
8
|
-
export { resolveLocale, isSupportedLocale, DEFAULT_LOCALE, SUPPORTED_LOCALES, } from './locale';
|
|
9
|
-
export type { SupportedLocale } from './locale';
|
|
10
|
-
export { I18N_KEYS, XP_SOURCE_KEYS } from './keys';
|
|
11
|
-
export type { LearningJourneyMessageKey } from './keys';
|
|
12
6
|
export { enMessages } from './catalogs/en';
|
|
13
|
-
export { frMessages } from './catalogs/fr';
|
|
14
7
|
export { esMessages } from './catalogs/es';
|
|
8
|
+
export { frMessages } from './catalogs/fr';
|
|
9
|
+
export type { LearningJourneyMessageKey } from './keys';
|
|
10
|
+
export { I18N_KEYS, XP_SOURCE_KEYS } from './keys';
|
|
11
|
+
export type { SupportedLocale } from './locale';
|
|
12
|
+
export { DEFAULT_LOCALE, isSupportedLocale, resolveLocale, SUPPORTED_LOCALES, } from './locale';
|
|
13
|
+
export type { LearningJourneyI18n } from './messages';
|
|
14
|
+
export { createLearningJourneyI18n, getDefaultI18n, resetI18nRegistry, } from './messages';
|