Source: https://super-memory.com/english/ol/sm2.htm
Each card (flashcard item) tracks three values:
- n — repetition number (count of successful reviews, starts at 0)
- EF — easiness factor (starts at 2.5, minimum 1.3)
- I — current interval in days (time until next review)
``` I(1) = 1 # after first successful review: 1 day I(2) = 6 # after second successful review: 6 days I(n) = I(n-1) * EF # for n > 2: multiply previous interval by EF ```
Fractional intervals are rounded up to the nearest integer day.
| Grade | Meaning | |-------|---------| | 5 | Perfect response — no hesitation | | 4 | Correct after hesitation | | 3 | Correct with serious difficulty | | 2 | Incorrect — correct answer seemed easy to recall after seeing it | | 1 | Incorrect — correct answer remembered after seeing it | | 0 | Complete blackout — no recollection |
After each review: ``` EF' = EF + (0.1 - (5 - q) * (0.08 + (5 - q) * 0.02)) ```
Where q is the quality grade (0–5). Results at each grade:
- q=5: EF increases by +0.10
- q=4: EF unchanged (delta = 0)
- q=3: EF decreases by -0.14
- q=2: EF decreases by -0.32
- q=1: EF decreases by -0.54
- q=0: EF decreases by -0.80
EF is clamped to minimum 1.3. Items with EF below 1.3 were found to be "annoyingly often repeated" and indicate a poorly-formed question.
When a review scores 0, 1, or 2: - Reset repetition counter to n=1 (restart interval sequence: 1 day, then 6 days) - Do NOT change the EF (keep accumulated EF to influence future spacing) - Re-show the card the same session until it scores >= 4
Within a single study session: - All items scoring < 4 are re-shown in the same session - Session continues until all shown items score >= 4 - New intervals only schedule for the NEXT day's review (not within-session repetitions)
```typescript interface CardProgress { cardId: string; repetitionNumber: number; // n (0 = never studied) easinessFactor: number; // EF (default 2.5, min 1.3) intervalDays: number; // I (days until next review) nextReviewDate: string; // ISO date string lastReviewDate: string | null; totalReviews: number; correctReviews: number; } ```
```typescript function scheduleNextReview(card: CardProgress, quality: number): CardProgress { let { n, EF, I } = card;
if (quality < 3) { // Failed: reset sequence but keep EF n = 0; I = 1; } else { // Successful: advance sequence if (n === 0) I = 1; else if (n === 1) I = 6; else I = Math.ceil(I * EF); n += 1; }
// Update EF (clamp to 1.3 minimum) EF = Math.max(1.3, EF + 0.1 - (5 - quality) * (0.08 + (5 - quality) * 0.02));
const nextDate = addDays(today(), I); return { ...card, n, EF, I, nextReviewDate: nextDate }; } ```
Cram mode ignores all SM-2 scheduling — it simply shows all cards in a subject (or selected subset) sequentially or randomly, without affecting the SM-2 state. Two approaches:
Each subject is a separate "deck" but SM-2 state is unified per-card. Recommended approach:
nextReviewDate <= todayRecommended: Use a simplified 3-button rating instead of the full 0-5 scale (less cognitive load for mobile):
| Button | Label | Maps to SM-2 Grade | |--------|-------|--------------------| | Again | Didn't know it | 1 | | Hard | Knew it with difficulty | 3 | | Good | Knew it well | 4 | | Easy | Perfect recall | 5 |
This is the same simplification Anki uses. The 4-button approach covers all meaningful SM-2 branches: - "Again" → reset (q=1) - "Hard" → decrease EF significantly (q=3) - "Good" → keep EF stable (q=4) - "Easy" → increase EF (q=5)