ESPECIFICAÇOES 1

This commit is contained in:
Flatlogic Bot 2026-02-18 18:46:08 +00:00
parent 928c0dddfd
commit 28516985ed

View File

@ -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 %}