Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

QuestionService: Add fetch random question endpoint #181

Merged
merged 1 commit into from
Oct 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions question-service/app/crud/questions.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from bson import ObjectId
from bson.errors import InvalidId
from dotenv import load_dotenv
from random import randint
import motor.motor_asyncio
import os
from typing import List
Expand All @@ -10,6 +11,7 @@
QuestionNotFoundError,
BatchUploadFailedError,
InvalidQuestionIdError,
RandomQuestionNotFoundError
)
from models.questions import (
CategoryEnum,
Expand Down Expand Up @@ -100,6 +102,24 @@ async def batch_create_questions(
"message": f"{len(result.inserted_ids)} questions added successfully."
})

async def fetch_random_question(
category: CategoryEnum | None,
complexity: ComplexityEnum | None,
) -> QuestionModel:
query = {}
if category:
query["categories"] = category
if complexity:
query["complexity"] = complexity

count = await question_collection.count_documents(query)
if count == 0:
raise RandomQuestionNotFoundError(category, complexity)

random_index = randint(0, count - 1)
random_question = await question_collection.find(query).skip(random_index).limit(1).to_list(1)
return QuestionModel.parse_obj(random_question[0])

def get_question_categories() -> List[CategoryEnum]:
return [category for category in CategoryEnum]

Expand Down
7 changes: 7 additions & 0 deletions question-service/app/exceptions/questions_exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,13 @@ class QuestionNotFoundError(Exception):
def __init__(self, question_id):
self.question_id = question_id
super().__init__(f"Question with ID '{question_id}' not found.")

class RandomQuestionNotFoundError(Exception):
"""Raised when a question with the given ID is not found."""
def __init__(self, category, complexity):
self.category = category
self.complexity = complexity
super().__init__(f"Question with category '{category}' and complexity '{complexity}' not found.")

class BatchUploadFailedError(Exception):
"""Raised when batch upload fails to upload any questions successfully"""
Expand Down
16 changes: 16 additions & 0 deletions question-service/app/routers/questions.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,14 @@
get_question_categories,
get_question_complexities,
update_question_by_id,
fetch_random_question,
)
from exceptions.questions_exceptions import (
DuplicateQuestionError,
QuestionNotFoundError,
BatchUploadFailedError,
InvalidQuestionIdError,
RandomQuestionNotFoundError,
)
from fastapi import APIRouter, HTTPException, Query
from models.questions import (
Expand All @@ -29,6 +31,20 @@

router = APIRouter()

@router.get("/random",
response_description="Get a random question based on category and complexity",
response_model=QuestionModel
)
async def get_random_question(
category: CategoryEnum | None = None,
complexity: ComplexityEnum | None = None,
):
try:
question = await fetch_random_question(category, complexity)
return question
except RandomQuestionNotFoundError as e:
raise HTTPException(status_code=404, detail=str(e))

@router.post("/",
response_description="Create new question",
response_model=QuestionModel,
Expand Down