Commit 4632a00601e03b5e7c0252414dc6c889b6c7eebf
1 parent
89ced4bb
Exists in
master
and in
1 other branch
Modified survey to save evaluations and reports in csv format.
Showing
1 changed file
with
119 additions
and
57 deletions
Show diff stats
src/web/survey.py
... | ... | @@ -8,7 +8,10 @@ import sys |
8 | 8 | import simplejson as json |
9 | 9 | import apt |
10 | 10 | import re |
11 | +import urllib | |
11 | 12 | import socket |
13 | +import csv | |
14 | +import datetime | |
12 | 15 | |
13 | 16 | sys.path.insert(0,"/var/www/AppRecommender/src/") |
14 | 17 | |
... | ... | @@ -18,8 +21,6 @@ from recommender import * |
18 | 21 | from user import * |
19 | 22 | from data import DebianPackage |
20 | 23 | |
21 | -import urllib | |
22 | - | |
23 | 24 | # avoid "RuntimeError: maximum recursion depth exceeded" |
24 | 25 | sys.setrecursionlimit(50000) |
25 | 26 | |
... | ... | @@ -35,10 +36,23 @@ class Thanks: |
35 | 36 | def POST(self): |
36 | 37 | web_input = web.input() |
37 | 38 | user_id = web_input['user_id'].encode('utf8') |
38 | - with open("/var/www/AppRecommender/src/web/submissions/%s/personal" % user_id,'w') as ident: | |
39 | - for key in ["name","email","comments"]: | |
40 | - if web_input.has_key(key): | |
41 | - ident.write("# %s\n%s\n" % (key.capitalize(),web_input[key].encode("utf-8"))) | |
39 | + personal_file = open("/var/www/AppRecommender/src/web/submissions/%s/personal" % user_id,'w') | |
40 | + personal = {} | |
41 | + for key in ["name","email","comments"]: | |
42 | + if web_input.has_key(key): | |
43 | + personal[key] = web_input[key].encode("utf-8") | |
44 | + else: | |
45 | + personal[key] = "" | |
46 | + try: | |
47 | + writer = csv.writer(personal_file) | |
48 | + writer.writerow(("user","name","email","comments")) | |
49 | + writer.writerow((user_id,personal["name"],personal["email"],personal["comments"])) | |
50 | + except: | |
51 | + error_msg = "Could not save optional information." | |
52 | + logging.critical("Could not save optional information.") | |
53 | + return render.error([error_msg],"/survey/","START") | |
54 | + finally: | |
55 | + personal_file.close() | |
42 | 56 | return render.thanks_id() |
43 | 57 | |
44 | 58 | class Fake: |
... | ... | @@ -51,31 +65,74 @@ class Save: |
51 | 65 | logging.info("Saving user evaluation...") |
52 | 66 | logging.info(web_input) |
53 | 67 | user_id = web_input['user_id'].encode('utf8') |
54 | - with open("/var/www/AppRecommender/src/web/submissions/%s/uploaded_file" % user_id) as packages_list: | |
55 | - pkgs_list = [line.strip() for line in packages_list.readlines()] | |
68 | + user_dir = "/var/www/AppRecommender/src/web/submissions/%s" % user_id | |
56 | 69 | strategy = web_input['strategy'] |
57 | - logging.debug("Saving evaluation for user %s, strategy %s and packages..." | |
70 | + strategy_dir = os.path.join(user_dir,strategy) | |
71 | + logging.debug("Saving evaluation for user %s strategy %s." | |
58 | 72 | % (user_id,strategy)) |
59 | - logging.debug(pkgs_list) | |
60 | - evaluations = {} | |
61 | - evaluations["poor"] = [] | |
62 | - evaluations["good"] = [] | |
63 | - evaluations["surprising"] = [] | |
64 | - for key, value in web_input.items(): | |
65 | - if key.startswith("evaluation-"): | |
66 | - evaluations[value.encode('utf8')].append(key.lstrip("evaluation-")) | |
67 | - output_dir = ("/var/www/AppRecommender/src/web/submissions/%s/%s/" % (user_id,strategy)) | |
68 | - for key,value in evaluations.items(): | |
69 | - with open(os.path.join(output_dir,key),'w') as output: | |
70 | - for item in value: | |
71 | - output.write(item+"\n") | |
72 | - with open(os.path.join(output_dir,"report"),'w') as report: | |
73 | - report.write("# User: %s\n# Strategy: %s\n# TP FP S\n%d %d %d\n" % | |
74 | - (user_id,strategy, | |
75 | - len(evaluations["good"])+len(evaluations["surprising"]), | |
76 | - len(evaluations["poor"]),len(evaluations["surprising"]))) | |
73 | + summary = {} | |
74 | + summary["poor"] = 0 | |
75 | + summary["good"] = 0 | |
76 | + summary["surprising"] = 0 | |
77 | + | |
78 | + # Save evaluation | |
79 | + try: | |
80 | + prediction_file = open(os.path.join(strategy_dir,"prediction"),'r') | |
81 | + evaluation_file = open(os.path.join(strategy_dir,"evaluation"),'w') | |
82 | + reader = csv.DictReader(prediction_file) | |
83 | + writer = csv.DictWriter(evaluation_file,fieldnames=reader.fieldnames) | |
84 | + headers = dict( (n,n) for n in reader.fieldnames ) | |
85 | + writer.writerow(headers) | |
86 | + for key, value in web_input.items(): | |
87 | + if key.startswith("evaluation-"): | |
88 | + ranking = key.lstrip("evaluation-") | |
89 | + for row in reader: | |
90 | + if row['ranking'] == ranking: | |
91 | + evaluation = value.encode('utf8') | |
92 | + row['evaluation'] = evaluation | |
93 | + writer.writerow(row) | |
94 | + summary[evaluation] += 1 | |
95 | + break | |
96 | + prediction_file.seek(0) | |
97 | + except: | |
98 | + error_msg = "Could not write evaluation to file." | |
99 | + logging.critical(error_msg) | |
100 | + return render.error([error_msg], "/survey/","START") | |
101 | + finally: | |
102 | + prediction_file.close() | |
103 | + evaluation_file.close() | |
104 | + os.remove(os.path.join(strategy_dir,"prediction")) | |
105 | + with open(os.path.join(strategy_dir,"end"),'w') as end: | |
106 | + end_time = datetime.datetime.now().strftime("%Y%m%d%H%M%S") | |
107 | + end.write(end_time) | |
108 | + | |
109 | + # Save report | |
110 | + try: | |
111 | + report = os.path.join(user_dir,"report") | |
112 | + report_file = open(os.path.join(user_dir,"report"),'a') | |
113 | + writer = csv.writer(report_file) | |
114 | + if os.path.getsize(report) == 0: | |
115 | + fieldnames = ('user','strategy',"start","end",'truepositive', | |
116 | + 'falsepositive','surprise','comments') | |
117 | + writer.writerow(fieldnames) | |
118 | + with open(os.path.join(strategy_dir,"start"),'r') as start: | |
119 | + start_time = start.readline().strip() | |
77 | 120 | if web_input.has_key("comments"): |
78 | - report.write("# Comments\n%s\n" % web_input['comments'].encode("utf-8")) | |
121 | + comments = web_input['comments'].encode("utf-8") | |
122 | + else: | |
123 | + comments = "" | |
124 | + writer.writerow((user_id,strategy,start_time,end_time, | |
125 | + summary["good"]+summary["surprising"], | |
126 | + summary["poor"],summary["surprising"],comments)) | |
127 | + except: | |
128 | + if comments: | |
129 | + error_msg = "Could not save comments." | |
130 | + logging.critical(error_msg) | |
131 | + return render.error([error_msg], "/survey/","START") | |
132 | + logging.critical("Could not save evaluation report.") | |
133 | + finally: | |
134 | + report_file.close() | |
135 | + | |
79 | 136 | if web_input.has_key('continue_button'): |
80 | 137 | return Survey().POST() |
81 | 138 | elif web_input.has_key('finish_button'): |
... | ... | @@ -137,38 +194,18 @@ class Survey: |
137 | 194 | "knnco","knnco_eset"] |
138 | 195 | request = Request(web_input,self.submissions_dir) |
139 | 196 | if len(request.user.pkg_profile)<10: |
140 | - return render.error(["Could not extract profile from uploaded file. It must have at least 10 applications."], | |
141 | - "/survey/","START") | |
197 | + error_msg = "Could not extract profile from uploaded file. It must have at least 10 applications." | |
198 | + logging.critical(error_msg) | |
199 | + return render.error([error_msg], "/survey/","START") | |
142 | 200 | else: |
143 | - ## Check the remaining strategies and select a new one | |
144 | - #old_strategies = [dirs for root, dirs, files in | |
145 | - # os.walk(os.path.join(self.submissions_dir, | |
146 | - # request.user_id))] | |
147 | - #if old_strategies: | |
148 | - # strategies = [s for s in self.strategies if s not in old_strategies[0]] | |
149 | - # logging.info("Already used strategies %s" % old_strategies[0]) | |
150 | - #else: | |
151 | - # strategies = self.strategies | |
152 | - #if not strategies: | |
153 | - # return render.thanks(request.user_id) | |
154 | - #request.strategy = random.choice(strategies) | |
155 | - #logging.info("Selected \'%s\' from %s" % (request.strategy,strategies)) | |
156 | - ## Get recommendation | |
157 | - #self.rec.set_strategy(request.strategy) | |
158 | 201 | request.strategy = self.set_rec_strategy(request.user_id) |
159 | 202 | prediction = self.rec.get_recommendation(request.user,10).get_prediction() |
160 | 203 | logging.info("Prediction for user %s" % request.user_id) |
161 | 204 | logging.info(str(prediction)) |
162 | - strategy_dir = os.path.join(request.user_dir,request.strategy) | |
163 | - os.makedirs(strategy_dir) | |
164 | - with open(os.path.join(strategy_dir,"prediction"),"w") as prediction_file: | |
165 | - for pkg,rating in prediction: | |
166 | - prediction_file.write("%s %f.2\n" % (pkg,rating)) | |
167 | - logging.debug("Saved %s/%s prediction to file" % | |
168 | - (request.user_id,request.strategy)) | |
169 | - recommendation = [result[0] for result in prediction] | |
205 | + self.save_prediction(request,prediction) | |
170 | 206 | |
171 | 207 | # Load packages details |
208 | + recommendation = [result[0] for result in prediction] | |
172 | 209 | pkgs_details = [] |
173 | 210 | for pkg_name in recommendation: |
174 | 211 | logging.info("Getting details of package %s" % pkg_name) |
... | ... | @@ -219,6 +256,30 @@ class Survey: |
219 | 256 | self.rec.set_strategy(selected_strategy,k,n) |
220 | 257 | return selected_strategy |
221 | 258 | |
259 | + def save_prediction(self,request,prediction): | |
260 | + strategy_dir = os.path.join(request.user_dir,request.strategy) | |
261 | + if not os.path.exists(strategy_dir): | |
262 | + os.makedirs(strategy_dir) | |
263 | + ranking = 0 | |
264 | + prediction_file = open(os.path.join(strategy_dir,"prediction"),"w") | |
265 | + try: | |
266 | + writer = csv.writer(prediction_file) | |
267 | + fieldnames = ('ranking','rating','package','evaluation') | |
268 | + writer.writerow(fieldnames) | |
269 | + for pkg,rating in prediction: | |
270 | + writer.writerow((ranking,"%.4f"%rating,pkg,"")) | |
271 | + ranking += 1 | |
272 | + except: | |
273 | + error_msg = "Error to write prediction to file." | |
274 | + logging.critical(error_msg) | |
275 | + return render.error([error_msg], "/survey/","START") | |
276 | + finally: | |
277 | + prediction_file.close() | |
278 | + with open(os.path.join(strategy_dir,"start"),'w') as start: | |
279 | + now = datetime.datetime.now() | |
280 | + start.write(now.strftime("%Y%m%d%H%M%S")) | |
281 | + logging.debug("Saved prediction to file at %s/%s" % | |
282 | + (request.user_id,request.strategy)) | |
222 | 283 | #def add_global_hook(): |
223 | 284 | # g = web.storage({"counter": "1"}) |
224 | 285 | # def _wrapper(handler): |
... | ... | @@ -227,14 +288,15 @@ class Survey: |
227 | 288 | # return _wrapper |
228 | 289 | |
229 | 290 | render = web.template.render('/var/www/AppRecommender/src/web/templates/', base='layout', globals={'hasattr':hasattr}) |
291 | +render_plain = web.template.render('/var/www/AppRecommender/src/web/templates/', globals={'hasattr':hasattr}) | |
230 | 292 | |
231 | -urls = ('', 'Index', | |
232 | - '/', 'Index', | |
233 | - '/survey', 'Survey', | |
234 | - '/apprec', 'Survey', | |
293 | +urls = ('/apprec', 'Survey', | |
235 | 294 | '/thanks', 'Thanks', |
236 | 295 | '/save', 'Save', |
237 | 296 | '/about', 'About', |
297 | + '/index', 'Index', | |
298 | + '/', 'Index', | |
299 | +# '/', 'Fake', | |
238 | 300 | ) |
239 | 301 | |
240 | 302 | web.webapi.internalerror = web.debugerror | ... | ... |