#!/usr/bin/perl
#
# Copyright (c) 2005 Mathieu Roy <yeupou--gnu.org>
# http://yeupou.coleumes.org
#
#   This program is free software; you can redistribute it and/or modify
#   it under the terms of the GNU General Public License as published by
#   the Free Software Foundation; either version 2 of the License, or
#   (at your option) any later version.
#
#   This program is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#   GNU General Public License for more details.
#
#   You should have received a copy of the GNU General Public License
#   along with this program; if not, write to the Free Software
#   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
#   USA
#
# $Id: keduca-shrinker.pl,v 1.3 2005/04/23 11:30:50 yeupou Exp $

use Getopt::Long;

my $getopt;
my $debug; 
my $help;

my $input;
my $output;
my $number = "20";


########### Get options, give help

eval {
    $getopt = GetOptions("debug" => \$debug,
			 "help" => \$help,
			 "number=s" => \$number,
			 "input=s" => \$input,
			 "output=s" => \$ouput);
};

if ($help) {
    print STDERR <<EOF;
Usage: $0 [OPTION] --input [FILE] 

A small program that take a kdeduca test file (.edu) as input with say 100
question and output a kdeduca test file with 20 questions selected randomly. 

    -i, --input=FILE          Input keduca file.
    -o, --output=FILE         Output keduca file, shrinked.
                              (By default, the suffix -shrinked will be added)
    -n, --number=NUMBER       Number expected of questions, in the shrinked
                              version.
                              ($number by default)
 
Project Homepage: https://gna.org/projects/keduca-shrinker/
EOF
exit(1);
}

# Test input file existence
unless ($input) {
    print "No input file.\n";
}
unless (-r $input) {
    print "Input file not readable.\n";
    exit;
}
open(INPUT, "< $input");

# Test output writability
unless ($output) {
    $output = $input;
    $output =~ s/.edu$//;
    $output .= "-shrinked.edu";
}
if (-e $output && ! -w $output) {
    print "Output file not writable.\n";
    exit;

}
open(OUTPUT, "> $output");

########### Define subs

sub fisher_yates_shuffle {
    my $table = shift;
    my $i;
    for ($i = @$table; --$i;) {
	my $j = int rand($i+1);
	next if $i == $j;
	@$table[$i,$j] = @$table[$j,$i];
    }
}


########### Grab the file header, store questions in an array.
# I know, it's XML, it may be simple to call an xml parser.
# But in fact, we have nothing to parse here, we do not care about
# the real content, so...
my $structure = "header";
my $header;
my $footer;
my @questions;
my $newquestion;

while (<INPUT>) {
    ## Grab the structure (footer and header)
    # the header last when data begins
    # the footer begin when data ends

    $header .= $_ if $structure eq "header";

    $structure = "content" if /\<Data\>/m;
    $structure = "footer" if /\<\/Data\>/m;

    $footer .= $_ if $structure eq "footer";

    ## Grab the questions
    if ($structure eq "content") {
	$newquestion .= $_;
	
	# If we found the string </question>, that the end of a question
	if (/\<\/question\>/m) {
	    push(@questions, $newquestion);
	    $newquestion = "";
	}
	
    }
}

########### Select the number of questions we want
# warn the user if there's nothing to do
if (scalar(@questions) < $number) {
    print "There are only ".scalar(@questions)." questions in the input file, less than $number.\n";
    # Copy & exit
    system("cp", $input, $output);
    exit;
} else {
    # Shuffle
    fisher_yates_shuffle(\@questions);
    # Keeps only the desired amount (number-1, as 0 is counted)
    $#questions = ($number-1);
}

########### Final output
print OUTPUT $header;
print OUTPUT @questions;
print OUTPUT $footer;

close(INPUT);
close(OUTPUT);
