319 lines
8.6 KiB
Python
319 lines
8.6 KiB
Python
"""
|
|
Fortune Cookie v1.0 - Python Backend Module
|
|
Framework 1.7 Standard
|
|
"""
|
|
|
|
import os
|
|
import random
|
|
import json
|
|
import platform
|
|
from pathlib import Path
|
|
|
|
# ============================================================================
|
|
# APP-METADATEN
|
|
# ============================================================================
|
|
APP_NAME = "fortunecookie"
|
|
APP_VERSION = "1.0.0"
|
|
MAINTAINER = "darklithium <dev@darklithium.de>"
|
|
|
|
# ============================================================================
|
|
# PLATTFORM-ERKENNUNG (Framework 1.7 Standard)
|
|
# ============================================================================
|
|
|
|
def get_platform():
|
|
"""Gibt die aktuelle Plattform zurueck (arm64/amd64)."""
|
|
machine = platform.machine().lower()
|
|
if "arm" in machine or "aarch" in machine:
|
|
return "arm64"
|
|
return "amd64"
|
|
|
|
|
|
# ============================================================================
|
|
# FORTUNE-LOGIK
|
|
# ============================================================================
|
|
|
|
# Globale Variablen
|
|
_current_fortune = ""
|
|
_fortunes = []
|
|
_initialized = False
|
|
|
|
# Musik-Status
|
|
_music_enabled = True
|
|
_music_playing = False
|
|
|
|
# Medien-Player (wird lazy initialisiert)
|
|
_media_player = None
|
|
_cookie_crack_sound = None
|
|
|
|
|
|
def _init():
|
|
"""Initialisiert das Modul (wird beim ersten Aufruf ausgefuehrt)."""
|
|
global _fortunes, _initialized, _music_enabled
|
|
|
|
if _initialized:
|
|
return True
|
|
|
|
# Lade Fortunes
|
|
_load_fortunes()
|
|
|
|
# Lade Last-State
|
|
_music_enabled = _load_music_state()
|
|
|
|
_initialized = True
|
|
return True
|
|
|
|
|
|
def _load_fortunes():
|
|
"""Laedt alle Sprueche aus assets/fortunes.json."""
|
|
global _fortunes
|
|
|
|
if _fortunes:
|
|
return
|
|
|
|
try:
|
|
# Versuche verschiedene Pfade
|
|
possible_paths = [
|
|
os.path.join(os.path.dirname(__file__), "..", "assets", "fortunes.json"),
|
|
os.path.join("assets", "fortunes.json"),
|
|
]
|
|
|
|
for fortunes_path in possible_paths:
|
|
if os.path.exists(fortunes_path):
|
|
with open(fortunes_path, "r", encoding="utf-8") as f:
|
|
data = json.load(f)
|
|
if isinstance(data, list):
|
|
_fortunes = data
|
|
elif isinstance(data, dict):
|
|
_fortunes = data.get("fortunes", [])
|
|
return
|
|
|
|
# Fallback: Standard-Sprueche
|
|
_fortunes = [
|
|
"Ein guter Tag beginnt mit einem Laecheln.",
|
|
"Das Glueck liegt in den kleinen Dingen.",
|
|
"Geduld ist eine Tugend.",
|
|
]
|
|
|
|
except Exception:
|
|
# Fallback: Einige Standard-Sprueche
|
|
_fortunes = [
|
|
"Ein guter Tag beginnt mit einem Laecheln.",
|
|
"Das Glueck liegt in den kleinen Dingen.",
|
|
"Geduld ist eine Tugend.",
|
|
]
|
|
|
|
|
|
def get_initial_fortune():
|
|
"""Gibt einen zufaelligen Spruch fuer den Start zurueck."""
|
|
_init()
|
|
global _current_fortune
|
|
_current_fortune = _get_random_fortune()
|
|
return _current_fortune
|
|
|
|
|
|
def open_fortune():
|
|
"""Oeffnet den Fortune Cookie (neuer Spruch + Knack-Geraeusch)."""
|
|
_init()
|
|
global _current_fortune
|
|
|
|
# Neuer Spruch
|
|
_current_fortune = _get_random_fortune()
|
|
|
|
# Knack-Geraeusch abspielen (wenn verfguebar)
|
|
_play_crack_sound()
|
|
|
|
return True
|
|
|
|
|
|
def get_current_fortune():
|
|
"""Gibt den aktuellen Spruch zurueck."""
|
|
_init()
|
|
global _current_fortune
|
|
return _current_fortune
|
|
|
|
|
|
def get_new_fortune():
|
|
"""Gibt einen neuen Spruch zurueck (Cookie schliesst sich)."""
|
|
_init()
|
|
global _current_fortune
|
|
_current_fortune = _get_random_fortune()
|
|
return _current_fortune
|
|
|
|
|
|
def _get_random_fortune():
|
|
"""Gibt einen zufaelligen Spruch zurueck."""
|
|
if not _fortunes:
|
|
_load_fortunes()
|
|
return random.choice(_fortunes) if _fortunes else "Keine Sprueche verfguebar."
|
|
|
|
|
|
# ============================================================================
|
|
# MUSIK-LOGIK
|
|
# ============================================================================
|
|
|
|
def start_music():
|
|
"""Startet die Hintergrundmusik."""
|
|
_init()
|
|
global _music_playing, _media_player, _music_enabled
|
|
|
|
if not _music_enabled:
|
|
return False
|
|
|
|
try:
|
|
# Medien-Player initialisieren (wenn nicht vorhanden)
|
|
if _media_player is None:
|
|
from PySide2 import QtMultimedia, QtCore
|
|
|
|
_media_player = QtMultimedia.QMediaPlayer()
|
|
audio_output = QtMultimedia.QAudioOutput()
|
|
_media_player.setAudioOutput(audio_output)
|
|
|
|
# Musik-Datei laden
|
|
music_path = get_asset_path("chinese_music.mp3")
|
|
_media_player.setSource(QtCore.QUrl.fromLocalFile(music_path))
|
|
_media_player.setLoops(QtMultimedia.QMediaPlayer.Infinite)
|
|
_media_player.setVolume(50)
|
|
|
|
_media_player.play()
|
|
_music_playing = True
|
|
return True
|
|
|
|
except Exception:
|
|
return False
|
|
|
|
|
|
def stop_music():
|
|
"""Stoppt die Hintergrundmusik."""
|
|
global _music_playing, _media_player
|
|
|
|
if _media_player is not None:
|
|
try:
|
|
_media_player.stop()
|
|
except Exception:
|
|
pass
|
|
_music_playing = False
|
|
|
|
return True
|
|
|
|
|
|
def toggle_music():
|
|
"""Wechselt Musik-Status (an/aus)."""
|
|
if _music_playing:
|
|
return stop_music()
|
|
else:
|
|
return start_music()
|
|
|
|
|
|
def set_music_enabled(enabled):
|
|
"""Aktiviert/Deaktiviert Musik generell."""
|
|
global _music_enabled
|
|
_music_enabled = enabled
|
|
_save_music_state(enabled)
|
|
return enabled
|
|
|
|
|
|
def get_music_enabled():
|
|
"""Gibt zurueck, ob Musik aktiviert ist."""
|
|
global _music_enabled
|
|
return _music_enabled
|
|
|
|
|
|
def get_music_playing():
|
|
"""Gibt zurueck, ob Musik gerade spielt."""
|
|
global _music_playing
|
|
return _music_playing
|
|
|
|
|
|
# ============================================================================
|
|
# LAST-STATE SPEICHERUNG
|
|
# ============================================================================
|
|
|
|
def _get_data_dir():
|
|
"""Gibt das Datenverzeichnis zurueck."""
|
|
if "CLICK" in os.environ:
|
|
return os.path.join(
|
|
os.path.expanduser("~"), ".local", "share", f"{APP_NAME}.darklithium"
|
|
)
|
|
else:
|
|
return os.path.join(
|
|
os.path.expanduser("~"), ".local", "share", f"{APP_NAME}"
|
|
)
|
|
|
|
|
|
def _load_music_state():
|
|
"""Laedt den Musik-Status aus Datei."""
|
|
try:
|
|
state_file = os.path.join(_get_data_dir(), "music_state.json")
|
|
if os.path.exists(state_file):
|
|
with open(state_file, "r") as f:
|
|
data = json.load(f)
|
|
return data.get("enabled", True)
|
|
except Exception:
|
|
pass
|
|
return True
|
|
|
|
|
|
def _save_music_state(enabled):
|
|
"""Speichert den Musik-Status in Datei."""
|
|
try:
|
|
data_dir = _get_data_dir()
|
|
os.makedirs(data_dir, exist_ok=True)
|
|
state_file = os.path.join(data_dir, "music_state.json")
|
|
with open(state_file, "w") as f:
|
|
json.dump({"enabled": enabled}, f)
|
|
except Exception:
|
|
pass
|
|
|
|
|
|
def _play_crack_sound():
|
|
"""Spielt das Knack-Geraeusch ab."""
|
|
try:
|
|
global _cookie_crack_sound
|
|
|
|
if _cookie_crack_sound is None:
|
|
from PySide2 import QtMultimedia, QtCore
|
|
|
|
_cookie_crack_sound = QtMultimedia.QMediaPlayer()
|
|
audio_output = QtMultimedia.QAudioOutput()
|
|
_cookie_crack_sound.setAudioOutput(audio_output)
|
|
|
|
crack_path = get_asset_path("cookie_crack.mp3")
|
|
if os.path.exists(crack_path):
|
|
_cookie_crack_sound.setSource(QtCore.QUrl.fromLocalFile(crack_path))
|
|
_cookie_crack_sound.setVolume(100)
|
|
_cookie_crack_sound.play()
|
|
except Exception:
|
|
pass
|
|
|
|
|
|
# ============================================================================
|
|
# DATENVERZEICHNIS (fuer zukuenftige Erweiterungen)
|
|
# ============================================================================
|
|
|
|
def get_data_dir():
|
|
"""Gibt das Datenverzeichnis der App zurueck."""
|
|
return _get_data_dir()
|
|
|
|
|
|
def get_fortunes_file_path():
|
|
"""Gibt den Pfad zur Fortunes-Datei zurueck."""
|
|
return os.path.join(_get_data_dir(), "fortunes.json")
|
|
|
|
|
|
# ============================================================================
|
|
# PLATTFORM-SPEZIFISCHE PFADERMITTLUNG
|
|
# ============================================================================
|
|
|
|
def get_asset_path(filename):
|
|
"""Gibt den Pfad zu einer Asset-Datei zurueck (funktioniert in Click & Desktop)."""
|
|
possible_paths = [
|
|
os.path.join(os.path.dirname(__file__), "..", "assets", filename),
|
|
os.path.join("assets", filename),
|
|
]
|
|
|
|
for path in possible_paths:
|
|
if os.path.exists(path):
|
|
return path
|
|
|
|
return os.path.join("assets", filename)
|