From 1e4744a7cba4f6be3f4d5d897268bf1f1bed2059 Mon Sep 17 00:00:00 2001 From: Cliff Hill Date: Thu, 30 Sep 2021 12:25:40 -0400 Subject: [PATCH] Making settings a little neater. Signed-off-by: Cliff Hill --- src/playlist/data/settings.py | 17 ++++++++++++----- src/playlist/plex/server.py | 36 +++++++++++++++++++++++++++-------- 2 files changed, 40 insertions(+), 13 deletions(-) diff --git a/src/playlist/data/settings.py b/src/playlist/data/settings.py index a4b6963..0f15284 100644 --- a/src/playlist/data/settings.py +++ b/src/playlist/data/settings.py @@ -1,6 +1,8 @@ """Define and control the Settings object for the playlist app.""" from __future__ import annotations +import collections.abc +import contextlib import dataclasses import datetime import functools @@ -12,7 +14,7 @@ import yaml from playlist.data import base from playlist.data import const -__all__ = ["get", "write"] +__all__ = ["get", "modify"] @dataclasses.dataclass @@ -131,7 +133,12 @@ def get() -> Settings: # pragma: no cover return instance -def write() -> None: # pragma: no cover - """Write the Settings object instance.""" - filepath = const.PATHS.CONFIG / const.SETTINGS_FILENAME - get().yaml_write(filepath) +@contextlib.contextmanager +def modify() -> collections.abc.Generator[Settings, None, None]: # pragma: no cover + """Provide the Settings object to make a modification and automatically save it.""" + s = get() + try: + yield s + finally: + filepath = const.PATHS.CONFIG / const.SETTINGS_FILENAME + s.yaml_write(filepath) diff --git a/src/playlist/plex/server.py b/src/playlist/plex/server.py index 28f0c9d..d1295be 100644 --- a/src/playlist/plex/server.py +++ b/src/playlist/plex/server.py @@ -19,6 +19,32 @@ __all__ = ["gen_tracks", "total_track_count", "get_creds"] throttle = asyncio.BoundedSemaphore(const.MAX_PROCESSES) +def calc_delay(times: list[float], weights: list[float]) -> None: + """Calculate the process delay. + + This is based on a weighted harmonic mean of the times the processes took in + the last run. + """ + with settings.modify() as s: + avg_time_per_batch = utils.harmonic_mean(times, weights=weights) + delay = avg_time_per_batch / const.MAX_PROCESSES + s.download.process_delay = round(delay, ndigits=6) + + +def calc_duration(durations: list[int]) -> None: + """Calculate the average duration and max tracks to play each day. + + This is based on the geometric mean of the durations of every track loaded from + Plex. The maximum tracks to load for a day is based on the average duration calculated + and the amount of time that the system was played the previous day. + """ + with settings.modify() as s: + avg_track_duration = statistics.geometric_mean(durations) + s.track.duration = round(avg_track_duration, ndigits=6) + playtime_seconds = settings.get().playlist.playtime.total_seconds() + s.playlist.max_tracks = int(playtime_seconds / avg_track_duration) + + async def gen_tracks( *, batch_size: int = settings.get().download.batch_size, @@ -50,14 +76,8 @@ async def gen_tracks( durations.append(track.duration) yield track - avg_time_per_batch = utils.harmonic_mean(times, weights=weights) - avg_track_duration = statistics.geometric_mean(durations) - delay = avg_time_per_batch / const.MAX_PROCESSES - settings.get().download.process_delay = round(delay, ndigits=6) - settings.get().track.duration = round(avg_track_duration, ndigits=6) - playtime_seconds = settings.get().playlist.playtime.total_seconds() - settings.get().playlist.max_tracks = int(playtime_seconds / avg_track_duration) - settings.write() + calc_delay(times, weights) + calc_duration(durations) async def total_track_count() -> int: