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)