function rankRegions()

in region-optimizer.js [76:144]


function rankRegions(regions, inputs) {
    let results = [];
    let missingData = [];
    let latencyData;

    normalizeAttributes(regions, cfeAttr);
    normalizeAttributes(regions, carbonIntensityAttr);
    normalizeAttributes(regions, priceAttr);

    // If latency is a criteria and some locations have been specified,
    // score each region based on proximity to locations.
    if (inputs.weights.latency > 0 && inputs.locations.length > 0) {
        latencyData = {};
        for (const region in regions) {
            let d = 0;
            for (const location of inputs.locations) {
                d += distance(location, regions[region]);
            }
            latencyData[region] = { distance: d };
        }
        normalizeAttributes(latencyData, distanceAttr);
    }

    for (const region in regions) {
        let score = 0;
        // price: lower is better
        if(inputs.weights.price > 0) {
            score += (1 - regions[region]?.[priceAttr + normalizedSuffix]) * inputs.weights.price;
        }
        // carbon
        if(inputs.weights.carbon > 0) {
            if (regions[region]?.[cfeAttr] !== undefined) {
                // CFE: higher is better
                score += regions[region]?.[cfeAttr + normalizedSuffix] * inputs.weights.carbon;
            } else {
                // Carbon Intensity: Lower is better
                score += (1 - regions[region]?.[carbonIntensityAttr + normalizedSuffix]) * inputs.weights.carbon;
            }
        }

        if (inputs.weights.latency > 0 && inputs.locations.length > 0) {
            // latency: lower is better
            score += (1 - latencyData?.[region]?.[distanceAttr + normalizedSuffix]) * inputs.weights.latency;
        }

        if (!isNaN(score)) {
            results.push({
                region: region,
                properties: regions[region],
                score: score,
            });
        } else {
            missingData.push({
                region: region,
            })
        }
    }

    const resultSorted = results.sort(function (a, b) {
        return b.score - a.score;
    });

    const resultFilteredSorted = keepOnlyAllowedRegionsFromResults(inputs.allowedRegions, resultSorted);

    return {
        sorted: resultFilteredSorted,
        missingData
    };
}