Skip to content

Commit

Permalink
Refactor QuickScoreConfig to extend BaseConfig
Browse files Browse the repository at this point in the history
Add useSkipReduction() method and emptyQueryScore to the config.
Move constants into config object so they can be overridden.
Use emptyQueryScore = 0 with the default config.
Rename config() to createConfig().
Create a config from the configOptions in createScorer().
Fix zero score tests.
Remove babel key from package.json.
Add babel-plugin-external-helpers to avoid duplicate class call checks.
Update eslintrc.
  • Loading branch information
fwextensions committed Sep 15, 2018
1 parent 8343fe9 commit 074b364
Show file tree
Hide file tree
Showing 8 changed files with 129 additions and 86 deletions.
6 changes: 3 additions & 3 deletions .eslintrc.js
Expand Up @@ -29,7 +29,7 @@ module.exports = {
"off",
"never"
],
"class-methods-use-this": "error",
"class-methods-use-this": "off",
"comma-dangle": "error",
"comma-spacing": [
"error",
Expand Down Expand Up @@ -88,7 +88,7 @@ module.exports = {
"error",
"always"
],
"max-classes-per-file": "error",
"max-classes-per-file": "off",
"max-depth": "off",
"max-len": "off",
"max-lines": "error",
Expand Down Expand Up @@ -244,7 +244,7 @@ module.exports = {
"prefer-const": "error",
"prefer-destructuring": "error",
"prefer-numeric-literals": "error",
"prefer-object-spread": "error",
"prefer-object-spread": "off",
"prefer-promise-reject-errors": "error",
"prefer-reflect": "error",
"prefer-rest-params": "error",
Expand Down
32 changes: 15 additions & 17 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 1 addition & 9 deletions package.json
Expand Up @@ -23,15 +23,6 @@
"test:coverage": "jest --coverage --runInBand --env node",
"debug": "node debug/debug-quick-score.js"
},
"babel": {
"env": {
"test": {
"presets": [
"env"
]
}
}
},
"jest": {
"collectCoverageFrom": [
"src/*.js",
Expand All @@ -45,6 +36,7 @@
"devDependencies": {
"ajv": "^6.5.2",
"babel": "^6.23.0",
"babel-plugin-external-helpers": "^6.22.0",
"babel-preset-env": "^1.7.0",
"eslint": "^5.3.0",
"jest": "^23.3.0",
Expand Down
7 changes: 4 additions & 3 deletions rollup.config.js
Expand Up @@ -17,9 +17,10 @@ const BabelConfig = {
exclude: "**/node_modules/**",
// tell babel to not transform modules, so that rollup can do it
presets: [
["env", {
modules: false
}]
["env", { modules: false }]
],
plugins: [
"external-helpers"
]
};

Expand Down
126 changes: 87 additions & 39 deletions src/config.js
@@ -1,28 +1,43 @@
const WordSeparators = "-/\\:()<>%._=&[]+ \t\n\r";
const UppercaseLetters = (function() {
const charCodeA = "A".charCodeAt(0);
const uppercase = [];
const BaseConfigDefaults = {
wordSeparators: "-/\\:()<>%._=&[]+ \t\n\r",
uppercaseLetters: (function() {
const charCodeA = "A".charCodeAt(0);
const uppercase = [];

for (let i = 0; i < 26; i++) {
uppercase.push(String.fromCharCode(charCodeA + i));
for (let i = 0; i < 26; i++) {
uppercase.push(String.fromCharCode(charCodeA + i));
}

return uppercase.join("");
})(),
ignoredScore: 0.9,
skippedScore: 0.15,
emptyQueryScore: 0
};
const QSConfigDefaults = {
longStringLength: 151,
maxMatchStartPct: 0.15,
minMatchDensityPct: 0.75,
maxMatchDensityPct: 0.95,
beginningOfStringPct: 0.1
};


class BaseConfig {
constructor(
options)
{
Object.assign(this, BaseConfigDefaults, options);
}

return uppercase.join("");
})();
const IgnoredScore = 0.9;
const SkippedScore = 0.15;
const LongStringLength = 151;
//const MaxMatchStartPct = .15;
const MinMatchDensityPct = .75;
const MaxMatchDensityPct = .95;
const BeginningOfStringPct = .1;
const ConfigDefaults = {
wordSeparators: WordSeparators,
uppercaseLetters: UppercaseLetters,
ignoredScore: IgnoredScore,
skippedScore: SkippedScore,
skipReduction: true,
adjustRemainingScore: function(

useSkipReduction()
{
return true;
}


adjustRemainingScore(
string,
query,
remainingScore,
Expand All @@ -32,7 +47,48 @@ const ConfigDefaults = {
matchedRange,
fullMatchedRange)
{
const isShortString = string.length < LongStringLength;
// use the original Quicksilver expression for the remainingScore
return remainingScore * remainingSearchRange.length;
}
}


class QuickScoreConfig extends BaseConfig {
constructor(
options)
{
super(Object.assign({}, QSConfigDefaults, options));
}


useSkipReduction(
string,
query,
remainingScore,
searchRange,
remainingSearchRange,
matchedRange,
fullMatchedRange)
{
const len = string.length;
const isShortString = len < this.longStringLength;
const matchStartPercentage = fullMatchedRange.location / len;

return isShortString || matchStartPercentage < this.maxMatchStartPct;
}


adjustRemainingScore(
string,
query,
remainingScore,
skippedSpecialChar,
searchRange,
remainingSearchRange,
matchedRange,
fullMatchedRange)
{
const isShortString = string.length < this.longStringLength;
const matchStartPercentage = fullMatchedRange.location / string.length;
let matchRangeDiscount = 1;
let matchStartDiscount = (1 - matchStartPercentage);
Expand All @@ -45,38 +101,30 @@ const ConfigDefaults = {
if (!skippedSpecialChar) {
matchRangeDiscount = query.length / fullMatchedRange.length;
matchRangeDiscount = (isShortString &&
matchStartPercentage <= BeginningOfStringPct &&
matchRangeDiscount >= MinMatchDensityPct) ?
matchStartPercentage <= this.beginningOfStringPct &&
matchRangeDiscount >= this.minMatchDensityPct) ?
1 : matchRangeDiscount;
matchStartDiscount = matchRangeDiscount >= MaxMatchDensityPct ?
matchStartDiscount = matchRangeDiscount >= this.maxMatchDensityPct ?
1 : matchStartDiscount;
}

// discount the scores of very long strings
return remainingScore * Math.min(remainingSearchRange.length, LongStringLength) *
return remainingScore * Math.min(remainingSearchRange.length, this.longStringLength) *
matchRangeDiscount * matchStartDiscount;
}
};


class QuickScoreConfig {
constructor(
options)
{
Object.assign(this, ConfigDefaults, options);
}
}


export function config(
export function createConfig(
options)
{
return new QuickScoreConfig(options);
}


export const DefaultConfig = config();
export const QuicksilverConfig = config({
export const DefaultConfig = createConfig();
export const QuicksilverConfig = new BaseConfig({
emptyQueryScore: 0.9,
adjustRemainingScore: function(
string,
query,
Expand Down
13 changes: 4 additions & 9 deletions src/quick-score.js
Expand Up @@ -2,10 +2,6 @@ import {Range} from "./range";
import {DefaultConfig} from "./config";


const LongStringLength = 151;
const MaxMatchStartPct = .15;


export function quickScore(
string,
query,
Expand All @@ -14,7 +10,7 @@ export function quickScore(
stringRange = new Range(0, string.length))
{
if (!query) {
return config.ignoredScore;
return config.emptyQueryScore;
}

const lcString = string.toLocaleLowerCase();
Expand Down Expand Up @@ -66,16 +62,15 @@ export function quickScore(
const remainingScore = calcScore(remainingSearchRange, remainingQueryRange, fullMatchedRange);

if (remainingScore) {
const isShortString = string.length < LongStringLength;
const matchStartPercentage = fullMatchedRange.location / string.length;
const useSkipReduction = config.skipReduction === true &&
(isShortString || matchStartPercentage < MaxMatchStartPct);
let score = remainingSearchRange.location - searchRange.location;
// default to true since we only want to apply a discount if
// we hit the final else clause below, and we won't get to
// any of them if the match is right at the start of the
// searchRange
let skippedSpecialChar = true;
const useSkipReduction = config.useSkipReduction(string, query,
remainingScore, remainingSearchRange, searchRange,
remainingSearchRange, matchedRange, fullMatchedRange);

if (matchedRange.location > searchRange.location) {
// some letters were skipped when finding this match, so
Expand Down

0 comments on commit 074b364

Please sign in to comment.