import logging from typing import Union, List, Dict from fastapi import BackgroundTasks from ielts_be.dtos.evaluation import EvaluationType from ielts_be.dtos.speaking import GradeSpeakingItem from ielts_be.dtos.writing import WritingGradeTaskDTO from ielts_be.repositories import IDocumentStore from ielts_be.services import IWritingService, ISpeakingService, IEvaluationService class EvaluationService(IEvaluationService): def __init__(self, db: IDocumentStore, writing_service: IWritingService, speaking_service: ISpeakingService): self._db = db self._writing_service = writing_service self._speaking_service = speaking_service self._logger = logging.getLogger(__name__) async def begin_evaluation( self, user_id: str, session_id: str, task: int, exercise_id: str, exercise_type: str, solution: Union[WritingGradeTaskDTO, List[GradeSpeakingItem]], background_tasks: BackgroundTasks ): background_tasks.add_task( self._begin_evaluation, user_id, session_id, task, exercise_id, exercise_type, solution ) async def _begin_evaluation( self, user_id: str, session_id: str, task: int, exercise_id: str, exercise_type: str, solution: Union[WritingGradeTaskDTO, List[GradeSpeakingItem]] ): try: if exercise_type == EvaluationType.WRITING: result = await self._writing_service.grade_writing_task( task, solution.question, solution.answer, solution.attachment ) else: result = await self._speaking_service.grade_speaking_task( task, solution ) eval_res = await self._db.find( "evaluation", { "user": user_id, "exercise_id": exercise_id, "session_id": session_id, } ) if len(eval_res) > 0: await self._db.update( "evaluation", { "user": user_id, "exercise_id": exercise_id, "session_id": session_id, }, { "$set": { "status": "completed", "result": result, } } ) else: self._logger.info("Skipping evaluation write to db since the record was removed.") except Exception as e: eval_res = await self._db.find( "evaluation", { "user": user_id, "exercise_id": exercise_id, "session_id": session_id, } ) if len(eval_res) > 0: self._logger.error(f"Error processing evaluation {session_id} - {exercise_id}: {str(e)}") await self._db.update( "evaluation", { "user": user_id, "exercise_id": exercise_id, "session_id": session_id }, { "$set": { "status": "error", "error": str(e), } } ) else: self._logger.info("Skipping evaluation write to db since the record was removed.")