101 lines
3.6 KiB
TypeScript
101 lines
3.6 KiB
TypeScript
import { sqliteTable, text, integer, real } from "drizzle-orm/sqlite-core";
|
|
import { sql } from "drizzle-orm";
|
|
|
|
export const courses = sqliteTable("courses", {
|
|
id: text("id").primaryKey(),
|
|
title: text("title").notNull(),
|
|
subject: text("subject").notNull(),
|
|
status: text("status", { enum: ["processing", "ready", "error"] })
|
|
.notNull()
|
|
.default("processing"),
|
|
stage: text("stage", {
|
|
enum: ["parsing_pdfs", "analysing_sources", "building_curriculum", "finalising", "ready", "error"],
|
|
}),
|
|
costAI: real("cost_ai").default(0),
|
|
costAudio: real("cost_audio").default(0),
|
|
auditReport: text("audit_report"),
|
|
auditScore: integer("audit_score"),
|
|
auditStatus: text("audit_status", { enum: ["pending", "running", "complete", "error"] }).default("pending"),
|
|
inferenceWarning: integer("inference_warning", { mode: "boolean" }).default(false),
|
|
organisation: text("organisation"),
|
|
createdAt: text("created_at")
|
|
.notNull()
|
|
.default(sql`(datetime('now'))`),
|
|
});
|
|
|
|
export const uploads = sqliteTable("uploads", {
|
|
id: text("id").primaryKey(),
|
|
courseId: text("course_id")
|
|
.notNull()
|
|
.references(() => courses.id),
|
|
filename: text("filename").notNull(),
|
|
type: text("type", { enum: ["slides", "past_paper", "lab_worksheet"] }).notNull(),
|
|
storedPath: text("stored_path").notNull(),
|
|
extractedText: text("extracted_text"),
|
|
createdAt: text("created_at")
|
|
.notNull()
|
|
.default(sql`(datetime('now'))`),
|
|
});
|
|
|
|
export const topics = sqliteTable("topics", {
|
|
id: text("id").primaryKey(),
|
|
courseId: text("course_id")
|
|
.notNull()
|
|
.references(() => courses.id),
|
|
title: text("title").notNull(),
|
|
description: text("description").notNull(),
|
|
order: integer("order").notNull(),
|
|
prerequisiteTopicIds: text("prerequisite_topic_ids").notNull().default("[]"),
|
|
difficulty: integer("difficulty").notNull().default(1),
|
|
relevantFiles: text("relevant_files"),
|
|
status: text("status", { enum: ["pending", "generating", "ready", "error"] }).notNull().default("pending"),
|
|
});
|
|
|
|
export const lessons = sqliteTable("lessons", {
|
|
id: text("id").primaryKey(),
|
|
topicId: text("topic_id")
|
|
.notNull()
|
|
.references(() => topics.id),
|
|
content: text("content").notNull(),
|
|
ttsProvider: text("tts_provider"),
|
|
costAI: real("cost_ai").default(0),
|
|
costAudio: real("cost_audio").default(0),
|
|
costBranchAI: real("cost_branch_ai").default(0),
|
|
costBranchAudio: real("cost_branch_audio").default(0),
|
|
costTotal: real("cost_total").default(0),
|
|
branchStatus: text("branch_status", { enum: ["pending", "generating", "ready", "error"] }).notNull().default("pending"),
|
|
createdAt: text("created_at")
|
|
.notNull()
|
|
.default(sql`(datetime('now'))`),
|
|
});
|
|
|
|
export const quizQuestions = sqliteTable("quiz_questions", {
|
|
id: text("id").primaryKey(),
|
|
topicId: text("topic_id")
|
|
.notNull()
|
|
.references(() => topics.id),
|
|
question: text("question").notNull(),
|
|
type: text("type", { enum: ["mcq", "short_answer", "worked"] }).notNull(),
|
|
options: text("options"),
|
|
answer: text("answer").notNull(),
|
|
explanation: text("explanation").notNull(),
|
|
});
|
|
|
|
export const userProgress = sqliteTable("user_progress", {
|
|
id: text("id").primaryKey(),
|
|
courseId: text("course_id")
|
|
.notNull()
|
|
.references(() => courses.id),
|
|
topicId: text("topic_id")
|
|
.notNull()
|
|
.references(() => topics.id),
|
|
lessonComplete: integer("lesson_complete", { mode: "boolean" })
|
|
.notNull()
|
|
.default(false),
|
|
quizScore: integer("quiz_score"),
|
|
tookBranches: integer("took_branches", { mode: "boolean" }).notNull().default(false),
|
|
branchCount: integer("branch_count").notNull().default(0),
|
|
updatedAt: text("updated_at")
|
|
.notNull()
|
|
.default(sql`(datetime('now'))`),
|
|
});
|