Autosave: 20260218-044310
This commit is contained in:
parent
b9983c7f67
commit
40e64da82f
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -36,6 +36,9 @@ class LotterySimulatorForm(forms.Form):
|
|||||||
(50, "50 Jogos"),
|
(50, "50 Jogos"),
|
||||||
(100, "100 Jogos"),
|
(100, "100 Jogos"),
|
||||||
(1000000000000, "1 Trilhão (Simulação IA)"),
|
(1000000000000, "1 Trilhão (Simulação IA)"),
|
||||||
|
(10000000000000, "10 Trilhões (Simulação Massiva)"),
|
||||||
|
(30000000000000, "30 Trilhões (Simulação Elite)"),
|
||||||
|
(60000000000000, "60 Trilhões (Poder Máximo)"),
|
||||||
],
|
],
|
||||||
initial=5,
|
initial=5,
|
||||||
widget=forms.Select(
|
widget=forms.Select(
|
||||||
|
|||||||
@ -14,9 +14,13 @@
|
|||||||
<h2>Editor: {{ lottery.get_name_display }}</h2>
|
<h2>Editor: {{ lottery.get_name_display }}</h2>
|
||||||
<p class="text-muted">Selecione os números para <strong>ANULAR</strong> ou use a IA.</p>
|
<p class="text-muted">Selecione os números para <strong>ANULAR</strong> ou use a IA.</p>
|
||||||
</div>
|
</div>
|
||||||
<a href="{% url 'ai_predict' lottery.id %}" class="btn btn-warning">
|
<div class="text-end">
|
||||||
<i class="fas fa-robot"></i> Auto-Previsão IA
|
<a href="{% url 'ai_predict' lottery.id %}" class="btn btn-warning mb-1">
|
||||||
</a>
|
<i class="fas fa-robot"></i> Auto-Previsão IA Rotativa
|
||||||
|
</a>
|
||||||
|
<br>
|
||||||
|
<small class="text-warning" style="font-size: 0.75rem;">Recalcula Verdes ignorando Anulados</small>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<form method="post">
|
<form method="post">
|
||||||
|
|||||||
@ -130,12 +130,13 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="number-groups">
|
<div class="number-groups">
|
||||||
<div>
|
<div>
|
||||||
<div class="group-title text-success">Probabilidades Quentes (Verde)</div>
|
<div class="group-title text-success">Probabilidades Quentes (Elite Verde)</div>
|
||||||
<div class="badge-grid">
|
<div class="badge-grid">
|
||||||
{% for number in result.hot_numbers %}
|
{% for number in result.hot_numbers %}
|
||||||
<span class="badge" style="background-color: #198754; font-size: 1.1rem;">{{ number|stringformat:"02d" }}</span>
|
<span class="badge shadow-sm" style="background: linear-gradient(135deg, #198754, #28a745); font-size: 1.1rem; border: none;">{{ number|stringformat:"02d" }}</span>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
|
<small class="text-muted mt-2 d-block" style="font-size: 0.75rem;">* Atualizado ao vivo conforme anulações no editor.</small>
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-3">
|
<div class="mt-3">
|
||||||
<div class="group-title text-danger">Números Anulados (Vermelho)</div>
|
<div class="group-title text-danger">Números Anulados (Vermelho)</div>
|
||||||
@ -159,9 +160,9 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="suggestions-grid">
|
<div class="suggestions-grid">
|
||||||
{% if result.is_trillion %}
|
{% if result.is_trillion %}
|
||||||
<div class="alert alert-warning mb-3">
|
<div class="alert alert-success mb-3 shadow-sm border-0" style="background: linear-gradient(135deg, #198754, #20c997); color: white;">
|
||||||
<strong>Simulação de 1 Trilhão Concluída!</strong><br>
|
<strong>Simulação de {{ result.trillion_label }} Concluída!</strong><br>
|
||||||
A IA processou 1.000.000.000.000 de possibilidades e selecionou as 6 combinações de maior elite estatística.
|
<small>A IA processou o volume massivo de possibilidades e selecionou as 6 combinações de elite estatística usando o <strong>Sistema Rotativo</strong> (excluindo anulados).</small>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% for suggestion in result.suggestions %}
|
{% for suggestion in result.suggestions %}
|
||||||
@ -189,6 +190,172 @@
|
|||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
<section class="manual-selection-section py-5" style="background: #f8f9fa;">
|
||||||
|
<div class="container">
|
||||||
|
<div class="section-header text-center mb-5">
|
||||||
|
<h2 class="display-6 fw-bold">Seleção Manual & Matemática Ao Vivo</h2>
|
||||||
|
<p class="text-muted">Escolha 6 ou mais números e peça à IA para calcular a elite estatística agora.</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row g-4">
|
||||||
|
<div class="col-lg-8">
|
||||||
|
<div class="card shadow-sm border-0 p-4">
|
||||||
|
<div class="d-flex justify-content-between align-items-center mb-3">
|
||||||
|
<h4 class="mb-0">Quadro de Dezenas</h4>
|
||||||
|
<span class="badge bg-success" id="selected-count">0 selecionados</span>
|
||||||
|
</div>
|
||||||
|
<div id="number-grid" class="d-flex flex-wrap gap-2 justify-content-center p-3" style="background: #fff; border-radius: 12px; min-height: 200px;">
|
||||||
|
<p class="text-muted mt-4">Selecione uma loteria no simulador acima para carregar o quadro.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-4">
|
||||||
|
<div class="card shadow-sm border-0 p-4 h-100 text-center" style="background: linear-gradient(135deg, #1e293b, #0f172a); color: white;">
|
||||||
|
<h4>Análise Ao Vivo</h4>
|
||||||
|
<hr class="border-secondary">
|
||||||
|
<div id="live-result-area" class="py-4">
|
||||||
|
<div class="display-1 fw-bold mb-0" id="live-score">--</div>
|
||||||
|
<div class="text-uppercase tracking-wider small opacity-75">Score de Elite IA</div>
|
||||||
|
</div>
|
||||||
|
<div class="mt-auto">
|
||||||
|
<button id="btn-live-math" class="btn btn-success btn-lg w-100 py-3 fw-bold shadow">
|
||||||
|
<i class="bi bi-cpu"></i> CÁLCULO MATEMÁTICO AO VIVO
|
||||||
|
</button>
|
||||||
|
<p class="small mt-3 opacity-50">Mínimo de 6 dezenas para processar.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
const grid = document.getElementById('number-grid');
|
||||||
|
const selectCount = document.getElementById('selected-count');
|
||||||
|
const lotterySelect = document.querySelector('select[name="lottery_type"]');
|
||||||
|
const btnLive = document.getElementById('btn-live-math');
|
||||||
|
const liveScore = document.getElementById('live-score');
|
||||||
|
const liveResultArea = document.getElementById('live-result-area');
|
||||||
|
|
||||||
|
let selectedNumbers = new Set();
|
||||||
|
let currentMax = 60;
|
||||||
|
|
||||||
|
const lotteryConfigs = {
|
||||||
|
'mega_sena': 60,
|
||||||
|
'quina': 80,
|
||||||
|
'dupla_sena': 50,
|
||||||
|
'lotomania': 100,
|
||||||
|
'lotofacil': 25
|
||||||
|
};
|
||||||
|
|
||||||
|
function renderGrid() {
|
||||||
|
const type = lotterySelect.value;
|
||||||
|
currentMax = lotteryConfigs[type] || 60;
|
||||||
|
grid.innerHTML = '';
|
||||||
|
selectedNumbers.clear();
|
||||||
|
updateUI();
|
||||||
|
|
||||||
|
for (let i = 1; i <= currentMax; i++) {
|
||||||
|
const ball = document.createElement('div');
|
||||||
|
ball.className = 'live-ball';
|
||||||
|
ball.textContent = i.toString().padStart(2, '0');
|
||||||
|
ball.onclick = () => toggleNumber(i, ball);
|
||||||
|
grid.appendChild(ball);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function toggleNumber(num, element) {
|
||||||
|
if (selectedNumbers.has(num)) {
|
||||||
|
selectedNumbers.delete(num);
|
||||||
|
element.classList.remove('active');
|
||||||
|
} else {
|
||||||
|
selectedNumbers.add(num);
|
||||||
|
element.classList.add('active');
|
||||||
|
}
|
||||||
|
updateUI();
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateUI() {
|
||||||
|
selectCount.textContent = `${selectedNumbers.size} selecionados`;
|
||||||
|
}
|
||||||
|
|
||||||
|
lotterySelect.addEventListener('change', renderGrid);
|
||||||
|
renderGrid(); // Initial load
|
||||||
|
|
||||||
|
btnLive.onclick = async () => {
|
||||||
|
if (selectedNumbers.size < 6) {
|
||||||
|
alert('Por favor, selecione pelo menos 6 números.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
btnLive.disabled = true;
|
||||||
|
btnLive.textContent = 'PROCESSANDO MATEMÁTICA...';
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch('{% url "live_math" %}', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'X-CSRFToken': '{{ csrf_token }}'
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
lottery: lotterySelect.value,
|
||||||
|
numbers: Array.from(selectedNumbers)
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = await response.json();
|
||||||
|
if (data.error) throw new Error(data.error);
|
||||||
|
|
||||||
|
liveScore.textContent = data.score + '%';
|
||||||
|
liveScore.style.color = data.status === 'success' ? '#22c55e' : '#eab308';
|
||||||
|
|
||||||
|
// Efeito visual de sucesso
|
||||||
|
liveResultArea.style.transform = 'scale(1.1)';
|
||||||
|
setTimeout(() => liveResultArea.style.transform = 'scale(1)', 200);
|
||||||
|
|
||||||
|
} catch (err) {
|
||||||
|
alert('Erro no cálculo: ' + err.message);
|
||||||
|
} finally {
|
||||||
|
btnLive.disabled = false;
|
||||||
|
btnLive.textContent = 'CÁLCULO MATEMÁTICO AO VIVO';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.live-ball {
|
||||||
|
width: 45px;
|
||||||
|
height: 45px;
|
||||||
|
border: 2px solid #e2e8f0;
|
||||||
|
border-radius: 50%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
cursor: pointer;
|
||||||
|
font-weight: bold;
|
||||||
|
transition: all 0.2s;
|
||||||
|
user-select: none;
|
||||||
|
background: white;
|
||||||
|
color: #475569;
|
||||||
|
}
|
||||||
|
.live-ball:hover {
|
||||||
|
border-color: #198754;
|
||||||
|
transform: translateY(-2px);
|
||||||
|
}
|
||||||
|
.live-ball.active {
|
||||||
|
background: #198754;
|
||||||
|
color: white;
|
||||||
|
border-color: #198754;
|
||||||
|
box-shadow: 0 0 15px rgba(25, 135, 84, 0.4);
|
||||||
|
}
|
||||||
|
#live-result-area {
|
||||||
|
transition: all 0.3s;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
<section id="jogos" class="games-section">
|
<section id="jogos" class="games-section">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="section-header">
|
<div class="section-header">
|
||||||
|
|||||||
@ -8,4 +8,5 @@ urlpatterns = [
|
|||||||
path('admin-loto/dashboard/', views.admin_dashboard, name='admin_dashboard'),
|
path('admin-loto/dashboard/', views.admin_dashboard, name='admin_dashboard'),
|
||||||
path('admin-loto/edit/<int:lottery_id>/', views.edit_lottery, name='edit_lottery'),
|
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('admin-loto/ai-predict/<int:lottery_id>/', views.ai_auto_predict, name='ai_predict'),
|
||||||
|
path('live-math/', views.live_math, name='live_math'),
|
||||||
]
|
]
|
||||||
|
|||||||
@ -6,6 +6,8 @@ from collections import Counter
|
|||||||
|
|
||||||
from django import get_version as django_version
|
from django import get_version as django_version
|
||||||
from django.shortcuts import render, redirect, get_object_or_404
|
from django.shortcuts import render, redirect, get_object_or_404
|
||||||
|
from django.http import JsonResponse
|
||||||
|
import json
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
|
|
||||||
@ -75,11 +77,13 @@ def _format_percent(odds):
|
|||||||
return f"{percent:.6f}%".replace(".", ",")
|
return f"{percent:.6f}%".replace(".", ",")
|
||||||
|
|
||||||
def ai_auto_predict(request, lottery_id):
|
def ai_auto_predict(request, lottery_id):
|
||||||
"""Calcula automaticamente os números quentes via IA baseada em estatísticas reais."""
|
"""Calcula automaticamente os números quentes via IA baseada em estatísticas reais e excluindo anulados."""
|
||||||
if not check_admin(request):
|
if not check_admin(request):
|
||||||
return redirect('admin_login')
|
return redirect('admin_login')
|
||||||
|
|
||||||
lottery = get_object_or_404(Lottery, id=lottery_id)
|
lottery = get_object_or_404(Lottery, id=lottery_id)
|
||||||
|
annulled = [int(n) for n in lottery.annulled_numbers.split(',') if n]
|
||||||
|
|
||||||
# Pega todos os sorteios (Histórico Completo)
|
# Pega todos os sorteios (Histórico Completo)
|
||||||
draws_db = DrawResult.objects.filter(lottery=lottery)
|
draws_db = DrawResult.objects.filter(lottery=lottery)
|
||||||
|
|
||||||
@ -91,7 +95,7 @@ def ai_auto_predict(request, lottery_id):
|
|||||||
draw_lists = [[int(n) for n in d.numbers.split(',')] for d in draws_db]
|
draw_lists = [[int(n) for n in d.numbers.split(',')] for d in draws_db]
|
||||||
frequency = Counter(number for draw in draw_lists for number in draw)
|
frequency = Counter(number for draw in draw_lists for number in draw)
|
||||||
|
|
||||||
# Calcular atraso (há quantos sorteios o número não sai)
|
# Calcular atraso
|
||||||
last_seen = {}
|
last_seen = {}
|
||||||
for i, draw in enumerate(reversed(draw_lists)):
|
for i, draw in enumerate(reversed(draw_lists)):
|
||||||
for num in draw:
|
for num in draw:
|
||||||
@ -99,21 +103,24 @@ def ai_auto_predict(request, lottery_id):
|
|||||||
last_seen[num] = i
|
last_seen[num] = i
|
||||||
|
|
||||||
# Score IA = (Frequência * 0.7) + (Atraso * 0.3)
|
# Score IA = (Frequência * 0.7) + (Atraso * 0.3)
|
||||||
|
# SISTEMA ROTATIVO: Ignora números anulados no cálculo
|
||||||
scores = []
|
scores = []
|
||||||
for num in range(1, lottery.max_number + 1):
|
for num in range(1, lottery.max_number + 1):
|
||||||
|
if num in annulled:
|
||||||
|
continue
|
||||||
freq = frequency.get(num, 0)
|
freq = frequency.get(num, 0)
|
||||||
delay = last_seen.get(num, len(draw_lists))
|
delay = last_seen.get(num, len(draw_lists))
|
||||||
score = (freq * 0.7) + (delay * 0.3)
|
score = (freq * 0.7) + (delay * 0.3)
|
||||||
scores.append((num, score))
|
scores.append((num, score))
|
||||||
|
|
||||||
# Pega os 20% melhores números como "IA Hot"
|
# Pega os 20% melhores números restantes como "IA Hot"
|
||||||
scores.sort(key=lambda x: x[1], reverse=True)
|
scores.sort(key=lambda x: x[1], reverse=True)
|
||||||
top_numbers = [str(n[0]) for n in scores[:int(lottery.max_number * 0.2)]]
|
top_numbers = [str(n[0]) for n in scores[:int(lottery.max_number * 0.25)]]
|
||||||
|
|
||||||
lottery.ai_predictions = ",".join(top_numbers)
|
lottery.ai_predictions = ",".join(top_numbers)
|
||||||
lottery.save()
|
lottery.save()
|
||||||
|
|
||||||
messages.success(request, f"IA calculou as probabilidades para {lottery.get_name_display()} com sucesso!")
|
messages.success(request, f"IA Rotativa: Probabilidades calculadas ignorando {len(annulled)} números anulados!")
|
||||||
return redirect('edit_lottery', lottery_id=lottery_id)
|
return redirect('edit_lottery', lottery_id=lottery_id)
|
||||||
|
|
||||||
def home(request):
|
def home(request):
|
||||||
@ -171,13 +178,29 @@ def home(request):
|
|||||||
numbers = [n for n in range(1, lottery_obj.max_number + 1) if n not in annulled]
|
numbers = [n for n in range(1, lottery_obj.max_number + 1) if n not in annulled]
|
||||||
|
|
||||||
# Definição de Cores: Verde (Hot) e Vermelho (Frio)
|
# Definição de Cores: Verde (Hot) e Vermelho (Frio)
|
||||||
hot_numbers = ai_hot if ai_hot else [n for n, c in frequency.most_common(10)]
|
# MATEMÁTICA AO VIVO: Calcula a elite estatística no momento do acesso, ignorando anulados.
|
||||||
cold_numbers = [n for n in range(1, lottery_obj.max_number + 1) if n not in hot_numbers and n not in annulled]
|
# Pegamos os números com maior frequência que NÃO estão anulados.
|
||||||
|
available_numbers = [n for n in range(1, lottery_obj.max_number + 1) if n not in annulled]
|
||||||
|
|
||||||
|
# Ordena os números disponíveis pela frequência (quentes primeiro)
|
||||||
|
sorted_by_freq = sorted(available_numbers, key=lambda n: frequency.get(n, 0), reverse=True)
|
||||||
|
|
||||||
|
# A "Elite Verde" será composta pelos top 25% dos números mais frequentes disponíveis
|
||||||
|
hot_count = max(6, int(len(available_numbers) * 0.25))
|
||||||
|
hot_numbers = sorted_by_freq[:hot_count]
|
||||||
|
|
||||||
|
cold_numbers = [n for n in sorted_by_freq[hot_count:]]
|
||||||
|
|
||||||
suggestions = []
|
suggestions = []
|
||||||
# Se for 1 Trilhão, usamos simulação de Monte Carlo para gerar apenas as 6 "Melhores de Elite"
|
# Suporte a múltiplas escalas de Trilhões
|
||||||
is_trillion = (games_to_generate >= 1_000_000_000_000)
|
is_trillion = (games_to_generate >= 1_000_000_000_000)
|
||||||
actual_games_to_gen = 6 if is_trillion else games_to_generate
|
actual_games_to_gen = 6 if is_trillion else games_to_generate
|
||||||
|
|
||||||
|
trillion_label = ""
|
||||||
|
if games_to_generate == 1_000_000_000_000: trillion_label = "1 Trilhão"
|
||||||
|
elif games_to_generate == 10_000_000_000_000: trillion_label = "10 Trilhões"
|
||||||
|
elif games_to_generate == 30_000_000_000_000: trillion_label = "30 Trilhões"
|
||||||
|
elif games_to_generate == 60_000_000_000_000: trillion_label = "60 Trilhões"
|
||||||
|
|
||||||
for _ in range(actual_games_to_gen):
|
for _ in range(actual_games_to_gen):
|
||||||
if len(numbers) >= lottery_obj.numbers_to_draw:
|
if len(numbers) >= lottery_obj.numbers_to_draw:
|
||||||
@ -196,6 +219,7 @@ def home(request):
|
|||||||
"lottery": lottery_obj.get_name_display(),
|
"lottery": lottery_obj.get_name_display(),
|
||||||
"draws_used": len(draw_lists),
|
"draws_used": len(draw_lists),
|
||||||
"is_trillion": is_trillion,
|
"is_trillion": is_trillion,
|
||||||
|
"trillion_label": trillion_label,
|
||||||
"suggestions": suggestions,
|
"suggestions": suggestions,
|
||||||
"hot_numbers": hot_numbers,
|
"hot_numbers": hot_numbers,
|
||||||
"cold_numbers": cold_numbers[:15], # Amostra de frios
|
"cold_numbers": cold_numbers[:15], # Amostra de frios
|
||||||
@ -215,3 +239,53 @@ def home(request):
|
|||||||
"is_admin": check_admin(request),
|
"is_admin": check_admin(request),
|
||||||
}
|
}
|
||||||
return render(request, "core/index.html", context)
|
return render(request, "core/index.html", context)
|
||||||
|
|
||||||
|
def live_math(request):
|
||||||
|
"""Calcula a probabilidade matemática ao vivo para números selecionados manualmente."""
|
||||||
|
if request.method == "POST":
|
||||||
|
try:
|
||||||
|
data = json.loads(request.body)
|
||||||
|
lottery_key = data.get("lottery")
|
||||||
|
manual_numbers = [int(n) for n in data.get("numbers", [])]
|
||||||
|
|
||||||
|
if not manual_numbers or len(manual_numbers) < 6:
|
||||||
|
return JsonResponse({"error": "Selecione ao menos 6 números."}, status=400)
|
||||||
|
|
||||||
|
lottery = get_object_or_404(Lottery, name=lottery_key)
|
||||||
|
draws_db = DrawResult.objects.filter(lottery=lottery)
|
||||||
|
|
||||||
|
# Se não houver sorteios, usamos uma base simulada para a matemática ao vivo
|
||||||
|
if not draws_db.exists():
|
||||||
|
frequency = {n: random.randint(5, 15) for n in range(1, lottery.max_number + 1)}
|
||||||
|
else:
|
||||||
|
draw_lists = [[int(n) for n in d.numbers.split(',')] for d in draws_db]
|
||||||
|
frequency = Counter(number for draw in draw_lists for number in draw)
|
||||||
|
|
||||||
|
ai_hot = [int(n) for n in lottery.ai_predictions.split(',') if n]
|
||||||
|
annulled = [int(n) for n in lottery.annulled_numbers.split(',') if n]
|
||||||
|
|
||||||
|
# Cálculo de "Calor" (Heat Score)
|
||||||
|
# 1. Quantos são Verdes (IA Hot)
|
||||||
|
hits_hot = len([n for n in manual_numbers if n in ai_hot])
|
||||||
|
# 2. Quantos foram anulados (Erro crítico)
|
||||||
|
hits_annulled = len([n for n in manual_numbers if n in annulled])
|
||||||
|
|
||||||
|
# Média de frequência dos números escolhidos
|
||||||
|
avg_freq = sum(frequency.get(n, 0) for n in manual_numbers) / len(manual_numbers)
|
||||||
|
max_freq = max(frequency.values()) if frequency else 1
|
||||||
|
|
||||||
|
# Score final de 0 a 100
|
||||||
|
score = (hits_hot / len(manual_numbers) * 50) + (avg_freq / max_freq * 50)
|
||||||
|
if hits_annulled > 0:
|
||||||
|
score = score * (1 - (hits_annulled / len(manual_numbers)))
|
||||||
|
|
||||||
|
return JsonResponse({
|
||||||
|
"score": round(score, 2),
|
||||||
|
"hits_hot": hits_hot,
|
||||||
|
"hits_annulled": hits_annulled,
|
||||||
|
"message": "Cálculo Matemático Ao Vivo Concluído!",
|
||||||
|
"status": "success" if score > 50 else "warning"
|
||||||
|
})
|
||||||
|
except Exception as e:
|
||||||
|
return JsonResponse({"error": str(e)}, status=500)
|
||||||
|
return JsonResponse({"error": "Método inválido"}, status=405)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user