The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
# Test that the example given in the POD's SYNOPSIS section actually works:

use strict;
use warnings;
use Test::More tests => 52;
use constant EPS => 1e-7;

BEGIN { use_ok('Statistics::ANOVA') };

my $aov = Statistics::ANOVA->new();
isa_ok($aov, 'Statistics::ANOVA');

my @gp1 = (qw/8 7 11 14 9/);
my @gp2 = (qw/11 9 8 11 13/);

eval {$aov->load(1, @gp1);}; # simple but useless load
ok(!$@, $@);

eval {$aov->load(1, \@gp1);}; # another simple but useless load
ok(!$@, $@);

eval {$aov->load_data({1 => \@gp1, 2 => \@gp2});};
ok(!$@, $@);

eval {$aov->unload()}; # going to try an alternative load
ok(!$@, $@);

eval {$aov->load_data([ [1, \@gp1], [2, \@gp2] ]);};
ok(!$@, $@);

eval {$aov->unload()}; # another anonymous unload; going to try yet another alternative load
ok(!$@, $@);

eval {$aov->load_data([ [1, @gp1], [2, @gp2] ]);};
ok(!$@, $@);

my @gp3 = (qw/7 13 12 8 10/);

eval {$aov->add_data(3 => \@gp3);};
ok(!$@, $@);

eval {$aov->unload(3)}; # a named unload; going to try yet an alternative add
ok(!$@, $@);

eval {$aov->add_data([3, \@gp3]);};
ok(!$@, $@);
ok( scalar(keys(%{$aov->{'data'}})) == 3, "Number of data-keys after unload/add should be 3; is ". scalar(keys(%{$aov->{'data'}})));

eval {$aov->unload(3)}; # going to try yet an alternative add
ok(!$@, $@);
ok( scalar(keys(%{$aov->{'data'}})) == 2, "Number of remaining data-keys should be 2; is ". scalar(keys(%{$aov->{'data'}})));

eval {$aov->add_data([[3, \@gp3]]);};
ok(!$@, $@);

eval {$aov->unload(3)}; # going to try yet an alternative add
ok(!$@, $@);

eval {$aov->add_data(3, \@gp3);};
ok(!$@, $@);

eval {$aov->unload(3)}; # going to try yet an alternative add
ok(!$@, $@);

eval {$aov->add_data(3, @gp3);};
ok(!$@, $@);

foreach (sort {$a cmp $b} keys %{$aov->{'data'}}) {
	eval {$aov->{'data'}->{$_}->mean};
	ok(!$@, $@);
}

my %ref_vals = (
	obrien_f => 0.386222473178995,
	levene_f => 0.388785046728972,
	indep_param_f => 0.0777777777777777,
	indep_dfree_h => 0.265209471,
	indep_param_trend_f => 0.01666666666,
	indep_param_ntrend_f => 0.1388888,
	dep_param_f => 0.060475161987041,
	dep_dfree_chi => 0.400000000000006,
	dep_dfree_f => 0.166666666666669,
);

eval {$aov->obrien();};
ok(!$@, $@);
ok( about_equal($aov->{'_stat'}->{'f_value'}, $ref_vals{'obrien_f'}), "Obrien f-value $aov->{'_stat'}->{'f_value'} = $ref_vals{'obrien_f'}" );

eval {$aov->levene();};
ok(!$@, $@);
ok( about_equal($aov->{'_stat'}->{'f_value'}, $ref_vals{'levene_f'}), "Levene f-value $aov->{'_stat'}->{'f_value'} = $ref_vals{'levene_f'}");

eval {$aov->anova(independent => 1, parametric => 1);};
ok(!$@, $@);
ok( about_equal($aov->{'_stat'}->{'f_value'}, $ref_vals{'indep_param_f'}), "Indep param f-value $aov->{'_stat'}->{'f_value'} = $ref_vals{'indep_param_f'}");

eval {$aov->anova(independent => 1, parametric => 0 );};
ok(!$@, $@);
ok( about_equal($aov->{'_stat'}->{'h_value'}, $ref_vals{'indep_dfree_h'}), "Indep non-param f-value $aov->{'_stat'}->{'h_value'} = $ref_vals{'indep_dfree_h'}");
 
# or test the linear trend over the levels instead of the group-wise variance:
eval {$aov->anova(independent => 1, parametric => 1, ordinal => 1)};
ok(!$@, $@);
ok( about_equal($aov->{'_stat'}->{'f_value'}, $ref_vals{'indep_param_trend_f'}), "Indep param f-value $aov->{'_stat'}->{'f_value'} = $ref_vals{'indep_param_trend_f'}");

eval {$aov->anova(independent => 1, parametric => 1, ordinal => -1)};
ok(!$@, $@);
ok( about_equal($aov->{'_stat'}->{'f_value'}, $ref_vals{'indep_param_ntrend_f'}), "Indep param f-value $aov->{'_stat'}->{'f_value'} = $ref_vals{'indep_param_ntrend_f'}");

eval {$aov->anova(independent => 1, parametric => 0, ordinal => 1);};
ok(!$@, $@);

# or if they are repeated measures:
eval {$aov->anova(independent => 0, parametric => 1);};
ok(!$@, $@);
ok( about_equal($aov->{'_stat'}->{'f_value'}, $ref_vals{'dep_param_f'}), "Dep f-value $aov->{'_stat'}->{'f_value'} = $ref_vals{'dep_param_f'}");

eval {$aov->anova(independent => 0, parametric => 0, f_equiv => 0);};
ok(!$@, $@);
ok( about_equal($aov->{'_stat'}->{'chi_value'}, $ref_vals{'dep_dfree_chi'}), "Dep f-value $aov->{'_stat'}->{'chi_value'} = $ref_vals{'dep_dfree_chi'}");
 
eval {$aov->anova(independent => 0, parametric => 0, f_equiv => 1);};
ok(!$@, $@);
ok( about_equal($aov->{'_stat'}->{'f_value'}, $ref_vals{'dep_dfree_f'}), "Dep f-value $aov->{'_stat'}->{'f_value'} = $ref_vals{'dep_dfree_f'}");

eval {$aov->unload('3');};
ok(!$@, $@);
ok( scalar(keys(%{$aov->{'data'}})) == 2, "Number of remaining data-keys should be 2; is ". scalar(keys(%{$aov->{'data'}})));

foreach my $indep(1, 0) {
    foreach my $param(1, 0) {
        foreach my $ord(0, 1) {
            eval {$aov->anova(independent => $indep, parametric => $param, ordinal => $ord, f_equiv => 0)->table();};
		ok(!$@, $@);
        }
    }
}

sub about_equal {
    return 1 if $_[0] + EPS > $_[1] and $_[0] - EPS < $_[1];
    return 0;
}