38545-vm/core/views.py
2026-02-18 01:17:28 +00:00

195 lines
6.0 KiB
Python

import math
import os
import platform
import random
from collections import Counter
from django import get_version as django_version
from django.shortcuts import render
from django.utils import timezone
from .forms import LotterySimulatorForm
LOTTERY_CONFIGS = {
"mega_sena": {
"label": "Mega-Sena",
"range_max": 60,
"picks": 6,
"sample_draws": 15,
"seed": 1982,
"tagline": "6 dezenas entre 60",
},
"quina": {
"label": "Quina",
"range_max": 80,
"picks": 5,
"sample_draws": 15,
"seed": 1971,
"tagline": "5 dezenas entre 80",
},
"dupla_sena": {
"label": "Dupla Sena",
"range_max": 50,
"picks": 6,
"sample_draws": 15,
"seed": 1990,
"tagline": "6 dezenas entre 50",
},
"lotomania": {
"label": "Lotomania",
"range_max": 100,
"picks": 50,
"sample_draws": 12,
"seed": 1999,
"tagline": "50 dezenas entre 100",
},
"lotofacil": {
"label": "Lotofacil",
"range_max": 25,
"picks": 15,
"sample_draws": 20,
"seed": 1994,
"tagline": "15 dezenas entre 25",
},
}
def _generate_sample_draws(config):
rng = random.Random(config["seed"])
draws = []
population = list(range(1, config["range_max"] + 1))
for _ in range(config["sample_draws"]):
draws.append(sorted(rng.sample(population, config["picks"])))
return draws
def _weighted_unique_sample(numbers, weights, picks, rng):
available = list(zip(numbers, weights))
selection = []
for _ in range(picks):
total_weight = sum(weight for _, weight in available)
if total_weight <= 0:
choice = rng.choice(available)
selection.append(choice[0])
available.remove(choice)
continue
pick = rng.uniform(0, total_weight)
cumulative = 0
for index, (number, weight) in enumerate(available):
cumulative += weight
if cumulative >= pick:
selection.append(number)
del available[index]
break
return selection
def _format_odds(total_combinations):
if total_combinations >= 1_000_000_000_000:
return f"1 em {total_combinations:.2e}"
return f"1 em {total_combinations:,}".replace(",", ".")
def _format_percent(odds):
percent = 100 / odds
if percent < 0.000001:
return "<0,000001%"
return f"{percent:.6f}%".replace(".", ",")
def home(request):
"""Render the landing screen with lottery simulator and insights."""
host_name = request.get_host().lower()
agent_brand = "AppWizzy" if host_name == "appwizzy.com" else "Flatlogic"
now = timezone.now()
lottery_choices = [
(key, config["label"]) for key, config in LOTTERY_CONFIGS.items()
]
lottery_cards = []
for key, config in LOTTERY_CONFIGS.items():
total_combinations = math.comb(config["range_max"], config["picks"])
lottery_cards.append(
{
"key": key,
"label": config["label"],
"tagline": config["tagline"],
"range_max": config["range_max"],
"picks": config["picks"],
"odds": _format_odds(total_combinations),
}
)
form = LotterySimulatorForm(
request.POST or None,
lottery_choices=lottery_choices,
)
result = None
if form.is_valid():
lottery_key = form.cleaned_data["lottery_type"]
draws_to_consider = form.cleaned_data["draws_to_consider"]
games_to_generate = form.cleaned_data["games_to_generate"]
config = LOTTERY_CONFIGS[lottery_key]
draws = _generate_sample_draws(config)
draws_to_consider = min(draws_to_consider, len(draws))
recent_draws = draws[-draws_to_consider:]
frequency = Counter(
number for draw in recent_draws for number in draw
)
numbers = list(range(1, config["range_max"] + 1))
weights = [frequency.get(number, 0) + 1 for number in numbers]
rng = random.Random(f"{lottery_key}-{draws_to_consider}-{games_to_generate}")
suggestions = []
for _ in range(games_to_generate):
suggestion = _weighted_unique_sample(
numbers, weights, config["picks"], rng
)
suggestions.append(sorted(suggestion))
total_combinations = math.comb(config["range_max"], config["picks"])
hot_numbers = [
number for number, _ in frequency.most_common(8)
]
cold_numbers = [
number
for number, _ in sorted(
frequency.items(), key=lambda item: item[1]
)
]
missing_numbers = [
number for number in numbers if number not in frequency
]
cold_numbers = (missing_numbers + cold_numbers)[:8]
result = {
"lottery": config["label"],
"draws_used": draws_to_consider,
"total_combinations": f"{total_combinations:,}".replace(",", "."),
"odds": _format_odds(total_combinations),
"percent": _format_percent(total_combinations),
"suggestions": suggestions,
"hot_numbers": hot_numbers,
"cold_numbers": cold_numbers,
}
context = {
"project_name": "LotoPulse",
"project_description": (
"Analise loterias brasileiras, gere jogos e acompanhe "
"probabilidades com base nos sorteios mais recentes."
),
"agent_brand": agent_brand,
"django_version": django_version(),
"python_version": platform.python_version(),
"current_time": now,
"host_name": host_name,
"project_image_url": os.getenv("PROJECT_IMAGE_URL", ""),
"deployment_timestamp": now.strftime("%Y%m%d%H%M%S"),
"form": form,
"result": result,
"lottery_cards": lottery_cards,
}
return render(request, "core/index.html", context)