@ooneex/gamification 0.0.1

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Ooneex
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1 @@
1
+ # @ooneex/gamification
@@ -0,0 +1,683 @@
1
+ import { IImage } from "@ooneex/image";
2
+ import { IStatus } from "@ooneex/status";
3
+ import { ITag } from "@ooneex/tag";
4
+ import { IBase as IBase2, IStat } from "@ooneex/types";
5
+ import { IBase } from "@ooneex/types";
6
+ interface ILevel extends IBase {
7
+ name: string;
8
+ code: string;
9
+ color: string;
10
+ }
11
+ declare enum ESessionType {
12
+ /** Learning-focused session with detailed explanations and guided experience */
13
+ TRAINING = "training",
14
+ /** Reinforcement session for solidifying already learned knowledge */
15
+ PRACTICE = "practice",
16
+ /** Mock test environment simulating real exam conditions */
17
+ SIMULATION = "simulation",
18
+ /** Quick knowledge check with immediate feedback */
19
+ QUIZ = "quiz",
20
+ /** Competitive or difficult questions designed to test limits */
21
+ CHALLENGE = "challenge",
22
+ /** Multiplayer competitive session with rankings and prizes */
23
+ TOURNAMENT = "tournament",
24
+ /** Session for revisiting previously answered questions and mistakes */
25
+ REVIEW = "review",
26
+ /** Initial assessment to identify knowledge gaps and skill levels */
27
+ DIAGNOSTIC = "diagnostic",
28
+ /** Time-pressured rapid-fire questions focusing on speed and accuracy */
29
+ SPEED_TEST = "speed_test"
30
+ }
31
+ declare enum EFlashcardState {
32
+ /** Brand new card that hasn't been studied yet */
33
+ NEW = "new",
34
+ /** Card in learning phase with short intervals */
35
+ LEARNING = "learning",
36
+ /** Card in relearning phase after being forgotten */
37
+ RELEARNING = "relearning",
38
+ /** Graduated card in long-term review cycle */
39
+ REVIEW = "review",
40
+ /** Card temporarily hidden until next day */
41
+ BURIED = "buried",
42
+ /** Card permanently hidden from reviews */
43
+ SUSPENDED = "suspended"
44
+ }
45
+ declare enum EFlashcardRating {
46
+ /** Incorrect answer - restart learning */
47
+ AGAIN = "again",
48
+ /** Correct but difficult - shorter interval */
49
+ HARD = "hard",
50
+ /** Correct with some effort - normal interval */
51
+ GOOD = "good",
52
+ /** Correct with no effort - longer interval */
53
+ EASY = "easy"
54
+ }
55
+ declare enum EFlashcardSessionStatus {
56
+ DRAFT = "draft",
57
+ STARTED = "started",
58
+ PAUSED = "paused",
59
+ COMPLETED = "completed"
60
+ }
61
+ declare enum EFlashcardAlgorithm {
62
+ /** Legacy SuperMemo 2 algorithm */
63
+ SM2 = "sm2",
64
+ /** Free Spaced Repetition Scheduler (modern) */
65
+ FSRS = "fsrs"
66
+ }
67
+ interface IFlashcardSchedule extends IBase2 {
68
+ /** Current state of the card */
69
+ state: EFlashcardState;
70
+ /** Days until next review */
71
+ interval: number;
72
+ /** Ease factor for SM-2 algorithm (2.5 = 250%) */
73
+ easeFactor: number;
74
+ /** Number of times card has been reviewed */
75
+ reviewCount: number;
76
+ /** Number of times card has failed (lapses) */
77
+ lapseCount: number;
78
+ /** Current step in learning/relearning sequence */
79
+ currentStep: number;
80
+ /** When the card is due for review */
81
+ dueDate: Date;
82
+ /** Last time the card was reviewed */
83
+ lastReviewedAt?: Date | null;
84
+ /** FSRS-specific parameters */
85
+ difficulty?: number;
86
+ stability?: number;
87
+ retrievability?: number;
88
+ /** Learning steps for this card (in minutes) */
89
+ learningSteps: number[];
90
+ /** Relearning steps for this card (in minutes) */
91
+ relearningSteps: number[];
92
+ }
93
+ interface IFlashcard extends IBase2 {
94
+ /** Front side content */
95
+ front: string;
96
+ /** Back side content */
97
+ back: string;
98
+ /** Optional hint text */
99
+ hint?: string;
100
+ /** Optional context or source */
101
+ context?: string;
102
+ contextId?: string;
103
+ /** Scheduling information */
104
+ schedule: IFlashcardSchedule;
105
+ /** Additional metadata */
106
+ tags?: ITag[];
107
+ stat?: IStat;
108
+ status?: IStatus;
109
+ image?: IImage;
110
+ }
111
+ interface IFlashcardReview extends IBase2 {
112
+ /** The flashcard being reviewed */
113
+ card: IFlashcard;
114
+ /** Session this review belongs to */
115
+ session: IFlashcardSession;
116
+ /** User's rating for this review */
117
+ rating: EFlashcardRating;
118
+ /** Time taken to answer (in seconds) */
119
+ responseTime: number;
120
+ /** Previous interval before this review */
121
+ previousInterval: number;
122
+ /** New interval after this review */
123
+ newInterval: number;
124
+ /** Previous ease factor */
125
+ previousEaseFactor: number;
126
+ /** New ease factor */
127
+ newEaseFactor: number;
128
+ /** Previous due date */
129
+ previousDueDate: Date;
130
+ /** New due date */
131
+ newDueDate: Date;
132
+ /** Previous card state */
133
+ previousState: EFlashcardState;
134
+ /** New card state */
135
+ newState: EFlashcardState;
136
+ /** Whether this was a lapse (forgotten card) */
137
+ wasLapse: boolean;
138
+ /** Algorithm used for scheduling */
139
+ algorithm: EFlashcardAlgorithm;
140
+ /** Review timestamp */
141
+ reviewedAt: Date;
142
+ }
143
+ interface IFlashcardSession extends IBase2 {
144
+ name: string;
145
+ /** Total cards available for study */
146
+ totalCards: number;
147
+ /** Number of new cards in session */
148
+ newCardsCount: number;
149
+ /** Number of learning cards in session */
150
+ learningCardsCount: number;
151
+ /** Number of review cards in session */
152
+ reviewCardsCount: number;
153
+ /** Cards studied so far */
154
+ studiedCount: number;
155
+ /** Cards answered correctly */
156
+ correctCount: number;
157
+ /** Cards answered incorrectly */
158
+ incorrectCount: number;
159
+ /** Total study time in seconds */
160
+ studyTime: number;
161
+ /** Cards in this session */
162
+ cards: IFlashcard[];
163
+ /** Reviews completed in this session */
164
+ reviews: IFlashcardReview[];
165
+ /** Session status */
166
+ status: EFlashcardSessionStatus;
167
+ /** Overall session score (0-100) */
168
+ score: number;
169
+ /** Session start time */
170
+ startedAt?: Date | null;
171
+ /** Session pause time */
172
+ pausedAt?: Date | null;
173
+ /** Session resume time */
174
+ resumedAt?: Date | null;
175
+ /** Session completion time */
176
+ completedAt?: Date | null;
177
+ /** Type of study session */
178
+ type: ESessionType;
179
+ /** Difficulty level */
180
+ level: ILevel;
181
+ /** Algorithm configuration */
182
+ algorithm: EFlashcardAlgorithm;
183
+ /** Maximum new cards per session */
184
+ maxNewCards: number;
185
+ /** Maximum review cards per session */
186
+ maxReviewCards: number;
187
+ /** Desired retention rate (0-1) for FSRS */
188
+ desiredRetention: number;
189
+ /** Learning steps (in minutes) */
190
+ learningSteps: number[];
191
+ /** Graduating interval (in days) */
192
+ graduatingInterval: number;
193
+ /** Easy interval (in days) */
194
+ easyInterval: number;
195
+ /** Maximum interval (in days) */
196
+ maxInterval: number;
197
+ }
198
+ interface IFlashcardDeck extends IBase2 {
199
+ name: string;
200
+ description?: string;
201
+ /** Total cards in deck */
202
+ totalCards: number;
203
+ /** New cards ready to learn */
204
+ newCards: number;
205
+ /** Cards in learning phase */
206
+ learningCards: number;
207
+ /** Cards due for review today */
208
+ dueCards: number;
209
+ /** Cards suspended */
210
+ suspendedCards: number;
211
+ /** All flashcards in this deck */
212
+ cards: IFlashcard[];
213
+ /** Deck settings */
214
+ algorithm: EFlashcardAlgorithm;
215
+ maxNewCardsPerDay: number;
216
+ maxReviewCardsPerDay: number;
217
+ desiredRetention: number;
218
+ learningSteps: number[];
219
+ relearningSteps: number[];
220
+ graduatingInterval: number;
221
+ easyInterval: number;
222
+ maxInterval: number;
223
+ /** FSRS parameters (17 parameters) */
224
+ fsrsParameters?: number[];
225
+ /** Leech threshold (number of lapses before marking as leech) */
226
+ leechThreshold: number;
227
+ /** Whether to bury sibling cards */
228
+ burySiblings: boolean;
229
+ /** Deck statistics */
230
+ stat?: IStat;
231
+ status?: IStatus;
232
+ }
233
+ interface IFlashcardPreset extends IBase2 {
234
+ name: string;
235
+ description?: string;
236
+ /** Algorithm to use */
237
+ algorithm: EFlashcardAlgorithm;
238
+ /** Learning configuration */
239
+ learningSteps: number[];
240
+ relearningSteps: number[];
241
+ graduatingInterval: number;
242
+ easyInterval: number;
243
+ maxInterval: number;
244
+ /** Daily limits */
245
+ maxNewCardsPerDay: number;
246
+ maxReviewCardsPerDay: number;
247
+ /** FSRS configuration */
248
+ desiredRetention: number;
249
+ fsrsParameters?: number[];
250
+ /** SM-2 configuration */
251
+ startingEaseFactor: number;
252
+ easyBonus: number;
253
+ intervalModifier: number;
254
+ hardInterval: number;
255
+ newInterval: number;
256
+ /** Lapse configuration */
257
+ minimumInterval: number;
258
+ leechThreshold: number;
259
+ /** Display options */
260
+ burySiblings: boolean;
261
+ showTimer: boolean;
262
+ autoPlayAudio: boolean;
263
+ }
264
+ interface IFlashcardStats extends IBase2 {
265
+ /** Cards studied today */
266
+ cardsStudiedToday: number;
267
+ /** Time spent studying today (minutes) */
268
+ timeSpentToday: number;
269
+ /** Current streak (days) */
270
+ currentStreak: number;
271
+ /** Longest streak (days) */
272
+ longestStreak: number;
273
+ /** Total reviews all time */
274
+ totalReviews: number;
275
+ /** Total study time all time (minutes) */
276
+ totalStudyTime: number;
277
+ /** Average retention rate */
278
+ retentionRate: number;
279
+ /** Breakdown by card state */
280
+ newCardsCount: number;
281
+ learningCardsCount: number;
282
+ reviewCardsCount: number;
283
+ suspendedCardsCount: number;
284
+ /** Maturity statistics */
285
+ matureCardsCount: number;
286
+ youngCardsCount: number;
287
+ /** Performance by rating */
288
+ againCount: number;
289
+ hardCount: number;
290
+ goodCount: number;
291
+ easyCount: number;
292
+ /** Date range for these stats */
293
+ startDate: Date;
294
+ endDate: Date;
295
+ }
296
+ /**
297
+ * Base interface for spaced repetition algorithms
298
+ */
299
+ interface ISpacedRepetitionAlgorithm {
300
+ /**
301
+ * Calculate the next review schedule for a card
302
+ */
303
+ calculateNextReview: (card: IFlashcard, rating: EFlashcardRating, reviewTime: number) => IFlashcardSchedule;
304
+ /**
305
+ * Get the predicted intervals for each rating button
306
+ */
307
+ getIntervalPreview: (card: IFlashcard) => Record<EFlashcardRating, number>;
308
+ /**
309
+ * Initialize a new card's schedule
310
+ */
311
+ initializeCard: (learningSteps: number[]) => IFlashcardSchedule;
312
+ /**
313
+ * Get algorithm-specific parameters
314
+ */
315
+ getParameters: () => Record<string, unknown>;
316
+ /**
317
+ * Update algorithm parameters
318
+ */
319
+ setParameters: (parameters: Record<string, unknown>) => void;
320
+ }
321
+ /**
322
+ * SM-2 (SuperMemo 2) Algorithm Implementation Interface
323
+ */
324
+ interface ISM2Algorithm extends ISpacedRepetitionAlgorithm {
325
+ /**
326
+ * SM-2 specific parameters
327
+ */
328
+ getParameters: () => {
329
+ startingEaseFactor: number;
330
+ easyBonus: number;
331
+ intervalModifier: number;
332
+ hardInterval: number;
333
+ newInterval: number;
334
+ minimumInterval: number;
335
+ maxInterval: number;
336
+ graduatingInterval: number;
337
+ easyInterval: number;
338
+ };
339
+ /**
340
+ * Calculate ease factor adjustment
341
+ */
342
+ calculateEaseAdjustment: (rating: EFlashcardRating, currentEase: number) => number;
343
+ /**
344
+ * Calculate interval for review cards
345
+ */
346
+ calculateReviewInterval: (previousInterval: number, easeFactor: number, rating: EFlashcardRating) => number;
347
+ /**
348
+ * Handle learning phase transitions
349
+ */
350
+ processLearningCard: (card: IFlashcard, rating: EFlashcardRating, learningSteps: number[]) => {
351
+ newState: EFlashcardState;
352
+ interval: number;
353
+ currentStep: number;
354
+ };
355
+ /**
356
+ * Handle lapse (forgotten card)
357
+ */
358
+ processLapse: (card: IFlashcard, relearningSteps: number[]) => {
359
+ newState: EFlashcardState;
360
+ interval: number;
361
+ easeFactor: number;
362
+ currentStep: number;
363
+ };
364
+ }
365
+ /**
366
+ * FSRS (Free Spaced Repetition Scheduler) Algorithm Interface
367
+ */
368
+ interface IFSRSAlgorithm extends ISpacedRepetitionAlgorithm {
369
+ /**
370
+ * FSRS specific parameters (17 parameters)
371
+ */
372
+ getParameters: () => {
373
+ parameters: number[];
374
+ desiredRetention: number;
375
+ requestRetention: number;
376
+ maxInterval: number;
377
+ };
378
+ /**
379
+ * Calculate memory state (Difficulty, Stability, Retrievability)
380
+ */
381
+ calculateMemoryState: (difficulty: number, stability: number, retrievability: number, rating: EFlashcardRating, deltaT: number) => {
382
+ newDifficulty: number;
383
+ newStability: number;
384
+ newRetrievability: number;
385
+ };
386
+ /**
387
+ * Calculate retrievability based on time elapsed
388
+ */
389
+ calculateRetrievability: (stability: number, deltaT: number) => number;
390
+ /**
391
+ * Calculate next interval based on desired retention
392
+ */
393
+ calculateInterval: (stability: number, desiredRetention: number) => number;
394
+ /**
395
+ * Initialize FSRS card state
396
+ */
397
+ initializeFSRSCard: () => {
398
+ difficulty: number;
399
+ stability: number;
400
+ retrievability: number;
401
+ };
402
+ /**
403
+ * Optimize parameters based on review history
404
+ */
405
+ optimizeParameters: (reviews: IFlashcardReview[]) => number[];
406
+ /**
407
+ * Evaluate parameter quality
408
+ */
409
+ evaluateParameters: (reviews: IFlashcardReview[]) => {
410
+ logLoss: number;
411
+ rmse: number;
412
+ };
413
+ }
414
+ /**
415
+ * Algorithm factory for creating algorithm instances
416
+ */
417
+ interface IAlgorithmFactory {
418
+ /**
419
+ * Create SM-2 algorithm instance
420
+ */
421
+ createSM2Algorithm: (parameters?: Partial<ISM2Algorithm["getParameters"]>) => ISM2Algorithm;
422
+ /**
423
+ * Create FSRS algorithm instance
424
+ */
425
+ createFSRSAlgorithm: (parameters?: Partial<IFSRSAlgorithm["getParameters"]>) => IFSRSAlgorithm;
426
+ /**
427
+ * Get default parameters for an algorithm
428
+ */
429
+ getDefaultParameters: (algorithm: "sm2" | "fsrs") => Record<string, unknown>;
430
+ }
431
+ /**
432
+ * Algorithm utilities and helpers
433
+ */
434
+ interface IAlgorithmUtils {
435
+ /**
436
+ * Apply fuzzing to interval (randomization)
437
+ */
438
+ applyFuzzing: (interval: number, fuzzFactor?: number) => number;
439
+ /**
440
+ * Convert learning steps from minutes to intervals
441
+ */
442
+ convertLearningSteps: (steps: number[]) => number[];
443
+ /**
444
+ * Calculate next due date
445
+ */
446
+ calculateDueDate: (interval: number, baseDate?: Date) => Date;
447
+ /**
448
+ * Determine if interval should be fuzzed
449
+ */
450
+ shouldApplyFuzzing: (interval: number) => boolean;
451
+ /**
452
+ * Clamp interval to valid range
453
+ */
454
+ clampInterval: (interval: number, minInterval: number, maxInterval: number) => number;
455
+ /**
456
+ * Calculate average interval for multiple ratings
457
+ */
458
+ calculateAverageInterval: (intervals: number[]) => number;
459
+ }
460
+ /**
461
+ * Review statistics calculator
462
+ */
463
+ interface IReviewStats {
464
+ /**
465
+ * Calculate retention rate from reviews
466
+ */
467
+ calculateRetention: (reviews: IFlashcardReview[]) => number;
468
+ /**
469
+ * Calculate average response time
470
+ */
471
+ calculateAverageResponseTime: (reviews: IFlashcardReview[]) => number;
472
+ /**
473
+ * Get rating distribution
474
+ */
475
+ getRatingDistribution: (reviews: IFlashcardReview[]) => Record<EFlashcardRating, number>;
476
+ /**
477
+ * Calculate study load (cards per day)
478
+ */
479
+ calculateStudyLoad: (cards: IFlashcard[]) => {
480
+ newCards: number;
481
+ learningCards: number;
482
+ reviewCards: number;
483
+ total: number;
484
+ };
485
+ /**
486
+ * Predict future workload
487
+ */
488
+ predictWorkload: (cards: IFlashcard[], algorithm: ISpacedRepetitionAlgorithm, days: number) => {
489
+ date: Date;
490
+ newCards: number;
491
+ reviews: number;
492
+ total: number;
493
+ }[];
494
+ }
495
+ /**
496
+ * Scheduler for managing card due dates and priorities
497
+ */
498
+ interface ICardScheduler {
499
+ /**
500
+ * Get cards due for review
501
+ */
502
+ getDueCards: (cards: IFlashcard[], maxCards?: number) => IFlashcard[];
503
+ /**
504
+ * Get new cards ready for learning
505
+ */
506
+ getNewCards: (cards: IFlashcard[], maxCards?: number) => IFlashcard[];
507
+ /**
508
+ * Get learning cards ready for next step
509
+ */
510
+ getLearningCards: (cards: IFlashcard[]) => IFlashcard[];
511
+ /**
512
+ * Sort cards by priority
513
+ */
514
+ sortCardsByPriority: (cards: IFlashcard[], sortOrder: "due" | "random" | "added") => IFlashcard[];
515
+ /**
516
+ * Check if card is overdue
517
+ */
518
+ isOverdue: (card: IFlashcard) => boolean;
519
+ /**
520
+ * Calculate overdue factor
521
+ */
522
+ getOverdueFactor: (card: IFlashcard) => number;
523
+ /**
524
+ * Reschedule all cards with new algorithm
525
+ */
526
+ rescheduleCards: (cards: IFlashcard[], algorithm: ISpacedRepetitionAlgorithm) => IFlashcard[];
527
+ }
528
+ /**
529
+ * Default Anki algorithm constants
530
+ */
531
+ declare const ANKI_DEFAULTS: {
532
+ readonly LEARNING_STEPS: readonly [1, 10];
533
+ readonly GRADUATING_INTERVAL: 1;
534
+ readonly EASY_INTERVAL: 4;
535
+ readonly STARTING_EASE_FACTOR: 2.5;
536
+ readonly EASY_BONUS: 1.3;
537
+ readonly INTERVAL_MODIFIER: 1.0;
538
+ readonly HARD_INTERVAL: 1.2;
539
+ readonly RELEARNING_STEPS: readonly [10];
540
+ readonly NEW_INTERVAL: 0.0;
541
+ readonly MINIMUM_INTERVAL: 1;
542
+ readonly LEECH_THRESHOLD: 8;
543
+ readonly MAX_NEW_CARDS_PER_DAY: 20;
544
+ readonly MAX_REVIEW_CARDS_PER_DAY: 200;
545
+ readonly MAX_ANSWER_TIME: 60;
546
+ readonly MIN_INTERVAL: 1;
547
+ readonly MAX_INTERVAL: 36500;
548
+ readonly DESIRED_RETENTION: 0.9;
549
+ readonly FSRS_DEFAULT_PARAMETERS: readonly [0.4072, 1.1829, 3.1262, 15.4722, 7.2102, 0.5316, 1.0651, 0.0234, 1.616, 0.1544, 1.0824, 1.9813, 0.0953, 0.2975, 2.2042, 0.2407, 2.9466];
550
+ };
551
+ /**
552
+ * Rating multipliers for interval calculation
553
+ */
554
+ declare const RATING_MULTIPLIERS: Record<EFlashcardRating, number>;
555
+ /**
556
+ * Ease factor adjustments based on rating
557
+ */
558
+ declare const EASE_ADJUSTMENTS: Record<EFlashcardRating, number>;
559
+ /**
560
+ * Minimum and maximum ease factor bounds
561
+ */
562
+ declare const EASE_BOUNDS: {
563
+ readonly MIN: 1.3;
564
+ readonly MAX: 2.5;
565
+ };
566
+ /**
567
+ * Card state transitions based on rating
568
+ */
569
+ declare const STATE_TRANSITIONS: Record<EFlashcardState, Record<EFlashcardRating, EFlashcardState>>;
570
+ /**
571
+ * Learning step multipliers for Hard button
572
+ */
573
+ declare const LEARNING_HARD_MULTIPLIERS: {
574
+ readonly FIRST_STEP: 1.5;
575
+ readonly AVERAGE_STEPS: 0.5;
576
+ };
577
+ /**
578
+ * Fuzz factor for randomizing intervals
579
+ */
580
+ declare const FUZZ_FACTOR: {
581
+ readonly MIN: 0.95;
582
+ readonly MAX: 1.05;
583
+ };
584
+ /**
585
+ * Session scoring weights
586
+ */
587
+ declare const SCORE_WEIGHTS: Record<EFlashcardRating, number>;
588
+ /**
589
+ * Card maturity threshold (days)
590
+ */
591
+ declare const MATURITY_THRESHOLD = 21;
592
+ /**
593
+ * Default preset configurations
594
+ */
595
+ declare const DEFAULT_PRESETS: {
596
+ readonly BEGINNER: {
597
+ readonly name: "Beginner";
598
+ readonly description: "For new learners with more repetition";
599
+ readonly learningSteps: readonly [1, 10, 1440];
600
+ readonly graduatingInterval: 2;
601
+ readonly easyInterval: 7;
602
+ readonly maxNewCardsPerDay: 10;
603
+ readonly desiredRetention: 0.85;
604
+ };
605
+ readonly DEFAULT: {
606
+ readonly name: "Default";
607
+ readonly description: "Balanced settings for most users";
608
+ readonly learningSteps: readonly [1, 10];
609
+ readonly graduatingInterval: 1;
610
+ readonly easyInterval: 4;
611
+ readonly maxNewCardsPerDay: 20;
612
+ readonly desiredRetention: 0.9;
613
+ };
614
+ readonly INTENSIVE: {
615
+ readonly name: "Intensive";
616
+ readonly description: "For serious learners who want higher retention";
617
+ readonly learningSteps: readonly [1, 10];
618
+ readonly graduatingInterval: 1;
619
+ readonly easyInterval: 4;
620
+ readonly maxNewCardsPerDay: 30;
621
+ readonly desiredRetention: 0.95;
622
+ };
623
+ readonly LIGHT: {
624
+ readonly name: "Light";
625
+ readonly description: "For casual learning with fewer reviews";
626
+ readonly learningSteps: readonly [1, 10];
627
+ readonly graduatingInterval: 3;
628
+ readonly easyInterval: 7;
629
+ readonly maxNewCardsPerDay: 15;
630
+ readonly desiredRetention: 0.8;
631
+ };
632
+ };
633
+ /**
634
+ * Algorithm-specific constants
635
+ */
636
+ interface SM2Constants {
637
+ MIN_EASE_FACTOR: number;
638
+ MAX_EASE_FACTOR: number;
639
+ EASE_ADJUSTMENT_STEP: number;
640
+ }
641
+ interface FSRSConstants {
642
+ MIN_DIFFICULTY: number;
643
+ MAX_DIFFICULTY: number;
644
+ MIN_STABILITY: number;
645
+ MAX_STABILITY: number;
646
+ MIN_RETRIEVABILITY: number;
647
+ MAX_RETRIEVABILITY: number;
648
+ }
649
+ type AlgorithmConstants = {
650
+ [EFlashcardAlgorithm.SM2]: SM2Constants;
651
+ [EFlashcardAlgorithm.FSRS]: FSRSConstants;
652
+ };
653
+ declare const ALGORITHM_CONSTANTS: AlgorithmConstants;
654
+ /**
655
+ * Utility functions for common calculations
656
+ */
657
+ declare const UTILS: {
658
+ /**
659
+ * Convert minutes to milliseconds
660
+ */
661
+ readonly minutesToMs: (minutes: number) => number;
662
+ /**
663
+ * Convert days to milliseconds
664
+ */
665
+ readonly daysToMs: (days: number) => number;
666
+ /**
667
+ * Apply fuzz factor to interval
668
+ */
669
+ readonly applyFuzz: (interval: number) => number;
670
+ /**
671
+ * Clamp ease factor to valid range
672
+ */
673
+ readonly clampEaseFactor: (ease: number) => number;
674
+ /**
675
+ * Calculate session score
676
+ */
677
+ readonly calculateScore: (ratings: EFlashcardRating[]) => number;
678
+ /**
679
+ * Determine if card is mature
680
+ */
681
+ readonly isMature: (interval: number) => boolean;
682
+ };
683
+ export { UTILS, STATE_TRANSITIONS, SCORE_WEIGHTS, RATING_MULTIPLIERS, MATURITY_THRESHOLD, LEARNING_HARD_MULTIPLIERS, ISpacedRepetitionAlgorithm, ISM2Algorithm, IReviewStats, IFlashcardStats, IFlashcardSession, IFlashcardSchedule, IFlashcardReview, IFlashcardPreset, IFlashcardDeck, IFlashcard, IFSRSAlgorithm, ICardScheduler, IAlgorithmUtils, IAlgorithmFactory, FUZZ_FACTOR, EFlashcardState, EFlashcardSessionStatus, EFlashcardRating, EFlashcardAlgorithm, EASE_BOUNDS, EASE_ADJUSTMENTS, DEFAULT_PRESETS, ANKI_DEFAULTS, ALGORITHM_CONSTANTS };
@@ -0,0 +1,3 @@
1
+ var J;((f)=>{f.NEW="new";f.LEARNING="learning";f.RELEARNING="relearning";f.REVIEW="review";f.BURIED="buried";f.SUSPENDED="suspended"})(J||={});var K;((x)=>{x.AGAIN="again";x.HARD="hard";x.GOOD="good";x.EASY="easy"})(K||={});var b;((x)=>{x.DRAFT="draft";x.STARTED="started";x.PAUSED="paused";x.COMPLETED="completed"})(b||={});var Q;((j)=>{j.SM2="sm2";j.FSRS="fsrs"})(Q||={});var w={LEARNING_STEPS:[1,10],GRADUATING_INTERVAL:1,EASY_INTERVAL:4,STARTING_EASE_FACTOR:2.5,EASY_BONUS:1.3,INTERVAL_MODIFIER:1,HARD_INTERVAL:1.2,RELEARNING_STEPS:[10],NEW_INTERVAL:0,MINIMUM_INTERVAL:1,LEECH_THRESHOLD:8,MAX_NEW_CARDS_PER_DAY:20,MAX_REVIEW_CARDS_PER_DAY:200,MAX_ANSWER_TIME:60,MIN_INTERVAL:1,MAX_INTERVAL:36500,DESIRED_RETENTION:0.9,FSRS_DEFAULT_PARAMETERS:[0.4072,1.1829,3.1262,15.4722,7.2102,0.5316,1.0651,0.0234,1.616,0.1544,1.0824,1.9813,0.0953,0.2975,2.2042,0.2407,2.9466]},z=Object.freeze({again:0,hard:1.2,good:2.5,easy:3.25}),B=Object.freeze({again:-0.2,hard:-0.15,good:0,easy:0.15}),V={MIN:1.3,MAX:2.5},G=Object.freeze({new:Object.freeze({again:"learning",hard:"learning",good:"learning",easy:"review"}),learning:Object.freeze({again:"learning",hard:"learning",good:"learning",easy:"review"}),review:Object.freeze({again:"relearning",hard:"review",good:"review",easy:"review"}),relearning:Object.freeze({again:"relearning",hard:"relearning",good:"relearning",easy:"review"}),buried:Object.freeze({again:"buried",hard:"buried",good:"buried",easy:"buried"}),suspended:Object.freeze({again:"suspended",hard:"suspended",good:"suspended",easy:"suspended"})}),N={FIRST_STEP:1.5,AVERAGE_STEPS:0.5},q={MIN:0.95,MAX:1.05},X=Object.freeze({again:0,hard:50,good:80,easy:100}),L=21,P={BEGINNER:{name:"Beginner",description:"For new learners with more repetition",learningSteps:[1,10,1440],graduatingInterval:2,easyInterval:7,maxNewCardsPerDay:10,desiredRetention:0.85},DEFAULT:{name:"Default",description:"Balanced settings for most users",learningSteps:[1,10],graduatingInterval:1,easyInterval:4,maxNewCardsPerDay:20,desiredRetention:0.9},INTENSIVE:{name:"Intensive",description:"For serious learners who want higher retention",learningSteps:[1,10],graduatingInterval:1,easyInterval:4,maxNewCardsPerDay:30,desiredRetention:0.95},LIGHT:{name:"Light",description:"For casual learning with fewer reviews",learningSteps:[1,10],graduatingInterval:3,easyInterval:7,maxNewCardsPerDay:15,desiredRetention:0.8}},W=Object.freeze({sm2:Object.freeze({MIN_EASE_FACTOR:1.3,MAX_EASE_FACTOR:2.5,EASE_ADJUSTMENT_STEP:0.15}),fsrs:Object.freeze({MIN_DIFFICULTY:1,MAX_DIFFICULTY:10,MIN_STABILITY:0.1,MAX_STABILITY:36500,MIN_RETRIEVABILITY:0.01,MAX_RETRIEVABILITY:0.99})}),y={minutesToMs:(p)=>p*60*1000,daysToMs:(p)=>p*24*60*60*1000,applyFuzz:(p)=>{let k=q.MIN+Math.random()*(q.MAX-q.MIN);return Math.max(1,Math.round(p*k))},clampEaseFactor:(p)=>{return Math.max(V.MIN,Math.min(p,V.MAX))},calculateScore:(p)=>{if(p.length===0)return 0;let k=p.reduce(($,x)=>$+X[x],0),j=p.length*X["easy"];return Math.round(k/j*100)},isMature:(p)=>p>=L};export{y as UTILS,G as STATE_TRANSITIONS,X as SCORE_WEIGHTS,z as RATING_MULTIPLIERS,L as MATURITY_THRESHOLD,N as LEARNING_HARD_MULTIPLIERS,q as FUZZ_FACTOR,J as EFlashcardState,b as EFlashcardSessionStatus,K as EFlashcardRating,Q as EFlashcardAlgorithm,V as EASE_BOUNDS,B as EASE_ADJUSTMENTS,P as DEFAULT_PRESETS,w as ANKI_DEFAULTS,W as ALGORITHM_CONSTANTS};
2
+
3
+ //# debugId=38A76FAEB9774D5664756E2164756E21
@@ -0,0 +1,11 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["src/flashcard/types.ts", "src/flashcard/constants.ts"],
4
+ "sourcesContent": [
5
+ "import type { IImage } from \"@ooneex/image\";\nimport type { IStatus } from \"@ooneex/status\";\nimport type { ITag } from \"@ooneex/tag\";\nimport type { IBase, IStat } from \"@ooneex/types\";\nimport type { ESessionType, ILevel } from \"../types\";\n\nexport enum EFlashcardState {\n /** Brand new card that hasn't been studied yet */\n NEW = \"new\",\n /** Card in learning phase with short intervals */\n LEARNING = \"learning\",\n /** Card in relearning phase after being forgotten */\n RELEARNING = \"relearning\",\n /** Graduated card in long-term review cycle */\n REVIEW = \"review\",\n /** Card temporarily hidden until next day */\n BURIED = \"buried\",\n /** Card permanently hidden from reviews */\n SUSPENDED = \"suspended\",\n}\n\nexport enum EFlashcardRating {\n /** Incorrect answer - restart learning */\n AGAIN = \"again\",\n /** Correct but difficult - shorter interval */\n HARD = \"hard\",\n /** Correct with some effort - normal interval */\n GOOD = \"good\",\n /** Correct with no effort - longer interval */\n EASY = \"easy\",\n}\n\nexport enum EFlashcardSessionStatus {\n DRAFT = \"draft\",\n STARTED = \"started\",\n PAUSED = \"paused\",\n COMPLETED = \"completed\",\n}\n\nexport enum EFlashcardAlgorithm {\n /** Legacy SuperMemo 2 algorithm */\n SM2 = \"sm2\",\n /** Free Spaced Repetition Scheduler (modern) */\n FSRS = \"fsrs\",\n}\n\nexport interface IFlashcardSchedule extends IBase {\n /** Current state of the card */\n state: EFlashcardState;\n /** Days until next review */\n interval: number;\n /** Ease factor for SM-2 algorithm (2.5 = 250%) */\n easeFactor: number;\n /** Number of times card has been reviewed */\n reviewCount: number;\n /** Number of times card has failed (lapses) */\n lapseCount: number;\n /** Current step in learning/relearning sequence */\n currentStep: number;\n /** When the card is due for review */\n dueDate: Date;\n /** Last time the card was reviewed */\n lastReviewedAt?: Date | null;\n /** FSRS-specific parameters */\n difficulty?: number; // FSRS difficulty (0-10)\n stability?: number; // FSRS stability in days\n retrievability?: number; // FSRS retrievability (0-1)\n /** Learning steps for this card (in minutes) */\n learningSteps: number[];\n /** Relearning steps for this card (in minutes) */\n relearningSteps: number[];\n}\n\nexport interface IFlashcard extends IBase {\n /** Front side content */\n front: string;\n /** Back side content */\n back: string;\n /** Optional hint text */\n hint?: string;\n /** Optional context or source */\n context?: string;\n contextId?: string;\n /** Scheduling information */\n schedule: IFlashcardSchedule;\n /** Additional metadata */\n tags?: ITag[];\n stat?: IStat;\n status?: IStatus;\n image?: IImage;\n}\n\nexport interface IFlashcardReview extends IBase {\n /** The flashcard being reviewed */\n card: IFlashcard;\n /** Session this review belongs to */\n session: IFlashcardSession;\n /** User's rating for this review */\n rating: EFlashcardRating;\n /** Time taken to answer (in seconds) */\n responseTime: number;\n /** Previous interval before this review */\n previousInterval: number;\n /** New interval after this review */\n newInterval: number;\n /** Previous ease factor */\n previousEaseFactor: number;\n /** New ease factor */\n newEaseFactor: number;\n /** Previous due date */\n previousDueDate: Date;\n /** New due date */\n newDueDate: Date;\n /** Previous card state */\n previousState: EFlashcardState;\n /** New card state */\n newState: EFlashcardState;\n /** Whether this was a lapse (forgotten card) */\n wasLapse: boolean;\n /** Algorithm used for scheduling */\n algorithm: EFlashcardAlgorithm;\n /** Review timestamp */\n reviewedAt: Date;\n}\n\nexport interface IFlashcardSession extends IBase {\n name: string;\n /** Total cards available for study */\n totalCards: number;\n /** Number of new cards in session */\n newCardsCount: number;\n /** Number of learning cards in session */\n learningCardsCount: number;\n /** Number of review cards in session */\n reviewCardsCount: number;\n /** Cards studied so far */\n studiedCount: number;\n /** Cards answered correctly */\n correctCount: number;\n /** Cards answered incorrectly */\n incorrectCount: number;\n /** Total study time in seconds */\n studyTime: number;\n /** Cards in this session */\n cards: IFlashcard[];\n /** Reviews completed in this session */\n reviews: IFlashcardReview[];\n /** Session status */\n status: EFlashcardSessionStatus;\n /** Overall session score (0-100) */\n score: number;\n /** Session start time */\n startedAt?: Date | null;\n /** Session pause time */\n pausedAt?: Date | null;\n /** Session resume time */\n resumedAt?: Date | null;\n /** Session completion time */\n completedAt?: Date | null;\n /** Type of study session */\n type: ESessionType;\n /** Difficulty level */\n level: ILevel;\n /** Algorithm configuration */\n algorithm: EFlashcardAlgorithm;\n /** Maximum new cards per session */\n maxNewCards: number;\n /** Maximum review cards per session */\n maxReviewCards: number;\n /** Desired retention rate (0-1) for FSRS */\n desiredRetention: number;\n /** Learning steps (in minutes) */\n learningSteps: number[];\n /** Graduating interval (in days) */\n graduatingInterval: number;\n /** Easy interval (in days) */\n easyInterval: number;\n /** Maximum interval (in days) */\n maxInterval: number;\n}\n\nexport interface IFlashcardDeck extends IBase {\n name: string;\n description?: string;\n /** Total cards in deck */\n totalCards: number;\n /** New cards ready to learn */\n newCards: number;\n /** Cards in learning phase */\n learningCards: number;\n /** Cards due for review today */\n dueCards: number;\n /** Cards suspended */\n suspendedCards: number;\n /** All flashcards in this deck */\n cards: IFlashcard[];\n /** Deck settings */\n algorithm: EFlashcardAlgorithm;\n maxNewCardsPerDay: number;\n maxReviewCardsPerDay: number;\n desiredRetention: number;\n learningSteps: number[];\n relearningSteps: number[];\n graduatingInterval: number;\n easyInterval: number;\n maxInterval: number;\n /** FSRS parameters (17 parameters) */\n fsrsParameters?: number[];\n /** Leech threshold (number of lapses before marking as leech) */\n leechThreshold: number;\n /** Whether to bury sibling cards */\n burySiblings: boolean;\n /** Deck statistics */\n stat?: IStat;\n status?: IStatus;\n}\n\nexport interface IFlashcardPreset extends IBase {\n name: string;\n description?: string;\n /** Algorithm to use */\n algorithm: EFlashcardAlgorithm;\n /** Learning configuration */\n learningSteps: number[];\n relearningSteps: number[];\n graduatingInterval: number;\n easyInterval: number;\n maxInterval: number;\n /** Daily limits */\n maxNewCardsPerDay: number;\n maxReviewCardsPerDay: number;\n /** FSRS configuration */\n desiredRetention: number;\n fsrsParameters?: number[];\n /** SM-2 configuration */\n startingEaseFactor: number;\n easyBonus: number;\n intervalModifier: number;\n hardInterval: number;\n newInterval: number;\n /** Lapse configuration */\n minimumInterval: number;\n leechThreshold: number;\n /** Display options */\n burySiblings: boolean;\n showTimer: boolean;\n autoPlayAudio: boolean;\n}\n\nexport interface IFlashcardStats extends IBase {\n /** Cards studied today */\n cardsStudiedToday: number;\n /** Time spent studying today (minutes) */\n timeSpentToday: number;\n /** Current streak (days) */\n currentStreak: number;\n /** Longest streak (days) */\n longestStreak: number;\n /** Total reviews all time */\n totalReviews: number;\n /** Total study time all time (minutes) */\n totalStudyTime: number;\n /** Average retention rate */\n retentionRate: number;\n /** Breakdown by card state */\n newCardsCount: number;\n learningCardsCount: number;\n reviewCardsCount: number;\n suspendedCardsCount: number;\n /** Maturity statistics */\n matureCardsCount: number; // Cards with interval >= 21 days\n youngCardsCount: number; // Cards with interval < 21 days\n /** Performance by rating */\n againCount: number;\n hardCount: number;\n goodCount: number;\n easyCount: number;\n /** Date range for these stats */\n startDate: Date;\n endDate: Date;\n}\n",
6
+ "import { EFlashcardAlgorithm, EFlashcardRating, EFlashcardState } from \"./types\";\n\n/**\n * Default Anki algorithm constants\n */\nexport const ANKI_DEFAULTS = {\n // Learning phase\n LEARNING_STEPS: [1, 10], // 1 minute, 10 minutes\n GRADUATING_INTERVAL: 1, // 1 day\n EASY_INTERVAL: 4, // 4 days\n\n // Review phase (SM-2)\n STARTING_EASE_FACTOR: 2.5, // 250%\n EASY_BONUS: 1.3, // 130%\n INTERVAL_MODIFIER: 1.0, // 100%\n HARD_INTERVAL: 1.2, // 120%\n\n // Lapses\n RELEARNING_STEPS: [10], // 10 minutes\n NEW_INTERVAL: 0.0, // 0% of previous interval\n MINIMUM_INTERVAL: 1, // 1 day\n LEECH_THRESHOLD: 8, // 8 lapses\n\n // Daily limits\n MAX_NEW_CARDS_PER_DAY: 20,\n MAX_REVIEW_CARDS_PER_DAY: 200,\n\n // Timing\n MAX_ANSWER_TIME: 60, // 60 seconds\n MIN_INTERVAL: 1, // 1 day minimum\n MAX_INTERVAL: 36500, // 100 years\n\n // FSRS\n DESIRED_RETENTION: 0.9, // 90%\n FSRS_DEFAULT_PARAMETERS: [\n 0.4072, 1.1829, 3.1262, 15.4722, 7.2102, 0.5316, 1.0651, 0.0234, 1.616, 0.1544, 1.0824, 1.9813, 0.0953, 0.2975,\n 2.2042, 0.2407, 2.9466,\n ],\n} as const;\n\n/**\n * Rating multipliers for interval calculation\n */\nexport const RATING_MULTIPLIERS: Record<EFlashcardRating, number> = Object.freeze({\n [EFlashcardRating.AGAIN]: 0, // Reset to learning\n [EFlashcardRating.HARD]: 1.2,\n [EFlashcardRating.GOOD]: 2.5, // Default ease factor\n [EFlashcardRating.EASY]: 2.5 * 1.3, // Easy bonus applied\n});\n\n/**\n * Ease factor adjustments based on rating\n */\nexport const EASE_ADJUSTMENTS: Record<EFlashcardRating, number> = Object.freeze({\n [EFlashcardRating.AGAIN]: -0.2, // Decrease ease by 20%\n [EFlashcardRating.HARD]: -0.15, // Decrease ease by 15%\n [EFlashcardRating.GOOD]: 0, // No change\n [EFlashcardRating.EASY]: 0.15, // Increase ease by 15%\n});\n\n/**\n * Minimum and maximum ease factor bounds\n */\nexport const EASE_BOUNDS = {\n MIN: 1.3, // 130% minimum\n MAX: 2.5, // 250% maximum (no upper bound in practice)\n} as const;\n\n/**\n * Card state transitions based on rating\n */\nexport const STATE_TRANSITIONS: Record<EFlashcardState, Record<EFlashcardRating, EFlashcardState>> = Object.freeze({\n [EFlashcardState.NEW]: Object.freeze({\n [EFlashcardRating.AGAIN]: EFlashcardState.LEARNING,\n [EFlashcardRating.HARD]: EFlashcardState.LEARNING,\n [EFlashcardRating.GOOD]: EFlashcardState.LEARNING,\n [EFlashcardRating.EASY]: EFlashcardState.REVIEW,\n }),\n [EFlashcardState.LEARNING]: Object.freeze({\n [EFlashcardRating.AGAIN]: EFlashcardState.LEARNING, // Restart learning\n [EFlashcardRating.HARD]: EFlashcardState.LEARNING, // Repeat current step\n [EFlashcardRating.GOOD]: EFlashcardState.LEARNING, // Next step or graduate\n [EFlashcardRating.EASY]: EFlashcardState.REVIEW, // Skip to review\n }),\n [EFlashcardState.REVIEW]: Object.freeze({\n [EFlashcardRating.AGAIN]: EFlashcardState.RELEARNING,\n [EFlashcardRating.HARD]: EFlashcardState.REVIEW,\n [EFlashcardRating.GOOD]: EFlashcardState.REVIEW,\n [EFlashcardRating.EASY]: EFlashcardState.REVIEW,\n }),\n [EFlashcardState.RELEARNING]: Object.freeze({\n [EFlashcardRating.AGAIN]: EFlashcardState.RELEARNING, // Restart relearning\n [EFlashcardRating.HARD]: EFlashcardState.RELEARNING, // Repeat current step\n [EFlashcardRating.GOOD]: EFlashcardState.RELEARNING, // Next step or back to review\n [EFlashcardRating.EASY]: EFlashcardState.REVIEW, // Skip to review\n }),\n [EFlashcardState.BURIED]: Object.freeze({\n [EFlashcardRating.AGAIN]: EFlashcardState.BURIED, // Remains buried\n [EFlashcardRating.HARD]: EFlashcardState.BURIED, // Remains buried\n [EFlashcardRating.GOOD]: EFlashcardState.BURIED, // Remains buried\n [EFlashcardRating.EASY]: EFlashcardState.BURIED, // Remains buried\n }),\n [EFlashcardState.SUSPENDED]: Object.freeze({\n [EFlashcardRating.AGAIN]: EFlashcardState.SUSPENDED, // Remains suspended\n [EFlashcardRating.HARD]: EFlashcardState.SUSPENDED, // Remains suspended\n [EFlashcardRating.GOOD]: EFlashcardState.SUSPENDED, // Remains suspended\n [EFlashcardRating.EASY]: EFlashcardState.SUSPENDED, // Remains suspended\n }),\n});\n\n/**\n * Learning step multipliers for Hard button\n */\nexport const LEARNING_HARD_MULTIPLIERS = {\n FIRST_STEP: 1.5, // 150% of first step when only one step\n AVERAGE_STEPS: 0.5, // 50% of average between current and next step\n} as const;\n\n/**\n * Fuzz factor for randomizing intervals\n */\nexport const FUZZ_FACTOR = {\n MIN: 0.95, // 95% of calculated interval\n MAX: 1.05, // 105% of calculated interval\n} as const;\n\n/**\n * Session scoring weights\n */\nexport const SCORE_WEIGHTS: Record<EFlashcardRating, number> = Object.freeze({\n [EFlashcardRating.AGAIN]: 0, // 0 points\n [EFlashcardRating.HARD]: 50, // 50 points\n [EFlashcardRating.GOOD]: 80, // 80 points\n [EFlashcardRating.EASY]: 100, // 100 points\n});\n\n/**\n * Card maturity threshold (days)\n */\nexport const MATURITY_THRESHOLD = 21; // Cards with interval >= 21 days are mature\n\n/**\n * Default preset configurations\n */\nexport const DEFAULT_PRESETS = {\n BEGINNER: {\n name: \"Beginner\",\n description: \"For new learners with more repetition\",\n learningSteps: [1, 10, 1440], // 1m, 10m, 1d\n graduatingInterval: 2,\n easyInterval: 7,\n maxNewCardsPerDay: 10,\n desiredRetention: 0.85,\n },\n DEFAULT: {\n name: \"Default\",\n description: \"Balanced settings for most users\",\n learningSteps: [1, 10], // 1m, 10m\n graduatingInterval: 1,\n easyInterval: 4,\n maxNewCardsPerDay: 20,\n desiredRetention: 0.9,\n },\n INTENSIVE: {\n name: \"Intensive\",\n description: \"For serious learners who want higher retention\",\n learningSteps: [1, 10], // 1m, 10m\n graduatingInterval: 1,\n easyInterval: 4,\n maxNewCardsPerDay: 30,\n desiredRetention: 0.95,\n },\n LIGHT: {\n name: \"Light\",\n description: \"For casual learning with fewer reviews\",\n learningSteps: [1, 10], // 1m, 10m\n graduatingInterval: 3,\n easyInterval: 7,\n maxNewCardsPerDay: 15,\n desiredRetention: 0.8,\n },\n} as const;\n\n/**\n * Algorithm-specific constants\n */\ninterface SM2Constants {\n MIN_EASE_FACTOR: number;\n MAX_EASE_FACTOR: number;\n EASE_ADJUSTMENT_STEP: number;\n}\n\ninterface FSRSConstants {\n MIN_DIFFICULTY: number;\n MAX_DIFFICULTY: number;\n MIN_STABILITY: number;\n MAX_STABILITY: number;\n MIN_RETRIEVABILITY: number;\n MAX_RETRIEVABILITY: number;\n}\n\ntype AlgorithmConstants = {\n [EFlashcardAlgorithm.SM2]: SM2Constants;\n [EFlashcardAlgorithm.FSRS]: FSRSConstants;\n};\n\nexport const ALGORITHM_CONSTANTS: AlgorithmConstants = Object.freeze({\n [EFlashcardAlgorithm.SM2]: Object.freeze({\n MIN_EASE_FACTOR: 1.3,\n MAX_EASE_FACTOR: 2.5,\n EASE_ADJUSTMENT_STEP: 0.15,\n }),\n [EFlashcardAlgorithm.FSRS]: Object.freeze({\n MIN_DIFFICULTY: 1,\n MAX_DIFFICULTY: 10,\n MIN_STABILITY: 0.1,\n MAX_STABILITY: 36500,\n MIN_RETRIEVABILITY: 0.01,\n MAX_RETRIEVABILITY: 0.99,\n }),\n});\n\n/**\n * Utility functions for common calculations\n */\nexport const UTILS = {\n /**\n * Convert minutes to milliseconds\n */\n minutesToMs: (minutes: number): number => minutes * 60 * 1000,\n\n /**\n * Convert days to milliseconds\n */\n daysToMs: (days: number): number => days * 24 * 60 * 60 * 1000,\n\n /**\n * Apply fuzz factor to interval\n */\n applyFuzz: (interval: number): number => {\n const fuzz = FUZZ_FACTOR.MIN + Math.random() * (FUZZ_FACTOR.MAX - FUZZ_FACTOR.MIN);\n return Math.max(1, Math.round(interval * fuzz));\n },\n\n /**\n * Clamp ease factor to valid range\n */\n clampEaseFactor: (ease: number): number => {\n return Math.max(EASE_BOUNDS.MIN, Math.min(ease, EASE_BOUNDS.MAX));\n },\n\n /**\n * Calculate session score\n */\n calculateScore: (ratings: EFlashcardRating[]): number => {\n if (ratings.length === 0) return 0;\n const totalPoints = ratings.reduce((sum, rating) => sum + SCORE_WEIGHTS[rating], 0);\n const maxPossible = ratings.length * SCORE_WEIGHTS[EFlashcardRating.EASY];\n return Math.round((totalPoints / maxPossible) * 100);\n },\n\n /**\n * Determine if card is mature\n */\n isMature: (interval: number): boolean => interval >= MATURITY_THRESHOLD,\n} as const;\n"
7
+ ],
8
+ "mappings": "AAMO,IAAK,GAAL,CAAK,IAAL,CAEL,MAAM,MAEN,WAAW,WAEX,aAAa,aAEb,SAAS,SAET,SAAS,SAET,YAAY,cAZF,QAeL,IAAK,GAAL,CAAK,IAAL,CAEL,QAAQ,QAER,OAAO,OAEP,OAAO,OAEP,OAAO,SARG,QAWL,IAAK,GAAL,CAAK,IAAL,CACL,QAAQ,QACR,UAAU,UACV,SAAS,SACT,YAAY,cAJF,QAOL,IAAK,GAAL,CAAK,IAAL,CAEL,MAAM,MAEN,OAAO,SAJG,QClCL,IAAM,EAAgB,CAE3B,eAAgB,CAAC,EAAG,EAAE,EACtB,oBAAqB,EACrB,cAAe,EAGf,qBAAsB,IACtB,WAAY,IACZ,kBAAmB,EACnB,cAAe,IAGf,iBAAkB,CAAC,EAAE,EACrB,aAAc,EACd,iBAAkB,EAClB,gBAAiB,EAGjB,sBAAuB,GACvB,yBAA0B,IAG1B,gBAAiB,GACjB,aAAc,EACd,aAAc,MAGd,kBAAmB,IACnB,wBAAyB,CACvB,OAAQ,OAAQ,OAAQ,QAAS,OAAQ,OAAQ,OAAQ,OAAQ,MAAO,OAAQ,OAAQ,OAAQ,OAAQ,OACxG,OAAQ,OAAQ,MAClB,CACF,EAKa,EAAuD,OAAO,OAAO,CAC/E,MAAyB,EACzB,KAAwB,IACxB,KAAwB,IACxB,KAAwB,IAC3B,CAAC,EAKY,EAAqD,OAAO,OAAO,CAC7E,MAAyB,KACzB,KAAwB,MACxB,KAAwB,EACxB,KAAwB,IAC3B,CAAC,EAKY,EAAc,CACzB,IAAK,IACL,IAAK,GACP,EAKa,EAAwF,OAAO,OAAO,CAChH,IAAsB,OAAO,OAAO,CAClC,iBACA,gBACA,gBACA,aACH,CAAC,EACA,SAA2B,OAAO,OAAO,CACvC,iBACA,gBACA,gBACA,aACH,CAAC,EACA,OAAyB,OAAO,OAAO,CACrC,mBACA,cACA,cACA,aACH,CAAC,EACA,WAA6B,OAAO,OAAO,CACzC,mBACA,kBACA,kBACA,aACH,CAAC,EACA,OAAyB,OAAO,OAAO,CACrC,eACA,cACA,cACA,aACH,CAAC,EACA,UAA4B,OAAO,OAAO,CACxC,kBACA,iBACA,iBACA,gBACH,CAAC,CACH,CAAC,EAKY,EAA4B,CACvC,WAAY,IACZ,cAAe,GACjB,EAKa,EAAc,CACzB,IAAK,KACL,IAAK,IACP,EAKa,EAAkD,OAAO,OAAO,CAC1E,MAAyB,EACzB,KAAwB,GACxB,KAAwB,GACxB,KAAwB,GAC3B,CAAC,EAKY,EAAqB,GAKrB,EAAkB,CAC7B,SAAU,CACR,KAAM,WACN,YAAa,wCACb,cAAe,CAAC,EAAG,GAAI,IAAI,EAC3B,mBAAoB,EACpB,aAAc,EACd,kBAAmB,GACnB,iBAAkB,IACpB,EACA,QAAS,CACP,KAAM,UACN,YAAa,mCACb,cAAe,CAAC,EAAG,EAAE,EACrB,mBAAoB,EACpB,aAAc,EACd,kBAAmB,GACnB,iBAAkB,GACpB,EACA,UAAW,CACT,KAAM,YACN,YAAa,iDACb,cAAe,CAAC,EAAG,EAAE,EACrB,mBAAoB,EACpB,aAAc,EACd,kBAAmB,GACnB,iBAAkB,IACpB,EACA,MAAO,CACL,KAAM,QACN,YAAa,yCACb,cAAe,CAAC,EAAG,EAAE,EACrB,mBAAoB,EACpB,aAAc,EACd,kBAAmB,GACnB,iBAAkB,GACpB,CACF,EAyBa,EAA0C,OAAO,OAAO,CAClE,IAA0B,OAAO,OAAO,CACvC,gBAAiB,IACjB,gBAAiB,IACjB,qBAAsB,IACxB,CAAC,EACA,KAA2B,OAAO,OAAO,CACxC,eAAgB,EAChB,eAAgB,GAChB,cAAe,IACf,cAAe,MACf,mBAAoB,KACpB,mBAAoB,IACtB,CAAC,CACH,CAAC,EAKY,EAAQ,CAInB,YAAa,CAAC,IAA4B,EAAU,GAAK,KAKzD,SAAU,CAAC,IAAyB,EAAO,GAAK,GAAK,GAAK,KAK1D,UAAW,CAAC,IAA6B,CACvC,IAAM,EAAO,EAAY,IAAM,KAAK,OAAO,GAAK,EAAY,IAAM,EAAY,KAC9E,OAAO,KAAK,IAAI,EAAG,KAAK,MAAM,EAAW,CAAI,CAAC,GAMhD,gBAAiB,CAAC,IAAyB,CACzC,OAAO,KAAK,IAAI,EAAY,IAAK,KAAK,IAAI,EAAM,EAAY,GAAG,CAAC,GAMlE,eAAgB,CAAC,IAAwC,CACvD,GAAI,EAAQ,SAAW,EAAG,MAAO,GACjC,IAAM,EAAc,EAAQ,OAAO,CAAC,EAAK,IAAW,EAAM,EAAc,GAAS,CAAC,EAC5E,EAAc,EAAQ,OAAS,EAAc,QACnD,OAAO,KAAK,MAAO,EAAc,EAAe,GAAG,GAMrD,SAAU,CAAC,IAA8B,GAAY,CACvD",
9
+ "debugId": "38A76FAEB9774D5664756E2164756E21",
10
+ "names": []
11
+ }
@@ -0,0 +1,40 @@
1
+ import { IBase } from "@ooneex/types";
2
+ interface ILevel extends IBase {
3
+ name: string;
4
+ code: string;
5
+ color: string;
6
+ }
7
+ declare enum ESessionType {
8
+ /** Learning-focused session with detailed explanations and guided experience */
9
+ TRAINING = "training",
10
+ /** Reinforcement session for solidifying already learned knowledge */
11
+ PRACTICE = "practice",
12
+ /** Mock test environment simulating real exam conditions */
13
+ SIMULATION = "simulation",
14
+ /** Quick knowledge check with immediate feedback */
15
+ QUIZ = "quiz",
16
+ /** Competitive or difficult questions designed to test limits */
17
+ CHALLENGE = "challenge",
18
+ /** Multiplayer competitive session with rankings and prizes */
19
+ TOURNAMENT = "tournament",
20
+ /** Session for revisiting previously answered questions and mistakes */
21
+ REVIEW = "review",
22
+ /** Initial assessment to identify knowledge gaps and skill levels */
23
+ DIAGNOSTIC = "diagnostic",
24
+ /** Time-pressured rapid-fire questions focusing on speed and accuracy */
25
+ SPEED_TEST = "speed_test"
26
+ }
27
+ declare enum EAnswerState {
28
+ CORRECT = "correct",
29
+ INCORRECT = "incorrect"
30
+ }
31
+ type SessionTypeItem = {
32
+ readonly code: ESessionType;
33
+ readonly name: string;
34
+ readonly description: string;
35
+ readonly color: string;
36
+ };
37
+ declare const SESSION_TYPES_EN: readonly SessionTypeItem[];
38
+ declare const SESSION_TYPES_FR: readonly SessionTypeItem[];
39
+ declare const SESSION_TYPES_RO: readonly SessionTypeItem[];
40
+ export { SESSION_TYPES_RO, SESSION_TYPES_FR, SESSION_TYPES_EN, ILevel, ESessionType, EAnswerState };
package/dist/index.js ADDED
@@ -0,0 +1,3 @@
1
+ var n;((e)=>{e.TRAINING="training";e.PRACTICE="practice";e.SIMULATION="simulation";e.QUIZ="quiz";e.CHALLENGE="challenge";e.TOURNAMENT="tournament";e.REVIEW="review";e.DIAGNOSTIC="diagnostic";e.SPEED_TEST="speed_test"})(n||={});var o;((i)=>{i.CORRECT="correct";i.INCORRECT="incorrect"})(o||={});var s=[{code:"training",name:"Training",description:"Learning-focused session with detailed explanations and guided experience. Perfect for acquiring new knowledge and understanding complex concepts step by step.",color:"#3b82f6"},{code:"practice",name:"Practice",description:"Reinforcement session for solidifying already learned knowledge. Helps strengthen understanding through repetition and application of learned concepts.",color:"#10b981"},{code:"simulation",name:"Simulation",description:"Mock test environment simulating real exam conditions. Provides realistic practice experience with authentic timing and pressure conditions.",color:"#f59e0b"},{code:"quiz",name:"Quiz",description:"Quick knowledge check with immediate feedback. Short and focused sessions to assess current understanding and identify areas for improvement.",color:"#8b5cf6"},{code:"challenge",name:"Challenge",description:"Competitive or difficult questions designed to test limits. Advanced sessions that push your knowledge boundaries and critical thinking skills.",color:"#ef4444"},{code:"tournament",name:"Tournament",description:"Multiplayer competitive session with rankings and prizes. Compete against other players in real-time for leaderboard positions and rewards.",color:"#f59e0b"},{code:"review",name:"Review",description:"Session for revisiting previously answered questions and mistakes. Focused practice on areas where improvement is needed based on past performance.",color:"#6b7280"},{code:"diagnostic",name:"Diagnostic",description:"Initial assessment to identify knowledge gaps and skill levels. Comprehensive evaluation to create a personalized learning path.",color:"#06b6d4"},{code:"speed_test",name:"Speed Test",description:"Time-pressured rapid-fire questions focusing on speed and accuracy. Develops quick thinking and decision-making skills under time constraints.",color:"#ec4899"}],t=[{code:"training",name:"Formation",description:"Session d'apprentissage avec explications détaillées et expérience guidée. Parfait pour acquérir de nouvelles connaissances et comprendre des concepts complexes étape par étape.",color:"#3b82f6"},{code:"practice",name:"Pratique",description:"Session de renforcement pour consolider les connaissances déjà apprises. Aide à renforcer la compréhension par la répétition et l'application des concepts appris.",color:"#10b981"},{code:"simulation",name:"Simulation",description:"Environnement d'examen simulé reproduisant les conditions réelles d'examen. Offre une expérience de pratique réaliste avec un timing et une pression authentiques.",color:"#f59e0b"},{code:"quiz",name:"Quiz",description:"Contrôle rapide des connaissances avec feedback immédiat. Sessions courtes et ciblées pour évaluer la compréhension actuelle et identifier les domaines à améliorer.",color:"#8b5cf6"},{code:"challenge",name:"Défi",description:"Questions compétitives ou difficiles conçues pour tester les limites. Sessions avancées qui repoussent vos limites de connaissances et vos compétences de pensée critique.",color:"#ef4444"},{code:"tournament",name:"Tournoi",description:"Session compétitive multijoueur avec classements et prix. Affrontez d'autres joueurs en temps réel pour des positions au classement et des récompenses.",color:"#f59e0b"},{code:"review",name:"Révision",description:"Session pour revoir les questions précédemment répondues et les erreurs. Pratique ciblée sur les domaines nécessitant une amélioration basée sur les performances passées.",color:"#6b7280"},{code:"diagnostic",name:"Diagnostic",description:"Évaluation initiale pour identifier les lacunes de connaissances et les niveaux de compétences. Évaluation complète pour créer un parcours d'apprentissage personnalisé.",color:"#06b6d4"},{code:"speed_test",name:"Test de Vitesse",description:"Questions rapides sous pression temporelle axées sur la vitesse et la précision. Développe la pensée rapide et les compétences de prise de décision sous contraintes de temps.",color:"#ec4899"}],c=[{code:"training",name:"Antrenament",description:"Sesiune de învățare cu explicații detaliate și experiență ghidată. Perfect pentru dobândirea de cunoștințe noi și înțelegerea conceptelor complexe pas cu pas.",color:"#3b82f6"},{code:"practice",name:"Practică",description:"Sesiune de consolidare pentru solidificarea cunoștințelor deja învățate. Ajută la consolidarea înțelegerii prin repetiție și aplicarea conceptelor învățate.",color:"#10b981"},{code:"simulation",name:"Simulare",description:"Mediu de testare simulat care reproduce condițiile reale de examen. Oferă o experiență de practică realistă cu timp și presiune autentice.",color:"#f59e0b"},{code:"quiz",name:"Quiz",description:"Verificare rapidă a cunoștințelor cu feedback imediat. Sesiuni scurte și focalizate pentru a evalua înțelegerea actuală și a identifica domeniile de îmbunătățit.",color:"#8b5cf6"},{code:"challenge",name:"Provocare",description:"Întrebări competitive sau dificile concepute pentru a testa limitele. Sesiuni avansate care îți împing limitele cunoștințelor și abilitățile de gândire critică.",color:"#ef4444"},{code:"tournament",name:"Turneu",description:"Sesiune competitivă multiplayer cu clasamente și premii. Concurează cu alți jucători în timp real pentru poziții în clasament și recompense.",color:"#f59e0b"},{code:"review",name:"Recapitulare",description:"Sesiune pentru revizuirea întrebărilor răspunse anterior și greșelilor. Practică focalizată pe domeniile care necesită îmbunătățire pe baza performanțelor anterioare.",color:"#6b7280"},{code:"diagnostic",name:"Diagnostic",description:"Evaluare inițială pentru identificarea lacunelor de cunoștințe și nivelurilor de competențe. Evaluare cuprinzătoare pentru crearea unei căi de învățare personalizate.",color:"#06b6d4"},{code:"speed_test",name:"Test de Viteză",description:"Întrebări rapide sub presiunea timpului, axate pe viteză și acuratețe. Dezvoltă gândirea rapidă și abilitățile de luare a deciziilor sub constrângeri de timp.",color:"#ec4899"}];export{c as SESSION_TYPES_RO,t as SESSION_TYPES_FR,s as SESSION_TYPES_EN,n as ESessionType,o as EAnswerState};
2
+
3
+ //# debugId=5E9540D7660497F164756E2164756E21
@@ -0,0 +1,11 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["src/types.ts", "src/constants.ts"],
4
+ "sourcesContent": [
5
+ "import type { IBase } from \"@ooneex/types\";\n\nexport interface ILevel extends IBase {\n name: string;\n code: string;\n color: string;\n}\n\nexport enum ESessionType {\n /** Learning-focused session with detailed explanations and guided experience */\n TRAINING = \"training\",\n /** Reinforcement session for solidifying already learned knowledge */\n PRACTICE = \"practice\",\n /** Mock test environment simulating real exam conditions */\n SIMULATION = \"simulation\",\n /** Quick knowledge check with immediate feedback */\n QUIZ = \"quiz\",\n /** Competitive or difficult questions designed to test limits */\n CHALLENGE = \"challenge\",\n /** Multiplayer competitive session with rankings and prizes */\n TOURNAMENT = \"tournament\",\n /** Session for revisiting previously answered questions and mistakes */\n REVIEW = \"review\",\n /** Initial assessment to identify knowledge gaps and skill levels */\n DIAGNOSTIC = \"diagnostic\",\n /** Time-pressured rapid-fire questions focusing on speed and accuracy */\n SPEED_TEST = \"speed_test\",\n}\n\nexport enum EAnswerState {\n CORRECT = \"correct\",\n INCORRECT = \"incorrect\",\n}\n",
6
+ "import { ESessionType } from \"./types\";\n\ntype SessionTypeItem = {\n readonly code: ESessionType;\n readonly name: string;\n readonly description: string;\n readonly color: string;\n};\n\nexport const SESSION_TYPES_EN: readonly SessionTypeItem[] = [\n {\n code: ESessionType.TRAINING,\n name: \"Training\",\n description:\n \"Learning-focused session with detailed explanations and guided experience. Perfect for acquiring new knowledge and understanding complex concepts step by step.\",\n color: \"#3b82f6\",\n },\n {\n code: ESessionType.PRACTICE,\n name: \"Practice\",\n description:\n \"Reinforcement session for solidifying already learned knowledge. Helps strengthen understanding through repetition and application of learned concepts.\",\n color: \"#10b981\",\n },\n {\n code: ESessionType.SIMULATION,\n name: \"Simulation\",\n description:\n \"Mock test environment simulating real exam conditions. Provides realistic practice experience with authentic timing and pressure conditions.\",\n color: \"#f59e0b\",\n },\n {\n code: ESessionType.QUIZ,\n name: \"Quiz\",\n description:\n \"Quick knowledge check with immediate feedback. Short and focused sessions to assess current understanding and identify areas for improvement.\",\n color: \"#8b5cf6\",\n },\n {\n code: ESessionType.CHALLENGE,\n name: \"Challenge\",\n description:\n \"Competitive or difficult questions designed to test limits. Advanced sessions that push your knowledge boundaries and critical thinking skills.\",\n color: \"#ef4444\",\n },\n {\n code: ESessionType.TOURNAMENT,\n name: \"Tournament\",\n description:\n \"Multiplayer competitive session with rankings and prizes. Compete against other players in real-time for leaderboard positions and rewards.\",\n color: \"#f59e0b\",\n },\n {\n code: ESessionType.REVIEW,\n name: \"Review\",\n description:\n \"Session for revisiting previously answered questions and mistakes. Focused practice on areas where improvement is needed based on past performance.\",\n color: \"#6b7280\",\n },\n {\n code: ESessionType.DIAGNOSTIC,\n name: \"Diagnostic\",\n description:\n \"Initial assessment to identify knowledge gaps and skill levels. Comprehensive evaluation to create a personalized learning path.\",\n color: \"#06b6d4\",\n },\n {\n code: ESessionType.SPEED_TEST,\n name: \"Speed Test\",\n description:\n \"Time-pressured rapid-fire questions focusing on speed and accuracy. Develops quick thinking and decision-making skills under time constraints.\",\n color: \"#ec4899\",\n },\n] as const;\n\nexport const SESSION_TYPES_FR: readonly SessionTypeItem[] = [\n {\n code: ESessionType.TRAINING,\n name: \"Formation\",\n description:\n \"Session d'apprentissage avec explications détaillées et expérience guidée. Parfait pour acquérir de nouvelles connaissances et comprendre des concepts complexes étape par étape.\",\n color: \"#3b82f6\",\n },\n {\n code: ESessionType.PRACTICE,\n name: \"Pratique\",\n description:\n \"Session de renforcement pour consolider les connaissances déjà apprises. Aide à renforcer la compréhension par la répétition et l'application des concepts appris.\",\n color: \"#10b981\",\n },\n {\n code: ESessionType.SIMULATION,\n name: \"Simulation\",\n description:\n \"Environnement d'examen simulé reproduisant les conditions réelles d'examen. Offre une expérience de pratique réaliste avec un timing et une pression authentiques.\",\n color: \"#f59e0b\",\n },\n {\n code: ESessionType.QUIZ,\n name: \"Quiz\",\n description:\n \"Contrôle rapide des connaissances avec feedback immédiat. Sessions courtes et ciblées pour évaluer la compréhension actuelle et identifier les domaines à améliorer.\",\n color: \"#8b5cf6\",\n },\n {\n code: ESessionType.CHALLENGE,\n name: \"Défi\",\n description:\n \"Questions compétitives ou difficiles conçues pour tester les limites. Sessions avancées qui repoussent vos limites de connaissances et vos compétences de pensée critique.\",\n color: \"#ef4444\",\n },\n {\n code: ESessionType.TOURNAMENT,\n name: \"Tournoi\",\n description:\n \"Session compétitive multijoueur avec classements et prix. Affrontez d'autres joueurs en temps réel pour des positions au classement et des récompenses.\",\n color: \"#f59e0b\",\n },\n {\n code: ESessionType.REVIEW,\n name: \"Révision\",\n description:\n \"Session pour revoir les questions précédemment répondues et les erreurs. Pratique ciblée sur les domaines nécessitant une amélioration basée sur les performances passées.\",\n color: \"#6b7280\",\n },\n {\n code: ESessionType.DIAGNOSTIC,\n name: \"Diagnostic\",\n description:\n \"Évaluation initiale pour identifier les lacunes de connaissances et les niveaux de compétences. Évaluation complète pour créer un parcours d'apprentissage personnalisé.\",\n color: \"#06b6d4\",\n },\n {\n code: ESessionType.SPEED_TEST,\n name: \"Test de Vitesse\",\n description:\n \"Questions rapides sous pression temporelle axées sur la vitesse et la précision. Développe la pensée rapide et les compétences de prise de décision sous contraintes de temps.\",\n color: \"#ec4899\",\n },\n] as const;\n\nexport const SESSION_TYPES_RO: readonly SessionTypeItem[] = [\n {\n code: ESessionType.TRAINING,\n name: \"Antrenament\",\n description:\n \"Sesiune de învățare cu explicații detaliate și experiență ghidată. Perfect pentru dobândirea de cunoștințe noi și înțelegerea conceptelor complexe pas cu pas.\",\n color: \"#3b82f6\",\n },\n {\n code: ESessionType.PRACTICE,\n name: \"Practică\",\n description:\n \"Sesiune de consolidare pentru solidificarea cunoștințelor deja învățate. Ajută la consolidarea înțelegerii prin repetiție și aplicarea conceptelor învățate.\",\n color: \"#10b981\",\n },\n {\n code: ESessionType.SIMULATION,\n name: \"Simulare\",\n description:\n \"Mediu de testare simulat care reproduce condițiile reale de examen. Oferă o experiență de practică realistă cu timp și presiune autentice.\",\n color: \"#f59e0b\",\n },\n {\n code: ESessionType.QUIZ,\n name: \"Quiz\",\n description:\n \"Verificare rapidă a cunoștințelor cu feedback imediat. Sesiuni scurte și focalizate pentru a evalua înțelegerea actuală și a identifica domeniile de îmbunătățit.\",\n color: \"#8b5cf6\",\n },\n {\n code: ESessionType.CHALLENGE,\n name: \"Provocare\",\n description:\n \"Întrebări competitive sau dificile concepute pentru a testa limitele. Sesiuni avansate care îți împing limitele cunoștințelor și abilitățile de gândire critică.\",\n color: \"#ef4444\",\n },\n {\n code: ESessionType.TOURNAMENT,\n name: \"Turneu\",\n description:\n \"Sesiune competitivă multiplayer cu clasamente și premii. Concurează cu alți jucători în timp real pentru poziții în clasament și recompense.\",\n color: \"#f59e0b\",\n },\n {\n code: ESessionType.REVIEW,\n name: \"Recapitulare\",\n description:\n \"Sesiune pentru revizuirea întrebărilor răspunse anterior și greșelilor. Practică focalizată pe domeniile care necesită îmbunătățire pe baza performanțelor anterioare.\",\n color: \"#6b7280\",\n },\n {\n code: ESessionType.DIAGNOSTIC,\n name: \"Diagnostic\",\n description:\n \"Evaluare inițială pentru identificarea lacunelor de cunoștințe și nivelurilor de competențe. Evaluare cuprinzătoare pentru crearea unei căi de învățare personalizate.\",\n color: \"#06b6d4\",\n },\n {\n code: ESessionType.SPEED_TEST,\n name: \"Test de Viteză\",\n description:\n \"Întrebări rapide sub presiunea timpului, axate pe viteză și acuratețe. Dezvoltă gândirea rapidă și abilitățile de luare a deciziilor sub constrângeri de timp.\",\n color: \"#ec4899\",\n },\n] as const;\n"
7
+ ],
8
+ "mappings": "AAQO,IAAK,GAAL,CAAK,IAAL,CAEL,WAAW,WAEX,WAAW,WAEX,aAAa,aAEb,OAAO,OAEP,YAAY,YAEZ,aAAa,aAEb,SAAS,SAET,aAAa,aAEb,aAAa,eAlBH,QAqBL,IAAK,GAAL,CAAK,IAAL,CACL,UAAU,UACV,YAAY,cAFF,QCpBL,IAAM,EAA+C,CAC1D,CACE,gBACA,KAAM,WACN,YACE,kKACF,MAAO,SACT,EACA,CACE,gBACA,KAAM,WACN,YACE,0JACF,MAAO,SACT,EACA,CACE,kBACA,KAAM,aACN,YACE,+IACF,MAAO,SACT,EACA,CACE,YACA,KAAM,OACN,YACE,gJACF,MAAO,SACT,EACA,CACE,iBACA,KAAM,YACN,YACE,kJACF,MAAO,SACT,EACA,CACE,kBACA,KAAM,aACN,YACE,8IACF,MAAO,SACT,EACA,CACE,cACA,KAAM,SACN,YACE,sJACF,MAAO,SACT,EACA,CACE,kBACA,KAAM,aACN,YACE,mIACF,MAAO,SACT,EACA,CACE,kBACA,KAAM,aACN,YACE,iJACF,MAAO,SACT,CACF,EAEa,EAA+C,CAC1D,CACE,gBACA,KAAM,YACN,YACE,oLACF,MAAO,SACT,EACA,CACE,gBACA,KAAM,WACN,YACE,qKACF,MAAO,SACT,EACA,CACE,kBACA,KAAM,aACN,YACE,qKACF,MAAO,SACT,EACA,CACE,YACA,KAAM,OACN,YACE,uKACF,MAAO,SACT,EACA,CACE,iBACA,KAAM,OACN,YACE,6KACF,MAAO,SACT,EACA,CACE,kBACA,KAAM,UACN,YACE,0JACF,MAAO,SACT,EACA,CACE,cACA,KAAM,WACN,YACE,6KACF,MAAO,SACT,EACA,CACE,kBACA,KAAM,aACN,YACE,2KACF,MAAO,SACT,EACA,CACE,kBACA,KAAM,kBACN,YACE,iLACF,MAAO,SACT,CACF,EAEa,EAA+C,CAC1D,CACE,gBACA,KAAM,cACN,YACE,iKACF,MAAO,SACT,EACA,CACE,gBACA,KAAM,WACN,YACE,+JACF,MAAO,SACT,EACA,CACE,kBACA,KAAM,WACN,YACE,6IACF,MAAO,SACT,EACA,CACE,YACA,KAAM,OACN,YACE,oKACF,MAAO,SACT,EACA,CACE,iBACA,KAAM,YACN,YACE,mKACF,MAAO,SACT,EACA,CACE,kBACA,KAAM,SACN,YACE,+IACF,MAAO,SACT,EACA,CACE,cACA,KAAM,eACN,YACE,yKACF,MAAO,SACT,EACA,CACE,kBACA,KAAM,aACN,YACE,yKACF,MAAO,SACT,EACA,CACE,kBACA,KAAM,iBACN,YACE,iKACF,MAAO,SACT,CACF",
9
+ "debugId": "5E9540D7660497F164756E2164756E21",
10
+ "names": []
11
+ }
@@ -0,0 +1,98 @@
1
+ import { IImage } from "@ooneex/image";
2
+ import { IStatus } from "@ooneex/status";
3
+ import { ITag } from "@ooneex/tag";
4
+ import { IBase as IBase2, IStat } from "@ooneex/types";
5
+ import { IBase } from "@ooneex/types";
6
+ interface ILevel extends IBase {
7
+ name: string;
8
+ code: string;
9
+ color: string;
10
+ }
11
+ declare enum ESessionType {
12
+ /** Learning-focused session with detailed explanations and guided experience */
13
+ TRAINING = "training",
14
+ /** Reinforcement session for solidifying already learned knowledge */
15
+ PRACTICE = "practice",
16
+ /** Mock test environment simulating real exam conditions */
17
+ SIMULATION = "simulation",
18
+ /** Quick knowledge check with immediate feedback */
19
+ QUIZ = "quiz",
20
+ /** Competitive or difficult questions designed to test limits */
21
+ CHALLENGE = "challenge",
22
+ /** Multiplayer competitive session with rankings and prizes */
23
+ TOURNAMENT = "tournament",
24
+ /** Session for revisiting previously answered questions and mistakes */
25
+ REVIEW = "review",
26
+ /** Initial assessment to identify knowledge gaps and skill levels */
27
+ DIAGNOSTIC = "diagnostic",
28
+ /** Time-pressured rapid-fire questions focusing on speed and accuracy */
29
+ SPEED_TEST = "speed_test"
30
+ }
31
+ declare enum EAnswerState {
32
+ CORRECT = "correct",
33
+ INCORRECT = "incorrect"
34
+ }
35
+ declare enum EMcqQuestionChoiceLetter {
36
+ A = "A",
37
+ B = "B",
38
+ C = "C",
39
+ D = "D",
40
+ E = "E",
41
+ F = "F",
42
+ G = "G",
43
+ H = "H",
44
+ I = "I",
45
+ J = "J"
46
+ }
47
+ declare enum EMcqSessionStatus {
48
+ DRAFT = "draft",
49
+ STARTED = "started",
50
+ PAUSED = "paused",
51
+ COMPLETED = "completed"
52
+ }
53
+ interface IMcqQuestionChoice extends IBase2 {
54
+ letter: EMcqQuestionChoiceLetter;
55
+ text: string;
56
+ isCorrect: boolean;
57
+ explanation?: string;
58
+ question: IMcqQuestion;
59
+ }
60
+ interface IMcqQuestion extends IBase2 {
61
+ questionNumber: number;
62
+ text: string;
63
+ choices: IMcqQuestionChoice[];
64
+ context?: string;
65
+ contextId?: string;
66
+ stat?: IStat;
67
+ status?: IStatus;
68
+ image?: IImage;
69
+ tags?: ITag[];
70
+ }
71
+ interface IMcqSession extends IBase2 {
72
+ name: string;
73
+ totalQuestions: number;
74
+ answeredCount: number;
75
+ correctCount: number;
76
+ incorrectCount: number;
77
+ timing: number;
78
+ questions: IMcqQuestion[];
79
+ status: EMcqSessionStatus;
80
+ score: number;
81
+ startedAt?: Date | null;
82
+ pausedAt?: Date | null;
83
+ resumedAt?: Date | null;
84
+ completedAt?: Date | null;
85
+ type: ESessionType;
86
+ level: ILevel;
87
+ }
88
+ interface IMcqSessionQuestion extends IBase2 {
89
+ session: IMcqSession;
90
+ question: IMcqQuestion;
91
+ questionNumber: number;
92
+ selectedChoices: IMcqQuestionChoice[];
93
+ context?: string;
94
+ contextId?: string;
95
+ state: EAnswerState;
96
+ score: number;
97
+ }
98
+ export { IMcqSessionQuestion, IMcqSession, IMcqQuestionChoice, IMcqQuestion, EMcqSessionStatus, EMcqQuestionChoiceLetter };
@@ -0,0 +1,3 @@
1
+ var n;((e)=>{e.A="A";e.B="B";e.C="C";e.D="D";e.E="E";e.F="F";e.G="G";e.H="H";e.I="I";e.J="J"})(n||={});var s;((t)=>{t.DRAFT="draft";t.STARTED="started";t.PAUSED="paused";t.COMPLETED="completed"})(s||={});export{s as EMcqSessionStatus,n as EMcqQuestionChoiceLetter};
2
+
3
+ //# debugId=EA8EAD6A5D8BC75D64756E2164756E21
@@ -0,0 +1,10 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["src/mcq/types.ts"],
4
+ "sourcesContent": [
5
+ "import type { IImage } from \"@ooneex/image\";\nimport type { IStatus } from \"@ooneex/status\";\nimport type { ITag } from \"@ooneex/tag\";\nimport type { IBase, IStat } from \"@ooneex/types\";\nimport type { EAnswerState, ESessionType, ILevel } from \"@/types\";\n\nexport enum EMcqQuestionChoiceLetter {\n A = \"A\",\n B = \"B\",\n C = \"C\",\n D = \"D\",\n E = \"E\",\n F = \"F\",\n G = \"G\",\n H = \"H\",\n I = \"I\",\n J = \"J\",\n}\n\nexport enum EMcqSessionStatus {\n DRAFT = \"draft\",\n STARTED = \"started\",\n PAUSED = \"paused\",\n COMPLETED = \"completed\",\n}\n\nexport interface IMcqQuestionChoice extends IBase {\n letter: EMcqQuestionChoiceLetter;\n text: string;\n isCorrect: boolean;\n explanation?: string;\n question: IMcqQuestion;\n}\n\nexport interface IMcqQuestion extends IBase {\n questionNumber: number;\n text: string;\n choices: IMcqQuestionChoice[];\n context?: string;\n contextId?: string;\n stat?: IStat;\n status?: IStatus;\n image?: IImage;\n tags?: ITag[];\n}\n\nexport interface IMcqSession extends IBase {\n name: string;\n totalQuestions: number;\n answeredCount: number;\n correctCount: number;\n incorrectCount: number;\n timing: number;\n questions: IMcqQuestion[];\n status: EMcqSessionStatus;\n score: number;\n startedAt?: Date | null;\n pausedAt?: Date | null;\n resumedAt?: Date | null;\n completedAt?: Date | null;\n type: ESessionType;\n level: ILevel;\n}\n\nexport interface IMcqSessionQuestion extends IBase {\n session: IMcqSession;\n question: IMcqQuestion;\n questionNumber: number;\n selectedChoices: IMcqQuestionChoice[];\n context?: string;\n contextId?: string;\n state: EAnswerState;\n score: number;\n}\n"
6
+ ],
7
+ "mappings": "AAMO,IAAK,GAAL,CAAK,IAAL,CACL,IAAI,IACJ,IAAI,IACJ,IAAI,IACJ,IAAI,IACJ,IAAI,IACJ,IAAI,IACJ,IAAI,IACJ,IAAI,IACJ,IAAI,IACJ,IAAI,MAVM,QAaL,IAAK,GAAL,CAAK,IAAL,CACL,QAAQ,QACR,UAAU,UACV,SAAS,SACT,YAAY,cAJF",
8
+ "debugId": "EA8EAD6A5D8BC75D64756E2164756E21",
9
+ "names": []
10
+ }
package/package.json ADDED
@@ -0,0 +1,51 @@
1
+ {
2
+ "name": "@ooneex/gamification",
3
+ "description": "",
4
+ "version": "0.0.1",
5
+ "type": "module",
6
+ "files": [
7
+ "dist",
8
+ "LICENSE",
9
+ "README.md",
10
+ "package.json"
11
+ ],
12
+ "module": "./dist/index.js",
13
+ "types": "./dist/index.d.ts",
14
+ "exports": {
15
+ ".": {
16
+ "import": {
17
+ "types": "./dist/index.d.ts",
18
+ "default": "./dist/index.js"
19
+ }
20
+ },
21
+ "./mcq": {
22
+ "import": {
23
+ "types": "./dist/mcq/index.d.ts",
24
+ "default": "./dist/mcq/index.js"
25
+ }
26
+ },
27
+ "./flashcard": {
28
+ "import": {
29
+ "types": "./dist/flashcard/index.d.ts",
30
+ "default": "./dist/flashcard/index.js"
31
+ }
32
+ },
33
+ "./package.json": "./package.json"
34
+ },
35
+ "license": "MIT",
36
+ "scripts": {
37
+ "build": "bunup",
38
+ "lint": "tsgo --noEmit && bunx biome lint",
39
+ "publish:prod": "bun publish --tolerate-republish --access public",
40
+ "publish:pack": "bun pm pack --destination ./dist",
41
+ "publish:dry": "bun publish --dry-run"
42
+ },
43
+ "dependencies": {},
44
+ "devDependencies": {
45
+ "@ooneex/image": "0.0.1",
46
+ "@ooneex/status": "0.0.1",
47
+ "@ooneex/tag": "0.0.1",
48
+ "@ooneex/types": "0.0.1"
49
+ },
50
+ "peerDependencies": {}
51
+ }