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