heathaet
This commit is contained in:
parent
4edfaf8740
commit
fe37996f7b
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
4
cookies.txt
Normal file
4
cookies.txt
Normal file
@ -0,0 +1,4 @@
|
||||
# Netscape HTTP Cookie File
|
||||
# https://curl.se/docs/http-cookies.html
|
||||
# This file was generated by libcurl! Edit at your own risk.
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1,13 +1,17 @@
|
||||
import os
|
||||
import time
|
||||
|
||||
from django.utils import timezone
|
||||
|
||||
|
||||
def project_context(request):
|
||||
"""
|
||||
Adds project-specific environment variables to the template context globally.
|
||||
"""
|
||||
"""Adds project-specific environment variables to the template context globally."""
|
||||
return {
|
||||
"project_description": os.getenv("PROJECT_DESCRIPTION", ""),
|
||||
"project_name": os.getenv("PROJECT_NAME", "Loterias BR Pro"),
|
||||
"project_description": os.getenv("PROJECT_DESCRIPTION", "Gerador inteligente de números para loterias do Brasil com histórico recente e indicadores estatísticos."),
|
||||
"project_image_url": os.getenv("PROJECT_IMAGE_URL", ""),
|
||||
"is_admin": bool(request.session.get("admin_auth")),
|
||||
"current_time": timezone.now(),
|
||||
# Used for cache-busting static assets
|
||||
"deployment_timestamp": int(time.time()),
|
||||
}
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -57,8 +57,8 @@
|
||||
</div>
|
||||
<div class="hero-stats">
|
||||
<div class="stat-card">
|
||||
<span class="stat-value">5 loterias</span>
|
||||
<span class="stat-label">Mega-Sena, Quina, Dupla Sena, Lotomania, Lotofacil</span>
|
||||
<span class="stat-value">{{ lottery_count }} loterias</span>
|
||||
<span class="stat-label">{{ lottery_overview }}</span>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<span class="stat-value">Analise recencia</span>
|
||||
@ -81,7 +81,7 @@
|
||||
<div class="mb-3">
|
||||
<label class="form-label" for="{{ form.lottery_type.id_for_label }}">{{ form.lottery_type.label }}</label>
|
||||
{{ form.lottery_type }}
|
||||
<div class="form-text">Baseado no historico recente simulado ate o admin importar dados reais.</div>
|
||||
<div class="form-text">Baseado no histórico recente já restaurado no banco e nas configurações atuais de cada loteria.</div>
|
||||
{{ form.lottery_type.errors }}
|
||||
</div>
|
||||
<div class="row g-3">
|
||||
@ -258,17 +258,11 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
let selectedNumbers = new Set();
|
||||
let currentMax = 60;
|
||||
|
||||
const lotteryConfigs = {
|
||||
'mega_sena': 60,
|
||||
'quina': 80,
|
||||
'dupla_sena': 50,
|
||||
'lotomania': 100,
|
||||
'lotofacil': 25
|
||||
};
|
||||
const lotteryConfigs = {{ lottery_configs_json|safe }};
|
||||
|
||||
function renderGrid() {
|
||||
const type = lotterySelect.value;
|
||||
currentMax = lotteryConfigs[type] || 60;
|
||||
currentMax = (lotteryConfigs[type] && lotteryConfigs[type].max_number) || 60;
|
||||
grid.innerHTML = '';
|
||||
selectedNumbers.clear();
|
||||
updateUI();
|
||||
@ -301,8 +295,9 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
renderGrid(); // Initial load
|
||||
|
||||
btnLive.onclick = async () => {
|
||||
if (selectedNumbers.size < 6) {
|
||||
alert('Por favor, selecione pelo menos 6 números.');
|
||||
const minimumRequired = (lotteryConfigs[lotterySelect.value] && lotteryConfigs[lotterySelect.value].numbers_to_draw) || 6;
|
||||
if (selectedNumbers.size < minimumRequired) {
|
||||
alert(`Por favor, selecione pelo menos ${minimumRequired} números para esta loteria.`);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
365
core/views.py
365
core/views.py
@ -1,72 +1,259 @@
|
||||
from django.shortcuts import render, get_object_or_404, redirect
|
||||
from django.http import JsonResponse, HttpResponse
|
||||
from .models import Lottery, DrawResult, AdminAccess
|
||||
from collections import Counter
|
||||
import random
|
||||
from django import get_version
|
||||
import json
|
||||
import csv
|
||||
import json
|
||||
import math
|
||||
import random
|
||||
|
||||
from django import get_version
|
||||
from django.http import HttpResponse, JsonResponse
|
||||
from django.shortcuts import get_object_or_404, redirect, render
|
||||
|
||||
from .forms import LotterySimulatorForm
|
||||
from .models import AdminAccess, DrawResult, Lottery
|
||||
|
||||
|
||||
def _format_int(value):
|
||||
return f"{int(value):,}".replace(",", ".")
|
||||
|
||||
|
||||
def _format_percent(value):
|
||||
if value <= 0:
|
||||
return "0%"
|
||||
if value < 0.000001:
|
||||
return "< 0,000001%"
|
||||
return f"{value:.6f}%".replace(".", ",")
|
||||
|
||||
|
||||
def _parse_annulled_numbers(lottery):
|
||||
return [int(number.strip()) for number in lottery.annulled_numbers.split(",") if number.strip().isdigit()]
|
||||
|
||||
|
||||
def _lottery_queryset():
|
||||
return Lottery.objects.all().order_by("id")
|
||||
|
||||
|
||||
def _lottery_choices():
|
||||
return [(lottery.name, lottery.get_name_display()) for lottery in _lottery_queryset()]
|
||||
|
||||
|
||||
def _get_recent_draws(lottery, draws_to_consider=0):
|
||||
queryset = DrawResult.objects.filter(lottery=lottery).order_by("-draw_number")
|
||||
if draws_to_consider:
|
||||
queryset = queryset[:draws_to_consider]
|
||||
return [[int(number) for number in draw.numbers.split(",") if number] for draw in queryset]
|
||||
|
||||
|
||||
def _rank_numbers(lottery, draw_matrix):
|
||||
total_draws = len(draw_matrix)
|
||||
if not total_draws:
|
||||
ordered = list(range(1, lottery.max_number + 1))
|
||||
return ordered, ordered[: lottery.numbers_to_draw], ordered[-lottery.numbers_to_draw :]
|
||||
|
||||
counts = Counter(number for draw in draw_matrix for number in draw)
|
||||
last_seen = {}
|
||||
for index, draw in enumerate(draw_matrix):
|
||||
for number in draw:
|
||||
last_seen.setdefault(number, index)
|
||||
|
||||
scored = []
|
||||
for number in range(1, lottery.max_number + 1):
|
||||
frequency_score = counts.get(number, 0) / total_draws
|
||||
delay_score = last_seen.get(number, total_draws) / total_draws
|
||||
total_score = (frequency_score * 0.7) + (delay_score * 0.3)
|
||||
scored.append((number, total_score))
|
||||
|
||||
scored.sort(key=lambda item: (-item[1], item[0]))
|
||||
ranked_numbers = [number for number, _ in scored]
|
||||
hot_numbers = ranked_numbers[: lottery.numbers_to_draw]
|
||||
cold_numbers = [number for number, _ in sorted(scored, key=lambda item: (item[1], item[0]))[: lottery.numbers_to_draw]]
|
||||
return ranked_numbers, hot_numbers, cold_numbers
|
||||
|
||||
|
||||
def _generate_suggestions(lottery, ranked_numbers, games_requested, annulled_numbers):
|
||||
if not ranked_numbers:
|
||||
ranked_numbers = list(range(1, lottery.max_number + 1))
|
||||
|
||||
filtered_pool = [number for number in ranked_numbers if number not in annulled_numbers]
|
||||
if len(filtered_pool) < lottery.numbers_to_draw:
|
||||
filtered_pool = ranked_numbers[:]
|
||||
|
||||
pool_size = min(len(filtered_pool), max(lottery.numbers_to_draw * 4, lottery.numbers_to_draw))
|
||||
candidate_pool = filtered_pool[:pool_size]
|
||||
display_total = min(games_requested, 12) if games_requested < 1_000_000_000_000 else 6
|
||||
|
||||
suggestions = []
|
||||
seen = set()
|
||||
attempt = 0
|
||||
while len(suggestions) < display_total and attempt < display_total * 10:
|
||||
generator = random.Random(f"{lottery.name}:{games_requested}:{attempt}:{','.join(map(str, candidate_pool[:20]))}")
|
||||
sample = sorted(generator.sample(candidate_pool, k=min(lottery.numbers_to_draw, len(candidate_pool))))
|
||||
key = tuple(sample)
|
||||
if key not in seen and len(sample) == lottery.numbers_to_draw:
|
||||
seen.add(key)
|
||||
suggestions.append(sample)
|
||||
attempt += 1
|
||||
|
||||
if not suggestions:
|
||||
suggestions.append(sorted(candidate_pool[: lottery.numbers_to_draw]))
|
||||
|
||||
return suggestions
|
||||
|
||||
|
||||
def _build_lottery_cards(lotteries):
|
||||
tagline_map = {
|
||||
"mega_sena": "6 dezenas no volante principal",
|
||||
"quina": "5 dezenas com universo amplo",
|
||||
"dupla_sena": "duas chances por concurso",
|
||||
"lotomania": "análise ampla para dezenas recorrentes",
|
||||
"lotofacil": "equilíbrio para 15 dezenas",
|
||||
"timemania": "histórico recente com foco estatístico",
|
||||
"dia_de_sorte": "recorte curto com leitura de frequência",
|
||||
"federal": "modelo estatístico interno por sequência",
|
||||
"super_sete": "sequências compactas por coluna",
|
||||
"maismilionaria": "base principal de 6 dezenas",
|
||||
}
|
||||
|
||||
cards = []
|
||||
for lottery in lotteries:
|
||||
try:
|
||||
combinations = math.comb(lottery.max_number, lottery.numbers_to_draw)
|
||||
odds = f"1 em {_format_int(combinations)}"
|
||||
except ValueError:
|
||||
odds = "Configuração personalizada"
|
||||
|
||||
cards.append({
|
||||
"label": lottery.get_name_display(),
|
||||
"tagline": tagline_map.get(lottery.name, "Análise estatística por histórico real"),
|
||||
"picks": lottery.numbers_to_draw,
|
||||
"range_max": lottery.max_number,
|
||||
"odds": odds,
|
||||
})
|
||||
return cards
|
||||
|
||||
|
||||
def _build_home_result(form):
|
||||
if not form.is_valid():
|
||||
return None
|
||||
|
||||
lottery = get_object_or_404(Lottery, name=form.cleaned_data["lottery_type"])
|
||||
draws_to_consider = int(form.cleaned_data["draws_to_consider"])
|
||||
games_requested = int(form.cleaned_data["games_to_generate"])
|
||||
draw_matrix = _get_recent_draws(lottery, draws_to_consider)
|
||||
ranked_numbers, hot_numbers, cold_numbers = _rank_numbers(lottery, draw_matrix)
|
||||
annulled_numbers = _parse_annulled_numbers(lottery)
|
||||
reclaimed_numbers = [number for number in hot_numbers if number in annulled_numbers]
|
||||
total_combinations = math.comb(lottery.max_number, lottery.numbers_to_draw)
|
||||
probability = 100 / total_combinations if total_combinations else 0
|
||||
suggestions = _generate_suggestions(lottery, ranked_numbers, games_requested, annulled_numbers)
|
||||
|
||||
trillion_labels = {
|
||||
1000000000000: "1 trilhão",
|
||||
10000000000000: "10 trilhões",
|
||||
30000000000000: "30 trilhões",
|
||||
60000000000000: "60 trilhões",
|
||||
}
|
||||
|
||||
return {
|
||||
"lottery": lottery.get_name_display(),
|
||||
"draws_used": len(draw_matrix),
|
||||
"total_combinations": _format_int(total_combinations),
|
||||
"odds": f"1 em {_format_int(total_combinations)}",
|
||||
"percent": _format_percent(probability),
|
||||
"hot_numbers": hot_numbers,
|
||||
"cold_numbers": cold_numbers,
|
||||
"annulled_numbers": annulled_numbers,
|
||||
"reclaimed_numbers": reclaimed_numbers,
|
||||
"suggestions": suggestions,
|
||||
"is_trillion": games_requested >= 1000000000000,
|
||||
"trillion_label": trillion_labels.get(games_requested, _format_int(games_requested)),
|
||||
}
|
||||
|
||||
|
||||
def home(request):
|
||||
"""Página inicial com resumo das estatísticas de IA."""
|
||||
loterias = Lottery.objects.all()
|
||||
"""Página inicial com resumo das estatísticas e simulador principal."""
|
||||
lotteries = list(_lottery_queryset())
|
||||
form = LotterySimulatorForm(
|
||||
request.POST or None,
|
||||
lottery_choices=[(lottery.name, lottery.get_name_display()) for lottery in lotteries],
|
||||
)
|
||||
result = _build_home_result(form) if request.method == "POST" else None
|
||||
|
||||
stats = []
|
||||
for lottery in loterias:
|
||||
last_draw = DrawResult.objects.filter(lottery=lottery).order_by('-draw_number').first()
|
||||
for lottery in lotteries:
|
||||
last_draw = DrawResult.objects.filter(lottery=lottery).order_by("-draw_number").first()
|
||||
stats.append({
|
||||
'name': lottery.get_name_display(),
|
||||
'key': lottery.name,
|
||||
'last_draw': last_draw.draw_number if last_draw else "N/A",
|
||||
'last_numbers': last_draw.numbers.split(',') if last_draw else [],
|
||||
'max_number': lottery.max_number
|
||||
"name": lottery.get_name_display(),
|
||||
"key": lottery.name,
|
||||
"last_draw": last_draw.draw_number if last_draw else "N/A",
|
||||
"last_numbers": last_draw.numbers.split(",") if last_draw else [],
|
||||
"max_number": lottery.max_number,
|
||||
"numbers_to_draw": lottery.numbers_to_draw,
|
||||
})
|
||||
return render(request, "core/index.html", {"stats": stats, "django_version": get_version()})
|
||||
|
||||
overview_names = [lottery.get_name_display() for lottery in lotteries[:4]]
|
||||
lottery_configs = {
|
||||
lottery.name: {
|
||||
"max_number": lottery.max_number,
|
||||
"numbers_to_draw": lottery.numbers_to_draw,
|
||||
}
|
||||
for lottery in lotteries
|
||||
}
|
||||
|
||||
context = {
|
||||
"form": form,
|
||||
"result": result,
|
||||
"stats": stats,
|
||||
"django_version": get_version(),
|
||||
"lottery_cards": _build_lottery_cards(lotteries),
|
||||
"lottery_count": len(lotteries),
|
||||
"lottery_overview": ", ".join(overview_names) + (" e mais" if len(lotteries) > 4 else ""),
|
||||
"lottery_configs_json": json.dumps(lottery_configs),
|
||||
}
|
||||
return render(request, "core/index.html", context)
|
||||
|
||||
|
||||
def lottery_info_api(request, lottery_key):
|
||||
"""
|
||||
Supercomputador de Elite 99.9% - Sincronizado com 10.000 concursos.
|
||||
Calcula dezenas de elite baseadas em convergência matemática de alto desempenho.
|
||||
"""
|
||||
"""Retorna indicadores estatísticos da loteria selecionada para o gerador sequencial."""
|
||||
lottery = get_object_or_404(Lottery, name=lottery_key)
|
||||
annulled = [int(n) for n in lottery.annulled_numbers.split(',') if n]
|
||||
|
||||
draws_db = DrawResult.objects.filter(lottery=lottery).order_by('draw_number')
|
||||
real_draws = [[int(n) for n in d.numbers.split(',')] for d in draws_db]
|
||||
annulled = _parse_annulled_numbers(lottery)
|
||||
|
||||
draws_db = DrawResult.objects.filter(lottery=lottery).order_by("draw_number")
|
||||
real_draws = [[int(n) for n in draw.numbers.split(",")] for draw in draws_db]
|
||||
last_real_num = draws_db.last().draw_number if draws_db.exists() else 0
|
||||
|
||||
|
||||
random.seed(f"{lottery_key}_supercomputer")
|
||||
all_draws = list(real_draws)
|
||||
max_num = lottery.max_number
|
||||
n_draw = lottery.numbers_to_draw
|
||||
|
||||
|
||||
while len(all_draws) < 10000:
|
||||
hist_flat = [n for d in all_draws[-50:] for n in d]
|
||||
hist_flat = [number for draw in all_draws[-50:] for number in draw]
|
||||
counts = Counter(hist_flat)
|
||||
candidates = []
|
||||
for n in range(1, max_num + 1):
|
||||
score = 100 - (counts.get(n, 0) * 2)
|
||||
candidates.append((n, score + random.randint(1, 10)))
|
||||
candidates.sort(key=lambda x: x[1], reverse=True)
|
||||
all_draws.append(sorted([c[0] for c in candidates[:n_draw]]))
|
||||
for number in range(1, max_num + 1):
|
||||
score = 100 - (counts.get(number, 0) * 2)
|
||||
candidates.append((number, score + random.randint(1, 10)))
|
||||
candidates.sort(key=lambda item: item[1], reverse=True)
|
||||
all_draws.append(sorted(candidate[0] for candidate in candidates[:n_draw]))
|
||||
|
||||
global_counts = Counter(n for d in all_draws for n in d)
|
||||
global_counts = Counter(number for draw in all_draws for number in draw)
|
||||
last_seen_real = {}
|
||||
if real_draws:
|
||||
for i, d in enumerate(reversed(real_draws)):
|
||||
for n in d:
|
||||
if n not in last_seen_real: last_seen_real[n] = i
|
||||
|
||||
elite_candidates = []
|
||||
for n in range(1, max_num + 1):
|
||||
if n in annulled: continue
|
||||
freq_score = (global_counts.get(n, 0) / 10000.0) * 100
|
||||
delay_score = last_seen_real.get(n, len(real_draws)) * 1.5
|
||||
total_score = (freq_score * 0.4) + (delay_score * 0.6)
|
||||
elite_candidates.append({'num': n, 'score': total_score})
|
||||
for index, draw in enumerate(reversed(real_draws)):
|
||||
for number in draw:
|
||||
last_seen_real.setdefault(number, index)
|
||||
|
||||
elite_candidates.sort(key=lambda x: x['score'], reverse=True)
|
||||
elite_greens = [c['num'] for c in elite_candidates[:20]]
|
||||
next_prediction = sorted([c['num'] for c in elite_candidates[:n_draw]])
|
||||
elite_candidates = []
|
||||
for number in range(1, max_num + 1):
|
||||
if number in annulled:
|
||||
continue
|
||||
freq_score = (global_counts.get(number, 0) / 10000.0) * 100
|
||||
delay_score = last_seen_real.get(number, len(real_draws)) * 1.5
|
||||
total_score = (freq_score * 0.4) + (delay_score * 0.6)
|
||||
elite_candidates.append({"num": number, "score": total_score})
|
||||
|
||||
elite_candidates.sort(key=lambda item: item["score"], reverse=True)
|
||||
elite_greens = [candidate["num"] for candidate in elite_candidates[:20]]
|
||||
next_prediction = sorted(candidate["num"] for candidate in elite_candidates[:n_draw])
|
||||
|
||||
return JsonResponse({
|
||||
"name": lottery.get_name_display(),
|
||||
@ -74,78 +261,112 @@ def lottery_info_api(request, lottery_key):
|
||||
"numbers_to_draw": lottery.numbers_to_draw,
|
||||
"elite_greens": elite_greens,
|
||||
"annulled_numbers": annulled,
|
||||
"reclaimed_numbers": [n for n in elite_greens if n in annulled][:5],
|
||||
"reclaimed_numbers": [number for number in elite_greens if number in annulled][:5],
|
||||
"supercomputer_sync": 10000,
|
||||
"last_real_contest": last_real_num,
|
||||
"next_prediction": next_prediction,
|
||||
"precision": "99.9%"
|
||||
"precision": "99.9%",
|
||||
})
|
||||
|
||||
|
||||
def sequential_generator(request):
|
||||
loterias = Lottery.objects.all()
|
||||
loterias = _lottery_queryset()
|
||||
return render(request, "core/sequential_generator.html", {"loterias": loterias})
|
||||
|
||||
|
||||
def lottery_results(request):
|
||||
loterias = Lottery.objects.all()
|
||||
loterias = _lottery_queryset()
|
||||
results_data = []
|
||||
for lottery in loterias:
|
||||
all_draws = DrawResult.objects.filter(lottery=lottery).order_by('-draw_number')
|
||||
all_draws = DrawResult.objects.filter(lottery=lottery).order_by("-draw_number")
|
||||
if all_draws.exists():
|
||||
current_draw = all_draws.first()
|
||||
current_numbers = [n.strip().zfill(2) for n in current_draw.numbers.split(',')]
|
||||
current_numbers = [number.strip().zfill(2) for number in current_draw.numbers.split(",")]
|
||||
results_data.append({
|
||||
'lottery': lottery,
|
||||
'last_draw': current_draw,
|
||||
'current_numbers': current_numbers,
|
||||
'prediction': ["??"] * lottery.numbers_to_draw
|
||||
"lottery": lottery,
|
||||
"last_draw": current_draw,
|
||||
"current_numbers": current_numbers,
|
||||
"prediction": ["??"] * lottery.numbers_to_draw,
|
||||
})
|
||||
return render(request, "core/results_ia.html", {"results": results_data})
|
||||
|
||||
|
||||
def hits_report(request):
|
||||
return render(request, "core/hits_report.html")
|
||||
|
||||
|
||||
def admin_login(request):
|
||||
if request.method == "POST":
|
||||
key = request.POST.get("private_key")
|
||||
if AdminAccess.objects.filter(private_key=key).exists() or key == "admin123":
|
||||
request.session['admin_auth'] = True
|
||||
return redirect('admin_dashboard')
|
||||
request.session["admin_auth"] = True
|
||||
return redirect("admin_dashboard")
|
||||
return render(request, "core/admin_login.html")
|
||||
|
||||
|
||||
def admin_logout(request):
|
||||
request.session.flush()
|
||||
return redirect('home')
|
||||
return redirect("home")
|
||||
|
||||
|
||||
def admin_dashboard(request):
|
||||
if not request.session.get('admin_auth'): return redirect('admin_login')
|
||||
loterias = Lottery.objects.all()
|
||||
if not request.session.get("admin_auth"):
|
||||
return redirect("admin_login")
|
||||
loterias = _lottery_queryset()
|
||||
return render(request, "core/admin_dashboard.html", {"loterias": loterias})
|
||||
|
||||
|
||||
def edit_lottery(request, lottery_id):
|
||||
if not request.session.get('admin_auth'): return redirect('admin_login')
|
||||
if not request.session.get("admin_auth"):
|
||||
return redirect("admin_login")
|
||||
lottery = get_object_or_404(Lottery, id=lottery_id)
|
||||
if request.method == "POST":
|
||||
lottery.annulled_numbers = request.POST.get("annulled_numbers", "")
|
||||
lottery.save()
|
||||
return redirect('admin_dashboard')
|
||||
return redirect("admin_dashboard")
|
||||
return render(request, "core/edit_lottery.html", {"lottery": lottery})
|
||||
|
||||
|
||||
def full_report(request):
|
||||
return render(request, "core/full_report.html")
|
||||
|
||||
|
||||
def download_funnel(request, lottery_id):
|
||||
lottery = get_object_or_404(Lottery, id=lottery_id)
|
||||
response = HttpResponse(content_type='text/csv')
|
||||
response['Content-Disposition'] = f'attachment; filename="funnel_{lottery.name}.csv"'
|
||||
response = HttpResponse(content_type="text/csv")
|
||||
response["Content-Disposition"] = f'attachment; filename="funnel_{lottery.name}.csv"'
|
||||
writer = csv.writer(response)
|
||||
writer.writerow(['Number', 'Status'])
|
||||
annulled = lottery.annulled_numbers.split(',')
|
||||
for n in range(1, lottery.max_number + 1):
|
||||
writer.writerow([n, 'Annulled' if str(n) in annulled else 'Active'])
|
||||
writer.writerow(["Number", "Status"])
|
||||
annulled = lottery.annulled_numbers.split(",")
|
||||
for number in range(1, lottery.max_number + 1):
|
||||
writer.writerow([number, "Annulled" if str(number) in annulled else "Active"])
|
||||
return response
|
||||
|
||||
|
||||
def ai_auto_predict(request, lottery_id=None):
|
||||
return JsonResponse({"status": "success", "message": "Neural re-calibration complete."})
|
||||
|
||||
|
||||
def live_math(request):
|
||||
return JsonResponse({"status": "live", "data": random.sample(range(1, 61), 6)})
|
||||
if request.method != "POST":
|
||||
return JsonResponse({"error": "Método não permitido."}, status=405)
|
||||
|
||||
payload = json.loads(request.body or "{}")
|
||||
lottery_key = payload.get("lottery")
|
||||
numbers = [int(number) for number in payload.get("numbers", []) if str(number).isdigit()]
|
||||
lottery = get_object_or_404(Lottery, name=lottery_key)
|
||||
|
||||
draw_matrix = _get_recent_draws(lottery, 50)
|
||||
ranked_numbers, hot_numbers, _ = _rank_numbers(lottery, draw_matrix)
|
||||
top_window = set(ranked_numbers[: max(lottery.numbers_to_draw * 2, lottery.numbers_to_draw)])
|
||||
overlap_score = sum(1 for number in numbers if number in top_window)
|
||||
hot_overlap = sum(1 for number in numbers if number in hot_numbers)
|
||||
diversity_bonus = 5 if len(set(number % 2 for number in numbers)) > 1 else 0
|
||||
score = min(99, 35 + (overlap_score * 8) + (hot_overlap * 10) + diversity_bonus)
|
||||
|
||||
return JsonResponse({
|
||||
"status": "success" if score >= 70 else "warning",
|
||||
"score": score,
|
||||
"numbers_checked": len(numbers),
|
||||
"lottery": lottery.get_name_display(),
|
||||
})
|
||||
|
||||
158
restore_app.py
158
restore_app.py
@ -1,87 +1,107 @@
|
||||
import os
|
||||
import django
|
||||
import requests
|
||||
from datetime import datetime
|
||||
|
||||
# Setup Django environment
|
||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings')
|
||||
import django
|
||||
import requests
|
||||
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings")
|
||||
django.setup()
|
||||
|
||||
from core.models import Lottery, DrawResult, AdminAccess
|
||||
from core.models import AdminAccess, DrawResult, Lottery
|
||||
|
||||
|
||||
LOTTERIES = [
|
||||
{"name": "mega_sena", "api_name": "megasena", "min": 1, "max": 60, "draw": 6},
|
||||
{"name": "quina", "api_name": "quina", "min": 1, "max": 80, "draw": 5},
|
||||
{"name": "dupla_sena", "api_name": "duplasena", "min": 1, "max": 50, "draw": 6},
|
||||
{"name": "lotomania", "api_name": "lotomania", "min": 0, "max": 99, "draw": 50},
|
||||
{"name": "lotofacil", "api_name": "lotofacil", "min": 1, "max": 25, "draw": 15},
|
||||
{"name": "timemania", "api_name": "timemania", "min": 1, "max": 80, "draw": 7},
|
||||
{"name": "dia_de_sorte", "api_name": "diadesorte", "min": 1, "max": 31, "draw": 7},
|
||||
{"name": "federal", "api_name": "federal", "min": 0, "max": 99999, "draw": 5},
|
||||
{"name": "super_sete", "api_name": "supersete", "min": 0, "max": 9, "draw": 7},
|
||||
{"name": "maismilionaria", "api_name": "maismilionaria", "min": 1, "max": 50, "draw": 6},
|
||||
]
|
||||
|
||||
|
||||
def restore_lotteries():
|
||||
lotteries_data = [
|
||||
('mega_sena', 1, 60, 6),
|
||||
('quina', 1, 80, 5),
|
||||
('dupla_sena', 1, 50, 6),
|
||||
('lotomania', 0, 99, 50),
|
||||
('lotofacil', 1, 25, 15),
|
||||
('timemania', 1, 80, 7),
|
||||
('dia_de_sorte', 1, 31, 7),
|
||||
('federal', 0, 99999, 5),
|
||||
('super_sete', 0, 9, 7),
|
||||
('maismilionaria', 1, 50, 6),
|
||||
]
|
||||
|
||||
for name, min_n, max_n, to_draw in lotteries_data:
|
||||
Lottery.objects.get_or_create(
|
||||
name=name,
|
||||
created = 0
|
||||
for item in LOTTERIES:
|
||||
lottery, was_created = Lottery.objects.get_or_create(
|
||||
name=item["name"],
|
||||
defaults={
|
||||
'min_number': min_n,
|
||||
'max_number': max_n,
|
||||
'numbers_to_draw': to_draw
|
||||
}
|
||||
"min_number": item["min"],
|
||||
"max_number": item["max"],
|
||||
"numbers_to_draw": item["draw"],
|
||||
},
|
||||
)
|
||||
print("Loterias inicializadas.")
|
||||
if not was_created:
|
||||
changed = False
|
||||
for field, value in {
|
||||
"min_number": item["min"],
|
||||
"max_number": item["max"],
|
||||
"numbers_to_draw": item["draw"],
|
||||
}.items():
|
||||
if getattr(lottery, field) != value:
|
||||
setattr(lottery, field, value)
|
||||
changed = True
|
||||
if changed:
|
||||
lottery.save(update_fields=["min_number", "max_number", "numbers_to_draw"])
|
||||
created += int(was_created)
|
||||
print(f"Loterias prontas. Novas criadas: {created}")
|
||||
|
||||
|
||||
def restore_admin():
|
||||
if not AdminAccess.objects.exists():
|
||||
admin = AdminAccess.objects.create(private_key='admin123')
|
||||
print(f"Chave Admin criada: {admin.private_key}")
|
||||
else:
|
||||
print(f"Chave Admin existente: {AdminAccess.objects.first().private_key}")
|
||||
admin, created = AdminAccess.objects.get_or_create(private_key="admin123")
|
||||
print(f"Chave admin pronta: {admin.private_key} ({'nova' if created else 'existente'})")
|
||||
|
||||
def sync_all_latest():
|
||||
from core.views import sync_results
|
||||
sync_results()
|
||||
print("Sincronização dos últimos resultados concluída.")
|
||||
|
||||
def sync_specific(lottery_name, contest_number):
|
||||
mapping = {
|
||||
'mega_sena': 'megasena',
|
||||
'lotofacil': 'lotofacil',
|
||||
}
|
||||
api_name = mapping.get(lottery_name)
|
||||
if not api_name: return
|
||||
def sync_history(draws_per_lottery=40):
|
||||
session = requests.Session()
|
||||
inserted = 0
|
||||
|
||||
for item in LOTTERIES:
|
||||
lottery = Lottery.objects.get(name=item["name"])
|
||||
latest_url = f"https://loteriascaixa-api.herokuapp.com/api/{item['api_name']}/latest"
|
||||
latest_response = session.get(latest_url, timeout=15)
|
||||
latest_response.raise_for_status()
|
||||
latest_data = latest_response.json()
|
||||
latest_contest = int(latest_data["concurso"])
|
||||
|
||||
current_inserted = 0
|
||||
for contest in range(latest_contest, max(latest_contest - draws_per_lottery, 0), -1):
|
||||
contest_url = f"https://loteriascaixa-api.herokuapp.com/api/{item['api_name']}/{contest}"
|
||||
response = session.get(contest_url, timeout=15)
|
||||
if response.status_code != 200:
|
||||
continue
|
||||
|
||||
lottery = Lottery.objects.get(name=lottery_name)
|
||||
try:
|
||||
url = f"https://loteriascaixa-api.herokuapp.com/api/{api_name}/{contest_number}"
|
||||
response = requests.get(url, timeout=5)
|
||||
if response.status_code == 200:
|
||||
data = response.json()
|
||||
draw_number = int(data.get('concurso'))
|
||||
if not DrawResult.objects.filter(lottery=lottery, draw_number=draw_number).exists():
|
||||
date_str = data.get('data')
|
||||
draw_date = datetime.strptime(date_str, "%d/%m/%Y").date()
|
||||
numbers_list = data.get('dezenas', [])
|
||||
numbers_str = ",".join([str(int(n)) for n in numbers_list])
|
||||
DrawResult.objects.create(
|
||||
lottery=lottery,
|
||||
draw_number=draw_number,
|
||||
draw_date=draw_date,
|
||||
numbers=numbers_str
|
||||
)
|
||||
print(f"Sincronizado específico: {lottery_name} Concurso {draw_number}")
|
||||
except Exception as e:
|
||||
print(f"Erro ao sincronizar {lottery_name} {contest_number}: {e}")
|
||||
dezenas = data.get("dezenas") or []
|
||||
if not dezenas:
|
||||
continue
|
||||
|
||||
if __name__ == "__main__":
|
||||
draw_date = datetime.strptime(data["data"], "%d/%m/%Y").date()
|
||||
numbers_str = ",".join(str(int(number)) for number in dezenas)
|
||||
|
||||
_, created = DrawResult.objects.get_or_create(
|
||||
lottery=lottery,
|
||||
draw_number=int(data["concurso"]),
|
||||
defaults={"draw_date": draw_date, "numbers": numbers_str},
|
||||
)
|
||||
inserted += int(created)
|
||||
current_inserted += int(created)
|
||||
|
||||
print(f"{item['name']}: ultimo={latest_contest}, novos={current_inserted}")
|
||||
|
||||
print(f"Total de resultados inseridos agora: {inserted}")
|
||||
|
||||
|
||||
def main():
|
||||
restore_lotteries()
|
||||
restore_admin()
|
||||
sync_all_latest()
|
||||
# Concursos solicitados na história
|
||||
for contest in [2976, 2977]:
|
||||
sync_specific('mega_sena', contest)
|
||||
sync_specific('lotofacil', contest)
|
||||
print("Restauração concluída!")
|
||||
sync_history(draws_per_lottery=40)
|
||||
print("Restauração concluída com sucesso.")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user