ClassQuizController basic gameplay cleanup

This commit is contained in:
Mawoka
2026-06-15 18:02:11 +02:00
parent 71d5989925
commit eb35654539
2 changed files with 44 additions and 31 deletions
+9
View File
@@ -11,3 +11,12 @@
reverse_proxy /openapi.json localhost:8000 reverse_proxy /openapi.json localhost:8000
reverse_proxy /socket.io* localhost:8000 reverse_proxy /socket.io* localhost:8000
} }
192.168.100.127:8081 {
tls internal
reverse_proxy /* localhost:3000
reverse_proxy /api* localhost:8000
reverse_proxy /rapidoc* localhost:8000
reverse_proxy /openapi.json localhost:8000
reverse_proxy /socket.io* localhost:8000
}
@@ -7,55 +7,53 @@ import enum
import typing import typing
from datetime import datetime from datetime import datetime
from fastapi import APIRouter, HTTPException, WebSocket, WebSocketDisconnect, status from fastapi import APIRouter, WebSocket, WebSocketDisconnect, status
from pydantic import BaseModel, ValidationError from pydantic import BaseModel, ValidationError
from classquiz.config import redis from classquiz.config import redis
from classquiz.db.models import PlayGame, QuizQuestionType, AnswerData, GamePlayer from classquiz.db.models import AnswerData, GamePlayer, PlayGame, QuizQuestionType
from classquiz.socket_server import sio, calculate_score, set_answer from classquiz.socket_server import calculate_score, set_answer, sio
from classquiz.socket_server.helpers import check_answer, has_already_answered
from classquiz.socket_server.models import SubmitAnswerData
router = APIRouter() router = APIRouter()
class SubmitAnswerInput(BaseModel):
answer: int
async def submit_answer_fn(data_answer: int, game_pin: str, player_id: str, now: datetime): async def submit_answer_fn(data_answer: int, game_pin: str, player_id: str, now: datetime):
redis_res_game = await redis.get(f"game:{game_pin}") print(data_answer)
username = await redis.get(f"game:cqc:player:{player_id}") game = await PlayGame.get_from_redis(game_pin)
if redis_res_game is None or username is None:
raise HTTPException(status_code=404, detail="id not existent")
game = PlayGame.model_validate_json(redis_res_game)
if not game.question_show: if not game.question_show:
print("Not showing q")
return return
question = game.questions[game.current_question] question = game.questions[game.current_question]
question_time = datetime.fromisoformat(await redis.get(f"game:{game_pin}:current_time")) question_time = datetime.fromisoformat(await redis.get(f"game:{game_pin}:current_time"))
try: username = await redis.get(f"game:cqc:player:{player_id}")
selected_answer = question.answers[data_answer].answer already_answered = await has_already_answered(game_pin, game.current_question, username)
except (KeyError, IndexError): if already_answered:
print("already answerered")
return return
if await redis.get(f"answer_given:{player_id}:{game.current_question}") is not None: if question.type not in (QuizQuestionType.ABCD, QuizQuestionType.VOTING):
return print("Wrong q type")
answer_right = False
if question.type == QuizQuestionType.ABCD:
for answer in question.answers:
if answer.answer == selected_answer and answer.right:
answer_right = True
break
elif question.type == QuizQuestionType.VOTING:
answer_right = False
else:
return return
selected_answer = question.answers[data_answer].answer
answer_data_obj = SubmitAnswerData(question_index=game.current_question, answer=selected_answer)
answer_right, stored_answer = check_answer(game, answer_data_obj)
diff = (question_time - now).total_seconds() * 1000 diff = (question_time - now).total_seconds() * 1000
score = 0 score = 0
if answer_right: if answer_right:
score = calculate_score(abs(diff), int(float(question.time))) score = calculate_score(
abs(diff),
int(float(question.time)),
)
if score > 1000:
score = 1000
await redis.set(f"answer_given:{player_id}:{game.current_question}", "True", ex=600) await redis.set(f"answer_given:{player_id}:{game.current_question}", "True", ex=600)
await redis.hincrby(f"game_session:{game_pin}:player_scores", username, score) await redis.hincrby(f"game_session:{game_pin}:player_scores", username, score)
answer_data = AnswerData( answer_data = AnswerData(
username=username, username=username,
answer=selected_answer, answer=stored_answer,
right=answer_right, right=answer_right,
time_taken=abs(diff), time_taken=abs(diff),
score=score, score=score,
@@ -64,11 +62,13 @@ async def submit_answer_fn(data_answer: int, game_pin: str, player_id: str, now:
answers = await set_answer(answers, game_pin=game_pin, data=answer_data, q_index=game.current_question) answers = await set_answer(answers, game_pin=game_pin, data=answer_data, q_index=game.current_question)
player_count = await redis.scard(f"game_session:{game_pin}:players") player_count = await redis.scard(f"game_session:{game_pin}:players")
await sio.emit("player_answer", {}) await sio.emit("player_answer", {})
if answers is not None and len(answers) == player_count: if len(answers) == player_count:
game.question_show = False
await game.save(game_pin)
await sio.emit("everyone_answered", {}) await sio.emit("everyone_answered", {})
button_to_index_map = {"y": 0, "r": 3, "g": 1, "b": 2} button_to_index_map = {"b": 0, "y": 1, "g": 2, "r": 3}
class WebSocketTypes(enum.Enum): class WebSocketTypes(enum.Enum):
@@ -104,7 +104,10 @@ async def websocket_endpoint(ws: WebSocket, game_id: str):
{"username": username, "sid": None}, {"username": username, "sid": None},
room=f"admin:{game_pin}", room=f"admin:{game_pin}",
) )
await redis.sadd(f"game_session:{game_pin}:players", GamePlayer(username=username, sid=None).model_dump_json()) await redis.sadd(
f"game_session:{game_pin}:players",
GamePlayer(username=username, sid=None).model_dump_json(),
)
while True: while True:
raw_data = await ws.receive_text() raw_data = await ws.receive_text()
@@ -120,6 +123,7 @@ async def websocket_endpoint(ws: WebSocket, game_id: str):
continue continue
if data.type == WebSocketTypes.ButtonPress: if data.type == WebSocketTypes.ButtonPress:
print("submitting")
now = datetime.now() now = datetime.now()
try: try:
answer_index = button_to_index_map[data.data.lower()] answer_index = button_to_index_map[data.data.lower()]