ESPECIFICAÇOES 1
This commit is contained in:
parent
928c0dddfd
commit
28516985ed
@ -1,96 +1,122 @@
|
|||||||
{% extends "base.html" %}
|
{% extends "base.html" %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="container-fluid py-4" style="background: #0f172a; min-height: 100vh; color: #f8fafc;">
|
<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="row justify-content-center">
|
||||||
<div class="col-lg-10">
|
<div class="col-lg-11">
|
||||||
<div class="card bg-slate-800 border-0 shadow-lg p-4" style="background: #1e293b; border-radius: 20px;">
|
<div class="card border-0 shadow-lg p-4" style="background: #0f172a; border-radius: 24px; border: 1px solid #1e293b !important;">
|
||||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
|
||||||
|
<!-- Cabeçalho de Supercomputador -->
|
||||||
|
<div class="d-flex justify-content-between align-items-center mb-4 border-bottom border-slate-800 pb-3">
|
||||||
<div>
|
<div>
|
||||||
<h2 class="display-6 fw-bold mb-0 text-white">Gerador Sequencial Inteligente IA</h2>
|
<h2 class="display-6 fw-bold mb-0 text-white text-uppercase tracking-tighter">
|
||||||
<p class="text-slate-400">Motor Autônomo de Probabilidades Matemáticas</p>
|
<i class="bi bi-cpu-fill text-info me-2"></i>Supercomputador <span class="text-info">IA v4.0</span>
|
||||||
|
</h2>
|
||||||
|
<p class="text-slate-400 mb-0">Análise Matemática Autônoma em Tempo Real</p>
|
||||||
</div>
|
</div>
|
||||||
<a href="{% url 'home' %}" class="btn btn-outline-light rounded-pill px-4">Voltar ao Início</a>
|
<div class="d-flex gap-3 align-items-center">
|
||||||
</div>
|
<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 class="row g-3 mb-4">
|
</div>
|
||||||
<div class="col-md-4">
|
<a href="{% url 'home' %}" class="btn btn-outline-slate rounded-pill px-4 text-white border-slate-700">Sair do Sistema</a>
|
||||||
<label class="form-label text-slate-300">Selecione a Loteria:</label>
|
|
||||||
<select id="lottery-select" class="form-select bg-slate-900 text-white border-slate-700 shadow-none">
|
|
||||||
<option value="">--- Selecione ---</option>
|
|
||||||
{% for l in loterias %}
|
|
||||||
<option value="{{ l.name }}">{{ l.get_name_display }}</option>
|
|
||||||
{% endfor %}
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div class="col-md-8 d-flex align-items-end gap-2">
|
|
||||||
<button id="btn-start" class="btn btn-success btn-lg flex-grow-1 rounded-pill fw-bold shadow-sm" disabled>
|
|
||||||
<i class="bi bi-play-fill"></i> INICIAR
|
|
||||||
</button>
|
|
||||||
<button id="btn-pause" class="btn btn-warning btn-lg flex-grow-1 rounded-pill fw-bold shadow-sm d-none">
|
|
||||||
<i class="bi bi-pause-fill"></i> PAUSAR
|
|
||||||
</button>
|
|
||||||
<button id="btn-up" class="btn btn-secondary btn-lg rounded-circle shadow-sm">
|
|
||||||
<i class="bi bi-arrow-up"></i>
|
|
||||||
</button>
|
|
||||||
<button id="btn-down" class="btn btn-secondary btn-lg rounded-circle shadow-sm">
|
|
||||||
<i class="bi bi-arrow-down"></i>
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Barra de Stats IA -->
|
<div class="row g-4">
|
||||||
<div id="stats-bar" class="row g-2 mb-4 d-none">
|
<!-- Coluna Esquerda: Controles e Gerador -->
|
||||||
<div class="col-md-3">
|
<div class="col-lg-8">
|
||||||
<div class="p-3 rounded bg-slate-900 text-center border-start border-success border-4">
|
<div class="row g-3 mb-4">
|
||||||
<small class="d-block text-muted">Sequências Geradas</small>
|
<div class="col-md-5">
|
||||||
<span id="count-total" class="h4 fw-bold">0</span>
|
<label class="form-label text-slate-300 small fw-bold">LOTERIA ALVO:</label>
|
||||||
|
<select id="lottery-select" class="form-select bg-slate-900 text-white border-slate-700 shadow-none py-2">
|
||||||
|
<option value="">--- Selecione o Jogo ---</option>
|
||||||
|
{% for l in loterias %}
|
||||||
|
<option value="{{ l.name }}">{{ l.get_name_display }}</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-7 d-flex align-items-end gap-2">
|
||||||
|
<button id="btn-start" class="btn btn-success btn-lg flex-grow-1 rounded-pill fw-bold shadow-glow-green" disabled>
|
||||||
|
<i class="bi bi-play-fill"></i> INICIAR SUPERCOMPUTADOR
|
||||||
|
</button>
|
||||||
|
<button id="btn-pause" class="btn btn-warning btn-lg flex-grow-1 rounded-pill fw-bold shadow-sm d-none">
|
||||||
|
<i class="bi bi-pause-fill"></i> PAUSAR MOTOR
|
||||||
|
</button>
|
||||||
|
<div class="btn-group shadow-sm">
|
||||||
|
<button id="btn-up" class="btn btn-dark border-slate-700"><i class="bi bi-chevron-up"></i></button>
|
||||||
|
<button id="btn-down" class="btn btn-dark border-slate-700"><i class="bi bi-chevron-down"></i></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
<div class="col-md-3">
|
|
||||||
<div class="p-3 rounded bg-slate-900 text-center border-start border-info border-4">
|
|
||||||
<small class="d-block text-muted">Elite Verde Detectada</small>
|
|
||||||
<span id="count-hot" class="h4 fw-bold">0</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-md-3">
|
|
||||||
<div class="p-3 rounded bg-slate-900 text-center border-start border-danger border-4">
|
|
||||||
<small class="d-block text-muted">Radar IA: Anulados</small>
|
|
||||||
<span id="count-annulled" class="h4 fw-bold">0</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-md-3">
|
|
||||||
<div class="p-3 rounded bg-slate-900 text-center border-start border-emerald border-4">
|
|
||||||
<small class="d-block text-muted">IA Radar: Resgatados</small>
|
|
||||||
<span id="count-reclaimed" class="h4 fw-bold">0</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Viewport do Motor -->
|
<!-- Viewport do Motor -->
|
||||||
<div class="generator-viewport p-3 bg-slate-950 rounded-4 shadow-inner" style="background: #020617; min-height: 500px; max-height: 600px; overflow-y: auto; border: 1px solid #334155;">
|
<div class="generator-viewport p-3 bg-black rounded-4 shadow-inner mb-3" style="min-height: 550px; max-height: 550px; overflow-y: auto; border: 2px solid #1e293b;">
|
||||||
<div id="sequence-container" class="d-flex flex-column gap-3">
|
<div id="sequence-container" class="d-flex flex-column gap-2">
|
||||||
<div class="text-center text-slate-500 py-5">
|
<div class="text-center text-slate-600 py-5 mt-5">
|
||||||
<i class="bi bi-cpu display-1 mb-3 d-block"></i>
|
<div class="spinner-grow text-info mb-3" role="status"></div>
|
||||||
<p>Aguardando comando do Motor de IA...</p>
|
<h4 class="fw-light">SISTEMA EM STANDBY</h4>
|
||||||
|
<p class="small">Selecione uma loteria para carregar o Funil de Probabilidades</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Barra de Stats Rápida -->
|
||||||
|
<div id="stats-bar" class="row g-2 d-none">
|
||||||
|
<div class="col-md-4">
|
||||||
|
<div class="p-2 rounded bg-slate-900 border-start border-success border-3">
|
||||||
|
<small class="d-block text-muted x-small">SEQUÊNCIAS</small>
|
||||||
|
<span id="count-total" class="h5 fw-bold text-success">0</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-4">
|
||||||
|
<div class="p-2 rounded bg-slate-900 border-start border-info border-3">
|
||||||
|
<small class="d-block text-muted x-small">ELITE VERDE</small>
|
||||||
|
<span id="count-hot" class="h5 fw-bold text-info">0</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-4">
|
||||||
|
<div class="p-2 rounded bg-slate-900 border-start border-danger border-3">
|
||||||
|
<small class="d-block text-muted x-small">IA RADAR</small>
|
||||||
|
<span id="count-reclaimed" class="h5 fw-bold text-emerald">0</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="mt-4 p-3 rounded-3 bg-slate-900 border border-slate-800">
|
<!-- Coluna Direita: Funil e Super Analisador -->
|
||||||
<h6 class="text-slate-400 small mb-2">Legenda do Motor IA:</h6>
|
<div class="col-lg-4">
|
||||||
<div class="d-flex gap-4 flex-wrap">
|
<!-- Painel Supercomputador Real-time -->
|
||||||
<div class="d-flex align-items-center gap-2">
|
<div class="card bg-black border-slate-800 mb-4 rounded-4 overflow-hidden">
|
||||||
<span class="badge" style="background: linear-gradient(135deg, #198754, #28a745); width: 20px; height: 20px;"></span>
|
<div class="bg-slate-900 p-2 border-bottom border-slate-800 text-center">
|
||||||
<span class="small">Elite Verde (Alta Chance)</span>
|
<span class="small fw-bold text-info"><i class="bi bi-lightning-charge-fill"></i> ANALISADOR DE ELITE</span>
|
||||||
|
</div>
|
||||||
|
<div id="elite-panel" class="p-3 d-flex flex-wrap gap-2 justify-content-center" style="min-height: 120px;">
|
||||||
|
<div class="text-slate-700 small text-center w-100 py-4">Aguardando Processamento...</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="d-flex align-items-center gap-2">
|
|
||||||
<span class="badge bg-danger" style="width: 20px; height: 20px;"></span>
|
<!-- Funil Numérico -->
|
||||||
<span class="small">Anulado Frio (Evite)</span>
|
<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>
|
||||||
|
</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>
|
||||||
|
<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>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="d-flex align-items-center gap-2">
|
|
||||||
<span class="badge reclaimed-pulse" style="background: #10b981; width: 20px; height: 20px; box-shadow: 0 0 10px #10b981;"></span>
|
<!-- Log de Voz / Atividade -->
|
||||||
<span class="small">IA Radar: Resgatado do Anulado</span>
|
<div class="mt-4">
|
||||||
|
<h6 class="text-slate-500 x-small fw-bold text-uppercase mb-2">Logs do Supercomputador:</h6>
|
||||||
|
<div id="voice-log" class="p-2 bg-black rounded border border-slate-800 x-small text-info font-monospace" style="height: 100px; overflow-y: auto;">
|
||||||
|
> Sistema Inicializado...<br>
|
||||||
|
> Aguardando entrada de dados...
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -100,70 +126,66 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.bg-slate-800 { background: #1e293b; }
|
.x-small { font-size: 0.7rem; }
|
||||||
|
.text-emerald { color: #10b981; }
|
||||||
.bg-slate-900 { background: #0f172a; }
|
.bg-slate-900 { background: #0f172a; }
|
||||||
.bg-slate-950 { background: #020617; }
|
.border-slate-700 { border-color: #334155 !important; }
|
||||||
.text-slate-300 { color: #cbd5e1; }
|
.border-slate-800 { border-color: #1e293b !important; }
|
||||||
.text-slate-400 { color: #94a3b8; }
|
.shadow-glow-green { box-shadow: 0 0 15px rgba(25, 135, 84, 0.4); }
|
||||||
.text-slate-500 { color: #64748b; }
|
.shadow-inner { box-shadow: inset 0 2px 10px rgba(0,0,0,0.8); }
|
||||||
.border-slate-700 { border-color: #334155; }
|
|
||||||
.border-slate-800 { border-color: #1e293b; }
|
|
||||||
.border-emerald { border-color: #10b981; }
|
|
||||||
|
|
||||||
.reclaimed-pulse {
|
.funnel-ball {
|
||||||
animation: pulse-green 1.5s infinite;
|
width: 32px;
|
||||||
}
|
height: 32px;
|
||||||
|
display: flex;
|
||||||
@keyframes pulse-green {
|
align-items: center;
|
||||||
0% { transform: scale(1); box-shadow: 0 0 0 0 rgba(16, 185, 129, 0.7); }
|
justify-content: center;
|
||||||
70% { transform: scale(1.1); box-shadow: 0 0 0 10px rgba(16, 185, 129, 0); }
|
border-radius: 6px;
|
||||||
100% { transform: scale(1); box-shadow: 0 0 0 0 rgba(16, 185, 129, 0); }
|
background: #1e293b;
|
||||||
|
color: #94a3b8;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.2s;
|
||||||
|
border: 1px solid transparent;
|
||||||
}
|
}
|
||||||
|
.funnel-ball:hover { background: #334155; color: white; }
|
||||||
|
.funnel-ball.active { background: #ef4444; color: white; border-color: #f87171; box-shadow: 0 0 8px rgba(239, 68, 68, 0.4); }
|
||||||
|
|
||||||
.sequence-row {
|
.sequence-row {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 8px;
|
gap: 6px;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
padding: 12px;
|
padding: 8px;
|
||||||
background: #0f172a;
|
background: #0f172a;
|
||||||
border-radius: 12px;
|
border-radius: 10px;
|
||||||
border: 1px solid #1e293b;
|
border: 1px solid #1e293b;
|
||||||
transition: all 0.2s;
|
transition: all 0.2s;
|
||||||
}
|
}
|
||||||
|
.sequence-row:hover { background: #1e293b; transform: scale(1.02); }
|
||||||
.sequence-row:hover {
|
|
||||||
background: #1e293b;
|
|
||||||
transform: translateX(5px);
|
|
||||||
}
|
|
||||||
|
|
||||||
.num-ball {
|
.num-ball {
|
||||||
width: 45px;
|
width: 38px;
|
||||||
height: 45px;
|
height: 38px;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
font-size: 1.2rem;
|
font-size: 1rem;
|
||||||
background: #334155;
|
background: #334155;
|
||||||
color: white;
|
color: white;
|
||||||
transition: all 0.3s;
|
|
||||||
}
|
}
|
||||||
|
.num-elite { background: linear-gradient(135deg, #198754, #28a745); box-shadow: 0 0 10px rgba(40, 167, 69, 0.4); }
|
||||||
|
.num-reclaimed { background: #10b981; animation: pulse-green 1.5s infinite; }
|
||||||
|
|
||||||
.num-elite {
|
@keyframes pulse-green {
|
||||||
background: linear-gradient(135deg, #198754, #28a745);
|
0% { transform: scale(1); box-shadow: 0 0 0 0 rgba(16, 185, 129, 0.7); }
|
||||||
box-shadow: 0 0 10px rgba(25, 135, 84, 0.5);
|
70% { transform: scale(1.1); box-shadow: 0 0 0 8px rgba(16, 185, 129, 0); }
|
||||||
|
100% { transform: scale(1); box-shadow: 0 0 0 0 rgba(16, 185, 129, 0); }
|
||||||
}
|
}
|
||||||
|
.pulse-info { animation: pulse-blue 1s infinite; }
|
||||||
.num-annulled {
|
@keyframes pulse-blue {
|
||||||
background: #dc3545;
|
0% { opacity: 1; } 50% { opacity: 0.5; } 100% { opacity: 1; }
|
||||||
opacity: 0.6;
|
|
||||||
}
|
|
||||||
|
|
||||||
.num-reclaimed {
|
|
||||||
background: #10b981;
|
|
||||||
animation: pulse-green 1.5s infinite;
|
|
||||||
box-shadow: 0 0 15px #10b981;
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
@ -173,29 +195,110 @@
|
|||||||
let currentStartNum = 1;
|
let currentStartNum = 1;
|
||||||
let totalGenerated = 0;
|
let totalGenerated = 0;
|
||||||
let countHot = 0;
|
let countHot = 0;
|
||||||
let countAnnulled = 0;
|
|
||||||
let countReclaimed = 0;
|
let countReclaimed = 0;
|
||||||
let animationId = null;
|
let animationId = null;
|
||||||
|
let annulledFunnel = new Set();
|
||||||
|
const MAX_FUNNEL = 31;
|
||||||
|
|
||||||
const container = document.getElementById("sequence-container");
|
const synth = window.speechSynthesis;
|
||||||
|
let voiceEnabled = true;
|
||||||
|
|
||||||
|
function speak(text) {
|
||||||
|
if (!voiceEnabled || !synth) return;
|
||||||
|
synth.cancel(); // Para a fala anterior para não encavalar
|
||||||
|
const utter = new SpeechSynthesisUtterance(text);
|
||||||
|
utter.lang = 'pt-BR';
|
||||||
|
utter.rate = 1.1;
|
||||||
|
|
||||||
|
// Tenta pegar voz feminina
|
||||||
|
const voices = synth.getVoices();
|
||||||
|
const femaleVoice = voices.find(v => v.name.includes('Maria') || v.name.includes('Google português do Brasil'));
|
||||||
|
if (femaleVoice) utter.voice = femaleVoice;
|
||||||
|
|
||||||
|
utter.onstart = () => document.getElementById("voice-indicator").classList.remove("d-none");
|
||||||
|
utter.onend = () => document.getElementById("voice-indicator").classList.add("d-none");
|
||||||
|
|
||||||
|
const log = document.getElementById("voice-log");
|
||||||
|
log.innerHTML += `> IA: ${text}<br>`;
|
||||||
|
log.scrollTop = log.scrollHeight;
|
||||||
|
|
||||||
|
synth.speak(utter);
|
||||||
|
}
|
||||||
|
|
||||||
|
const lotterySelect = document.getElementById("lottery-select");
|
||||||
|
const funnelGrid = document.getElementById("funnel-grid");
|
||||||
|
const funnelCountLabel = document.getElementById("funnel-count");
|
||||||
const btnStart = document.getElementById("btn-start");
|
const btnStart = document.getElementById("btn-start");
|
||||||
const btnPause = document.getElementById("btn-pause");
|
const btnPause = document.getElementById("btn-pause");
|
||||||
const lotterySelect = document.getElementById("lottery-select");
|
const container = document.getElementById("sequence-container");
|
||||||
const viewport = document.querySelector(".generator-viewport");
|
const viewport = document.querySelector(".generator-viewport");
|
||||||
|
const elitePanel = document.getElementById("elite-panel");
|
||||||
|
|
||||||
lotterySelect.addEventListener("change", async (e) => {
|
lotterySelect.addEventListener("change", async (e) => {
|
||||||
const key = e.target.value;
|
const key = e.target.value;
|
||||||
if (!key) {
|
if (!key) return;
|
||||||
btnStart.disabled = true;
|
|
||||||
return;
|
speak(`Iniciando análise para ${key}. Carregando base de dados histórica.`);
|
||||||
}
|
|
||||||
const resp = await fetch(`/api/lottery-info/${key}/`);
|
const resp = await fetch(`/api/lottery-info/${key}/`);
|
||||||
lotteryData = await resp.json();
|
lotteryData = await resp.json();
|
||||||
|
|
||||||
|
setupFunnel(lotteryData.max_number);
|
||||||
|
updateElitePanel();
|
||||||
btnStart.disabled = false;
|
btnStart.disabled = false;
|
||||||
document.getElementById("stats-bar").classList.remove("d-none");
|
document.getElementById("stats-bar").classList.remove("d-none");
|
||||||
resetGenerator();
|
resetGenerator();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function setupFunnel(max) {
|
||||||
|
funnelGrid.innerHTML = "";
|
||||||
|
annulledFunnel.clear();
|
||||||
|
updateFunnelLabel();
|
||||||
|
|
||||||
|
for (let i = 1; i <= max; i++) {
|
||||||
|
const ball = document.createElement("div");
|
||||||
|
ball.className = "funnel-ball";
|
||||||
|
ball.innerText = i.toString().padStart(2, "0");
|
||||||
|
|
||||||
|
// Pré-carrega os anulados do banco, se houver espaço
|
||||||
|
if (lotteryData.annulled_numbers.includes(i) && annulledFunnel.size < MAX_FUNNEL) {
|
||||||
|
ball.classList.add("active");
|
||||||
|
annulledFunnel.add(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
ball.onclick = () => {
|
||||||
|
if (ball.classList.contains("active")) {
|
||||||
|
ball.classList.remove("active");
|
||||||
|
annulledFunnel.delete(i);
|
||||||
|
} else {
|
||||||
|
if (annulledFunnel.size >= MAX_FUNNEL) {
|
||||||
|
speak("Limite do funil atingido. Máximo de 31 dezenas.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ball.classList.add("active");
|
||||||
|
annulledFunnel.add(i);
|
||||||
|
}
|
||||||
|
updateFunnelLabel();
|
||||||
|
};
|
||||||
|
funnelGrid.appendChild(ball);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateFunnelLabel() {
|
||||||
|
funnelCountLabel.innerText = `${annulledFunnel.size} / ${MAX_FUNNEL}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateElitePanel() {
|
||||||
|
elitePanel.innerHTML = "";
|
||||||
|
lotteryData.elite_greens.slice(0, 10).forEach(n => {
|
||||||
|
const ball = document.createElement("div");
|
||||||
|
ball.className = "num-ball num-elite mb-2";
|
||||||
|
ball.style.width = "42px";
|
||||||
|
ball.style.height = "42px";
|
||||||
|
ball.innerText = n.toString().padStart(2, "0");
|
||||||
|
elitePanel.appendChild(ball);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function resetGenerator() {
|
function resetGenerator() {
|
||||||
generatorRunning = false;
|
generatorRunning = false;
|
||||||
btnStart.classList.remove("d-none");
|
btnStart.classList.remove("d-none");
|
||||||
@ -204,7 +307,6 @@
|
|||||||
currentStartNum = 1;
|
currentStartNum = 1;
|
||||||
totalGenerated = 0;
|
totalGenerated = 0;
|
||||||
countHot = 0;
|
countHot = 0;
|
||||||
countAnnulled = 0;
|
|
||||||
countReclaimed = 0;
|
countReclaimed = 0;
|
||||||
updateStats();
|
updateStats();
|
||||||
if (animationId) cancelAnimationFrame(animationId);
|
if (animationId) cancelAnimationFrame(animationId);
|
||||||
@ -213,7 +315,6 @@
|
|||||||
function updateStats() {
|
function updateStats() {
|
||||||
document.getElementById("count-total").innerText = totalGenerated.toLocaleString();
|
document.getElementById("count-total").innerText = totalGenerated.toLocaleString();
|
||||||
document.getElementById("count-hot").innerText = countHot.toLocaleString();
|
document.getElementById("count-hot").innerText = countHot.toLocaleString();
|
||||||
document.getElementById("count-annulled").innerText = countAnnulled.toLocaleString();
|
|
||||||
document.getElementById("count-reclaimed").innerText = countReclaimed.toLocaleString();
|
document.getElementById("count-reclaimed").innerText = countReclaimed.toLocaleString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -223,26 +324,38 @@
|
|||||||
const nToDraw = lotteryData.numbers_to_draw;
|
const nToDraw = lotteryData.numbers_to_draw;
|
||||||
const maxNum = lotteryData.max_number;
|
const maxNum = lotteryData.max_number;
|
||||||
|
|
||||||
// Geramos 3 sequências por frame para suavidade
|
for (let i = 0; i < 2; i++) {
|
||||||
for (let i = 0; i < 3; i++) {
|
|
||||||
let sequence = [];
|
let sequence = [];
|
||||||
for (let j = 0; j < nToDraw; j++) {
|
let safetyCounter = 0;
|
||||||
let val = ((currentStartNum + j - 1) % maxNum) + 1;
|
|
||||||
|
while (sequence.length < nToDraw && safetyCounter < 200) {
|
||||||
|
let val = ((currentStartNum - 1) % maxNum) + 1;
|
||||||
|
currentStartNum++;
|
||||||
|
safetyCounter++;
|
||||||
|
|
||||||
|
// Pula se estiver no FUNIL
|
||||||
|
if (annulledFunnel.has(val)) continue;
|
||||||
|
|
||||||
sequence.push(val);
|
sequence.push(val);
|
||||||
|
|
||||||
// Stats
|
|
||||||
if (lotteryData.reclaimed_numbers.includes(val)) countReclaimed++;
|
if (lotteryData.reclaimed_numbers.includes(val)) countReclaimed++;
|
||||||
else if (lotteryData.elite_greens.includes(val)) countHot++;
|
else if (lotteryData.elite_greens.includes(val)) countHot++;
|
||||||
else if (lotteryData.annulled_numbers.includes(val)) countAnnulled++;
|
|
||||||
}
|
}
|
||||||
currentStartNum += nToDraw;
|
|
||||||
renderSequence(sequence);
|
if (sequence.length === nToDraw) {
|
||||||
totalGenerated++;
|
renderSequence(sequence);
|
||||||
|
totalGenerated++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
updateStats();
|
updateStats();
|
||||||
// Auto-scroll para baixo
|
|
||||||
viewport.scrollTop = viewport.scrollHeight;
|
viewport.scrollTop = viewport.scrollHeight;
|
||||||
|
|
||||||
|
// Voz aleatória a cada 1000 gerações
|
||||||
|
if (totalGenerated % 1000 === 0 && totalGenerated > 0) {
|
||||||
|
speak(`Processadas ${totalGenerated} combinações. Elite detectada em ${countHot} pontos.`);
|
||||||
|
}
|
||||||
|
|
||||||
animationId = requestAnimationFrame(generateChunk);
|
animationId = requestAnimationFrame(generateChunk);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -259,17 +372,11 @@
|
|||||||
ball.classList.add("num-reclaimed");
|
ball.classList.add("num-reclaimed");
|
||||||
} else if (lotteryData.elite_greens.includes(n)) {
|
} else if (lotteryData.elite_greens.includes(n)) {
|
||||||
ball.classList.add("num-elite");
|
ball.classList.add("num-elite");
|
||||||
} else if (lotteryData.annulled_numbers.includes(n)) {
|
|
||||||
ball.classList.add("num-annulled");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
row.appendChild(ball);
|
row.appendChild(ball);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Limita o DOM para performance (mantém as últimas 40)
|
if (container.children.length > 30) container.removeChild(container.firstChild);
|
||||||
if (container.children.length > 40) {
|
|
||||||
container.removeChild(container.firstChild);
|
|
||||||
}
|
|
||||||
container.appendChild(row);
|
container.appendChild(row);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -278,6 +385,7 @@
|
|||||||
generatorRunning = true;
|
generatorRunning = true;
|
||||||
btnStart.classList.add("d-none");
|
btnStart.classList.add("d-none");
|
||||||
btnPause.classList.remove("d-none");
|
btnPause.classList.remove("d-none");
|
||||||
|
speak("Motor Sequencial Iniciado. Aplicando Funil de Trinta e uma Dezenas.");
|
||||||
generateChunk();
|
generateChunk();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -285,15 +393,11 @@
|
|||||||
generatorRunning = false;
|
generatorRunning = false;
|
||||||
btnPause.classList.add("d-none");
|
btnPause.classList.add("d-none");
|
||||||
btnStart.classList.remove("d-none");
|
btnStart.classList.remove("d-none");
|
||||||
|
speak("Motor pausado pelo operador.");
|
||||||
if (animationId) cancelAnimationFrame(animationId);
|
if (animationId) cancelAnimationFrame(animationId);
|
||||||
});
|
});
|
||||||
|
|
||||||
document.getElementById("btn-up").addEventListener("click", () => {
|
document.getElementById("btn-up").addEventListener("click", () => viewport.scrollBy({ top: -300, behavior: "smooth" }));
|
||||||
viewport.scrollBy({ top: -300, behavior: "smooth" });
|
document.getElementById("btn-down").addEventListener("click", () => viewport.scrollBy({ top: 300, behavior: "smooth" }));
|
||||||
});
|
|
||||||
|
|
||||||
document.getElementById("btn-down").addEventListener("click", () => {
|
|
||||||
viewport.scrollBy({ top: 300, behavior: "smooth" });
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user