Commit 928cc9054b057b5b14ed07d6cb6020d6236e866d

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

Survey refactoring.

Showing 2 changed files with 104 additions and 126 deletions   Show diff stats
src/web/survey.py
... ... @@ -8,6 +8,7 @@ import sys
8 8 import simplejson as json
9 9 import apt
10 10 import re
  11 +import socket
11 12  
12 13 sys.path.insert(0,"../")
13 14  
... ... @@ -15,6 +16,7 @@ import logging
15 16 from config import Config
16 17 from recommender import *
17 18 from user import *
  19 +from data import DebianPackage
18 20  
19 21 import urllib
20 22  
... ... @@ -77,64 +79,13 @@ class Package:
77 79 subtags = []
78 80 return debtags
79 81  
80   -class Request:
81   - def __init__(self,web_input,submissions_dir,user_id=0,pkgs_list=0):
82   - self.strategy = ""
83   - if user_id:
84   - self.user_id = user_id
85   - self.outputdir = os.path.join(submissions_dir,user_id)
86   - logging.info("New round for user %s" % self.user_id)
87   - else:
88   - self.outputdir = tempfile.mkdtemp(prefix='',dir=submissions_dir)
89   - self.user_id = self.outputdir.lstrip(submissions_dir)
90   - logging.info("Request from user %s" % self.user_id)
91   - logging.debug("Created dir %s" % self.outputdir)
92   -
93   - pkgs_list_file = os.path.join(self.outputdir,"packages_list")
94   - if pkgs_list:
95   - self.pkgs_list = pkgs_list
96   - if not os.path.exists(pkgs_list_file):
97   - with open(pkgs_list_file,"w") as f:
98   - for pkg in pkgs_list:
99   - f.write(pkg+"\n")
100   - else:
101   - self.pkgs_list = []
102   - if web_input['pkgs_file'].value:
103   - f = open(pkgs_list_file, "w")
104   - lines = web_input['pkgs_file'].file.readlines()
105   - with open(os.path.join(self.outputdir,"upload"), "w") as upload:
106   - upload.writelines(lines)
107   - # popcon submission format
108   - if lines[0].startswith('POPULARITY-CONTEST'):
109   - del lines[0]
110   - del lines[-1]
111   - package_name_field = 2
112   - else:
113   - package_name_field = 0
114   - for line in lines:
115   - self.pkgs_list.append(line.split()[package_name_field])
116   - for pkg in self.pkgs_list:
117   - f.write(pkg+'\n')
118   - f.close()
119   -
120   - def __str__(self):
121   - return "Request %s:\n %s" % (self.user_id,str(self.pkgs_list))
122   -
123   - def validates(self):
124   - self.errors = []
125   - if not self.pkgs_list:
126   - self.errors.append("No packages list provided.")
127   - if self.errors:
128   - return False
129   - return True
130   -
131 82 class Save:
132 83 def POST(self):
133 84 web_input = web.input()
134 85 logging.info("Saving user evaluation...")
135 86 logging.info(web_input)
136 87 user_id = web_input['user_id'].encode('utf8')
137   - with open("./submissions/%s/packages_list" % user_id) as packages_list:
  88 + with open("./submissions/%s/uploaded_file" % user_id) as packages_list:
