Spaces:
Runtime error
Runtime error
| # models/question_models.py | |
| from dataclasses import dataclass, field | |
| from typing import Dict, List, Optional | |
| from datetime import datetime | |
| import json | |
| class Question: | |
| """Modelo para questões do Revalida""" | |
| id: int | |
| text: str | |
| options: Dict[str, str] | |
| correct_answer: str | |
| explanation: str | |
| area: str | |
| year: Optional[int] = None | |
| difficulty: str = "medium" | |
| tags: List[str] = field(default_factory=list) | |
| references: List[str] = field(default_factory=list) | |
| times_used: int = 0 | |
| success_rate: float = 0.0 | |
| def to_dict(self) -> Dict: | |
| """Converte para dicionário""" | |
| return { | |
| "id": self.id, | |
| "text": self.text, | |
| "options": self.options, | |
| "correct_answer": self.correct_answer, | |
| "explanation": self.explanation, | |
| "area": self.area, | |
| "year": self.year, | |
| "difficulty": self.difficulty, | |
| "tags": self.tags, | |
| "references": self.references, | |
| "times_used": self.times_used, | |
| "success_rate": self.success_rate | |
| } | |
| def format_for_display(self, show_answer: bool = False) -> str: | |
| """Formata questão para exibição""" | |
| formatted = f"📝 Questão {self.id}\n\n" | |
| formatted += f"{self.text}\n\n" | |
| for letra, texto in self.options.items(): | |
| formatted += f"{letra}) {texto}\n" | |
| if show_answer: | |
| formatted += f"\n✅ Resposta: {self.correct_answer}\n" | |
| formatted += f"📋 Explicação: {self.explanation}\n" | |
| if self.references: | |
| formatted += "\n📚 Referências:\n" | |
| for ref in self.references: | |
| formatted += f"• {ref}\n" | |
| return formatted | |
| class ClinicalCase: | |
| """Modelo para casos clínicos""" | |
| id: int | |
| title: str | |
| description: str | |
| area: str | |
| steps: Dict[str, str] | |
| expected_answers: Dict[str, str] | |
| hints: Dict[str, List[str]] | |
| difficulty: str = "medium" | |
| references: List[str] = field(default_factory=list) | |
| created_at: datetime = field(default_factory=datetime.now) | |
| def to_dict(self) -> Dict: | |
| """Converte para dicionário""" | |
| return { | |
| "id": self.id, | |
| "title": self.title, | |
| "description": self.description, | |
| "area": self.area, | |
| "steps": self.steps, | |
| "expected_answers": self.expected_answers, | |
| "hints": self.hints, | |
| "difficulty": self.difficulty, | |
| "references": self.references, | |
| "created_at": self.created_at.isoformat() | |
| } | |
| def get_step(self, step_number: int) -> Optional[Dict[str, str]]: | |
| """Retorna informações de uma etapa específica""" | |
| step_key = str(step_number) | |
| if step_key not in self.steps: | |
| return None | |
| return { | |
| "description": self.steps[step_key], | |
| "expected_answer": self.expected_answers.get(step_key, ""), | |
| "hints": self.hints.get(step_key, []) | |
| } | |
| def format_step(self, step_number: int, show_answer: bool = False) -> str: | |
| """Formata uma etapa do caso clínico para exibição""" | |
| step = self.get_step(step_number) | |
| if not step: | |
| return "Etapa não encontrada." | |
| formatted = f"🏥 Caso Clínico: {self.title}\n" | |
| formatted += f"Etapa {step_number}\n\n" | |
| formatted += f"{step['description']}\n" | |
| if show_answer: | |
| formatted += f"\n✅ Resposta esperada:\n{step['expected_answer']}\n" | |
| if step['hints']: | |
| formatted += "\n💡 Dicas:\n" | |
| for hint in step['hints']: | |
| formatted += f"• {hint}\n" | |
| return formatted | |
| class Simulado: | |
| """Modelo para simulados""" | |
| id: str | |
| questions: List[Question] | |
| difficulty: str | |
| created_at: datetime = field(default_factory=datetime.now) | |
| completed_at: Optional[datetime] = None | |
| user_answers: Dict[int, str] = field(default_factory=dict) | |
| score: Optional[float] = None | |
| time_taken: Optional[int] = None | |
| analysis: Dict = field(default_factory=dict) | |
| def to_dict(self) -> Dict: | |
| """Converte para dicionário""" | |
| return { | |
| "id": self.id, | |
| "questions": [q.to_dict() for q in self.questions], | |
| "difficulty": self.difficulty, | |
| "created_at": self.created_at.isoformat(), | |
| "completed_at": self.completed_at.isoformat() if self.completed_at else None, | |
| "user_answers": self.user_answers, | |
| "score": self.score, | |
| "time_taken": self.time_taken, | |
| "analysis": self.analysis | |
| } | |
| def submit_answer(self, question_id: int, answer: str) -> bool: | |
| """Registra resposta do usuário""" | |
| if not any(q.id == question_id for q in self.questions): | |
| return False | |
| self.user_answers[question_id] = answer | |
| return True | |
| def calculate_score(self) -> float: | |
| """Calcula pontuação do simulado""" | |
| if not self.questions or not self.user_answers: | |
| return 0.0 | |
| correct = sum( | |
| 1 for q in self.questions | |
| if q.id in self.user_answers and | |
| q.correct_answer.upper() == self.user_answers[q.id].upper() | |
| ) | |
| return (correct / len(self.questions)) * 100 | |
| def generate_analysis(self) -> Dict: | |
| """Gera análise detalhada do desempenho""" | |
| analysis = { | |
| "total_questions": len(self.questions), | |
| "answered_questions": len(self.user_answers), | |
| "score": self.calculate_score(), | |
| "performance_by_area": {}, | |
| "weak_areas": [], | |
| "recommendations": [] | |
| } | |
| # Análise por área | |
| area_stats = {} | |
| for question in self.questions: | |
| if question.area not in area_stats: | |
| area_stats[question.area] = {"total": 0, "correct": 0} | |
| area_stats[question.area]["total"] += 1 | |
| if (question.id in self.user_answers and | |
| question.correct_answer.upper() == self.user_answers[question.id].upper()): | |
| area_stats[question.area]["correct"] += 1 | |
| # Calcula percentuais e identifica áreas fracas | |
| for area, stats in area_stats.items(): | |
| percentage = (stats["correct"] / stats["total"]) * 100 | |
| analysis["performance_by_area"][area] = { | |
| "total": stats["total"], | |
| "correct": stats["correct"], | |
| "percentage": percentage | |
| } | |
| if percentage < 60: | |
| analysis["weak_areas"].append(area) | |
| # Gera recomendações | |
| if analysis["weak_areas"]: | |
| analysis["recommendations"].append( | |
| "Revisar os seguintes tópicos: " + ", ".join(analysis["weak_areas"]) | |
| ) | |
| if analysis["score"] < 70: | |
| analysis["recommendations"].append( | |
| "Aumentar a quantidade de questões práticas" | |
| ) | |
| return analysis | |
| def load_question_from_dict(data: Dict) -> Question: | |
| """Cria instância de Question a partir de dicionário""" | |
| return Question( | |
| id=data["id"], | |
| text=data["text"], | |
| options=data["options"], | |
| correct_answer=data["correct_answer"], | |
| explanation=data["explanation"], | |
| area=data["area"], | |
| year=data.get("year"), | |
| difficulty=data.get("difficulty", "medium"), | |
| tags=data.get("tags", []), | |
| references=data.get("references", []), | |
| times_used=data.get("times_used", 0), | |
| success_rate=data.get("success_rate", 0.0) | |
| ) | |
| def load_clinical_case_from_dict(data: Dict) -> ClinicalCase: | |
| """Cria instância de ClinicalCase a partir de dicionário""" | |
| return ClinicalCase( | |
| id=data["id"], | |
| title=data["title"], | |
| description=data["description"], | |
| area=data["area"], | |
| steps=data["steps"], | |
| expected_answers=data["expected_answers"], | |
| hints=data["hints"], | |
| difficulty=data.get("difficulty", "medium"), | |
| references=data.get("references", []), | |
| created_at=datetime.fromisoformat(data["created_at"]) | |
| if "created_at" in data else datetime.now() | |
| ) | |
| if __name__ == "__main__": | |
| # Testes básicos | |
| test_question = Question( | |
| id=1, | |
| text="Qual é o principal sintoma da hipertensão?", | |
| options={ | |
| "A": "Dor de cabeça", | |
| "B": "Tontura", | |
| "C": "Náusea", | |
| "D": "Assintomático" | |
| }, | |
| correct_answer="D", | |
| explanation="A hipertensão é frequentemente assintomática...", | |
| area="ClínicaMédica" | |
| ) | |
| print(test_question.format_for_display(show_answer=True)) |