diff --git a/docs/library.md b/docs/library.md index efb871c..9ef59c4 100644 --- a/docs/library.md +++ b/docs/library.md @@ -40,7 +40,7 @@ Diese Woche (the last 7 days), Diesen Monat (30 days), then the months — after Kino feed. In „Folgen“ (sort „Nach Zeitraum, seltene zuerst“, the default) and „Neu“ the podcasts that seldom come go first within a group: `interval_days` of each feed in `/podcasts/state/`, the mean gap between its newest 10 episodes (one episode: its -age, at least 30 days; kept an hour). Heard is a filter chip, not an order. +age, at least 30 days, the same when all came on one day; kept an hour). Heard is a filter chip, not an order. ### Shared code: `static/js/folders.js` (diora-web, every platform) diff --git a/podcasts/tests.py b/podcasts/tests.py index 5e72b01..ee4cf8b 100644 --- a/podcasts/tests.py +++ b/podcasts/tests.py @@ -810,6 +810,14 @@ class EpisodeListTests(TestCase): self.assertAlmostEqual(feeds[self.fa.id]['interval_days'], (_at(1, 3) - _at(1, 1)).total_seconds() / 86400 / 2, places=1) self.assertAlmostEqual(feeds[self.fb.id]['interval_days'], (_at(1, 5) - _at(1, 4)).total_seconds() / 86400, places=1) + def test_a_whole_archive_at_once_counts_as_seldom(self): + f = PodcastFeed.objects.create(user=self.user, rss_url='https://example.org/c', title='Archiv') + for k in range(5): + PodcastEpisode.objects.create(feed=f, guid=f'c{k}', title=f'C{k}', audio_url=f'https://example.org/c{k}.mp3', + pub_date=_at(1, 1) + timedelta(minutes=k)) + feeds = {x['id']: x for x in self.client.get('/podcasts/state/').json()['feeds']} + self.assertGreater(feeds[f.id]['interval_days'], 30) + def test_all_newest_first_without_date_last(self): data = self.get() self.assertEqual([e['id'] for e in data['episodes']], diff --git a/podcasts/views.py b/podcasts/views.py index c569cfb..4ca92d7 100644 --- a/podcasts/views.py +++ b/podcasts/views.py @@ -816,7 +816,7 @@ INTERVAL_SINGLE_DAYS = 30 def _intervals(user): """How often each feed brings an episode, in days: the mean gap between its newest - INTERVAL_EPISODES. One episode only: its age, at least INTERVAL_SINGLE_DAYS. The lists + INTERVAL_EPISODES. One episode only (or all on one day): its age, at least INTERVAL_SINGLE_DAYS. The lists put the seldom ones first within a day or week (after Kino's feed; feeds.js does the same for blogs). One query (the newest episodes per feed by a window), kept an hour.""" key = f'podcasts:intervals:{user.id}' @@ -835,10 +835,12 @@ def _intervals(user): now = timezone.now() out = {} for feed_id, ds in dates.items(): - if len(ds) == 1: - days = max((now - ds[0]).total_seconds() / 86400, INTERVAL_SINGLE_DAYS) + span = (max(ds) - min(ds)).total_seconds() / 86400 + if len(ds) == 1 or span < 1: + # One episode, or all of them at once (an archive, a course): no rhythm to go by. + days = max((now - max(ds)).total_seconds() / 86400, INTERVAL_SINGLE_DAYS) else: - days = (max(ds) - min(ds)).total_seconds() / 86400 / (len(ds) - 1) + days = span / (len(ds) - 1) out[feed_id] = round(days, 2) cache.set(key, out, 3600) return out