from enum import Enum from pydantic import BaseModel, Field from typing import List, Union from uuid import uuid4, UUID class WriteBlanksSolution(BaseModel): id: str solution: List[str] class WriteBlanksExercise(BaseModel): id: UUID = Field(default_factory=uuid4) type: str = "writeBlanks" maxWords: int solutions: List[WriteBlanksSolution] text: str @property def prompt(self) -> str: return f"Choose no more than {self.maxWords} words and/or a number from the passage for each answer." class MatchSentencesOption(BaseModel): id: str sentence: str class MatchSentencesSentence(MatchSentencesOption): solution: str class MatchSentencesVariant(str, Enum): HEADING = "heading" IDEAMATCH = "ideaMatch" class MatchSentencesExercise(BaseModel): options: List[MatchSentencesOption] sentences: List[MatchSentencesSentence] type: str = "matchSentences" variant: MatchSentencesVariant @property def prompt(self) -> str: return ( "Choose the correct heading for paragraphs from the list of headings below." if self.variant == MatchSentencesVariant.HEADING else "Choose the correct author for the ideas/opinions from the list of authors below." ) class TrueFalseSolution(str, Enum): TRUE = "true" FALSE = "false" NOT_GIVEN = "not_given" class TrueFalseQuestions(BaseModel): prompt: str solution: TrueFalseSolution id: str class TrueFalseExercise(BaseModel): id: UUID = Field(default_factory=uuid4) questions: List[TrueFalseQuestions] type: str = "trueFalse" prompt: str = "Do the following statements agree with the information given in the Reading Passage?" class FillBlanksSolution(BaseModel): id: str solution: str class FillBlanksWord(BaseModel): letter: str word: str class FillBlanksExercise(BaseModel): id: UUID = Field(default_factory=uuid4) solutions: List[FillBlanksSolution] text: str type: str = "fillBlanks" words: List[FillBlanksWord] allowRepetition: bool = False @property def prompt(self) -> str: prompt = "Complete the summary below. Write the letter of the corresponding word(s) for it." return ( f"{prompt}" if len(self.solutions) == len(self.words) else f"{prompt}\\nThere are more words than spaces so you will not use them all." ) Exercise = Union[FillBlanksExercise, TrueFalseExercise, MatchSentencesExercise, WriteBlanksExercise] class Context(BaseModel): title: str content: str class Part(BaseModel): exercises: List[Exercise] text: Context class Exam(BaseModel): id: UUID = Field(default_factory=uuid4) module: str = "reading" minTimer: int isDiagnostic: bool = False parts: List[Part]