Building Custom Scoring Functions

Published: 18-Jan-2025

Score

  • The score is a floating point number ranging from 0 to 1.
  • To score a function we must set the property score on plugins (that was passed as argument to the function)
plugin.score = 0.5;

Where to see and create score functions?

  • /scorer page shows the list of all custom score functions.
  • /scorer/build page is where we create our custom score functions from.

Have a look at /scorer. Right now, it will be empty with no score functions.

List of custom scorers

Click on + Create Scorer button and start creating a scorer.

Score Builder

Signature of the custom score function

To build a custom scorer, you must create a javascript function

function scorePlugins(plugins, utils) {
  // ...
}

Let's build a simple score functions.

Example 1: Setting score of all plugins to 50

To set the scores of all plugins to 50, you can write the following custom score function.

function scorePlugins(plugins, utils) {
  plugins.forEach(plugin => {
    plugin.score = 0.5; // Setting the score of each plug to 0.5
  })
}

The first and last lines are not editable in the UI. So, fill the function with the 3 lines from above.

  • One you are done, click Validate.
  • Upon successful validation, enter a name and description to the score function.
  • Click Save and Use

Save and Use

πŸŽ‰ Congratulations! Your just set a custom score of 50 to all the plugins across the website. You can see the custom scores in different pages now (new, most-downloaded etc.)

Let's build something usable now. In the /scorer/build page, click on "New Scorer" button to build our next scorer.

Example 2: Setting score based on downloads count

Use the below code to build a custom score function based on download count (totalDownloads property) of the plugins.

Get all the download values

function scorePlugins(plugins, utils) {
  let downloads = plugins.map(plugin => plugin.totalDownloads);
}

Find min and max download counts among all plugins

function scorePlugins(plugins, utils) {
  let downloads = plugins.map(plugin => plugin.totalDownloads);
  const min = Math.min(...downloads); // We use min and max from Math library
  const max = Math.max(...downloads);
}

Assign normalized value of a plugin's totalDownloads as it's score

function scorePlugins(plugins, utils) {
  let downloads = plugins.map(plugin => plugin.totalDownloads);
  const min = Math.min(...downloads);
  const max = Math.max(...downloads);
  plugins.forEach(plugin => {
    // we use normalize function from utils
    plugin.score = utils.normalize(plugin.totalDownloads, min, max);
  });
}
  • The top most downloaded plugin has totalDownloads of 3,244,441 (Excalidraw)
  • The second most downloaded plugin has totalDownloads of 2,413,498 (Dataview)
  • The above function will score Excalidraw as 100 and the second best plugin will have a score of 76.
  • To avoid this skew in number we can remove few extreme values (outliers) on the higher end (we can do it on lower end as well to avoid outliers with zero or very less totalDownloads)

Remove outliers values before scoring

function scorePlugins(plugins, utils) {
  let downloads = plugins
    .map(plugin => plugin.totalDownloads)
    .sort((a, b) => a - b);  // Let's sort all the totalDownload values
  
  const outliersCount = Math.round(plugins.length * 0.005) // We are considering 0.5% values as outliers on either side
  downloads = downloads.slice(outliersCount, plugins.length - outliersCount) // Sliding off the outliers
  
  const min = Math.min(...downloads);
  const max = Math.max(...downloads);
  plugins.forEach(plugin => {
    // we use normalize function from utils
    plugin.score = utils.normalize(plugin.totalDownloads, min, max);
  });
}

This change makes 10 plugins to score more than 80.

Note: We must analyse the distribution of each dimension we use to determine the outliers. The 0.5% is just an example here!

Validate, give a name and description and click Save and Use.

Normalized download count scorer

πŸš€ Our new custom score function is being used across the website.

You can go to all plugins and sort by "Score (High to Low)" and see your custom scores in action. Here is magic link for the same!

all plugins with score

Go to /scorer page to view the list of custom score function. You can edit a score function or use it from here!

scorer list with scorers

Note: Your custom score function score the plugin locally in the browser and the custom scores are saved locally in your browser's localStorage.

Going forward

  • I want to fix the default score function with clear objective to cater new comers to Obsidian.
  • I want to add more functions to utils to make building score functions easier.
  • Ofcourse, I want to develop a process to publish scorer function and let everyone use it just like how we use themes and plugins in Obsidian.

Contribution

  • All your feedback and suggestions are welcome at the Github discussion.
  • Will update the link to the source of the plugins and utils soon. (They are not published anywhere yet as I write this!)