Skip to content

Commit

Permalink
Несколько правильных ответов + корректные схемы вопросов
Browse files Browse the repository at this point in the history
  • Loading branch information
codEnjoyer committed Nov 15, 2023
1 parent 9dc64d3 commit 6ea6c74
Show file tree
Hide file tree
Showing 8 changed files with 172 additions and 19 deletions.
8 changes: 3 additions & 5 deletions backend/migrations/env.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
from sqlalchemy.ext.asyncio import async_engine_from_config
from alembic import context


sys.path.append(os.path.join(sys.path[0], 'src'))
from settings import Settings

Expand All @@ -32,17 +31,16 @@
from game.map.models import Map
from game.modules.models import Module
from game.levels.models import Level
from game.units.tasks.models import Task
from game.units.theory.models import Theory, TheoryVideo
from game.units.tasks.models import TaskUnit, EmployeesTasks
from game.units.tasks.questions.models import Question, Answer
from game.units.theory.models import TheoryUnit, TheoryVideo

from users.models import User
from users.tutors.models import Tutor
from users.employees.models import Employee

from database import BaseModel


# TODO: Добавить metadata из моделей
target_metadata = BaseModel.metadata


Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
"""Добавляет таблицы вопросов и ответов
Revision ID: 5bc05f78249a
Revises: 5aa9681ef1db
Create Date: 2023-11-15 12:05:18.429020
"""
from typing import Sequence, Union

from alembic import op
import sqlalchemy as sa


# revision identifiers, used by Alembic.
revision: str = '5bc05f78249a'
down_revision: Union[str, None] = '5aa9681ef1db'
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None


def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.create_table('answers',
sa.Column('id', sa.UUID(), nullable=False),
sa.Column('question_id', sa.UUID(), nullable=False),
sa.Column('content', sa.String(), nullable=False),
sa.PrimaryKeyConstraint('id')
)
op.create_table('questions',
sa.Column('id', sa.UUID(), nullable=False),
sa.Column('type', sa.Enum(name='question_types'), nullable=False),
sa.Column('question', sa.String(), nullable=False),
sa.Column('correct_answer_id', sa.UUID(), nullable=False),
sa.PrimaryKeyConstraint('id')
)
op.create_table('task_employees',
sa.Column('task_id', sa.UUID(), nullable=False),
sa.Column('employee_id', sa.UUID(), nullable=False),
sa.Column('state', sa.Enum(name='task_states'), nullable=False),
sa.ForeignKeyConstraint(['employee_id'], ['employees.id'], ),
sa.ForeignKeyConstraint(['task_id'], ['tasks.id'], ),
sa.PrimaryKeyConstraint('task_id', 'employee_id')
)
op.add_column('tasks', sa.Column('type', sa.Enum(name='task_types'), nullable=False))
op.add_column('tasks', sa.Column('requires_review', sa.Boolean(), nullable=False))
op.drop_column('tasks', 'content')
op.drop_column('tasks', 'is_accomplished')
# ### end Alembic commands ###


def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('tasks', sa.Column('is_accomplished', sa.BOOLEAN(), autoincrement=False, nullable=False))
op.add_column('tasks', sa.Column('content', sa.TEXT(), autoincrement=False, nullable=False))
op.drop_column('tasks', 'requires_review')
op.drop_column('tasks', 'type')
op.drop_table('task_employees')
op.drop_table('questions')
op.drop_table('answers')
# ### end Alembic commands ###
8 changes: 4 additions & 4 deletions backend/src/game/levels/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@

if typing.TYPE_CHECKING:
from game.modules.models import Module
from game.units.tasks.models import Task
from game.units.theory.models import Theory
from game.units.tasks.models import TaskUnit
from game.units.theory.models import TheoryUnit


class Level(BaseModel):
Expand All @@ -21,5 +21,5 @@ class Level(BaseModel):
is_accomplished: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False)

module: Mapped["Module"] = relationship(back_populates='level')
theory: Mapped[list["Theory"]] = relationship(back_populates='level')
tasks: Mapped[list["Task"]] = relationship(back_populates='level')
theory: Mapped[list["TheoryUnit"]] = relationship(back_populates='level')
tasks: Mapped[list["TaskUnit"]] = relationship(back_populates='level')
39 changes: 31 additions & 8 deletions backend/src/game/units/tasks/models.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,44 @@
import uuid
import enum
from typing import TYPE_CHECKING

from sqlalchemy import UUID, Boolean, Integer, Text
from sqlalchemy.orm import Mapped, mapped_column
from sqlalchemy import UUID, Integer, Text, Enum, ForeignKey, Boolean
from sqlalchemy.orm import Mapped, mapped_column, relationship

from database import BaseModel

if TYPE_CHECKING:
from questions.models import Question

class Task(BaseModel):

class TaskTypes(enum.Enum):
Test = enum.auto()


class TaskStates(enum.Enum):
NotViewed = enum.auto()
Viewed = enum.auto()
Submitted = enum.auto()
Finished = enum.auto()


class TaskUnit(BaseModel):
__tablename__ = 'tasks'

