X-Git-Url: https://www.fi.muni.cz/~kas/git//home/kas/public_html/git/?a=blobdiff_plain;f=SCX%2FTrack.pm;h=c5d464068b5e79e4418077d8a621e096205e1e54;hb=e85448fbe0a0384457115dc91638aa773fd9c5c0;hp=ab12a44e09aa3e6b37dd651f1461ae6932a74cce;hpb=e22f8cbb94df063c77cc9ee5f5bae839e252777d;p=slotcarman.git diff --git a/SCX/Track.pm b/SCX/Track.pm index ab12a44..c5d4640 100644 --- a/SCX/Track.pm +++ b/SCX/Track.pm @@ -5,8 +5,12 @@ package SCX::Track; use strict; use Carp; +use Time::HiRes qw(gettimeofday); +use Glib qw(TRUE FALSE); use SCX::Car; +our $SEMAPHORE_STEP = 1000; + sub new { my ($class, $args) = @_; @@ -16,17 +20,208 @@ sub new { $self->{race_running} = 0; $self->{lap_counting_up} = 1; + bless $self, $class; + for my $i (0..5) { $self->{cars}->[$i] = SCX::Car->new({ gui => $self->{gui}, - order => $i, + id => $i, + track => $self, }); + $self->car($i)->set_order($i); } - bless $self, $class; + return $self; } sub car { return shift->{cars}->[shift]; } +sub race_start { + my ($self) = @_; + + return if $self->{race_running} || $self->{start_in_progress} + || $self->{qualification_running}; + $self->{race_running} = 0; + $self->{start_in_progress} = 1; + $self->{semaphore} = 0; + $self->{gui}->show_semaphore(0); + Glib::Timeout->add($SEMAPHORE_STEP, \&semaphore_step, $self); +} + +sub semaphore_step { + my ($self) = @_; + + return FALSE if !$self->{start_in_progress} && !$self->{race_running}; + + $self->{semaphore}++; + if ($self->{semaphore} <= 5) { + $self->{gui}->show_semaphore($self->{semaphore}); + my $timeout = $SEMAPHORE_STEP; + $timeout += $SEMAPHORE_STEP * rand() + if $self->{semaphore} == 5; + Glib::Timeout->add($timeout, \&semaphore_step, $self); + } elsif ($self->{semaphore} == 6) { + $self->{race_running} = 1; + $self->{race_running_since} = gettimeofday; + $self->{start_in_progress} = undef; + $self->{gui}->show_semaphore(0); + Glib::Timeout->add($SEMAPHORE_STEP, \&semaphore_step, $self); + } else { + $self->{gui}->show_semaphore(undef); + $self->{semaphore} = undef; + } + return FALSE; +} +sub race_end { + my ($self) = @_; + + $self->{race_running} = 0; +} + +sub race_setup { + my ($self, $rounds) = @_; + + $self->{round} = 0; + if ($rounds) { + $self->{race_rounds} = $rounds; + } else { + $self->{race_rounds} = 0; + } + + $self->print_rounds; + $self->{best_lap} = undef; + + $self->{gui}->show_semaphore(undef); + $self->{race_running} = 0; + $self->{start_in_progress} = 0; + + $self->{gui}->time(undef); + $self->{gui}->best_lap(undef); +} + +sub reset { + my ($self) = @_; + + $self->{race_running} = 0; + $self->{start_in_progress} = 0; + $self->{best_lap} = undef; + $self->{round} = 0; + + $self->print_rounds; + $self->{gui}->best_lap(undef); + $self->{gui}->time(undef); + + for my $car (0..5) { + $self->car($car)->reset; + } +} + +sub print_rounds { + my ($self) = @_; + + $self->{gui}->rounds($self->{qualification_running} + ? 'Qualification' + : $self->{race_rounds} + ? $self->{round} . '/' . $self->{race_rounds} + : $self->{round} + ); +} + +sub check_best_lap { + my ($self, $time, $who) = @_; + + return if !defined $time || $time == 0; + +# print "Check_best_lap $time $who vs ", +# defined $self->{best_lap} ? $self->{best_lap} : 'undef', +# "\n"; + if (!defined $self->{best_lap} + || $time < $self->{best_lap}) { + $self->{best_lap} = $time; + $self->{gui}->best_lap($time, $who); + return 1; + } + return 0; +} + +sub qualification_start { + my ($self) = @_; + + return if $self->{qualification_running}; + for my $car (0..5) { + $self->car($car)->set_lap(undef); + $self->car($car)->set_laptime(undef); + } + + $self->{qualification_running} = 1; + $self->{gui}->rounds('Qualification'); + $self->{gui}->time(undef); + $self->{gui}->best_lap(undef); +} + +sub packet_received { + my ($self, $time) = @_; + + if ($self->{race_running}) { + $self->{gui}->time($time - $self->{race_running_since}); + } +} + +sub recalc_order { + my ($self, $now) = @_; + + return if !$self->{race_running}; + + my @laps; + my @times; + for my $id (0..5) { + $laps[$id] = $self->car($id)->{lap} // -1; + $times[$id] = $self->car($id)->{first_finish_time} // $now; + } + + my @new_order = sort { + $laps[$b] <=> $laps[$a] + || + $times[$a] <=> $times[$b] + || + $a <=> $b; + } (0..5); + + my $lap_max = $laps[$new_order[0]]; + if (defined $lap_max && $self->{round} && $lap_max != $self->{round} + && (!$self->{race_rounds} + || $lap_max <= $self->{race_rounds})) { + $self->{round} = $lap_max; + $self->print_rounds; + } + + for my $id (0..5) { + my $car = $new_order[$id]; + if ($self->car($car)->{order} != $id) { + $self->car($car)->set_order($id); + } + } + return ($new_order[0], $lap_max, $times[$new_order[0]]); +} + +sub finish_line { + my ($self, $time, $regular, @cars) = @_; + + my @processed; + for my $car (@cars) { + push @processed, $car + if $self->car($car)->finish_line($time, $regular); + } + + if (@processed) { + my ($first_car, $lap_max, $time_min) + = $self->recalc_order($time); + + for my $car (@processed) { + $self->car($car)->recalc_distance($lap_max, $time_min); + } + } +} + 1;