package route;
import game_timer.GameTimer;
import game_timer.TimerNotify;
import java.util.ArrayList;
import map.Map;
import misc.carType;
import vehicles.RobberyCar;
import vehicles.Vehicle;
import _main.Game;
import bunny.Bunny;
import cross.Cross;
/**
* Az utat reprezent�l� oszt�ly. Ir�ny�tottak, egyir�ny�ak, keresztez�d�st�l keresztez�d�sig tart.
* � felel�s a rajta halad� aut�k megfelel� mozgat�s��rt �s a rajta t�rt�nt esetleges �tk�z�s felismer�s��rt.
* A Map oszt�ly hozza l�tre �t.
*
*/
public class Route implements TimerNotify {
private Map m;
private Cross startCross;
private Cross endCross;
private int length;
private ArrayList<Vehicle> vehicles = new ArrayList<Vehicle>();
// [DOC] vehiclesAtCross nincs a doksiban. Itt azt taroljuk, hogy kik azok, akik az ut vegere ertek
private ArrayList<Vehicle> vehiclesAtCross = new ArrayList<Vehicle>();
private Bunny bunny;
/**
* Az �t default konstrukora.
*/
public Route(){
GameTimer.getInstance().registObserver(this);
}
/**
* A route parameterezett konstruktora
* @param m A palya, ami az adott utat tartalmazza
* @param startCross A kiidulasi keresztezodes
* @param endCross A vegen, a keresztezodes
* @param length Az ut hossza[minimum az autok maximalis sebessegenek ketszerese + 1]
*/
public Route(Map m, Cross startCross, Cross endCross, int length){
GameTimer.getInstance().registObserver(this);
this.m = m;
this.startCross = startCross;
this.endCross = endCross;
this.length = length;
}
/**
* V�gign�zi, milyen aut�k vannak az �ton, �s a megfelel� m�don l�pteti �ket,
* aut�k positionj�t, �s currentSpeedj�t �ll�tjuk.
* K�zben megk�rdezi, hogy a k�t aut� utol�rte-e egym�st,
* �s ennek tudat�ban h�vja meg a megfelel� met�dusokat.
*
* A k�rd�sn�l csak "i" vagy "n" bemenetet fogad el, m�s bemenet eset�n �jb�l k�rdez.
*/
public void moveCars() {
//itt meg meg kellene vizsgalni, hogy az ut vegere ert-e
//eloszor is nezzuk meg, hogy elert-e valamelyik auto a keresztezodesig
if(vehicles.size() > 0){
for(int i = 0; i < vehicles.size(); i++){
Vehicle car = vehicles.get(i);
int currSpd = car.getCurrentSpeed();
int currPos = car.getPosition();
if((currPos + currSpd) > (length - vehiclesAtCross.size())){
if(car.getCarType() == carType.Robbery && i == 0){
//ha az ut vegere ert es mar belepne a keresztezodesbe, akkor berakjuk es eltavolitjuk az utrol
car.getCross().addVehicleToCross(car);
vehicles.remove(car);
} else if(car.getCarType() == carType.Robbery && vehiclesAtCross.size() > 0){
//mar belepett volna a keresztezodesbe, de voltak elotte
Game.getInstance().finishGame();
} else {
//hogyha a vegere ert[a hosszbol levonjuk a keresztezodesnel varakozokat]
//beallitjuk a keresztezodes elotti sorba,
//majd a mozgo autok tombjebol kiszedjuk
//es berakjuk a keresztezodes elott varakozoekba(0 sebeseggel)
car.setPosition(length - vehiclesAtCross.size());
car.setCurrentSpeed(0);
vehiclesAtCross.add(car);
vehicles.remove(car);
}
}
//TODO: [PROG] hogyha forditva halad a rablo az uton, akkor is vizsgalni, hogy 0-hoz ert-e
//ha megfordult es mondjuk, a kovetkezo lepesnel mar 0-nal jar
if(car.getCarType() == carType.Robbery){
if(currPos + currSpd < 0){
startCross.addVehicleToCross(car);
vehicles.remove(car);
}
}
}
}
//itt fogjuk lassitani, gyorsitani az autokat, akik meg "mozognak"
if(vehicles.size() > 1){
for(int i = 0; i < vehicles.size()-1; i++){
Vehicle leader_car = vehicles.get(i);//az az auto ami elorebb halad
Vehicle follower_car = vehicles.get(i+1);//az az auto, ami mogotte halad
//lekerdezzuk a poziciokat
int leader_pos = leader_car.getPosition();
int follower_pos = follower_car.getPosition();
//lekerdezzuk a sebessegeket, amivel mennek
int leader_currentSpd = leader_car.getCurrentSpeed();
int follower_currentSpd = follower_car.getCurrentSpeed();
//hogyha ezzel a sebesseggel, a kovetkezo lepesnel utolerne, akkor lassitsuk le
if(follower_car.getCarType() != carType.Robbery){
//ha a followerCar nem robbery, akkor lassitsuk le
if(follower_pos + follower_currentSpd >= leader_pos + leader_currentSpd){
follower_car.setCurrentSpeed(leader_currentSpd);
} else {
//ha nem erte utol, akkor probaljon meg a rendes sebessegevel haldani
int original_speed = follower_car.getSpeed();
if(follower_pos + original_speed < leader_pos + leader_currentSpd){
follower_car.setCurrentSpeed(original_speed);
}
}
}
}
}
//autok leptetese, itt mar csak azok maradnak es olyan sebeseggel, ami jo. :)
if(vehicles.size() > 0){
//vegigmegyunk az autokon es beallitjuk nekik a kovetkezo poziciojukat
for(int i = 0; i < vehicles.size(); i++){
Vehicle car = vehicles.get(i);
//uj poz = aktualis poz + lepesi tavolsag
int new_pos = car.getPosition() + car.getCurrentSpeed();
car.setPosition(new_pos);
}
}
}
/**
* v�gign�zi az �ton tal�lhat� Vehicle-�ket,
* hogy �tk�ztek-e, mivel � l�pteti �ket.
*
* A program megk�rdezi a felhaszn�l�t�l, hogy szeretn�-e, hogy legyen �tk�z�s, �s
* ezalapj�n alakul majd ez a teszteset.
*
* A k�rd�sn�l csak "i" vagy "n" bemenetet fogad el, m�s bemenet eset�n �jb�l k�rdez.
*/
public void collisionDetect() {
//megvizsgaljuk, hogy elutotte-e a nyulat a rablo
RobberyCar rcar = m.getRobberyCar();
if(bunny != null && rcar.getRoute() == this){
if(rcar.getTurned()){
if((rcar.getPosition() <= bunny.getPos()) && (rcar.getPosition() + rcar.getCurrentSpeed() >= Bunny.get().getPos())){
rcar.setImmune(true);
rcar.setImmuneTime(Bunny.get().getImmuneTime());
bunny.setHit();
}
} else {
if((rcar.getPosition() >= bunny.getPos()) && (rcar.getPosition() + rcar.getCurrentSpeed() <= bunny.getPos())){
rcar.setImmune(true);
rcar.setImmuneTime(bunny.getImmuneTime());
bunny.setHit();
}
}
}
//itt csak azt kell vizsgalni, hogy a rablo utkozott-e masik autoval, mivel a tobbi auto
//keruli az utkozest -> csak a rablo utkozhet
if(vehicles.size() > 1){
for(int i = 0; i < vehicles.size()-1; i++){
Vehicle leader_car = vehicles.get(i);//az az auto ami elorebb halad
Vehicle follower_car = vehicles.get(i+1);//az az auto, ami mogotte halad
//lekerdezzuk a poziciokat
int leader_pos = leader_car.getPosition();
int follower_pos = follower_car.getPosition();
//amolyan debug esetre
if(leader_pos == follower_pos){
if(leader_car.getCarType() == carType.Robbery || follower_car.getCarType() == carType.Robbery){
Game.getInstance().finishGame();
}
}
//lekerdezzuk a sebessegeket, amivel mennek
int follower_currentSpd = follower_car.getCurrentSpeed();
int leader_currentSpd = leader_car.getCurrentSpeed();
//megvizsgaljuk, hogy a rablo utkozne-e az elotte haladoval[follower = robbery, leader=otherCar]
if(follower_car.getCarType() == carType.Robbery){
//ha a rablo olyan sebeseggel halad, hogy a kovetkezo pozicioja annyi lenne
//mint az elotte halado autoe vagy attol nagyobb, akkor bizony utkozott es vege a jateknak
if(follower_pos + follower_currentSpd >= leader_pos + leader_currentSpd)
Game.getInstance().finishGame();
}
//megvizsgaljuk, hogyha a rablo forditva halad, akkor a "mogotte levobe" belemenne-e[follower = otherCar, leader = robbery, direction = false(hatrafele megy)]
if(leader_car.getCarType() == carType.Robbery){
//ha visszafele halad, akkor a sebessege negativ(tehat pl -90)
if(leader_pos + leader_currentSpd <= follower_pos + follower_currentSpd){
Game.getInstance().finishGame();
break;
}
}
if(follower_car.getCarType() == carType.Police && leader_car.getCarType() == carType.Robbery){
if(follower_pos + follower_currentSpd >= leader_pos + leader_currentSpd && !((RobberyCar)leader_car).getImmune()){
Game.getInstance().finishGame();
}
}
}
}
}
//[DOC] nincs ilyen metodus, dokumentalni!
/**
* Visszaadja a referenciat a keresztezodesnel, legelol allo autorol, de nem tavolitja azt el, az utrol.
* A metodus, csak informaciszerzes celjabol hasznalando!
*/
public Vehicle getLastCar(){
//ha vannak a keresztezodesnel, akkor adjuk vissza
if(vehiclesAtCross.size() > 0){
return vehiclesAtCross.get(0);
} else {
//ha viszont nincsenek, akkor adjunk vissza egy null-t
return null;
}
}
/**
* A Cross ezt h�vja meg, ha egy aut�t beh�v a keresztez�d�sbe: leszedi az �tr�l az aut�t, majd visszat�r a leszedett aut� �rt�k�vel.
* Ha ures a tomb, akkor null-t ad vissza!
*/
public Vehicle getAndRemoveLastCar() {
//ha van valaki a keresztezodesnel
if(vehiclesAtCross.size() > 0 ){
//get and remove last car
Vehicle removed_car = vehiclesAtCross.get(0);
vehiclesAtCross.remove(0);
//ha azon a valakin kivul meg mas is van a keresztezodesnel
//akkor egyel elorebb tokjuk oket
if(vehiclesAtCross.size() > 1){
for(int i = 1; i < vehiclesAtCross.size(); i++){
//lekerdezzuk, megnoveljuk,beallitjuk a poziciot
int current_pos = vehiclesAtCross.get(i).getPosition();
current_pos++;
vehiclesAtCross.get(i).setPosition(current_pos);
}
}
//visszaadjuk a kivett autot
return removed_car;
} else{
//ha nincs senki a keresztezodesben, akkor adjunk vissza null-t
return null;
}
}
/**
* Autot tesz az utra es bellitja neki az aktualis parametereket
* @param v aut�
*/
public void addVehicle(Vehicle v) {
if(v.getCarType() == carType.Robbery && v.getCross() == endCross ){
vehicles.add(0, v);
//ezen az uton halad
v.setRoute(this);
//e fele a keresztezodes fele
v.setCross(startCross);
//bepakoljuk az ut vegere
v.setPosition(length);
//probaljon meg olyan sebesseggel haladni "amilyennel szerene"
v.setCurrentSpeed(-1 * v.getSpeed());
// RobberyCar rcar = (RobberyCar)v;
// if(rcar.getTurned()){
// rcar.turn();
// } else {
// //hax... igy tuti jok lesznek a sebesseg elojelek, meg ilyesmik
// rcar.turn();
// rcar.turn();
// }
} else {
vehicles.add(v);
//ezen az uton halad
v.setRoute(this);
//e fele a keresztezodes fele
v.setCross(endCross);
//most kezdett az uton haladni
v.setPosition(0);
//probaljon meg olyan sebesseggel haladni "amilyennel szerene"
v.setCurrentSpeed(v.getSpeed());
}
}
/**
* Autot tesz az utra es bellitja neki az aktualis parametereket
* @param v aut�
*/
public void addVehicle(Vehicle v, int pos) {
if(pos < 0 || pos > length){
System.out.println("Hiba! Az autot olyan poziciora akartad rakni, amire nem lehetseges!");
return;
}
int insertWhere = 0;
//a korrekt helyre rakjuk be, nem csak ugy pikk-pakk
if(vehicles.size() > 0 || vehiclesAtCross.size() > 0){
for(int i = 0; i < vehicles.size(); i++){
//elindulunk a tomb elejen es amint olyan helyre erunk, hogy
if(pos < vehicles.get(i).getPosition()){
vehicles.add(++insertWhere, v);
break;
}
}
} else {
vehicles.add(v);
}
//ezen az uton halad
v.setRoute(this);
//e fele a keresztezodes fele
v.setCross(endCross);
//beallitjuk, hogy epp hol jar az uton
v.setPosition(pos);
//probaljon meg olyan sebesseggel haladni "amilyennel szeretne"
v.setSpeed(v.getSpeed());
}
/**
* onTick: a GameTimer megh�vja a megfelel� f�ggv�nyeket adott id�k�z�nk�nt
*/
public void onTick() {
//megvizsgaljuk, hogy a rablo utkozott-e
collisionDetect();
//ha nem tortent semmi, akkor csak mozgassuk elorebb az autokat
moveCars();
}
/**
* Az �thoz adhat� meg olyan keresztez�d�s, amely az �t elej�n tal�lhat�. Ha mar letezett, akkor a regit felulirja.
* @param c keresztezodes
*/
public void addStartCross(Cross c) {
if(c != null){
this.startCross = c;
c.addOutRoutes(this);
}
}
/**
* Az �thoz adhat� meg olyan keresztez�d�s, amely az �t v�g�n tal�lhat�. Ha mar letezett, akkor a regit felulirja.
* @param c keresztezodes
*/
public void addEndCross(Cross c) {
if(c != null){
this.endCross = c;
c.addInRoutes(this);
}
}
//[DOC] nincs ilyen fuggveny dokumentalva
/**
* Eltavolitja a parametreben megadott jarmuvet az utrol.
*/
public void removeCarFromRoute(Vehicle v){
//megprobalja eltavolitani a jarmuvet
vehicles.remove(v);
vehiclesAtCross.remove(v);
}
public ArrayList<Vehicle> getVehiclesFromRoute(){
//merge the two arrays
ArrayList<Vehicle> sumVehicles = new ArrayList<Vehicle>();
sumVehicles.addAll(vehicles);
sumVehicles.addAll(vehiclesAtCross);
return sumVehicles;
}
/**
* Visszaadja az ut belepesi keresztezodeset.
* @return kezdeti pont beli keresztezodes
*/
public Cross getStartCross(){
return startCross;
}
//TODO:[DOC] ugyanaz, mint az egy fvel fentebb levo...
/**
* Visszaadja az ut vegpontjanal levo keresztezodest.
* @return vegponti keresztezodes
*/
public Cross getEndCross(){
return endCross;
}
public void setBunny(Bunny bunny){
this.bunny = bunny;
}
public void removeBunny(){
this.bunny = null;
}
public int getLength(){
return length;
}
}