Commit 8f1cfce9e673bc0d4a4457f9d729b040fb3ddad5

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

Definition of forms as classes; Validation of input form data; New option of

recommendation by packages_list; Templates layout modifications.
src/recommender.py
... ... @@ -49,7 +49,7 @@ class RecommendationResult:
49 49 Return prediction based on recommendation size (number of items).
50 50 """
51 51 sorted_result = sorted(self.item_score.items(), key=itemgetter(1))
52   - return reversed(sorted_result[:size])
  52 + return reversed(sorted_result[-size:])
53 53  
54 54 class Recommender:
55 55 """
... ...
src/strategy.py
... ... @@ -20,6 +20,7 @@ __license__ = """
20 20 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 21 """
22 22  
  23 +import string
23 24 import os, re
24 25 import xapian
25 26 from data import *
... ... @@ -181,7 +182,8 @@ class AxiContentBasedStrategy(RecommendationStrategy):
181 182 Perform recommendation strategy.
182 183 """
183 184 profile = user.axi_tag_profile(rec.items_repository,50)
184   - query = xapian.Query(xapian.Query.OP_OR,profile)
  185 + #profile_str = string.join(list(profile),' ')
  186 + query = xapian.Query(xapian.Query.OP_OR,list(profile))
185 187 enquire = xapian.Enquire(rec.items_repository)
186 188 enquire.set_query(query)
187 189  
... ... @@ -200,13 +202,17 @@ class CollaborativeStrategy(RecommendationStrategy):
200 202 """
201 203 Colaborative recommendation strategy.
202 204 """
  205 + def __init__(self):
  206 + self.description = "Collaborative"
  207 +
203 208 #def run(self,rec,user,similarity_measure):
204 209 def run(self,rec,user):
205 210 """
206 211 Perform recommendation strategy.
207 212 """
208 213 profile = user.maximal_pkg_profile()
209   - query = xapian.Query(xapian.Query.OP_OR,profile)
  214 + #profile_str = string.join(list(profile),' ')
  215 + query = xapian.Query(xapian.Query.OP_OR,list(profile))
210 216 enquire = xapian.Enquire(rec.users_repository)
211 217 enquire.set_query(query)
212 218  
... ... @@ -236,6 +242,9 @@ class KnowledgeBasedStrategy(RecommendationStrategy):
236 242 """
237 243 Knowledge-based recommendation strategy.
238 244 """
  245 + def __init__(self):
  246 + self.description = "Knowledge-based"
  247 +
239 248 def run(self,user,knowledge_repository):
240 249 """
241 250 Perform recommendation strategy.
... ... @@ -247,6 +256,9 @@ class DemographicStrategy(RecommendationStrategy):
247 256 """
248 257 Recommendation strategy based on demographic data.
249 258 """
  259 + def __init__(self):
  260 + self.description = "Demographic"
  261 +
