8 use Glib qw(TRUE FALSE);
11 our $SEMAPHORE_STEP = 1000;
14 my ($class, $args) = @_;
22 qualification_setup => -100,
23 no_semaphore => $args->{no_semaphore},
29 $self->{cars}->[$i] = SCX::Car->new({
37 $self->{gui}->time(undef);
38 $self->{gui}->best_lap(undef, undef);
43 sub car { return shift->{cars}->[shift]; }
46 my ($self, $time) = @_;
48 return if $self->{race_running} || $self->{start_in_progress}
49 || $self->{qualification_running};
51 if ($time - $self->{qualification_setup} < 1) {
52 $self->{qualification_running} = 1;
53 } elsif ($self->{no_semaphore}) {
55 $self->{race_running} = 1;
56 $self->{race_running_since} = $self->{now};
57 $self->{start_in_progress} = undef;
60 $self->{race_running} = 0;
61 $self->{start_in_progress} = 1;
62 $self->{semaphore} = 0;
63 $self->{gui}->show_semaphore(0);
64 Glib::Timeout->add($SEMAPHORE_STEP, \&semaphore_step, $self);
72 return FALSE if !$self->{start_in_progress} && !$self->{race_running};
75 if ($self->{semaphore} <= 5) {
76 $self->{gui}->show_semaphore($self->{semaphore});
77 my $timeout = $SEMAPHORE_STEP;
78 $timeout += $SEMAPHORE_STEP * rand()
79 if $self->{semaphore} == 5;
80 Glib::Timeout->add($timeout, \&semaphore_step, $self);
81 } elsif ($self->{semaphore} == 6) {
82 $self->{race_running} = 1;
83 $self->{race_running_since} = $self->{now};
84 $self->{start_in_progress} = undef;
85 $self->{gui}->show_semaphore(0);
86 Glib::Timeout->add($SEMAPHORE_STEP, \&semaphore_step, $self);
88 $self->{gui}->show_semaphore(undef);
89 $self->{semaphore} = undef;
97 $self->{race_running} = 0;
101 my ($self, $rounds, $time) = @_;
103 if ($time - $self->{qualification_setup} < 1) {
107 $self->{race_rounds} = $rounds;
109 $self->{race_rounds} = 0;
115 $self->{best_lap} = undef;
117 $self->{gui}->show_semaphore(undef);
118 $self->{race_running} = 0;
119 $self->{qualification_running} = 0;
120 $self->{start_in_progress} = 0;
122 $self->{gui}->time(undef);
123 $self->{gui}->best_lap(undef);
126 $self->car($car)->reset;
133 $self->{race_running} = 0;
134 $self->{qualification_running} = 0;
135 $self->{start_in_progress} = 0;
136 $self->{race_finishing} = 0;
137 $self->{best_lap} = undef;
141 $self->{gui}->best_lap(undef);
142 $self->{gui}->time(undef);
145 $self->car($car)->reset;
153 if ($self->{qualification_running}
154 || $self->{now} - $self->{qualification_setup} < 1) {
155 $msg = 'Qualification: ' . $self->{race_rounds}
156 . ($self->{race_rounds} == 1 ? ' round' : ' rounds');
157 } elsif ($self->{race_rounds}) {
158 $msg = $self->{round} . '/' . $self->{race_rounds};
160 $msg = $self->{round};
163 $self->{gui}->rounds($msg);
167 my ($self, $time, $who) = @_;
169 return if !defined $time || $time == 0;
171 # print "Check_best_lap $time $who vs ",
172 # defined $self->{best_lap} ? $self->{best_lap} : 'undef',
174 if (!defined $self->{best_lap}
175 || $time < $self->{best_lap}) {
176 $self->{best_lap} = $time;
177 $self->{gui}->best_lap($time, $who);
183 sub qualification_setup {
184 my ($self, $rounds, $cars, $time) = @_;
186 return if $self->{qualification_running};
189 $self->car($car)->set_lap(undef);
190 $self->car($car)->set_laptime(undef);
193 $self->{qualification_setup} = $time;
194 $self->{race_rounds} = $rounds;
195 $self->{qualification_cars} = $cars;
196 $self->{gui}->time(undef);
197 $self->{gui}->best_lap(undef);
201 sub packet_received {
202 my ($self, $time) = @_;
204 $self->{now} = $time;
206 if ($self->{race_running}) {
207 $self->{gui}->time($time - $self->{race_running_since});
212 my ($self, $now) = @_;
214 return if !$self->{race_running};
219 $laps[$id] = $self->car($id)->{lap} // -1;
220 $times[$id] = $self->car($id)->{first_finish_time} // $now;
223 my @new_order = sort {
224 $laps[$b] <=> $laps[$a]
226 $times[$a] <=> $times[$b]
231 my $lap_max = $laps[$new_order[0]];
232 my $lap_max_changed = 0;
233 if (defined $lap_max && defined $self->{round}
234 && $lap_max != $self->{round}) {
235 $self->{round} = $lap_max;
236 $lap_max_changed = 1;
240 if ($self->{round} && $self->{race_rounds}
241 && $self->{round} > $self->{race_rounds}) {
242 $self->{race_finishing} = 1;
246 my $car = $new_order[$id];
247 if ($self->car($car)->{order} != $id) {
248 $self->car($car)->set_order($id);
251 return ($lap_max_changed, $lap_max, $times[$new_order[0]]);
254 sub recalc_qual_order {
257 return if !$self->{qualification_running};
261 $times[$id] = $self->car($id)->{best_lap};
262 if (!defined $times[$id] || $times[$id] <= 0) {
263 $times[$id] = 999_999;
267 my @new_order = sort {
268 $times[$a] <=> $times[$b]
273 my $best_time = $times[$new_order[0]];
276 my $car = $new_order[$id];
277 if ($self->car($car)->{order} != $id) {
278 $self->car($car)->set_order($id);
281 return ($times[$new_order[0]]);
285 my ($self, $time, $regular, @cars) = @_;
290 for my $car (@cars) {
291 if ($self->car($car)->finish_line($time, $regular)) {
292 $processed{$car} = 1;
297 return if !$was_processed;
299 if ($self->{qualification_running}) {
300 my ($best) = $self->recalc_qual_order;
302 $self->car($car)->recalc_qual_distance($best);
307 my ($lap_max_changed, $lap_max, $time_min)
308 = $self->recalc_order($time);
311 if ($processed{$car}) {
312 $self->car($car)->recalc_distance(
313 $lap_max, $time_min, $self->{race_finishing},
315 } elsif ($lap_max_changed) {
316 $self->car($car)->greyout_distance;