-my (@rubric) = read_text_file (shift);
-my (@pass) = @ARGV;
-
-my (@grade);
-
-our ($possible_overall, $score_overall) = (0, 0);
-our ($possible, $score) = (0, 0);
-for my $i (0...$#rubric) {
- local ($_) = $rubric[$i];
- if (/^\S/ || /^\s*$/) {
- end_section ();
- push (@grade, $_);
- } elsif (my ($value, $name, $desc) = /^\s+(\d+)\s+(\S+):\s+(.*)$/) {
- $possible += $value;
- my ($marker);
- if (grep ($_ eq $name, @pass)) {
- $score += $value;
- $marker = ' ';
- } else {
- $marker = '-';
- }
- push (@grade, " $marker$value $name: $desc");
- } else {
- die;
+@ARGV == 3 || die;
+my ($src_dir, $results_file, $grading_file) = @ARGV;
+
+# Read pass/file verdicts from $results_file.
+open (RESULTS, '<', $results_file) || die "$results_file: open: $!\n";
+my (%verdicts, %verdict_counts);
+while (<RESULTS>) {
+ my ($verdict, $test) = /^(pass|FAIL) (.*)$/ or die;
+ $verdicts{$test} = $verdict eq 'pass';
+}
+close RESULTS;
+
+my (@failures);
+my (@overall, @rubrics, @summary);
+my ($pct_actual, $pct_possible) = (0, 0);
+
+# Read grading file.
+my (@items);
+open (GRADING, '<', $grading_file) || die "$grading_file: open: $!\n";
+while (<GRADING>) {
+ s/#.*//;
+ next if /^\s*$/;
+ my ($max_pct, $rubric_suffix) = /^\s*(\d+(?:\.\d+)?)%\t(.*)/ or die;
+ my ($dir) = $rubric_suffix =~ /^(.*)\//;
+ my ($rubric_file) = "$src_dir/$rubric_suffix";
+ open (RUBRIC, '<', $rubric_file) or die "$rubric_file: open: $!\n";
+
+ # Rubric file must begin with title line.
+ my $title = <RUBRIC>;
+ chomp $title;
+ $title =~ s/:$// or die;
+ $title .= " ($rubric_suffix):";
+ push (@rubrics, $title);
+
+ my ($score, $possible) = (0, 0);
+ my ($cnt, $passed) = (0, 0);
+ my ($was_score) = 0;
+ while (<RUBRIC>) {
+ chomp;
+ push (@rubrics, "\t$_"), next if /^-/;
+ push (@rubrics, ""), next if /^\s*$/;
+ my ($poss, $name) = /^(\d+)\t(.*)$/ or die;
+ my ($test) = "$dir/$name";
+ my ($points) = 0;
+ if (!defined $verdicts{$test}) {
+ push (@overall, "warning: $test not tested, assuming failure");
+ } elsif ($verdicts{$test}) {
+ $points = $poss;
+ $passed++;
+ }
+ push (@failures, $test) if !$points;
+ $verdict_counts{$test}++;
+ push (@rubrics, sprintf ("\t%4s%2d/%2d %s",
+ $points ? '' : '**', $points, $poss, $test));
+ $score += $points;
+ $possible += $poss;
+ $cnt++;