Spaces:
Runtime error
Runtime error
# 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)) |