aboutsummaryrefslogtreecommitdiffstats
path: root/background_scripts/completion.coffee
diff options
context:
space:
mode:
Diffstat (limited to 'background_scripts/completion.coffee')
-rw-r--r--background_scripts/completion.coffee57
1 files changed, 36 insertions, 21 deletions
diff --git a/background_scripts/completion.coffee b/background_scripts/completion.coffee
index 77332967..5fc98b88 100644
--- a/background_scripts/completion.coffee
+++ b/background_scripts/completion.coffee
@@ -130,7 +130,8 @@ class Suggestion
# Simplify a suggestion's URL (by removing those parts which aren't useful for display or comparison).
shortenUrl: () ->
return @shortUrl if @shortUrl?
- url = @url
+ # We get easier-to-read shortened URLs if we URI-decode them.
+ url = (Utils.decodeURIByParts(@url) || @url).toLowerCase()
for [ filter, replacements ] in @stripPatterns
if new RegExp(filter).test url
for replace in replacements
@@ -149,12 +150,19 @@ class Suggestion
# Google search specific replacements; this replaces query parameters which are known to not be helpful.
# There's some additional information here: http://www.teknoids.net/content/google-search-parameters-2012
[ "^https?://www\.google\.(com|ca|com\.au|co\.uk|ie)/.*[&?]q="
- "ei gws_rd url ved usg sa usg sig2 bih biw cd".split(/\s+/).map (param) -> new RegExp "\&#{param}=[^&]+" ]
+ "ei gws_rd url ved usg sa usg sig2 bih biw cd aqs ie sourceid es_sm"
+ .split(/\s+/).map (param) -> new RegExp "\&#{param}=[^&]+" ]
# General replacements; replaces leading and trailing fluff.
[ '.', [ "^https?://", "\\W+$" ].map (re) -> new RegExp re ]
]
+ # Boost a relevancy score by a factor (in the range (0,1.0)), while keeping the score in the range [0,1].
+ # This makes greater adjustments to scores near the middle of the range (so, very poor relevancy scores
+ # remain very poor).
+ @boostRelevancyScore: (factor, score) ->
+ score + if score < 0.5 then score * factor else (1.0 - score) * factor
+
class BookmarkCompleter
folderSeparator: "/"
currentSearch: null
@@ -454,18 +462,9 @@ class SearchEngineCompleter
factor = Math.max 0.0, Math.min 1.0, Settings.get "omniSearchWeight"
haveCompletionEngine = (0.0 < factor or custom) and CompletionSearch.haveCompletionEngine searchUrl
- # Relevancy:
- # - Relevancy does not depend upon the actual suggestion (so, it does not depend upon word
- # relevancy, say). We assume that the completion engine has already factored that in. Also,
- # completion engines sometimes handle spelling mistakes, in which case we wouldn't find the query
- # terms in the suggestion anyway.
- # - Scores are weighted such that they retain the order provided by the completion engine.
- # - The relavancy is higher if the query term is longer. The idea is that search suggestions are more
- # likely to be relevant if, after typing some number of characters, the user hasn't yet found
- # a useful suggestion from another completer.
- #
- characterCount = query.length - queryTerms.length + 1
- relevancy = (if custom then 0.5 else factor) * 12.0 / Math.max 12.0, characterCount
+ # We weight the relevancy factor by the length of the query (exponentially). The idea is that, the
+ # more the user has typed, the less likely it is that another completer has proven fruitful.
+ factor *= 1 - Math.pow 0.8, query.length
# This filter is applied to all of the suggestions from all of the completers, after they have been
# aggregated by the MultiCompleter.
@@ -493,16 +492,19 @@ class SearchEngineCompleter
highlightTerms: not haveCompletionEngine
isSearchSuggestion: true
- mkSuggestion = (suggestion) ->
+ mkSuggestion = (suggestion) =>
new Suggestion
queryTerms: queryTerms
type: description
url: Utils.createSearchUrl suggestion, searchUrl
title: suggestion
- relevancy: relevancy *= 0.9
insertText: suggestion
highlightTerms: false
- isSearchSuggestion: true
+ isCustomSearch: custom
+ relevancyFunction: @computeRelevancy
+ # We reduce the relevancy factor as suggestions are added. This respects, to some extent, the
+ # order provided by the completion engine.
+ relevancyData: factor *= 0.95
cachedSuggestions =
if haveCompletionEngine then CompletionSearch.complete searchUrl, queryTerms else null
@@ -521,11 +523,16 @@ class SearchEngineCompleter
onComplete suggestions,
filter: filter
continuation: (suggestions, onComplete) =>
- # Fetch completion suggestions from suggestion engines.
- # We can skip this if any new suggestions we propose cannot score highly enough to make the list
- # anyway.
- if 10 <= suggestions.length and relevancy < suggestions[suggestions.length-1].relevancy
+ # We can skip querying the completion engine if any new suggestions we propose will not score highly
+ # enough to make the list anyway. We construct a suggestion which perfectly matches the query, and
+ # ask the relevancy function what score it would get. If that score is less than the score of the
+ # lowest-ranked suggestion from another completer (and there are already 10 suggestions), then
+ # there's no need to query the completion engine.
+ perfectRelevancyScore = @computeRelevancy new Suggestion
+ queryTerms: queryTerms, title: queryTerms.join(" "), relevancyData: factor
+
+ if 10 <= suggestions.length and perfectRelevancyScore < suggestions[suggestions.length-1].relevancy
console.log "skip (cannot make the grade):", suggestions.length, query if SearchEngineCompleter.debug
return onComplete []
@@ -533,6 +540,14 @@ class SearchEngineCompleter
console.log "fetched suggestions:", suggestions.length, query if SearchEngineCompleter.debug
onComplete suggestions.map mkSuggestion
+ computeRelevancy: ({ relevancyData, queryTerms, title }) ->
+ # Tweaks:
+ # - Calibration: we boost relevancy scores to try to achieve an appropriate balance between relevancy
+ # scores here, and those provided by other completers.
+ # - Relevancy depends only on the title (which is the search terms), and not on the URL.
+ Suggestion.boostRelevancyScore 0.5,
+ relevancyData * RankingUtils.wordRelevancy queryTerms, title, title
+
postProcessSuggestions: (request, suggestions) ->
return unless request.searchEngines
engines = (engine for _, engine of request.searchEngines)