Initial commit

This commit is contained in:
Florian Sylvain
2025-03-22 22:37:21 +01:00
commit e29162b470
3 changed files with 374 additions and 0 deletions
+175
View File
@@ -0,0 +1,175 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
.cache.*
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
.pybuilder/
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# UV
# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
#uv.lock
# poetry
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
#poetry.lock
# pdm
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
#pdm.lock
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
# in version control.
# https://pdm.fming.dev/latest/usage/project/#working-with-version-control
.pdm.toml
.pdm-python
.pdm-build/
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# pytype static type analyzer
.pytype/
# Cython debug symbols
cython_debug/
# PyCharm
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/
# Ruff stuff:
.ruff_cache/
# PyPI configuration file
.pypirc
+193
View File
@@ -0,0 +1,193 @@
import os
import time
import hashlib
import secrets
import random
import socket
import platform
import psutil
import uuid
import threading
import datetime
import multiprocessing
from progress.bar import Bar
from concurrent.futures import ProcessPoolExecutor
import openmeteo_requests
import requests_cache
from retry_requests import retry
def fetch_weather_entropy():
"""Récupère des données météo comme source supplémentaire d'entropie"""
try:
# Configuration du client API Open-Meteo avec cache et nouvelle tentative en cas d'erreur
cache_session = requests_cache.CachedSession('.cache', expire_after=60) # Courte durée de cache
retry_session = retry(cache_session, retries=2, backoff_factor=0.2) # Nouvelle tentative rapide
openmeteo = openmeteo_requests.Client(session=retry_session)
# Demande de données météo avec un délai d'expiration
url = "https://api.open-meteo.com/v1/forecast"
params = {
"latitude": 50.4,
"longitude": 1.83,
"hourly": ["temperature_2m", "relative_humidity_2m", "wind_speed_10m",
"visibility", "precipitation", "cloud_cover"],
"timezone": "auto"
}
responses = openmeteo.weather_api(url, params=params)
response = responses[0]
# Extraction de toutes les valeurs numériques des prévisions horaires
entropy_values = []
hourly = response.Hourly()
# Traitement de chaque variable météorologique
for i in range(len(params["hourly"])):
var_values = hourly.Variables(i).ValuesAsNumpy()
entropy_values.extend(var_values.tolist())
# Création d'un hash de toutes les données météorologiques
weather_str = "".join([str(v) for v in entropy_values])
weather_hash = hashlib.sha256(weather_str.encode()).hexdigest()
return weather_hash
except Exception as e:
# If anything fails, return a timestamp-based fallback
fallback = f"weather_fallback_{time.time()}_{random.getrandbits(64)}"
return hashlib.sha256(fallback.encode()).hexdigest()
def initialize_entropy_pool():
"""Crée un pool d'entropie de base avec des sources qui ne changent pas rapidement"""
weather_entropy = fetch_weather_entropy()
return [
str(os.urandom(32)), # 32 octets d'aléa du système
str(secrets.token_bytes(32)), # Autre source cryptographique
socket.gethostname(), # Nom de l'hôte
str(platform.system_alias(platform.system(), platform.release(), platform.version())),
str(uuid.getnode()), # Adresse MAC
str(multiprocessing.cpu_count()), # Nombre de CPU
"".join([str(v) for v in psutil.disk_partitions()]), # Configuration des disques
str(hash(frozenset(os.environ.items()))), # Variables d'environnement,
weather_entropy, # Données météorologiques
]
def generate_seed(base_pool=None):
"""Génère une graine aléatoire en combinant différentes sources d'entropie"""
# Utiliser le pool de base si fourni, sinon créer des sources complètes
if base_pool:
entropy_sources = base_pool.copy()
else:
entropy_sources = []
# Ajouter les sources dynamiques qui changent à chaque appel
dynamic_sources = [
str(time.time()), # Timestamp actuel
hashlib.sha256(str(time.perf_counter()).encode()).hexdigest(), # Timer haute précision hashé
str(os.getpid()), # ID du processus
str(psutil.cpu_percent(interval=0.01)), # Utilisation CPU (réduit à 0.01)
str(psutil.virtual_memory().percent), # Utilisation mémoire
str(psutil.disk_usage('/').percent), # Utilisation disque
str(random.getrandbits(256)), # Bits aléatoires du générateur par défaut
str(datetime.datetime.now().microsecond), # Microsecondes actuelles
str(threading.active_count()), # Nombre de threads actifs
str(sum(psutil.cpu_times())), # Temps CPU cumulés
str(psutil.net_io_counters().bytes_sent if hasattr(psutil, 'net_io_counters') else 0), # Trafic réseau
str(id({})), # Adresse mémoire d'un nouvel objet
]
entropy_sources.extend(dynamic_sources)
random.shuffle(entropy_sources)
# Concaténer et hacher plusieurs fois avec différents algorithmes
entropy_str = "".join(entropy_sources)
intermediate_hash = hashlib.sha512(entropy_str.encode()).digest()
intermediate_hash = hashlib.blake2b(intermediate_hash).digest()
# Utiliser un hachage final pour obtenir un entier
final_hash = hashlib.sha256(intermediate_hash).hexdigest()
seed = int(final_hash, 16)
return seed
def faire_tirage(base_pool=None):
"""Génère un tirage avec 5 numéros et 2 étoiles en utilisant une graine aléatoire"""
# Génération de nouveaux nombres avec une nouvelle graine
seed = generate_seed(base_pool)
random.seed(seed)
numeros = random.sample(range(1, 51), 5)
etoiles = random.sample(range(1, 13), 2)
return {
"graine": seed,
"numeros": sorted(numeros),
"etoiles": sorted(etoiles)
}
def worker_process(num_tirages, base_pool):
"""Fonction exécutée par chaque processus travailleur"""
local_tirages = []
for _ in range(num_tirages):
local_tirages.append(faire_tirage(base_pool))
return local_tirages
def generate_draws(num_tirages):
"""Génère plusieurs tirages en parallèle"""
# Initialiser le pool d'entropie de base
base_pool = initialize_entropy_pool()
# Déterminer le nombre optimal de processus
num_processes = min(os.cpu_count() or 4, 4) # Limiter à un nombre raisonnable
# Répartir le travail entre les processus
tirages_par_processus = num_tirages // num_processes
remainder = num_tirages % num_processes
# Préparer les tâches pour chaque processus
tasks = []
for i in range(num_processes):
count = tirages_par_processus + (1 if i < remainder else 0)
if count > 0:
tasks.append((count, base_pool))
bar = Bar('Progression', max=num_tirages, suffix='%(percent)d%%')
# Exécuter les tâches en parallèle
tirages = []
with ProcessPoolExecutor(max_workers=num_processes) as executor:
futures = [executor.submit(worker_process, count, bp) for count, bp in tasks]
for future in futures:
batch = future.result()
tirages.extend(batch)
bar.next(len(batch))
bar.finish()
return tirages
if __name__ == "__main__":
print("Génération de 100 tirages différents...")
tirages = generate_draws(100)
# Mélange final pour le choix du tirage avec une nouvelle graine
base_pool = initialize_entropy_pool()
random.seed(generate_seed(base_pool))
tirage_choisi = random.choice(tirages)
print("\n===== RÉSULTAT FINAL =====")
print("Tirage sélectionné parmi les 100 générés")
print("Graine utilisée :", tirage_choisi["graine"])
print("Numéros :", tirage_choisi["numeros"])
print("Étoiles :", tirage_choisi["etoiles"])
# Demander à l'utilisateur s'il souhaite afficher tous les tirages
afficher_tous = input("\nVoulez-vous afficher tous les tirages générés? (o/n): ").lower().strip()
if afficher_tous in ['o', 'oui', 'y', 'yes']:
print("\n===== TOUS LES TIRAGES =====")
for i, tirage in enumerate(tirages, 1):
print(f"Tirage {i}:")
print(f" Numéros: {tirage['numeros']}")
print(f" Étoiles: {tirage['etoiles']}")
print(f" Graine: {tirage['graine']}")
print("-" * 30)
input("\nAppuyez sur Entrée pour quitter...")
+6
View File
@@ -0,0 +1,6 @@
futures==3.0.5
openmeteo_requests==1.3.0
progress==1.6
psutil==7.0.0
requests-cache==1.2.1
retry-requests==2.0.0