id: Mapped[uuid.UUID] = mapped_column(UUID, primary_key=True, default=uuid.uuid4)
is_accomplished: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False)
# TODO: Задание не может быть выполнено глобально, нужна таблица для выполненных заданий пользователями
# requires_review: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False)
type: Mapped[TaskTypes] = mapped_column(Enum(name='task_types'), nullable=False, default=TaskTypes.Test)
requires_review: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False)
score_reward: Mapped[int] = mapped_column(Integer, nullable=False, default=1)
content: Mapped[str] = mapped_column(Text, nullable=False, default="Текст задания")
# proof: Mapped[URL] = mapped_column(URLType, nullable=True, default=None)

questions: Mapped[list["Question"]] = relationship()


class EmployeesTasks(BaseModel):
__tablename__ = 'task_employees'

task_id: Mapped[uuid.UUID] = mapped_column(UUID, ForeignKey('tasks.id'), primary_key=True)
employee_id: Mapped[uuid.UUID] = mapped_column(UUID, ForeignKey('employees.id'), primary_key=True)
state: Mapped[TaskStates] = mapped_column(Enum(name='task_states'), nullable=False, default=TaskStates.NotViewed)

# class Proof(BaseModel):
# __tablename__ = "proofs"
Expand Down
40 changes: 40 additions & 0 deletions backend/src/game/units/tasks/questions/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import uuid
import enum
from typing import TYPE_CHECKING

from sqlalchemy import UUID, Enum, String
from sqlalchemy.orm import Mapped, mapped_column, relationship

from database import BaseModel

if TYPE_CHECKING:
from game.units.tasks.models import TaskUnit


class QuestionTypes(enum.Enum):
SingleChoice = enum.auto()
MultipleChoice = enum.auto()


class Question(BaseModel):
__tablename__ = 'questions'

id: Mapped[uuid.UUID] = mapped_column(UUID, primary_key=True, default=uuid.uuid4)
type: Mapped[QuestionTypes] = mapped_column(
Enum(name='question_types'), nullable=False, default=QuestionTypes.SingleChoice)
question: Mapped[str] = mapped_column(String, nullable=False, default="Вопрос!")
correct_answer_id: Mapped[uuid.UUID] = mapped_column(UUID, default=uuid.uuid4)

task: Mapped["TaskUnit"] = relationship(back_populates='questions')
possible_answers: Mapped[list["Answer"]] = relationship(back_populates='question')
correct_answers: Mapped[list["Answer"]] = relationship(back_populates='question')


class Answer(BaseModel):
__tablename__ = 'answers'

id: Mapped[uuid.UUID] = mapped_column(UUID, primary_key=True, default=uuid.uuid4)
question_id: Mapped[uuid.UUID] = mapped_column(UUID, default=uuid.uuid4)
content: Mapped[str] = mapped_column(String, nullable=False, default='Ответ?')

question: Mapped["Question"] = relationship(back_populates='answers')
30 changes: 30 additions & 0 deletions backend/src/game/units/tasks/questions/schemas.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import uuid
from uuid import UUID

from pydantic import BaseModel, ConfigDict

from game.units.tasks.questions.models import QuestionTypes


class __QuestionBase(BaseModel):
type: QuestionTypes
question: str
possible_answers: list[str]

model_config = ConfigDict(from_attributes=True)


class TaskRead(__QuestionBase):
id: UUID
task_id: UUID


class TaskCreate(__QuestionBase):
correct_answers: list[str]
task_id: UUID


class TaskUpdate(__QuestionBase):
question: str | None
possible_answers: list[str] | None
correct_answers: list[str] | None
4 changes: 2 additions & 2 deletions backend/src/game/units/theory/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from database import BaseModel


class Theory(BaseModel):
class TheoryUnit(BaseModel):
__tablename__ = 'theory_blocks'

id: Mapped[uuid.UUID] = mapped_column(UUID, primary_key=True, default=uuid.uuid4)
Expand All @@ -24,4 +24,4 @@ class TheoryVideo(BaseModel):
theory_id: Mapped[uuid.UUID] = mapped_column(UUID, ForeignKey('theory_blocks.id'), nullable=False)
url: Mapped[URL] = mapped_column(URLType, nullable=False)

theory: Mapped["Theory"] = relationship(back_populates="theory_video")
theory: Mapped["TheoryUnit"] = relationship(back_populates="theory_video")
2 changes: 2 additions & 0 deletions backend/src/users/employees/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

if typing.TYPE_CHECKING:
from users.tutors.models import Tutor
from game.units.tasks.models import TaskUnit


class Employee(BaseModel):
Expand All @@ -23,3 +24,4 @@ class Employee(BaseModel):
hired_at: Mapped[datetime.date] = mapped_column(Date, server_default=func.current_date())

tutor: Mapped["Tutor"] = relationship(back_populates='employee')
tasks: Mapped[list["TaskUnit"]] = relationship(secondary="task_employees", back_populates='employees')

0 comments on commit 6ea6c74

Please sign in to comment.