code icon Code

Update Review Results

Update deck cards with review results and new SRS intervals

Source Code

import { readFileSync, writeFileSync, existsSync } from "fs";

const [resultsPath, decksPath] = process.argv.slice(2);

try {
  // Read review results
  if (!existsSync(resultsPath)) {
    console.log(
      JSON.stringify({
        success: false,
        error: "No review results found",
      })
    );
    process.exit(1);
  }

  const resultsData = JSON.parse(readFileSync(resultsPath, "utf-8"));
  const { results } = resultsData;

  if (!results || !Array.isArray(results) || results.length === 0) {
    console.log(
      JSON.stringify({
        success: true,
        updated: 0,
        message: "No results to process",
      })
    );
    process.exit(0);
  }

  // Load decks
  if (!existsSync(decksPath)) {
    console.log(
      JSON.stringify({
        success: false,
        error: "Decks file not found",
      })
    );
    process.exit(1);
  }

  const decksData = JSON.parse(readFileSync(decksPath, "utf-8"));
  const today = new Date().toISOString().split("T")[0];

  let correctCount = 0;
  let incorrectCount = 0;
  let updatedCount = 0;

  // Process each result
  for (const result of results) {
    const { cardId, deckSlug, correct } = result;

    if (!decksData.decks[deckSlug]) continue;

    const cardIndex = decksData.decks[deckSlug].cards.findIndex(
      (c) => c.id === cardId
    );
    if (cardIndex === -1) continue;

    const card = decksData.decks[deckSlug].cards[cardIndex];

    // Update card based on result
    card.lastReviewed = today;

    if (correct) {
      // Double the interval on correct
      card.interval = Math.min(card.interval * 2, 365); // Cap at 1 year
      card.correctCount += 1;
      correctCount += 1;
    } else {
      // Reset interval on incorrect
      card.interval = 1;
      card.incorrectCount += 1;
      incorrectCount += 1;
    }

    // Calculate next review date
    const nextDate = new Date();
    nextDate.setDate(nextDate.getDate() + card.interval);
    card.nextReview = nextDate.toISOString().split("T")[0];

    updatedCount += 1;
  }

  // Save updated decks
  writeFileSync(decksPath, JSON.stringify(decksData, null, 2));

  console.log(
    JSON.stringify({
      success: true,
      updated: updatedCount,
      correct: correctCount,
      incorrect: incorrectCount,
      message: `Updated ${updatedCount} cards: ${correctCount} correct, ${incorrectCount} to review again`,
    })
  );
} catch (error) {
  console.log(
    JSON.stringify({
      success: false,
      error: `Failed to update results: ${error.message}`,
    })
  );
  process.exit(1);
}