diff --git a/app/blueprints/quiz.py b/app/blueprints/quiz.py index 86f3895..ba09b4b 100644 --- a/app/blueprints/quiz.py +++ b/app/blueprints/quiz.py @@ -46,7 +46,9 @@ def get_answer(controller: QuizController = Provide[Container.quiz_controller]): def get_quiz_recommendation( 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/", methods=["GET"]) diff --git a/app/controllers/quiz_controller.py b/app/controllers/quiz_controller.py index fb23b70..af4f2b2 100644 --- a/app/controllers/quiz_controller.py +++ b/app/controllers/quiz_controller.py @@ -104,3 +104,26 @@ class QuizController: ) except Exception as 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) diff --git a/app/di_container.py b/app/di_container.py index c73e885..566e7ea 100644 --- a/app/di_container.py +++ b/app/di_container.py @@ -28,7 +28,11 @@ class Container(containers.DeclarativeContainer): # services auth_service = providers.Factory(AuthService, 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( AnswerService, answer_repository, diff --git a/app/mapper/quiz_mapper.py b/app/mapper/quiz_mapper.py index c66e8d5..78458fd 100644 --- a/app/mapper/quiz_mapper.py +++ b/app/mapper/quiz_mapper.py @@ -14,7 +14,9 @@ def map_question_entity_to_schema(entity: QuestionItemEntity) -> QuestionItemSch def map_quiz_entity_to_schema(entity: QuizEntity) -> QuizGetSchema: + print(entity.id) return QuizGetSchema( + id=str(entity.id), author_id=entity.author_id, title=entity.title, description=entity.description, diff --git a/app/repositories/quiz_repositroy.py b/app/repositories/quiz_repositroy.py index 69418b9..cda6403 100644 --- a/app/repositories/quiz_repositroy.py +++ b/app/repositories/quiz_repositroy.py @@ -74,3 +74,15 @@ class QuizRepository: def count_by_user_id(self, user_id: str) -> int: 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] diff --git a/app/schemas/response/__init__.py b/app/schemas/response/__init__.py index 458792c..9bd8c7c 100644 --- a/app/schemas/response/__init__.py +++ b/app/schemas/response/__init__.py @@ -4,6 +4,7 @@ from .quiz.question_item_schema import QuestionItemSchema from .quiz.quiz_data_rsp_schema import UserQuizListResponse from .history.history_response import HistoryResultSchema from .history.detail_history_response import QuizHistoryResponse, QuestionResult +from .recomendation.recomendation_response_schema import RecomendationResponse __all__ = [ "QuizCreationResponse", @@ -13,4 +14,5 @@ __all__ = [ "HistoryResultSchema", "QuizHistoryResponse", "QuestionResult", + "RecomendationResponse", ] diff --git a/app/schemas/response/quiz/quiz_get_response.py b/app/schemas/response/quiz/quiz_get_response.py index de4977b..c7d870f 100644 --- a/app/schemas/response/quiz/quiz_get_response.py +++ b/app/schemas/response/quiz/quiz_get_response.py @@ -5,6 +5,7 @@ from .question_item_schema import QuestionItemSchema class QuizGetSchema(BaseModel): + id: str author_id: str title: str description: Optional[str] = None diff --git a/app/schemas/response/recomendation/recomendation_response_schema.py b/app/schemas/response/recomendation/recomendation_response_schema.py new file mode 100644 index 0000000..bb4497e --- /dev/null +++ b/app/schemas/response/recomendation/recomendation_response_schema.py @@ -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 diff --git a/app/services/answer_service.py b/app/services/answer_service.py index 6f5f4f9..68e1010 100644 --- a/app/services/answer_service.py +++ b/app/services/answer_service.py @@ -25,10 +25,11 @@ class AnswerService: def create_answer(self, answer_data: UserAnswerSchema): 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) if not user_data: raise ValidationException(message="user is not registered") - total_quiz_played = quiz_data.total_user_playing + 1 self.quiz_repository.update_user_playing( quiz_id=quiz_data.id, total_user=total_quiz_played diff --git a/app/services/quiz_service.py b/app/services/quiz_service.py index 20a33e4..16d8063 100644 --- a/app/services/quiz_service.py +++ b/app/services/quiz_service.py @@ -1,16 +1,17 @@ from typing import List -from repositories import QuizRepository +from repositories import QuizRepository, UserRepository from schemas import QuizGetSchema from schemas.requests import QuizCreateSchema -from schemas.response import UserQuizListResponse +from schemas.response import UserQuizListResponse, RecomendationResponse from exception import DataNotFoundException from mapper import map_quiz_entity_to_schema from exception import ValidationException class QuizService: - def __init__(self, quiz_repository=QuizRepository): + def __init__(self, quiz_repository=QuizRepository, user_repository=UserRepository): self.quiz_repository = quiz_repository + self.user_repostory = user_repository def get_quiz(self, quiz_id) -> QuizGetSchema: data = self.quiz_repository.get_by_id(quiz_id) @@ -45,9 +46,26 @@ class QuizService: def delete_quiz(self, quiz_id): return self.quiz_repository.delete(quiz_id) - def quiz_recommendation(self): - data = self.quiz_repository - if data is None: + def get_quiz_recommendation(self, page: int = 1, limit: int = 3): + + 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") - 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