Dazoot Formula 1
 
   

Formula 1 - Proiect BLIA

PDF
PDF

Introducere

Preview

Aplicatia Java simuland o cursa de Formula 1, in care masinile (punctuletele colorate) sunt Agenti Inteligenti

Formula 1 - Cursa in plina desfasurare

Enuntul problemei

			
Formula 1 (Razvan Mosaloiu)

Fie o cursa de Formula 1 in care participa un numar N de monoposturi/
agentzi.
Fiecare din ei are anumitzi parametrii:
- viteza maxima
- rata de consum al combustibilului
- timp de viatza al rotzilor
- viteza de accelatzie
Traseul pe care are loc cursa se considera un inel de M casutze pe 
care pot sa apara:
- curbe la stanga sau la drepata 
(fiecare are o anumita viteza maxima cu care poate fi trecuta)
- intrare/ieshire la boxe
- linie de start = linia de stop
Initzial cele N monoposturi ocupa N casutze consecutive in spatele
liniei de start. O depashire nu poate sa aiba loc decat daca cel 
doua monoposturi se afla pentru un anumit timp in aceeashi casutza 
moment in care cel care vine din urma poate sa incerce o depashire. 
Depashirea are un succes cu o anumita probabilitate shi poate sa 
reushasca sau sa eshueze fie cu 0, 1 sau ambele monoposturi 
avariate. Cursa se termina dupa un anumit numar de tururi 
de pista.
			

Abordarea problemei

Simularea a fost implementata folosind Java folosind Threads (fire de executie separate). Aplicatia functioneaza ca Applet si ca aplicatie Stand Alone(JWS compliant).
In cadrul aplicatiei exista un singur tip de Agent si anume Masina. Fiecare masina incearca sa castige cursa, respectand regulile si luand decizii privind intrarea la boxe sau depasirile.

Implementare

Citirea datelor si generarea configuratiei

Pentru definirea constantelor am folosit formatul de fisier Java Properties.
In fisierul de configurare definim:

  • - pista ca fiind o lista dublu inlantuita de celule
    Nota
    O celula poate fi drum drept sau curba (stanga sau dreapta, depinde sensul din care vin)
    Nota
    Fiecare celula poate primi caracteristici, in momentul de fata singurul parametru fiind viteza maxima cu care se poate intra in respectiva Celule (de obicei doar la curbe se foloseste asta).
  • - ordinea masinilor pe grila de start, precum si caracteristicile fiecarei masini
  • - parametrii grafici (marimea unei celule, pozitia de start X, Y), etc.
  • - directia iniaiala care se aplica celulei de start (folosita in desenarea areneie, si miscarea masinilor)
  • - timpul in milisecunde pentru un TACT (tactul fiind unitatea de masura pentru timp)
  • - timpul care fiecare masina asteapta la boxe (schimbarea rotilor, umplerea rezervorului cu combustibil)
  • - numarul de tururi de pista in cursa curenta
  • - parametri ce contribuie la luarea deciziei de depasire (daca este cazul)

Pentru stocarea datelor am folosit 2 JavaBeans, si anume CellBean.java si MasinaBean.java.

Citirea se face in clasa Configuration. Fiecare JavaBean specificat mai sus este extins de clasa propriuzisa, Cell si Masina, acestea fiind obiectele cu care se populeaza configuratia.

