French-Coach / db /init.sql
Asma-F's picture
Deploy: French Coach app (MiniCPM4.1-8B ZeroGPU + React frontend)
4fd1234 verified
Raw
History Blame Contribute Delete
2.37 kB
CREATE EXTENSION IF NOT EXISTS "pgcrypto";
CREATE TABLE IF NOT EXISTS pages (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id TEXT NOT NULL,
title TEXT NOT NULL,
date DATE NOT NULL DEFAULT CURRENT_DATE,
raw_text TEXT NOT NULL,
annotations JSONB DEFAULT '{}'::jsonb,
metadata JSONB DEFAULT '{}'::jsonb, -- category, summary, tags (for smart browser)
created_at TIMESTAMPTZ DEFAULT NOW()
);
CREATE INDEX IF NOT EXISTS idx_pages_user ON pages(user_id, created_at DESC);
CREATE INDEX IF NOT EXISTS idx_pages_metadata ON pages USING gin(metadata);
CREATE TABLE IF NOT EXISTS concepts (
id TEXT PRIMARY KEY,
name TEXT NOT NULL,
cefr_level TEXT NOT NULL,
family TEXT NOT NULL,
covered_on DATE
);
CREATE TABLE IF NOT EXISTS exercises (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id TEXT NOT NULL,
page_id UUID REFERENCES pages(id) ON DELETE CASCADE,
kind TEXT NOT NULL,
prompt TEXT,
model_answer TEXT,
content JSONB DEFAULT '{}'::jsonb,
created_at TIMESTAMPTZ DEFAULT NOW()
);
CREATE INDEX IF NOT EXISTS idx_exercises_user ON exercises(user_id, created_at DESC);
-- Append-only participation ledger — never deduct points
CREATE TABLE IF NOT EXISTS points (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id TEXT NOT NULL,
reason TEXT NOT NULL,
amount INT NOT NULL CHECK (amount > 0),
earned_at TIMESTAMPTZ DEFAULT NOW()
);
CREATE INDEX IF NOT EXISTS idx_points_user ON points(user_id, earned_at DESC);
-- Tracks which pre-generated sample images a user has already practiced
-- with, so the matched-image visual exercise (Day 4) doesn't repeat one
-- before cycling through the rest of the set.
CREATE TABLE IF NOT EXISTS user_image_usage (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id TEXT NOT NULL,
image_id TEXT NOT NULL,
used_at TIMESTAMPTZ DEFAULT NOW()
);
CREATE INDEX IF NOT EXISTS idx_user_image_usage ON user_image_usage(user_id, image_id);
-- PRIVATE table (defined here but never written by the public Space)
CREATE TABLE IF NOT EXISTS mistakes (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id TEXT NOT NULL,
concept_id TEXT REFERENCES concepts(id),
category TEXT NOT NULL,
user_answer TEXT,
correct_answer TEXT,
explanation TEXT,
made_on TIMESTAMPTZ DEFAULT NOW()
);