Commit 4632a00601e03b5e7c0252414dc6c889b6c7eebf

Authored by Tássia Camões Araújo
1 parent 89ced4bb
Exists in master and in 1 other branch add_vagrant

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
... ...