Ca format avem pista=20,0,2:{viteza_max=50},0,0,2,2,1,1,0,0.... pentru definirea pistei si cars=Catalin:{viteza_max=100 rata_consum=150 viata_roti=150 viteza_acc=10},Dana:{viteza_max=30 rata_consum=... pentru definirea masinilor (ordinea conteaza, fiind folosita la grila de start).

Afisarea configuratiei

Afisarea configuratiei (pista, masinile pe pista) se face in clasa ArenaPanel. Pentru performanta pista este "desenata" initial intr-un Buffer, ulterioarele "afisari" facandu-se direct din acel buffer.

Fiecarei masina, in functie de start_order i se asociaza o culoare (RGB), cu care simbolul va fi desenat pe pista.

Nota
Problemele cu afisarea au intervenit atat la generarea pistei, datorita curbelor (arce de cerc), cat si pozitionarii masinilor intr-o curba.
Nota
Metoda repaint are atributul de synchronized, pentru a nu permite mai multor threaduri sa o apeleze simultan.

Masina, agent inteligent

Fiecare masina este o entitate, reprezentata in cadrul aplicatiei noastre printr-un Thread. Initial fiecarei entitati ii este asociata o celula (celula din care porneste), iar viteza mobilului este 0.
Actiunile pe care o masina le face intr-un ciclu sunt urmatoarele:

  1. verifica parintele (Pista) daca nu cumva a fost implicat intr-un accident si este in afara pistei (dead)
  2. daca celula curenta este cea de Start incrementez numarul de tururi parcuse si verifica daca nu cumva a terminat cursa, in caz afirmativ anuntand pista de acest lucru.
  3. verific daca nu cumva am ramas fara combustibil sau cauciucurile s-au uzat suficient de mult, in cazul afirmativ masina iese din cursa
  4. verific daca ma aflu in celula care contine intrarea la boxe, caz in care daca am nevoie de schimbarea de cauciucuri sau de plin la masina intru la boxa
  5. accelerez, tinand cont de celula curenta (in caz ca e curba si are limita de viteza cu care poate fi abordata, nu depasesc viteza specificata)
  6. verific daca ma aflu in situatia de depasire
  7. daca pot depasii (am viteza mai mare decat masina din fata) intru in metoda de decizie
  8. decizia depasirii tine cont de niste factori, printre care: numarul de depasiri reusite in celula respectiva, numarul de reusiri esuate in celula respectiva, numarul de accidente in celula respectiva, daca celula respectiva este curba sau nu, cat si de un Random
  9. daca decid sa depasesc urmeaza partea de Random in care se decide daca depasirea are sau nu succes (probabilitati egale) SAU cazul mai grav(cu probabilitate mult mai mica) in care ambele se accidenteaza.
  10. ultimul pas este cel de a avansa la celula urmatoare pista.moveCar(this, cell.next());pasi++;

Mai jos este partea de cod in care se ia decizia de depasire:

				
public boolean decideDepasire()
{
	int accidente_max_random=Controller.getInstance().
		getProperties().getIntProperty("accidente_max_random", 10);
	int ok_contor=Controller.getInstance().
		getProperties().getIntProperty("ok_contor", 10);
	
	ok_contor-=
		(cell.getIncercari_esuate()-cell.getIncercari_reusite());
	if (cell.isCurba()) ok_contor-=5;
	
	ok_contor-=
		r.nextInt(accidente_max_random)-cell.getAccidente();
	
	//msg(ok_contor+"");
	return ok_contor>0;
}
				

Integritatea datelor

Simularea se face avand cate un Thread pentru fiecare Masina, este nevoie de garantarea integritatii datelor. Drept urmare TOATE miscarile unei masini se fac apeland metode publice din clasa Pista.

Clasa Pista tine lista de masini, lista masinilor avariate si lista masinilor ce au terminat cursa.

Metodele importante din clasa Pista sunt:

  • isCarOut(Masina m) - verifica daca masina m a fost avaraiata
  • finishCar(Masina m) - adauga masina m in lista de terminati, elibereaza celula in care se afla masina, setand null ca noua celula
  • accident(Masina m1, Masina m2) - elimina din cursa masinile m1 si m2, elibereaza celulele in care se afla masinile
  • autoAvarie(Masina m) - elimina masina m din cursa, elibereaza celula
    Nota
    Acesta metoda este apelata atunci cand o masina ramane fara combustibil sau viata cauciucurilor a expirat.
    Acest lucru se poate intampla DOAR daca in configuratia masinii viata cauciucurilor (rotilor) sau rata de consum este mai mica decat distanta pana la intrarea la boxe
  • moveCar(Masina m, Cell newcell) - muta masina m in celula newcell eliberand totodata celula curenta in care se afla masina
    Nota
    Aceasta metoda arunca o Exceptie ce trebuie tratata de fiecare Agent.
    Exceptia se poate intampla cand in noua celula sunt deja 2 masini.
  • carOut(Masina m) - elibereaza celula m.getCell()

Dupa fiecare din metodele enumerate mai sus se apeleaza this.updateArena() care are 2 functii:

  1. face update la pista (grafic)
  2. verifica daca nu cumva s-a terminat cursa, moment in care sunt afisate intr-un JOptionPane rezultatele (folosind formatare HTML)

In clasa pista nici o metoda nu este synchronized deoarece metodele din Cell sunt cele care permit accesul unui singur thread la resursa.

Fiecare Cell isi tine o lista cu masinile care se afla in interiorul celulei. Adaugarea se face apeland metoda carIn(Masina m), iar eliberarea folosind metoda carOut(Masina m).

In carIn(..) se verifica daca nu cumva exista deja 2 masini in celula curenta, moment in care adaugarea este esuata aruncandu-se exceptia: throw new Exception("Too many cars in this cell !"+cars);

O alta metoda importanta este getOtherCar(Masina m) care intoarce cealalta masina aflata in celula curenta. (daca exista, daca nu aruncandu-se o exceptie throw new Exception("You are not in this cell, ERROR !"); sau throw new Exception("In this cell is no other car my friend !");)

Alte specificatii

Mai jos sunt cateva informatii care ajuta la intelegerea "problemei" cat si la intelegerea algoritmului.

viteza_acc (viteza de acceleratie), este definita ca numarul de celule necesare pentru a atinge viteza maxima (folosita in Masina.speed(int ds))

Afisarea rezultatelor se face printrun mesaj de informare. Continutul mesajului este generat consultand cele 2 Collections Set out_cars si List finish_list

Formula 1 - Rezultat

Simularea vitezei se face folosind formula sleep(100*tact/speed);.

Linkuri

Proiectul se gaseste online la adresa: http://opensource.dazoot.ro/member/catalin/formula1/.

by CONSTANTIN Catalin