# 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))