2 with Ada
.Text_IO
; use Ada
.Text_IO
;
3 with Simulator
.Controller
;
10 --with Ada.Numerics.Generic_Elementary_Functions;
13 with Input_Sources
.File
; use Input_Sources
.File
;
14 with Sax
.Readers
; use Sax
.Readers
;
15 with DOM
.Readers
; use DOM
.Readers
;
16 with DOM
.Core
; use DOM
.Core
;
17 with DOM
.Core
.Documents
; use DOM
.Core
.Documents
;
18 with DOM
.Core
.Nodes
; use DOM
.Core
.Nodes
;
19 with DOM
.Core
.Attrs
; use DOM
.Core
.Attrs
;
20 with Ada
.Text_IO
; use Ada
.Text_IO
;
22 with Ada
.Numerics
.Generic_Elementary_Functions
;
24 package body Simulator
.Track
is
25 package Float_Functions
is new Ada
.Numerics
.Generic_Elementary_Functions
(
29 MaxMultiplicity
: Positive := 3;
30 n_registered
: CarId_T
:=1;
31 BoxSpeedLimit
: Integer := 80;
32 PitStopSector
: Positive;
34 type PitStopRequest_T
is array (CarId_T
) of Boolean ;
36 type PitStopRecord_T
is record
40 type PitStopData_T
is array (CarId_T
) of PitStopRecord_T
;
41 PitStopData
: PitStopData_T
;
42 PitStopRequest
: PitStopRequest_T
;
43 type RetireRequest_T
is array (CarId_T
) of Boolean ;
44 RetireRequest
: PitStopRequest_T
;
45 --TODO confornto tra indici di prestazioni
46 --Semantica: ritorna 1 se il primo argomento è maggiore del secondo, 0 altrimenti
47 function GreaterThan
(id1
: Natural; id2
: Natural) return Boolean is
62 procedure CalculateDriveTime
(my_properties
: CarProperties_T
; my_length
: Natural; my_level
: Integer; isbox
: Boolean; my_fuel
: out Float; my_consumption
: out Float; my_speed
: in out Float; finish
: out Time
) is
64 Vmax
: Float := 100.0;
65 difficulty
: Integer := my_level
;
66 -- dati per calcolo velocità e accelerazione
68 Smax
: Float:= Float(my_length
);
70 V0
: Float := my_speed
;
74 if (difficulty
< 0) then
75 difficulty
:= - difficulty
;
79 a
:= a
- a
*0.8* ( Float(my_properties
.TiresConsumption
) * 0.35 + 0.5*( (Float(difficulty
) / Float(MaxLevel
))) + 0.15 * ( Float(my_properties
.CarFuel
)/ Float(MaxFuel
)));
80 Vmax
:= Vmax
* Float( Float(1 + MaxLevel
- difficulty
)/ Float(1 + MaxLevel
));
81 Vmax
:= Vmax
- ( Vmax
* (10.0 * Float( my_properties
.TiresConsumption
) )) / 100.0;
82 Put_Line
("Vmax ="& Float(Vmax
* 3.6)'Img&"km/h");
83 Put_Line
("Difficoltà della curva "& difficulty
'Img);
84 Put_Line
("a ="& a
'Img&"m/s");
85 --TODO calcolare la durata di percorrenza in base ai parametri di auto e a quelli di sector e lane
87 Vmax
:= Float(BoxSpeedLimit
);
91 -- Parte in moto uniformemente accelerato
92 S
:= ((Vmax
*Vmax
) - (V0
*V0
))/(2.0*a
);
93 -- Put_Line("Spazio di accelerazione necessario per raggiungere Vmax ="&S'Img);
96 -- pezzo in moto uniformemente accelerato
97 -- Put_Line("La velocità che raggiungo è maggiore di quella consentita");
100 -- pezzo in moto rettilineo uniforme
101 t
:= t
+ ((Smax
- S
) / Vmax
);
104 -- percorro tutto il tratto accelerando
105 Vfinal
:= Float_Functions
.Sqrt
((V0
*V0
) + (2.0*a
*Smax
));
106 t
:= (Vfinal
- V0
) / a
;
109 --arrivo a velocità troppo alta. Freno in maniera istantanea e percorro il tratto
110 --a velocità costante
114 -- Vfinal è la velocità di uscita dal tratto, t il tempo impiegato
116 if ( (Float( PitStopData
(my_properties
.CarId
).CarFuel
) / 12.0) < 5.5) then
119 t
:= t
+ Float(Float(PitStopData
(my_properties
.CarId
).CarFuel
) / 12.0);
122 -- Put_Line("Vfinal ="& Float(Vfinal* 3.6)'Img&" km/h");
123 Put_Line
("Durata tratto "&Duration(t
)'Img);
125 my_consumption
:= 0.0;
127 finish
:= start
+ Duration(t
);
128 -- Put_Line("Calcolo Tempo di risveglio previsto "& Seconds(finish)'Img);
129 end CalculateDriveTime
;
131 --TODO driveLane aggiorna i carproperties in base al lane percorso
133 protected type Semaphore
is
135 procedure Signal
(start
: Boolean); -- V
137 Started
: Boolean := false;
140 protected body Semaphore
is
141 entry Wait
when Started
= True is
143 Put_Line
("Auto partita");
145 procedure Signal
(start
: Boolean) is
153 protected type Lane_T
(my_length
: Natural; my_level
: Integer; my_isbox
: Boolean) is
154 entry Demand
( my_properties
: CarProperties_T
; my_time
: out Time
; my_fuel
: out Float; my_consumption
: out Float; my_speed
: in out Float);
156 IsBox
: Boolean := my_isbox
;
157 exit_time
: Time
:= Clock
;
158 Level
: Integer := my_level
;
159 Length
: Natural := my_length
;
163 entered
: Integer :=0;
164 open
: Boolean := False;
167 type Corsie_Array_T
is array (Positive range <>, Positive range<>) of access Lane_T
;
168 Corsie
: access Corsie_Array_T
;
169 type PitLane_T
is array(CarId_T
) of Semaphore
;
170 PitLane
: access PitLane_T
:= new PitLane_T
;
172 type LaneCounter_T
is array (Positive range<>) of Natural;
173 type CarLane_T
is array (CarId_T
) of Positive;
175 type ExitRecord
is record
177 CarTime
: Time
:= Clock
;
178 Arrived
: Boolean := False;
180 type ExitArray_T
is array (Integer range <>) of ExitRecord
;
182 protected type Sector
(my_sector_id
: Natural; my_multiplicity
: Natural; my_length
: Natural; my_level
: Integer; my_isbox
: Boolean ) is
183 --sceglie la corsia da percorrere in base alla strategia, calcola il tempo di percorrenza e effettua la requeue su di essa
184 entry Enter
( my_properties
: CarProperties_T
; my_time
: out Time
; my_fuel
: out Float; my_consumption
: out Float; my_speed
: in out Float);
185 entry Release
(my_properties
: CarProperties_T
);
186 entry BookExit
(my_properties
: CarProperties_T
; my_time
: Time
);
190 entry ExitLane
(my_properties
: CarProperties_T
);
191 ExitArray
: ExitArray_T
(1 .. 5*MaxMultiplicity
);
192 ExitCount
: Natural := 0;
193 LaneCounter
: LaneCounter_T
(1 .. my_multiplicity
) ;
195 Free
: Natural := 5 * my_multiplicity
;
196 MaxCars
: Natural := 5 * my_multiplicity
;
198 Sector_Id
: Natural :=my_sector_id
;
199 Length
: Natural := my_length
;
200 Multiplicity
: Natural := my_multiplicity
;
201 Level
: Integer := my_level
;
202 IsBox
: Boolean := my_isbox
;
204 Changed
: Boolean := False;
207 entered
: Integer :=0;
208 open
: Boolean := False;
211 protected body Sector
is
212 entry BookExit
(my_properties
: CarProperties_T
; my_time
: Time
) when True is
216 if (ExitCount
<= 0) then
217 ExitArray
(1) := (my_properties
.CarId
, my_time
, False);
218 Put_Line
("DEBUG : Book: accodo Auto "&my_properties
.CarId
'Img&" in posizione 1 perchè la lista uscite è vuota");
219 ExitCount
:= ExitCount
+ 1;
221 for Index
in reverse 0 .. ExitCount
loop
222 -- Put_Line("Debug: Book: loop esterno indice "& Index'Img);
224 Put_Line
("DEBUG : Book: Inerisco l'auto in posizione 1");
225 for I
in reverse (Index
+ 1) .. ExitCount
loop
226 -- Put_Line("Debug: Book: loop interno");
227 ExitArray
(I
+1) := ExitArray
(I
);
229 ExitArray
(Index
+ 1) := (my_properties
.CarId
, my_time
, False);
230 -- temp := Index + 1;
231 -- Put_Line("DEBUG : Book: accodo Auto "&my_properties.CarId'Img&" in posizione "&temp'Img);
232 ExitCount
:= ExitCount
+ 1;
234 else if(ExitArray
(Index
).CarTime
< my_time
) then
235 Put_Line
("DEBUG : Book: Inerisco l'auto in posizione "&Integer(Index
+1)'Img);
236 -- Put_Line("Debug: Book: dentro if");
237 for I
in reverse (Index
+ 1) .. ExitCount
loop
238 -- Put_Line("Debug: Book: loop interno");
239 ExitArray
(I
+1) := ExitArray
(I
);
241 ExitArray
(Index
+ 1) := (my_properties
.CarId
, my_time
, False);
242 -- temp := Index + 1;
243 -- Put_Line("DEBUG : Book: accodo Auto "&my_properties.CarId'Img&" in posizione "&temp'Img);
244 ExitCount
:= ExitCount
+ 1;
250 -- Put_Line("Non è stato preso ne l'if ne l'else");
253 entry Enter
( my_properties
: CarProperties_T
; my_time
: out Time
; my_fuel
: out Float; my_consumption
: out Float; my_speed
: in out Float) when Free
> 0 is
256 -- Put_Line("DEBUG: entrato nella procedura Enter di Sector");
257 --Prima auto a entrare nel tracciato azzera i campi dato
258 if (MaxCars
= Free
) then
259 for Index
in 1 .. Multiplicity
loop
260 LaneCounter
(Index
) := 0;
263 -- decido la corsia da percorrere. Trovo quella meno trafficata
266 for Index
in 1.. Multiplicity
loop
267 if (LaneCounter
(Index
) < LaneCounter
(n_lane
)) then
270 -- n_lane è l'id del lane meno trafficato
272 LaneCounter
(n_lane
) := LaneCounter
(n_lane
) + 1;
274 CarLane
(my_properties
.CarId
) := n_lane
;
276 Put_Line
("DEBUG: requeue su Corsie("&Sector_Id
'Img&","&n_lane
'Img&")");
277 requeue Corsie
(Sector_Id
,n_lane
).Demand
with abort;
278 --Corsie(sector_number,n_lane).Demand(my_id);
281 entry Release
(my_properties
: CarProperties_T
) when Free
< MaxCars
is
284 Put_Line
("Debug: Relase invocata");
285 if (ExitCount
= 0) then
286 Put_Line
("Bug del software: invocata Relase senza aver invocato BookExit");
288 if (ExitArray
(1).CarId
= my_properties
.CarId
) then
289 Put_Line
("DEBUG: relase : l'auto è in prima posizione : sposto le altre");
290 for Index
in 2 .. ExitCount
loop
291 Put_Line
("DEBUG: relase : sposto l'auto che era in posizione "& Index
'Img);
292 ExitArray
(Index
-1) := ExitArray
(Index
);
294 LaneCounter
(CarLane
(my_properties
.CarId
)) := LaneCounter
(CarLane
(my_properties
.CarId
)) -1;
296 ExitCount
:= ExitCount
-1;
297 if (ExitCount
> 0) then
298 if(ExitArray
(1).Arrived
= True) then
304 Put_Line
("Debug: Relase terminata");
306 for Index
in 1 .. ExitCount
loop
307 if (ExitArray
(Index
).CarId
= my_properties
.CarId
) then
308 ExitArray
(Index
).Arrived
:= True;
309 Put_Line
("DEBUG: Auto "&my_properties
.CarId
'Img&" ha superato dove non doveva..accodo in ExitLane");
318 entry ExitLane
(my_properties
: CarProperties_T
) when Changed
= True is
321 if (ExitArray
(1).CarId
= my_properties
.CarId
) then
322 -- Put_Line("DEBUG: Auto "&my_properties.CarId'Img&" in uscita da ExitLane");
323 for Index
in 2 .. ExitCount
loop
324 ExitArray
(Index
-1) := ExitArray
(Index
);
326 LaneCounter
(CarLane
(my_properties
.CarId
)) := LaneCounter
(CarLane
(my_properties
.CarId
)) -1;
328 ExitCount
:= ExitCount
-1;
329 if (ExitArray
(1).Arrived
= True) then
341 protected body Lane_T
is
342 entry Demand
(my_properties
: CarProperties_T
; my_time
: out Time
; my_fuel
: out Float; my_consumption
: out Float; my_speed
: in out Float) when True is
345 CalculateDriveTime
(my_properties
, my_length
,my_level
,IsBox
,my_fuel
, my_consumption
,my_speed
, my_time
);
346 if (my_time
> exit_time
) then
347 exit_time
:= my_time
;
348 elsif (my_time
< exit_time
) then
349 my_time
:= exit_time
+ 0.001;
357 ----------------STRUTTURE DATI DI TRACK
358 --codice di test. Operazioni svolte dal lettore del file di configurazione xml
360 type Sector_Array_T
is array (Positive range <>) of access Sector
;
361 Sectors
: access Sector_Array_T
;
362 BoxSector
: access Sector
;
365 -- inserisce la macchina nel circuito, fornisce in ingresso le
366 -- caratteristiche iniziali dell'auto. Quando questo metodo termina vuol
367 -- dire che la macchina ha finito la gara (conclusa o per ritiro)
369 procedure PutOnPitLane
(Self
: Simulator
.Partition_ID
; my_CarProperties
: CarProperties_T
) is
373 my_consumption
: Float;
374 CarProperties
: CarProperties_T
:= my_CarProperties
;
375 Speed
: Float := 0.0;
378 Put_Line
("Car " & CarId_T
'Image(CarProperties
.CarId
) & " registered on track");
379 Temp
:= CarProperties
.CarWeight
+100;
381 --Auto si mette nelle linee di partenza. Quando tornerà da questa ciamata, la corsa per l'auto sarà iniziata
382 PitLane
(CarProperties
.CarId
).Wait
;
383 --inizio la corsa iterando tra i vari Sector
386 for Index
in 1 .. Sectors
'Length loop
388 if (RetireRequest
(CarProperties
.CarId
) = True) then
391 if (Index
= PitStopSector
and PitStopRequest
(CarProperties
.CarId
) = True) then
392 -- TODO effettua il pti stop
393 BoxSector
.Enter
(CarProperties
, my_time
,my_fuel
, my_consumption
, Speed
);
394 Put_Line
("Auto ferma ai box fino al tempo"&CarProperties
.CarId
'Img&" :"& Seconds
(my_time
)'Img);
395 BoxSector
.BookExit
(CarProperties
, my_time
);
396 CarProperties
.CarFuel
:= CarProperties
.CarFuel
- 50;
397 Simulator
.Controller
.GetCar
(Self
).UpdateProperties
(CarId
=> CarProperties
.CarId
,
398 Tires
=> CarProperties
.Tires
,
399 TiresConsumption
=> CarProperties
.TiresConsumption
,
400 CarWeight
=> CarProperties
.CarWeight
,
401 CarFuel
=> CarProperties
.CarFuel
,
402 CarPerformance
=> CarProperties
.CarPerformance
,
404 -- Put_Line("!!! se stampa prima questo dei parametri auto aggiornati la chiamata è stata asincrona!!!");
406 Sectors
(Index
).Release
(CarProperties
);
407 Put_Line
("Auto "&CarProperties
.CarId
'Img&" Entra nella corsia dei Box");
410 Sectors
(Index
).Enter
(CarProperties
, my_time
, my_fuel
, my_consumption
, Speed
);
411 -- Put_Line("Velocità dell'auto "&CarProperties.CarId'Img&" è di "&Float(Speed * 3.6)'Img&" Km/h");
412 Put_Line
("Tempo di risveglio previsto per l'auto"&CarProperties
.CarId
'Img&" :"& Seconds
(my_time
)'Img);
413 Sectors
(Index
).BookExit
(CarProperties
, my_time
);
414 -- CarProperties.CarFuel := CarProperties.CarFuel - 50;
415 Simulator
.Controller
.GetCar
(Self
).UpdateProperties
(CarId
=> CarProperties
.CarId
,
416 Tires
=> CarProperties
.Tires
,
417 TiresConsumption
=> CarProperties
.TiresConsumption
,
418 CarWeight
=> CarProperties
.CarWeight
,
419 CarFuel
=> CarProperties
.CarFuel
,
420 CarPerformance
=> CarProperties
.CarPerformance
,
422 -- Put_Line("!!! se stampa prima questo dei parametri auto aggiornati la chiamata è stata asincrona!!!");
424 Sectors
(Index
).Release
(CarProperties
);
430 Put_Line
("DEBUG: PutOnPitLane è ritornato dalla simulazione.. Auto "&CarProperties
.CarId
'Img&" ha terminato la corsa");
436 procedure StartRace
(n_cars
: CarId_T
) is
438 -- inizializzo PitStopRequest.
439 for Index
in 1 .. n_cars
loop
440 PitStopRequest
(Index
) := False;
443 -- sveglio le auto in attesa su PitLane
444 Put_Line
("3...2...1... Go !!!");
445 for Index
in 1 .. n_cars
loop
446 PitLane
(Index
).Signal
(True);
450 Put_Line
("DEBUG: Tutte le auto sono partite");
454 -- Comunica di ritirare l'auto con id = CarId dal circuito
455 procedure Kill
(CarId
: in CarId_T
) is
457 Put_Line
("Killing car "&CarId
'Img&" ...");
458 RetireRequest
(CarId
) := True;
459 Simulator
.Controller
.GetRace
.Kill
(CarId
);
462 -- metodo di richiesta fermata ai box
463 -- l'invocazione di questo metodo porta il circuito a far fare una sosta
464 -- all'auto "CarId" appena possibile.
465 procedure CallForPitStop
(CarId
: in CarId_T
; CarFuel
:CarFuel_T
; Tires
:Tires_T
) is
467 PitStopRequest
(CarId
) := True;
468 PitStopData
(CarId
) := (CarFuel
, Tires
);
469 Put_Line
("Car "&CarId_T
'Image(CarId
)&" requires Pit Stop.");
473 procedure ReadTrackConf
(confFile
: String) is
475 Reader
: Tree_Reader
;
478 TrackList
: Node_List
;
485 Multiplicity
: Positive;
487 Put_Line
("DEBUG: Leggo configurazione da file xml");
488 Set_Public_Id
(Input
, "input");
489 --da passare come parametro il percorso
490 Open
(confFile
, Input
);
491 Set_Feature
(Reader
, Validation_Feature
, False);
492 Set_Feature
(Reader
, Namespace_Feature
, False);
493 Parse
(Reader
, Input
);
496 Doc
:= Get_Tree
(Reader
);
497 TrackList
:= Get_Elements_By_Tag_Name
(Doc
, "track");
498 if (Length
(TrackList
) /= 1) then
499 Put_Line
("Errore nel file XML. Ogni file deve contenere esattamente 1 track");
502 List
:= Get_Elements_By_Tag_Name
(Doc
, "sector");
503 Put_Line
("DEBUG TRACK:ci sono "&Length
(List
)'Img&" settori");
504 Sectors
:= new Sector_Array_T
(1 .. Length
(List
));
505 Corsie
:= new Corsie_Array_T
(1 .. Length
(List
) + 1, 1 .. 4);
506 for Index
in 1 .. Length
(List
) loop
507 Settore
:= Item
(List
, Index
- 1);
509 A
:= Get_Named_Item
(Attributes
(Settore
), "level");
510 Livello
:= Integer'Value (Node_Value
(A
)) ;
511 A
:= Get_Named_Item
(Attributes
(Settore
), "length");
512 Lunghezza
:= Natural'Value (Node_Value
(A
));
513 A
:= Get_Named_Item
(Attributes
(Settore
), "multiplicity");
514 Multiplicity
:= Positive'Value (Node_Value
(A
));
515 --Creo il settore e i lane
516 Sectors
(Index
) := new Sector
(Index
,Multiplicity
,Lunghezza
,Livello
,False);
517 for i
in 1 .. Multiplicity
loop
518 Corsie
(Index
, i
) := new Lane_T
(Lunghezza
,Livello
,False);
520 Put_Line
("creato settore "& Index
'Img);
522 BoxList
:= Child_Nodes
( Settore
);
523 if (Length
(BoxList
) /= 0) then
524 Put_Line
("Inizializzo box");
525 PitStopSector
:= Index
;
526 A
:= Get_Named_Item
(Attributes
(Item
(BoxList
,1)), "length");
527 Lunghezza
:= Natural'Value (Node_Value
(A
));
528 BoxSector
:= new Sector
(Length
( List
) + 1, 1, Lunghezza
, Livello
, True);
529 Corsie
(Length
( List
) + 1, 1) := new Lane_T
(Lunghezza
,Livello
,True);
530 Put_Line
("Trovati box nel sttore "& PitStopSector
'Img&" di lunghezza "&Lunghezza
'Img);