feat: мини-истории, слово дня, меню практики
- Добавлены мини-истории для чтения с выбором жанра и вопросами - Кнопка показа/скрытия перевода истории - Количество вопросов берётся из настроек пользователя - Слово дня генерируется глобально в 00:00 UTC - Кнопка "Практика" открывает меню выбора режима - Убран автоматический create_all при запуске (только миграции) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -139,3 +139,52 @@ class AIModel(Base):
|
||||
display_name: Mapped[str] = mapped_column(String(100), nullable=False) # Название для отображения
|
||||
is_active: Mapped[bool] = mapped_column(Boolean, default=False) # Только одна модель активна
|
||||
created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow)
|
||||
|
||||
|
||||
class StoryGenre(str, enum.Enum):
|
||||
"""Жанры мини-историй"""
|
||||
dialogue = "dialogue" # 🗣 Диалоги
|
||||
news = "news" # 📰 Новости
|
||||
story = "story" # 🎭 Истории
|
||||
letter = "letter" # 📧 Письма
|
||||
recipe = "recipe" # 🍳 Рецепты
|
||||
|
||||
|
||||
class MiniStory(Base):
|
||||
"""Модель мини-истории для чтения"""
|
||||
__tablename__ = "mini_stories"
|
||||
|
||||
id: Mapped[int] = mapped_column(primary_key=True)
|
||||
user_id: Mapped[int] = mapped_column(Integer, nullable=False, index=True)
|
||||
title: Mapped[str] = mapped_column(String(255), nullable=False)
|
||||
content: Mapped[str] = mapped_column(String(5000), nullable=False) # Текст истории
|
||||
translation: Mapped[Optional[str]] = mapped_column(String(5000), nullable=True) # Перевод истории
|
||||
genre: Mapped[StoryGenre] = mapped_column(SQLEnum(StoryGenre), nullable=False)
|
||||
learning_lang: Mapped[str] = mapped_column(String(5), nullable=False) # en/ja
|
||||
level: Mapped[str] = mapped_column(String(5), nullable=False) # A1-C2 или N5-N1
|
||||
word_count: Mapped[int] = mapped_column(Integer, default=0) # Количество слов
|
||||
vocabulary: Mapped[Optional[dict]] = mapped_column(JSON) # [{word, translation, transcription}]
|
||||
questions: Mapped[Optional[dict]] = mapped_column(JSON) # [{question, options[], correct}]
|
||||
is_completed: Mapped[bool] = mapped_column(Boolean, default=False)
|
||||
correct_answers: Mapped[int] = mapped_column(Integer, default=0)
|
||||
created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow)
|
||||
|
||||
|
||||
class WordOfDay(Base):
|
||||
"""Модель слова дня (глобальная для всех пользователей по уровню)"""
|
||||
__tablename__ = "word_of_day"
|
||||
__table_args__ = (
|
||||
UniqueConstraint("date", "learning_lang", "level", name="uq_wod_date_lang_level"),
|
||||
)
|
||||
|
||||
id: Mapped[int] = mapped_column(primary_key=True)
|
||||
word: Mapped[str] = mapped_column(String(255), nullable=False)
|
||||
transcription: Mapped[Optional[str]] = mapped_column(String(255))
|
||||
translation: Mapped[str] = mapped_column(String(500), nullable=False)
|
||||
examples: Mapped[Optional[dict]] = mapped_column(JSON) # [{sentence, translation}]
|
||||
synonyms: Mapped[Optional[str]] = mapped_column(String(500)) # Синонимы через запятую
|
||||
etymology: Mapped[Optional[str]] = mapped_column(String(500)) # Этимология/интересный факт
|
||||
learning_lang: Mapped[str] = mapped_column(String(5), nullable=False, index=True) # en/ja
|
||||
level: Mapped[str] = mapped_column(String(5), nullable=False, index=True) # A1-C2 или N5-N1
|
||||
date: Mapped[datetime] = mapped_column(DateTime, nullable=False, index=True) # Дата слова (только дата, без времени)
|
||||
created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow)
|
||||
|
||||
Reference in New Issue
Block a user