added new functions for random sounds
This commit is contained in:
+43
-8
@@ -24,8 +24,8 @@ AUTO_STATE_PATH = os.path.join(Config.LOG_DIR, 'auto_random_state.json')
|
||||
# Sound-Cache: path -> pygame.mixer.Sound
|
||||
loaded_sounds = {}
|
||||
random_history = defaultdict(deque) # sound_id -> deque[timestamps]
|
||||
MAX_PER_HOUR = 2
|
||||
WINDOW_SECONDS = 3600
|
||||
DEFAULT_MAX_PER_HOUR = 2
|
||||
DEFAULT_WINDOW_SECONDS = 3600
|
||||
|
||||
def _ensure_mixer():
|
||||
from config import Config
|
||||
@@ -103,8 +103,9 @@ def _pick_random_sound():
|
||||
candidates = []
|
||||
for sound in rnd_list:
|
||||
sid = sound.get('id') or sound.get('file')
|
||||
dq = _prune_history(sid, now)
|
||||
if len(dq) < MAX_PER_HOUR:
|
||||
max_per_hour, window_seconds = _get_limits(sound)
|
||||
dq = _prune_history(sid, now, window_seconds)
|
||||
if len(dq) < max_per_hour:
|
||||
candidates.append(sound)
|
||||
|
||||
if not candidates:
|
||||
@@ -117,6 +118,30 @@ def _pick_random_sound():
|
||||
return sound_entry, None
|
||||
|
||||
|
||||
def _get_limits(sound_entry=None):
|
||||
"""
|
||||
Ermittelt Grenzen für Random-Wiedergabe.
|
||||
Priorität: pro Sound (max_per_hour, window_minutes) -> aktuelles Soundboard -> Defaults.
|
||||
"""
|
||||
max_per_hour = DEFAULT_MAX_PER_HOUR
|
||||
window_seconds = DEFAULT_WINDOW_SECONDS
|
||||
|
||||
if state.current_soundboard:
|
||||
sb = state.current_soundboard
|
||||
max_per_hour = int(sb.get('random_limit_per_hour', max_per_hour))
|
||||
window_minutes = sb.get('random_window_minutes')
|
||||
if window_minutes:
|
||||
window_seconds = int(window_minutes * 60)
|
||||
|
||||
if sound_entry:
|
||||
if 'max_per_hour' in sound_entry:
|
||||
max_per_hour = int(sound_entry['max_per_hour'])
|
||||
if 'window_minutes' in sound_entry:
|
||||
window_seconds = int(sound_entry['window_minutes'] * 60)
|
||||
|
||||
return max_per_hour, window_seconds
|
||||
|
||||
|
||||
def _auto_random_tick():
|
||||
global auto_random_timer
|
||||
with auto_random_lock:
|
||||
@@ -165,9 +190,9 @@ def _persist_auto_state(clear=False):
|
||||
logger.error(f"Persist auto-random state fehlgeschlagen: {e}")
|
||||
|
||||
|
||||
def _prune_history(sound_id, now):
|
||||
def _prune_history(sound_id, now, window_seconds=DEFAULT_WINDOW_SECONDS):
|
||||
dq = random_history[sound_id]
|
||||
while dq and now - dq[0] > WINDOW_SECONDS:
|
||||
while dq and now - dq[0] > window_seconds:
|
||||
dq.popleft()
|
||||
return dq
|
||||
|
||||
@@ -451,6 +476,8 @@ def api_soundboard_auto_start():
|
||||
imax = float(data.get('interval_max', 10))
|
||||
dmin = float(data.get('delay_min', 3))
|
||||
dmax = float(data.get('delay_max', 12))
|
||||
limit_ph = int(data.get('limit_per_hour', DEFAULT_MAX_PER_HOUR))
|
||||
window_min = float(data.get('window_minutes', DEFAULT_WINDOW_SECONDS/60))
|
||||
if imax < imin: imax = imin
|
||||
if dmax < dmin: dmax = dmin
|
||||
|
||||
@@ -465,6 +492,8 @@ def api_soundboard_auto_start():
|
||||
auto_random_params['dmax'] = dmax
|
||||
auto_random_params['next_ts'] = time.time() + delay
|
||||
auto_random_params['theme'] = state.current_soundboard.get('filename')
|
||||
auto_random_params['limit_per_hour'] = limit_ph
|
||||
auto_random_params['window_seconds'] = window_min * 60
|
||||
global auto_random_timer
|
||||
auto_random_timer = threading.Timer(delay, _auto_random_tick)
|
||||
auto_random_timer.daemon = True
|
||||
@@ -500,6 +529,8 @@ def api_soundboard_status():
|
||||
dmin = auto_random_params.get('dmin')
|
||||
dmax = auto_random_params.get('dmax')
|
||||
current_theme = state.current_soundboard.get('filename') if state.current_soundboard else None
|
||||
limit_ph = auto_random_params.get('limit_per_hour', DEFAULT_MAX_PER_HOUR)
|
||||
window_sec = auto_random_params.get('window_seconds', DEFAULT_WINDOW_SECONDS)
|
||||
next_seconds = max(0, next_ts - time.time()) if next_ts else None
|
||||
return jsonify({
|
||||
"active": active,
|
||||
@@ -508,7 +539,9 @@ def api_soundboard_status():
|
||||
"interval_max": imax,
|
||||
"delay_min": dmin,
|
||||
"delay_max": dmax,
|
||||
"current_theme": current_theme
|
||||
"current_theme": current_theme,
|
||||
"limit_per_hour": limit_ph,
|
||||
"window_minutes": window_sec/60 if window_sec else None
|
||||
})
|
||||
|
||||
|
||||
@@ -557,7 +590,9 @@ def _restore_auto_state():
|
||||
'dmin': data.get('dmin', 3),
|
||||
'dmax': data.get('dmax', 12),
|
||||
'next_ts': next_ts,
|
||||
'theme': theme
|
||||
'theme': theme,
|
||||
'limit_per_hour': data.get('limit_per_hour', DEFAULT_MAX_PER_HOUR),
|
||||
'window_seconds': data.get('window_seconds', DEFAULT_WINDOW_SECONDS)
|
||||
})
|
||||
delay = max(1, next_ts - time.time())
|
||||
global auto_random_timer
|
||||
|
||||
Reference in New Issue
Block a user