ESTABILIDADE DO SISTEMA 1

This commit is contained in:
Flatlogic Bot 2026-02-18 17:30:19 +00:00
parent 688b6e4a0b
commit 928c0dddfd
6 changed files with 356 additions and 0 deletions

View File

@ -35,6 +35,11 @@
<main id="top" class="site-main">
<section class="hero-section">
<div class="container">
<div class="text-center mb-5">
<a href="{% url 'sequential_generator' %}" class="btn btn-dark btn-lg rounded-pill px-5 shadow-lg border-info" style="background: #0f172a; border-width: 2px;">
<i class="bi bi-cpu-fill text-info me-2"></i> ABRIR GERADOR SEQUENCIAL INTELIGENTE IA
</a>
</div>
<div class="row align-items-center g-5">
<div class="col-lg-6">
<div class="eyebrow">Inteligencia matematica aplicada</div>

View File

@ -0,0 +1,299 @@
{% extends "base.html" %}
{% block content %}
<div class="container-fluid py-4" style="background: #0f172a; min-height: 100vh; color: #f8fafc;">
<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>
<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>
</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>
</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>
</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>
</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>
</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>
</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>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<style>
.bg-slate-800 { background: #1e293b; }
.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; }
.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); }
}
.sequence-row {
display: flex;
gap: 8px;
justify-content: center;
padding: 12px;
background: #0f172a;
border-radius: 12px;
border: 1px solid #1e293b;
transition: all 0.2s;
}
.sequence-row:hover {
background: #1e293b;
transform: translateX(5px);
}
.num-ball {
width: 45px;
height: 45px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 50%;
font-weight: bold;
font-size: 1.2rem;
background: #334155;
color: white;
transition: all 0.3s;
}
.num-elite {
background: linear-gradient(135deg, #198754, #28a745);
box-shadow: 0 0 10px rgba(25, 135, 84, 0.5);
}
.num-annulled {
background: #dc3545;
opacity: 0.6;
}
.num-reclaimed {
background: #10b981;
animation: pulse-green 1.5s infinite;
box-shadow: 0 0 15px #10b981;
}
</style>
<script>
let generatorRunning = false;
let lotteryData = null;
let currentStartNum = 1;
let totalGenerated = 0;
let countHot = 0;
let countAnnulled = 0;
let countReclaimed = 0;
let animationId = null;
const container = document.getElementById("sequence-container");
const btnStart = document.getElementById("btn-start");
const btnPause = document.getElementById("btn-pause");
const lotterySelect = document.getElementById("lottery-select");
const viewport = document.querySelector(".generator-viewport");
lotterySelect.addEventListener("change", async (e) => {
const key = e.target.value;
if (!key) {
btnStart.disabled = true;
return;
}
const resp = await fetch(`/api/lottery-info/${key}/`);
lotteryData = await resp.json();
btnStart.disabled = false;
document.getElementById("stats-bar").classList.remove("d-none");
resetGenerator();
});
function resetGenerator() {
generatorRunning = false;
btnStart.classList.remove("d-none");
btnPause.classList.add("d-none");
container.innerHTML = "";
currentStartNum = 1;
totalGenerated = 0;
countHot = 0;
countAnnulled = 0;
countReclaimed = 0;
updateStats();
if (animationId) cancelAnimationFrame(animationId);
}
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();
}
function generateChunk() {
if (!generatorRunning) return;
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++) {
let sequence = [];
for (let j = 0; j < nToDraw; j++) {
let val = ((currentStartNum + j - 1) % maxNum) + 1;
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++;
}
updateStats();
// Auto-scroll para baixo
viewport.scrollTop = viewport.scrollHeight;
animationId = requestAnimationFrame(generateChunk);
}
function renderSequence(numbers) {
const row = document.createElement("div");
row.className = "sequence-row";
numbers.forEach(n => {
const ball = document.createElement("div");
ball.className = "num-ball";
ball.innerText = n.toString().padStart(2, "0");
if (lotteryData.reclaimed_numbers.includes(n)) {
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);
}
container.appendChild(row);
}
btnStart.addEventListener("click", () => {
if (!lotteryData) return;
generatorRunning = true;
btnStart.classList.add("d-none");
btnPause.classList.remove("d-none");
generateChunk();
});
btnPause.addEventListener("click", () => {
generatorRunning = false;
btnPause.classList.add("d-none");
btnStart.classList.remove("d-none");
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" });
});
</script>
{% endblock %}

View File

@ -9,4 +9,6 @@ urlpatterns = [
path('admin-loto/edit/<int:lottery_id>/', views.edit_lottery, name='edit_lottery'),
path('admin-loto/ai-predict/<int:lottery_id>/', views.ai_auto_predict, name='ai_predict'),
path('live-math/', views.live_math, name='live_math'),
path('gerador-sequencial/', views.sequential_generator, name='sequential_generator'),
path('api/lottery-info/<str:lottery_key>/', views.lottery_info_api, name='lottery_info_api'),
]

View File

@ -308,3 +308,53 @@ def live_math(request):
except Exception as e:
return JsonResponse({"error": str(e)}, status=500)
return JsonResponse({"error": "Método inválido"}, status=405)
def sequential_generator(request):
"""Página do Gerador Sequencial Inteligente."""
loterias = Lottery.objects.all()
return render(request, "core/sequential_generator.html", {"loterias": loterias})
def lottery_info_api(request, lottery_key):
"""Retorna informações de IA para uma loteria específica via JSON."""
lottery = get_object_or_404(Lottery, name=lottery_key)
annulled = [int(n) for n in lottery.annulled_numbers.split(',') if n]
# Pegamos os sorteios para o Radar de Reclamação
draws_db = DrawResult.objects.filter(lottery=lottery)
draw_lists = [[int(n) for n in d.numbers.split(',')] for d in draws_db]
if not draw_lists:
# Mock se vazio
frequency = {n: random.randint(1, 10) for n in range(1, lottery.max_number + 1)}
else:
frequency = Counter(number for draw in draw_lists for number in draw)
# Lógica de Elite Verde (Top 25% dos disponíveis)
available_numbers = [n for n in range(1, lottery.max_number + 1) if n not in annulled]
sorted_by_freq = sorted(available_numbers, key=lambda n: frequency.get(n, 0), reverse=True)
hot_count = max(6, int(len(available_numbers) * 0.25))
elite_greens = sorted_by_freq[:hot_count]
# IA Radar de Reclamação
last_seen_all = {}
for i, draw in enumerate(reversed(draw_lists)):
for num in draw:
if num not in last_seen_all:
last_seen_all[num] = i
reclaimed = []
for n in annulled:
freq = frequency.get(n, 0)
delay = last_seen_all.get(n, len(draw_lists))
reclaim_score = (freq * 0.6) + (delay * 0.4)
if reclaim_score > (max(frequency.values() or [1]) * 0.8):
reclaimed.append(n)
return JsonResponse({
"name": lottery.get_name_display(),
"max_number": lottery.max_number,
"numbers_to_draw": lottery.numbers_to_draw,
"elite_greens": elite_greens,
"annulled_numbers": [n for n in annulled if n not in reclaimed],
"reclaimed_numbers": reclaimed,
})