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