#!/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')) { 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); 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'; 16136 21804 30291 30686 32746 32753 32754 32757 32759 32778 32813 32837 34595 34596 34598 34599 34603 34604 34608 34650 34654 39546 40549 42335 42611 42612 42613 42614 50169 50711 52484 84146 END_OF_NUMBERS if ($estudents{$suffix}) { return 1; } return 0; }