8 use Glib qw(TRUE FALSE);
11 our $SEMAPHORE_STEP = 1000;
14 my ($class, $args) = @_;
22 qualification_setup => -100,
28 $self->{cars}->[$i] = SCX::Car->new({
36 $self->{gui}->time(undef);
37 $self->{gui}->best_lap(undef, undef);
42 sub car { return shift->{cars}->[shift]; }
45 my ($self, $time) = @_;
47 return if $self->{race_running} || $self->{start_in_progress}
48 || $self->{qualification_running};
50 if ($time - $self->{qualification_setup} < 1) {
51 $self->{qualification_running} = 1;
54 $self->{race_running} = 0;
55 $self->{start_in_progress} = 1;
56 $self->{semaphore} = 0;
57 $self->{gui}->show_semaphore(0);
58 Glib::Timeout->add($SEMAPHORE_STEP, \&semaphore_step, $self);
66 return FALSE if !$self->{start_in_progress} && !$self->{race_running};
69 if ($self->{semaphore} <= 5) {
70 $self->{gui}->show_semaphore($self->{semaphore});
71 my $timeout = $SEMAPHORE_STEP;
72 $timeout += $SEMAPHORE_STEP * rand()
73 if $self->{semaphore} == 5;
74 Glib::Timeout->add($timeout, \&semaphore_step, $self);
75 } elsif ($self->{semaphore} == 6) {
76 $self->{race_running} = 1;
77 $self->{race_running_since} = $self->{now};
78 $self->{start_in_progress} = undef;
79 $self->{gui}->show_semaphore(0);
80 Glib::Timeout->add($SEMAPHORE_STEP, \&semaphore_step, $self);
82 $self->{gui}->show_semaphore(undef);
83 $self->{semaphore} = undef;
91 $self->{race_running} = 0;
95 my ($self, $rounds, $time) = @_;
97 if ($time - $self->{qualification_setup} < 1) {
101 $self->{race_rounds} = $rounds;
103 $self->{race_rounds} = 0;
109 $self->{best_lap} = undef;
111 $self->{gui}->show_semaphore(undef);
112 $self->{race_running} = 0;
113 $self->{qualification_running} = 0;
114 $self->{start_in_progress} = 0;
116 $self->{gui}->time(undef);
117 $self->{gui}->best_lap(undef);
123 $self->{race_running} = 0;
124 $self->{qualification_running} = 0;
125 $self->{start_in_progress} = 0;
126 $self->{race_finishing} = 0;
127 $self->{best_lap} = undef;
131 $self->{gui}->best_lap(undef);
132 $self->{gui}->time(undef);
135 $self->car($car)->reset;
143 if ($self->{qualification_running}
144 || $self->{now} - $self->{qualification_setup} < 1) {
145 $msg = 'Qualification: ' . $self->{race_rounds}
146 . ($self->{race_rounds} == 1 ? ' round' : ' rounds');
147 } elsif ($self->{race_rounds}) {
148 $msg = $self->{round} . '/' . $self->{race_rounds};
150 $msg = $self->{round};
153 $self->{gui}->rounds($msg);
157 my ($self, $time, $who) = @_;
159 return if !defined $time || $time == 0;
161 # print "Check_best_lap $time $who vs ",
162 # defined $self->{best_lap} ? $self->{best_lap} : 'undef',
164 if (!defined $self->{best_lap}
165 || $time < $self->{best_lap}) {
166 $self->{best_lap} = $time;
167 $self->{gui}->best_lap($time, $who);
173 sub qualification_setup {
174 my ($self, $rounds, $cars, $time) = @_;
176 return if $self->{qualification_running};
179 $self->car($car)->set_lap(undef);
180 $self->car($car)->set_laptime(undef);
183 $self->{qualification_setup} = $time;
184 $self->{race_rounds} = $rounds;
185 $self->{qualification_cars} = $cars;
186 $self->{gui}->time(undef);
187 $self->{gui}->best_lap(undef);
191 sub packet_received {
192 my ($self, $time) = @_;
194 $self->{now} = $time;
196 if ($self->{race_running}) {
197 $self->{gui}->time($time - $self->{race_running_since});
202 my ($self, $now) = @_;
204 return if !$self->{race_running};
209 $laps[$id] = $self->car($id)->{lap} // -1;
210 $times[$id] = $self->car($id)->{first_finish_time} // $now;
213 my @new_order = sort {
214 $laps[$b] <=> $laps[$a]
216 $times[$a] <=> $times[$b]
221 my $lap_max = $laps[$new_order[0]];
222 my $lap_max_changed = 0;
223 if (defined $lap_max && defined $self->{round}
224 && $lap_max != $self->{round}) {
225 $self->{round} = $lap_max;
226 $lap_max_changed = 1;
230 if ($self->{round} && $self->{race_rounds}
231 && $self->{round} > $self->{race_rounds}) {
232 $self->{race_finishing} = 1;
236 my $car = $new_order[$id];
237 if ($self->car($car)->{order} != $id) {
238 $self->car($car)->set_order($id);
241 return ($lap_max_changed, $lap_max, $times[$new_order[0]]);
244 sub recalc_qual_order {
247 return if !$self->{qualification_running};
251 $times[$id] = $self->car($id)->{best_lap};
252 if (!defined $times[$id] || $times[$id] <= 0) {
253 $times[$id] = 999_999;
257 my @new_order = sort {
258 $times[$a] <=> $times[$b]
263 my $best_time = $times[$new_order[0]];
266 my $car = $new_order[$id];
267 if ($self->car($car)->{order} != $id) {
268 $self->car($car)->set_order($id);
271 return ($times[$new_order[0]]);
275 my ($self, $time, $regular, @cars) = @_;
280 for my $car (@cars) {
281 if ($self->car($car)->finish_line($time, $regular)) {
282 $processed{$car} = 1;
287 return if !$was_processed;
289 if ($self->{qualification_running}) {
290 my ($best) = $self->recalc_qual_order;
292 $self->car($car)->recalc_qual_distance($best);
297 my ($lap_max_changed, $lap_max, $time_min)
298 = $self->recalc_order($time);
301 if ($processed{$car}) {
302 $self->car($car)->recalc_distance(
303 $lap_max, $time_min, $self->{race_finishing},
305 } elsif ($lap_max_changed) {
306 $self->car($car)->greyout_distance;