Commit 100c50829e5d0c6defa61cf0941bd37728f1714d

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

New script dedicated for survey.

src/web/server.py
... ... @@ -16,16 +16,16 @@ from user import *
16 16  
17 17 import urllib
18 18  
19   -class FeedbackForm(form.Form):
20   - def __init__(self,selected_strategies):
21   - desc_dict = {"cb": "Content-based", "cbt": "Content-based",
22   - "cbd": "Content-based", "col": "Collaborative",
23   - "hybrid": "Hybrib"}
24   - fields = []
25   - for strategy in selected_strategies:
26   - fields.append(form.Radio(desc_dict[strategy],
27   - [('1','1 '),('2','2 '),('3','3'),('4','4 '),('5','5')]))
28   - form.Form.__init__(self, *fields, validators = [])
  19 +#class FeedbackForm(form.Form):
  20 +# def __init__(self,selected_strategies):
  21 +# desc_dict = {"cb": "Content-based", "cbt": "Content-based",
  22 +# "cbd": "Content-based", "col": "Collaborative",
  23 +# "hybrid": "Hybrib"}
  24 +# fields = []
  25 +# for strategy in selected_strategies:
  26 +# fields.append(form.Radio(desc_dict[strategy],
  27 +# [('1','1 '),('2','2 '),('3','3'),('4','4 '),('5','5')]))
  28 +# form.Form.__init__(self, *fields, validators = [])
29 29  
30 30 class Index:
31 31 def GET(self):
... ... @@ -38,9 +38,9 @@ class About:
38 38 def GET(self):
39 39 return render.about()
40 40  
41   -class Support:
42   - def GET(self):
43   - return render.support()
  41 +#class Support:
  42 +# def GET(self):
  43 +# return render.support()
44 44  
45 45 class Thanks:
46 46 def POST(self):
... ... @@ -220,14 +220,15 @@ class Request:
220 220 print details
221 221 return details
222 222  
223   -class RandomRequest(Request):
224   - def __init__(self):
225   - pass
226   - #self.storage = web.Storage()
  223 +#class RandomRequest(Request):
  224 +# def __init__(self):
  225 +# pass
  226 +# #self.storage = web.Storage()
227 227  
228 228 class AppRecommender:
229 229 def __init__(self):
230   - self.rec = Recommender(Config())
  230 + self.cfg = Config()
  231 + self.rec = Recommender(self.cfg)
231 232  
232 233 def POST(self):
233 234 request = Request(web.input(pkgs_file={}))
... ... @@ -248,8 +249,7 @@ class AppRecommender:
248 249 pkg_summaries[pkg] = ""
249 250 if Config().survey_mode:
250 251 return render.survey(recommendation, pkg_details,
251   - FeedbackForm(request.selected_strategies),
252   - request)
  252 + FeedbackForm(request.selected_strategies))
