#!/usr/bin/perl use strict; use utf8; use TAP::Parser; use Data::Dumper; use Cwd; binmode(STDOUT, ':utf8'); binmode(STDERR, ':utf8'); my %overrides = (); if (-r 'overrides.txt') { read_overrides(); } my @reports = sort @ARGV; my $total; my %section_points = ('A' => 0, 'B' => 0, 'C' => 0); my $student_id = get_student_id(); if (defined $student_id) { print "STUDENT ID is $student_id\n"; } else { print "UNKNOWN STUDENT ID\n"; } intro(); for my $report (@reports) { update_total($report, process_report($report)); } outro($total); sub get_student_id { my $pwd = cwd(); if (my ($student_id) = ($pwd =~ m{-s(\d{5,7})(/arena)?})) { return $student_id; } return undef; } sub update_total { my ($report_file_path, $points) = @_; my $section = get_section($report_file_path); if (defined $section && ($section ne 'A' && $section ne 'B' && $section ne 'C' && $section ne 'D' && $section ne 'E' && $section ne 'F' && $section ne 'G' && $section ne 'H')) { if ($section_points{$section} > 0) { print "UWAGA: TYLKO ZADANIE Z NAJWIĘKSZĄ LICZBĄ PUNKTÓW BĘDZIE LICZONE DLA DZIAŁU $section\n"; } if ($points > $section_points{$section}) { $total = $total - $section_points{$section} + $points; $section_points{$section} = $points; } } else { $total += $points; } } sub get_section { my ($report_file_path) = @_; if (my ($section) = ($report_file_path =~ m{Task([ABC])})) { return $section; } return undef; } sub get_failures_and_successes { my ($file_path) = @_; open my $tap_fh, $file_path or die $!; my $tap_parser = TAP::Parser->new( { source => $tap_fh } ); while ( my $result = $tap_parser->next ) { } return (scalar($tap_parser->actual_failed), scalar($tap_parser->passed)) } sub process_report { my ($report_file) = @_; my ($task_id) = ($report_file =~ m{^(.*)/report\.txt$}); my $override_key = get_override_key($student_id, $task_id); if (exists $overrides{$override_key}) { my $override_points = $overrides{$override_key}; print $task_id, " ", "FROM overrides.txt: ", $override_points, "\n"; return $override_points; } my ($nb_of_failures, $nb_of_successes) = get_failures_and_successes($report_file); my $success = ($nb_of_failures == 0 && $nb_of_successes > 0); my ($points, $deadline, $total, $remainder) = parse_description($task_id); if (is_estudent($student_id)) { if ($task_id =~ /E..$/) { $deadline = '2021-01-07 15:30:00'; } if ($task_id =~ /F..$/) { $deadline = '2021-01-25 23:59:59'; } } print $task_id, " ", ($success ? "PASSED" : "FAILED"); if (!check_deadline($task_id, $deadline)) { $success = 0; } if (!check_if_the_right_task($student_id, $task_id, $total, $remainder)) { print " WRONG TASK!"; $success = 0; } if (!$success) { $points = 0; } if ($success) { print " POINTS: $points"; } print "\n"; return $points; } sub check_deadline { my ($task_id, $deadline) = @_; for my $file (glob "$task_id/*") { if ($file !~ m{\.(in|arg|out|exp|\~)$|/(description\.txt|run)$}) { my $dir_to_check = "../djfz-2020-s$student_id"; if (not defined($student_id)) { $dir_to_check = '.'; } my $last_timestamp = `(cd $dir_to_check; git log -1 --format=\%cd --date=iso $file 2> /dev/null)`; if ($last_timestamp =~ m{\S}) { chomp $last_timestamp; if ($last_timestamp gt $deadline) { print " TOO LATE [$file: $last_timestamp later than $deadline]"; return 0; } } } } return 1; } sub check_if_the_right_task { my ($student_id, $task_id, $total, $remainder) = @_; if (defined($total)) { if ($student_id % $total != $remainder) { return 0; } } # return 0 if $task_id =~ m{^TaskE} and not is_estudent($student_id); # return 0 if $task_id =~ m{^Task[AC]} and is_estudent($student_id); return 1; } sub intro { print_header(); print "SUMMARY\n\n"; } sub outro { my ($points) = @_; print "\nTOTAL POINTS: $points\n"; open my $fh, '>', 'result.csv'; print $fh "POINTS\n"; print $fh $points, "\n"; close($fh); print_header(); } sub print_header { print "=" x 20,"\n"; } sub parse_description { my ($task_id) = @_; open my $fh, '<', "$task_id/description.txt" or die "???"; my $points = 0; my $deadline = undef; my $total = undef; my $remainder = undef; while (my $line=<$fh>) { if ($line =~ m{^POINTS\s*:\s*(\d+)\s*$}) { $points = $1; } elsif ($line =~ m{^DEADLINE\s*:\s*(.*?)\s*$}) { $deadline = $1; } elsif ($line =~ m{^REMAINDER\s*:\s*(\d+)/(\d+)\s*$}) { $remainder = $1; $total = $2; } } return ($points, $deadline, $total, $remainder); } sub read_overrides { open my $fh, '<', 'overrides.txt'; while (my $line=<$fh>) { chomp $line; my ($id, $task, $points, $info) = split/\s+/,$line; $overrides{get_override_key($id, "Task".$task)} = $points; } } sub get_override_key { my ($id, $task) = @_; return $id.'+'.$task; } sub is_estudent { my ($id) = @_; my $suffix = substr($id, 1); my %estudents = map { $_ => 1 } split/\n/,<<'END_OF_NUMBERS'; 500276 44517 500259 42720 44519 500271 42611 39546 42612 44416 25077 16136 32754 44522 44523 42614 END_OF_NUMBERS if ($estudents{$suffix}) { return 1; } return 0; }