138 89 pkgs_list = [line.strip() for line in packages_list.readlines()]
139 90 strategy = web_input['strategy']
140 91 logging.debug("Saving evaluation for user %s, strategy %s and packages..."
... ... @@ -164,10 +115,48 @@ class Save:
164 115 else:
165 116 return render.survey_index()
166 117  
  118 +class Request:
  119 + def __init__(self,web_input,submissions_dir):
  120 + self.strategy = ""
  121 + # Check if it is first round
  122 + if web_input.has_key('user_id'):
  123 + self.user_id = web_input['user_id'].encode('utf8')
  124 + self.user_dir = os.path.join(submissions_dir, self.user_id)
  125 + logging.info("New round for user %s" % self.user_id)
  126 + else:
  127 + self.user_dir = tempfile.mkdtemp(prefix='',dir=submissions_dir)
  128 + self.user_id = self.user_dir.split("/")[-1]
  129 + logging.info("Request from user %s" % self.user_id)
  130 + logging.debug("Created dir %s" % self.user_dir)
  131 + uploaded_file = os.path.join(self.user_dir,"uploaded_file")
  132 + if not os.path.exists(uploaded_file):
  133 + if web_input['pkgs_file'].value:
  134 + lines = web_input['pkgs_file'].file.readlines()
  135 + with open(uploaded_file, "w") as uploaded:
  136 + uploaded.writelines(lines)
  137 + with open(uploaded_file) as uploaded:
  138 + if uploaded.readline().startswith('POPULARITY-CONTEST'):
  139 + self.user = PopconSystem(uploaded_file,self.user_id)
  140 + else:
  141 + self.user = PkgsListSystem(uploaded_file,self.user_id)
  142 +
  143 + def __str__(self):
  144 + return "Request %s:\n %s" % (self.user.user_id,
  145 + str(self.user.pkg_profile))
  146 +
  147 + def validates(self):
  148 + self.errors = []
  149 + if not self.user.pkg_profile:
  150 + self.errors.append("No packages list provided.")
  151 + if self.errors:
  152 + return False
  153 + return True
  154 +
167 155 class Survey:
168 156 def __init__(self):
169 157 logging.info("Setting up survey...")
170   - self.rec = Recommender(Config())
  158 + self.cfg = Config()
  159 + self.rec = Recommender(self.cfg)
171 160 self.submissions_dir = "./submissions/"
172 161 if not os.path.exists(self.submissions_dir):
173 162 os.makedirs(self.submissions_dir)
... ... @@ -175,25 +164,12 @@ class Survey:
175 164 def POST(self):
176 165 web_input = web.input(pkgs_file={})
177 166 logging.debug("Survey web_input %s" % str(web_input))
178   - self.strategies = ["cb","cbd","cbt","col"]
179   - # If it is not the first strategy round, save the previous evaluation
180   - if not web_input.has_key('user_id'):
181   - request = Request(web_input,self.submissions_dir)
182   - else:
183   - user_id = web_input['user_id'].encode('utf8')
184   - with open("./submissions/%s/packages_list" % user_id) as packages_list:
185   - pkgs_list = [line.strip() for line in packages_list.readlines()]
186   - request = Request(web_input,self.submissions_dir,user_id,pkgs_list)
  167 + self.strategies = ["demo_cb","demo_cbd","demo_cbt","demo_col"]#,"demo_colco"]
  168 + request = Request(web_input,self.submissions_dir)
187 169 if not request.validates():
188 170 return render.error_survey()
189 171 else:
190   - user = User(dict.fromkeys(request.pkgs_list,1),request.user_id)
191   - program_profile = user.filter_pkg_profile(os.path.join(self.rec.cfg.filters,"program"))
192   - desktop_profile = user.filter_pkg_profile(os.path.join(self.rec.cfg.filters,"desktop"))
193   - if (len(desktop_profile)>10 or
194   - len(desktop_profile)>len(program_profile)/2):
195   - self.strategies = [strategy_str+"_desktop" for strategy_str
196   - in self.strategies[:]]
  172 + # Check the remaining strategies and select a new one
197 173 old_strategies = [dirs for root, dirs, files in
198 174 os.walk(os.path.join(self.submissions_dir,
199 175 request.user_id))]
... ... @@ -203,34 +179,45 @@ class Survey:
203 179 else:
204 180 strategies = self.strategies
205 181 if not strategies:
206   - return render.thanks(user_id)
  182 + return render.thanks(request.user_id)
207 183 request.strategy = random.choice(strategies)
208 184 logging.info("Selected \'%s\' from %s" % (request.strategy,strategies))
  185 + # Get recommendation
209 186 self.rec.set_strategy(request.strategy)
210   - prediction = self.rec.get_recommendation(user,10).get_prediction()
211   - logging.info("Prediction for user %s" % user.user_id)
  187 + prediction = self.rec.get_recommendation(request.user,2).get_prediction()
  188 + logging.info("Prediction for user %s" % request.user_id)
212 189 logging.info(str(prediction))
213   - output_dir = ("./submissions/%s/%s/" %
214   - (user.user_id,request.strategy))
215   - os.makedirs(output_dir)
216   - with open(os.path.join(output_dir,"prediction"),"w") as prediction_file:
  190 + strategy_dir = os.path.join(request.user_dir,request.strategy)
  191 + os.makedirs(strategy_dir)
  192 + with open(os.path.join(strategy_dir,"prediction"),"w") as prediction_file:
217 193 for pkg,rating in prediction:
218 194 prediction_file.write("%s %f.2\n" % (pkg,rating))
219 195 logging.debug("Saved %s/%s prediction to file" %
220   - (user.user_id,request.strategy))
  196 + (request.user_id,request.strategy))
