import logging from typing import Union, Dict, List from fastapi import BackgroundTasks from app.dtos.evaluation import EvaluationType from app.dtos.speaking import GradeSpeakingItem from app.dtos.writing import WritingGradeTaskDTO from app.repositories.abc import IDocumentStore from app.services.abc 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 create_evaluation( self, user_id: str, session_id: str, exercise_id: str, eval_type: EvaluationType, task: int ): await self._db.save_to_db( "evaluation", { "user": user_id, "session_id": session_id, "exercise_id": exercise_id, "type": eval_type, "task": task, "status": "pending" } ) 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 ) else: result = await self._speaking_service.grade_speaking_task( task, solution ) await self._db.update( "evaluation", { "user": user_id, "exercise_id": exercise_id, "session_id": session_id, }, { "$set": { "status": "completed", "result": result, } } ) except Exception as e: 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), } } ) async def get_evaluations(self, session_id: str, status: str) -> List[Dict]: return await self._db.find( "evaluation", { "session_id": session_id, "status": status } )