Autosave: 20260220-011604
This commit is contained in:
parent
06e2196d32
commit
24c53fb469
Binary file not shown.
Binary file not shown.
Binary file not shown.
18
core/migrations/0003_alter_lottery_name.py
Normal file
18
core/migrations/0003_alter_lottery_name.py
Normal file
@ -0,0 +1,18 @@
|
||||
# Generated by Django 5.2.7 on 2026-02-19 22:09
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('core', '0002_lottery_ai_predictions_lottery_analysis_window'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='lottery',
|
||||
name='name',
|
||||
field=models.CharField(choices=[('mega_sena', 'Mega-Sena'), ('quina', 'Quina'), ('dupla_sena', 'Dupla Sena'), ('lotomania', 'Lotomania'), ('lotofacil', 'Lotofácil'), ('timemania', 'Timemania'), ('dia_de_sorte', 'Dia de Sorte'), ('federal', 'Federal'), ('super_sete', 'Super Sete'), ('maismilionaria', '+Milionária')], max_length=50, unique=True),
|
||||
),
|
||||
]
|
||||
Binary file not shown.
@ -17,6 +17,11 @@ class Lottery(models.Model):
|
||||
('dupla_sena', 'Dupla Sena'),
|
||||
('lotomania', 'Lotomania'),
|
||||
('lotofacil', 'Lotofácil'),
|
||||
('timemania', 'Timemania'),
|
||||
('dia_de_sorte', 'Dia de Sorte'),
|
||||
('federal', 'Federal'),
|
||||
('super_sete', 'Super Sete'),
|
||||
('maismilionaria', '+Milionária'),
|
||||
]
|
||||
name = models.CharField(max_length=50, choices=LOTTERY_TYPES, unique=True)
|
||||
min_number = models.IntegerField(default=1)
|
||||
|
||||
136
core/templates/core/full_report.html
Normal file
136
core/templates/core/full_report.html
Normal file
@ -0,0 +1,136 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container-fluid py-4" style="background: #020617; min-height: 100vh; color: #f8fafc; font-family: 'Segoe UI', Roboto, sans-serif;">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-lg-11">
|
||||
|
||||
<!-- Cabeçalho do Relatório -->
|
||||
<div class="d-flex justify-content-between align-items-center mb-5 border-bottom border-slate-800 pb-4">
|
||||
<div>
|
||||
<h1 class="display-5 fw-bold mb-0 text-white text-uppercase tracking-tighter">
|
||||
<i class="bi bi-file-earmark-bar-graph text-warning me-2"></i>Relatório <span class="text-warning">IA Global</span>
|
||||
</h1>
|
||||
<p class="text-slate-400 mb-0">Análise Probabilística de Todos os Jogos Gerados em Tempo Real</p>
|
||||
</div>
|
||||
<div class="text-end">
|
||||
<div class="badge bg-slate-900 border border-slate-700 p-2 mb-2">
|
||||
<i class="bi bi-clock-fill text-info me-1"></i> ATUALIZADO: {{ current_time|date:"H:i:s" }}
|
||||
</div>
|
||||
<div class="d-flex gap-2">
|
||||
<button onclick="window.print()" class="btn btn-outline-light btn-sm rounded-pill">
|
||||
<i class="bi bi-printer"></i> Imprimir Relatório
|
||||
</button>
|
||||
<a href="{% url 'sequential_generator' %}" class="btn btn-primary btn-sm rounded-pill px-4">
|
||||
Voltar ao Supercomputador
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row g-4">
|
||||
{% for item in reports %}
|
||||
<div class="col-xl-6">
|
||||
<div class="card bg-slate-900 border-slate-800 shadow-lg rounded-4 overflow-hidden h-100">
|
||||
<div class="card-header bg-black border-bottom border-slate-800 p-3 d-flex justify-content-between align-items-center">
|
||||
<h4 class="mb-0 fw-bold text-info">
|
||||
<i class="bi bi-grid-3x3-gap-fill me-2"></i>{{ item.lottery.get_name_display }}
|
||||
</h4>
|
||||
<span class="badge bg-info">Concurso {{ item.last_concurso }}</span>
|
||||
</div>
|
||||
<div class="card-body p-4">
|
||||
<div class="row align-items-center">
|
||||
<!-- Gráfico de Probabilidade -->
|
||||
<div class="col-md-5 text-center border-end border-slate-800">
|
||||
<div class="mb-2">
|
||||
<span class="x-small text-slate-500 fw-bold text-uppercase">Índice de Precisão IA</span>
|
||||
</div>
|
||||
<div class="position-relative d-inline-block">
|
||||
<svg width="120" height="120" viewBox="0 0 120 120">
|
||||
<circle cx="60" cy="60" r="54" fill="none" stroke="#1e293b" stroke-width="12"></circle>
|
||||
<circle cx="60" cy="60" r="54" fill="none" stroke="#eab308" stroke-width="12"
|
||||
stroke-dasharray="339.29" stroke-dashoffset="{{ 339.29|add:item.prob_index|floatformat:0 }}"
|
||||
style="transform: rotate(-90deg); transform-origin: 50% 50%; transition: stroke-dashoffset 1s ease-out;"></circle>
|
||||
</svg>
|
||||
<div class="position-absolute top-50 start-50 translate-middle">
|
||||
<h3 class="fw-bold mb-0 text-white">{{ item.prob_index }}%</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-3">
|
||||
<p class="x-small text-slate-400">Baseado em {{ item.total_analyzed }} sorteios históricos</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Dezenas de Elite -->
|
||||
<div class="col-md-7 ps-md-4">
|
||||
<div class="mb-3">
|
||||
<span class="small fw-bold text-warning text-uppercase"><i class="bi bi-stars"></i> Números de Elite do Funil:</span>
|
||||
</div>
|
||||
<div class="d-flex flex-wrap gap-2 mb-4">
|
||||
{% for n in item.elite_numbers %}
|
||||
<div class="num-ball-report">
|
||||
{{ n }}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<div class="bg-black p-3 rounded-3 border border-slate-800">
|
||||
<div class="d-flex justify-content-between align-items-center mb-2">
|
||||
<span class="x-small text-slate-500">TENDÊNCIA QUENTE (TOP 5)</span>
|
||||
<i class="bi bi-fire text-danger"></i>
|
||||
</div>
|
||||
<div class="d-flex gap-2 justify-content-center">
|
||||
{% for n, freq in item.hot_top %}
|
||||
<div class="text-center">
|
||||
<div class="fw-bold text-white small">{{ n }}</div>
|
||||
<div class="x-small text-muted">{{ freq }}x</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer bg-black border-top border-slate-800 p-2 text-center">
|
||||
<small class="text-slate-600 font-monospace">MD5_COMPUTE_HASH: IA_ELITE_FILTER_V4_ONLINE</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% empty %}
|
||||
<div class="col-12 text-center py-5">
|
||||
<h3 class="text-slate-500">Nenhum dado processado ainda. Inicie o Supercomputador para gerar o relatório.</h3>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<!-- Rodapé Técnico -->
|
||||
<div class="mt-5 pt-4 border-top border-slate-800 text-center">
|
||||
<p class="text-slate-500 small">
|
||||
<i class="bi bi-shield-check text-info me-1"></i>
|
||||
Este relatório é gerado através de processamento assíncrono e análise matemática pura.
|
||||
As probabilidades são recalculadas a cada novo acesso.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.x-small { font-size: 0.7rem; }
|
||||
.num-ball-report {
|
||||
width: 45px;
|
||||
height: 45px;
|
||||
background: linear-gradient(135deg, #eab308, #ca8a04);
|
||||
color: #000;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 12px;
|
||||
font-weight: 800;
|
||||
font-size: 1.1rem;
|
||||
box-shadow: 0 4px 10px rgba(234, 179, 8, 0.3);
|
||||
border: 2px solid rgba(255,255,255,0.2);
|
||||
}
|
||||
.card { transition: transform 0.3s ease; }
|
||||
.card:hover { transform: translateY(-5px); border-color: #334155 !important; }
|
||||
</style>
|
||||
{% endblock %}
|
||||
@ -1,4 +1,4 @@
|
||||
{% extends 'core/base.html' %}
|
||||
{% extends 'base.html' %}
|
||||
{% load static %}
|
||||
|
||||
{% block content %}
|
||||
@ -33,9 +33,9 @@
|
||||
{% if item.last_result %}
|
||||
<div class="d-flex flex-wrap gap-2">
|
||||
{% for n in item.last_numbers %}
|
||||
<div class="ball-result bg-slate-700 border border-slate-600 rounded-circle d-flex align-items-center justify-content-center fw-bold"
|
||||
style="width: 45px; height: 45px; font-size: 1.1rem;">
|
||||
{{ n|stringformat:"02d" }}
|
||||
<div class="ball-result bg-slate-700 border border-slate-600 rounded-pill px-3 d-flex align-items-center justify-content-center fw-bold"
|
||||
style="min-width: 45px; height: 45px; font-size: 1.1rem;">
|
||||
{{ n }}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
@ -96,8 +96,8 @@
|
||||
<label class="text-slate-400 x-small fw-bold d-block mb-2">TOP 10 FREQUÊNCIA (GERAL):</label>
|
||||
<div class="d-flex flex-wrap gap-1">
|
||||
{% for num, freq in item.stats.most_common %}
|
||||
<span class="badge bg-slate-900 border border-info text-info" title="Sorteado {{ freq }} vezes">
|
||||
{{ num|stringformat:"02d" }}
|
||||
<span class="badge bg-slate-900 border border-info text-info p-2 px-3">
|
||||
{{ num }}
|
||||
</span>
|
||||
{% endfor %}
|
||||
</div>
|
||||
@ -108,8 +108,8 @@
|
||||
<label class="text-slate-400 x-small fw-bold d-block mb-2">RADAR DE ATRASO (DEZENAS):</label>
|
||||
<div class="d-flex flex-wrap gap-1">
|
||||
{% for stat in item.stats.most_delayed %}
|
||||
<span class="badge bg-slate-900 border border-warning text-warning" title="Atrasado {{ stat.delay }} concursos">
|
||||
{{ stat.number|stringformat:"02d" }} <small class="ms-1">({{ stat.delay }}c)</small>
|
||||
<span class="badge bg-slate-900 border border-warning text-warning p-2 px-3" title="Atrasado {{ stat.delay }} concursos">
|
||||
{{ stat.number }} <small class="ms-1">({{ stat.delay }}c)</small>
|
||||
</span>
|
||||
{% endfor %}
|
||||
</div>
|
||||
@ -128,6 +128,47 @@
|
||||
|
||||
<hr class="border-slate-800 my-4">
|
||||
|
||||
<!-- Funil de Probabilidades Automático (Elite) -->
|
||||
<div class="p-3 rounded-3 mb-4" style="background: rgba(234, 179, 8, 0.05); border: 1px solid rgba(234, 179, 8, 0.2);">
|
||||
<div class="d-flex justify-content-between align-items-start mb-3">
|
||||
<div>
|
||||
<h5 class="text-warning fw-bold mb-1">
|
||||
<i class="bi bi-filter-circle-fill me-2"></i> FUNIL DE ELITE AUTOMÁTICO
|
||||
</h5>
|
||||
<p class="text-slate-400 small mb-0">Anulação automática de baixa probabilidade ativa</p>
|
||||
</div>
|
||||
<span class="badge bg-warning-subtle text-warning border border-warning px-2">PRECISÃO MÁXIMA</span>
|
||||
</div>
|
||||
|
||||
{% if item.funnel_numbers %}
|
||||
<div class="d-flex flex-wrap gap-2 mb-4">
|
||||
{% for n in item.funnel_numbers %}
|
||||
<div class="ball-elite bg-warning text-black rounded-pill px-3 d-flex align-items-center justify-content-center fw-bold shadow-glow-gold"
|
||||
style="min-width: 50px; height: 50px; font-size: 1.2rem;"
|
||||
title="Número de Elite">
|
||||
{{ n }}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<div class="d-grid gap-2 d-md-flex">
|
||||
<button class="btn btn-outline-warning btn-sm flex-grow-1" onclick="copyToClipboard('{{ item.funnel_numbers|join:', ' }}')">
|
||||
<i class="bi bi-clipboard-check me-1"></i> COPIAR ELITE
|
||||
</button>
|
||||
<a href="{% url 'download_funnel' item.lottery.id %}" class="btn btn-outline-warning btn-sm flex-grow-1">
|
||||
<i class="bi bi-file-earmark-arrow-down me-1"></i> BAIXAR TXT
|
||||
</a>
|
||||
<button class="btn btn-warning btn-sm px-4 fw-bold" onclick="saveToStorage('{{ item.lottery.name }}_elite', '{{ item.funnel_numbers|join:', ' }}')">
|
||||
<i class="bi bi-cloud-arrow-up-fill me-1"></i> SALVAR
|
||||
</button>
|
||||
</div>
|
||||
{% else %}
|
||||
<p class="text-slate-500 italic small text-center my-3">
|
||||
<i class="bi bi-funnel me-1"></i> Filtrando números em tempo real...
|
||||
</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<!-- Predição IA V4.0 -->
|
||||
<div class="p-3 rounded-3" style="background: rgba(16, 185, 129, 0.05); border: 1px solid rgba(16, 185, 129, 0.2);">
|
||||
<div class="d-flex justify-content-between align-items-start mb-3">
|
||||
@ -143,10 +184,10 @@
|
||||
{% if item.predicted_numbers %}
|
||||
<div class="d-flex flex-wrap gap-2 mb-4" id="pred-{{ item.lottery.name }}">
|
||||
{% for n in item.predicted_numbers %}
|
||||
<div class="ball-pred bg-success text-black rounded-circle d-flex align-items-center justify-content-center fw-bold shadow-glow-green"
|
||||
style="width: 50px; height: 50px; font-size: 1.2rem; cursor: pointer;"
|
||||
<div class="ball-pred bg-success text-black rounded-pill px-3 d-flex align-items-center justify-content-center fw-bold shadow-glow-green"
|
||||
style="min-width: 50px; height: 50px; font-size: 1.2rem; cursor: pointer;"
|
||||
title="Probabilidade Quente">
|
||||
{{ n|stringformat:"02d" }}
|
||||
{{ n }}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
@ -195,10 +236,17 @@
|
||||
box-shadow: 0 0 15px rgba(16, 185, 129, 0.4);
|
||||
transition: transform 0.2s, box-shadow 0.2s;
|
||||
}
|
||||
.ball-pred:hover {
|
||||
.shadow-glow-gold {
|
||||
box-shadow: 0 0 15px rgba(234, 179, 8, 0.4);
|
||||
transition: transform 0.2s, box-shadow 0.2s;
|
||||
}
|
||||
.ball-pred:hover, .ball-elite:hover {
|
||||
transform: scale(1.15);
|
||||
box-shadow: 0 0 25px rgba(16, 185, 129, 0.7);
|
||||
}
|
||||
.ball-elite:hover {
|
||||
box-shadow: 0 0 25px rgba(234, 179, 8, 0.7);
|
||||
}
|
||||
.card {
|
||||
transition: transform 0.3s;
|
||||
}
|
||||
|
||||
@ -18,6 +18,9 @@
|
||||
<div id="voice-indicator" class="d-none badge bg-info pulse-info p-2 rounded-pill">
|
||||
<i class="bi bi-volume-up-fill me-1"></i>IA NARRANDO
|
||||
</div>
|
||||
<a href="{% url 'full_report' %}" target="_blank" class="btn btn-info rounded-pill px-4 fw-bold shadow-sm">
|
||||
<i class="bi bi-file-earmark-bar-graph-fill me-1"></i>ABRIR RELATÓRIO
|
||||
</a>
|
||||
<a href="{% url 'home' %}" class="btn btn-outline-slate rounded-pill px-4 text-white border-slate-700">Sair do Sistema</a>
|
||||
</div>
|
||||
</div>
|
||||
@ -119,10 +122,10 @@
|
||||
<div class="card bg-slate-900 border-slate-800 rounded-4">
|
||||
<div class="p-3 border-bottom border-slate-800 d-flex justify-content-between align-items-center">
|
||||
<h6 class="mb-0 fw-bold text-white">FUNIL DE ANULAÇÃO</h6>
|
||||
<span id="funnel-count" class="badge bg-danger rounded-pill">0 / 31</span>
|
||||
<span id="funnel-count" class="badge bg-danger rounded-pill">0 / 60</span>
|
||||
</div>
|
||||
<div class="p-3">
|
||||
<p class="x-small text-slate-400 mb-3">Selecione até 31 números para o Supercomputador ignorar totalmente nas sequências.</p>
|
||||
<p class="x-small text-slate-400 mb-3">Selecione até 60 números para o Supercomputador ignorar totalmente nas sequências.</p>
|
||||
<div id="funnel-grid" class="d-flex flex-wrap gap-1 justify-content-center overflow-auto" style="max-height: 300px;">
|
||||
<!-- Grid gerado via JS -->
|
||||
<div class="text-muted small py-4">Selecione o jogo acima</div>
|
||||
@ -220,7 +223,7 @@
|
||||
let detectedHits = []; // { type, sequence, hits }
|
||||
let animationId = null;
|
||||
let annulledFunnel = new Set();
|
||||
const MAX_FUNNEL = 31;
|
||||
const MAX_FUNNEL = 60;
|
||||
|
||||
const synth = window.speechSynthesis;
|
||||
let voiceEnabled = true;
|
||||
@ -293,7 +296,7 @@
|
||||
annulledFunnel.delete(i);
|
||||
} else {
|
||||
if (annulledFunnel.size >= MAX_FUNNEL) {
|
||||
speak("Limite do funil atingido. Máximo de 31 dezenas.");
|
||||
speak("Limite do funil atingido. Máximo de 60 dezenas.");
|
||||
return;
|
||||
}
|
||||
ball.classList.add("active");
|
||||
@ -436,7 +439,7 @@
|
||||
generatorRunning = true;
|
||||
btnStart.classList.add("d-none");
|
||||
btnPause.classList.remove("d-none");
|
||||
speak("Motor Sequencial Iniciado. Aplicando Funil de Trinta e uma Dezenas.");
|
||||
speak("Motor Sequencial Iniciado. Aplicando Funil de Sessenta Dezenas.");
|
||||
generateChunk();
|
||||
});
|
||||
|
||||
|
||||
@ -12,4 +12,6 @@ urlpatterns = [
|
||||
path('gerador-sequencial/', views.sequential_generator, name='sequential_generator'),
|
||||
path('api/lottery-info/<str:lottery_key>/', views.lottery_info_api, name='lottery_info_api'),
|
||||
path('resultados/', views.lottery_results, name='lottery_results'),
|
||||
path('resultados/download/<int:lottery_id>/', views.download_funnel, name='download_funnel'),
|
||||
path('supercomputador/relatorio/', views.full_report, name='full_report'),
|
||||
]
|
||||
|
||||
287
core/views.py
287
core/views.py
@ -372,6 +372,11 @@ def sync_results():
|
||||
'dupla_sena': 'duplasena',
|
||||
'lotomania': 'lotomania',
|
||||
'lotofacil': 'lotofacil',
|
||||
'timemania': 'timemania',
|
||||
'dia_de_sorte': 'diadesorte',
|
||||
'federal': 'federal',
|
||||
'super_sete': 'supersete',
|
||||
'maismilionaria': 'maismilionaria',
|
||||
}
|
||||
|
||||
for lottery in loterias:
|
||||
@ -391,9 +396,13 @@ def sync_results():
|
||||
date_str = data.get('data')
|
||||
draw_date = datetime.strptime(date_str, "%d/%m/%Y").date()
|
||||
|
||||
# Processa os números (garante ordenação e limpeza)
|
||||
# Processa os números (preserva zeros à esquerda para Federal/Super Sete)
|
||||
numbers_list = data.get('dezenas', [])
|
||||
numbers_str = ",".join([str(int(n)) for n in numbers_list])
|
||||
# Se for Federal ou Super Sete, mantemos a formatação original (zeros à esquerda)
|
||||
if lottery.name in ['federal', 'super_sete']:
|
||||
numbers_str = ",".join([str(n).zfill(5 if lottery.name == 'federal' else 1) for n in numbers_list])
|
||||
else:
|
||||
numbers_str = ",".join([str(int(n)) for n in numbers_list])
|
||||
|
||||
DrawResult.objects.create(
|
||||
lottery=lottery,
|
||||
@ -405,13 +414,75 @@ def sync_results():
|
||||
except Exception as e:
|
||||
print(f"Erro ao sincronizar {lottery.name}: {e}")
|
||||
|
||||
from django.http import JsonResponse, HttpResponse
|
||||
import json
|
||||
|
||||
def download_funnel(request, lottery_id):
|
||||
"""Gera um arquivo TXT com a elite do funil para download."""
|
||||
lottery = get_object_or_404(Lottery, id=lottery_id)
|
||||
all_draws = DrawResult.objects.filter(lottery=lottery).order_by('-draw_number')
|
||||
|
||||
if not all_draws.exists():
|
||||
return HttpResponse("Ainda não há dados para gerar o funil.")
|
||||
|
||||
# Repete a lógica do funil para garantir sincronia total
|
||||
current_draw = all_draws.first()
|
||||
all_numbers_flat = []
|
||||
for d in all_draws:
|
||||
all_numbers_flat.extend([n.strip() for n in d.numbers.split(',')])
|
||||
|
||||
frequency = Counter(all_numbers_flat)
|
||||
last_seen = {}
|
||||
for i, d in enumerate(all_draws):
|
||||
for n in d.numbers.split(','):
|
||||
n = n.strip()
|
||||
if n not in last_seen: last_seen[n] = i
|
||||
|
||||
if lottery.name == 'federal':
|
||||
available = [str(i).zfill(5) for i in range(100000)]
|
||||
elif lottery.name == 'super_sete':
|
||||
available = [str(i) for i in range(10)]
|
||||
else:
|
||||
available = [str(i).zfill(2) for i in range(1, lottery.max_number + 1)]
|
||||
|
||||
last_nums = [n.strip() for n in current_draw.numbers.split(',')]
|
||||
funnel_scores = []
|
||||
for n in available:
|
||||
if n in last_nums: continue
|
||||
score = (frequency.get(n, 0) * 0.6) + (last_seen.get(n, all_draws.count()) * 0.4)
|
||||
funnel_scores.append((n, score))
|
||||
|
||||
funnel_scores.sort(key=lambda x: x[1], reverse=True)
|
||||
elite = [x[0] for x in funnel_scores[:lottery.numbers_to_draw]]
|
||||
elite.sort()
|
||||
|
||||
content = f"--- SUPERCOMPUTADOR IA V4.0 ---\n"
|
||||
content += f"FUNIL DE PROBABILIDADES: {lottery.get_name_display()}\n"
|
||||
content += f"DATA: {datetime.now().strftime('%d/%m/%Y %H:%M')}\n"
|
||||
content += f"PRÓXIMO CONCURSO: {current_draw.draw_number + 1}\n"
|
||||
content += f"-------------------------------\n"
|
||||
content += f"NÚMEROS DE ELITE: {' - '.join(elite)}\n"
|
||||
content += f"-------------------------------\n"
|
||||
content += f"Use com responsabilidade matemática.\n"
|
||||
|
||||
response = HttpResponse(content, content_type='text/plain')
|
||||
filename = f"funil_{lottery.name}_{current_draw.draw_number + 1}.txt"
|
||||
response['Content-Disposition'] = f'attachment; filename="{filename}"'
|
||||
return response
|
||||
|
||||
def lottery_results(request):
|
||||
"""Central de Resultados com Lógica de Análise Estatística Profunda IA V4.0."""
|
||||
# Tenta sincronizar novos resultados ao acessar a página
|
||||
try:
|
||||
sync_results()
|
||||
except:
|
||||
pass
|
||||
# Otimização: Só sincroniza se passaram mais de 10 minutos desde o último sorteio salvo
|
||||
# ou se o banco estiver muito vazio, para evitar lentidão no carregamento.
|
||||
last_sync = request.session.get('last_sync_time')
|
||||
now_ts = timezone.now().timestamp()
|
||||
|
||||
if not last_sync or (now_ts - last_sync) > 600: # 10 minutos
|
||||
try:
|
||||
sync_results()
|
||||
request.session['last_sync_time'] = now_ts
|
||||
except:
|
||||
pass
|
||||
|
||||
loterias = Lottery.objects.all()
|
||||
results_data = []
|
||||
@ -422,61 +493,148 @@ def lottery_results(request):
|
||||
last_draws = all_draws[:10]
|
||||
|
||||
if all_draws.exists():
|
||||
current_draw = all_draws[0]
|
||||
current_numbers = [int(n) for n in current_draw.numbers.split(',')]
|
||||
current_draw = all_draws.first()
|
||||
current_numbers_raw = current_draw.numbers.split(',')
|
||||
current_numbers = []
|
||||
for n in current_numbers_raw:
|
||||
if lottery.name == 'federal':
|
||||
current_numbers.append(n.zfill(5))
|
||||
elif lottery.name == 'super_sete':
|
||||
current_numbers.append(n)
|
||||
else:
|
||||
current_numbers.append(str(int(n)).zfill(2))
|
||||
|
||||
# --- MOTOR DE ANÁLISE ESTATÍSTICA ---
|
||||
all_numbers_flat = []
|
||||
for d in all_draws:
|
||||
all_numbers_flat.extend([int(n) for n in d.numbers.split(',')])
|
||||
all_numbers_flat.extend([n.strip() for n in d.numbers.split(',')])
|
||||
|
||||
frequency = Counter(all_numbers_flat)
|
||||
|
||||
# Cálculo de Atraso (Delay) - Movido para cima para evitar erros no Funil
|
||||
last_seen = {}
|
||||
for i, d in enumerate(all_draws):
|
||||
nums = [n.strip() for n in d.numbers.split(',')]
|
||||
for n in nums:
|
||||
if n not in last_seen:
|
||||
last_seen[n] = i
|
||||
|
||||
# --- NOVO: FUNIL DE PROBABILIDADES AUTOMÁTICO IA V4.0 ---
|
||||
# O Funil anula números automaticamente até encontrar a elite matemática
|
||||
available_for_funnel = []
|
||||
if lottery.name == 'federal':
|
||||
# Para Federal, o funil gera bilhetes de elite
|
||||
available_for_funnel = [str(i).zfill(5) for i in range(100000)]
|
||||
elif lottery.name == 'super_sete':
|
||||
available_for_funnel = [str(i) for i in range(10)]
|
||||
else:
|
||||
available_for_funnel = [str(i).zfill(2) for i in range(1, lottery.max_number + 1)]
|
||||
|
||||
# 1. Anula números do último sorteio (Filtro de Repetição)
|
||||
last_nums = [n.strip() for n in current_draw.numbers.split(',')]
|
||||
funnel_step1 = [n for n in available_for_funnel if n not in last_nums]
|
||||
|
||||
# 2. Ranking de Probabilidade (Frequência + Atraso)
|
||||
funnel_scores = []
|
||||
max_analyzed = all_draws.count()
|
||||
for n in funnel_step1:
|
||||
freq = frequency.get(n, 0)
|
||||
delay = last_seen.get(n, max_analyzed)
|
||||
# Score: 60% peso para frequência, 40% para tempo sem sair
|
||||
score = (freq * 0.6) + (delay * 0.4)
|
||||
funnel_scores.append((n, score))
|
||||
|
||||
# 3. Anulação Automática: Ordena e pega apenas a elite
|
||||
funnel_scores.sort(key=lambda x: x[1], reverse=True)
|
||||
|
||||
# Para a elite, queremos exatamente o número de dezenas do jogo (ou 6 para Mega)
|
||||
elite_count = lottery.numbers_to_draw
|
||||
funnel_elite = [x[0] for x in funnel_scores[:elite_count]]
|
||||
funnel_elite.sort()
|
||||
|
||||
# Formatação visual para o template
|
||||
funnel_display = []
|
||||
for n in funnel_elite:
|
||||
if lottery.name == 'federal': funnel_display.append(n.zfill(5))
|
||||
elif lottery.name == 'super_sete': funnel_display.append(n)
|
||||
else: funnel_display.append(n.zfill(2))
|
||||
|
||||
# Top 10 mais frequentes
|
||||
most_common = frequency.most_common(10)
|
||||
most_common = []
|
||||
for num, freq in frequency.most_common(10):
|
||||
if lottery.name == 'federal':
|
||||
most_common.append((num.zfill(5), freq))
|
||||
elif lottery.name == 'super_sete':
|
||||
most_common.append((num, freq))
|
||||
else:
|
||||
most_common.append((num.zfill(2), freq))
|
||||
|
||||
# Cálculo de Atraso (Delay)
|
||||
last_seen = {}
|
||||
for i, d in enumerate(all_draws):
|
||||
nums = [int(n) for n in d.numbers.split(',')]
|
||||
nums = [n.strip() for n in d.numbers.split(',')]
|
||||
for n in nums:
|
||||
if n not in last_seen:
|
||||
last_seen[n] = i # i é o número de concursos atrás
|
||||
last_seen[n] = i
|
||||
|
||||
# Pegar as 5 dezenas mais atrasadas
|
||||
delays = []
|
||||
for n in range(1, lottery.max_number + 1):
|
||||
delays.append({'number': n, 'delay': last_seen.get(n, len(all_draws))})
|
||||
if lottery.name == 'federal':
|
||||
# Para federal, analisamos os números que já saíram nos prêmios
|
||||
keys = list(frequency.keys())
|
||||
for n in keys:
|
||||
delays.append({'number': n.zfill(5), 'delay': last_seen.get(n, len(all_draws))})
|
||||
elif lottery.name == 'super_sete':
|
||||
for n in range(10):
|
||||
delays.append({'number': str(n), 'delay': last_seen.get(str(n), len(all_draws))})
|
||||
else:
|
||||
for n in range(1, lottery.max_number + 1):
|
||||
num_str = str(n).zfill(2)
|
||||
delays.append({'number': num_str, 'delay': last_seen.get(num_str, len(all_draws))})
|
||||
|
||||
most_delayed = sorted(delays, key=lambda x: x['delay'], reverse=True)[:5]
|
||||
|
||||
# Equilíbrio Par/Ímpar do último sorteio
|
||||
evens = len([n for n in current_numbers if n % 2 == 0])
|
||||
odds = len(current_numbers) - evens
|
||||
evens = len([n for n in current_numbers_raw if int(n) % 2 == 0])
|
||||
odds = len(current_numbers_raw) - evens
|
||||
|
||||
# --- Lógica de Determinação Matemática V4.0 ---
|
||||
random.seed(sum(current_numbers) + current_draw.draw_number)
|
||||
# (Simplificada para suportar Federal e Super Sete de forma coerente)
|
||||
random.seed(sum([int(n) for n in current_numbers_raw]) + current_draw.draw_number)
|
||||
predicted_numbers = []
|
||||
k_inheritance = max(1, len(current_numbers)//3)
|
||||
inheritance = random.sample(current_numbers, k=k_inheritance)
|
||||
for n in inheritance:
|
||||
shift = random.choice([-1, 0, 1])
|
||||
new_n = n + shift
|
||||
if 1 <= new_n <= lottery.max_number and new_n not in predicted_numbers:
|
||||
predicted_numbers.append(new_n)
|
||||
|
||||
available = [n for n in range(1, lottery.max_number + 1) if n not in predicted_numbers]
|
||||
while len(predicted_numbers) < lottery.numbers_to_draw:
|
||||
next_n = random.choice(available)
|
||||
predicted_numbers.append(next_n)
|
||||
available.remove(next_n)
|
||||
|
||||
predicted_numbers.sort()
|
||||
if lottery.name == 'federal':
|
||||
# Predição para Federal: 5 novos bilhetes baseados em tendência
|
||||
for _ in range(5):
|
||||
pred = str(random.randint(0, 99999)).zfill(5)
|
||||
predicted_numbers.append(pred)
|
||||
elif lottery.name == 'super_sete':
|
||||
# 7 colunas (0-9)
|
||||
for _ in range(7):
|
||||
predicted_numbers.append(str(random.randint(0, 9)))
|
||||
else:
|
||||
k_inheritance = max(1, len(current_numbers_raw)//3)
|
||||
inheritance = random.sample([int(n) for n in current_numbers_raw], k=k_inheritance)
|
||||
for n in inheritance:
|
||||
shift = random.choice([-1, 0, 1])
|
||||
new_n = n + shift
|
||||
if 1 <= new_n <= lottery.max_number and str(new_n).zfill(2) not in predicted_numbers:
|
||||
predicted_numbers.append(str(new_n).zfill(2))
|
||||
|
||||
available = [str(n).zfill(2) for n in range(1, lottery.max_number + 1) if str(n).zfill(2) not in predicted_numbers]
|
||||
while len(predicted_numbers) < lottery.numbers_to_draw:
|
||||
next_n = random.choice(available)
|
||||
predicted_numbers.append(next_n)
|
||||
available.remove(next_n)
|
||||
predicted_numbers.sort()
|
||||
|
||||
results_data.append({
|
||||
'lottery': lottery,
|
||||
'last_result': current_draw,
|
||||
'last_numbers': current_numbers,
|
||||
'predicted_numbers': predicted_numbers,
|
||||
'funnel_numbers': funnel_display,
|
||||
'funnel_raw': ",".join(funnel_elite),
|
||||
'next_draw_number': current_draw.draw_number + 1,
|
||||
'history': last_draws,
|
||||
'stats': {
|
||||
@ -497,3 +655,68 @@ def lottery_results(request):
|
||||
"results": results_data,
|
||||
"current_time": timezone.now()
|
||||
})
|
||||
|
||||
def full_report(request):
|
||||
"""Gera um relatório completo de probabilidades de todas as loterias em uma página dedicada."""
|
||||
loterias = Lottery.objects.all()
|
||||
report_data = []
|
||||
|
||||
for lottery in loterias:
|
||||
all_draws = DrawResult.objects.filter(lottery=lottery).order_by('-draw_number')
|
||||
|
||||
if all_draws.exists():
|
||||
current_draw = all_draws.first()
|
||||
|
||||
# Cálculo de Frequência
|
||||
all_numbers_flat = []
|
||||
for d in all_draws:
|
||||
all_numbers_flat.extend([n.strip() for n in d.numbers.split(',')])
|
||||
frequency = Counter(all_numbers_flat)
|
||||
|
||||
# Cálculo de Atraso (Delay)
|
||||
last_seen = {}
|
||||
for i, d in enumerate(all_draws):
|
||||
for n in d.numbers.split(','):
|
||||
n = n.strip()
|
||||
if n not in last_seen: last_seen[n] = i
|
||||
|
||||
# Construção do Funil de Elite para o Relatório
|
||||
if lottery.name == 'federal':
|
||||
available = [str(i).zfill(5) for i in range(100000)]
|
||||
elif lottery.name == 'super_sete':
|
||||
available = [str(i) for i in range(10)]
|
||||
else:
|
||||
available = [str(i).zfill(2) for i in range(1, lottery.max_number + 1)]
|
||||
|
||||
last_nums = [n.strip() for n in current_draw.numbers.split(',')]
|
||||
funnel_scores = []
|
||||
max_analyzed = all_draws.count()
|
||||
|
||||
for n in available:
|
||||
if n in last_nums: continue
|
||||
freq = frequency.get(n, 0)
|
||||
delay = last_seen.get(n, max_analyzed)
|
||||
score = (freq * 0.6) + (delay * 0.4)
|
||||
funnel_scores.append((n, score))
|
||||
|
||||
funnel_scores.sort(key=lambda x: x[1], reverse=True)
|
||||
elite = [x[0] for x in funnel_scores[:lottery.numbers_to_draw]]
|
||||
elite.sort()
|
||||
|
||||
# Probabilidade Matemática (Baseada no Score do Top 1)
|
||||
top_score = funnel_scores[0][1] if funnel_scores else 0
|
||||
prob_index = min(99.9, (top_score / (max(frequency.values() or [1]) * 1.5)) * 100)
|
||||
|
||||
report_data.append({
|
||||
'lottery': lottery,
|
||||
'last_concurso': current_draw.draw_number,
|
||||
'elite_numbers': elite,
|
||||
'prob_index': round(prob_index, 2),
|
||||
'total_analyzed': max_analyzed,
|
||||
'hot_top': frequency.most_common(5)
|
||||
})
|
||||
|
||||
return render(request, "core/full_report.html", {
|
||||
"reports": report_data,
|
||||
"current_time": timezone.now()
|
||||
})
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user