/*
Een kaart van de wereld in ASTSP
Casper Eyckelhof Oktober 2000

Let op alle "hacks" om de index van 1..aantal te laten lopen!
*/
import java.util.*;
import java.lang.*;


public class Kaart
{
  //Constanten
  public final double tau_0 = 0.000001;
  
    
  private Vector stedenLijst; //lijst met steden
  private double[][] geurTabel;
  private double[][] afstandTabel;
  private boolean[] stadBestaat; //globale blacklist, steden met "false" hierin "bestaan niet"
  
  private double max_distance = 0; //maximale afstand tussen willekeurig 2 steden
  
  
  Kaart() {
     stedenLijst = new Vector();
     //Om de index van 1..aantal te laten lopen, ipv 0..aantal-1, een dummy
     stedenLijst.addElement(null);  
  }
  
  public void voegToe(Stad s){
     stedenLijst.addElement(s);     
  }
  
  public Stad get(int index){
     return (Stad) stedenLijst.elementAt(index); 
  }  
  
  //aantal steden in de lijst
  public int grootte(){
     return stedenLijst.size()-1;  
  }
  
  /*
    pre: alle steden zijn ingelezen, zodat we de maximale size van alle tabellen en lijsten weten
  */
  public void initTabellen(){
    Stad a,b;
    int aantal = this.grootte();
    double afstand;
    //afstandTabel
    afstandTabel = new double[aantal+1][aantal+1];
    for (int i = 1; i <= aantal; i++){
         a = (Stad) stedenLijst.elementAt(i);
         for (int j = 1; j <= aantal; j++){
           b = (Stad) stedenLijst.elementAt(j); 
           afstand = Math.sqrt( Math.abs(a.getX() - b.getX())*Math.abs(a.getX() - b.getX()) + Math.abs(a.getY() - b.getY())*Math.abs(a.getY() - b.getY()));
           afstandTabel[i][j] = afstand;
           if (afstand > max_distance) { max_distance = afstand; }
        }      
    }
    //blacklist
    //Alles bestaat default
    stadBestaat = new boolean[aantal+1];
    for (int i = 1; i <= aantal; i++){
       stadBestaat[i] = true;     
    }    
    //geurTabel, alles is eerst tau_0
    geurTabel = new double[aantal+1][aantal+1];
    for (int i = 1; i <= aantal; i++){
        for (int j = 1; j <= aantal; j++){
             geurTabel[i][j] = tau_0;
        }     
    }
         
  }
  /*
    Geeft de afstand tussen steden met index stad1 en stad2
  */
  public double afstand(int stad1, int stad2){
      return afstandTabel[stad1][stad2];           
  } 
  
  public void setAfstand(int stad1, int stad2, double afstand){
      afstandTabel[stad1][stad2] = afstand;
      afstandTabel[stad2][stad1] = afstand;
  }  
  
  
  public double geur(int stad1, int stad2){
      return geurTabel[stad1][stad2];  
  }
  
  //zet de geur tussen stad1 en stad2 op een nieuwe waarde
  public void setGeur(int stad1, int stad2, double geurwaarde){
      geurTabel[stad1][stad2] = geurwaarde; 
  }   
  
  
  //regelt een "nettere" geurverdeling. Een soort dempingsfilter. 
  public void schud(){
  	  int aantal = this.grootte();
  	  double correctie = 1 - Math.log(tau_0);
  	  for (int i = 1; i <= aantal; i++){
        for (int j = 1; j <= aantal; j++){
             geurTabel[i][j] = tau_0 * (Math.log(geurTabel[i][j])+correctie);
        }     
    }
  }	
  
  //Zie schud(), maar dan niet op de hele kaart, maar op een bepaald gebied rond 2 plaatsen
  // a en b zijn de plaatsen, p is schudpercentage
  public void schudlokaal(int a, int b, double p){
  	  int aantal = this.grootte();
  	  double range = max_distance * (p / 100); //the range in which the normalisation will take place
  	  //System.out.println("max_distance , p,  range zijn: " + max_distance + " , " + p + " , " +range);
  	  double correctie = 1 - Math.log(tau_0);
  	  for (int i = 1; i <= aantal; i++){
        for (int j = 1; j <= aantal; j++){	
          if ( (afstand(a,i) < range) || (afstand(b,i) < range) || (afstand(a,j) < range) || (afstand(b,j) < range)  )
          {	
             geurTabel[i][j] = tau_0 * (Math.log(geurTabel[i][j])+correctie);
            // System.out.println("Correctie tussen "+i+" en "+j);
          }  
        }     
    }
  }	


  //Zet alle geursporen weer op uitgangsniveau (Tau_0)
  public void reset(){
  	 int aantal = this.grootte();
  	 for (int i = 1; i <= aantal; i++){
        for (int j = 1; j <= aantal; j++){
             geurTabel[i][j] = tau_0;
        }     
    }
  } 	


}