crmjarevalida / utils /helpers.py
danielraynaud's picture
Create utils/helpers.py
cbb5c88 verified
raw
history blame
6.62 kB
# utils/helpers.py
import re
from datetime import datetime, timedelta
from typing import Dict, List, Optional, Union
import json
import logging
# Configuração de logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)
class ValidationError(Exception):
"""Exceção customizada para erros de validação"""
pass
def validate_email(email: str) -> bool:
"""Valida formato de email"""
pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
return bool(re.match(pattern, email))
def validate_date_format(date_str: str) -> bool:
"""Valida formato de data (YYYY-MM-DD)"""
try:
datetime.strptime(date_str, '%Y-%m-%d')
return True
except ValueError:
return False
def format_time_delta(minutes: int) -> str:
"""Formata duração em minutos para formato legível"""
hours = minutes // 60
remaining_minutes = minutes % 60
if hours > 0:
return f"{hours}h{remaining_minutes:02d}min"
return f"{minutes}min"
def calculate_study_efficiency(hours_studied: float,
questions_answered: int,
correct_answers: int) -> float:
"""Calcula eficiência de estudo"""
if hours_studied <= 0 or questions_answered == 0:
return 0.0
accuracy = correct_answers / questions_answered
questions_per_hour = questions_answered / hours_studied
# Fórmula personalizada para eficiência
efficiency = (accuracy * 0.7 + (questions_per_hour / 20) * 0.3) * 100
return round(min(efficiency, 100), 2)
def format_performance_message(score: float) -> str:
"""Gera mensagem motivacional baseada no desempenho"""
if score >= 90:
return "🌟 Excelente! Você está dominando o conteúdo!"
elif score >= 80:
return "💪 Ótimo trabalho! Continue assim!"
elif score >= 70:
return "👍 Bom progresso! Mantenha o foco!"
elif score >= 60:
return "📚 Você está no caminho certo! Continue estudando!"
else:
return "💡 Não desanime! Cada questão é uma oportunidade de aprendizado!"
def generate_study_recommendations(weak_areas: List[str],
hours_available: float) -> Dict[str, any]:
"""Gera recomendações de estudo baseadas em áreas fracas"""
total_weight = len(weak_areas)
hours_per_area = hours_available / total_weight if total_weight > 0 else 0
recommendations = {
"distribuicao_tempo": {},
"prioridades": [],
"recursos_sugeridos": []
}
for area in weak_areas:
recommendations["distribuicao_tempo"][area] = round(hours_per_area, 1)
recommendations["prioridades"].append({
"area": area,
"foco": ["Revisão teórica", "Questões práticas", "Casos clínicos"]
})
recommendations["recursos_sugeridos"] = [
"Material teórico focado",
"Questões comentadas",
"Vídeo-aulas específicas",
"Casos clínicos interativos"
]
return recommendations
def parse_command_args(command: str) -> Dict[str, str]:
"""Processa argumentos de comandos do bot"""
parts = command.split()
if len(parts) < 1:
return {}
command_dict = {
"command": parts[0]
}
# Processa argumentos nomeados (e.g., /comando area=pediatria tempo=2)
for part in parts[1:]:
if '=' in part:
key, value = part.split('=', 1)
command_dict[key.lower()] = value
else:
# Argumentos posicionais
if 'args' not in command_dict:
command_dict['args'] = []
command_dict['args'].append(part)
return command_dict
def format_question(question: Dict[str, any],
number: Optional[int] = None) -> str:
"""Formata questão para exibição"""
formatted = ""
if number is not None:
formatted += f"Questão {number}:\n"
formatted += f"{question['texto']}\n\n"
for letra, texto in question['opcoes'].items():
formatted += f"{letra}) {texto}\n"
return formatted
def calculate_remaining_time(target_date: str) -> Dict[str, int]:
"""Calcula tempo restante até a data alvo"""
target = datetime.strptime(target_date, '%Y-%m-%d').date()
today = datetime.now().date()
difference = target - today
return {
"dias": difference.days,
"semanas": difference.days // 7,
"meses": difference.days // 30
}
def format_study_summary(progress_data: Dict[str, any]) -> str:
"""Formata resumo de estudos para exibição"""
summary = "📊 Resumo de Estudos:\n\n"
# Total de horas
total_hours = sum(progress_data.get('horas_por_area', {}).values())
summary += f"⏱ Total de horas estudadas: {total_hours:.1f}h\n"
# Desempenho por área
summary += "\n📈 Desempenho por área:\n"
for area, score in progress_data.get('desempenho_por_area', {}).items():
summary += f"• {area}: {score:.1f}%\n"
# Média geral
if 'media_geral' in progress_data:
summary += f"\n🎯 Média geral: {progress_data['media_geral']:.1f}%\n"
return summary
def safe_json_loads(json_str: str, default: Union[Dict, List] = None) -> Union[Dict, List]:
"""Carrega JSON com segurança"""
try:
return json.loads(json_str)
except Exception as e:
logger.error(f"Erro ao carregar JSON: {e}")
return default if default is not None else {}
def sanitize_input(text: str) -> str:
"""Sanitiza input do usuário"""
# Remove caracteres potencialmente perigosos
return re.sub(r'[<>&;]', '', text.strip())
def format_error_message(error: Exception) -> str:
"""Formata mensagem de erro para usuário"""
return f"""❌ Ops! Ocorreu um erro:
{str(error)}
Por favor, tente novamente ou use /ajuda para ver os comandos disponíveis."""
if __name__ == "__main__":
# Testes básicos
print(validate_email("test@example.com")) # True
print(validate_email("invalid-email")) # False
print(format_time_delta(90)) # "1h30min"
print(format_time_delta(45)) # "45min"
test_question = {
"texto": "Qual é o principal sintoma da condição X?",
"opcoes": {
"A": "Sintoma 1",
"B": "Sintoma 2",
"C": "Sintoma 3",
"D": "Sintoma 4"
}
}
print(format_question(test_question, 1))