package skyline;
import java.util.TreeSet;
/**
* Klasse die het algoritme implementeert om een optimale stad te bouwen.
* Het is NIET toegelaten bestaande methodes en/of signaturen te wijzigen, maar
* het staat je vrij naar behoefte methodes en velden toe te voegen.
* @author Timbermont Bouke
**/
public class SkylineSolver{
private BuildingList list;
private double o,l;
private TreeSet<Skyline> set;
private int leftBorder,rightBorder;
private double orgineleVerhouding;
/**
* Creeert een nieuwe instantie van SkylineSolver met gegeven
* lijst van Buildings.
* @param list de Buildings die gebruikt moeten worden.
**/
public SkylineSolver(BuildingList list) {
this.list=list;
set=new TreeSet<Skyline>();
leftBorder=listToSkyline(list).coords[0];
rightBorder=listToSkyline(list).coords[listToSkyline(list).coords.length-2];
}
/**
* Geeft een lijst van optimale Skylines terug.
* @param o Vrij in te stellen parameter O uit de opgave
* @param l Vrij in te stellen parameter L uit de opgave
* @param x Maximaal aantal verschuivingen
**/
public TreeSet<Skyline> getOptimalSkylines(double o, double l, int x) {
this.o=o;
this.l=l;
orgineleVerhouding=verhouding(listToSkyline(list));
System.out.println("org verh: "+orgineleVerhouding);
addAllTransformations(x);
TreeSet<Skyline> newSet=new TreeSet<Skyline>();
for(Skyline s : set)if(verhouding(s)>orgineleVerhouding)newSet.add(s);
return newSet;
}
/*Deze methode voegt in onze treeset alle verschillende skylines in op
*recursieve wijze. Wanneer een skyline reeds is toegevoegd of buiten de
*stadsgrenzen valt, wordt de methode niet verder opgeroepen.
*/
private void addAllTransformations(int x){
boolean check=set.add(listToSkyline(list));
if(check&&x!=0){
for(int i=0;i<list.size();i++){
if(list.getBuilding(i).getLeft()-1>=leftBorder){
list.getBuilding(i).moveToLeft();
addAllTransformations(x-1);
list.getBuilding(i).moveToRight();
}
if(list.getBuilding(i).getRight()+1<=rightBorder){
list.getBuilding(i).moveToRight();
addAllTransformations(x-1);
list.getBuilding(i).moveToLeft();
}
}
}
}
/*De volgende methode neemt een skyline en berekent ervan de verhouding
*die aangeeft in hoeverre die skyline ideaal is.
*/
public double verhouding(Skyline s){
double teller=s.getSurface()-Math.min((double)s.getSurface(),o);
double len=s.coords[s.coords.length-2]-s.coords[0];
double noemer=1+len-Math.min(len,l);
return teller/noemer;
}
/*De volgende mthode neemt een buildinglist en maakt er een skyline van op
*recursieve wijze.
*/
public static Skyline listToSkyline(BuildingList list){
if(list.size()>1){
BuildingList[] halflist=new BuildingList[2];
halflist[0]=new BuildingList();
halflist[1]=new BuildingList();
int i=0;
for(Building building:list){
halflist[i%2].addBuilding(building);
i++;
}
return Skyline.merge(listToSkyline(halflist[0]),listToSkyline(halflist[1]));
}else{
return new Skyline(list.getBuilding(0));
}
}
}