/** * Calculate the distances by using the numbers, strings and dates. * @param {node} source * @param {node} target * @param {array} properties - the properties of the nodes. * @param {object} normArgs - the normalization arguments. * @return {number} the distance between source and target nodes. */ function calculateDistance(source, target, properties, normArgs) { var val1 = 0.0, val2 = 0.0, sumDiff = 0.0, ordDiff = 1.0, ORD_FACTOR = 0.75, cols = 0, average = normArgs.avg, sigma = normArgs.sig, st_dev = normArgs.st_d; // Iterate through every column of data for (var i = 0; i < properties.length; i++) { property = properties[i]; if (source.hasOwnProperty(property) && target.hasOwnProperty(property) && property.toLowerCase() !== "index" ) { var s = source[property], t = target[property]; // Comparing Floats and Integers if ((isNumeric(s) && isNumeric(t))) { val1 = parseFloat(s); val2 = parseFloat(t); if (sigma[i] != 0) { val1 = (val1 - average[i]) / (st_dev[i] * sigma[i]); val2 = (val2 - average[i]) / (st_dev[i] * sigma[i]); } sumDiff += (val1-val2) * (val1-val2); cols++; // Comparing strings } else if (/[a-zA-Z]/.test(s) && /[a-zA-Z]/.test(t) && s === t) { ordDiff *= ORD_FACTOR; cols++; } else { // Comparing Dates var parsedDateS = Date.parse(s); var parsedDateT = Date.parse(t); if (isNaN(s) && !isNaN(parsedDateS) && isNaN(t) && !isNaN(parsedDateT)) { val1 = parsedDateS.valueOf(), val2 = parsedDateT.valueOf(); if (sigma[i] !== 0) { val1 = (val1 - average[i]) / (st_dev[i] * sigma[i]); val2 = (val2 - average[i]) / (st_dev[i] * sigma[i]); } sumDiff += (val1-val2) * (val1-val2); cols++; } } } } sumDiff = Math.sqrt(sumDiff); sumDiff *= ordDiff; if (cols > 0) { sumDiff *= properties.length/cols; } console.log(sumDiff); return sumDiff; }