Spaces:
Sleeping
Sleeping
| """Comparações históricas entre métricas. | |
| Compara o valor atual de uma métrica com o dia anterior e com a média dos | |
| últimos 7 dias, calculando variação absoluta, percentual e tendência. | |
| """ | |
| from __future__ import annotations | |
| from typing import Any | |
| from ..utils.validators import arredondar, divisao_segura | |
| # Faixa de variação (em %) considerada "estável" para definição da tendência. | |
| _LIMIAR_ESTAVEL_PERCENT = 1.0 | |
| def _tendencia(variacao_percent: float | None) -> str: | |
| """Classifica a tendência a partir da variação percentual. | |
| Returns: | |
| ``"up"``, ``"down"`` ou ``"stable"``. | |
| """ | |
| if variacao_percent is None: | |
| return "stable" | |
| if variacao_percent > _LIMIAR_ESTAVEL_PERCENT: | |
| return "up" | |
| if variacao_percent < -_LIMIAR_ESTAVEL_PERCENT: | |
| return "down" | |
| return "stable" | |
| def compare_metric( | |
| current_value: float | None, | |
| previous_value: float | None, | |
| seven_day_avg: float | None, | |
| ) -> dict[str, Any]: | |
| """Compara um valor atual com o dia anterior e com a média de 7 dias. | |
| Args: | |
| current_value: Valor atual da métrica. | |
| previous_value: Valor do dia anterior (ou None). | |
| seven_day_avg: Média dos últimos 7 dias (ou None). | |
| Returns: | |
| Dicionário com variações absolutas/percentuais e a tendência. | |
| """ | |
| atual = current_value if current_value is not None else 0.0 | |
| # --- Comparação com o dia anterior --- | |
| var_prev: float | None = None | |
| var_prev_pct: float | None = None | |
| if previous_value is not None: | |
| var_prev = arredondar(atual - previous_value, 2) | |
| var_prev_pct = arredondar( | |
| divisao_segura(atual - previous_value, abs(previous_value)) * 100.0, 2 | |
| ) | |
| # --- Comparação com a média de 7 dias --- | |
| var_avg: float | None = None | |
| var_avg_pct: float | None = None | |
| if seven_day_avg is not None: | |
| var_avg = arredondar(atual - seven_day_avg, 2) | |
| var_avg_pct = arredondar( | |
| divisao_segura(atual - seven_day_avg, abs(seven_day_avg)) * 100.0, 2 | |
| ) | |
| return { | |
| "current": arredondar(atual, 2), | |
| "previous": arredondar(previous_value, 2) if previous_value is not None else None, | |
| "seven_day_avg": arredondar(seven_day_avg, 2) | |
| if seven_day_avg is not None | |
| else None, | |
| "variation_vs_previous": var_prev, | |
| "variation_percent_vs_previous": var_prev_pct, | |
| "variation_vs_7day_avg": var_avg, | |
| "variation_percent_vs_7day_avg": var_avg_pct, | |
| "trend": _tendencia(var_prev_pct if var_prev_pct is not None else var_avg_pct), | |
| } | |
| def aplicar_comparacoes( | |
| metricas_atuais: dict[str, Any], | |
| metricas_anteriores: dict[str, Any] | None, | |
| media_7_dias: dict[str, float] | None, | |
| chaves_numericas: list[str], | |
| ) -> dict[str, dict[str, Any]]: | |
| """Gera o bloco de comparações para um conjunto de métricas numéricas. | |
| Args: | |
| metricas_atuais: Métricas do dia atual (dict plano). | |
| metricas_anteriores: Métricas do dia anterior (ou None). | |
| media_7_dias: Médias de 7 dias por métrica (ou None). | |
| chaves_numericas: Quais chaves devem ser comparadas. | |
| Returns: | |
| Dicionário ``{chave: resultado_de_compare_metric}``. | |
| """ | |
| anteriores = metricas_anteriores or {} | |
| medias = media_7_dias or {} | |
| resultado: dict[str, dict[str, Any]] = {} | |
| for chave in chaves_numericas: | |
| atual = metricas_atuais.get(chave) | |
| if not isinstance(atual, (int, float)): | |
| continue | |
| anterior = anteriores.get(chave) | |
| media = medias.get(chave) | |
| resultado[chave] = compare_metric( | |
| float(atual), | |
| float(anterior) if isinstance(anterior, (int, float)) else None, | |
| float(media) if isinstance(media, (int, float)) else None, | |
| ) | |
| return resultado | |