Files
wordloop/backend/models.py
T
John 68c5efe573 Add spell practice, memory analytics, auth persistence, and word library UX.
Includes per-word training stats and curves, quiz session auto-save, remember-login,
paginated word list with floating page arrows, and Obsidian-style relationship graph baseline.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-04 14:57:39 -07:00

75 lines
3.0 KiB
Python

from sqlalchemy import Column, ForeignKey, Integer, String, Text
from database import Base
class User(Base):
__tablename__ = "users"
id = Column(Integer, primary_key=True, autoincrement=True)
username = Column(String(50), unique=True, nullable=False, index=True)
password_hash = Column(String(255), nullable=False)
created_at = Column(String(32), nullable=False)
class Word(Base):
__tablename__ = "words"
id = Column(Integer, primary_key=True, autoincrement=True)
user_id = Column(Integer, ForeignKey("users.id"), nullable=False, index=True)
source_text = Column(String(500), nullable=False)
target_text = Column(String(500), nullable=False)
source_lang = Column(String(8), nullable=False)
target_lang = Column(String(8), nullable=False)
phonetic = Column(String(128), nullable=True)
example_en = Column(Text, nullable=True)
example_cn = Column(Text, nullable=True)
status = Column(String(32), nullable=False, default="new")
correct_count = Column(Integer, nullable=False, default=0)
wrong_count = Column(Integer, nullable=False, default=0)
consecutive_correct_count = Column(Integer, nullable=False, default=0)
mastery_score = Column(Integer, nullable=False, default=0)
train_count = Column(Integer, nullable=False, default=0)
total_train_seconds = Column(Integer, nullable=False, default=0)
review_due_date = Column(String(32), nullable=True)
last_reviewed_at = Column(String(32), nullable=True)
created_at = Column(String(32), nullable=False)
class QuizRecord(Base):
__tablename__ = "quiz_records"
id = Column(Integer, primary_key=True, autoincrement=True)
user_id = Column(Integer, ForeignKey("users.id"), nullable=False, index=True)
word_id = Column(Integer, ForeignKey("words.id"), nullable=False)
question_type = Column(String(32), nullable=False)
user_answer = Column(String(500), nullable=False)
correct_answer = Column(String(500), nullable=False)
is_correct = Column(Integer, nullable=False)
duration_seconds = Column(Integer, nullable=False, default=0)
created_at = Column(String(32), nullable=False)
class UserSettings(Base):
__tablename__ = "user_settings"
id = Column(Integer, primary_key=True, autoincrement=True)
user_id = Column(Integer, ForeignKey("users.id"), unique=True, nullable=False)
daily_target = Column(Integer, nullable=False, default=20)
master_required_count = Column(Integer, nullable=False, default=3)
weak_wrong_threshold = Column(Integer, nullable=False, default=3)
class DictionaryEntry(Base):
"""全局离线翻译词典,与用户个人 words 表分离。"""
__tablename__ = "dictionary_entries"
id = Column(Integer, primary_key=True, autoincrement=True)
lemma_en = Column(String(128), unique=True, nullable=False, index=True)
zh = Column(String(256), nullable=False, index=True)
phonetic = Column(String(128), nullable=True)
example_en = Column(Text, nullable=True)
example_cn = Column(Text, nullable=True)
source = Column(String(64), nullable=True)