Source: Community_EntropyBased.js

var minCom = Infinity;

/**
 * This function calculates a measure to determine the degree of visual overlap between the communities.
 * The area considered  around a specific node is a square and determined by the
 * filerArea. If this region contains nodes from only one community, the entropy value is 0, which means that the community
 * structure is represented perfectly. If the region contains an equal mixture of all communities, the entropy value reaches
 * a maximum, meaning that the community structure is not represented at all. This value is calculated for each node of the graph.
 * For every node the entropy is starting at 0.
 * @param {number} N Amount of nodes in the graph
 * @param {number} M Amount of communities in the graph
 * @param {Array} C Amount of nodes in a specific community
 * @param {Array} nodes contains the nodes of the original graph
 * @param {number} filterArea is the size of the area around the node
 * @return {Array} array of objects, H[0] contains the global value, H[i != 0] contains local values for all other nodes.
 */
function Community_EntropyBased(N, M, C, nodes, filterArea)
{
    //Global Visual Overlap Metric
    var H_global = entropyMetric(M,percentage(N,C));
    // Array of local Visual Overlap Metrics (defined by the size of the filter)
    var H_local = localFilter(nodes, filterArea);

    H_local[0] = {
        x: 0,
        y: 0,
        comDistr: minCom//H_global
    }

    console.log(H_local)

    return H_local;


    /**
     * This function calculates the percentage P(c) of nodes from community c
     * @param {number} totalNodes Total Amount of Nodes (relativ to the Area)
     * @param {Array} communityAmount Array of communities and the amount of nodes in them
     * @returns {Array} result contains the percentage of nodes for each community
     */
    function percentage(totalNodes,communityAmount) {
        var result = [];

        communityAmount.forEach(function (amount, community) {
            result[community] = (amount/totalNodes);
        });

        return result;
    }

    /**
     * This function calculates the visual overlap metric
     * @param {number} communityCount Number of communities
     * @param {Array} percentage percentage P(c) of nodes from community c
     * @returns {number} result contains the average value of the visual overlap for the whole graph
     */
    function entropyMetric(communityCount,percentage) {
        var result = 0;

        for (var i = 0; i < communityCount; i++) {

            result = result + (percentage[i] * (Math.log(percentage[i])/Math.log(2)));
            result = result * -1;
        }

        return result;
    }

    /**
     * This function calculates the metric on the graph with a defined filter size (area at a specific node)
     * @param {Array} nodes contains all nodes with different attributes
     * @param {number} filterArea is the size of the square area around every node
     * @returns {Array} H is an array containing the metric's result for every node of the graph
     */
    function localFilter(nodes, filterArea) {

        var region = filterArea;
        //Array of Arrays
        var communityAmount = [];
        var H = [];
        var i = 0;


        for (var node in nodes)
        {
            i = i+1;

            var nodesInsideRegion = [];

            for (var n in nodes) {

                if ((nodes[n].x <= nodes[node].x + region) && (nodes[n].x >= nodes[node].x - region)
                    && (nodes[n].y <= nodes[node].y + region) && (nodes[n].y >= nodes[node].y - region)) {

                    nodesInsideRegion.push(nodes[n]);
                }
            }

            communityAmount = countNodesInCommunities(nodesInsideRegion);
            var p = localPercentage(communityAmount);

            if(entropyMetric(communityAmount[0].length,p[1]) < minCom)
            {
                minCom = entropyMetric(communityAmount[0].length,p[1]);
            }

            H[i] = {
                x: nodes[node].x,
                y: nodes[node].y,
                comDistr: entropyMetric(communityAmount[0].length,p[1])
            };
        }

        return H;
    }


    /**
     * This function returns the communities and the amount of nodes in the particular communities
     * @param {Array} nodes contains all nodes of the graph
     * @returns {Array} returns an array containing for every community the amount of nodes
     */
    function countNodesInCommunities(nodes) {

        //2D Array [Community, Amount of Nodes]
        var communities = [];
        var nodesInCommunities = [];
        for (var n in nodes)
        {
            if(!communities.includes(nodes[n].module)){
                communities.push(nodes[n].module);
                nodesInCommunities.push(1);
            }
            else{
                var pos = communities.indexOf(nodes[n].module);
                nodesInCommunities[pos]= nodesInCommunities[pos] +1;
            }
        }

        return [communities, nodesInCommunities];
    }


    /**
     * This function calculates the local percentage P(c) of nodes from community c
     * @param {Array} communityAmount is an array of arrays for communities and the amount of nodes in them [[communities], [nodesInCommunities]]
     * @returns {Array} returns an array of arrays which contains for every community an percentage
     */
    function localPercentage(communityAmount) {
        var percent = [];
        var totalNodes = 0;

        // Calculate total amount of nodes
        communityAmount[1].forEach(function (nodes) {
            totalNodes = totalNodes +  nodes;
        });

        for(var i = 0; i < communityAmount[0].length; i++){
            percent.push ((communityAmount[1][i]/totalNodes));
        }

        return [communityAmount[0], percent];
    }

}