DeutschLernen/docs/database/initial-database-schema.sql
Lasse Rune Hansen 76e8af4987 Add complete solution: documentation, frontend, and project files
- Add comprehensive documentation in docs/ (architecture, features, roadmap)
- Add german-app-frontend with Vite, TypeScript, ESLint configuration
- Add AGENTS.md and .gitignore

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
2026-05-31 18:20:53 +02:00

242 lines
No EOL
7.1 KiB
SQL

-- Enable UUID extension (optional, but useful for unique IDs)
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
---
--- **1. Users and Authentication**
---
-- Users table
CREATE TABLE Users (
Id SERIAL PRIMARY KEY,
Username VARCHAR(50) UNIQUE NOT NULL,
Email VARCHAR(100) UNIQUE NOT NULL,
PasswordHash VARCHAR(255) NOT NULL,
Role VARCHAR(20) DEFAULT 'user' CHECK (Role IN ('user', 'admin')),
LastLoginAt TIMESTAMP,
CreatedAt TIMESTAMP DEFAULT NOW()
);
---
--- **2. Learning Content: Levels, Lessons, and Dependencies**
---
-- Levels table
CREATE TABLE Levels (
Id SERIAL PRIMARY KEY,
Name VARCHAR(10) UNIQUE NOT NULL, -- e.g., "A1", "A2"
Description TEXT,
Order INT UNIQUE NOT NULL,
IsActive BOOLEAN DEFAULT TRUE
);
-- Lessons table
CREATE TABLE Lessons (
Id SERIAL PRIMARY KEY,
LevelId INT REFERENCES Levels(Id) ON DELETE CASCADE,
Title VARCHAR(100) NOT NULL,
Description TEXT,
Order INT NOT NULL,
EstimatedMinutes INT,
UNIQUE(LevelId, Order)
);
---
--- **3. Vocabulary and Word Details**
---
-- Vocabulary table (core words)
CREATE TABLE Vocabulary (
Id SERIAL PRIMARY KEY,
LessonId INT REFERENCES Lessons(Id) ON DELETE CASCADE,
BaseWord VARCHAR(50) NOT NULL, -- e.g., "gehen", "Buch"
UNIQUE(LessonId, BaseWord)
);
-- WordMetadata table (metadata for vocabulary, e.g., frequency, part of speech)
CREATE TABLE WordMetadata (
Id SERIAL PRIMARY KEY,
VocabularyId INT REFERENCES Vocabulary(Id) ON DELETE CASCADE,
Translation VARCHAR(100) NOT NULL,
WordClass VARCHAR(20) NOT NULL CHECK (WordClass IN ('noun', 'verb', 'adjective', 'adverb', 'preposition', 'conjunction', 'pronoun', 'article', 'other')),
Frequency INT CHECK (Frequency BETWEEN 1 AND 5), -- 1 = rare, 5 = very common
AudioUrl VARCHAR(255) NOT NULL,
ImageUrl VARCHAR(255)
);
-- WordForms table (inflections, plurals, conjugations, etc.)
CREATE TABLE WordForms (
Id SERIAL PRIMARY KEY,
VocabularyId INT REFERENCES Vocabulary(Id) ON DELETE CASCADE,
FormType VARCHAR(20) NOT NULL CHECK (FormType IN ('plural', 'singular', 'infinitive', 'past_tense', 'past_participle', 'present_participle', 'conjugation_ich', 'conjugation_du', 'conjugation_er', 'conjugation_wir', 'conjugation_ihr', 'conjugation_sie', 'dative', 'accusative', 'genitive', 'nominative')),
Form VARCHAR(50) NOT NULL,
Article VARCHAR(10) CHECK (Article IN ('der', 'die', 'das', '')), -- Only for nouns
AudioUrl VARCHAR(255),
UNIQUE(VocabularyId, FormType, Form)
);
---
--- **4. Story Segments**
---
-- StorySegments table
CREATE TABLE StorySegments (
Id SERIAL PRIMARY KEY,
LevelId INT REFERENCES Levels(Id) ON DELETE CASCADE,
LessonId INT REFERENCES Lessons(Id) ON DELETE CASCADE NOT NULL, -- Required
Title VARCHAR(100) NOT NULL,
Content TEXT NOT NULL,
AudioUrl VARCHAR(255) NOT NULL,
Order INT NOT NULL,
IsUnlocked BOOLEAN DEFAULT FALSE, -- Managed by the app logic (unlocked via lesson completion)
UNIQUE(LevelId, Order)
);
---
--- **5. Quizzes and Questions**
---
-- Quizzes table
CREATE TABLE Quizzes (
Id SERIAL PRIMARY KEY,
LessonId INT REFERENCES Lessons(Id) ON DELETE CASCADE,
Title VARCHAR(100) NOT NULL,
Description TEXT,
PassingScore INT DEFAULT 80
);
-- Questions table
CREATE TABLE Questions (
Id SERIAL PRIMARY KEY,
QuizId INT REFERENCES Quizzes(Id) ON DELETE CASCADE,
Type VARCHAR(20) NOT NULL CHECK (Type IN ('mcq', 'fill_in', 'listening', 'matching')),
Content TEXT NOT NULL,
CorrectAnswer TEXT NOT NULL,
AudioUrl VARCHAR(255),
AudioScript TEXT, -- For listening questions: the text of the audio
Explanation TEXT,
Points INT DEFAULT 1,
Difficulty INT CHECK (Difficulty BETWEEN 1 AND 5)
);
-- QuestionOptions table (normalized for MCQ)
CREATE TABLE QuestionOptions (
Id SERIAL PRIMARY KEY,
QuestionId INT REFERENCES Questions(Id) ON DELETE CASCADE,
OptionText TEXT NOT NULL,
Order INT NOT NULL,
UNIQUE(QuestionId, Order)
);
---
--- **6. User Progress and Quiz Attempts**
---
-- UserProgress table
CREATE TABLE UserProgress (
Id SERIAL PRIMARY KEY,
UserId INT REFERENCES Users(Id) ON DELETE CASCADE,
LessonId INT REFERENCES Lessons(Id) ON DELETE CASCADE,
IsCompleted BOOLEAN DEFAULT FALSE,
CurrentLevelId INT REFERENCES Levels(Id), -- Moved from Users
Streak INT DEFAULT 0,
TotalPoints INT DEFAULT 0,
TimeSpentMinutes INT DEFAULT 0,
LastVisitedAt TIMESTAMP DEFAULT NOW(),
UNIQUE(UserId, LessonId)
);
-- QuizAttempts table (tracks all attempts)
CREATE TABLE QuizAttempts (
Id SERIAL PRIMARY KEY,
UserId INT REFERENCES Users(Id) ON DELETE CASCADE,
QuizId INT REFERENCES Quizzes(Id) ON DELETE CASCADE,
Score INT NOT NULL,
TotalPoints INT NOT NULL,
Passed BOOLEAN NOT NULL,
AttemptDate TIMESTAMP DEFAULT NOW(),
TimeSpentSeconds INT
);
---
--- **7. Gamification**
---
-- Badges table
CREATE TABLE Badges (
Id SERIAL PRIMARY KEY,
Name VARCHAR(50) NOT NULL,
Description TEXT,
ImageUrl VARCHAR(255),
PointsRequired INT,
Category VARCHAR(50),
UNIQUE(Name)
);
-- UserBadges table
CREATE TABLE UserBadges (
UserId INT REFERENCES Users(Id) ON DELETE CASCADE,
BadgeId INT REFERENCES Badges(Id) ON DELETE CASCADE,
EarnedDate TIMESTAMP DEFAULT NOW(),
PRIMARY KEY (UserId, BadgeId)
);
---
--- **8. Practice Sessions**
---
-- PracticeSessions table
CREATE TABLE PracticeSessions (
Id SERIAL PRIMARY KEY,
UserId INT REFERENCES Users(Id) ON DELETE CASCADE,
Type VARCHAR(20) NOT NULL CHECK (Type IN ('speaking', 'writing')),
Prompt TEXT NOT NULL,
UserResponse TEXT,
Feedback TEXT,
Score INT,
TimeSpentSeconds INT,
Date TIMESTAMP DEFAULT NOW()
);
---
--- **9. User Settings**
---
-- UserSettings table
CREATE TABLE UserSettings (
UserId INT PRIMARY KEY REFERENCES Users(Id) ON DELETE CASCADE,
AudioAutoplay BOOLEAN DEFAULT TRUE,
Theme VARCHAR(20) DEFAULT 'light' CHECK (Theme IN ('light', 'dark')),
NativeLanguage VARCHAR(50) DEFAULT 'en'
);
---
--- **10. Feedback**
---
-- Feedback table
CREATE TABLE Feedback (
Id SERIAL PRIMARY KEY,
UserId INT REFERENCES Users(Id) ON DELETE CASCADE,
LessonId INT REFERENCES Lessons(Id) ON DELETE SET NULL,
QuizId INT REFERENCES Quizzes(Id) ON DELETE SET NULL,
Rating INT CHECK (Rating BETWEEN 1 AND 5),
Comment TEXT,
CreatedAt TIMESTAMP DEFAULT NOW(),
CHECK (LessonId IS NOT NULL OR QuizId IS NOT NULL)
);
---
--- **11. Indexes for Performance**
---
CREATE INDEX idx_userprogress_userid ON UserProgress(UserId);
CREATE INDEX idx_userprogress_lessonid ON UserProgress(LessonId);
CREATE INDEX idx_vocabulary_lessonid ON Vocabulary(LessonId);
CREATE INDEX idx_wordmetadata_vocabularyid ON WordMetadata(VocabularyId);
CREATE INDEX idx_wordforms_vocabularyid ON WordForms(VocabularyId);
CREATE INDEX idx_questions_quizid ON Questions(QuizId);
CREATE INDEX idx_questionoptions_questionid ON QuestionOptions(QuestionId);
CREATE INDEX idx_quizattempts_userid ON QuizAttempts(UserId);
CREATE INDEX idx_quizattempts_quizid ON QuizAttempts(QuizId);
CREATE INDEX idx_storysegments_levelid ON StorySegments(LevelId);
CREATE INDEX idx_storysegments_lessonid ON StorySegments(LessonId);