#!/usr/bin/perl 
#
# I unproudly present to you ..... the .....
#
# Tournement Bruteforce Tool
#
# Some friends and I were organising a tournement. We had to make a scheme.
#
# The 'input' to our issue:
#  - Team C1 and D2 had the wish not to play in the same round
#  - Team C4 had the wish the skip the first 5 rounds
#  - Teams should not have to wait too long between matches
#  - There are two playfields
#  - We already know which matches will be played. We created that scheme in some MS-tool.
#  		Poule A+B : 4 teams, plays cross finals (1st of A plays against 1st of B, etc).
#  		Poule C+D : 5 teams
# The 'output' should be:
#  - A scheme that fits :)
#
# This tool tries to 'brute force' such a scheme in a really dump and inefficient way.
# ..... But it will get the job done :)
#
# You may use this tool, but i won't stand in for the concequences :)
# The code is bad and ugly, should rewrite it once ...
#
# By Pet (painfullscratch.nl)
 
use strict;
use warnings;

if(scalar(@ARGV) != 1) { 
	print STDERR "Usage: $0 <waittime>\n";
	print STDERR " i.e.: $0 8\n";
	exit(1);
} 

my $verbose = 0;
my $waittime = $ARGV[0];
my $number_of_fields = 2;
my @matches = (
	[qw/A1 A2/], [qw/A3 A4/], [qw/C1 C2/], [qw/C5 C3/], [qw/B2 B4/], [qw/A1 A4/],
	[qw/D3 D4/], [qw/C1 C3/], [qw/C2 C4/], [qw/D2 D3/], [qw/C5 C1/], [qw/D1 D3/],
	[qw/B1 B4/], [qw/B2 B3/], [qw/D4 D1/], [qw/C4 C5/], [qw/D4 D5/], [qw/B3 B4/],
	[qw/D5 D3/], [qw/D1 D2/], [qw/B1 B3/], [qw/A2 A3/], [qw/C2 C5/], [qw/D5 D1/],
	[qw/D2 D4/], [qw/B1 B2/], [qw/C2 C3/], [qw/A2 A4/], [qw/C3 C4/], [qw/A1 A3/],
	[qw/D2 D5/], # [qw/C4 C1/], # See below
);

my $data; 				# placeholder for the result

OUTER: while(1) { 		# infinite loop

	$data = undef; 		# clear placeholder
	my $rounds = {}; 	# hashref containing all rounds
 
	# Default matches ..
	push(@{$rounds->{'16'} ||= []},[qw/4A 4B/]); # 4th of A against 4th of B
	push(@{$rounds->{'17'} ||= []},[qw/2A 2B/]); # 2nd of A against 2nd of B
	push(@{$rounds->{'17'} ||= []},[qw/3A 3B/]); # 3th of A against 3th of B
	push(@{$rounds->{'18'} ||= []},[qw/1A 1B/]); # 1st of A against 1st of B
	push(@{$rounds->{'18'} ||= []},[qw/C4 C1/]); # I want these guys to play the last round

	my $round = 1; 
	foreach my $match (sort { (-1,1)[rand 2] } @matches) {
		push(@{$rounds->{$round} ||= []},$match);
		if(scalar(@{$rounds->{$round}}) == $number_of_fields) { 
			$round++;
		} 
	} 

	my $hist = {}; # hashref that will keep track of the team's last playround

INNER: foreach my $round (sort { $a <=> $b } keys %$rounds) { 

		# Some shortcuts to increase readability
		my $a = $rounds->{$round}[0][0];
		my $b = $rounds->{$round}[0][1];
		my $c = $rounds->{$round}[1][0];
		my $d = $rounds->{$round}[1][1];
	
		$data .= $round."\t".$a."-".$b."\t".$c."-".$d."\n";

		# A team can't play in the same round on different fields
		if($a eq $c || $a eq $d || $b eq $c || $b eq $d) {
			$verbose && print STDERR "A team can't play in the same round on different fields\n";
			next OUTER;
		} 

		# C1&D2 have the wish not to play in the same round
		if( ($a eq 'C1' && ($c eq 'D2' || $d eq 'D2')) ||
			($b eq 'C1' && ($c eq 'D2' || $d eq 'D2')) ||
			($c eq 'C1' && ($a eq 'D2' || $b eq 'D2')) ||
			($d eq 'C1' && ($a eq 'D2' || $b eq 'D2'))) { 
			$verbose && print STDERR "C1&D2 have the wish not to play in the same round!\n"; 
			next OUTER;
		} 

		# C4 has the wish to play after round 5
		if($round <= 5 && ($a eq 'C4' || $b eq 'C4' || $c eq 'C4' || $d eq 'C4')) { 
			$verbose && print STDERR "C4 has the wish to play after round 5\n"; 
			next OUTER;
		} 

		if( ( $a =~ /^[A-Z]\d{1}$/ && abs($round - ($hist->{$a} || 1)) > $waittime && $a ne 'C4')||
			( $b =~ /^[A-Z]\d{1}$/ && abs($round - ($hist->{$b} || 1)) > $waittime && $b ne 'C4')||
			( $c =~ /^[A-Z]\d{1}$/ && abs($round - ($hist->{$c} || 1)) > $waittime && $c ne 'C4')||
			( $d =~ /^[A-Z]\d{1}$/ && abs($round - ($hist->{$d} || 1)) > $waittime && $d ne 'C4')) { 
				# I don't care if C4 has to wait for a while
				$verbose && print STDERR "One of the teams has to wait too long\n";
				next OUTER;
		} 

		if( ( $a =~ /^[A-Z]\d{1}$/ && defined($hist->{$a}) && $hist->{$a} == ($round - 1) && $a ne 'C4')||
	   	    ( $b =~ /^[A-Z]\d{1}$/ && defined($hist->{$b}) && $hist->{$b} == ($round - 1) && $b ne 'C4')||
	   	    ( $c =~ /^[A-Z]\d{1}$/ && defined($hist->{$c}) && $hist->{$c} == ($round - 1) && $c ne 'C4')||
	   	    ( $d =~ /^[A-Z]\d{1}$/ && defined($hist->{$d}) && $hist->{$d} == ($round - 1) && $d ne 'C4')) { 
				# I don't care if C4 has to play two rows right next after each other
				$verbose && print STDERR "One of the teams plays two times in a row\n";
				next OUTER;
		} 

		# Update hist information
		if( $a =~ /^[A-Z]\d{1}$/) { $hist->{$a} = $round } ;
		if( $b =~ /^[A-Z]\d{1}$/) { $hist->{$b} = $round } ;
		if( $c =~ /^[A-Z]\d{1}$/) { $hist->{$c} = $round } ;
		if( $d =~ /^[A-Z]\d{1}$/) { $hist->{$d} = $round } ;
	} 

	# Teams in poule A and B cannot have their last round before round 11 
	# Teams in poule C and D cannot have their last round before round 12 
	foreach my $team (keys %$hist) { 
		if($team =~ /^[AB]\d{1}$/ && $hist->{$team} < 11) { 
			$verbose && print STDERR "Team $team finished in round $round. That is too early.\n"; 
			next OUTER;
		} 
		if($team =~ /^[CD]\d{1}$/ && $hist->{$team} < 12) { 
			$verbose && print STDERR "Team $team finished in round $round. That is too early.\n"; 
			next OUTER;
		} 
	} 
	last OUTER;
}

print "Result with max waittime $waittime\n";
print $data;
print "Success!\n";
