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" %}
{% 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 %}