crmjarevalida / simulado_system.py
danielraynaud's picture
Create simulado_system.py
be9b915 verified
raw
history blame
11.7 kB
# simulado_system.py
import json
import uuid
import logging
from datetime import datetime, timedelta
from typing import Dict, List, Optional, Tuple
from difflib import SequenceMatcher
import numpy as np
# Configuração de logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)
class SimuladoConstants:
"""Constantes para configuração de simulados"""
TEMPO_PADRAO = 240 # minutos
QUESTOES_TOTAIS = 120
NOTA_APROVACAO = 60
NIVEIS = ["facil", "medio", "dificil", "mixed"]
PESO_SIMILARIDADE = 0.7
class SimuladoSystem:
"""Sistema avançado de simulados e casos clínicos"""
def __init__(self, db_connection):
self.conn = db_connection
self.areas_simulado = {
"ClínicaMédica": 40,
"Cirurgia": 20,
"Pediatria": 15,
"GinecologiaObstetrícia": 15,
"MedicinaFamília": 5,
"SaúdeMental": 5
}
self.simulados_ativos = {} # Cache de simulados em andamento
def create_simulado(self, difficulty: str = "mixed",
num_questions: int = SimuladoConstants.QUESTOES_TOTAIS) -> Dict:
"""Cria simulado personalizado com mais opções"""
try:
simulado_id = str(uuid.uuid4())
simulado = {
"id": simulado_id,
"questoes": [],
"tempo_sugerido": self._calculate_time(num_questions),
"nivel": difficulty,
"data_criacao": datetime.now().isoformat(),
"status": "criado",
"estatisticas": {
"questoes_por_area": {},
"distribuicao_dificuldade": {}
}
}
cursor = self.conn.cursor()
# Distribuição de questões por área
for area, percentual in self.areas_simulado.items():
num_area_questions = int((percentual/100) * num_questions)
# Query considerando dificuldade
difficulty_clause = ""
if difficulty != "mixed":
difficulty_clause = "AND difficulty = ?"
params = (area, difficulty, num_area_questions)
else:
params = (area, num_area_questions)
cursor.execute(f'''
SELECT id, question_text, options, correct_answer,
explanation, difficulty, references
FROM previous_questions
WHERE area = ? {difficulty_clause}
ORDER BY RANDOM()
LIMIT ?
''', params)
questions = cursor.fetchall()
for q in questions:
question_data = {
"id": q[0],
"area": area,
"texto": q[1],
"opcoes": json.loads(q[2]),
"resposta": q[3],
"explicacao": q[4],
"dificuldade": q[5],
"referencias": json.loads(q[6]) if q[6] else []
}
simulado["questoes"].append(question_data)
# Atualizar estatísticas
simulado["estatisticas"]["questoes_por_area"][area] = \
simulado["estatisticas"]["questoes_por_area"].get(area, 0) + 1
simulado["estatisticas"]["distribuicao_dificuldade"][q[5]] = \
simulado["estatisticas"]["distribuicao_dificuldade"].get(q[5], 0) + 1
self.simulados_ativos[simulado_id] = simulado
return simulado
except Exception as e:
logger.error(f"Erro ao criar simulado: {e}")
return None
def _calculate_time(self, num_questions: int) -> int:
"""Calcula tempo sugerido baseado no número de questões"""
return int(num_questions * 2) # 2 minutos por questão
def evaluate_simulado(self, simulado_id: str,
respostas: Dict[str, str],
tempo_usado: int = None) -> Dict:
"""Avalia respostas do simulado com análise detalhada"""
try:
if simulado_id not in self.simulados_ativos:
raise ValueError("Simulado não encontrado")
simulado = self.simulados_ativos[simulado_id]
resultado = {
"id": simulado_id,
"total_questoes": len(simulado["questoes"]),
"corretas": 0,
"tempo_usado": tempo_usado,
"desempenho_por_area": {},
"analise_erros": [],
"recomendacoes": [],
"timestamp": datetime.now().isoformat()
}
# Análise detalhada por área
area_stats = {}
for area in self.areas_simulado:
area_stats[area] = {
"total": 0,
"corretas": 0,
"erros_comuns": [],
"tempo_medio": 0
}
# Avaliação de cada resposta
for q_id, resp in respostas.items():
questao = next((q for q in simulado["questoes"] if q["id"] == q_id), None)
if not questao:
continue
area = questao["area"]
area_stats[area]["total"] += 1
if resp.upper() == questao["resposta"].upper():
area_stats[area]["corretas"] += 1
resultado["corretas"] += 1
else:
# Análise do erro
area_stats[area]["erros_comuns"].append({
"questao_id": q_id,
"resposta_dada": resp,
"resposta_correta": questao["resposta"],
"tema": questao.get("tema", ""),
"dificuldade": questao["dificuldade"]
})
# Calcular porcentagens e gerar recomendações
for area, stats in area_stats.items():
if stats["total"] > 0:
percentual = (stats["corretas"] / stats["total"]) * 100
resultado["desempenho_por_area"][area] = {
"total": stats["total"],
"corretas": stats["corretas"],
"percentual": percentual,
"erros_comuns": stats["erros_comuns"]
}
if percentual < SimuladoConstants.NOTA_APROVACAO:
resultado["recomendacoes"].append(
self._generate_recommendations(area, stats)
)
# Salvar resultado no banco de dados
self._save_resultado(simulado_id, resultado)
return resultado
except Exception as e:
logger.error(f"Erro ao avaliar simulado: {e}")
return None
def _generate_recommendations(self, area: str, stats: Dict) -> Dict:
"""Gera recomendações detalhadas baseadas no desempenho"""
erros_comuns = self._analyze_common_errors(stats["erros_comuns"])
return {
"area": area,
"sugestoes": [
f"Revisar conceitos básicos de {area}",
f"Focar em {', '.join(erros_comuns[:3])}",
"Praticar questões similares",
"Revisar casos clínicos relacionados"
],
"recursos": [
"banco de questões",
"casos clínicos",
"revisão teórica",
"videoaulas específicas"
],
"plano_acao": self._create_action_plan(area, stats)
}
def _analyze_common_errors(self, erros: List[Dict]) -> List[str]:
"""Analisa padrões comuns de erros"""
temas_errados = {}
for erro in erros:
tema = erro["tema"]
if tema in temas_errados:
temas_errados[tema] += 1
else:
temas_errados[tema] = 1
return sorted(temas_errados.keys(),
key=lambda x: temas_errados[x],
reverse=True)
def _create_action_plan(self, area: str, stats: Dict) -> Dict:
"""Cria plano de ação personalizado"""
return {
"prioridade": "alta" if len(stats["erros_comuns"]) > stats["corretas"] else "média",
"etapas": [
"Revisão teórica dos temas com mais erros",
"Resolução de questões comentadas",
"Prática com casos clínicos",
"Simulado focado na área"
],
"tempo_sugerido": "2 semanas",
"material_sugerido": [
"Bibliografia básica",
"Questões anteriores comentadas",
"Vídeo-aulas específicas"
]
}
def _save_resultado(self, simulado_id: str, resultado: Dict) -> None:
"""Salva resultado do simulado no banco de dados"""
try:
cursor = self.conn.cursor()
cursor.execute('''
INSERT INTO resultados_simulados
(simulado_id, data, resultado_json)
VALUES (?, ?, ?)
''', (
simulado_id,
datetime.now().isoformat(),
json.dumps(resultado)
))
self.conn.commit()
except Exception as e:
logger.error(f"Erro ao salvar resultado: {e}")
def get_simulado_history(self, user_id: str) -> List[Dict]:
"""Obtém histórico de simulados do usuário"""
try:
cursor = self.conn.cursor()
cursor.execute('''
SELECT simulado_id, data, resultado_json
FROM resultados_simulados
WHERE user_id = ?
ORDER BY data DESC
''', (user_id,))
return [
{
"id": row[0],
"data": row[1],
"resultado": json.loads(row[2])
}
for row in cursor.fetchall()
]
except Exception as e:
logger.error(f"Erro ao obter histórico: {e}")
return []
# [O resto do código do CasoClinicoSystem continua o mesmo...]
def initialize_simulado_system(db_connection) -> Tuple[SimuladoSystem, CasoClinicoSystem]:
"""Inicializa o sistema de simulados"""
try:
simulado_sys = SimuladoSystem(db_connection)
caso_sys = CasoClinicoSystem(db_connection)
return simulado_sys, caso_sys
except Exception as e:
logger.error(f"Erro ao inicializar sistema de simulados: {e}")
return None, None
if __name__ == "__main__":
# Código para testes
import sqlite3
try:
conn = sqlite3.connect('revalida.db')
simulado_sys, caso_sys = initialize_simulado_system(conn)
# Teste básico
simulado = simulado_sys.create_simulado()
if simulado:
print("Sistema funcionando corretamente")
print(f"Simulado criado: {json.dumps(simulado['estatisticas'], indent=2)}")
except Exception as e:
print(f"Erro nos testes: {e}")
finally:
conn.close()