All files / web/src/lib/vision trainingData.ts

79.72% Statements 59/74
100% Branches 0/0
0% Functions 0/2
79.72% Lines 59/74

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 751x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x         1x 1x 1x 1x 1x 1x 1x 1x                        
/**
 * Vision Training Data Collection
 *
 * Utilities for collecting abacus column images for training the column classifier model.
 * Images are saved in the format expected by the training pipeline.
 */
 
/**
 * Request body for the training data collection API
 */
export interface TrainingDataRequest {
  /** Array of column images, one per column (left to right) */
  columns: ColumnImageData[]
  /** The correct answer (validated by the app) */
  correctAnswer: number
  /** Player ID for attribution */
  playerId: string
  /** Session ID for grouping */
  sessionId: string
}
 
/**
 * A single column image with metadata
 */
export interface ColumnImageData {
  /** Column index (0 = leftmost/highest place value) */
  columnIndex: number
  /** Base64-encoded PNG image data (64x128 grayscale) */
  imageData: string
}
 
/**
 * Response from the training data collection API
 */
export interface TrainingDataResponse {
  /** Whether the save was successful */
  success: boolean
  /** Number of column images saved */
  savedCount: number
  /** Error message if any */
  error?: string
}
 
/**
 * Convert a number to an array of digit labels for each column
 *
 * @param value - The number to convert
 * @param columnCount - Number of columns (pads with leading zeros if needed)
 * @returns Array of digits, one per column (leftmost first)
 */
export function valueToDigitLabels(value: number, columnCount: number): number[] {
  const valueStr = Math.abs(value).toString()
  const padded = valueStr.padStart(columnCount, '0')
  return padded.split('').map(Number)
}
 
/**
 * Convert ImageData to a base64-encoded PNG string
 *
 * @param imageData - The ImageData to convert
 * @returns Base64-encoded PNG data URL (without the data:image/png;base64, prefix)
 */
export function imageDataToBase64Png(imageData: ImageData): string {
  const canvas = document.createElement('canvas')
  canvas.width = imageData.width
  canvas.height = imageData.height
  const ctx = canvas.getContext('2d')!
  ctx.putImageData(imageData, 0, 0)

  // Get base64 PNG data
  const dataUrl = canvas.toDataURL('image/png')
  // Remove the "data:image/png;base64," prefix
  return dataUrl.replace(/^data:image\/png;base64,/, '')
}