All files / web/src/db/schema euclid-progress.ts

100% Statements 44/44
100% Branches 2/2
100% Functions 1/1
100% Lines 44/44

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 452x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 39x 39x 39x 39x 39x 39x 39x 39x 39x 2x 2x 2x 2x  
import { createId } from '@paralleldrive/cuid2'
import { index, integer, sqliteTable, text, uniqueIndex } from 'drizzle-orm/sqlite-core'
import { players } from './players'
 
/**
 * Euclid Progress
 *
 * Tracks which propositions a player has completed in the Euclid's Elements
 * interactive. One row per (player, proposition) pair.
 */
export const euclidProgress = sqliteTable(
  'euclid_progress',
  {
    id: text('id')
      .primaryKey()
      .$defaultFn(() => createId()),
 
    /** Foreign key to players table */
    playerId: text('player_id')
      .notNull()
      .references(() => players.id, { onDelete: 'cascade' }),
 
    /** Proposition number (1-48) */
    propositionId: integer('proposition_id').notNull(),
 
    /** When the proposition was completed */
    completedAt: integer('completed_at', { mode: 'timestamp' })
      .notNull()
      .$defaultFn(() => new Date()),
  },
  (table) => ({
    /** Index for fast lookups by playerId */
    playerIdx: index('euclid_progress_player_idx').on(table.playerId),
 
    /** Unique constraint: one record per player per proposition */
    playerPropUnique: uniqueIndex('euclid_progress_player_prop_unique').on(
      table.playerId,
      table.propositionId
    ),
  })
)
 
export type EuclidProgress = typeof euclidProgress.$inferSelect
export type NewEuclidProgress = typeof euclidProgress.$inferInsert