var sampleData = []; geofenceData = [], clusters = [], centroidData = [], silhouetteData = [], predictions = [];
var cleanData, geofences, partitions, centroids, entryIDs, geofenceIDs, clusterEntries;
var K = 0;
var maxDuration = 0;
// DOM Ready
$(document).ready(function () {
    retrievePastEvents();
    //populateGeofences();
    //populateCentroids();
    //populateClusters();
    //populatePredictions();
    $('#btnCheck').on('click', checkStopDuration);
    $('#btnGenerate').on('click', generateClusters);    
    $('#btnSilhouette').on('click', generateSilhouettes);
    $('#btn10Fold').on('click', tenFoldEvaluation);
    $('#btnLoad2').on('click', loadSilhouettes);
    $('#btnLoad').on('click', loadData);
});
function retrievePastEvents() {
    $.getJSON('/users/sampleData', function (data) {
        sampleData = data;
    });
};
function populateGeofences() {
    var tableContent = '';
    $.getJSON('/users/geofences', function (data) {
        geofenceData = data;
        $.each(data, function () {
            tableContent += '<tr>';
            tableContent += '<td>' + this.geofenceID + '</td>';
            tableContent += '<td> ' + this.entries + '</td>';
            tableContent += '</tr>';
        });
        $('#geofences table tbody').html(tableContent);
    });
};
function populateCentroids() {
    var tableContent = '';
    $.getJSON('/users/centroids', function (data) {
        centroidData = data;
        $.each(data, function () {
            tableContent += '<tr>';
            tableContent += '<td>' + this.geofenceID + '</td>';
            tableContent += '<td> ' + this.centroids + '</td>';
            tableContent += '</tr>';
        });
        $('#centroids table tbody').html(tableContent);
    });
};
function populateClusters() {
    var tableContent = '';
    $.getJSON('/users/clusters', function (data) {
        clusterData = data;
        $.each(data, function () {
            tableContent += '<tr>';
            tableContent += '<td>' + this.geofenceID + '</td>';
            tableContent += '<td>' + this.clusterNum + '</td>';
            tableContent += '<td>' + this.centroidID + '</td>';
            tableContent += '<td> ' + this.entries + '</td>';
            tableContent += '</tr>';
        });
        $('#clusters table tbody').html(tableContent);
    });
    populatePredictions();
};
function populateSilhouettes() {
    var tableContent = '';
    $.getJSON('/users/silhouettes', function (data) {
        silhouetteData = data;
        $.each(data, function () {
            tableContent += '<tr>';
            tableContent += '<td>' + this.entryID + '</td>';
            tableContent += '<td>' + this.geofenceID + '</td>';
            tableContent += '<td>' + this.internalSilhouette + '</td>';
            tableContent += '<td>' + this.externalSilhouette+ '</td>';
            tableContent += '</tr>';
        });
        $('#silhouettes table tbody').html(tableContent);
    });
};
function populatePredictions() {
    var tableContent = '';
    $.getJSON('/users/predictions', function (data) {
        predictions = data;
        $.each(data, function () {
            tableContent += '<tr>';
            tableContent += '<td>' + this.foldNumber + '</td>';
            tableContent += '<td>' + this.averageDifference + '</td>';
            tableContent += '<td>' + this.accuracy + '</td>';
            tableContent += '</tr>';
        });
        $('#predictions table tbody').html(tableContent);
    });
};

