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}")
already_answered = await has_already_answered(game_pin, game.current_question, username)
if already_answered:
print("already answerered")
return
if question.type not in (QuizQuestionType.ABCD, QuizQuestionType.VOTING):
print("Wrong q type")
return
selected_answer = question.answers[data_answer].answer selected_answer = question.answers[data_answer].answer
except (KeyError, IndexError):
return answer_data_obj = SubmitAnswerData(question_index=game.current_question, answer=selected_answer)
if await redis.get(f"answer_given:{player_id}:{game.current_question}") is not None: answer_right, stored_answer = check_answer(game, answer_data_obj)
return
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
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()]