ESPECIFICAÇOES 1
This commit is contained in:
parent
928c0dddfd
commit
28516985ed
@ -1,96 +1,122 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% 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="col-lg-10">
|
||||
<div class="card bg-slate-800 border-0 shadow-lg p-4" style="background: #1e293b; border-radius: 20px;">
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
<div class="col-lg-11">
|
||||
<div class="card border-0 shadow-lg p-4" style="background: #0f172a; border-radius: 24px; border: 1px solid #1e293b !important;">
|
||||
|
||||
<!-- Cabeçalho de Supercomputador -->
|
||||
<div class="d-flex justify-content-between align-items-center mb-4 border-bottom border-slate-800 pb-3">
|
||||
<div>
|
||||
<h2 class="display-6 fw-bold mb-0 text-white">Gerador Sequencial Inteligente IA</h2>
|
||||
<p class="text-slate-400">Motor Autônomo de Probabilidades Matemáticas</p>
|
||||
<h2 class="display-6 fw-bold mb-0 text-white text-uppercase tracking-tighter">
|
||||
<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>
|
||||
<a href="{% url 'home' %}" class="btn btn-outline-light rounded-pill px-4">Voltar ao Início</a>
|
||||
</div>
|
||||
|
||||
<div class="row g-3 mb-4">
|
||||
<div class="col-md-4">
|
||||
<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 class="d-flex gap-3 align-items-center">
|
||||
<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 'home' %}" class="btn btn-outline-slate rounded-pill px-4 text-white border-slate-700">Sair do Sistema</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Barra de Stats IA -->
|
||||
<div id="stats-bar" class="row g-2 mb-4 d-none">
|
||||
<div class="col-md-3">
|
||||
<div class="p-3 rounded bg-slate-900 text-center border-start border-success border-4">
|
||||
<small class="d-block text-muted">Sequências Geradas</small>
|
||||
<span id="count-total" class="h4 fw-bold">0</span>
|
||||
<div class="row g-4">
|
||||
<!-- Coluna Esquerda: Controles e Gerador -->
|
||||
<div class="col-lg-8">
|
||||
<div class="row g-3 mb-4">
|
||||
<div class="col-md-5">
|
||||
<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 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 -->
|
||||
<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 id="sequence-container" class="d-flex flex-column gap-3">
|
||||
<div class="text-center text-slate-500 py-5">
|
||||
<i class="bi bi-cpu display-1 mb-3 d-block"></i>
|
||||
<p>Aguardando comando do Motor de IA...</p>
|
||||
<!-- Viewport do Motor -->
|
||||
<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-2">
|
||||
<div class="text-center text-slate-600 py-5 mt-5">
|
||||
<div class="spinner-grow text-info mb-3" role="status"></div>
|
||||
<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 class="mt-4 p-3 rounded-3 bg-slate-900 border border-slate-800">
|
||||
<h6 class="text-slate-400 small mb-2">Legenda do Motor IA:</h6>
|
||||
<div class="d-flex gap-4 flex-wrap">
|
||||
<div class="d-flex align-items-center gap-2">
|
||||
<span class="badge" style="background: linear-gradient(135deg, #198754, #28a745); width: 20px; height: 20px;"></span>
|
||||
<span class="small">Elite Verde (Alta Chance)</span>
|
||||
<!-- Coluna Direita: Funil e Super Analisador -->
|
||||
<div class="col-lg-4">
|
||||
<!-- Painel Supercomputador Real-time -->
|
||||
<div class="card bg-black border-slate-800 mb-4 rounded-4 overflow-hidden">
|
||||
<div class="bg-slate-900 p-2 border-bottom border-slate-800 text-center">
|
||||
<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 class="d-flex align-items-center gap-2">
|
||||
<span class="badge bg-danger" style="width: 20px; height: 20px;"></span>
|
||||
<span class="small">Anulado Frio (Evite)</span>
|
||||
|
||||
<!-- Funil Numérico -->
|
||||
<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 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>
|
||||
<span class="small">IA Radar: Resgatado do Anulado</span>
|
||||
|
||||
<!-- Log de Voz / Atividade -->
|
||||
<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>
|
||||
@ -100,70 +126,66 @@
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.bg-slate-800 { background: #1e293b; }
|
||||
.x-small { font-size: 0.7rem; }
|
||||
.text-emerald { color: #10b981; }
|
||||
.bg-slate-900 { background: #0f172a; }
|
||||
.bg-slate-950 { background: #020617; }
|
||||
.text-slate-300 { color: #cbd5e1; }
|
||||
.text-slate-400 { color: #94a3b8; }
|
||||
.text-slate-500 { color: #64748b; }
|
||||
.border-slate-700 { border-color: #334155; }
|
||||
.border-slate-800 { border-color: #1e293b; }
|
||||
.border-emerald { border-color: #10b981; }
|
||||
.border-slate-700 { border-color: #334155 !important; }
|
||||
.border-slate-800 { border-color: #1e293b !important; }
|
||||
.shadow-glow-green { box-shadow: 0 0 15px rgba(25, 135, 84, 0.4); }
|
||||
.shadow-inner { box-shadow: inset 0 2px 10px rgba(0,0,0,0.8); }
|
||||
|
||||
.reclaimed-pulse {
|
||||
animation: pulse-green 1.5s infinite;
|
||||
}
|
||||
|
||||
@keyframes pulse-green {
|
||||
0% { transform: scale(1); box-shadow: 0 0 0 0 rgba(16, 185, 129, 0.7); }
|
||||
70% { transform: scale(1.1); box-shadow: 0 0 0 10px rgba(16, 185, 129, 0); }
|
||||
100% { transform: scale(1); box-shadow: 0 0 0 0 rgba(16, 185, 129, 0); }
|
||||
.funnel-ball {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 6px;
|
||||
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 {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
gap: 6px;
|
||||
justify-content: center;
|
||||
padding: 12px;
|
||||
padding: 8px;
|
||||
background: #0f172a;
|
||||
border-radius: 12px;
|
||||
border-radius: 10px;
|
||||
border: 1px solid #1e293b;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.sequence-row:hover {
|
||||
background: #1e293b;
|
||||
transform: translateX(5px);
|
||||
}
|
||||
.sequence-row:hover { background: #1e293b; transform: scale(1.02); }
|
||||
|
||||
.num-ball {
|
||||
width: 45px;
|
||||
height: 45px;
|
||||
width: 38px;
|
||||
height: 38px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 50%;
|
||||
font-weight: bold;
|
||||
font-size: 1.2rem;
|
||||
font-size: 1rem;
|
||||
background: #334155;
|
||||
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 {
|
||||
background: linear-gradient(135deg, #198754, #28a745);
|
||||
box-shadow: 0 0 10px rgba(25, 135, 84, 0.5);
|
||||
@keyframes pulse-green {
|
||||
0% { transform: scale(1); box-shadow: 0 0 0 0 rgba(16, 185, 129, 0.7); }
|
||||
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); }
|
||||
}
|
||||
|
||||
.num-annulled {
|
||||
background: #dc3545;
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.num-reclaimed {
|
||||
background: #10b981;
|
||||
animation: pulse-green 1.5s infinite;
|
||||
box-shadow: 0 0 15px #10b981;
|
||||
.pulse-info { animation: pulse-blue 1s infinite; }
|
||||
@keyframes pulse-blue {
|
||||
0% { opacity: 1; } 50% { opacity: 0.5; } 100% { opacity: 1; }
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -173,29 +195,110 @@
|
||||
let currentStartNum = 1;
|
||||
let totalGenerated = 0;
|
||||
let countHot = 0;
|
||||
let countAnnulled = 0;
|
||||
let countReclaimed = 0;
|
||||
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 btnPause = document.getElementById("btn-pause");
|
||||
const lotterySelect = document.getElementById("lottery-select");
|
||||
const container = document.getElementById("sequence-container");
|
||||
const viewport = document.querySelector(".generator-viewport");
|
||||
const elitePanel = document.getElementById("elite-panel");
|
||||
|
||||
lotterySelect.addEventListener("change", async (e) => {
|
||||
const key = e.target.value;
|
||||
if (!key) {
|
||||
btnStart.disabled = true;
|
||||
return;
|
||||
}
|
||||
if (!key) return;
|
||||
|
||||
speak(`Iniciando análise para ${key}. Carregando base de dados histórica.`);
|
||||
const resp = await fetch(`/api/lottery-info/${key}/`);
|
||||
lotteryData = await resp.json();
|
||||
|
||||
setupFunnel(lotteryData.max_number);
|
||||
updateElitePanel();
|
||||
btnStart.disabled = false;
|
||||
document.getElementById("stats-bar").classList.remove("d-none");
|
||||
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() {
|
||||
generatorRunning = false;
|
||||
btnStart.classList.remove("d-none");
|
||||
@ -204,7 +307,6 @@
|
||||
currentStartNum = 1;
|
||||
totalGenerated = 0;
|
||||
countHot = 0;
|
||||
countAnnulled = 0;
|
||||
countReclaimed = 0;
|
||||
updateStats();
|
||||
if (animationId) cancelAnimationFrame(animationId);
|
||||
@ -213,7 +315,6 @@
|
||||
function updateStats() {
|
||||
document.getElementById("count-total").innerText = totalGenerated.toLocaleString();
|
||||
document.getElementById("count-hot").innerText = countHot.toLocaleString();
|
||||
document.getElementById("count-annulled").innerText = countAnnulled.toLocaleString();
|
||||
document.getElementById("count-reclaimed").innerText = countReclaimed.toLocaleString();
|
||||
}
|
||||
|
||||
@ -223,26 +324,38 @@
|
||||
const nToDraw = lotteryData.numbers_to_draw;
|
||||
const maxNum = lotteryData.max_number;
|
||||
|
||||
// Geramos 3 sequências por frame para suavidade
|
||||
for (let i = 0; i < 3; i++) {
|
||||
for (let i = 0; i < 2; i++) {
|
||||
let sequence = [];
|
||||
for (let j = 0; j < nToDraw; j++) {
|
||||
let val = ((currentStartNum + j - 1) % maxNum) + 1;
|
||||
let safetyCounter = 0;
|
||||
|
||||
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);
|
||||
|
||||
// Stats
|
||||
if (lotteryData.reclaimed_numbers.includes(val)) countReclaimed++;
|
||||
else if (lotteryData.elite_greens.includes(val)) countHot++;
|
||||
else if (lotteryData.annulled_numbers.includes(val)) countAnnulled++;
|
||||
}
|
||||
currentStartNum += nToDraw;
|
||||
renderSequence(sequence);
|
||||
totalGenerated++;
|
||||
|
||||
if (sequence.length === nToDraw) {
|
||||
renderSequence(sequence);
|
||||
totalGenerated++;
|
||||
}
|
||||
}
|
||||
|
||||
updateStats();
|
||||
// Auto-scroll para baixo
|
||||
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);
|
||||
}
|
||||
|
||||
@ -259,17 +372,11 @@
|
||||
ball.classList.add("num-reclaimed");
|
||||
} else if (lotteryData.elite_greens.includes(n)) {
|
||||
ball.classList.add("num-elite");
|
||||
} else if (lotteryData.annulled_numbers.includes(n)) {
|
||||
ball.classList.add("num-annulled");
|
||||
}
|
||||
|
||||
row.appendChild(ball);
|
||||
});
|
||||
|
||||
// Limita o DOM para performance (mantém as últimas 40)
|
||||
if (container.children.length > 40) {
|
||||
container.removeChild(container.firstChild);
|
||||
}
|
||||
if (container.children.length > 30) container.removeChild(container.firstChild);
|
||||
container.appendChild(row);
|
||||
}
|
||||
|
||||
@ -278,6 +385,7 @@
|
||||
generatorRunning = true;
|
||||
btnStart.classList.add("d-none");
|
||||
btnPause.classList.remove("d-none");
|
||||
speak("Motor Sequencial Iniciado. Aplicando Funil de Trinta e uma Dezenas.");
|
||||
generateChunk();
|
||||
});
|
||||
|
||||
@ -285,15 +393,11 @@
|
||||
generatorRunning = false;
|
||||
btnPause.classList.add("d-none");
|
||||
btnStart.classList.remove("d-none");
|
||||
speak("Motor pausado pelo operador.");
|
||||
if (animationId) cancelAnimationFrame(animationId);
|
||||
});
|
||||
|
||||
document.getElementById("btn-up").addEventListener("click", () => {
|
||||
viewport.scrollBy({ top: -300, behavior: "smooth" });
|
||||
});
|
||||
|
||||
document.getElementById("btn-down").addEventListener("click", () => {
|
||||
viewport.scrollBy({ top: 300, behavior: "smooth" });
|
||||
});
|
||||
document.getElementById("btn-up").addEventListener("click", () => viewport.scrollBy({ top: -300, behavior: "smooth" }));
|
||||
document.getElementById("btn-down").addEventListener("click", () => viewport.scrollBy({ top: 300, behavior: "smooth" }));
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user