const _ = require("lodash");
const optimizelySDK = require("@optimizely/optimizely-sdk");
const defaultLogger = require('@optimizely/optimizely-sdk/lib/plugins/logger');
const SDK_KEY = 'XWsD3vvR34mQnuKyguDEE5'; // TODO: 1. UPDATE TO MATCH YOUR SDK KEY
const userId = 'user123'; // You can change this userId to see if you get bucketed into different variations!
// This is the data we will sort!
const posts = [
{ name: 'Deliver Pizza', type: 'delivery', price: 25 , daysAgo: 30, }, // Oldest
{ name: 'Wordpress Plugin', type: 'software', price: 35 , daysAgo: 1, }, // Newest
{ name: 'Help with Resume', type: 'editorial', price: 20 , daysAgo: 5, },
{ name: 'Design Project', type: 'software', price: 50 , daysAgo: 4, },
{ name: 'Deliver Ice Cream', type: 'software', price: 65 , daysAgo: 21, },
{ name: 'Complete Puzzle', type: 'physical', price: 5 , daysAgo: 16, }, // Cheapest
{ name: 'Personal Assistant', type: 'physical', price: 300, daysAgo: 18, }, // Most Expensive
];
const optimizelyClientInstance = optimizelySDK.createInstance({
sdkKey: SDK_KEY,
});
await optimizelyClientInstance.onReady()
/** With Optimizely - configuration can be changed without deploys through Optimizely UI **/
const featureKey = 'demo_sort_algorithm'; // TODO: 2. CREATE A FEATURE named 'sort_algorithm' in your project
// TODO: 3. Replace enabled variable value with a feature flag
var enabled = optimizelyClientInstance.isFeatureEnabled('demo_sort_algorithm', userId);
if (enabled) {
var daysWeight = optimizelyClientInstance.getFeatureVariableInteger('demo_sort_algorithm', 'daysWeight', userId);
var priceWeight = optimizelyClientInstance.getFeatureVariableInteger('demo_sort_algorithm', 'priceWeight', userId);
var scoringFn = optimizelyClientInstance.getFeatureVariableString('demo_sort_algorithm', 'scoringFn', userId);
var limit = optimizelyClientInstance.getFeatureVariableInteger('demo_sort_algorithm', 'limit', userId);
// TODO: 4. Replace each property's value with the corresponding feature variable call
const config = {
'scoringFn': scoringFn,
'priceWeight': priceWeight,
'daysWeight': daysWeight,
'limit': limit,
}
console.log('Sorting algorithm loaded with configuration:');
console.log(config);
// YOU ONLY NEED TO PAY ATTENTION TO WHERE THE CONFIG OBJECT IS BEING USED IN THE FOLLOWING CODE
/**
* Creates a normalizing function for a specific property
* Normalizes by ensuring all values range from 0 to 1.
*/
const normalizer = (posts, property) => {
const items = posts.map((post) => (post[property]))
const max = _.max(items);
const min = _.min(items);
const range = max - min;
return (value) => {
return (value - min) / range;
}
}
/**
* Create a normalizing function for the properties we want to normalize
*/
const normalizePrice = normalizer(posts, 'price');
const normalizeDaysAgo = normalizer(posts, 'daysAgo');
/**
* Scoring functions used to sort items by score
*/
const scoringFns = {
weightedSum: (item) => {
const nPrice = normalizePrice(item.price)
const nDaysAgo = normalizeDaysAgo(item.daysAgo)
return (
nPrice*config.priceWeight +
nDaysAgo*config.daysWeight
)
},
byPrice: (item) => (item.price),
byDate: (item) => (item.daysAgo),
random: () => (Math.random()),
}
const scoreItem = scoringFns[config.scoringFn];
function sortByScore(scoreItem) {
return (a, b) => {
return scoreItem(b) - scoreItem(a);
}
}
const sortedItems = _(posts)
.sort(sortByScore(scoreItem))
.take(config.limit)
.value();
console.log(sortedItems);
sortedItems.forEach((item, index) => {
console.log(`${index}: ${item.name} for ${item.price} posted ${item.daysAgo} days ago`);
});
}