221 197 recommendation = [result[0] for result in prediction]
222   - pkg_summaries = {}
223   - pkg_details = []
224   - cache = apt.Cache()
225   - for pkg in recommendation:
226   - try:
227   - logging.debug("Getting details of package %s" % pkg)
228   - pkg_details.append(Package().get_details_from_dde(pkg))
229   - pkg_summaries[pkg] = cache[pkg].candidate.summary
230   - except:
231   - pkg_summaries[pkg] = ""
232   - if pkg_details:
233   - return render.survey(pkg_details, request)
  198 +
  199 + # Check connection to DDE
  200 + try:
  201 + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  202 + s.connect((self.cfg.dde_server,self.cfg.dde_port))
  203 + dde = 1
  204 + s.close()
  205 + except:
  206 + dde =0
  207 + logging.debug("Could not connect to dde")
  208 + # Load packages details
  209 + pkgs_details = []
  210 + for pkg_name in recommendation:
  211 + logging.info("Getting details of package %s" % pkg_name)
  212 + pkg = DebianPackage(pkg_name)
  213 + if dde:
  214 + pkg.load_details_from_dde(self.cfg.dde_server,self.cfg.dde_port)
  215 + else:
  216 + pkg.load_details_from_apt()
  217 + pkgs_details.append(pkg)
  218 + if pkgs_details:
  219 + logging.info("Rendering survey slide...")
  220 + return render.survey(pkgs_details, request)
234 221 else:
235 222 return render.error_survey()
236 223  
... ... @@ -241,7 +228,7 @@ def add_global_hook():
241 228 return handler()
242 229 return _wrapper
243 230  
244   -render = web.template.render('templates/', base='layout')
  231 +render = web.template.render('templates/', base='layout', globals={'hasattr':hasattr})
