2 # This file is part of my.gpodder.org.
4 # my.gpodder.org is free software: you can redistribute it and/or modify it
5 # under the terms of the GNU Affero General Public License as published by
6 # the Free Software Foundation, either version 3 of the License, or (at your
7 # option) any later version.
9 # my.gpodder.org is distributed in the hope that it will be useful, but
10 # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11 # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
12 # License for more details.
14 # You should have received a copy of the GNU Affero General Public License
15 # along with my.gpodder.org. If not, see <http://www.gnu.org/licenses/>.
18 from functools
import wraps
20 from mygpo
.users
.models
import EpisodeUserState
23 class EpisodeHeatmap(object):
24 """ Information about how often certain parts of Episodes are played """
26 def __init__(self
, podcast_id
, episode_id
=None, user_id
=None,
28 """ Initialize a new Episode heatmap
30 EpisodeHeatmap(podcast_id, [episode_id, [user_id]]) """
32 self
.podcast_id
= podcast_id
34 if episode_id
is not None and podcast_id
is None:
35 raise ValueError('episode_id can only be used '
36 'if podcast_id is not None')
38 self
.episode_id
= episode_id
40 if user_id
is not None and episode_id
is None:
41 raise ValueError('user_id can only be used '
42 'if episode_id is not None')
44 self
.user_id
= user_id
45 self
.duration
= duration
51 """ Queries the database and stores the heatmap and its borders """
53 db
= EpisodeUserState
.get_db()
55 group_level
= len(filter(None, [self
.podcast_id
,
56 self
.episode_id
, self
.user_id
]))
58 r
= db
.view('users/episode_heatmap',
59 startkey
= [self
.podcast_id
, self
.episode_id
,
61 endkey
= [self
.podcast_id
, self
.episode_id
or {},
65 group_level
= group_level
,
66 stale
= 'update_after',
73 res
= r
.first()['value']
74 self
.heatmap
= res
['heatmap']
75 self
.borders
= res
['borders']
77 # heatmap info doesn't reach until the end of the episode
78 # so we extend it with 0 listeners
79 if self
.duration
> self
.borders
[-1]:
80 self
.heatmap
.append(0)
81 self
.borders
.append(self
.duration
)
84 def query_if_required():
85 """ If required, queries the database before calling the function """
89 def tmp(self
, *args
, **kwargs
):
90 if None in (self
.heatmap
, self
.borders
):
93 return f(self
, *args
, **kwargs
)
101 """ Returns the highest number of plays of all sections """
103 return max(self
.heatmap
)
109 """ Returns an iterator that emits (from, to, play-counts) tuples
111 Each tuple represents one part in the heatmap with a distinct
112 play-count. from and to indicate the range of section in seconds."""
114 for i
in range(len(self
.heatmap
)):
115 yield (self
.borders
[i
], self
.borders
[i
+1], self
.heatmap
[i
])
119 def __nonzero__(self
):
120 return any(self
.heatmap
)