Versione finale relazione
[toni-reis.git] / src / simulator-track.adb
blob5df1507f973b51ab9d83cc8ac02a1ea56a01eb19
1 with System;
2 with Ada.Text_IO; use Ada.Text_IO;
3 with Ada.Calendar; use Ada.Calendar;
4 with Ada.Containers.Vectors;
5 with Ada.Numerics;
6 with Ada.Numerics.Generic_Elementary_Functions;
9 with Simulator;
10 with Simulator.Controller;
11 with Simulator.Car; use Simulator.Car;
12 with Simulator.Statistics; use Simulator.Statistics;
13 with Simulator.TrackGui; use Simulator.TrackGui;
14 with Simulator.TrackData; use Simulator.TrackData;
16 with Unicode.CES;
18 with Schema.Schema_Readers, Schema.Validators, Input_Sources.File;
19 use Schema.Schema_Readers, Schema.Validators, Input_Sources.File;
20 with Schema.Schema_Grammar; use Schema.Schema_Grammar;
22 with Sax.Readers;
23 with Schema.Readers; use Schema.Readers;
24 with Schema.Dom_Readers; use Schema.Dom_Readers;
26 --with DOM.Readers; use DOM.Readers;
27 with DOM.Core; use DOM.Core;
28 with DOM.Core.Documents; use DOM.Core.Documents;
29 with DOM.Core.Nodes; use DOM.Core.Nodes;
30 with DOM.Core.Attrs; use DOM.Core.Attrs;
32 with Ada.Numerics.Float_Random;
33 use Ada.Numerics.Float_Random;
34 with Ada.Exceptions; use Ada.Exceptions;
37 package body Simulator.Track is
38 type Intermediate_Count_T is new Positive range 1 .. 1_000;
39 package IntVector is new Ada.Containers.Vectors(Element_Type => Integer, Index_Type => Intermediate_Count_T);
40 package Float_Functions is new Ada.Numerics.Generic_Elementary_Functions (Float);
44 --STRUTTURE DATI
45 MaxMultiplicity : Positive := 3;
46 -- n_registered : Natural :=0;
47 BoxSpeedLimit : Float := 22.2; -- m/s
48 PitStopSector : Positive;
49 Intermediate : IntVector.Vector;
50 TrackStarted : Boolean := False;
52 type PitStopRequest_T is array (CarId_T) of Boolean ;
54 type PitStopRecord_T is record
55 CarFuel : CarFuel_T;
56 Tires : Tires_T;
57 end record;
59 type PitStopData_T is array (CarId_T) of PitStopRecord_T;
60 PitStopData : PitStopData_T;
61 PitStopRequest: PitStopRequest_T;
62 type RetireRequest_T is array (CarId_T) of Boolean ;
63 RetireRequest: PitStopRequest_T;
65 procedure CalculateDriveTime(my_properties : CarProperties_T; my_length: Natural; my_level : Integer; weather: Weather_T; isbox : Boolean; my_fuel: out Float; my_consumption : out Float; my_speed : in out Float; finish : out Duration) is
66 Vmax : Float := 100.0;
67 difficulty : Integer := my_level;
68 -- dati per calcolo velocità e accelerazione
69 a : Float := 9.25;
70 Smax : Float:= Float(my_length);
71 S : Float;
72 V0 : Float := my_speed;
73 Vfinal : Float;
74 t : Float := 0.0;
75 begin
76 if (difficulty < 0) then
77 difficulty := - difficulty;
78 end if;
79 a:= a - a*0.8* ( 0.3 * (1.0 - Float(my_properties.CarPerformance) / 100.0) + 0.10 * Float(my_properties.TiresConsumption ) + 0.4*( (Float(difficulty) / Float(MaxLevel))) + 0.20 * ( Float(my_properties.CarFuel)/ Float(MaxFuel)));
80 if (weather = Wet) then
81 -- se piove diminuiso l'accelerazione massima di 1/3;
82 a := a / 3.0;
83 if (my_properties.Tires = Slick) then
84 -- se piove e monto le gomme da asciutto diminuisco l'accelerazione di un ulteriore terzo
85 a := a/3.0;
86 end if;
87 else
88 -- Il tracciato è asciutto
89 if (my_properties.Tires = Rain) then
90 -- monto le gomme da bagnato
91 a := a/3.0;
92 end if;
93 end if;
95 Vmax := Vmax * Float( Float(1 + MaxLevel - difficulty)/ Float(1 + MaxLevel));
96 if (isbox) then
97 Vmax := Float(BoxSpeedLimit);
98 end if;
99 if (V0 < Vmax) then
101 -- Parte in moto uniformemente accelerato
102 S := ((Vmax*Vmax) - (V0*V0))/(2.0*a);
104 if (S <= Smax) then
105 -- pezzo in moto uniformemente accelerato
106 Vfinal := Vmax;
107 t := (Vmax - V0)/a;
108 -- pezzo in moto rettilineo uniforme
109 t := t + ((Smax - S) / Vmax);
111 else
112 -- percorro tutto il tratto accelerando
113 Vfinal := Float_Functions.Sqrt((V0*V0) + (2.0*a*Smax));
114 t := (Vfinal - V0) / a;
115 end if;
116 else
117 --arrivo a velocità troppo alta. Freno in maniera istantanea e percorro il tratto
118 --a velocità costante
119 t := Smax / Vmax;
120 Vfinal := Vmax;
121 end if;
122 -- Vfinal è la velocità di uscita dal tratto, t il tempo impiegato
123 -- in ogni caso, aggiorno il consumo
124 my_consumption := Float(my_length) / 180000.0;
125 my_consumption := my_consumption*( 1.0 + 0.2* (Float(my_properties.CarPerformance) / 100.0) + 0.3* Float(my_properties.CarFuel)/ Float(MaxFuel) );
126 my_fuel := - Float(my_length) / 2040.0;
127 my_fuel := my_fuel*( 1.0 + 0.3* ( Float(my_properties.CarPerformance) / 100.0) + 0.2* Float(my_properties.CarFuel)/ Float(MaxFuel) );
128 if (isbox) then
129 if ( (Float( PitStopData(my_properties.CarId).CarFuel ) / 12.0) < 5.5) then
130 t := t + 5.5;
132 else
133 t := t + Float(Float(PitStopData(my_properties.CarId).CarFuel) / 12.0);
134 end if;
135 my_consumption := Float(- my_properties.TiresConsumption);
136 my_fuel := Float(PitStopData(my_properties.CarId).CarFuel);
137 end if;
139 my_speed := Vfinal;
141 finish := Duration(t);
143 end CalculateDriveTime;
145 protected type Semaphore is
146 entry Wait; -- P
147 entry Internal;
148 procedure Signal(start : Boolean; car : out Boolean); -- V
149 private
150 Started : Boolean := false;
151 Used : Boolean := False;
152 end Semaphore;
153 type Semaphore_Ref is access Semaphore;
154 protected body Semaphore is
155 entry Wait when True is
156 begin
157 Used := True;
158 requeue Internal;
159 end Wait;-- P
160 entry Internal when Started = True is
161 begin
162 null;
163 end Internal;
164 procedure Signal(start : Boolean; car : out Boolean) is
165 begin
166 Started := start;
167 car := Used;
168 Used := False;
169 end Signal;
171 end Semaphore;
174 protected type Lane_T(my_length: Natural; my_level : Integer;my_weather : Weather_T; my_isbox : Boolean) is
175 entry Demand(my_properties : in CarProperties_T; sector : in out Integer; my_time : in out Time; my_duration : out Duration; my_fuel: out Float; my_consumption : out Float; my_speed : in out Float);
176 private
177 Weather : Weather_T :=my_weather;
178 IsBox : Boolean := my_isbox;
179 exit_time : Time := Clock;
180 exit_speed : Float := 0.0;
181 Level : Integer := my_level;
182 Length : Natural := my_length;
183 max : Natural;
184 maxId : CarId_T;
185 tot : Integer :=0;
186 entered : Integer :=0;
187 open : Boolean := False;
188 end Lane_T;
189 type Corsie_T is array (Positive range <>) of access Lane_T;
190 type Corsie_Array_T is array (Positive range <>) of access Corsie_T;
191 Corsie : access Corsie_Array_T;
192 type PitLane_T is array(CarId_T) of Semaphore_Ref;
193 PitLane: access PitLane_T := new PitLane_T;
195 type LaneCounter_T is array (Positive range<>) of Natural;
196 type CarLane_T is array (CarId_T) of Positive;
198 type ExitRecord is record
199 CarId : CarId_T;
200 CarTime : Time := Clock;
201 Arrived : Boolean := False;
202 end record;
203 type ExitArray_T is array (Integer range <>) of ExitRecord;
205 protected type Sector(my_sector_id: Natural; my_multiplicity : Natural; my_length: Natural; my_level : Integer; my_isbox: Boolean ) is
206 --sceglie la corsia da percorrere, cioè quella con meno traffico, calcola il tempo di percorrenza e effettua la requeue su di essa
207 entry Enter(my_properties : in CarProperties_T; sector : in out Integer; my_time : in out Time; my_duration : out Duration; my_fuel: out Float; my_consumption : out Float; my_speed : in out Float);
208 entry Release(my_properties : in CarProperties_T; sector : in out Integer; my_time : in out Time; my_duration : out Duration; my_fuel: out Float; my_consumption : out Float; my_speed : in out Float);
209 entry BookExit(my_properties: CarProperties_T; my_time : Time);
211 private
212 entry ExitLane(my_properties : in CarProperties_T; sector : in out Integer; my_time : in out Time; my_duration : out Duration; my_fuel: out Float; my_consumption : out Float; my_speed : in out Float);
213 ExitArray : ExitArray_T(1 .. MaxId);
214 ExitCount : Natural := 0;
215 LaneCounter : LaneCounter_T(1 .. my_multiplicity) ;
216 CarLane : CarLane_T;
217 Free : Natural := MaxId;
218 MaxCars : Natural := MaxId;
219 Sector_Id: Natural :=my_sector_id;
220 Length : Natural := my_length;
221 Multiplicity: Natural := my_multiplicity;
222 Level : Integer := my_level;
223 IsBox : Boolean := my_isbox;
224 -- per la exit
225 Changed : Boolean := False;
226 max : Natural;
227 tot : Integer :=0;
228 entered : Integer :=0;
229 open : Boolean := False;
230 end Sector;
232 type Sector_Array_T is array (Positive range <>) of access Sector;
233 -- settori circuito
234 Sectors : access Sector_Array_T;
235 -- settore box
236 BoxSector : access Sector;
238 procedure CheckSurpass(Sector_Id : Natural; CarId : CarId_T) is
239 begin
240 Print("Controllo i sorpassi nel settore"& Sector_Id'Img);
241 if (Sector_Id /= 1) then
242 if ( (not ExitOrder(Sector_Id - 1).Is_Empty) ) then
243 if (ExitOrder(Sector_Id - 1).First_Element /= CarId) then
244 Print("Errore : L'auto ha superato tra l'uscita di un settore e l'entrata nel settore "& Sector_Id'Img);
245 end if;
246 -- cancello il primo elemento
247 ExitOrder(Sector_Id - 1).Delete_First;
248 end if;
249 else
250 if ( (not ExitOrder(Sectors'Length).Is_Empty)) then
251 if( ExitOrder(Sectors'Length ).First_Element /= CarId) then
252 Print("Errore : L'auto ha superato tra l'uscita di un settore e l'entrata nel settore "& Sector_Id'Img);
253 end if;
254 -- cancello il primo elemento
255 ExitOrder(Sectors'Length).Delete_First;
256 end if;
257 end if;
258 end CheckSurpass;
261 protected body Sector is
262 entry BookExit(my_properties: CarProperties_T; my_time : Time) when True is
263 begin
264 if (ExitCount <= 0) then
265 ExitArray(1) := (my_properties.CarId, my_time, False);
266 ExitCount := ExitCount + 1;
267 else
268 for Index in reverse 0 .. ExitCount loop
269 if(Index = 0 ) then
270 for I in reverse (Index + 1) .. ExitCount loop
271 ExitArray(I+1) := ExitArray(I);
272 end loop;
273 ExitArray(Index + 1) := (my_properties.CarId, my_time, False);
274 ExitCount := ExitCount + 1;
275 exit;
276 else if(ExitArray(Index).CarTime < my_time) then
277 for I in reverse (Index + 1) .. ExitCount loop
278 ExitArray(I+1) := ExitArray(I);
279 end loop;
280 ExitArray(Index + 1) := (my_properties.CarId, my_time, False);
281 ExitCount := ExitCount + 1;
282 exit;
283 end if;
284 end if;
285 end loop;
286 end if;
287 end BookExit;
289 entry Enter(my_properties : in CarProperties_T; sector : in out Integer; my_time : in out Time; my_duration : out Duration; my_fuel: out Float; my_consumption : out Float; my_speed : in out Float) when Free > 0 is
290 n_lane : Natural;
291 begin
292 --Prima auto a entrare nel tracciato azzera i campi dato
293 if (MaxCars = Free) then
294 for Index in 1 .. Multiplicity loop
295 LaneCounter(Index) := 0;
296 end loop;
297 end if;
298 -- decido la corsia da percorrere. Trovo quella meno trafficata
300 n_lane := 1;
301 for Index in 1.. Multiplicity loop
302 if (LaneCounter(Index) < LaneCounter(n_lane)) then
303 n_lane := Index;
304 end if;
305 -- n_lane è l'id del lane meno trafficato
306 end loop;
307 LaneCounter(n_lane) := LaneCounter(n_lane) + 1;
308 Free := Free - 1;
309 CarLane(my_properties.CarId) := n_lane;
311 pragma Debug (CheckSurpass(Sector_Id, my_properties.CarId));
313 Print("Auto "&my_properties.CarId'Img&" percorre Settore: "&Sector_Id'Img&", Tratto:"&n_lane'Img&".");
314 if (IsBox = False) then
315 requeue Corsie(Sector_Id)(n_lane).Demand with abort;
316 else
317 requeue Corsie(Sectors'Length + 1)(n_lane).Demand with abort;
318 end if;
319 end Enter;
321 entry Release(my_properties : in CarProperties_T; sector : in out Integer; my_time : in out Time; my_duration : out Duration; my_fuel: out Float; my_consumption : out Float; my_speed : in out Float) when Free < MaxCars is
322 next_sect : Integer;
323 a : Integer := 0;
324 t : Integer := Sector_Id;
325 begin
326 if (ExitCount = 0) then
327 Put_Line("Bug del software: invocata Relase senza aver invocato BookExit");
328 end if;
329 if (ExitArray(1).CarId = my_properties.CarId) then
330 for Index in 2 .. ExitCount loop
331 ExitArray(Index -1) := ExitArray(Index);
332 end loop;
333 LaneCounter(CarLane(my_properties.CarId)) := LaneCounter(CarLane(my_properties.CarId)) -1;
334 Free := Free + 1;
335 ExitCount := ExitCount -1;
336 if (ExitCount > 0) then
337 if(ExitArray(1).Arrived = True) then
338 Changed := True;
339 else
340 Changed := False;
341 end if;
342 end if;
343 -- release terminata
344 else
345 for Index in 1 .. ExitCount loop
346 if (ExitArray(Index).CarId = my_properties.CarId) then
347 ExitArray(Index).Arrived := True;
348 Print("DEBUG: Auto "&my_properties.CarId'Img&" ha superato dove non doveva..accodo in ExitLane");
349 Changed := False;
350 requeue ExitLane;
351 end if;
352 end loop;
354 end if;
355 ExitOrder(Sector_Id).Append(my_properties.CarId);
356 -- calcolo il prossimo settore
357 if (Sector_Id = Sectors'Length) then
358 next_sect := 1;
359 else
360 next_sect := Sector_Id +1;
361 end if;
363 -- sosta ai box?
364 if (PitStopRequest(my_properties.CarId) = true and then next_sect = PitStopSector) then
365 sector := 0;
366 PitStopRequest(my_properties.CarId) := False;
367 requeue BoxSector.Enter;
368 else
369 sector := next_sect;
370 requeue Sectors(next_sect).Enter;
371 end if;
372 end Release;
374 entry ExitLane(my_properties : in CarProperties_T; sector : in out Integer; my_time : in out Time; my_duration : out Duration; my_fuel: out Float; my_consumption : out Float; my_speed : in out Float) when Changed = True is
375 next_sect : Integer;
376 begin
377 if (ExitArray(1).CarId = my_properties.CarId) then
378 for Index in 2 .. ExitCount loop
379 ExitArray(Index -1) := ExitArray(Index);
380 end loop;
381 LaneCounter(CarLane(my_properties.CarId)) := LaneCounter(CarLane(my_properties.CarId)) -1;
382 Free := Free + 1;
383 ExitCount := ExitCount -1;
384 ExitOrder(Sector_Id).Append(my_properties.CarId);
385 if (ExitArray(1).Arrived = True) then
386 Changed := True;
387 else
388 Changed := False;
389 end if;
390 -- calcolo il prossimo settore
391 if (Sector_Id = Sectors'Length) then
392 next_sect := 1;
393 else
394 next_sect := Sector_Id +1;
395 end if;
397 -- sosta ai box?
398 if (PitStopRequest(my_properties.CarId) = true and then next_sect = PitStopSector) then
399 sector := 0;
400 requeue BoxSector.Enter;
401 else
402 sector := next_sect;
403 requeue Sectors(next_sect).Enter;
404 end if;
405 else
406 requeue ExitLane;
407 end if;
408 end ExitLane;
410 end Sector;
412 protected body Lane_T is
413 entry Demand(my_properties : in CarProperties_T; sector : in out Integer; my_time : in out Time; my_duration : out Duration; my_fuel: out Float; my_consumption : out Float; my_speed : in out Float) when True is
414 --start : Time;
415 t : Duration;
416 begin
417 -- TEST: modifica codice per usare solo i tempi calcolati
418 --start := Clock;
419 -- END TEST
420 CalculateDriveTime(my_properties , my_length ,my_level ,Weather,IsBox ,my_fuel, my_consumption,my_speed, t );
421 --TEST
422 my_time := my_time + t;--start + t;
423 -- END TEST
424 if (my_time > exit_time) then
425 exit_time := my_time;
426 exit_speed := my_speed;
427 elsif (my_time < exit_time) then
428 -- se l'auto è dietro, esce al tempo dell'auto che precede e al più alla sua stessa velocità
429 my_time := exit_time;
430 if (my_speed > exit_speed) then
431 my_speed := exit_speed;
432 end if;
433 end if;
434 my_duration := t;--my_time - start;
435 end Demand;
436 end Lane_T;
438 -- inserisce la macchina nel circuito, fornisce in ingresso le
439 -- caratteristiche iniziali dell'auto. Quando questo metodo termina vuol
440 -- dire che la macchina ha finito la gara (conclusa o per ritiro)
441 procedure PutOnPitLane(my_CarProperties : CarProperties_T) is
442 my_sect : Integer :=0;
443 my_time : Time;
444 my_fuel : Float;
445 my_consumption : Float;
446 my_duration : Duration;
447 CarProperties : CarProperties_T := my_CarProperties;
448 Speed : Float := 0.0;
449 temp : Float;
450 lap : Integer :=0;
451 inter : Integer;
452 old_lap: Integer :=0;
453 old_sect: Integer := 0;
454 old_time :Time;
455 old_speed : Float := 0.0;
456 use IntVector;
457 begin
458 Put_Line("DEBUG: chiamata putonpilane");
459 Print("Car " & CarId_T'Image(CarProperties.CarId) & " registered");
460 --Auto si mette nelle linee di partenza. Quando tornerà da questa chiamata, la corsa per l'auto sarà iniziata
461 PitLane(CarProperties.CarId).Wait;
463 old_time := Clock;
464 my_time := old_time;
465 Put_Line("Auto "&CarProperties.CarId'Img&" partita");
466 Simulator.Controller.GetRace.UpdateStatistics(CarProperties.CarId,CarProperties.Name, 0,1, (my_time - Time_Of(2009,9,21)), 0.0, 1);
468 -- mi prenoto sull'ultimo settore
469 Sectors(Sectors'Last).Enter(CarProperties, my_sect, my_time, my_duration, my_fuel, my_consumption, Speed);
470 Sectors(Sectors'Last).BookExit(CarProperties, old_time);
471 my_time := old_time;
472 -- Partenza: ogni auto parte e notifica l0avvenuta partenza a quella in posizione successiva
473 declare
474 i: Integer := 1;
475 success : Boolean := False;
476 begin
477 while ( i<= Integer(CarId_T'Last) and then success = False) loop
478 PitLane(CarId_T(i)).Signal(True, success);
479 Put_Line("Mando segnale all'auto "&i'Img&" con responso "&success'Img);
480 i := i+1;
481 end loop;
482 end;
483 Sectors(Sectors'Last).Release(CarProperties, my_sect, my_time, my_duration, my_fuel, my_consumption, Speed);
485 Put_Line("DEBUG: Auto "&CarProperties.CarId'Img&" è partita e passata dal via.");
486 --inizio la corsa iterando tra i vari Sector
487 while (RetireRequest(CarProperties.CarId) = False) loop
488 --calcolo il giro
489 if (my_sect = 1) then
490 lap := lap +1;
491 end if;
492 -- book
493 if (my_sect /= 0) then
494 Sectors(my_sect).BookExit(CarProperties, my_time);
495 else
496 BoxSector.BookExit(CarProperties, my_time);
497 end if;
499 -- aggiorno dati auto
500 temp:= Float(CarProperties.CarFuel) + my_fuel;
501 if (temp < Float(CarFuel_T'First)) then
502 CarProperties.CarFuel := 0.0;
503 elsif (temp > Float(CarFuel_T'Last)) then
504 CarProperties.CarFuel := CarFuel_T'Last;
505 else CarProperties.CarFuel := CarFuel_T(temp);
506 end if;
507 temp := Float(CarProperties.TiresConsumption) + my_consumption;
508 if (temp < Float(TiresConsumption_T'First)) then
509 CarProperties.TiresConsumption:=TiresConsumption_T'First ;
510 elsif (temp > Float(TiresConsumption_T'Last)) then
511 CarProperties.TiresConsumption := TiresConsumption_T'Last;
512 else CarProperties.TiresConsumption := TiresConsumption_T(temp);
513 end if;
514 -- aggiorno l'auto remota
515 Simulator.Controller.GetCar(CarProperties.CarId).UpdateProperties(CarId => CarProperties.CarId,
516 Tires => CarProperties.Tires,
517 TiresConsumption => CarProperties.TiresConsumption,
518 CarFuel => CarProperties.CarFuel,
519 CarPerformance => CarProperties.CarPerformance,
520 Lap => lap,
521 Sector => my_sect,
522 Speed => Speed,
523 SectorDuration => my_time - old_time);-- my_duration);
525 -- controllo se è un intermedio
526 if (my_sect /= 0 and then Intermediate.Find_Index(Item => my_sect, Index => Intermediate_Count_T'First) /= No_Index ) then
527 inter := Integer(Intermediate.Find_Index(Item => my_sect, Index => Intermediate_Count_T'First));
528 elsif ( my_sect = 0 and then Intermediate.Find_Index(Item => PitStopSector, Index => Intermediate_Count_T'First) /= No_Index) then
529 inter := Integer(Intermediate.Find_Index(Item => PitStopSector, Index => Intermediate_Count_T'First));
530 else
531 inter := 0;
532 end if;
534 old_lap := lap;
535 old_sect := my_sect;
536 old_time := my_time;
537 old_speed := Speed;
538 -- se sto percorrendo i box, notifico la cosa alla gara, che deve saperlo prima che l auto termini di percorrerli
539 if (my_sect = 0) then
540 Simulator.Controller.GetRace.UpdateCarStatus(CarProperties.CarId, old_lap, CarStatus_T(Box));
541 end if;
543 delay until my_time;
545 --release
546 if (my_sect /= 0) then
547 Sectors(my_sect).Release(CarProperties, my_sect, my_time, my_duration, my_fuel, my_consumption, Speed);
548 else
549 BoxSector.Release(CarProperties, my_sect, my_time, my_duration, my_fuel, my_consumption, Speed);
550 end if;
552 -- TEST PER BUG
553 if (old_sect = 0) then
554 old_sect := PitStopSector;
555 end if;
556 --FINE TEST
558 -- aggiorno le statistiche
559 Simulator.Controller.GetRace.UpdateStatistics(CarProperties.CarId, CarProperties.Name,old_lap,old_sect, (old_time - Time_Of(2009,9,21)), old_speed, inter);
560 --controllo se sono in grado di continuare la gara
561 if (CarProperties.CarFuel <= 0.0 or CarProperties.TiresConsumption >= 1.0) then
562 Print("LOG: Auto "&CarProperties.CarId'Img&" non puo' proseguire la gara.");
563 Simulator.Controller.GetRace.Kill(CarProperties.CarId);
564 RetireRequest(CarProperties.CarId) := True;
565 end if;
566 end loop;
568 Put_Line("DEBUG: PutOnPitLane è ritornato dalla simulazione.. Auto "&CarProperties.CarId'Img&" ha terminato la corsa");
569 end PutOnPitLane;
572 function StartRace(n_cars : CarId_T; Randomized : Boolean) return Boolean is
573 begin
574 if (TrackStarted = False) then
575 return False;
576 end if;
577 -- inizializzo PitStopRequest.
578 for Index in 1 .. n_cars loop
579 PitStopRequest(Index) := False;
581 end loop;
582 -- Modifico l'array in base al metodo di partenza deciso;
583 if (Randomized = True) then
584 Put_Line("Randomizzo la griglia di partenza");
585 declare
586 Temp : Semaphore_Ref;
587 G: Generator;
588 pos : CarId_T;
589 begin
590 Reset(G);
591 for Index in 1 .. 48 loop
592 for i in 1 .. CarId_T'Last loop
593 -- intero casuale equamente disribuito tra 1 e n_registered
594 pos := CarId_T( 1 + (Integer(Float(CarId_T'Last ) * Random(G)) mod Integer(CarId_T'Last))) ;
595 -- eseguo lo switch tra l elemento i-esimo e pos-esimo
596 Temp := PitLane(pos);
597 PitLane(pos) := PitLane(i);
598 PitLane(i) := Temp;
599 end loop;
600 end loop;
601 end;
602 Put_Line("Terminata randomizzazione griglia di partenza");
603 end if;
604 -- sveglio la prima auto in attesa su PitLane,
605 declare
606 i: Integer := 1;
607 success : Boolean := False;
608 begin
609 while (i <= Integer(CarId_T'Last) and then success = False) loop
610 PitLane(CarId_T(i)).Signal(True, success);
611 Put_Line("Mando segnale all'auto "&i'Img&" con responso "&success'Img);
612 i := i+1;
613 end loop;
614 end;
615 Put_Line("Race started.");
616 return True;
617 end StartRace;
619 -- Comunica di ritirare l'auto con id = CarId dal circuito
620 procedure Kill(CarId: in CarId_T) is
621 begin
622 Put_Line("Killing car "&CarId'Img&" ...");
623 RetireRequest(CarId) := True;
624 end Kill;
626 -- metodo di richiesta fermata ai box l'invocazione di questo metodo porta
627 -- il circuito a far fare una sosta all'auto "CarId" appena possibile.
628 procedure CallForPitStop(CarId: in CarId_T; CarFuel :CarFuel_T; Tires :Tires_T) is
629 begin
630 PitStopRequest(CarId) := True;
631 PitStopData(CarId) := (CarFuel, Tires);
632 Put_Line("Car "&CarId_T'Image(CarId)&" requires Pit Stop.");
633 end CallForPitStop;
635 procedure InitTrack is
636 begin
637 for i in CarId_T loop
638 PitLane(i) := new Semaphore;
639 end loop;
640 -- Put_Line("griglia di partenza inizializzata");
641 end InitTrack;
643 function ReadTrackConf(confFile : String) return Boolean is
644 Grammar : XML_Grammar;
645 SReader : Schema_Reader;
646 SInput : File_Input;
647 Input : File_Input;
648 Reader : Schema.Dom_Readers.Tree_Reader;
649 Doc : Document;
650 List : Node_List;
651 TrackList : Node_List;
652 BoxList : Node_List;
653 Settore : Node;
654 A : Attr;
655 Livello : Integer;
656 Lunghezza : Natural;
657 Multiplicity : Positive;
658 Weather : String := "------";
659 w : Weather_T;
660 intermedi: Boolean := False;
661 begin
662 Set_Public_Id (SInput, "Schema-file");
663 -- importo il file XMLSchema
664 Open ("schema.xsd", SInput);
665 Parse (SReader, SInput);
666 Close (SInput);
667 Grammar := Get_Created_Grammar (SReader);
668 Global_Check (Grammar);
670 Put_Line("DEBUG: Leggo configurazione da file xml");
671 Set_Validating_Grammar (Reader, Grammar);
674 Set_Public_Id (Input, "Track file");
675 Open (confFile, Input);
676 Set_Feature (Reader, Sax.Readers.Validation_Feature, false);
677 Set_Feature (Reader, Sax.Readers.Namespace_Feature, false);
678 Set_Feature (Reader, Sax.Readers.Schema_Validation_Feature, True);
680 Parse (Reader, Input);
681 Close (Input);
682 Doc := Get_Tree (Reader);
683 TrackList := Get_Elements_By_Tag_Name(Doc, "track");
685 if (Length(TrackList) /= 1) then
686 Put_Line("Errore nel file XML. Ogni file deve contenere esattamente un elemento track");
687 end if;
688 List := Get_Elements_By_Tag_Name(Doc, "sector");
689 Put_Line("DEBUG TRACK:ci sono "&Length(List)'Img&" settori");
690 Sectors := new Sector_Array_T(1 .. Length(List));
691 Corsie:= new Corsie_Array_T (1 .. Length(List) + 1);
692 ExitOrder := new ExitOrder_T(1 .. Length(List) +1);
694 for Index in 1 .. Length (List) loop
695 Settore := Item (List, Index - 1);
696 A := Get_Named_Item (Attributes (Settore), "level");
697 Livello := Integer'Value (Node_Value(A)) ;
698 A := Get_Named_Item (Attributes (Settore), "length");
699 Lunghezza := Natural'Value (Node_Value(A));
700 A := Get_Named_Item (Attributes (Settore), "multiplicity");
701 Multiplicity := Positive'Value (Node_Value(A));
702 -- Creo l'array Corsie_T relativo al settore
703 Corsie(Index) := new Corsie_T( 1 .. Multiplicity);
704 ExitOrder(Index) := new CarIdVector_T.Vector;
705 --weather
706 A := Get_Named_Item (Attributes (Settore), "weather");
707 -- Se l'attributo weather non è specificato, il settore è asciutto
708 if( A = null or else Node_Value(A) = "dry") then
709 Put_Line("dry sector");
710 w := Dry;
711 else
712 Put_Line("wet sector");
713 w := Wet;
714 end if;
716 A := Get_Named_Item (Attributes (Settore), "intermediate");
718 if( A /= null and then Boolean'Value (Node_Value(A)) = True) then
719 Intermediate.Append(Index);
720 Put_Line("intertempo");
721 end if;
723 --Creo il settore e i lane
724 Sectors(Index) := new Sector(Index,Multiplicity,Lunghezza,Livello,False);
725 for i in 1 .. Multiplicity loop
726 Corsie(Index)(i) := new Lane_T(Lunghezza,Livello,w,False);
727 end loop;
728 Put_Line ("creato settore "& Index'Img);
730 BoxList := Child_Nodes( Settore);
731 if (Length(BoxList) /= 0) then
732 Put_Line("Inizializzo box");
733 PitStopSector := Index;
735 A := Get_Named_Item (Attributes (Item(BoxList,1)), "length");
736 Lunghezza := Natural'Value (Node_Value(A));
737 BoxSector := new Sector(Index, MaxId, Lunghezza, Livello, True);
738 -- Creo l'array Corsie_T relativo ai box .. Moltiplicità MaxId
739 Corsie(Length(List) + 1) := new Corsie_T( 1 .. MaxId);
740 ExitOrder(Length(List) + 1) := new CarIdVector_T.Vector;
741 for i in 1 .. MaxId loop
742 Corsie(Length( List ) + 1)(i) := new Lane_T(Lunghezza,Livello,w,True);
743 end loop;
744 Put_Line("Trovati box nel sttore "& PitStopSector'Img&" di lunghezza "&Lunghezza'Img);
745 end if;
746 end loop;
747 -- Inizializzo PitLane
748 -- for i in CarId_T loop
749 -- PitLane(i) := new Semaphore;
750 -- end loop;
751 Free (List);
752 Free (Reader);
753 TrackStarted := True;
754 return True;
755 exception
756 when Error : others =>
757 Print_NoLock("Errore nel file di configurazione");
758 Print_NoLock(Exception_Message(Error));
759 return False;
760 end ReadTrackConf;
762 end Simulator.Track;