245 232 render_plain = web.template.render('templates/')
246 233  
247 234 urls = ('/', 'Index',
... ...
src/web/templates/survey.html
1   -$def with (pkg_details, request)
  1 +$def with (pkgs_details, request)
2 2 $var title: Survey
3 3 $var mod = 'survey';
4 4 $var cssfiles: static/coda-slider-2.0/stylesheets/coda-slider-2.0.css static/css/facebox.css static/css/survey.css
... ... @@ -38,7 +38,7 @@ button below.
38 38  
39 39 <form action="/save" method="post" enctype="multipart/form-data" name="surveyform">
40 40  
41   -<input type="hidden" name="user_id" value=$request.user_id>
  41 +<input type="hidden" name="user_id" value=$request.user.user_id>
42 42 <input type="hidden" name="strategy" value=$request.strategy>
43 43 <div id="controls-form" style="display: none;" class="show-end"><!-- display show in the end form -->
44 44 <label for="finish_button" id="tip-finish">
... ... @@ -57,63 +57,54 @@ button below.
57 57  
58 58 <div class="coda-slider-wrapper hide-end">
59 59 <div class="coda-slider preload" id="coda-slider-1">
60   -$for pkg in pkg_details:
  60 +$for pkg in pkgs_details:
61 61 <div class="panel">
62 62 <div class="panel-wrapper">
63 63 <div class="screenshot">
64 64 <a class="link-thumb" rel="facebox"
65   - href="http://screenshots.debian.net/screenshot/$pkg['package']?.jpg"
66   - title="Click to enlarge screenshot of package $pkg['package']" alt="Click to enlarge screenshot">
67   - <img height="70px" src="http://screenshots.debian.net/thumbnail/$pkg['package']"
68   - alt="Screenshot $pkg['package']" /></a>
  65 + href="http://screenshots.debian.net/screenshot/$pkg.name?.jpg"
  66 + title="Click to enlarge screenshot of package $pkg.name" alt="Click to enlarge screenshot">
  67 + <img height="70px" src="http://screenshots.debian.net/thumbnail/$pkg.name"
  68 + alt="Screenshot $pkg.name" /></a>
69 69 </div><!-- screenshot -->
70   - <h1 style="float: right;">($(pkg_details.index(pkg)+1)/10)</h1>
71   - <h1 id="title_pkg"> $pkg['package'] <br />
72   - <span>$pkg['description']</span></h1>
  70 + <h1 style="float: right;">($(pkgs_details.index(pkg)+1)/10)</h1>
  71 + <h1 id="title_pkg"> $pkg.name <br />
  72 + <span>$pkg.summary</span></h1>
73 73 <br style="clear: both;" />
74 74 <div id="panel-controls" class="glass">
75 75 <fieldset>
76 76 <legend>How do you evaluate this<br> recommendation?</legend>
77 77 <label class="radioButton">
78   - <input class="radio" type="radio" name="evaluation-$pkg_details.index(pkg)" value="surprising" />
  78 + <input class="radio" type="radio" name="evaluation-$pkgs_details.index(pkg)" value="surprising" />
79 79 Pleasantly surprising
80   - <!--<div class="tip tip">
81   - <p>Pleasantly $pkg['package'] FIXME </p>
82   - </div>-->
83 80 </label><br />
84 81 <label class="radioButton">
85   - <input class="radio yesb" type="radio" name="evaluation-$pkg_details.index(pkg)" value="good" />
  82 + <input class="radio yesb" type="radio" name="evaluation-$pkgs_details.index(pkg)" value="good" />
86 83 Useful
87   - <!--<div class="tip tip">
88   - <p>Good $pkg['package'] FIXME </p>
89   - </div>-->
90 84 </label><br />
91 85 <label class="radioButton">
92   - <input class="radio" type="radio" name="evaluation-$pkg_details.index(pkg)" value="poor" />
  86 + <input class="radio" type="radio" name="evaluation-$(pkgs_details.index(pkg))" value="poor" />
93 87 Poor
94   - <!--<div class="tip tip">
95   - <p>Poor $pkg['package'] FIXME </p>
96   - </div>-->
97 88 </label>
98 89 </fieldset>
99 90 <br style="clear: both;" />
100 91 </div><!-- #panel-controls -->
101 92 <div class="content-pkg">
102 93 <ul>
103   - <li><b>Description</b>:
104   - <br />$:pkg['long_description']</li>
105   - $if pkg['homepage']:
106   - <li><b>Homepage</b>: $pkg['homepage']</li>
107   - $if pkg['task']:
108   - <li><b>Tasks</b>: $pkg['task']</li>
109   - <li><b>Section</b>: $pkg['section']</li>
110   - $if pkg['recommends']:
111   - <li><b>Recommends</b>: $pkg['recommends']</li>
112   - $if pkg['suggests']:
113   - <li><b>Suggests</b>: $pkg['suggests']</li>
114   - $if pkg['origin']:
115   - <li><b>Origin</b>: $pkg['origin']</li>
116   - <li><b>Maintainer</b>: $pkg['maintainer']</li>
  94 + $if hasattr(pkg,'description'):
  95 + <li><b>Description</b>: <br />$:pkg.description</li>
  96 + $if hasattr(pkg,'homepage'):
  97 + <li><b>Homepage</b>: $pkg.homepage</li>
  98 + $if hasattr(pkg,'task'):
  99 + <li><b>Tasks</b>: $pkg.task</li>
  100 + $if hasattr(pkg,'section'):
  101 + <li><b>Section</b>: $pkg.section</li>
  102 + $if hasattr(pkg,'recommends'):
  103 + <li><b>Recommends</b>: $pkg.recommends</li>
  104 + $if hasattr(pkg,'suggests'):
  105 + <li><b>Suggests</b>: $pkg.suggests</li>
  106 + $if hasattr(pkg,'maintainer'):
  107 + <li><b>Maintainer</b>: $pkg.maintainer.</li>
117 108 </ul>
118 109 </div><!-- id="content-pkg" -->
119 110 </div><!-- .panel-wrapper -->
... ...