-
Notifications
You must be signed in to change notification settings - Fork 0
/
views.py
139 lines (128 loc) · 6.11 KB
/
views.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
#!/usr/bin/env python
# vim: ai ts=4 sts=4 et sw=4
from django.http import HttpResponse
from django.template import RequestContext
from django.shortcuts import render_to_response
from django.contrib.auth.decorators import login_required, permission_required
from tree.models import *
from StringIO import StringIO
import csv
@login_required
@permission_required("tree.can_view")
def index(req):
allTrees = Tree.objects.all()
if len(allTrees) != 0:
t = allTrees[len(allTrees) - 1]
return render_to_response("tree/index.html",
{ "trees": allTrees, "t": t },
context_instance=RequestContext(req))
else:
return render_to_response("tree/index.html", {},
context_instance=RequestContext(req))
@login_required
@permission_required("tree.can_view")
def data(req, id = None):
allTrees = Tree.objects.all()
# ok, the plan is to generate a table of responses per state, but this is tricky with loops.
# the first thing we'll do is get all the possible states you can reach from the tree
# then we'll tabulate the results of each state's first value
# then we'll look at paths, by using the concatenated list of states taken for that path as a key
if len(allTrees) != 0:
t = get_tree(id)
all_states = t.get_all_states()
loops = t.has_loops()
if not loops:
# this is the easy case. just create one column per state and then display the results
sessions = Session.objects.all().filter(tree=t)
return render_to_response("tree/data.html",
{ "trees": allTrees, "t": t, "states" : all_states, "sessions" : sessions, "loops" : loops},
context_instance=RequestContext(req))
else:
# here what we want is a table where the columns are every unique path through the
# tree, and the rows are the sessions, with the paths filled in.
# Since there are loops we have to generate the list of unique paths from
# the session data.
# So we get every session, and for every entry in that session we get the path.
# If we haven't seen the path we add it to the master list.
# Then we walk back through the master list, and walk through each session to
# see if it has an entry matching that path, and if so set the answer.
sessions = Session.objects.all().filter(tree=t)
paths = {}
# i think paths will be a dictionary of paths to dictionaries of sessions to answers
# e.g. { <path> : { <session> : <answer>}
# which will allow us to iterate through paths and say:
# if paths[path].has_key(session):
# this_cell = paths[path][session]
for session in sessions:
entries = session.entry_set.all().order_by('sequence_id')
path = ''
for entry in entries:
path = path + str(entry.transition.current_state.id) + '/'
entry.path = path
if paths.has_key(path):
paths[path][session] = entry.transition.answer
else:
paths[path] = { session : entry.transition.answer }
return render_to_response("tree/data.html",
{ "trees": allTrees, "t": t, "paths" : paths, "sessions" : sessions, "loops" : loops },
context_instance=RequestContext(req))
# now we need to map all states to answers
states_w_answers = {}
for state in all_states:
states_w_answers[state] = map((lambda x: x.answer), state.transition_set.all())
# now we need to get all the entries
all_entries = Entry.objects.all().filter(session__tree = t)
if loops:
# stupid error fix to prevent trees with loops from exploding. This should be done better
t = Tree()
t.trigger = "Sorry, can't display this tree because it has loops. We're working on it."
return render_to_response("tree/index.html",
{ "trees": allTrees, "t": t },
context_instance=RequestContext(req))
else:
return render_to_response("tree/index.html",
context_instance=RequestContext(req))
@login_required
@permission_required("tree.can_view")
def export(req, id = None):
t = get_tree(id)
all_states = t.get_all_states()
loops = t.has_loops()
if not loops:
output = StringIO()
w = csv.writer(output)
headings = ["Person", "Date"]
headings.extend([state.question for state in all_states])
w.writerow(headings)
sessions = Session.objects.all().filter(tree=t)
for session in sessions:
values = [str(session.person), session.start_date]
transitions = map((lambda x: x.transition), session.entry_set.all())
states_w_transitions = {}
for transition in transitions:
states_w_transitions[transition.current_state] = transition
for state in all_states:
if states_w_transitions.has_key(state):
values.append(states_w_transitions[state].answer)
else:
values.append("")
w.writerow(values)
# rewind the virtual file
output.seek(0)
response = HttpResponse(output.read(),
mimetype='application/ms-excel')
response["content-disposition"] = "attachment; filename=%s.csv" % t.trigger
return response
else:
return render_to_response("tree/index.html",{}, context_instance=RequestContext(req))
def get_tree(id):
'''Gets a tree. If id is specified it gets the tree with that Id.
If Id is not specified it gets the latest tree. If there are
no trees, it returns an empty tree.'''
if id:
return Tree.objects.get(id=id)
else:
if len(Tree.objects.all()) > 0:
return Tree.objects.all()[len(Tree.objects.all()) - 1]
else:
return Tree()