const currentScores = {}; const rescore = (target, { name, jab, rgb }) => { currentScores[name] = { jab: { total: applyMetrics(jab.total, target.jab), clusters: jab.clusters.map(c => applyMetrics(c, target.jab)), }, rgb: { total: applyMetrics(rgb.total, target.rgb), clusters: rgb.clusters.map(c => applyMetrics(c, target.rgb)), }, }; }; const rescoreAll = target => pokemonData.forEach(pkmn => rescore(target, pkmn)); const getBestClusterIndex = (pkmn, space, { sortMetric, scaleOption, sortOrder }) => { // get the scales const scales = scaleOption(pkmn); // and multiply with the intended metric, and find the best value return argComp(sortOrder)( currentScores[pkmn.name][space].map((c, i) => c[sortMetric] * scales[i]) ); } const getBest = (number, space, clusterSettings, { sortMetric, scaleOption, sortOrder }) => { let valueExtractor; if (clusterSettings) { valueExtractor = pkmn => { const index = getBestClusterIndex(pkmn, space, clusterSettings); // and then get the *actual* score according to the sort metric return scaleOption(pkmn)[index] * clusters[index][sortMetric]; }; } else { // ignore scaleOption if not using clusters valueExtractor = pkmn => currentScores[pkmn.name][space].total[sortMetric]; } return pokemonData .slice() .sort((a, b) => sortOrder(valueExtractor(a), valueExtractor(b))) .slice(0, number); };