import { IImage } from "@ooneex/image"; import { IStatus } from "@ooneex/status"; import { ITag } from "@ooneex/tag"; import { IBase as IBase2, IStat } from "@ooneex/types"; import { IBase } from "@ooneex/types"; interface ILevel extends IBase { name: string; code: string; color: string; } declare enum ESessionType { /** Learning-focused session with detailed explanations and guided experience */ TRAINING = "training", /** Reinforcement session for solidifying already learned knowledge */ PRACTICE = "practice", /** Mock test environment simulating real exam conditions */ SIMULATION = "simulation", /** Quick knowledge check with immediate feedback */ QUIZ = "quiz", /** Competitive or difficult questions designed to test limits */ CHALLENGE = "challenge", /** Multiplayer competitive session with rankings and prizes */ TOURNAMENT = "tournament", /** Session for revisiting previously answered questions and mistakes */ REVIEW = "review", /** Initial assessment to identify knowledge gaps and skill levels */ DIAGNOSTIC = "diagnostic", /** Time-pressured rapid-fire questions focusing on speed and accuracy */ SPEED_TEST = "speed_test" } declare enum EFlashcardState { /** Brand new card that hasn't been studied yet */ NEW = "new", /** Card in learning phase with short intervals */ LEARNING = "learning", /** Card in relearning phase after being forgotten */ RELEARNING = "relearning", /** Graduated card in long-term review cycle */ REVIEW = "review", /** Card temporarily hidden until next day */ BURIED = "buried", /** Card permanently hidden from reviews */ SUSPENDED = "suspended" } declare enum EFlashcardRating { /** Incorrect answer - restart learning */ AGAIN = "again", /** Correct but difficult - shorter interval */ HARD = "hard", /** Correct with some effort - normal interval */ GOOD = "good", /** Correct with no effort - longer interval */ EASY = "easy" } declare enum EFlashcardSessionStatus { DRAFT = "draft", STARTED = "started", PAUSED = "paused", COMPLETED = "completed" } declare enum EFlashcardAlgorithm { /** Legacy SuperMemo 2 algorithm */ SM2 = "sm2", /** Free Spaced Repetition Scheduler (modern) */ FSRS = "fsrs" } interface IFlashcardSchedule extends IBase2 { /** Current state of the card */ state: EFlashcardState; /** Days until next review */ interval: number; /** Ease factor for SM-2 algorithm (2.5 = 250%) */ easeFactor: number; /** Number of times card has been reviewed */ reviewCount: number; /** Number of times card has failed (lapses) */ lapseCount: number; /** Current step in learning/relearning sequence */ currentStep: number; /** When the card is due for review */ dueDate: Date; /** Last time the card was reviewed */ lastReviewedAt?: Date | null; /** FSRS-specific parameters */ difficulty?: number; stability?: number; retrievability?: number; /** Learning steps for this card (in minutes) */ learningSteps: number[]; /** Relearning steps for this card (in minutes) */ relearningSteps: number[]; } interface IFlashcard extends IBase2 { /** Front side content */ front: string; /** Back side content */ back: string; /** Optional hint text */ hint?: string; /** Optional context or source */ context?: string; contextId?: string; /** Scheduling information */ schedule: IFlashcardSchedule; /** Additional metadata */ tags?: ITag[]; stat?: IStat; status?: IStatus; image?: IImage; } interface IFlashcardReview extends IBase2 { /** The flashcard being reviewed */ card: IFlashcard; /** Session this review belongs to */ session: IFlashcardSession; /** User's rating for this review */ rating: EFlashcardRating; /** Time taken to answer (in seconds) */ responseTime: number; /** Previous interval before this review */ previousInterval: number; /** New interval after this review */ newInterval: number; /** Previous ease factor */ previousEaseFactor: number; /** New ease factor */ newEaseFactor: number; /** Previous due date */ previousDueDate: Date; /** New due date */ newDueDate: Date; /** Previous card state */ previousState: EFlashcardState; /** New card state */ newState: EFlashcardState; /** Whether this was a lapse (forgotten card) */ wasLapse: boolean; /** Algorithm used for scheduling */ algorithm: EFlashcardAlgorithm; /** Review timestamp */ reviewedAt: Date; } interface IFlashcardSession extends IBase2 { name: string; /** Total cards available for study */ totalCards: number; /** Number of new cards in session */ newCardsCount: number; /** Number of learning cards in session */ learningCardsCount: number; /** Number of review cards in session */ reviewCardsCount: number; /** Cards studied so far */ studiedCount: number; /** Cards answered correctly */ correctCount: number; /** Cards answered incorrectly */ incorrectCount: number; /** Total study time in seconds */ studyTime: number; /** Cards in this session */ cards: IFlashcard[]; /** Reviews completed in this session */ reviews: IFlashcardReview[]; /** Session status */ status: EFlashcardSessionStatus; /** Overall session score (0-100) */ score: number; /** Session start time */ startedAt?: Date | null; /** Session pause time */ pausedAt?: Date | null; /** Session resume time */ resumedAt?: Date | null; /** Session completion time */ completedAt?: Date | null; /** Type of study session */ type: ESessionType; /** Difficulty level */ level: ILevel; /** Algorithm configuration */ algorithm: EFlashcardAlgorithm; /** Maximum new cards per session */ maxNewCards: number; /** Maximum review cards per session */ maxReviewCards: number; /** Desired retention rate (0-1) for FSRS */ desiredRetention: number; /** Learning steps (in minutes) */ learningSteps: number[]; /** Graduating interval (in days) */ graduatingInterval: number; /** Easy interval (in days) */ easyInterval: number; /** Maximum interval (in days) */ maxInterval: number; } interface IFlashcardDeck extends IBase2 { name: string; description?: string; /** Total cards in deck */ totalCards: number; /** New cards ready to learn */ newCards: number; /** Cards in learning phase */ learningCards: number; /** Cards due for review today */ dueCards: number; /** Cards suspended */ suspendedCards: number; /** All flashcards in this deck */ cards: IFlashcard[]; /** Deck settings */ algorithm: EFlashcardAlgorithm; maxNewCardsPerDay: number; maxReviewCardsPerDay: number; desiredRetention: number; learningSteps: number[]; relearningSteps: number[]; graduatingInterval: number; easyInterval: number; maxInterval: number; /** FSRS parameters (17 parameters) */ fsrsParameters?: number[]; /** Leech threshold (number of lapses before marking as leech) */ leechThreshold: number; /** Whether to bury sibling cards */ burySiblings: boolean; /** Deck statistics */ stat?: IStat; status?: IStatus; } interface IFlashcardPreset extends IBase2 { name: string; description?: string; /** Algorithm to use */ algorithm: EFlashcardAlgorithm; /** Learning configuration */ learningSteps: number[]; relearningSteps: number[]; graduatingInterval: number; easyInterval: number; maxInterval: number; /** Daily limits */ maxNewCardsPerDay: number; maxReviewCardsPerDay: number; /** FSRS configuration */ desiredRetention: number; fsrsParameters?: number[]; /** SM-2 configuration */ startingEaseFactor: number; easyBonus: number; intervalModifier: number; hardInterval: number; newInterval: number; /** Lapse configuration */ minimumInterval: number; leechThreshold: number; /** Display options */ burySiblings: boolean; showTimer: boolean; autoPlayAudio: boolean; } interface IFlashcardStats extends IBase2 { /** Cards studied today */ cardsStudiedToday: number; /** Time spent studying today (minutes) */ timeSpentToday: number; /** Current streak (days) */ currentStreak: number; /** Longest streak (days) */ longestStreak: number; /** Total reviews all time */ totalReviews: number; /** Total study time all time (minutes) */ totalStudyTime: number; /** Average retention rate */ retentionRate: number; /** Breakdown by card state */ newCardsCount: number; learningCardsCount: number; reviewCardsCount: number; suspendedCardsCount: number; /** Maturity statistics */ matureCardsCount: number; youngCardsCount: number; /** Performance by rating */ againCount: number; hardCount: number; goodCount: number; easyCount: number; /** Date range for these stats */ startDate: Date; endDate: Date; } /** * Base interface for spaced repetition algorithms */ interface ISpacedRepetitionAlgorithm { /** * Calculate the next review schedule for a card */ calculateNextReview: (card: IFlashcard, rating: EFlashcardRating, reviewTime: number) => IFlashcardSchedule; /** * Get the predicted intervals for each rating button */ getIntervalPreview: (card: IFlashcard) => Record; /** * Initialize a new card's schedule */ initializeCard: (learningSteps: number[]) => IFlashcardSchedule; /** * Get algorithm-specific parameters */ getParameters: () => Record; /** * Update algorithm parameters */ setParameters: (parameters: Record) => void; } /** * SM-2 (SuperMemo 2) Algorithm Implementation Interface */ interface ISM2Algorithm extends ISpacedRepetitionAlgorithm { /** * SM-2 specific parameters */ getParameters: () => { startingEaseFactor: number; easyBonus: number; intervalModifier: number; hardInterval: number; newInterval: number; minimumInterval: number; maxInterval: number; graduatingInterval: number; easyInterval: number; }; /** * Calculate ease factor adjustment */ calculateEaseAdjustment: (rating: EFlashcardRating, currentEase: number) => number; /** * Calculate interval for review cards */ calculateReviewInterval: (previousInterval: number, easeFactor: number, rating: EFlashcardRating) => number; /** * Handle learning phase transitions */ processLearningCard: (card: IFlashcard, rating: EFlashcardRating, learningSteps: number[]) => { newState: EFlashcardState; interval: number; currentStep: number; }; /** * Handle lapse (forgotten card) */ processLapse: (card: IFlashcard, relearningSteps: number[]) => { newState: EFlashcardState; interval: number; easeFactor: number; currentStep: number; }; } /** * FSRS (Free Spaced Repetition Scheduler) Algorithm Interface */ interface IFSRSAlgorithm extends ISpacedRepetitionAlgorithm { /** * FSRS specific parameters (17 parameters) */ getParameters: () => { parameters: number[]; desiredRetention: number; requestRetention: number; maxInterval: number; }; /** * Calculate memory state (Difficulty, Stability, Retrievability) */ calculateMemoryState: (difficulty: number, stability: number, retrievability: number, rating: EFlashcardRating, deltaT: number) => { newDifficulty: number; newStability: number; newRetrievability: number; }; /** * Calculate retrievability based on time elapsed */ calculateRetrievability: (stability: number, deltaT: number) => number; /** * Calculate next interval based on desired retention */ calculateInterval: (stability: number, desiredRetention: number) => number; /** * Initialize FSRS card state */ initializeFSRSCard: () => { difficulty: number; stability: number; retrievability: number; }; /** * Optimize parameters based on review history */ optimizeParameters: (reviews: IFlashcardReview[]) => number[]; /** * Evaluate parameter quality */ evaluateParameters: (reviews: IFlashcardReview[]) => { logLoss: number; rmse: number; }; } /** * Algorithm factory for creating algorithm instances */ interface IAlgorithmFactory { /** * Create SM-2 algorithm instance */ createSM2Algorithm: (parameters?: Partial) => ISM2Algorithm; /** * Create FSRS algorithm instance */ createFSRSAlgorithm: (parameters?: Partial) => IFSRSAlgorithm; /** * Get default parameters for an algorithm */ getDefaultParameters: (algorithm: "sm2" | "fsrs") => Record; } /** * Algorithm utilities and helpers */ interface IAlgorithmUtils { /** * Apply fuzzing to interval (randomization) */ applyFuzzing: (interval: number, fuzzFactor?: number) => number; /** * Convert learning steps from minutes to intervals */ convertLearningSteps: (steps: number[]) => number[]; /** * Calculate next due date */ calculateDueDate: (interval: number, baseDate?: Date) => Date; /** * Determine if interval should be fuzzed */ shouldApplyFuzzing: (interval: number) => boolean; /** * Clamp interval to valid range */ clampInterval: (interval: number, minInterval: number, maxInterval: number) => number; /** * Calculate average interval for multiple ratings */ calculateAverageInterval: (intervals: number[]) => number; } /** * Review statistics calculator */ interface IReviewStats { /** * Calculate retention rate from reviews */ calculateRetention: (reviews: IFlashcardReview[]) => number; /** * Calculate average response time */ calculateAverageResponseTime: (reviews: IFlashcardReview[]) => number; /** * Get rating distribution */ getRatingDistribution: (reviews: IFlashcardReview[]) => Record; /** * Calculate study load (cards per day) */ calculateStudyLoad: (cards: IFlashcard[]) => { newCards: number; learningCards: number; reviewCards: number; total: number; }; /** * Predict future workload */ predictWorkload: (cards: IFlashcard[], algorithm: ISpacedRepetitionAlgorithm, days: number) => { date: Date; newCards: number; reviews: number; total: number; }[]; } /** * Scheduler for managing card due dates and priorities */ interface ICardScheduler { /** * Get cards due for review */ getDueCards: (cards: IFlashcard[], maxCards?: number) => IFlashcard[]; /** * Get new cards ready for learning */ getNewCards: (cards: IFlashcard[], maxCards?: number) => IFlashcard[]; /** * Get learning cards ready for next step */ getLearningCards: (cards: IFlashcard[]) => IFlashcard[]; /** * Sort cards by priority */ sortCardsByPriority: (cards: IFlashcard[], sortOrder: "due" | "random" | "added") => IFlashcard[]; /** * Check if card is overdue */ isOverdue: (card: IFlashcard) => boolean; /** * Calculate overdue factor */ getOverdueFactor: (card: IFlashcard) => number; /** * Reschedule all cards with new algorithm */ rescheduleCards: (cards: IFlashcard[], algorithm: ISpacedRepetitionAlgorithm) => IFlashcard[]; } /** * Default Anki algorithm constants */ declare const ANKI_DEFAULTS: { readonly LEARNING_STEPS: readonly [1, 10]; readonly GRADUATING_INTERVAL: 1; readonly EASY_INTERVAL: 4; readonly STARTING_EASE_FACTOR: 2.5; readonly EASY_BONUS: 1.3; readonly INTERVAL_MODIFIER: 1.0; readonly HARD_INTERVAL: 1.2; readonly RELEARNING_STEPS: readonly [10]; readonly NEW_INTERVAL: 0.0; readonly MINIMUM_INTERVAL: 1; readonly LEECH_THRESHOLD: 8; readonly MAX_NEW_CARDS_PER_DAY: 20; readonly MAX_REVIEW_CARDS_PER_DAY: 200; readonly MAX_ANSWER_TIME: 60; readonly MIN_INTERVAL: 1; readonly MAX_INTERVAL: 36500; readonly DESIRED_RETENTION: 0.9; 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]; }; /** * Rating multipliers for interval calculation */ declare const RATING_MULTIPLIERS: Record; /** * Ease factor adjustments based on rating */ declare const EASE_ADJUSTMENTS: Record; /** * Minimum and maximum ease factor bounds */ declare const EASE_BOUNDS: { readonly MIN: 1.3; readonly MAX: 2.5; }; /** * Card state transitions based on rating */ declare const STATE_TRANSITIONS: Record>; /** * Learning step multipliers for Hard button */ declare const LEARNING_HARD_MULTIPLIERS: { readonly FIRST_STEP: 1.5; readonly AVERAGE_STEPS: 0.5; }; /** * Fuzz factor for randomizing intervals */ declare const FUZZ_FACTOR: { readonly MIN: 0.95; readonly MAX: 1.05; }; /** * Session scoring weights */ declare const SCORE_WEIGHTS: Record; /** * Card maturity threshold (days) */ declare const MATURITY_THRESHOLD = 21; /** * Default preset configurations */ declare const DEFAULT_PRESETS: { readonly BEGINNER: { readonly name: "Beginner"; readonly description: "For new learners with more repetition"; readonly learningSteps: readonly [1, 10, 1440]; readonly graduatingInterval: 2; readonly easyInterval: 7; readonly maxNewCardsPerDay: 10; readonly desiredRetention: 0.85; }; readonly DEFAULT: { readonly name: "Default"; readonly description: "Balanced settings for most users"; readonly learningSteps: readonly [1, 10]; readonly graduatingInterval: 1; readonly easyInterval: 4; readonly maxNewCardsPerDay: 20; readonly desiredRetention: 0.9; }; readonly INTENSIVE: { readonly name: "Intensive"; readonly description: "For serious learners who want higher retention"; readonly learningSteps: readonly [1, 10]; readonly graduatingInterval: 1; readonly easyInterval: 4; readonly maxNewCardsPerDay: 30; readonly desiredRetention: 0.95; }; readonly LIGHT: { readonly name: "Light"; readonly description: "For casual learning with fewer reviews"; readonly learningSteps: readonly [1, 10]; readonly graduatingInterval: 3; readonly easyInterval: 7; readonly maxNewCardsPerDay: 15; readonly desiredRetention: 0.8; }; }; /** * Algorithm-specific constants */ interface SM2Constants { MIN_EASE_FACTOR: number; MAX_EASE_FACTOR: number; EASE_ADJUSTMENT_STEP: number; } interface FSRSConstants { MIN_DIFFICULTY: number; MAX_DIFFICULTY: number; MIN_STABILITY: number; MAX_STABILITY: number; MIN_RETRIEVABILITY: number; MAX_RETRIEVABILITY: number; } type AlgorithmConstants = { [EFlashcardAlgorithm.SM2]: SM2Constants; [EFlashcardAlgorithm.FSRS]: FSRSConstants; }; declare const ALGORITHM_CONSTANTS: AlgorithmConstants; /** * Utility functions for common calculations */ declare const UTILS: { /** * Convert minutes to milliseconds */ readonly minutesToMs: (minutes: number) => number; /** * Convert days to milliseconds */ readonly daysToMs: (days: number) => number; /** * Apply fuzz factor to interval */ readonly applyFuzz: (interval: number) => number; /** * Clamp ease factor to valid range */ readonly clampEaseFactor: (ease: number) => number; /** * Calculate session score */ readonly calculateScore: (ratings: EFlashcardRating[]) => number; /** * Determine if card is mature */ readonly isMature: (interval: number) => boolean; }; 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 };