[Migration] handle Episode.listeners = None in episode toplist
[mygpo.git] / mygpo / web / templatetags / charts.py
blob2aa369f20b1b34afcf6e2e06e67a54e515befbcf
1 from django import template
2 from django.utils.safestring import mark_safe
3 from django.contrib.staticfiles.storage import staticfiles_storage
5 from mygpo.utils import format_time
6 from mygpo.publisher.utils import colour_repr
9 register = template.Library()
11 @register.simple_tag
12 def vertical_bar(value, max_value, display=None):
13 if not max_value:
14 return ''
16 if display == 'ratio':
17 value_str = '%d/%d' % (value, max_value)
18 else:
19 value_str = str(value)
21 # handle value == None
22 value = value or 0
24 try:
25 ratio = min(float(value) / float(max_value), 1) * 100
26 except ValueError:
27 return ''
29 if ratio > 40:
30 left, right = '<span>'+ value_str +'</span>', ''
31 else:
32 left, right = '&nbsp;', '<span>'+ value_str +'</span>'
33 s = '<div class="barbg"><div class="bar" style="width: %.2d%%">%s</div>%s</div>' % (ratio, left, right)
34 return s
36 @register.filter
37 def timeline(data):
38 s = '<script type="text/javascript" src="//www.google.com/jsapi"></script>\n'
39 s += '<script type="text/javascript">\n'
40 s += 'google.load("visualization", "1", {"packages":["annotatedtimeline"]});\n'
41 s += 'google.setOnLoadCallback(drawChart);\n'
42 s += 'function drawChart() {\n'
43 s += 'var data = new google.visualization.DataTable();\n'
44 s += 'data.addColumn("date", "Date");\n'
45 s += 'data.addColumn("number", "Listeners");\n'
46 s += 'data.addColumn("string", "title1");\n'
47 s += 'data.addColumn("string", "text1");\n'
48 s += 'data.addRows([\n'
50 for r in data:
51 if 'episode' in r and r['episode']:
52 episode = '"%s"' % r['episode'].title if r['episode'].title else '"Unnamed Episode"'
53 episode_ = '"released"'
54 else:
55 episode = 'undefined'
56 episode_ = 'undefined'
58 s += '[new Date(%d, %d, %d), %d, %s, %s],\n' % (r['date'].year, r['date'].month-1, r['date'].day, r['listeners'], episode, episode_)
60 s += ']);\n'
61 s += 'var chart = new google.visualization.AnnotatedTimeLine(document.getElementById("chart_div"));\n'
62 s += 'chart.draw(data, {displayAnnotations: true});\n'
63 s += '}\n'
64 s += '</script>\n'
66 return mark_safe(s)
69 @register.filter
70 def pie_chart(parts):
71 parts = [
72 'cht=p',
73 'chs=250x100',
74 'chl=%s' % '|'.join(parts.iterkeys()),
75 'chd=t:%s' % ','.join([ repr(x) for x in parts.itervalues() ])
78 s = '<img src="http://chart.apis.google.com/chart?%s"' % '&'.join(parts)
80 return mark_safe(s)
83 @register.filter
84 def episode_heatmap_visualization(heatmap):
85 """
86 display a visual heatmap using the Google Charts API
88 heatmap_data is expected as an array of numbers of users that have
89 played this part part of the episode. the length of the parts is
90 indicated by step_length; the duration of the whole episode is
91 therefore approximated by len(heatmap_data) * step_length
92 """
93 label_steps = 2
95 max_plays = heatmap.max_plays
97 if max_plays == 1:
98 # light blue dark blue
99 colours = ( (198, 217, 253), (77, 137, 249) )
100 else:
101 # red yellow green
102 colours = ( (210, 54, 28), (239, 236, 22), (15, 212, 18) )
104 WIDTH=760
106 # maximum number of labels that will be placed on the visualization
107 MAX_LABELS=20
109 axis_pos = []
110 axis_label = []
111 part_colours = []
112 widths = []
113 duration = max(heatmap.borders)
115 last_label = None
116 for start, end, plays in heatmap.sections:
118 if last_label is None or (end-last_label) > (duration/MAX_LABELS):
119 axis_pos.append(end)
120 axis_label.append(format_time(end))
121 last_label = end
123 rgb = colour_repr(plays, max_plays, colours)
124 part_colours.append('%02x%02x%02x' % rgb)
125 widths.append( end-start )
127 parts = [
128 'cht=bhs', # bar chart
129 'chco=%s' % ','.join(part_colours), # colors
130 'chs=%dx50' % WIDTH, # width corresponds to length, arbitrary height
131 'chds=0,%s' % duration, # axis scaling from 0 to maximum duration
132 'chd=t:%s' % '|'.join([repr(w) for w in widths]), # all block have the same width
133 'chxt=x', # visible axes
134 'chxr=0,0,%s' % duration, # axis range for axis 0 (x): 0 - duration
135 'chxl=0:|%s' % '|'.join(axis_label), # axis labels
136 'chxp=0,%s' % ','.join([repr(x) for x in axis_pos]), # axis label positions
139 s = '<img src="http://chart.apis.google.com/chart?%s" />' % '&'.join(parts)
141 return mark_safe(s)
145 @register.simple_tag
146 def subscriber_change(change):
148 if change > 1:
149 change -= 1
150 return '+{0:.1%}'.format(change)
152 # we don't care about negative changes
153 return ''