package ri;

import java.util.Collection;
import java.util.Map;

import org.graphstream.algorithm.Toolkit;
import org.graphstream.graph.Graph;
import org.graphstream.graph.Node;
import org.graphstream.stream.file.FileSourceEdge;

import ri.scenario.Scenario1;
import ri.utils.GraphUtils;

/**
 * @author Yoann Eichelberger
 */
public class Propagation {

    public static void main(String[] args) {
        Graph g = GraphUtils.readResource("DBLP", "com-dblp.ungraph.txt", new FileSourceEdge());
        double averageDegree = Toolkit.averageDegree(g);

        // Un individu envoie en moyenne un mail par semaine à chacun de ses
        // collaborateurs.
        float beta = 1F / 7;
        // Un individu met à jour son anti-virus en moyenne deux fois par mois.
        // Cela nettoie son système mais ne le protège pas de nouvelles infections car
        // le virus mute.
        float mu = 1F / 14;
        double kCarre = degreeVariance(g);
        float lambda = tauxDePropagation(beta, mu);
        float lambdaC = seuilEpidemique(g);
        System.out.println("<k²>=" + kCarre);
        System.out.println("λ=" + lambda);
        System.out.println("λc=" + lambdaC);

        // Si λ > λc la maladie persiste
        // Si λ < λc la maladie disparaît
        System.out.println("Maladie " + (lambda > lambdaC ? "persiste" : "disparait"));

        // Comparez avec le seuil théorique d'un réseau aléatoire du même degré moyen.
        // <k²> = Somme(k²_pk)
        // "pk = 1 / N" dans notre modèle car la probabilité est la même pour chaque
        // personne.
        float lambdaCRdm = seuilEpidemiqueAleatoire(averageDegree);
        System.out.println("RDM λc=" + lambdaCRdm);

        // RDM λc > λc donc RDM λc a plus de chance de faire disparaitre la maladie pour
        // un λ donné.

        Node source = Toolkit.randomNode(g);
        Scenario1 s1 = new Scenario1(g, 1F / 7, 1F / 14);
        Map<Integer, Collection<Node>> p = s1.propagation(84);
        int sum = 0;
        for (Collection<Node> c : p.values())
            sum += c.size();
        System.out.println(g.getNodeCount());
        System.out.println(sum);
        System.out.println(sum / (double) g.getNodeCount());

        /*
317080
17425648
54.95662924183171

317080
18072356
56.99620285101552

317080
18205360
57.415667970228334

317080
18345867
57.85879588747319
         */

        /*
         * Graph g2 = GraphUtils.randomGen(100, 2); g2.addAttribute("ui.stylesheet",
         * "url(g2.css)"); Node source = Toolkit.randomNode(g2);
         * source.addAttribute("ui.style", "fill-color: green;"); propagation(source,
         * 100, 1F / 7, 1F / 14); for (Node n : g2) { if (n != source &&
         * n.hasAttribute(I)) { n.addAttribute("ui.style", "fill-color: red;"); } }
         * g2.display();
         */
    }

    public static float tauxDePropagation(float beta, float mu) {
        return beta / mu;
    }

    public static double degreeVariance(Graph g) {
        int sum = 0;
        for (Node n : g)
            sum += Math.pow(n.getDegree(), 2);
        return sum / (double) g.getNodeCount();
    }

    public static float seuilEpidemique(Graph g) {
        return (float) (Toolkit.averageDegree(g) / degreeVariance(g));
    }

    public static float seuilEpidemiqueAleatoire(double averageDegree) {
        return (float) (1 / (averageDegree + 1));
    }
}