package graphe; import java.io.*; import java.lang.*; import java.util.Calendar; import java.util.*; import javax.swing.*; /** *Classe ThreadCandidat. *Cette classe hérite de tous les attributs et méthodes de ThreadSommet, *les élections en plus. *@author Estelle Colin, Thomas Peclier, Fabrice Berna @ IUP GMI *@see Graphe, Application, ThreadSommet *@version 1.0 */ public final class ColorationDistribuee extends ElectionDistribuee { /*----------------------------- Variables -----------------------------*/ /** *Nombre de couleurs de la coloration */ private int nbCouleurs; /** *Nombre de couleurs de la coloration */ private int nbRepAtt; /** * numéro de la couleur que j'ai choisie, -1 sinon */ private int maCouleur = -1; /** * Tableau de taille le nombre de couleurs (nbCouleurs). * Permet de connaître les couleurs occupées par mes voisins déjà coloriés * ainsi que les couleurs que j'ai déjà tentées d'utiliser, sans succès */ private boolean couleursLibres[]; /** * Tableau de taille le nombre de voisins (nbvoisins), * permet d'associer chacun de mes voisins déjà colorié à sa couleur */ private int couleursVoisins[]; /** * Utilisé pour interpréter les message */ private StringTokenizer strToken; /** * Le message reçu */ private String message; /** * L'initiateur du message */ private int initiateurId; /** * Etat du sommet */ public String etat; /** * Nombre de coloration effectuées */ private int nbColoration; /** * Tableau du nombre de couleurs reçues par chaque voisin */ private int nbCouleurReçues[]; /*----------------------------- Accesseurs -----------------------------*/ /** * Accesseur sur la couleur * @return int, la couleur du sommet */ public final int getCouleur() { return maCouleur; } /** * Setter nbCouleurs */ public final void setNbCouleurs(int k) { nbCouleurs = k; couleursLibres = new boolean[nbCouleurs]; for (int j = 0; j < nbCouleurs; j++) { couleursLibres[j] = true; } } /** * Getter de la durée d'un traitement * @return long */ public final int getDuree() { return (niveau); } /*----------------------------- Méthodes -----------------------------*/ /** * Constructeur * * - sauve le nombre de couleurs de la k-coloration * - initialise les couleurs de tous mes voisins à -1 * - initialise toutes les couleurs libres à oui * * @param int, mon identifiant * @param int, le nombre de sommets dans le graphe * @param boolean[], la liste de mes voisins et de mes non voisins * @param int, le nombre de couleur de la k-coloration */ public ColorationDistribuee(int i, int nb, boolean[] v, JTextArea out) { super(i, nb, v, out); etat = ""; nbColoration = 0; couleursVoisins = new int[nbvoisins]; nbCouleurReçues = new int[nbvoisins]; for (int j = 0; j < nbvoisins; j++) { couleursVoisins[j] = -1; nbCouleurReçues[j] = 0; } } /** * Méthode de choix d'une couleur: * @return int, le numéro de la couleur choisie, -1 s'il n'y en a plus */ private final int choisirCouleur() { int i = 0; while ((i < nbCouleurs) && (!couleursLibres[i])) { i++; } if (i == nbCouleurs) { return -1; } else { couleursLibres[i] = false; return i; } } /** * Méthodes permettant de se colorer et de transmettre sa couleur à ses fils * * Choix de la couleur * Si je n'ai pas trouvé de couleur Alors * J'envoie un message d'erreur à mon père * Sinon * Si je n'ai plus de fils Alors j'envoie OK à tous mes voisins colorés * Sinon Je diffuse ma couleur à mes fils * * @throws IOException */ final void lancerColoration() throws IOException { nbColoration++; maCouleur = choisirCouleur(); if (maCouleur == -1) { etat = "pasColore"; ecrit(voisins[pere], "Erreur " + niveau); } else { //Pour voir la coloration try { sleep(1000); } catch (Exception e) { } if (nbvoisins == 0) { println( "##### " + id + " : Je suis élu Pour le niveau " + niveau + " (pas de voisin) #####"); etat = "colore"; cancel(); } else { if (nbFils == 0) { etat = "colore"; envoiATousMesPeres("Ok"); } else { envoiATousMesFils("Couleur " + maCouleur + " " + (niveau + 1)); nbRepAtt = nbFils; } } } } /** * Effectue les traitements afférents à la réception d'une couleur * * Si mon niveau est supérieur au niveau reçu Alors * J'ai déjà participé à un processus d'élection * Je sauve la couleur reçue * * Sinon * Si je n'ai pas déjà reçu de couleur du sommet Alors Je lance la candidature * Sinon (j'ai déjà reçu sa couleur) Si le voisin en question est mon père Alors je lance une coloration (car je sais que je serai l'élu) * * * @param int, la couleur reçue * @param int, le numéro du voisin qui m'a envoyé sa couleur * @param int, le niveau de la coloration * @throws IOException */ final void sur_Reception_Couleur(int c, int j, int niv) throws IOException { //System.out.println(id + " -> " + messageAIgnorer[j]); if (c == couleursVoisins[j]) return; /* if (messageAIgnorer[j] > 0) { System.out.println(id + " -> a évité une deuxième réception de " + voisinsId[j] + " ... " + messageAIgnorer[j]); messageAIgnorer[j] --; return; } */ niveau = niv; //Si je n'ai pas déjà reçu de couleur du sommet if (couleursVoisins[j] == -1) { //on sauve le canal. Peut-etre mon père??? actualiserCouleurs(j, c); tmpPere = voisinsId[j]; candidature(voisinsId[j], c); } else { actualiserCouleurs(j, c); //Si le sommet est mon père et que je reçoit une nouvelle couleur, // je peux relancer une coloration, sinon, je sauve sa couleur if (voisinsId[j] == pere) { lancerColoration(); } } } /** * Effectue les traitements afférents à une réception de message Erreur (un de mes fils n'a pas réussi à se colorer) * * - Réinitialise le niveau de traitement * - Recommence une coloration * @param int, le niveau de l'erreur * @throws IOException */ private final void sur_Reception_Erreur(int niv) throws IOException { if (pere == id) { println(id + " -> Coloration en " + nbCouleurs + "-couleurs Ratée"); } else { niveau = niv; lancerColoration(); } } /** * Effectue les traitements afférents à une réception de message Ok (un de mes fils a réussi à se colorer) * * Décrémente le nombre de réponse attendues * Si j'ai reçu toutes les réponses attendues, j'envoie à tous mes pères le signal que j'ai réussi à me colorer et * que tous mes fils sont bien colorés * @throws IOException */ private final void sur_Reception_Ok() throws IOException { nbRepAtt--; if (nbRepAtt == 0) { etat = "colore"; //Je suis le premier sommet, je peux dire que la coloration a réussi if (pere == id) { println("Coloration en " + nbCouleurs + "-couleurs Réussie " + id); } else { envoiATousMesPeres("Ok"); } } } /** * Actualise : * - le tableau des couleurs libres en fonction de toutes les couleurs des voisins * - le nombre de fils : nombre de voisins total moins voisins colorés * @param int, le numéro du voisin qui m'a envoyé sa couleur * @param int, la couleur reçue */ private final void actualiserCouleurs(int k, int c) { couleursVoisins[k] = c; for (int j = 0; j < nbCouleurs; j++) { couleursLibres[j] = true; } nbFils = nbvoisins; for (int i = 0; i < nbvoisins; i++) { if (couleursVoisins[i] != -1) { couleursLibres[couleursVoisins[i]] = false; nbFils--; } } } /** * Méthode d'interprétation des messages reçus * * - Acquittement * - Candidat * - Couleur * - Ok * - Erreur * * @param String, le message à interpréter * @param i, le numéro du voisin qui m'a envoyé ce message * @throws IOException */ public final void interprete(String s, int i) throws IOException { strToken = new StringTokenizer(s); message = strToken.nextToken(); if (message.equals("Acquittement")) { initiateurId = Integer.parseInt(strToken.nextToken()); sur_Reception_de_Acquittement(initiateurId); } else if (message.equals("Candidat")) { initiateurId = Integer.parseInt(strToken.nextToken()); int nbFilsReçu = Integer.parseInt(strToken.nextToken()); int nivReçu = Integer.parseInt(strToken.nextToken()); int init = Integer.parseInt(strToken.nextToken()); int couleurReçue = Integer.parseInt(strToken.nextToken()); sur_Reception_de_Candidat( i, initiateurId, nbFilsReçu, nivReçu, init, couleurReçue); } else if (message.equals("Couleur")) { int couleurReçue = Integer.parseInt(strToken.nextToken()); int nivReçu = Integer.parseInt(strToken.nextToken()); sur_Reception_Couleur(couleurReçue, i, nivReçu); } else if (message.equals("Ok")) { sur_Reception_Ok(); } else if (message.equals("Erreur")) { int nivReçu = Integer.parseInt(strToken.nextToken()); sur_Reception_Erreur(nivReçu); } } /** * Transfere un message à tous mes pères * * un père est un voisin coloré * * @param String, le message à envoyer * @throws IOException */ final void envoiATousMesPeres(String s) throws IOException { for (int i = 0; i < nbvoisins; i++) { if (couleursVoisins[i] != -1) ecrit(i, s); } } /** * Transfere un message à tous mes fils * * un fils est un voisin non coloré * * @param String, le message à envoyer * @throws IOException */ final void envoiATousMesFils(String s) throws IOException { for (int i = 0; i < nbvoisins; i++) { if (couleursVoisins[i] == -1) ecrit(i, s); } } /** * Transfere un message à tous mes fils sauf mon père * * un fils est un voisin non coloré * * @param String, le message à envoyer * @param int, le canal pour joindre mon père * @throws IOException */ final void envoiATousMesFilsSaufMonPere(String s, int monPere) throws IOException { for (int i = 0; i < nbvoisins; i++) { if ((i != monPere) && (couleursVoisins[i] == -1)) { //on transmet le message à tous nos voisins participant à l'élection sauf exp ecrit(i, s); } } } /** * affichage de l'état du sommet */ public final void etat() { println( id + " | " + nbvoisins + " voisins | chef " + max + " | Couleur " + maCouleur); } }