253 253 else:
254 254 return render.apprec(recommendation, pkg_summaries,
255 255 FeedbackForm(request.selected_strategies),
... ...
src/web/survey.py 0 → 100755
... ... @@ -0,0 +1,222 @@
  1 +#!/usr/bin/env python
  2 +
  3 +import os
  4 +import web
  5 +from web import form
  6 +import tempfile
  7 +import sys
  8 +import simplejson as json
  9 +import apt
  10 +import re
  11 +
  12 +sys.path.insert(0,"../")
  13 +
  14 +from config import *
  15 +from recommender import *
  16 +from user import *
  17 +
  18 +import urllib
  19 +
  20 +class Index:
  21 + def GET(self):
  22 + return render.survey_index()
  23 +
  24 +class About:
  25 + def GET(self):
  26 + return render.about()
  27 +
  28 +class Thanks:
  29 + def POST(self):
  30 + return render.thanks()
  31 +
  32 +class Package:
  33 + def GET(self, pkg):
  34 + result = self.get_details_from_dde(pkg)
  35 + return render_plain.package(result)
  36 +
  37 + def get_details_from_dde(self, pkg):
  38 + json_source = Config().dde_url % pkg
  39 + json_data = json.load(urllib.urlopen(json_source))
  40 + # parse tags
  41 + tags = self._debtags_list_to_dict(json_data['r']['tag'])
  42 + json_data['r']['tag'] = tags
  43 + # format long description
  44 + json_data['r']['long_description'] = json_data['r']['long_description'].replace(' .\n','').replace('\n','<br />')
  45 + return json_data['r']
  46 +
  47 + def _debtags_list_to_dict(self, debtags_list):
  48 + """ in:
  49 + ['use::editing',
  50 + 'works-with-format::gif',
  51 + 'works-with-format::jpg',
  52 + 'works-with-format::pdf']
  53 + out:
  54 + {'use': [editing],
  55 + 'works-with-format': ['gif', 'jpg', 'pdf']'
  56 + }
  57 + """
  58 + debtags = {}
  59 + subtags = []
  60 + for tag in debtags_list:
  61 + match = re.search(r'^(.*)::(.*)$', tag)
  62 + if not match:
  63 + log.error("Could not parse debtags format from tag: %s", tag)
  64 + facet, subtag = match.groups()
  65 + subtags.append(subtag)
  66 + if facet not in debtags:
  67 + debtags[facet] = subtags
  68 + else:
  69 + debtags[facet].append(subtag)
  70 + subtags = []
  71 + return debtags
  72 +
  73 +class Request:
  74 + def __init__(self,web_input,submissions_dir,user_id=0,pkgs_list=0):
  75 + self.strategy = ""
  76 + if user_id:
  77 + self.user_id = user_id
  78 + self.outputdir = os.path.join(submissions_dir,user_id)
  79 + else:
  80 + self.outputdir = tempfile.mkdtemp(prefix='',dir=submissions_dir)
  81 + print "created dir %s",self.outputdir
  82 + self.user_id = self.outputdir.lstrip(submissions_dir)
  83 +
  84 + if pkgs_list:
  85 + self.pkgs_list = pkgs_list
  86 + else:
  87 + self.pkgs_list = []
  88 + if web_input['pkgs_file'].value:
  89 + f = open(self.outputdir + "/packages_list", "wb")
  90 + lines = web_input['pkgs_file'].file.readlines()
  91 + # popcon submission format
  92 + if lines[0].startswith('POPULARITY-CONTEST'):
  93 + del lines[0]
  94 + del lines[-1]
  95 + package_name_field = 2
  96 + else:
  97 + package_name_field = 0
  98 + for line in lines:
  99 + self.pkgs_list.append(line.split()[package_name_field])
  100 + f.write(line)
  101 + f.close()
  102 +
  103 + def __str__(self):
  104 + return "Request %s:\n %s" % (self.user_id,str(self.pkgs_list))
  105 +
  106 + def validates(self):
  107 + self.errors = []
  108 + if not self.pkgs_list:
  109 + self.errors.append("No packages list provided.")
  110 + if self.errors:
  111 + return False
  112 + return True
  113 +
  114 +class Save:
  115 + def POST(self):
  116 + web_input = web.input()
  117 + print web_input
  118 + user_id = web_input['user_id'].encode('utf8')
  119 + with open("./submissions/%s/packages_list" % user_id) as packages_list:
  120 + pkgs_list = [line.strip() for line in packages_list.readlines()]
  121 + strategy = web_input['strategy']
  122 + print user_id,strategy,pkgs_list
  123 + output_dir = "./submissions/%s/%s/" % (user_id,strategy)
  124 + if not os.path.exists(output_dir):
  125 + os.makedirs(output_dir)
  126 + evaluations = {}
  127 + evaluations["poor"] = []
  128 + evaluations["good"] = []
  129 + evaluations["surprising"] = []
  130 + for key, value in web_input.items():
  131 + if key.startswith("evaluation-"):
  132 + evaluations[value.encode('utf8')].append(key.lstrip("evaluation-"))
  133 + for key,value in evaluations.items():
  134 + with open(output_dir+key,'w') as output:
  135 + for item in value:
  136 + output.write(item+"\n")
  137 + with open(output_dir+"report",'w') as report:
  138 + report.write("# User: %s\n# Strategy: %s\n# TP FP\n%d %d\n" %
  139 + (user_id,strategy,
  140 + len(evaluations["good"])+len(evaluations["surprising"]),
  141 + len(evaluations["poor"])))
  142 + if web_input.has_key('strategy_button'):
  143 + return Survey().POST()
  144 + elif web_input.has_key('finish_button'):
  145 + return render.thanks()
  146 + else:
  147 + return render.survey_index()
  148 +
  149 +class Survey:
  150 + def __init__(self):
  151 + self.strategies = ["cb","cbd","cbt"]
  152 + self.rec = Recommender(Config())
  153 + self.submissions_dir = "./submissions/"
  154 + if not os.path.exists(self.submissions_dir):
  155 + os.makedirs(self.submissions_dir)
  156 +
  157 + def POST(self):
  158 + web_input = web.input(pkgs_file={})
  159 + print "WEB_INPUT",web_input
  160 + # If it is not the first strategy round, save the previous evaluation
  161 + if not web_input.has_key('user_id'):
  162 + request = Request(web_input,self.submissions_dir)
  163 + else:
  164 + user_id = web_input['user_id'].encode('utf8')
  165 + with open("./submissions/%s/packages_list" % user_id) as packages_list:
  166 + pkgs_list = [line.strip() for line in packages_list.readlines()]
  167 + request = Request(web_input,self.submissions_dir,user_id,pkgs_list)
  168 + if not request.validates():
  169 + return render.error(request.errors)
  170 + else:
  171 + user = User(dict.fromkeys(request.pkgs_list,1),request.user_id)
  172 + user.maximal_pkg_profile()
  173 + results = dict()
  174 + old_strategies = [dirs for root, dirs, files in
  175 + os.walk(os.path.join(self.submissions_dir,
  176 + request.user_id))]
  177 + print "OLD Strategies", old_strategies[0]
  178 + strategies = [s for s in self.strategies if s not in old_strategies[0]]
  179 + print "LEFT",strategies
  180 + request.strategy = random.choice(strategies)
  181 + print "selected",request.strategy
  182 + self.rec.set_strategy(request.strategy)
  183 + prediction = self.rec.get_recommendation(user,10).get_prediction()
  184 + print prediction
  185 + recommendation = [result[0] for result in prediction]
  186 + pkg_summaries = {}
  187 + pkg_details = []
  188 + cache = apt.Cache()
  189 + for pkg in recommendation:
  190 + try:
  191 + pkg_details.append(Package().get_details_from_dde(pkg))
  192 + pkg_summaries[pkg] = cache[pkg].candidate.summary
  193 + except:
  194 + pkg_summaries[pkg] = ""
  195 + return render.survey(pkg_details, request)
  196 +
  197 +def add_global_hook():
  198 + g = web.storage({"counter": "1"})
  199 + def _wrapper(handler):
  200 + web.ctx.globals = g
  201 + return handler()
  202 + return _wrapper
  203 +
  204 +render = web.template.render('templates/', base='layout')
  205 +render_plain = web.template.render('templates/')
  206 +
  207 +urls = ('/', 'Index',
  208 + '/survey', 'Survey',
  209 + '/apprec', 'Survey',
  210 + '/thanks', 'Thanks',
  211 + '/save', 'Save',
  212 + '/about', 'About',
  213 + '/package/(.*)', 'Package'
  214 + )
  215 +
  216 +web.webapi.internalerror = web.debugerror
  217 +
  218 +if __name__ == "__main__":
  219 + apprec = web.application(urls, globals())
  220 + apprec.add_processor(add_global_hook())
  221 + apprec.run()
  222 +
... ...
src/web/templates/layout.html
... ... @@ -12,14 +12,14 @@ $ url_base = &quot;http://localhost:8080&quot;
12 12  
13 13 <link href="static/css/style.css" rel="stylesheet" type="text/css" media="screen" charset="utf-8">
14 14  
15   - $if content.cssfiles:
  15 + $if content.has_key('cssfiles'):
16 16 $for css in content.cssfiles.split():
17 17 <link href="$css" rel="stylesheet" type="text/css" media="screen" charset="utf-8"/>
18 18  
19 19 <script src="/static/js/jquery.js" type="text/javascript"></script>
20 20 <script src="/static/js/FormManager.js" type="text/javascript"></script>
21 21  
22   - $if content.jsfiles:
  22 + $if content.has_key('jsfiles'):
23 23 $for js in content.jsfiles.split():
24 24 <script src="$js" type="text/javascript"></script>
25 25  
... ... @@ -85,10 +85,11 @@ function validateForm()
85 85 </p>
86 86 <div id="tip-upload" class="tip important">
87 87 <p>
88   - You can use file <strong>/var/log/popularity-contest</strong> or create a with <strong>dpkg</strong>, use:
  88 + Upload a popularity-contest submission file ('/var/log/popularity-contest')
  89 + or run the following command and upload generated 'packages.list' file.
89 90 </p>
90 91 <p>
91   - <code> # dpkg -l > blih.list </code>
  92 + <code> # dpkg-query --show > packages.list </code>
92 93 </p>
93 94 </div><!-- id="tip-upload" -->
94 95 </fieldset>
... ...
src/web/templates/survey.html
1   -$def with (recommends, pkg_details, form, request)
  1 +$def with (pkg_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
... ... @@ -24,18 +24,23 @@ $var jsfiles: static/coda-slider-2.0/javascripts/jquery-1.3.2.min.js static/coda
24 24  
25 25 <h1>AppRecommender Survey</h1>
26 26  
27   -<form action="/thanks" method="post" enctype="multipart/form-data" name="surveyform">
  27 +<form action="/save" method="post" enctype="multipart/form-data" name="surveyform">
28 28  
  29 +<input type="hidden" name="user_id" value=$request.user_id>
  30 +<input type="hidden" name="strategy" value=$request.strategy>
29 31 <div id="controls-form" style="display: none;"><!-- display show in the end form -->
30   -<a id="finish-button" class="glass">Finish
31   - <div class="tip important" id="tip-bar"><p>Tem certeza que não gostaria de avaliar uma nova estratégia? </p></div>
32   -</a>
33 32  
34   -<a id="bar-button" class="glass">New Recommends
35   - <div class="tip note" id="tip-finish"><p>Fazer uma nova recomendação com uma nova lista de pacotes.</p></div>
  33 +<!--<a id="finish-button" class="glass">Finish
  34 + <div class="tip important" id="tip-bar"><p>Conclude your participation in this survey</p></div>
36 35 </a>
  36 +<a id="bar-button" class="glass" href="http://localhost:8080">Restart
  37 + <div class="tip note" id="tip-finish"><p>Restart the survey with a new packages list.</p></div>
  38 +</a>-->
  39 +
  40 +<input id="restart-button" name="restart_button" type="submit" value="Restart" class="glass" />
  41 +<input id="finish-button" name="finish_button" type="submit" value="Finish" class="glass" />
37 42  
38   -<label for="strategy_button" id="tip-strategy"><div class="tip tip"><p> Gerar um novo resultado com uma estratégia diferente para esta mesma lista de pacotes. </p></div><input id="strategy-button" name="strategy_button" type="submit" value="New Strategy" class="glass" /></label>
  43 +<label for="strategy_button" id="tip-strategy"><div class="tip tip"><p> New round of evaluations for the same list of packages and suggestions produced by a different recommendation strategy. </p></div><input id="strategy-button" name="strategy_button" type="submit" value="New Round" class="glass" /></label>
39 44 </div><!-- id="controls-form" -->
40 45  
41 46 <div class="coda-slider-wrapper">
... ... @@ -44,12 +49,13 @@ $for pkg in pkg_details:
44 49 <div class="panel">
45 50 <div class="panel-wrapper">
46 51 <div id="panel-controls">
47   - <label for="bad-$pkg['package']">Bad</label>
48   - <input class="radio" type="radio" name="radio" value="poor-$pkg['package']" /><br />
49   - <label for="good-$pkg['package']">Good</label>
50   - <input class="radio" type="radio" name="radio" value="good-$pkg['package']" /><br />
51   - <label for="surprise-$pkg['package']">Surprise</label>
52   - <input class="radio" type="radio" name="radio" value="surprise-$pkg['package']" />
  52 + <label for="poor">Poor</label>
  53 + <input class="radio" type="radio" name="evaluation-$pkg_details.index(pkg)" value="poor" /><br />
  54 + <label for="good">Good</label>
  55 + <input class="radio" type="radio" name="evaluation-$pkg_details.index(pkg)" value="good" /><br />
  56 + <label for="surprising">Surprising</label>
  57 + <input class="radio" type="radio"
  58 + name="evaluation-$pkg_details.index(pkg)" value="surprising" />
53 59 </div><!-- #panel-controls -->
54 60 <h1 id="title_pkg">$pkg['package'] <br />
55 61 <span>$pkg['description']</span></h1>
... ... @@ -72,6 +78,17 @@ $for pkg in pkg_details:
72 78 <li><b>Origin</b>: $pkg['origin']</li>
73 79 <li><b>Maintainer</b>: $pkg['maintainer']</li>
74 80 </ul>
  81 + <div id="debresources_box" class="graybox vert-grad">
  82 + <h2>Debian resources:</h2>
  83 + <ul>
  84 + <li><a href="http://packages.debian.org/$pkg['package']">Package page on debian.org</a></li>
  85 + <li><a href="http://bugs.debian.org/$pkg['package']">Debian bug tracking system (BTS)</a></li>
  86 + <li><a href="http://packages.qa.debian.org/$pkg['package']">Debian package tracking system (PTS)</a></li>
  87 + <li><a href="http://qa.debian.org/popcon.php?package=$pkg['package']">Popularity contest statistics (Popcon)</a></li>
  88 + <li><a href="http://patch-tracker.debian.org/package/$pkg['package']">Debian patch tracking system</a></li>
  89 + <li><a href="http://screenshots.debian.net/package/$pkg['package']">Screenshots</a></li>
  90 + </ul>
  91 + </div><!-- id="debresources_box -->
75 92 </div><!-- id="content-pkg" -->
76 93 </div><!-- .panel-wrapper -->
77 94 </div><!-- .panel -->
... ... @@ -80,6 +97,5 @@ $for pkg in pkg_details:
80 97  
81 98 </form>
82 99  
83   -
84 100 </div><!-- class="innertube" -->
85 101 </div><!-- id="maincontent" -->
... ...
src/web/templates/survey_index.html
... ... @@ -3,7 +3,6 @@ $var mod = &#39;index&#39;;
3 3 $var cssfiles: static/css/survey.css
4 4 $var jsfiles:
5 5  
6   -
7 6 <!-- Dynamic form -->
8 7 <script type="application/x-javascript">
9 8 window.onload = function() {
... ... @@ -15,7 +14,8 @@ window.onload = function() {
15 14 <div class="innertube">
16 15  
17 16 <div class="textbox">
18   -<h1>Help us learn your needs</h1>
  17 +<h1>AppRecommender Survey</h1>
  18 +<h2>Help us learn your needs</h2>
19 19  
20 20 <p>Participate in this survey and contribute for the development of
21 21 AppRecommender, a recommender system for GNU/Linux applications.</p>
... ... @@ -26,12 +26,6 @@ You need to analyse at least 10 sugestions to be considered in the survey,
26 26 though we appreciate if you do as many as you can.</p>
27 27 <br />
28 28 <p>Your help is very much appreciated!</p>
29   -<!--
30   -(Caixinha com intruções)
31   -<p> Instructions: if you have popularity-contest package installed, upload your
32   -popcon submission file, usually located at '/var/log/popularity-contest'.
33   -Otherwise run the following command and upload the 'packages_list' file: ``dpkg -l > packages_list''.</p>
34   --->
35 29 </div>
36 30  
37 31 </div><!-- class="innertube" -->
... ...