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