soroban-abacus-flashcards/client/node/API.md

6.0 KiB

Soroban Flashcard Generator - Node.js API Documentation

Installation

npm install python-shell

Basic Usage

import { SorobanGenerator } from './soroban-generator-bridge';

const generator = new SorobanGenerator();
const result = await generator.generate({
  range: '0-99',
  cardsPerPage: 6
});

API Reference

SorobanGenerator

The main class for generating flashcards from Node.js/TypeScript.

Constructor

new SorobanGenerator(projectRoot?: string)
  • projectRoot (optional): Path to the soroban-abacus-flashcards directory. Defaults to ../../ from the module location.

Methods

generate(config: FlashcardConfig): Promise<FlashcardResult>

Generate flashcards with the specified configuration.

Parameters:

  • config: Configuration object (see FlashcardConfig below)

Returns: Promise resolving to:

{
  pdf: string;      // Base64 encoded PDF
  count: number;    // Number of flashcards generated
  numbers: number[]; // Array of numbers (limited to first 100)
}
generateBuffer(config: FlashcardConfig): Promise<Buffer>

Generate flashcards and return as Node.js Buffer.

Parameters:

  • config: Configuration object

Returns: Promise resolving to Buffer containing PDF data

initialize(): Promise<void>

Initialize a persistent Python process for better performance when generating multiple PDFs.

close(): Promise<void>

Clean up the persistent Python process.

Configuration Interface

interface FlashcardConfig {
  // Required
  range: string;              // e.g., "0-99" or "1,2,5,10"
  
  // Optional
  step?: number;              // Increment (default: 1)
  cardsPerPage?: number;      // 1-30+ (default: 6)
  paperSize?: 'us-letter' | 'a4' | 'a3' | 'a5';
  orientation?: 'portrait' | 'landscape';
  margins?: {
    top?: string;           // e.g., "0.5in"
    bottom?: string;
    left?: string;
    right?: string;
  };
  gutter?: string;           // Space between cards (default: "5mm")
  shuffle?: boolean;         // Randomize order
  seed?: number;             // Random seed for deterministic shuffle
  showCutMarks?: boolean;    // Show cutting guides
  showRegistration?: boolean; // Show alignment marks
  fontFamily?: string;       // Font name (default: "DejaVu Sans")
  fontSize?: string;         // Font size (default: "48pt")
  columns?: string | number; // "auto" or specific number
  showEmptyColumns?: boolean;
  hideInactiveBeads?: boolean;
  beadShape?: 'diamond' | 'circle' | 'square';
  colorScheme?: 'monochrome' | 'place-value' | 'heaven-earth' | 'alternating';
  coloredNumerals?: boolean; // Color numerals to match beads
  scaleFactor?: number;      // 0.1 to 1.0 (default: 0.9)
}

Examples

Basic Generation

const generator = new SorobanGenerator();

// Simple 0-9 flashcards
const result = await generator.generate({
  range: '0-9'
});

Skip Counting

// Count by 5s from 0 to 100
const result = await generator.generate({
  range: '0-100',
  step: 5,
  cardsPerPage: 12
});

Educational Colors

// Place-value coloring for learning
const result = await generator.generate({
  range: '0-999',
  colorScheme: 'place-value',
  coloredNumerals: true,
  showCutMarks: true
});

Express.js Route

app.post('/api/flashcards', async (req, res) => {
  try {
    const generator = new SorobanGenerator();
    const config = {
      range: req.body.range || '0-9',
      cardsPerPage: req.body.cardsPerPage || 6,
      colorScheme: req.body.colorScheme || 'monochrome',
      ...req.body
    };
    
    const result = await generator.generate(config);
    
    if (req.query.format === 'json') {
      // Return metadata
      res.json({
        count: result.count,
        numbers: result.numbers
      });
    } else {
      // Return PDF
      const pdfBuffer = Buffer.from(result.pdf, 'base64');
      res.contentType('application/pdf');
      res.setHeader('Content-Disposition', 'attachment; filename=flashcards.pdf');
      res.send(pdfBuffer);
    }
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

Next.js API Route

// pages/api/flashcards.ts
import { NextApiRequest, NextApiResponse } from 'next';
import { SorobanGenerator } from '@/lib/soroban-generator-bridge';

export default async function handler(
  req: NextApiRequest,
  res: NextApiResponse
) {
  if (req.method !== 'POST') {
    return res.status(405).json({ error: 'Method not allowed' });
  }

  try {
    const generator = new SorobanGenerator();
    const result = await generator.generate(req.body);
    const pdfBuffer = Buffer.from(result.pdf, 'base64');
    
    res.setHeader('Content-Type', 'application/pdf');
    res.setHeader('Content-Disposition', 'attachment; filename=flashcards.pdf');
    res.send(pdfBuffer);
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
}

Performance Optimization

For generating multiple PDFs, use persistent mode:

const generator = new SorobanGenerator();

// Initialize once
await generator.initialize();

// Generate multiple PDFs quickly
for (const config of configs) {
  const result = await generator.generate(config);
  // Process result...
}

// Clean up when done
await generator.close();

Requirements

  • Node.js 14+
  • Python 3.8+
  • Typst (installed via brew install typst)
  • qpdf (optional, for PDF optimization)

Error Handling

The generator will throw errors for:

  • Missing Python installation
  • Missing Typst installation
  • Invalid configuration
  • Typst compilation errors

Always wrap calls in try/catch blocks:

try {
  const result = await generator.generate(config);
} catch (error) {
  console.error('Generation failed:', error.message);
}

TypeScript Types

All interfaces and types are included in the module. Import them as needed:

import { 
  SorobanGenerator,
  FlashcardConfig,
  FlashcardResult 
} from './soroban-generator-bridge';