Wiederholungsregel für die Grund-Playlist
Ein Playlist-Titel kommt erst wieder, wenn seit seinem letzten Einsatz mindestens X % der Playlist gelaufen sind (Admin → Einstellungen → Ablauf, Standard 50 %). Der Player merkt sich die gespielten Titel über Neustarts. Wünsche sind ausgenommen (dort gilt weiter die Sperrzeit in Minuten). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,101 @@
|
||||
"""Tests für die Wiederholungsregel der Grund-Playlist (ohne Spotify)."""
|
||||
|
||||
import random
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
|
||||
from controller import Controller, Playlist # noqa: E402
|
||||
|
||||
|
||||
class FakeSpotify:
|
||||
def __init__(self, titel):
|
||||
self.titel = list(titel)
|
||||
|
||||
def playlist_titel(self, playlist_id):
|
||||
return list(self.titel)
|
||||
|
||||
|
||||
def spielen(pl: Playlist, anzahl: int) -> list[str]:
|
||||
folge = []
|
||||
for _ in range(anzahl):
|
||||
uri = pl.naechster()
|
||||
pl.gespielt(uri)
|
||||
folge.append(uri)
|
||||
return folge
|
||||
|
||||
|
||||
def kleinster_abstand(folge: list[str]) -> int:
|
||||
"""Wie viele verschiedene andere Titel liefen mindestens zwischen zwei Einsätzen desselben Titels?"""
|
||||
minimum = 10**9
|
||||
letzte: dict[str, int] = {}
|
||||
for i, uri in enumerate(folge):
|
||||
if uri in letzte:
|
||||
minimum = min(minimum, len(set(folge[letzte[uri] + 1:i])))
|
||||
letzte[uri] = i
|
||||
return minimum
|
||||
|
||||
|
||||
TITEL = [f"spotify:track:{i:022d}" for i in range(10)]
|
||||
|
||||
|
||||
@pytest.mark.parametrize("prozent, mindestens", [(50, 5), (80, 8), (100, 9)])
|
||||
def test_regel_haelt_abstand_ein(prozent, mindestens):
|
||||
random.seed(prozent)
|
||||
pl = Playlist(FakeSpotify(TITEL), "liste", prozent)
|
||||
assert kleinster_abstand(spielen(pl, 300)) >= mindestens
|
||||
|
||||
|
||||
def test_jeder_titel_kommt_dran():
|
||||
pl = Playlist(FakeSpotify(TITEL), "liste", 100)
|
||||
assert set(spielen(pl, 10)) == set(TITEL)
|
||||
|
||||
|
||||
def test_regel_gilt_ueber_neustart():
|
||||
random.seed(1)
|
||||
alt = Playlist(FakeSpotify(TITEL), "liste", 50)
|
||||
vorher = spielen(alt, 7)
|
||||
neu = Playlist(FakeSpotify(TITEL), "liste", 50) # "Neustart"
|
||||
neu.zuletzt.extend(alt.zuletzt)
|
||||
gesperrt = set(vorher[-5:])
|
||||
assert not gesperrt & set(spielen(neu, 5))
|
||||
|
||||
|
||||
def test_neu_mischen_bricht_regel_nicht():
|
||||
random.seed(2)
|
||||
pl = Playlist(FakeSpotify(TITEL), "liste", 80)
|
||||
folge = spielen(pl, 4)
|
||||
pl.neu_mischen()
|
||||
folge += spielen(pl, 30)
|
||||
assert kleinster_abstand(folge) >= 8
|
||||
|
||||
|
||||
def test_null_prozent_wie_bisher():
|
||||
pl = Playlist(FakeSpotify(TITEL), "liste", 0)
|
||||
assert pl.gesperrt() == set()
|
||||
assert len(spielen(pl, 25)) == 25
|
||||
|
||||
|
||||
def test_titel_anderer_playlist_zaehlen_nicht():
|
||||
pl = Playlist(FakeSpotify(TITEL), "liste", 100)
|
||||
pl.zuletzt.extend(f"spotify:track:x{i:021d}" for i in range(50)) # alte Playlist
|
||||
pl.naechster()
|
||||
assert pl.gesperrt() == set()
|
||||
|
||||
|
||||
def test_ein_titel_bleibt_immer_frei():
|
||||
pl = Playlist(FakeSpotify(TITEL[:2]), "liste", 100)
|
||||
assert len(spielen(pl, 10)) == 10
|
||||
|
||||
|
||||
def test_zustand_speichert_zuletzt(tmp_path):
|
||||
datei = tmp_path / "zustand.json"
|
||||
neu = lambda: Controller(sp=None, playlist=Playlist(FakeSpotify(TITEL), "liste", 50), server=None, # noqa: E731
|
||||
n=3, geraetename="Audiofy", bt_mac=None, zustand_pfad=datei)
|
||||
c = neu()
|
||||
c.playlist.gespielt(TITEL[3])
|
||||
c.playlist.gespielt(TITEL[4])
|
||||
c.zustand_sichern()
|
||||
assert list(neu().playlist.zuletzt) == [TITEL[3], TITEL[4]]
|
||||
Reference in New Issue
Block a user