✨ Added new range-answer type
This commit is contained in:
+24
-3
@@ -7,7 +7,7 @@ from datetime import datetime
|
||||
from typing import Optional
|
||||
|
||||
import ormar
|
||||
from pydantic import BaseModel, Json
|
||||
from pydantic import BaseModel, Json, validator
|
||||
from enum import Enum
|
||||
from . import metadata, database
|
||||
|
||||
@@ -62,17 +62,38 @@ class UserSession(ormar.Model):
|
||||
database = database
|
||||
|
||||
|
||||
class QuizAnswer(BaseModel):
|
||||
class ABCDQuizAnswer(BaseModel):
|
||||
right: bool
|
||||
answer: str
|
||||
|
||||
|
||||
class RangeQuizAnswer(BaseModel):
|
||||
min: int
|
||||
max: int
|
||||
min_correct: int
|
||||
max_correct: int
|
||||
|
||||
|
||||
class QuizQuestionType(str, Enum):
|
||||
ABCD = "ABCD"
|
||||
RANGE = "RANGE"
|
||||
|
||||
|
||||
class QuizQuestion(BaseModel):
|
||||
question: str
|
||||
time: str # in Secs
|
||||
answers: list[QuizAnswer]
|
||||
type: None | QuizQuestionType = QuizQuestionType.ABCD
|
||||
answers: list[ABCDQuizAnswer] | RangeQuizAnswer
|
||||
image: str | None = None
|
||||
|
||||
@validator("answers")
|
||||
def answers_not_none_if_abcd_type(cls, v, values):
|
||||
if values["type"] == QuizQuestionType.ABCD and len(v) == 0:
|
||||
raise ValueError("Answers can't be none if type is ABCD")
|
||||
if values["type"] == QuizQuestionType.RANGE and type(v) != RangeQuizAnswer:
|
||||
raise ValueError("Answer must be from type RangeQuizAnswer if type is RANGE")
|
||||
return v
|
||||
|
||||
|
||||
class QuizInput(BaseModel):
|
||||
public: bool = False
|
||||
|
||||
@@ -10,7 +10,7 @@ from datetime import datetime
|
||||
from aiohttp import ClientSession
|
||||
|
||||
from classquiz.config import settings, storage, meilisearch
|
||||
from classquiz.db.models import Quiz, QuizAnswer, QuizQuestion, User
|
||||
from classquiz.db.models import Quiz, ABCDQuizAnswer, QuizQuestion, User
|
||||
from classquiz.kahoot_importer.get import get as get_quiz
|
||||
from classquiz.helpers import get_meili_data
|
||||
|
||||
@@ -38,7 +38,7 @@ async def import_quiz(quiz_id: str, user: User) -> Quiz | str:
|
||||
meilisearch.create_index(settings.meilisearch_index)
|
||||
|
||||
for q in quiz.kahoot.questions:
|
||||
answers: list[QuizAnswer] = []
|
||||
answers: list[ABCDQuizAnswer] = []
|
||||
image = None
|
||||
if q.image is not None and q.image != "":
|
||||
image_bytes = await _download_image(q.image)
|
||||
@@ -46,7 +46,7 @@ async def import_quiz(quiz_id: str, user: User) -> Quiz | str:
|
||||
image = await storage.upload(file_name=image_name, file_data=image_bytes)
|
||||
image = f"{settings.root_address}/api/v1/storage/download/{image_name}"
|
||||
for a in q.choices:
|
||||
answers.append((QuizAnswer(right=a.correct, answer=html.unescape(a.answer))))
|
||||
answers.append((ABCDQuizAnswer(right=a.correct, answer=html.unescape(a.answer))))
|
||||
quiz_questions.append(
|
||||
QuizQuestion(
|
||||
question=q.question,
|
||||
|
||||
@@ -96,9 +96,9 @@ async def upload_image(edit_id: str, pow_data: str, file: UploadFile = File()):
|
||||
if session_data is None:
|
||||
raise HTTPException(status_code=401, detail="Edit ID not found!")
|
||||
|
||||
if uploaded_images == 0 and not check_hashcash(pow_data, pow_data_server, "16"):
|
||||
if uploaded_images == 0 and not check_hashcash(pow_data, pow_data_server, "8"):
|
||||
raise HTTPException(status_code=401, detail="Edit ID not found!")
|
||||
if uploaded_images != 0 and not check_hashcash(pow_data, pow_data_server, "16"):
|
||||
if uploaded_images != 0 and not check_hashcash(pow_data, pow_data_server, "8"):
|
||||
raise HTTPException(status_code=401, detail="Edit ID not found!")
|
||||
file_bytes = await file.read()
|
||||
if len(file_bytes) < 2000:
|
||||
|
||||
@@ -10,7 +10,7 @@ import socketio
|
||||
|
||||
from typing import Any
|
||||
from classquiz.config import redis, settings
|
||||
from classquiz.db.models import PlayGame
|
||||
from classquiz.db.models import PlayGame, QuizQuestionType
|
||||
from pydantic import BaseModel, ValidationError
|
||||
|
||||
sio = socketio.AsyncServer(async_mode="asgi", cors_allowed_origins=[])
|
||||
@@ -188,10 +188,20 @@ async def submit_answer(sid: str, data: dict):
|
||||
session = await sio.get_session(sid)
|
||||
game_data = PlayGame.parse_raw(await redis.get(f"game:{session['game_pin']}"))
|
||||
answer_right = False
|
||||
for answer in game_data.questions[int(data.question_index)].answers:
|
||||
if answer.answer == data.answer and answer.right:
|
||||
if game_data.questions[int(data.question_index)].type == QuizQuestionType.ABCD:
|
||||
for answer in game_data.questions[int(data.question_index)].answers:
|
||||
if answer.answer == data.answer and answer.right:
|
||||
answer_right = True
|
||||
break
|
||||
elif game_data.questions[int(data.question_index)].type == QuizQuestionType.RANGE:
|
||||
if (
|
||||
game_data.questions[int(data.question_index)].answers.min_correct
|
||||
<= int(data.answer)
|
||||
<= game_data.questions[int(data.question_index)].answers.max_correct
|
||||
):
|
||||
answer_right = True
|
||||
break
|
||||
else:
|
||||
raise NotImplementedError
|
||||
answers = await redis.get(f"game_session:{session['game_pin']}:{data.question_index}")
|
||||
if answers is None:
|
||||
await redis.set(
|
||||
|
||||
Reference in New Issue
Block a user