feat: working on quiz
This commit is contained in:
parent
019eb2ecc9
commit
7a521b9ca2
|
@ -4,22 +4,46 @@ from dependency_injector.wiring import inject, Provide
|
||||||
from controllers import QuizController
|
from controllers import QuizController
|
||||||
|
|
||||||
|
|
||||||
quiz_bp = Blueprint(
|
quiz_bp = Blueprint("quiz", __name__, url_prefix="/quiz")
|
||||||
"quiz",
|
|
||||||
__name__,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@quiz_bp.route("/quiz", methods=["POST"])
|
@quiz_bp.route("/", methods=["POST"])
|
||||||
@inject
|
@inject
|
||||||
def create_quiz(controller: QuizController = Provide[Container.quiz_controller]):
|
def create_quiz(controller: QuizController = Provide[Container.quiz_controller]):
|
||||||
reqBody = request.get_json()
|
reqBody = request.get_json()
|
||||||
return controller.create_quiz(reqBody)
|
return controller.create_quiz(reqBody)
|
||||||
|
|
||||||
|
|
||||||
@quiz_bp.route("/quiz/<quiz_id>", methods=["GET"])
|
@quiz_bp.route("/<quiz_id>", methods=["GET"])
|
||||||
@inject
|
@inject
|
||||||
def get_quiz(
|
def get_quiz(
|
||||||
quiz_id: str, controller: QuizController = Provide[Container.quiz_controller]
|
quiz_id: str, controller: QuizController = Provide[Container.quiz_controller]
|
||||||
):
|
):
|
||||||
return controller.get_quiz(quiz_id)
|
return controller.get_quiz(quiz_id)
|
||||||
|
|
||||||
|
|
||||||
|
@quiz_bp.route("/answer", methods=["POST"])
|
||||||
|
@inject
|
||||||
|
def submit_answer(controller: QuizController = Provide[Container.quiz_controller]):
|
||||||
|
req_body = request.get_json()
|
||||||
|
return controller.submit_answer(req_body)
|
||||||
|
|
||||||
|
|
||||||
|
@quiz_bp.route("/answer", methods=["GET"])
|
||||||
|
@inject
|
||||||
|
def get_answer(controller: QuizController = Provide[Container.quiz_controller]):
|
||||||
|
quiz_id = request.args.get("quiz_id")
|
||||||
|
user_id = request.args.get("user_id")
|
||||||
|
session_id = request.args.get("session_id")
|
||||||
|
|
||||||
|
return controller.get_answer(
|
||||||
|
quiz_id=quiz_id, user_id=user_id, session_id=session_id
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@quiz_bp.route("/recomendation", methods=["GET"])
|
||||||
|
@inject
|
||||||
|
def get_quiz_recommendation(
|
||||||
|
controller: QuizController = Provide[Container.quiz_controller],
|
||||||
|
):
|
||||||
|
return controller.get_quiz_recommendation()
|
||||||
|
|
|
@ -1,14 +1,15 @@
|
||||||
from flask import jsonify
|
from flask import jsonify
|
||||||
from pydantic import ValidationError
|
from pydantic import ValidationError
|
||||||
from schemas.requests import QuizCreateSchema
|
from schemas.requests import QuizCreateSchema, UserAnswerSchema
|
||||||
from schemas.response import QuizCreationResponse
|
from schemas.response import QuizCreationResponse
|
||||||
from services import QuizService
|
from services import QuizService, AnswerService
|
||||||
from helpers import make_response, make_error_response
|
from helpers import make_response, make_error_response
|
||||||
|
|
||||||
|
|
||||||
class QuizController:
|
class QuizController:
|
||||||
def __init__(self, quiz_service: QuizService):
|
def __init__(self, quiz_service: QuizService, answer_service: AnswerService):
|
||||||
self.quiz_service = quiz_service
|
self.quiz_service = quiz_service
|
||||||
|
self.answer_service = answer_service
|
||||||
|
|
||||||
def get_quiz(self, quiz_id):
|
def get_quiz(self, quiz_id):
|
||||||
try:
|
try:
|
||||||
|
@ -50,3 +51,34 @@ class QuizController:
|
||||||
if not success:
|
if not success:
|
||||||
return jsonify({"error": "Quiz not found"}), 400
|
return jsonify({"error": "Quiz not found"}), 400
|
||||||
return jsonify({"message": "Quiz deleted"}), 200
|
return jsonify({"message": "Quiz deleted"}), 200
|
||||||
|
|
||||||
|
def quiz_recomendation(self):
|
||||||
|
try:
|
||||||
|
result = self.quiz_service.get_quiz_recommendation()
|
||||||
|
if not result:
|
||||||
|
return make_response(message="Quiz not found", status_code=404)
|
||||||
|
return make_response(message="Quiz Found", data=result.dict())
|
||||||
|
except Exception as e:
|
||||||
|
return make_error_response(e)
|
||||||
|
|
||||||
|
def submit_answer(self, answer_data):
|
||||||
|
try:
|
||||||
|
# Assuming answer_data is a dictionary with the necessary fields
|
||||||
|
answer_obj = UserAnswerSchema(**answer_data)
|
||||||
|
answer_id = self.answer_service.create_answer(answer_obj)
|
||||||
|
return make_response(
|
||||||
|
message="Answer submitted",
|
||||||
|
data={"answer_id": answer_id},
|
||||||
|
status_code=201,
|
||||||
|
)
|
||||||
|
except ValidationError as e:
|
||||||
|
return make_response(e.errors(), status_code=400)
|
||||||
|
except Exception as e:
|
||||||
|
return make_error_response(e)
|
||||||
|
|
||||||
|
def get_answer(self, quiz_id, user_id, session_id):
|
||||||
|
try:
|
||||||
|
# self.answer_service.
|
||||||
|
print("yps")
|
||||||
|
except Exception as e:
|
||||||
|
return make_error_response(e)
|
||||||
|
|
|
@ -1,12 +1,7 @@
|
||||||
from dependency_injector import containers, providers
|
from dependency_injector import containers, providers
|
||||||
from controllers import UserController
|
from controllers import UserController, AuthController, QuizController
|
||||||
from repositories.user_repository import UserRepository
|
from repositories import UserRepository, QuizRepository, UserAnswerRepository
|
||||||
from services import UserService, AuthService
|
from services import UserService, AuthService, QuizService, AnswerService
|
||||||
from controllers import AuthController
|
|
||||||
from flask_pymongo import PyMongo
|
|
||||||
from repositories import QuizRepository
|
|
||||||
from services import QuizService
|
|
||||||
from controllers import QuizController
|
|
||||||
|
|
||||||
|
|
||||||
class Container(containers.DeclarativeContainer):
|
class Container(containers.DeclarativeContainer):
|
||||||
|
@ -17,13 +12,15 @@ class Container(containers.DeclarativeContainer):
|
||||||
# repository
|
# repository
|
||||||
user_repository = providers.Factory(UserRepository, mongo.provided.db)
|
user_repository = providers.Factory(UserRepository, mongo.provided.db)
|
||||||
quiz_repository = providers.Factory(QuizRepository, mongo.provided.db)
|
quiz_repository = providers.Factory(QuizRepository, mongo.provided.db)
|
||||||
|
answer_repository = providers.Factory(UserAnswerRepository, mongo.provided.db)
|
||||||
|
|
||||||
# services
|
# services
|
||||||
auth_service = providers.Factory(AuthService, user_repository)
|
auth_service = providers.Factory(AuthService, user_repository)
|
||||||
user_service = providers.Factory(UserService, user_repository)
|
user_service = providers.Factory(UserService, user_repository)
|
||||||
quiz_service = providers.Factory(QuizService, quiz_repository)
|
quiz_service = providers.Factory(QuizService, quiz_repository)
|
||||||
|
answer_service = providers.Factory(AnswerService, answer_repository)
|
||||||
|
|
||||||
# controllers
|
# controllers
|
||||||
auth_controller = providers.Factory(AuthController, user_service, auth_service)
|
auth_controller = providers.Factory(AuthController, user_service, auth_service)
|
||||||
user_controller = providers.Factory(UserController, user_service)
|
user_controller = providers.Factory(UserController, user_service)
|
||||||
quiz_controller = providers.Factory(QuizController, quiz_service)
|
quiz_controller = providers.Factory(QuizController, quiz_service, answer_service)
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# app/models/__init__.py
|
# app/models/__init__.py
|
||||||
from .entities import UserEntity, QuizEntity, QuestionItemEntity
|
from .entities import UserEntity, QuizEntity, QuestionItemEntity, UserAnswerEntity
|
||||||
from .login import UserResponseModel
|
from .login import UserResponseModel
|
||||||
|
|
||||||
|
|
||||||
|
@ -9,4 +9,5 @@ __all__ = [
|
||||||
"UserResponseModel",
|
"UserResponseModel",
|
||||||
"QuizEntity",
|
"QuizEntity",
|
||||||
"QuestionItemEntity",
|
"QuestionItemEntity",
|
||||||
|
"UserAnswerEntity",
|
||||||
]
|
]
|
||||||
|
|
|
@ -2,10 +2,12 @@ from .user_entity import UserEntity
|
||||||
from .base import PyObjectId
|
from .base import PyObjectId
|
||||||
from .quiz_entity import QuizEntity
|
from .quiz_entity import QuizEntity
|
||||||
from .question_item_entity import QuestionItemEntity
|
from .question_item_entity import QuestionItemEntity
|
||||||
|
from .user_answer_entity import UserAnswerEntity
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
"UserEntity",
|
"UserEntity",
|
||||||
"PyObjectId",
|
"PyObjectId",
|
||||||
"QuizEntity",
|
"QuizEntity",
|
||||||
"QuestionItemEntity",
|
"QuestionItemEntity",
|
||||||
|
"UserAnswerEntity",
|
||||||
]
|
]
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
from pydantic import BaseModel
|
||||||
|
|
||||||
|
|
||||||
|
class AnswerItemEntity(BaseModel):
|
||||||
|
question_index: int
|
||||||
|
question: str
|
||||||
|
answer: str
|
||||||
|
correct_answer: str
|
||||||
|
is_correct: bool
|
||||||
|
duration: int
|
||||||
|
time_spent: float
|
|
@ -1,8 +1,10 @@
|
||||||
from bson import ObjectId
|
from bson import ObjectId
|
||||||
|
from pydantic import GetJsonSchemaHandler
|
||||||
|
from pydantic.json_schema import JsonSchemaValue
|
||||||
|
|
||||||
|
|
||||||
class PyObjectId(ObjectId):
|
class PyObjectId(ObjectId):
|
||||||
"""Custom ObjectId type for Pydantic to handle MongoDB _id"""
|
"""Custom ObjectId type for Pydantic v2 to handle MongoDB _id"""
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def __get_validators__(cls):
|
def __get_validators__(cls):
|
||||||
|
@ -15,5 +17,7 @@ class PyObjectId(ObjectId):
|
||||||
return ObjectId(v)
|
return ObjectId(v)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def __modify_schema__(cls, field_schema):
|
def __get_pydantic_json_schema__(
|
||||||
field_schema.update(type="string")
|
cls, schema: JsonSchemaValue, handler: GetJsonSchemaHandler
|
||||||
|
) -> JsonSchemaValue:
|
||||||
|
return {"type": "string"}
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
from typing import List, Optional
|
||||||
|
from pydantic import BaseModel, Field
|
||||||
|
from datetime import datetime
|
||||||
|
from bson import ObjectId
|
||||||
|
|
||||||
|
from .answer_item import AnswerItemEntity
|
||||||
|
from .base import PyObjectId
|
||||||
|
|
||||||
|
|
||||||
|
class UserAnswerEntity(BaseModel):
|
||||||
|
_id: Optional[PyObjectId] = None
|
||||||
|
session_id: Optional[PyObjectId]
|
||||||
|
quiz_id: PyObjectId
|
||||||
|
user_id: str
|
||||||
|
answered_at: datetime
|
||||||
|
answers: List[AnswerItemEntity]
|
||||||
|
total_score: int
|
||||||
|
total_correct: int
|
||||||
|
total_questions: int
|
||||||
|
|
||||||
|
class Config:
|
||||||
|
allow_population_by_field_name = True
|
||||||
|
arbitrary_types_allowed = True
|
||||||
|
json_encoders = {ObjectId: str}
|
|
@ -1,8 +1,9 @@
|
||||||
from .user_repository import UserRepository
|
from .user_repository import UserRepository
|
||||||
from .quiz_repositroy import QuizRepository
|
from .quiz_repositroy import QuizRepository
|
||||||
|
from .answer_repository import UserAnswerRepository
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
"UserRepository",
|
"UserRepository",
|
||||||
"QuizRepository",
|
"QuizRepository",
|
||||||
|
"UserAnswerRepository",
|
||||||
]
|
]
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
from pymongo.collection import Collection
|
||||||
|
from bson import ObjectId
|
||||||
|
from typing import Optional, List
|
||||||
|
from models import UserAnswerEntity
|
||||||
|
|
||||||
|
|
||||||
|
class UserAnswerRepository:
|
||||||
|
def __init__(self, db):
|
||||||
|
self.collection: Collection = db.user_answers
|
||||||
|
|
||||||
|
def create(self, answer_session: UserAnswerEntity) -> str:
|
||||||
|
data = answer_session.model_dump(by_alias=True)
|
||||||
|
result = self.collection.insert_one(data)
|
||||||
|
return str(result.inserted_id)
|
||||||
|
|
||||||
|
def get_by_id(self, id: str) -> Optional[dict]:
|
||||||
|
result = self.collection.find_one({"_id": ObjectId(id)})
|
||||||
|
return result
|
||||||
|
|
||||||
|
def get_by_user_and_quiz(self, user_id: str, quiz_id: str) -> List[dict]:
|
||||||
|
result = self.collection.find(
|
||||||
|
{"user_id": user_id, "quiz_id": ObjectId(quiz_id)}
|
||||||
|
)
|
||||||
|
return list(result)
|
||||||
|
|
||||||
|
def get_by_session(self, session_id: str) -> List[dict]:
|
||||||
|
result = self.collection.find({"session_id": ObjectId(session_id)})
|
||||||
|
return list(result)
|
||||||
|
|
||||||
|
def delete_by_id(self, id: str) -> bool:
|
||||||
|
result = self.collection.delete_one({"_id": ObjectId(id)})
|
||||||
|
return result.deleted_count > 0
|
|
@ -5,9 +5,14 @@ from .quiz import (
|
||||||
QuizCreateSchema,
|
QuizCreateSchema,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
from .answer.answer_request_schema import UserAnswerSchema
|
||||||
|
from .answer.answer_item_request_schema import AnswerItemSchema
|
||||||
|
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
"RegisterSchema",
|
"RegisterSchema",
|
||||||
"QuestionItemSchema",
|
"QuestionItemSchema",
|
||||||
"QuizCreateSchema",
|
"QuizCreateSchema",
|
||||||
|
"UserAnswerSchema",
|
||||||
|
"AnswerItemSchema",
|
||||||
]
|
]
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
from pydantic import BaseModel
|
||||||
|
|
||||||
|
|
||||||
|
class AnswerItemSchema(BaseModel):
|
||||||
|
question_index: int
|
||||||
|
question: str
|
||||||
|
answer: str
|
||||||
|
correct_answer: str
|
||||||
|
is_correct: bool
|
||||||
|
duration: int
|
||||||
|
time_spent: float
|
|
@ -0,0 +1,15 @@
|
||||||
|
from typing import List, Optional
|
||||||
|
from pydantic import BaseModel, Field
|
||||||
|
from datetime import datetime
|
||||||
|
from .answer_item_request_schema import AnswerItemSchema
|
||||||
|
|
||||||
|
|
||||||
|
class UserAnswerSchema(BaseModel):
|
||||||
|
session_id: Optional[str] = None
|
||||||
|
quiz_id: str
|
||||||
|
user_id: str
|
||||||
|
answered_at: datetime
|
||||||
|
total_score: int
|
||||||
|
total_correct: int
|
||||||
|
total_questions: int
|
||||||
|
answers: List[AnswerItemSchema]
|
|
@ -1,10 +1,12 @@
|
||||||
from .auth_service import AuthService
|
from .auth_service import AuthService
|
||||||
from .user_service import UserService
|
from .user_service import UserService
|
||||||
from .quiz_service import QuizService
|
from .quiz_service import QuizService
|
||||||
|
from .answer_service import AnswerService
|
||||||
|
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
"AuthService",
|
"AuthService",
|
||||||
"UserService",
|
"UserService",
|
||||||
"QuizService",
|
"QuizService",
|
||||||
|
"AnswerService",
|
||||||
]
|
]
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
from repositories import UserAnswerRepository
|
||||||
|
|
||||||
|
|
||||||
|
class AnswerService:
|
||||||
|
def __init__(self, answer_repository: UserAnswerRepository):
|
||||||
|
self.answer_repository = answer_repository
|
||||||
|
|
||||||
|
def get_answer_by_id(self, answer_id):
|
||||||
|
return self.answer_repository.get_answer_by_id(answer_id)
|
||||||
|
|
||||||
|
def get_answer(self, quiz_id, user_id, session_id):
|
||||||
|
if quiz_id is not None:
|
||||||
|
return self.answer_repository
|
||||||
|
|
||||||
|
def create_answer(self, answer_data):
|
||||||
|
return self.answer_repository.create(answer_data)
|
||||||
|
|
||||||
|
def update_answer(self, answer_id, answer_data):
|
||||||
|
return self.answer_repository.update(answer_id, answer_data)
|
||||||
|
|
||||||
|
def delete_answer(self, answer_id):
|
||||||
|
return self.answer_repository.delete_by_id(answer_id)
|
|
@ -23,3 +23,10 @@ class QuizService:
|
||||||
|
|
||||||
def delete_quiz(self, quiz_id):
|
def delete_quiz(self, quiz_id):
|
||||||
return self.quiz_repository.delete(quiz_id)
|
return self.quiz_repository.delete(quiz_id)
|
||||||
|
|
||||||
|
def quiz_recommendation(self):
|
||||||
|
data = self.quiz_repository
|
||||||
|
if data is None:
|
||||||
|
raise DataNotFoundException("Quiz not found")
|
||||||
|
|
||||||
|
return map_quiz_entity_to_schema(data)
|
||||||
|
|
Loading…
Reference in New Issue