diff --git a/core/__pycache__/views.cpython-311.pyc b/core/__pycache__/views.cpython-311.pyc
index ea857fb..da4f488 100644
Binary files a/core/__pycache__/views.cpython-311.pyc and b/core/__pycache__/views.cpython-311.pyc differ
diff --git a/core/templates/core/index.html b/core/templates/core/index.html
index 8915a9c..8532dee 100644
--- a/core/templates/core/index.html
+++ b/core/templates/core/index.html
@@ -139,15 +139,24 @@
* Atualizado ao vivo conforme anulações no editor.
-
Números Anulados (Vermelho)
+
Números Anulados (IA Radar Radar)
{% for number in result.annulled_numbers %}
- {{ number|stringformat:"02d" }}
+ {% if number in result.reclaimed_numbers %}
+ {{ number|stringformat:"02d" }}
+ {% else %}
+ {{ number|stringformat:"02d" }}
+ {% endif %}
{% endfor %}
{% if not result.annulled_numbers %}
Nenhum numero anulado pelo admin.
{% endif %}
+ {% if result.reclaimed_numbers %}
+
+ IA DETECTOU: {{ result.reclaimed_numbers|length }} número(s) anulado(s) com alta chance de sorteio imediato (Verde)!
+
+ {% endif %}
@@ -351,6 +360,21 @@ document.addEventListener('DOMContentLoaded', function() {
border-color: #198754;
box-shadow: 0 0 15px rgba(25, 135, 84, 0.4);
}
+.pulse-green {
+ animation: pulse-animation 2s infinite;
+ box-shadow: 0 0 0 0 rgba(32, 201, 151, 0.7);
+}
+@keyframes pulse-animation {
+ 0% {
+ box-shadow: 0 0 0 0 rgba(32, 201, 151, 0.7);
+ }
+ 70% {
+ box-shadow: 0 0 0 10px rgba(32, 201, 151, 0);
+ }
+ 100% {
+ box-shadow: 0 0 0 0 rgba(32, 201, 151, 0);
+ }
+}
#live-result-area {
transition: all 0.3s;
}
diff --git a/core/views.py b/core/views.py
index edfb902..698791e 100644
--- a/core/views.py
+++ b/core/views.py
@@ -179,9 +179,27 @@ def home(request):
# Definição de Cores: Verde (Hot) e Vermelho (Frio)
# MATEMÁTICA AO VIVO: Calcula a elite estatística no momento do acesso, ignorando anulados.
- # Pegamos os números com maior frequência que NÃO estão anulados.
available_numbers = [n for n in range(1, lottery_obj.max_number + 1) if n not in annulled]
+ # IA DE RECLAMAÇÃO: Identifica números anulados com alta probabilidade de sorteio imediato
+ # Calculamos o atraso (delay) para todos os números
+ last_seen_all = {}
+ for i, draw in enumerate(reversed(draw_lists)):
+ for num in draw:
+ if num not in last_seen_all:
+ last_seen_all[num] = i
+
+ # Score de Reclamação para Anulados
+ reclaimed_numbers = []
+ for n in annulled:
+ freq = frequency.get(n, 0)
+ delay = last_seen_all.get(n, len(draw_lists))
+ # Se o número tem frequência alta E está "atrasado", ele é um forte candidato a voltar
+ reclaim_score = (freq * 0.6) + (delay * 0.4)
+ # Se o score dele estiver no topo 15% de probabilidade global, nós o "reclamamos"
+ if reclaim_score > (max(frequency.values()) * 0.8):
+ reclaimed_numbers.append(n)
+
# Ordena os números disponíveis pela frequência (quentes primeiro)
sorted_by_freq = sorted(available_numbers, key=lambda n: frequency.get(n, 0), reverse=True)
@@ -224,6 +242,7 @@ def home(request):
"hot_numbers": hot_numbers,
"cold_numbers": cold_numbers[:15], # Amostra de frios
"annulled_numbers": annulled,
+ "reclaimed_numbers": reclaimed_numbers,
}
context = {