function loadData(event) {
    event.preventDefault();
    var tableContent = '';
    $.getJSON('/users/sampleData', function (data) {
        $.each(data, function () {
            tableContent += '<tr>';
            tableContent += '<td><a href="#" class="linkshowuser" rel="' + this.EntryID + '" title="Show Details">' + this.EntryID + '</a></td>';
            tableContent += '<td>' + this.VehicleID + '</td>';
            tableContent += '<td>' + this.GeofenceID + '</td>';
            tableContent += '<td>' + this.GeofenceCategory + '</td>';
            tableContent += '<td>' + this.ArrivalTimeNZ + '</td>';
            tableContent += '<td>' + this.DepartureTimeNZ + '</td>';
            tableContent += '<td>' + this.DurationSeconds + '</td>';
            tableContent += '</tr>';
        });
        $('#pastEvents table tbody').html(tableContent);
    });
};
function loadSilhouettes(event) {
    event.preventDefault();
    var confirmation = confirm('Load silhouette values?');
    if (confirmation == true) {
        var tableContent = '';
        $.getJSON('/users/silhouettes', function (data) {
            silhouetteData = data;
            $.each(data, function () {
                tableContent += '<tr>';
                tableContent += '<td>' + this.entryID + '</td>';
                tableContent += '<td>' + this.geofenceID + '</td>';
                tableContent += '<td>' + this.internalSilhouette + '</td>';
                tableContent += '<td>' + this.externalSilhouette + '</td>';
                tableContent += '</tr>';
            });
            $('#silhouettes table tbody').html(tableContent);
        });
    }
};
function checkStopDuration(event) {
    event.preventDefault();
    var confirmation = confirm('Predict Stop Duration?');
    try {
        if (confirmation == true) {
            if ($('#inputVehicleID').val() === '' || $('#inputGeofenceID').val() === '' || $('#inputGeofenceCategory').val() === '' || $('#inputArrivalTime').val() === '') {
                alert("Please fill in all fields");
            } else {
                var object = {
                    'VehicleID': $('#inputVehicleID').val(),
                    'GeofenceID': $('#inputGeofenceID').val(),
                    'GeofenceCategory': $('#inputGeofenceCategory').val(),
                    'ArrivalTimeNZ': $('#inputArrivalTime').val()
                }
                var minCentOfGeo = [];
                var minDistanceOfGeo = [];
                for (j = 0; j < geofences.length; j++) {
                    var distances = [];
                    for (k = 0; k < K; k++) {
                        var A = 0; B = 0, C = 0, D = 0;
                        A = object.VehicleID == centroids[j][k].VehicleID ? 0 : 1;
                        B = object.GeofenceID == centroids[j][k].GeofenceID ? 0 : 1;
                        C = object.GeofenceCategory == centroids[j][k].GeofenceCategory ? 0 : 1;
                        D = month(object.ArrivalTimeNZ) == month(centroids[j][k].ArrivalTimeNZ) ? 0 : 1;
                        distances[k] = Math.sqrt((0.25 * A) + (0.25 * B) + (0.25 * C) + (0.25 * D));
                    }
                    var minIndex = distances.indexOf(Math.min.apply(null, distances));
                    minDistanceOfGeo.push(distances[minIndex]);
                    minCentOfGeo.push(minIndex);
                }
                var geoWithMin = minDistanceOfGeo.indexOf(Math.min.apply(null, minDistanceOfGeo));
                var minGeoCent = minCentOfGeo[geoWithMin];
                //$('#inputVehicleID').val('');
                //$('#inputGeofenceID').val('');
                //$('#inputGeofenceCategory').val('');
                //$('#inputArrivalTime').val('');
                alert("Predicted stop duration: " + centroids[geoWithMin][minGeoCent].DurationSeconds);
            }
        }
    } catch (err) {
        alert(err);
    }
};
function generateClusters(event) {
    event.preventDefault();
    var confirmation = confirm('Update Clusters?');
    try {
        if (confirmation == true) {
            $.getJSON('/users/removegeofences');
            $.getJSON('/users/removecentroids');
            $.getJSON('/users/removeclusters');
            cleanData = [];
            var i, j;
            for (i = 0; i < sampleData.length; i++) {
                if (sampleData[i].DurationSeconds <= 80340) {
                    cleanData.push(sampleData[i]);
                }
            }
            var numOfEntries = cleanData.length;
            geofences = [];
            for (i = 0; i < numOfEntries; i++) {
                geofences.push(cleanData[i].GeofenceID);
            }
            geofences = geofences.filter(onlyUnique);
            var numOfGeofences = geofences.length;
            K = 10;
            var entries = dataPartition(cleanData, numOfGeofences, numOfEntries);
            var tempClusters = [];
            for (i = 1; i <= 10; i++) {
                var centroidIDs = initializeCentroids(numOfGeofences);
                var clust = assignClusters(numOfGeofences);
                if (i == 1) {
                    tempClusters = clust.map(function(arr) {return arr.slice();})
                    continue;
                }
                var SSE1 = getSSE(clust);
                var SSE2 = getSSE(tempClusters);
                if (SSE1 < SSE2) {
                    tempClusters = clust.map(function(arr) {return arr.slice();})
                }
            }
            clusters = tempClusters.map(function (arr) { return arr.slice(); })
            addGeofences(entries);
            addCentroids(centroidIDs);            
            for (i = 0; i < numOfGeofences; i++) {
                for (j = 0; j < K; j++) {
                    clusterEntries[i][j].push(clusters[i][j].length);
                }
            }
            alert("Clusters Updated");
            addClusters(centroidIDs, clusterEntries);
        }
    } catch (err) {
        alert(err);
    }
};
function dataPartition(data, numOfGeofences, numOfEntries) {
    var i, j;
    var entries = [];
    partitions = [];
    for (i = 0; i < numOfGeofences; i++) {
        entries.push(0);
        partitions[i] = [];
    }
    for (i = 0; i < numOfEntries; i++) {
        entries[geofences.indexOf(data[i].GeofenceID)]++;
        partitions[geofences.indexOf(data[i].GeofenceID)].push(data[i]);
    }
    return entries;
};
function initializeCentroids(numOfGeofences) {
    var i, j;
    centroids = [];
    var centroidIDs = [];
    for (i = 0; i < numOfGeofences; i++) {
        centroids[i] = [];
        centroidIDs[i] = [];
    }
    for (i = 0; i < numOfGeofences; i++) {
        for (j = 0; j < K; j++) {
            var random = Math.floor(Math.random() * partitions[i].length);
            centroids[i][j] = partitions[i][random];
            centroidIDs[i].push(centroids[i][j].EntryID);
        }
    }
    return centroidIDs;
};
function assignClusters(numOfGeofences) {
    var i, j, k;
    var iterateClusters = [];
    entryIDs = [];
    geofenceIDs = [];
    clusterEntries = [];
    for (i = 0; i < numOfGeofences; i++) {
        iterateClusters[i] = [];
        clusterEntries[i] = [];
        for (j = 0; j < K; j++) {
            iterateClusters[i][j] = [];
            clusterEntries[i][j] = [];
        }
    }
    for (i = 0; i < numOfGeofences; i++) {
        for (j = 0; j < partitions[i].length; j++) {
            var distances = [];
            for (k = 0; k < centroids[i].length; k++) {
                distances[k] = distance(partitions[i][j], centroids[i][k]);
            }
            var minIndex = distances.indexOf(Math.min.apply(null, distances));
            iterateClusters[i][minIndex].push(partitions[i][j]);
            entryIDs.push(partitions[i][j].EntryID);
            geofenceIDs.push(partitions[i][j].GeofenceID);
        }
    }
    return iterateClusters;
};
function getSSE(clusters) {
    try {
        var i, j, k;
        var errors = [];
        var clusterSSE = [];
        var partitionSSE = [];
        for (i = 0; i < clusters.length; i++) {
            for (j = 0; j < clusters[i].length; j++) {
                for (k = 0; k < clusters[i][j].length; k++) {
                    errors.push(Math.pow(distance(centroids[i][j], clusters[i][j][k]), 2));
                }
                clusterSSE.push(errors.reduce(function (pv, cv) { return pv + cv; }, 0));
            }
            partitionSSE.push(clusterSSE.reduce(function (pv, cv) { return pv + cv; }, 0));
        }
        var SSE = partitionSSE.reduce(function (pv, cv) { return pv + cv; }, 0);
        return SSE;
    } catch (err) {
        alert(err);
    }
};
function generateSilhouettes(event) {
    event.preventDefault();
    var confirmation = confirm('Generate silhouette values?');
    try {
        if (confirmation == true) {
            $.getJSON('/users/removesilhouettes');
            var i,j,k,l,m;
            var internals = [];
            var externals = [];
            var silhouettes = [];
            var ints = [];
            var exts = [];
            for (i = 0; i < clusters.length; i++) {
                internals[i] = [];
                externals[i] = [];
                silhouettes[i] = [];
                for (j = 0; j < clusters[i].length; j++) {
                    internals[i][j] = [];
                    externals[i][j] = [];
                    silhouettes[i][j] = [];
                    for (k = 0; k < clusters[i][j].length; k++) {
                        var datum = clusters[i][j][k];
                        var internalDistances = [];
                        for (l = 0; l < clusters[i][j].length; l++) {
                            if (l != k) {
                                internalDistances.push(distance(datum, clusters[i][j][l]));
                            }
                        }
                        var sum = 0;
                        for (l = 0; l < internalDistances.length; l++) {
                            sum += internalDistances[l];
                        }
                        internals[i][j].push((sum/internalDistances.length).toFixed(2));
                        ints.push(internals[i][j][k]);
                    }
                }
            }
            for (i = 0; i < clusters.length; i++) {
                for (j = 0; j < clusters[i].length; j++) {
                    for (k = 0; k < clusters[i][j].length; k++) {
                        var datum = clusters[i][j][k];
                        var externalDistances = [];
                        var averages = [];
                        for (l = 0; l < clusters[i].length; l++) {
                            if (l != j) {
                                for (m = 0; m < clusters[i][l].length; m++) {
                                    externalDistances.push(distance(datum, clusters[i][l][m]));
                                }
                                var sum = 0;
                                for (m = 0; m < externalDistances.length; m++) {
                                    sum += externalDistances[m];
                                }
                                averages.push(sum / externalDistances.length);
                            }
                        }
                        externals[i][j].push(Math.min.apply(null, averages));
                        var internalAve = internals[i][j][k];
                        var externalAve = externals[i][j][k];
                        silhouettes[i][j][k] = ((externalAve - internalAve) / Math.max(internalAve, externalAve)).toFixed(2);
                        exts.push(silhouettes[i][j][k]);
                    }          
                }
            }
            addSilhouettes(ints,exts);
            alert("Silhouette values calculated");
            populateSilhouettes();
        }
    } catch (err) {
        alert(err);
    }
};
function tenFoldEvaluation(event) {
    event.preventDefault();
    var confirmation = confirm('Evaluation Predictions?');
    try {
        if (confirmation == true) {
            $.getJSON('/users/removepredictions');
            var i, j;
            var valDataLength = Math.ceil(cleanData.length / 10);
            var averageDifferences = [];
            var accuracy = [];
            for (var foldNum = 0; foldNum < 10; foldNum++) {
                var fold = [];
                var index = 0;
                for (i = 0; i < valDataLength; i++) {
                    var randIndex = Math.floor(Math.random() * cleanData.length);
                    if (randIndex == index) {
                        i--;
                    } else {
                        fold.push(cleanData[randIndex]);
                        index = randIndex;
                    }
                }
                var data = [];
                var count = 0;
                for (i = 0; i < sampleData.length; i++) {
                    var isInFold = false;
                    for (j = 0; j < fold.length; j++) {
                        if (sampleData[i].EntryID == fold[j].EntryID) {
                            isInFold = true;
                            break;
                        }
                    }
                    if (isInFold == false) {
                        data.push(sampleData[i]);
                    }
                }
                var numOfEntries = data.length;
                geofences = [];
                for (i = 0; i < numOfEntries; i++) {
                    geofences.push(data[i].GeofenceID);
                }
                geofences = geofences.filter(onlyUnique);
                var numOfGeofences = geofences.length;
                K = 10;
                var entries = dataPartition(data, numOfGeofences, numOfEntries);
                var tempClusters = [];
                for (i = 1; i <= 10; i++) {
                    var centroidIDs = initializeCentroids(numOfGeofences);
                    var clust = assignClusters(numOfGeofences);
                    if (i == 1) {
                        tempClusters = clust.map(function (arr) { return arr.slice(); })
                        continue;
                    }
                    var SSE1 = getSSE(clust);
                    var SSE2 = getSSE(tempClusters);
                    if (SSE1 < SSE2) {
                        tempClusters = clust.map(function (arr) { return arr.slice(); })
                    }
                }
                var differences = [];
                var falseCount = 0;
                var trueCount = 0;
                for (i = 0; i < fold.length; i++) {
                    var minCentOfGeo = [];
                    var minDistanceOfGeo = [];
                    for (j = 0; j < geofences.length; j++) {
                        var distances = [];
                        for (k = 0; k < K; k++) {
                            distances[k] = distance(fold[i], centroids[j][k]);
                        }
                        var minIndex = distances.indexOf(Math.min.apply(null, distances));
                        minDistanceOfGeo.push(distances[minIndex]);
                        minCentOfGeo.push(minIndex);
                    }
                    var geoWithMin = minDistanceOfGeo.indexOf(Math.min.apply(null, minDistanceOfGeo));
                    var minGeoCent = minCentOfGeo[geoWithMin];
                    differences.push(Math.abs(centroids[geoWithMin][minGeoCent].DurationSeconds - fold[i].DurationSeconds));
                    var minCentOfGeo2 = [];
                    var minDistanceOfGeo2 = [];
                    for (j = 0; j < geofences.length; j++) {
                        var distances2 = [];
                        for (k = 0; k < K; k++) {
                            if (j == geoWithMin && k == minGeoCent) {
                                continue;
                            }
                            distances2.push(distance(fold[i], centroids[j][k]))
                        }
                        var minIndex2 = distances2.indexOf(Math.min.apply(null, distances2));
                        minDistanceOfGeo2.push(distances2[minIndex2]);
                        minCentOfGeo2.push(minIndex2);
                    }
                    var geoWithMin2 = minDistanceOfGeo2.indexOf(Math.min.apply(null, minDistanceOfGeo2));
                    var minGeoCent2 = minCentOfGeo2[geoWithMin2];
                    var otherDifference = Math.abs(centroids[geoWithMin2][minGeoCent2].DurationSeconds - fold[i].DurationSeconds);
                    if (otherDifference < differences[i]) {
                        falseCount++;
                    } else {
                        trueCount++;
                    }
                }
                accuracy.push(((trueCount/(trueCount + falseCount))*100).toFixed(2));
                var sum = 0;
                for (i = 0; i < differences.length; i++) {
                    sum += differences[i]
                }
                averageDifferences.push((sum/differences.length).toFixed(2));
            }
            alert("10 Fold Evaluation Performed");
            addPredictions(averageDifferences, accuracy);
        }
    } catch (err) {
        alert(err);
    }
};
function generateSSE(event) {
    event.preventDefault();
    var confirmation = confirm('Generate SSE?');
    try {
        if (confirmation == true) {
            var i, j, k;
            var errors = [];
            var clusterSSE = [];
            var partitionSSE = [];
            for (i = 0; i < clusters.length; i++) {
                for (j = 0; j < clusters[i].length; j++) {
                    for (k = 0; k < clusters[i][j].length; k++) {
                        errors.push(Math.pow(distance(centroids[i][j],clusters[i][j][k]),2));
                    }
                    clusterSSE.push(errors.reduce(function(pv,cv){return pv+cv;}, 0));
                }
                partitionSSE.push(clusterSSE.reduce(function(pv,cv){return pv+cv;}, 0));
            }
            var SSE = partitionSSE.reduce(function(pv,cv){return pv+cv;}, 0);
            alert("SSE: " + SSE);
        }
    } catch (err) {
        alert(err);
    }
};
function addGeofences(entries) {
    for (i = 0; i < geofences.length; i++) {
        var entry = { 'geofenceID': geofences[i], 'entries': entries[i] }
        $.ajax({
            type: 'POST',
            data: entry,
            url: '/users/addgeofences',
            dataType: 'JSON'
        }).done(function (response) {
            if (response.msg === '') {
                populateGeofences();
            }
            else {
                alert('Error: ' + response.msg);
            }
        });
    }
};
function addCentroids(centroidsIDs) {
    for (i = 0; i < geofences.length; i++) {
        var entry = { 'geofenceID': geofences[i], 'centroids': centroidsIDs[i] }
        $.ajax({
            type: 'POST',
            data: entry,
            url: '/users/addcentroids',
            dataType: 'JSON'
        }).done(function (response) {
            if (response.msg === '') {
                populateCentroids();
            }
            else {
                alert('Error: ' + response.msg);
            }
        });
    }
};
function addClusters(centroidIDs, entries) {
    for (i = 0; i < geofences.length; i++) {
        for (j = 0; j < entries[i].length; j++) {
            var entry = { 'geofenceID': geofences[i],'clusterNum': j+1,'centroidID':centroidIDs[i][j], 'entries': entries[i][j] }
            $.ajax({
                type: 'POST',
                data: entry,
                url: '/users/addclusters',
                dataType: 'JSON'
            }).done(function (response) {
                if (response.msg === '') {
                    populateClusters();
                }
                else {
                    alert('Error: ' + response.msg);
                }
            });
        }
    }
};
function addSilhouettes(ints, exts) {
    for (i = 0; i < ints.length; i++) {
        var entry = {'entryID': entryIDs[i], 'geofenceID': geofenceIDs[i], 'internalSilhouette': ints[i], 'externalSilhouette': exts[i] }
        $.ajax({
            type: 'POST',
            data: entry,
            url: '/users/addsilhouettes',
            dataType: 'JSON'
        }).done(function (response) {
            if (response.msg === '') {
                //populateSilhouettes();
            }
            else {
                alert('Error: ' + response.msg);
            }
        });
    }
};
function addPredictions(averageDifference, accuracy) {
    for (i = 0; i < 10; i++) {
        var entry = { 'foldNumber': i + 1, 'averageDifference': averageDifference[i], 'accuracy': accuracy[i] }
        $.ajax({
            type: 'POST',
            data: entry,
            url: '/users/addpredictions',
            dataType: 'JSON'
        }).done(function (response) {
            if (response.msg === '') {
                populatePredictions();
            }
            else {
                alert('Error: ' + response.msg);
            }
        });
    }
};
function distance(object1,object2) {
    var A=0; B=0, C=0, D=0, E=0;
    A = object1.VehicleID==object2.VehicleID ? 0 : 1;
    B = object1.GeofenceCategory==object2.GeofenceCategory ? 0 : 1;
    C = month(object1.ArrivalTimeNZ)==month(object2.ArrivalTimeNZ) ? 0 : 1;
    D = (object1.DurationSeconds) - (object2.DurationSeconds);
    var d = Math.sqrt((0.2*A)+(0.2*B)+(0.2*C)+(0.4*(Math.pow(D,2))));
    return d;
}
function month(date) {
    var month = date.substring(date.indexOf('/')+1,date.indexOf('/')+3);
    switch (month) {
        case "01": 
            month = "January";
            break;
        case "02": 
            month = "Febuary";
            break;
        case "03": 
            month = "March";
            break;
        case "04": 
            month = "April";
            break;        
        case "05": 
            month = "May";
            break;
        case "06": 
            month = "June";
            break;        
        case "07": 
            month = "July";
            break;
        case "08": 
            month = "August";
            break;
        case "09": 
            month = "September";
            break;
        case "10": 
            month = "October";
            break;
        case "11": 
            month = "November";
            break;
        case "12": 
            month = "December";
            break;         
    }
    return month;
}
function period(date) {
    var hour = date.substring(date.indexOf(' ')+1,date.indexOf(':'));
    var period = hour < 12 ? "AM" : "PM";
    return period;
}
function onlyUnique(value,index,self) { 
    return self.indexOf(value) === index;
}
/*function computeCentroids(isMicro) {
    // Recompute the centroid of each cluster using the sum of the squared errors.
    if (isMicro==0) {
        for (i=0; i<clusters.length; i++) {
            var driver=0,truck=0,route=0,stop=0,items=0,duration=0;
            for (j=0; j<clusters[i].length; j++) {
                driver += parseInt(clusters[i][j].driver);
                truck += parseInt(clusters[i][j].truck);
                route += parseInt(clusters[i][j].route);
                stop += parseInt(clusters[i][j].stop);
                items += parseInt(clusters[i][j].items);
                duration += parseInt(clusters[i][j].duration);
            }
            driver = driver/clusters[i].length;
            truck = truck/clusters[i].length;
            route = route/clusters[i].length;
            stop = stop/clusters[i].length;
            items = items/clusters[i].length;
            duration = duration/clusters[i].length;
            centroids[i] = [driver,truck,route,stop,items,duration];
        }
    } else {
        for (i=0; i<finalClusters.length; i++) {
            for (j=0; j<finalClusters[i].length; j++) {
                var driver=0,truck=0,route=0,stop=0,items=0,duration=0;
                for (k=0; k<finalClusters[i][j].length; k++) {
                    driver += parseInt(finalClusters[i][j][k].driver);
                    truck += parseInt(finalClusters[i][j][k].truck);
                    route += parseInt(finalClusters[i][j][k].route);
                    stop += parseInt(finalClusters[i][j][k].stop);
                    items += parseInt(finalClusters[i][j][k].items);
                    duration += parseInt(finalClusters[i][j][k].duration);
                }
                driver = driver/finalClusters[i][j].length;
                truck = truck/finalClusters[i][j].length;
                route = route/finalClusters[i][j].length;
                stop = stop/finalClusters[i][j].length;
                items = items/finalClusters[i][j].length;
                duration = duration/finalClusters[i][j].length;
                microCentroids[i][j] = [driver,truck,route,stop,items,duration];
            }
        }
    }
}*/
/*function storeStopPredictions() {
    // From the final centroids, store the predicted stop duration for each object in the data
    for (i=0; i<userListData.length; i++) {
        var routeIndexes = [];  
        var stopIndexes = [];      
        for (j=0; j<centroids.length; j++) {
            routeIndexes[j] = Math.sqrt((Math.pow(centroids[j][0]-userListData[i].driver, 2)) +
                              (Math.pow(centroids[j][1]-userListData[i].truck, 2)) +
                              (Math.pow(centroids[j][2]-userListData[i].route, 2)) +
                              (Math.pow(centroids[j][3]-userListData[i].stop, 2)) +
                              (Math.pow(centroids[j][4]-userListData[i].items, 2)) +
                              (Math.pow(centroids[j][5]-userListData[i].duration, 2)));
        }
        var route = routeIndexes.indexOf(Math.min.apply(null,routeIndexes));
        for (j=0; j<microCentroids[route].length; j++) {
            stopIndexes[j] = Math.sqrt((Math.pow(microCentroids[route][j][0]-userListData[i].driver, 2)) +
                             (Math.pow(microCentroids[route][j][1]-userListData[i].truck, 2)) +
                             (Math.pow(microCentroids[route][j][2]-userListData[i].route, 2)) +
                             (Math.pow(microCentroids[route][j][3]-userListData[i].stop, 2)) +
                             (Math.pow(microCentroids[route][j][4]-userListData[i].items, 2)) +
                             (Math.pow(microCentroids[route][j][5]-userListData[i].duration, 2)));
        }
        var stop = stopIndexes.indexOf(Math.min.apply(null,stopIndexes));
        userListData[i].stopDuration = Math.round(microCentroids[route][stop][5]);            
    }
}*/
/*function randIndex(a,b) {
    // Calculate Rand Index of clusters
    var TP=0,TN=0,FP=0,FN=0;
    for (i=0; i<a.length; i++) {
        for (j=i+1; j<a.length) {
            if ((a[i]==a[j]) && (b[i]==b[j])) { TP++; }
            if ((a[i]!=a[j]) && (b[i]==b[j])) { TN++; }
            if ((a[i]==a[j]) && (b[i]!=b[j])) { FP++; }
            if ((a[i]!=a[j]) && (b[i]!=b[j])) { FN++; }
        }
    }    
    var RI = (TP+TN) / (TP+TN+FP+FN);
    alert("Rand Index = " + RI);
}*/
// Add User
//function addUser(event) {
//    event.preventDefault();
//    // Super basic validation - increase errorCount variable if any fields are blank
//    var errorCount = 0;
//    $('#addUser input').each(function (index, val) {
//        if ($(this).val() === '') {errorCount++;}
//    });
//    // Check and make sure errorCount's still at zero
//    if (errorCount === 0) {
//        // If it is, compile all user info into one object
//        var newUser = {
//            'data': $('#addUser fieldset input#inputData').val(),
//            'VehicleID': $('#addUser fieldset input#inputVehicle').val(),
//            'GeofenceID': $('#addUser fieldset input#inputGeofence').val(),
//            'GeofenceCategory': $('#addUser fieldset input#inputCategory').val(),
//            'ArrivalTimeNZ': $('#addUser fieldset input#inputArrival').val(),
//            'DepartureTimeNZ': $('#addUser fieldset input#inputDeparture').val(),
//            'DurationSeconds': $('#addUser fieldset input#inputDuration').val() 
//        }
//        // Use AJAX to post the object to our adduser service
//        $.ajax({
//            type: 'POST',
//            data: newUser,
//            url: '/users/adduser',
//            dataType: 'JSON'
//        }).done(function (response) {
//            // Check for successful (blank) response
//            if (response.msg === '') {
//                // Clear the form inputs
//                $('#addUser fieldset input').val('');
//                // Update the table
//                populateTable();
//            }
//            else {
//                // If something goes wrong, alert the error message that our service returned
//                alert('Error: ' + response.msg);
//            }
//        });
//    }
//    else {
//        // If errorCount is more than 0, error out
//        alert('Please fill in all fields');
//        return false;
//    }
//};
//// Delete User
//function deleteUser(event) {
//    event.preventDefault();
//    // Pop up a confirmation dialog
//    var confirmation = confirm('Are you sure you want to delete this user?');
//    // Check and make sure the user confirmed
//    if (confirmation === true) {
//        // If they did, do our delete
//        $.ajax({
//            type: 'DELETE',
//            url: '/users/deleteuser/' + $(this).attr('rel')
//        }).done(function (response) {
//            // Check for a successful (blank) response
//            if (response.msg === '') {
//            }
//            else {
//                alert('Error: ' + response.msg);
//            }
//            // Update the table
//            populateTable();
//        });
//    }
//    else {
//        // If they said no to the confirm, do nothing
//        return false;
//    }
//};