[kupfer] Alternative ranking for Actions



commit ebe59610c2cbdd15fcfda1af9aa1f31daed6b7a9
Author: Ulrik Sverdrup <ulrik sverdrup gmail com>
Date:   Wed Jan 13 15:46:22 2010 +0100

    Alternative ranking for Actions
    
    This adjusts the rank for actions, *without query* (no search text),
    to be more rigid. Basically, we honor all rank_adjust actions, so
    default actions are almost always on top, and negatively adjusted
    actions are always at the bottom.
    
    This is the only way we can get sane and predictable results right
    now, what is needed for the future is:
    
     * Object-specific action memory
     * Action configuration: which actions to use, which rank to give them
    
    With a search query in the action pane, it behaves exactly as before,
    with the old ranking mechanism.

 kupfer/core/data.py   |   48 ++++++++++++++++++++++++++++++++++--------------
 kupfer/core/search.py |   16 ++++++++++++++++
 2 files changed, 50 insertions(+), 14 deletions(-)
---
diff --git a/kupfer/core/data.py b/kupfer/core/data.py
index 5af1bca..0bfef35 100644
--- a/kupfer/core/data.py
+++ b/kupfer/core/data.py
@@ -5,7 +5,7 @@ import os
 import gobject
 
 from kupfer.obj import base, sources, compose
-from kupfer import pretty, scheduler, task
+from kupfer import pretty, scheduler
 from kupfer import commandexec
 from kupfer import datatools
 from kupfer.core import search, learn
@@ -31,6 +31,17 @@ def dress_leaves(seq, action):
 		sc.decorate_object(itm.object, action=action)
 		yield itm
 
+def peekfirst(seq):
+	"""This function will return (firstitem, iter)
+	where firstitem is the first item of @seq or None if empty,
+	and iter an equivalent copy of @seq
+	"""
+	seq = iter(seq)
+	for itm in seq:
+		old_iter = itertools.chain((itm, ), seq)
+		return (itm, old_iter)
+	return (None, seq)
+
 class Searcher (object):
 	"""
 	This class searches KupferObjects efficiently, and
@@ -115,23 +126,33 @@ class Searcher (object):
 				if (not hasattr(obj, "is_valid")) or obj.is_valid():
 					yield itm
 
-		def peekfirst(seq):
-			"""This function will return (firstitem, iter)
-			where firstitem is the first item of @seq or None if empty,
-			and iter an equivalent copy of @seq
-			"""
-			seq = iter(seq)
-			for itm in seq:
-				old_iter = itertools.chain((itm, ), seq)
-				return (itm, old_iter)
-			return (None, seq)
-
 		# Check if the items are valid as the search
 		# results are accessed through the iterators
 		unique_matches = as_set_iter(matches)
 		match, match_iter = peekfirst(decorator(valid_check(unique_matches)))
 		return match, match_iter
 
+	def rank_actions(self, objects, key, item_check=None, decorator=None):
+		"""
+		rank @objects, which should be a sequence of KupferObjects,
+		for @key, with the action ranker algorithm.
+
+		Filters and return value like .score().
+		"""
+		if not item_check: item_check = identity
+		if not decorator: decorator = identity
+
+		rankables = search.make_rankables(item_check(objects))
+		if key:
+			rankables = search.score_objects(rankables, key)
+			matches = search.bonus_objects(rankables, key)
+		else:
+			matches = search.score_actions(rankables)
+		matches = sorted(matches, key=operator.attrgetter("rank"), reverse=True)
+
+		match, match_iter = peekfirst(decorator(matches))
+		return match, match_iter
+
 class Pane (gobject.GObject):
 	"""
 	signals:
@@ -306,8 +327,7 @@ class PrimaryActionPane (Pane):
 				if is_valid_cached(obj.object):
 					yield obj
 
-		sources = (actions, )
-		match, match_iter = self.searcher.search(sources, key,
+		match, match_iter = self.searcher.rank_actions(actions, key,
 				decorator=valid_decorator)
 		self.emit_search_result(match, match_iter, context)
 
diff --git a/kupfer/core/search.py b/kupfer/core/search.py
index 1a93fcd..2c5d4a3 100644
--- a/kupfer/core/search.py
+++ b/kupfer/core/search.py
@@ -74,3 +74,19 @@ def score_objects(rankables, key):
 			rb.rank = rank
 			yield rb
 
+
+def score_actions(rankables):
+	"""Alternative (rigid) scoring mechanism for objects,
+	putting much more weight in rank_adjust
+	"""
+	get_record_score = learn.get_record_score
+	for obj in rankables:
+		ra = obj.object.rank_adjust
+		if ra > 0:
+			obj.rank = 50 + ra + get_record_score(obj.object)/2
+		elif ra == 0:
+			obj.rank = get_record_score(obj.object)
+		else:
+			obj.rank = -50 + ra + get_record_score(obj.object)
+		yield obj
+



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]