feat: quiz recomendation

This commit is contained in:
akhdanre 2025-05-01 10:53:50 +07:00
parent 650c4d7b03
commit a2df303e02
10 changed files with 85 additions and 10 deletions

View File

@ -46,7 +46,9 @@ def get_answer(controller: QuizController = Provide[Container.quiz_controller]):
def get_quiz_recommendation( def get_quiz_recommendation(
controller: QuizController = Provide[Container.quiz_controller], controller: QuizController = Provide[Container.quiz_controller],
): ):
return controller.get_quiz_recommendation() page = request.args.get("page")
limit = request.args.get("limit")
return controller.get_quiz_recommendation(page=page, limit=limit)
@quiz_bp.route("/user/<user_id>", methods=["GET"]) @quiz_bp.route("/user/<user_id>", methods=["GET"])

View File

@ -104,3 +104,26 @@ class QuizController:
) )
except Exception as e: except Exception as e:
return make_error_response(e) return make_error_response(e)
def get_quiz_recommendation(self, page, limit):
try:
# Convert to int
page = int(page)
limit = int(limit)
# Validate input
if page <= 0 or limit <= 0:
raise ValueError("Page and limit must be greater than 0.")
result = self.quiz_service.get_quiz_recommendation(page=page, limit=limit)
return make_response(
message="success retrieve recommendation quiz", data=result
)
except ValueError as e:
return make_response(message=str(e), data=None, status_code=400)
except ValidationError as e:
return make_response(
message="validation error", data=json.loads(e.json()), status_code=400
)
except Exception as e:
return make_error_response(e)

View File

@ -28,7 +28,11 @@ class Container(containers.DeclarativeContainer):
# 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,
user_repository,
)
answer_service = providers.Factory( answer_service = providers.Factory(
AnswerService, AnswerService,
answer_repository, answer_repository,

View File

@ -14,7 +14,9 @@ def map_question_entity_to_schema(entity: QuestionItemEntity) -> QuestionItemSch
def map_quiz_entity_to_schema(entity: QuizEntity) -> QuizGetSchema: def map_quiz_entity_to_schema(entity: QuizEntity) -> QuizGetSchema:
print(entity.id)
return QuizGetSchema( return QuizGetSchema(
id=str(entity.id),
author_id=entity.author_id, author_id=entity.author_id,
title=entity.title, title=entity.title,
description=entity.description, description=entity.description,

View File

@ -74,3 +74,15 @@ class QuizRepository:
def count_by_user_id(self, user_id: str) -> int: def count_by_user_id(self, user_id: str) -> int:
return self.collection.count_documents({"author_id": user_id}) return self.collection.count_documents({"author_id": user_id})
def get_top_played_quizzes(
self, page: int = 1, limit: int = 3, is_public: bool = True
) -> List[QuizEntity]:
skip = (page - 1) * limit
cursor = (
self.collection.find({"is_public": is_public})
.sort("total_user_playing", -1)
.skip(skip)
.limit(limit)
)
return [QuizEntity(**doc) for doc in cursor]

View File

@ -4,6 +4,7 @@ from .quiz.question_item_schema import QuestionItemSchema
from .quiz.quiz_data_rsp_schema import UserQuizListResponse from .quiz.quiz_data_rsp_schema import UserQuizListResponse
from .history.history_response import HistoryResultSchema from .history.history_response import HistoryResultSchema
from .history.detail_history_response import QuizHistoryResponse, QuestionResult from .history.detail_history_response import QuizHistoryResponse, QuestionResult
from .recomendation.recomendation_response_schema import RecomendationResponse
__all__ = [ __all__ = [
"QuizCreationResponse", "QuizCreationResponse",
@ -13,4 +14,5 @@ __all__ = [
"HistoryResultSchema", "HistoryResultSchema",
"QuizHistoryResponse", "QuizHistoryResponse",
"QuestionResult", "QuestionResult",
"RecomendationResponse",
] ]

View File

@ -5,6 +5,7 @@ from .question_item_schema import QuestionItemSchema
class QuizGetSchema(BaseModel): class QuizGetSchema(BaseModel):
id: str
author_id: str author_id: str
title: str title: str
description: Optional[str] = None description: Optional[str] = None

View File

@ -0,0 +1,10 @@
from pydantic import BaseModel
class RecomendationResponse(BaseModel):
quiz_id: str
author_id: str
author_name: str
title: str
description: str
date: str

View File

@ -25,10 +25,11 @@ class AnswerService:
def create_answer(self, answer_data: UserAnswerSchema): def create_answer(self, answer_data: UserAnswerSchema):
quiz_data = self.quiz_repository.get_by_id(answer_data.quiz_id) quiz_data = self.quiz_repository.get_by_id(answer_data.quiz_id)
if not quiz_data:
raise ValidationException(message="Quiz not found")
user_data = self.user_repositroy.get_user_by_id(answer_data.user_id) user_data = self.user_repositroy.get_user_by_id(answer_data.user_id)
if not user_data: if not user_data:
raise ValidationException(message="user is not registered") raise ValidationException(message="user is not registered")
total_quiz_played = quiz_data.total_user_playing + 1 total_quiz_played = quiz_data.total_user_playing + 1
self.quiz_repository.update_user_playing( self.quiz_repository.update_user_playing(
quiz_id=quiz_data.id, total_user=total_quiz_played quiz_id=quiz_data.id, total_user=total_quiz_played

View File

@ -1,16 +1,17 @@
from typing import List from typing import List
from repositories import QuizRepository from repositories import QuizRepository, UserRepository
from schemas import QuizGetSchema from schemas import QuizGetSchema
from schemas.requests import QuizCreateSchema from schemas.requests import QuizCreateSchema
from schemas.response import UserQuizListResponse from schemas.response import UserQuizListResponse, RecomendationResponse
from exception import DataNotFoundException from exception import DataNotFoundException
from mapper import map_quiz_entity_to_schema from mapper import map_quiz_entity_to_schema
from exception import ValidationException from exception import ValidationException
class QuizService: class QuizService:
def __init__(self, quiz_repository=QuizRepository): def __init__(self, quiz_repository=QuizRepository, user_repository=UserRepository):
self.quiz_repository = quiz_repository self.quiz_repository = quiz_repository
self.user_repostory = user_repository
def get_quiz(self, quiz_id) -> QuizGetSchema: def get_quiz(self, quiz_id) -> QuizGetSchema:
data = self.quiz_repository.get_by_id(quiz_id) data = self.quiz_repository.get_by_id(quiz_id)
@ -45,9 +46,26 @@ 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): def get_quiz_recommendation(self, page: int = 1, limit: int = 3):
data = self.quiz_repository
if data is None: page = page or 1
limit = limit or 3
data = self.quiz_repository.get_top_played_quizzes(page=page, limit=limit)
if not data:
raise DataNotFoundException("Quiz not found") raise DataNotFoundException("Quiz not found")
return map_quiz_entity_to_schema(data) result = []
for quiz in data:
author = self.user_repostory.get_user_by_id(user_id=quiz.author_id)
result.append(
RecomendationResponse(
quiz_id=str(quiz.id),
author_id=str(author.id),
author_name=author.name,
title=quiz.title,
description=quiz.description,
date=quiz.date.strftime("%d-%B-%Y"),
)
)
return result