package trafficjams.model.factories;
import trafficjams.model.Numbers;
import trafficjams.model.classes.*;
import trafficjams.model.interfaces.ICrossRoad;
import trafficjams.model.interfaces.IElementPosition;
import trafficjams.model.interfaces.IRoad;
import trafficjams.model.interfaces.IVehicle;
import trafficjams.model.registers.RoadMap;
import trafficjams.model.registers.VehicleRegister;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
/**
* Created by IntelliJ IDEA.
* User: Администратор
* Date: 17.11.11
* Time: 22:07
* To change this template use File | Settings | File Templates.
*/
public class VehicleRegisterFactory {
static {
instance = new VehicleRegisterFactory();
}
private static VehicleRegisterFactory instance;
public static VehicleRegisterFactory getInstance() {
return instance;
}
private VehicleRegisterFactory(){}
public VehicleRegister makeVehicles(RoadMap map, int vehiclesCount) {
VehicleRegister retVal = new VehicleRegister();
ArrayList<IVehicle> vehicles = new ArrayList<IVehicle>();
Auto auto = null;
Road elem = null;
RoadPosition pos = null;
for (int i = 0 ; i < vehiclesCount ; ++i){
auto = new Auto();
elem = this.makeElement(map);
pos = makePosition(map,vehicles,elem);
auto.setStartElement(elem);
auto.setStartPosition(pos);
auto.setStartCoord(pos.getCoord());//makeCoord(elem,pos));
auto.setCoord(auto.getStartCoord().copy());
auto.setCurrentElement((auto.getStartElement()));
auto.setCurrentPosition(auto.getStartPosition());
elem = this.makeElement(map);
pos = makePosition(map, vehicles, elem);
auto.setFinishElement(elem);
auto.setFinishPosition(pos);
auto.setFinishCoord(pos.getCoord());//makeCoord(elem, pos));
auto.setMaxSpeed(map.getMaxSpeed());
vehicles.add(auto);
}
this.registarte(map,vehicles);
try {
this.makeTrips(map,vehicles);
} catch (Exception e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}
retVal.setVehicles(vehicles);
return retVal;
}
private void makeTrips(RoadMap map, ArrayList<IVehicle> vehicles) throws Exception {
for (IVehicle v : vehicles){
Auto _v = (Auto) v;
ArrayList<ICrossRoad> tripAr = this.makeTrips(map,v.getStartPosition(), v.getFinishPosition());
/*
ArrayList<IRoad> ar = new ArrayList<IRoad>();
ar.add((IRoad)_v.getCurrentElement());
ar.add((IRoad)_v.getCurrentElement());
ar.add((IRoad)_v.getCurrentElement());
ar.add((IRoad)_v.getCurrentElement());
*/
Trip trip = new Trip(tripAr);
_v.setCurrentTrip(trip);
}
}
private ArrayList<ICrossRoad> makeTrips(RoadMap map, IElementPosition startPosition, IElementPosition finishPosition) throws Exception {
ICrossRoad firstCross = this.findFirstCross(startPosition);
if (firstCross==null){
throw new Exception("make trip exception 1");
}
ICrossRoad end = this.findFirstCross(startPosition);
//ICrossRoad preend = ((Road)finishPosition.getElement()).getOtherEnd(end);
ArrayList<ICrossRoad> retVal = null;
//CrossRoad cr = (CrossRoad) preend;
CrossRoad cr = (CrossRoad) end;
Road[] roads = (Road[]) cr.getRoads();
float minDist = 0 ;
ArrayList<ICrossRoad> temp = null;
for (int i = 0; i<4 ; ++i){
if (roads[i]==null){
continue;
}
if (roads[i].getOtherEnd(cr).equals(end)){
continue;
}
temp = new ArrayList<ICrossRoad>();
HashSet<ICrossRoad> hs = new HashSet<ICrossRoad>();
float len = this.makeBFS(temp,0,hs,roads[i].getOtherEnd(cr), firstCross);
if ((i==0 || minDist>len) && temp.size()!=0){
minDist = len;
retVal = temp;
}
}
if(retVal==null){
throw new Exception("make trip exception 2");
}
Collections.reverse(retVal);
//retVal.add(preend);
retVal.add(end);
return retVal;
}
private float makeBFS(ArrayList<ICrossRoad> temp, float len, HashSet<ICrossRoad> hs, ICrossRoad begin, ICrossRoad end) throws Exception {
float retVal = 0;
if (hs.contains(begin)){
temp.clear();
return -1;
}
if (begin.equals(end)){
return len;
}
temp.add(begin);
hs.add(begin);
Road[] roads = (Road[]) ((CrossRoad)begin).getRoads();
float minDist = Float.MAX_VALUE ;
for (IRoad r : roads){
if (r != null){
ArrayList<ICrossRoad> t_temp = (ArrayList<ICrossRoad>)temp.clone();
CrossRoad _cr = (CrossRoad)((Road) r).getOtherEnd(begin);
if (!hs.contains(_cr)){
float val = this.makeBFS(t_temp, len+((Road) r).getLength(),hs,_cr,end);
if (val<minDist){
minDist = val;
temp = t_temp;
}
}
}
}
return retVal;
}
private ICrossRoad findFirstCross(IElementPosition startPosition) {
float pos = ((Float) startPosition.getValue()).floatValue();
if (pos>=0){
return ((IRoad)startPosition.getElement()).getLCross();
}else{
return ((IRoad)startPosition.getElement()).getFCross();
}
}
private void registarte(RoadMap map, ArrayList<IVehicle> vehicles) {
for (IRoad r : map.getRoads()){
ArrayList<IVehicle> a1 = new ArrayList<IVehicle>();
ArrayList<IVehicle> a2 = new ArrayList<IVehicle>();
for (IVehicle v : vehicles){
if (v.getCurrentElement().equals(r)&& ((Float)v.getCurrentPosition().getValue()>=0)){
a1.add(v);
}
if (v.getCurrentElement().equals(r)&& ((Float)v.getCurrentPosition().getValue()<0)){
a2.add(v);
}
}
Road _r = (Road) r;
Collections.sort(a1, new Comparator<IVehicle>() {
public int compare(IVehicle o1, IVehicle o2) {
return Float.compare((Float)o1.getCurrentPosition().getValue(),(Float)o2.getCurrentPosition().getValue());
}
});
Collections.sort(a2, new Comparator<IVehicle>() {
public int compare(IVehicle o1, IVehicle o2) {
return Float.compare((Float)o2.getCurrentPosition().getValue(),(Float)o2.getCurrentPosition().getValue());
}
});
_r.getRoadQueueFtoL().addAll(a1);
_r.getRoadQueueLtoF().addAll(a2);
}
}
private RoadPosition makePosition(RoadMap map , ArrayList<IVehicle> vehicles , Road elem) {
RoadPosition retVal = null;
int j = 0 ;
do{
if (Math.random()>0.5){
retVal = new RoadPosition((float)Math.random()*elem.getLength(), elem);
}else{
retVal = new RoadPosition(-1.0f*(float)Math.random()*elem.getLength(), elem);
}
}while (checkPosition(map , vehicles, elem , retVal) && j++< Numbers.maxRandTry);
return retVal;
}
private boolean checkPosition(RoadMap map, ArrayList<IVehicle> vehicles , Road elem, RoadPosition retVal) {
for (IVehicle v : vehicles){
float p1 = ((Float)v.getStartPosition().getValue()).floatValue();
float p2 = ((Float)retVal.getValue()).floatValue();
if (v.getStartElement().equals(elem)
&& ((((Float)v.getStartPosition().getValue()).floatValue() - ((Float)retVal.getValue()).floatValue())
< map.getMinDist())){
return true;
}
}
return false;
}
private Road makeElement(RoadMap map) {
int j = 0 ;
Road ret = null;
while ((j++ < Numbers.maxRandTry)){
int i = j % map.getRoads().size();
ret = (Road) map.getRoads().get(i);
if ((ret != null ) && (Math.random()<Numbers.randElementPercent)){
return ret;
}
}
return ret;
}
}