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