250 262 def run(self,user,items_repository):
251 263 """
252 264 Perform recommendation strategy.
... ...
src/user.py
... ... @@ -123,12 +123,17 @@ class User:
123 123 cache = apt.Cache()
124 124 old_profile_size = len(self.pkg_profile)
125 125 for p in self.pkg_profile[:]: #iterate list copy
126   - pkg = cache[p]
127   - if pkg.candidate:
128   - for dep in pkg.candidate.dependencies:
129   - for or_dep in dep.or_dependencies:
130   - if or_dep.name in self.pkg_profile:
131   - self.pkg_profile.remove(or_dep.name)
  126 + try:
  127 + if cache.has_key(p):
  128 + pkg = cache[p]
  129 + if pkg.candidate:
  130 + for dep in pkg.candidate.dependencies:
  131 + for or_dep in dep.or_dependencies:
  132 + if or_dep.name in self.pkg_profile:
  133 + self.pkg_profile.remove(or_dep.name)
  134 + except:
  135 + logging.debug("Disconsidering package not found in cache: %s"
  136 + % p)
132 137 profile_size = len(self.pkg_profile)
133 138 logging.info("Reduced packages profile size from %d to %d." %
134 139 (old_profile_size, profile_size))
... ... @@ -157,9 +162,14 @@ class LocalSystem(User):
157 162 cache = apt.Cache()
158 163 old_profile_size = len(self.pkg_profile)
159 164 for p in self.pkg_profile[:]: #iterate list copy
160   - pkg = cache[p]
161   - if pkg.is_auto_installed:
162   - self.pkg_profile.remove(p)
  165 + try:
  166 + if cache.has_key(p):
  167 + pkg = cache[p]
  168 + if pkg.is_auto_installed:
  169 + self.pkg_profile.remove(p)
  170 + except:
  171 + logging.debug("Disconsidering package not found in cache: %s"
  172 + % p)
163 173 profile_size = len(self.pkg_profile)
164 174 logging.info("Reduced packages profile size from %d to %d." %
165 175 (old_profile_size, profile_size))
... ...
src/web/server.py
... ... @@ -11,119 +11,117 @@ from config import *
11 11 from recommender import *
12 12 from user import *
13 13  
14   -def add_global_hook():
15   - g = web.storage({"counter": "1"})
16   - def _wrapper(handler):
17   - web.ctx.globals = g
18   - return handler()
19   - return _wrapper
20   -
21   -class Index:
22   - def GET(self):
23   - form_action = "/feedback"
24   - form_method = "post"
25   - form = self._form()
26   - return render.index(form_action, form_method, form)
27   -
28   - def _form(self):
29   - send_form = form.Form(
30   - form.File("pkgs_file", description="Packages list"),
31   - form.Dropdown('limit', [('5', '05'), ('10', '10'), ('20', '20')],
  14 +class RequestForm(form.Form):
  15 + def __init__(self):
  16 + form.Form.__init__(self, \
  17 + form.File("pkgs_file", description="Upload file"),
  18 + form.Textarea("pkgs_list", description="Packages",
  19 + rows="4", cols="40"),
  20 + form.Dropdown('limit', [(5, '05'), (10, '10'), (20, '20')],
32 21 description = "Limit"),
33   - form.Checkbox("strategy_cb", value="True", checked=False,
  22 + form.Checkbox("strategy_cb", value=1, checked=False,
34 23 description="Content-based"),
35   - form.Checkbox("strategy_col", value="True", checked=False,
  24 + form.Checkbox("strategy_col", value=1, checked=False,
36 25 description="Collaborative"),
37 26 form.Checkbox("strategy_hybrid", value="True", checked=False,
38 27 description="Hybrid"),
39 28 form.Checkbox("strategy_hybrid_plus", value="True", checked=False,
40 29 description="Hybrid plus"),
41   - validators = [form.Validator("You must select at least one strategy",
42   - lambda i: i.strategy_cb | i.startegy_col |
43   - i.strategy_hybrid | i.strategy_hybrid_plus)]
44   - )
45   - return send_form()
  30 + validators = [form.Validator("No packages list provided.",
  31 + lambda f: f.has_key("pkgs_list") |
  32 + f.has_key("pkgs_file") ),
  33 + form.Validator("No strategy selected.",
  34 + lambda f: f.has_key("strategy_cb") |
  35 + f.has_key("startegy_col") |
  36 + f.has_key("strategy_hybrid") |
  37 + f.has_key("strategy_hybrid_plus")) ])
  38 +
  39 +class FeedbackForm(form.Form):
  40 + def __init__(self,strategies):
  41 + desc_dict = {"cta": "Content-based", "col": "Collaborative",
  42 + "hybrid": "Hybrib", "hybrid_plus": "Hybrid Plus"}
  43 + fields = []
  44 + for strategy in strategies:
  45 + fields.append(form.Radio(desc_dict[strategy],
  46 + [('1','1 '),('2','2 '),('3','3'),('4','4 '),('5','5')]))
  47 + form.Form.__init__(self, *fields, validators = [])
  48 +
  49 +class Index:
  50 + def GET(self):
  51 + return render.index("/apprec", "post", RequestForm())
  52 +
  53 +class Thanks:
  54 + def POST(self):
  55 + return render.thanks()
46 56  
47   -class FeedbackForm:
  57 +class AppRecommender:
48 58 def POST(self):
49   - action = "/thanks"
50   - method = "post"
51 59 outputdir = tempfile.mkdtemp(prefix='',dir='./submissions/')
52 60 user_id = outputdir.lstrip('./submissions/')
53   - x = web.input(pkgs_file={})
54   - f = open(outputdir + "/packages_list", "wb")
55   - #content = x['pkgs_file'].value
56   - self.pkgs_list = []
57   - for line in x['pkgs_file'].file:
58   - self.pkgs_list.append(line.split()[0])
59   - f.write(line)
60   - # while 1:
61   - # chunk = x['pkgs_file'].file.read(10000)
62   - # if not chunk:
63   - # break
64   - # f.write(chunk)
65   - f.close()
66   -
67   - strategies = []
68   - if 'strategy_cb' in x: strategies.append("cta")
69   - if 'strategy_col' in x: strategies.append("col")
70   - if 'strategy_hybrid' in x: strategies.append("hybrid")
71   - if 'strategy_hybrid+' in x: strategies.append("hybrid+")
72   -
73   - return render.feedbackForm(action, method,
74   - self._recommends(user_id,strategies),
75   - self._form())
76   -
77   - def _recommends(self,user_id,strategies):
78   - user = User(dict.fromkeys(self.pkgs_list,1),user_id)
  61 + request = RequestForm()
  62 + request_info = web.input(pkgs_file={})
  63 + if not request.validates(request_info):
  64 + return render.error(request)
  65 + else:
  66 + user_pkgs_list = []
  67 + if request_info.has_key('pkgs_list'):
  68 + user_pkgs_list = request_info['pkgs_list'].encode('utf8').split()
  69 + print user_pkgs_list
  70 +
  71 + if request_info.has_key('pkgs_file'):
  72 + f = open(outputdir + "/packages_list", "wb")
  73 + for line in request_info['pkgs_file'].file:
  74 + user_pkgs_list.append(line.split()[0])
  75 + f.write(line)
  76 + f.close()
  77 +
  78 + strategies = []
  79 + if request_info.has_key('strategy_cb'): strategies.append("cta")
  80 + ### Colaborative strategies can not go online yet
  81 + if request_info.has_key('strategy_col'): strategies.append("col")
  82 + if request_info.has_key('strategy_hybrid'):
  83 + strategies.append("hybrid")
  84 + if request_info.has_key('strategy_hybrid_plus'):
  85 + strategies.append("hybrid_plus")
  86 +
  87 + return render.apprec("/thanks", "post",
  88 + self._recommends(user_id,user_pkgs_list,
  89 + strategies, int(request_info['limit'])),
  90 + FeedbackForm(strategies))
  91 +
  92 + def _recommends(self,user_id,user_pkgs_list,strategies,limit):
  93 + user = User(dict.fromkeys(user_pkgs_list,1),user_id)
79 94 user.maximal_pkg_profile()
80 95 cfg = Config()
81 96 rec = Recommender(cfg)
82 97 results = dict()
83 98 for strategy in strategies:
84   - eval("rec."+strategy+"(cfg)")
85   - prediction = rec.get_recommendation(user).get_prediction()
86   - results[rec.strategy.description] = [result[0] for result in prediction]
87   - # Colaborative strategies can not go online yet
88   - results['Hybrid+'] = []
89   - results['Hybrid'] = []
90   - results['Collaborative'] = []
  99 + ### Colaborative strategies can not go online yet
  100 + #eval("rec."+strategy+"(cfg)")
  101 + rec.cta(cfg)
  102 + prediction = rec.get_recommendation(user).get_prediction(limit)
  103 + results[rec.strategy.description] = \
  104 + [result[0] for result in prediction]
91 105 return results
92 106  
93   - def _form(self):
94   - send_form = form.Form(
95   - form.Radio('Content-based',
96   - [('1','1 '),('2','2 '),('3','3 '),('4','4 '),('5','5')]),
97   - form.Radio('Collaborative',
98   - [('1','1 '),('2','2 '),('3','3 '),('4','4 '),('5','5')]),
99   - form.Radio('Hybrid',
100   - [('1','1 '),('2','2 '),('3','3 '),('4','4 '),('5','5')]),
101   - form.Radio('Hybrid+',
102   - [('1','1 '),('2','2 '),('3','3 '),('4','4 '),('5','5')]),
103   - form.Dropdown('expertise',
104   - ["Newbie", "Intermediate", "Advanced", "Guru", "Chuck Norris"],
105   - description ='Debian expertise'),
106   - form.Textarea('comments', rows="7", cols="60",
107   - description="Anything else to share?"),
108   -
109   - )
110   - return send_form
111   -
112   -class FeedbackThanks:
113   - def POST(self):
114   - return render.feedbackThanks()
  107 +def add_global_hook():
  108 + g = web.storage({"counter": "1"})
  109 + def _wrapper(handler):
  110 + web.ctx.globals = g
  111 + return handler()
  112 + return _wrapper
115 113  
116 114 render = web.template.render('templates/', base='layout')
117 115  
118 116 urls = ('/', 'Index',
119   - '/feedback', 'FeedbackForm',
120   - '/thanks', 'FeedbackThanks'
  117 + '/apprec', 'AppRecommender',
  118 + '/thanks', 'Thanks'
121 119 )
122 120  
123 121 web.webapi.internalerror = web.debugerror
124 122  
125 123 if __name__ == "__main__":
126   - app = web.application(urls, globals())
127   - app.add_processor(add_global_hook())
128   - app.run()
  124 + apprec = web.application(urls, globals())
  125 + apprec.add_processor(add_global_hook())
  126 + apprec.run()
129 127  
... ...
src/web/templates/apprec.html 0 → 100644
... ... @@ -0,0 +1,48 @@
  1 +$def with (action, method, recommends, form)
  2 +$var title: Feedback
  3 +$var mod = 'feedback';
  4 +
  5 + <div class="index_include">
  6 +
  7 +
  8 +<center>
  9 + <h1>Recommendations</h1>
  10 +</center>
  11 +
  12 +<p>Results per strategy:</p>
  13 +
  14 +<ul class="toc">
  15 +$for strategy, result in recommends.items():
  16 + <li><a href="#$strategy">$strategy</a></li>
  17 +<li><a href="#feedback">Your feedback is appreciated!</a></li>
  18 +</ul>
  19 +
  20 +<form action="$action" method="$method">
  21 +$for strategy, result in recommends.items():
  22 + <h2><a name="$strategy" id="$strategy">$strategy</a></h2>
  23 + $for pkg in result:
  24 + <div class="line">
  25 + <div class="item col50">
  26 + <image src="http://screenshots.debian.net/screenshot/$pkg" width="300">
  27 + </div>
  28 + <div class="item col50 lastcol">
  29 + <script>loadPackage("$pkg");</script>
  30 + <b id="pack-$pkg"></b><div id="desc-$pkg"> </div>
  31 + <ul>
  32 + <li id="maint-$pkg"></li>
  33 + <li id="homepage-$pkg"></li>
  34 + </ul>
  35 + </div>
  36 + <div class="clear"></div>
  37 + </div>
  38 + <hr />
  39 +
  40 +<h2><a name="feedback" id="feedback">Feedback</a></h2>
  41 +
  42 +$:form.render()
  43 +<input type="submit" />
  44 +</form>
  45 +
  46 +
  47 +</div>
  48 +
... ...
src/web/templates/error.html 0 → 100644
... ... @@ -0,0 +1,23 @@
  1 +$def with (form)
  2 +$var title: Error
  3 +$var mod = 'error';
  4 +
  5 +<div class="index_include">
  6 +<center>
  7 + <h1>Welcome to AppRecommender</h1>
  8 +</center>
  9 +
  10 +<div class="align-right"><img alt="AppRecommender logo" src="/static/Pics/AppRecommender-logo.jpg" /></div>
  11 +
  12 +Your request could not be proccessed due to the following error(s):
  13 +
  14 +<ul>
  15 +$for v in form.validators:
  16 + <b><li>$v.msg</li></b>
  17 +</ul>
  18 +
  19 +<p><a href="/">Go back</a> and try again. </p>
  20 +<p>If you believe it is a bug, please report to <a
  21 +href="mailto:tassia@gamil.com">tassia@gmail.com</a>.</p>
  22 +
  23 +</div>
... ...
src/web/templates/feedbackForm.html
... ... @@ -1,50 +0,0 @@
1   -$def with (action, method, recommends, form)
2   -$var title: Feedback
3   -$var mod = 'feedback';
4   -
5   - <div class="index_include">
6   -
7   -
8   -<center>
9   - <h1>Recommendations</h1>
10   -</center>
11   -
12   -<p>Results per strategy:</p>
13   -
14   -<ul class="toc">
15   -$for strategy, result in recommends.items():
16   - <li><a href="#$strategy">$strategy</a></li>
17   -<li><a href="#feedback">Your feedback is appreciated!</a></li>
18   -</ul>
19   -
20   -<form action="$action" method="$method">
21   -$for strategy, result in recommends.items():
22   - <h2><a name="$strategy" id="$strategy">$strategy</a></h2>
23   - $for pkg in result:
24   - <div class="line">
25   - <div class="item col50">
26   - <image src="http://screenshots.debian.net/screenshot/$pkg" width="300">
27   - </div>
28   - <div class="item col50 lastcol">
29   - <script>loadPackage("$pkg");</script>
30   - <b id="pack-$pkg"></b><div id="desc-$pkg"> </div>
31   - <ul>
32   - <li id="maint-$pkg"></li>
33   - <li id="homepage-$pkg"></li>
34   - </ul>
35   - </div>
36   - <div class="clear"></div>
37   - </div>
38   - <hr />
39   -
40   -<h2><a name="feedback" id="feedback">Feedback</a></h2>
41   -
42   -$if not form.valid: <p>Try again, AmeriCAN:</p>
43   -$:form.render()
44   -<br />
45   -<input type="submit" />
46   -</form>
47   -
48   -
49   -</div>
50   -
src/web/templates/feedbackThanks.html
... ... @@ -1,9 +0,0 @@
1   -$var title: Feedback
2   -$var mod = 'thanks';
3   -
4   - <div class="index_include">
5   -<center>
6   - <h1>Thanks!</h1>
7   -</center>
8   -
9   -</div>
src/web/templates/index.html
... ... @@ -16,9 +16,7 @@ providing platform independent solutions, it should also follow this
16 16 principle.</p>
17 17  
18 18 <form action="$action" enctype="multipart/form-data" method="$method">
19   -$if not form.valid: <p>Try again, AmeriCAN:</p>
20 19 $:form.render()
21   -<p>&nbsp;</p>
22 20 <input type="submit" />
23 21 </form>
24 22  
... ...
src/web/templates/layout.html
... ... @@ -40,7 +40,7 @@ function loadPackage(packagename)
40 40 <div id="logo">
41 41 <a href="http://www.debian.org/" title="Debian Home"><img src="/static/Pics/openlogo-50.png" alt="Debian" width="50" height="61" /></a>
42 42 </div>
43   - <p class="section">Recommender</p>
  43 + <p class="section">APP_REC</p>
44 44  
45 45 </div>
46 46  
... ... @@ -48,10 +48,13 @@ function loadPackage(packagename)
48 48  
49 49 <p class="hidecss"><a href="#inner">Skip Quicknav</a></p>
50 50 <ul>
51   - <li><a href="http://www.debian.org/intro/about">About Debian</a></li>
52   - <li><a href="http://www.debian.org/distrib/">Getting Debian</a></li>
53   - <li><a href="http://www.debian.org/support">Support</a></li>
54   - <li><a href="http://www.debian.org/devel/">Developers'&nbsp;Corner</a></li>
  51 + <li><a href="/">Home</a></li>
  52 + <li>
  53 + <a href="http://www.ime.usp.br/~tassia/apprec.html">About</a>
  54 + </li>
  55 + <li>
  56 + <a href="http://github.com/tassia/AppRecommender">Devel</a>
  57 + </li>
55 58  
56 59 </ul>
57 60 </div>
... ... @@ -69,11 +72,9 @@ $:content
69 72 <div id="footer">
70 73 <div id="pageinfo">
71 74  
72   -<p>Back to the <a href="http://www.debian.org/../">Debian Project homepage</a>.</p>
73   -<hr/>
74 75 <div id="footermap">
75 76 <!--UdmComment-->
76   -<p><strong><a href="http://www.debian.org">Home</a></strong></p>
  77 +<p><strong><a href="http://www.debian.org">Debian Project homepage</a></strong></p>
77 78 <ul id="footermap-cola">
78 79 <li><a href="http://www.debian.org/intro/about">About</a>
79 80 <ul>
... ... @@ -141,11 +142,13 @@ $:content
141 142 </ul>
142 143 <!--/UdmComment-->
143 144 </div> <!-- end footermap -->
  145 +
  146 +<hr />
144 147 <div id="fineprint">
145 148 <p>To report a problem with the web site, e-mail <a
146 149 href="mailto:tassia@gmail.com">tassia@gmail.com</a>.</p>
147 150 <p>
148   -Last Modified: <span class="date">Mon 09 May 2011 04:08:40 AM UTC</span>
  151 +Last Modified: <span class="date">Mon 24 June 2011 21:00:40 UTC</span>
149 152 <br />
150 153 Copyright &copy; 2011
151 154 <a href="$url_base">AppRecommender</a>.<br />
... ...
src/web/templates/thanks.html 0 → 100644
... ... @@ -0,0 +1,9 @@
  1 +$var title: Feedback
  2 +$var mod = 'thanks';
  3 +
  4 + <div class="index_include">
  5 +<center>
  6 + <h1>Thanks!</h1>
  7 +</center>
  8 +
  9 +</div>
... ...