#!/usr/bin/perl
# Description:
#  Simple script to check that a gantt is correct, with regard to overlaping jobs
# Usage:
#  oarstat -g "2008-04-29 18:00:00, 2008-04-30 08:00:00" | ./test_gantt_overlap.pl
# Todo:
#  - handle timesharing jobs
#  - handle container jobs
#  - ...

use strict;
use Data::Dumper;
my $gantt_input;
while (<STDIN>) {
    $gantt_input .= $_;
}

my $gantt  = eval($gantt_input);
my $jobs   = $gantt->{jobs};
my @jobids = keys(%$jobs);

sub match($$) {
    my $a1 = shift;
    my $a2 = shift;
    my %h;
    my @res;
    foreach my $k (@$a1, @$a2) {
        if (exists($h{$k})) {
            push @res, $k;
        }
        $h{$k} = undef;
    }
    return @res;
}

while (my $jobid0 = shift(@jobids)) {
    foreach my $jobidN (@jobids) {
        if (
            (
                # job0 across jobN start_time
                $jobs->{$jobid0}->{start_time} <= $jobs->{$jobidN}->{start_time} and
                $jobs->{$jobid0}->{stop_time} >= $jobs->{$jobidN}->{start_time}
            ) or
            (
                # job0 across jobN stop_time
                $jobs->{$jobid0}->{start_time} <= $jobs->{$jobidN}->{stop_time} and
                $jobs->{$jobid0}->{stop_time} >= $jobs->{$jobidN}->{stop_time}
            ) or
            (
                # job0 within jobN
                $jobs->{$jobid0}->{start_time} >= $jobs->{$jobidN}->{start_time} and
                $jobs->{$jobid0}->{stop_time} <= $jobs->{$jobidN}->{stop_time})
        ) {

            my @m = match($jobs->{$jobid0}->{resources}, $jobs->{$jobidN}->{resources});
            if ($#m > 0) {

                # exceptions
                my $ok;
                foreach my $r ($jobid0, $jobidN) {
                    my $j = ($r == $jobid0) ? $jobidN : $jobid0;
                    if (    # besteffort
                        $jobs->{$r}->{queue_name} eq 'besteffort' and
                        $jobs->{$j}->{queue_name} ne 'besteffort' and
                        $jobs->{$r}->{state} eq 'Waiting'         and    #other states ?
                        $jobs->{$j}->{state} eq 'Waiting'         and    #other states ?
                        $jobs->{$r}->{start_time} < $jobs->{$j}->{start_time}
                    ) {
                        $ok = 1;
                    } elsif (0) {    # container
                    } elsif (0) {    # timesharing
                    }
                    last if (defined($ok));
                }
                unless (defined($ok)) {
                    print "CONFLICT: $jobid0 and $jobidN\n";
                    foreach my $j ($jobid0, $jobidN) {
                        print "|-[$j]-start_time: " . localtime($jobs->{$j}->{start_time}) . "\n";
                        print "|-[$j]-stop_time: " . localtime($jobs->{$j}->{stop_time}) . "\n";
                        print "|-[$j]-user: " . $jobs->{$j}->{user} . "\n";
                        print "|-[$j]-walltime: " . $jobs->{$j}->{walltime} . "\n";
                    }
                    print "`-conficting resources: " . join(", ", @m) . "\n";
                }
            }
        }
    }
}
