diff --git a/src/recommender.py b/src/recommender.py index 8e11bdd..48a42c7 100644 --- a/src/recommender.py +++ b/src/recommender.py @@ -49,7 +49,7 @@ class RecommendationResult: Return prediction based on recommendation size (number of items). """ sorted_result = sorted(self.item_score.items(), key=itemgetter(1)) - return reversed(sorted_result[:size]) + return reversed(sorted_result[-size:]) class Recommender: """ diff --git a/src/strategy.py b/src/strategy.py index 2171e75..18c6e38 100644 --- a/src/strategy.py +++ b/src/strategy.py @@ -20,6 +20,7 @@ __license__ = """ along with this program. If not, see . """ +import string import os, re import xapian from data import * @@ -181,7 +182,8 @@ class AxiContentBasedStrategy(RecommendationStrategy): Perform recommendation strategy. """ profile = user.axi_tag_profile(rec.items_repository,50) - query = xapian.Query(xapian.Query.OP_OR,profile) + #profile_str = string.join(list(profile),' ') + query = xapian.Query(xapian.Query.OP_OR,list(profile)) enquire = xapian.Enquire(rec.items_repository) enquire.set_query(query) @@ -200,13 +202,17 @@ class CollaborativeStrategy(RecommendationStrategy): """ Colaborative recommendation strategy. """ + def __init__(self): + self.description = "Collaborative" + #def run(self,rec,user,similarity_measure): def run(self,rec,user): """ Perform recommendation strategy. """ profile = user.maximal_pkg_profile() - query = xapian.Query(xapian.Query.OP_OR,profile) + #profile_str = string.join(list(profile),' ') + query = xapian.Query(xapian.Query.OP_OR,list(profile)) enquire = xapian.Enquire(rec.users_repository) enquire.set_query(query) @@ -236,6 +242,9 @@ class KnowledgeBasedStrategy(RecommendationStrategy): """ Knowledge-based recommendation strategy. """ + def __init__(self): + self.description = "Knowledge-based" + def run(self,user,knowledge_repository): """ Perform recommendation strategy. @@ -247,6 +256,9 @@ class DemographicStrategy(RecommendationStrategy): """ Recommendation strategy based on demographic data. """ + def __init__(self): + self.description = "Demographic" + def run(self,user,items_repository): """ Perform recommendation strategy. diff --git a/src/user.py b/src/user.py index a25bbb2..40ce349 100644 --- a/src/user.py +++ b/src/user.py @@ -123,12 +123,17 @@ class User: cache = apt.Cache() old_profile_size = len(self.pkg_profile) for p in self.pkg_profile[:]: #iterate list copy - pkg = cache[p] - if pkg.candidate: - for dep in pkg.candidate.dependencies: - for or_dep in dep.or_dependencies: - if or_dep.name in self.pkg_profile: - self.pkg_profile.remove(or_dep.name) + try: + if cache.has_key(p): + pkg = cache[p] + if pkg.candidate: + for dep in pkg.candidate.dependencies: + for or_dep in dep.or_dependencies: + if or_dep.name in self.pkg_profile: + self.pkg_profile.remove(or_dep.name) + except: + logging.debug("Disconsidering package not found in cache: %s" + % p) profile_size = len(self.pkg_profile) logging.info("Reduced packages profile size from %d to %d." % (old_profile_size, profile_size)) @@ -157,9 +162,14 @@ class LocalSystem(User): cache = apt.Cache() old_profile_size = len(self.pkg_profile) for p in self.pkg_profile[:]: #iterate list copy - pkg = cache[p] - if pkg.is_auto_installed: - self.pkg_profile.remove(p) + try: + if cache.has_key(p): + pkg = cache[p] + if pkg.is_auto_installed: + self.pkg_profile.remove(p) + except: + logging.debug("Disconsidering package not found in cache: %s" + % p) profile_size = len(self.pkg_profile) logging.info("Reduced packages profile size from %d to %d." % (old_profile_size, profile_size)) diff --git a/src/web/server.py b/src/web/server.py index 3103f78..2bad012 100755 --- a/src/web/server.py +++ b/src/web/server.py @@ -11,119 +11,117 @@ from config import * from recommender import * from user import * -def add_global_hook(): - g = web.storage({"counter": "1"}) - def _wrapper(handler): - web.ctx.globals = g - return handler() - return _wrapper - -class Index: - def GET(self): - form_action = "/feedback" - form_method = "post" - form = self._form() - return render.index(form_action, form_method, form) - - def _form(self): - send_form = form.Form( - form.File("pkgs_file", description="Packages list"), - form.Dropdown('limit', [('5', '05'), ('10', '10'), ('20', '20')], +class RequestForm(form.Form): + def __init__(self): + form.Form.__init__(self, \ + form.File("pkgs_file", description="Upload file"), + form.Textarea("pkgs_list", description="Packages", + rows="4", cols="40"), + form.Dropdown('limit', [(5, '05'), (10, '10'), (20, '20')], description = "Limit"), - form.Checkbox("strategy_cb", value="True", checked=False, + form.Checkbox("strategy_cb", value=1, checked=False, description="Content-based"), - form.Checkbox("strategy_col", value="True", checked=False, + form.Checkbox("strategy_col", value=1, checked=False, description="Collaborative"), form.Checkbox("strategy_hybrid", value="True", checked=False, description="Hybrid"), form.Checkbox("strategy_hybrid_plus", value="True", checked=False, description="Hybrid plus"), - validators = [form.Validator("You must select at least one strategy", - lambda i: i.strategy_cb | i.startegy_col | - i.strategy_hybrid | i.strategy_hybrid_plus)] - ) - return send_form() + validators = [form.Validator("No packages list provided.", + lambda f: f.has_key("pkgs_list") | + f.has_key("pkgs_file") ), + form.Validator("No strategy selected.", + lambda f: f.has_key("strategy_cb") | + f.has_key("startegy_col") | + f.has_key("strategy_hybrid") | + f.has_key("strategy_hybrid_plus")) ]) + +class FeedbackForm(form.Form): + def __init__(self,strategies): + desc_dict = {"cta": "Content-based", "col": "Collaborative", + "hybrid": "Hybrib", "hybrid_plus": "Hybrid Plus"} + fields = [] + for strategy in strategies: + fields.append(form.Radio(desc_dict[strategy], + [('1','1 '),('2','2 '),('3','3'),('4','4 '),('5','5')])) + form.Form.__init__(self, *fields, validators = []) + +class Index: + def GET(self): + return render.index("/apprec", "post", RequestForm()) + +class Thanks: + def POST(self): + return render.thanks() -class FeedbackForm: +class AppRecommender: def POST(self): - action = "/thanks" - method = "post" outputdir = tempfile.mkdtemp(prefix='',dir='./submissions/') user_id = outputdir.lstrip('./submissions/') - x = web.input(pkgs_file={}) - f = open(outputdir + "/packages_list", "wb") - #content = x['pkgs_file'].value - self.pkgs_list = [] - for line in x['pkgs_file'].file: - self.pkgs_list.append(line.split()[0]) - f.write(line) - # while 1: - # chunk = x['pkgs_file'].file.read(10000) - # if not chunk: - # break - # f.write(chunk) - f.close() - - strategies = [] - if 'strategy_cb' in x: strategies.append("cta") - if 'strategy_col' in x: strategies.append("col") - if 'strategy_hybrid' in x: strategies.append("hybrid") - if 'strategy_hybrid+' in x: strategies.append("hybrid+") - - return render.feedbackForm(action, method, - self._recommends(user_id,strategies), - self._form()) - - def _recommends(self,user_id,strategies): - user = User(dict.fromkeys(self.pkgs_list,1),user_id) + request = RequestForm() + request_info = web.input(pkgs_file={}) + if not request.validates(request_info): + return render.error(request) + else: + user_pkgs_list = [] + if request_info.has_key('pkgs_list'): + user_pkgs_list = request_info['pkgs_list'].encode('utf8').split() + print user_pkgs_list + + if request_info.has_key('pkgs_file'): + f = open(outputdir + "/packages_list", "wb") + for line in request_info['pkgs_file'].file: + user_pkgs_list.append(line.split()[0]) + f.write(line) + f.close() + + strategies = [] + if request_info.has_key('strategy_cb'): strategies.append("cta") + ### Colaborative strategies can not go online yet + if request_info.has_key('strategy_col'): strategies.append("col") + if request_info.has_key('strategy_hybrid'): + strategies.append("hybrid") + if request_info.has_key('strategy_hybrid_plus'): + strategies.append("hybrid_plus") + + return render.apprec("/thanks", "post", + self._recommends(user_id,user_pkgs_list, + strategies, int(request_info['limit'])), + FeedbackForm(strategies)) + + def _recommends(self,user_id,user_pkgs_list,strategies,limit): + user = User(dict.fromkeys(user_pkgs_list,1),user_id) user.maximal_pkg_profile() cfg = Config() rec = Recommender(cfg) results = dict() for strategy in strategies: - eval("rec."+strategy+"(cfg)") - prediction = rec.get_recommendation(user).get_prediction() - results[rec.strategy.description] = [result[0] for result in prediction] - # Colaborative strategies can not go online yet - results['Hybrid+'] = [] - results['Hybrid'] = [] - results['Collaborative'] = [] + ### Colaborative strategies can not go online yet + #eval("rec."+strategy+"(cfg)") + rec.cta(cfg) + prediction = rec.get_recommendation(user).get_prediction(limit) + results[rec.strategy.description] = \ + [result[0] for result in prediction] return results - def _form(self): - send_form = form.Form( - form.Radio('Content-based', - [('1','1 '),('2','2 '),('3','3 '),('4','4 '),('5','5')]), - form.Radio('Collaborative', - [('1','1 '),('2','2 '),('3','3 '),('4','4 '),('5','5')]), - form.Radio('Hybrid', - [('1','1 '),('2','2 '),('3','3 '),('4','4 '),('5','5')]), - form.Radio('Hybrid+', - [('1','1 '),('2','2 '),('3','3 '),('4','4 '),('5','5')]), - form.Dropdown('expertise', - ["Newbie", "Intermediate", "Advanced", "Guru", "Chuck Norris"], - description ='Debian expertise'), - form.Textarea('comments', rows="7", cols="60", - description="Anything else to share?"), - - ) - return send_form - -class FeedbackThanks: - def POST(self): - return render.feedbackThanks() +def add_global_hook(): + g = web.storage({"counter": "1"}) + def _wrapper(handler): + web.ctx.globals = g + return handler() + return _wrapper render = web.template.render('templates/', base='layout') urls = ('/', 'Index', - '/feedback', 'FeedbackForm', - '/thanks', 'FeedbackThanks' + '/apprec', 'AppRecommender', + '/thanks', 'Thanks' ) web.webapi.internalerror = web.debugerror if __name__ == "__main__": - app = web.application(urls, globals()) - app.add_processor(add_global_hook()) - app.run() + apprec = web.application(urls, globals()) + apprec.add_processor(add_global_hook()) + apprec.run() diff --git a/src/web/templates/apprec.html b/src/web/templates/apprec.html new file mode 100644 index 0000000..54cc63e --- /dev/null +++ b/src/web/templates/apprec.html @@ -0,0 +1,48 @@ +$def with (action, method, recommends, form) +$var title: Feedback +$var mod = 'feedback'; + +
+ + +
+

Recommendations

+
+ +

Results per strategy:

+ + + +
+$for strategy, result in recommends.items(): +

$strategy

+ $for pkg in result: +
+
+ +
+
+ +
+
    +
  • +
  • +
+
+
+
+
+ +

Feedback

+ +$:form.render() + +
+ + +
+ diff --git a/src/web/templates/error.html b/src/web/templates/error.html new file mode 100644 index 0000000..37e1e1c --- /dev/null +++ b/src/web/templates/error.html @@ -0,0 +1,23 @@ +$def with (form) +$var title: Error +$var mod = 'error'; + +
+
+

Welcome to AppRecommender

+
+ +
AppRecommender logo
+ +Your request could not be proccessed due to the following error(s): + + + +

Go back and try again.

+

If you believe it is a bug, please report to tassia@gmail.com.

+ +
diff --git a/src/web/templates/feedbackForm.html b/src/web/templates/feedbackForm.html deleted file mode 100644 index 42149b0..0000000 --- a/src/web/templates/feedbackForm.html +++ /dev/null @@ -1,50 +0,0 @@ -$def with (action, method, recommends, form) -$var title: Feedback -$var mod = 'feedback'; - -
- - -
-

Recommendations

-
- -

Results per strategy:

- - - -
-$for strategy, result in recommends.items(): -

$strategy

- $for pkg in result: -
-
- -
-
- -
-
    -
  • -
  • -
-
-
-
-
- -

Feedback

- -$if not form.valid:

Try again, AmeriCAN:

-$:form.render() -
- -
- - -
- diff --git a/src/web/templates/feedbackThanks.html b/src/web/templates/feedbackThanks.html deleted file mode 100644 index c268c39..0000000 --- a/src/web/templates/feedbackThanks.html +++ /dev/null @@ -1,9 +0,0 @@ -$var title: Feedback -$var mod = 'thanks'; - -
-
-

Thanks!

-
- -
diff --git a/src/web/templates/index.html b/src/web/templates/index.html index 466f27e..d6502d2 100644 --- a/src/web/templates/index.html +++ b/src/web/templates/index.html @@ -16,9 +16,7 @@ providing platform independent solutions, it should also follow this principle.

-$if not form.valid:

Try again, AmeriCAN:

$:form.render() -

 

diff --git a/src/web/templates/layout.html b/src/web/templates/layout.html index a6e1f46..3f9f261 100644 --- a/src/web/templates/layout.html +++ b/src/web/templates/layout.html @@ -40,7 +40,7 @@ function loadPackage(packagename) -

Recommender

+

APP_REC

@@ -48,10 +48,13 @@ function loadPackage(packagename)

Skip Quicknav

@@ -69,11 +72,9 @@ $:content