first commit
This commit is contained in:
108
app/schemas/session.py
Normal file
108
app/schemas/session.py
Normal file
@@ -0,0 +1,108 @@
|
||||
"""
|
||||
Pydantic schemas for Session API endpoints.
|
||||
"""
|
||||
|
||||
from datetime import datetime
|
||||
from typing import List, Literal, Optional
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
|
||||
class UserAnswerInput(BaseModel):
|
||||
"""Input schema for a single user answer."""
|
||||
|
||||
item_id: int = Field(..., description="Item/question ID")
|
||||
response: str = Field(..., min_length=1, max_length=10, description="User's answer (A, B, C, D)")
|
||||
time_spent: int = Field(default=0, ge=0, description="Time spent on this question (seconds)")
|
||||
|
||||
|
||||
class SessionCompleteRequest(BaseModel):
|
||||
"""Request schema for completing a session."""
|
||||
|
||||
end_time: datetime = Field(..., description="Session end timestamp")
|
||||
user_answers: List[UserAnswerInput] = Field(..., description="List of user answers")
|
||||
|
||||
|
||||
class UserAnswerOutput(BaseModel):
|
||||
"""Output schema for a single user answer."""
|
||||
|
||||
id: int
|
||||
item_id: int
|
||||
response: str
|
||||
is_correct: bool
|
||||
time_spent: int
|
||||
bobot_earned: float
|
||||
scoring_mode_used: str
|
||||
|
||||
model_config = {"from_attributes": True}
|
||||
|
||||
|
||||
class SessionCompleteResponse(BaseModel):
|
||||
"""Response schema for completed session with CTT scores."""
|
||||
|
||||
id: int
|
||||
session_id: str
|
||||
wp_user_id: str
|
||||
website_id: int
|
||||
tryout_id: str
|
||||
start_time: datetime
|
||||
end_time: Optional[datetime]
|
||||
is_completed: bool
|
||||
scoring_mode_used: str
|
||||
|
||||
# CTT scores
|
||||
total_benar: int = Field(description="Total correct answers")
|
||||
total_bobot_earned: float = Field(description="Total weight earned")
|
||||
NM: Optional[int] = Field(description="Nilai Mentah (raw score) [0, 1000]")
|
||||
NN: Optional[int] = Field(description="Nilai Nasional (normalized score) [0, 1000]")
|
||||
|
||||
# Normalization metadata
|
||||
rataan_used: Optional[float] = Field(description="Mean value used for normalization")
|
||||
sb_used: Optional[float] = Field(description="Standard deviation used for normalization")
|
||||
|
||||
# User answers
|
||||
user_answers: List[UserAnswerOutput]
|
||||
|
||||
model_config = {"from_attributes": True}
|
||||
|
||||
|
||||
class SessionCreateRequest(BaseModel):
|
||||
"""Request schema for creating a new session."""
|
||||
|
||||
session_id: str = Field(..., description="Unique session identifier")
|
||||
wp_user_id: str = Field(..., description="WordPress user ID")
|
||||
website_id: int = Field(..., description="Website identifier")
|
||||
tryout_id: str = Field(..., description="Tryout identifier")
|
||||
scoring_mode: Literal["ctt", "irt", "hybrid"] = Field(
|
||||
default="ctt", description="Scoring mode for this session"
|
||||
)
|
||||
|
||||
|
||||
class SessionResponse(BaseModel):
|
||||
"""Response schema for session data."""
|
||||
|
||||
id: int
|
||||
session_id: str
|
||||
wp_user_id: str
|
||||
website_id: int
|
||||
tryout_id: str
|
||||
start_time: datetime
|
||||
end_time: Optional[datetime]
|
||||
is_completed: bool
|
||||
scoring_mode_used: str
|
||||
|
||||
# CTT scores (populated after completion)
|
||||
total_benar: int
|
||||
total_bobot_earned: float
|
||||
NM: Optional[int]
|
||||
NN: Optional[int]
|
||||
|
||||
# IRT scores (populated after completion)
|
||||
theta: Optional[float]
|
||||
theta_se: Optional[float]
|
||||
|
||||
# Normalization metadata
|
||||
rataan_used: Optional[float]
|
||||
sb_used: Optional[float]
|
||||
|
||||
model_config = {"from_attributes": True}
|
||||
Reference in New Issue
Block a user