From ed96cf0c71d9373cb3a1f7aae62b16d5362d71d2 Mon Sep 17 00:00:00 2001 From: Andrew Miner Date: Sat, 28 Jan 2017 19:59:18 -0800 Subject: [PATCH] Update SAYT algo to give better matches The algorithm will now give higher rankings to items containing multiple sequential letters which match, and higher rankings to those whose length more closely matches the given term. --- src/client/models/site/item_selector.coffee | 40 ++++++++++++++------- 1 file changed, 27 insertions(+), 13 deletions(-) diff --git a/src/client/models/site/item_selector.coffee b/src/client/models/site/item_selector.coffee index ae6ec3071..0911dd72d 100644 --- a/src/client/models/site/item_selector.coffee +++ b/src/client/models/site/item_selector.coffee @@ -47,25 +47,36 @@ module.exports = class ItemSelector extends BaseModel # Private Methods ############################################################################## - _isMatch: (name, itemSlug)-> + _computeScore: (name, itemSlug)-> hintIndex = 0 hintLetter = @_hint[hintIndex] name = name.toLowerCase() + nextScore = 1 + totalScore = 0 for nameIndex in [0...name.length] by 1 if name.charAt(nameIndex) is hintLetter + totalScore += nextScore + nextScore += 1 hintIndex += 1 if hintIndex is @_hint.length item = @_modPack.findItem itemSlug - return false unless item? - return @_isAcceptable item - hintLetter = @_hint[hintIndex] + return 0 unless item? + return 0 unless @_isAcceptable item + break - return false + hintLetter = @_hint[hintIndex] + else + nextScore = 1 + + return 0 if hintIndex < @_hint.length + + totalScore *= @_hint.length / name.length + return totalScore _refreshResults: -> oldResults = @_results - newResults = {} + scoredItems = [] count = 0 logger.verbose => "Looking for items which match: #{@_hint}" @@ -75,15 +86,18 @@ module.exports = class ItemSelector extends BaseModel return unless mod.enabled mod.eachName (name, itemSlug)=> - return if count >= @_maxResults + return if scoredItems.length >= @_maxResults + return unless itemSlug.isQualified - if @_isMatch name, itemSlug - if itemSlug.isQualified - newResults[itemSlug] = itemSlug - count += 1 + score = @_computeScore name, itemSlug + if score >= @_hint.length + scoredItems.push score:score, itemSlug:itemSlug - newResults = _.values(newResults) - newResults.sort ItemSlug.compare + scoredItems.sort (a, b)-> + if a.score isnt b.score + return if a.score > b.score then -1 else +1 + return ItemSlug.compare a.itemSlug, b.itemSlug + newResults = (e.itemSlug for e in scoredItems) @_results = newResults @trigger c.event.change + ':results', this, oldResults, newResults