#!perl

our $DATE = '2018-07-07'; # DATE
our $VERSION = '0.001'; # VERSION

use strict;
use warnings;

use Getopt::Long qw(:config bundling no_ignore_case);

my %Opts = (
    calc_count    => 1,
    calc_mode     => 1,
    calc_min      => 1,
    calc_max      => 1,
    calc_mean     => 1,
    calc_median   => 1,
    calc_variance => 1,
    calc_stddev   => 1,
    calc_percentiles => [25, 75],
    calc_covariance => 0,
    calc_correlation => 0,
);

sub parse_cmdline {
    my $res = GetOptions(
        'count!'    => \$Opts{calc_count},
        'mode!'     => \$Opts{calc_mode},
        'max!'      => \$Opts{calc_max},
        'min!'      => \$Opts{calc_min},
        'mean!'     => \$Opts{calc_mean},
        'median!'   => \$Opts{calc_median},
        'variance!' => \$Opts{calc_variance},
        'stddev!'   => \$Opts{calc_stddev},
        'no-percentile|P' => sub { $Opts{calc_percentiles} = [] },
        'percentile|p=s'  => sub {
            my $p = int($_[1]);
            die "summ: Invalid percentile $p, must be between 0 and 100\n"
                if $p < 0 || $p > 100;
            push @{ $Opts{calc_percentiles} }, $p
                unless grep { $p == $_ } @{ $Opts{calc_percentiles} };
        },
        'covariance!'  => \$Opts{calc_covariance},
        'correlation!' => \$Opts{calc_correlation},
        'help|h' => sub {
            print <<USAGE;
Usage:
  summ [OPTIONS]... [INPUT]...
  summ --help

For more details, see the manpage/documentation.
USAGE
            exit 0;
        },
        'version|v' => sub {
            no warnings 'once';
            print "summ version ".($main::VERSION // 'dev'), "\n";
            exit 0;
        },
    );
    exit 99 if !$res;
}

sub run {
    my (@nums, @nums2);
    while (<>) {
        chomp;
        if ($Opts{calc_covariance} || $Opts{calc_correlation}) {
            my ($n, $n2) = split /\s+/, $_, 2;
            defined $n2 or die "summ:$.: Please supply two numbers: $_\n";
            push @nums, $n+0;
            push @nums2, $n2+0;
        } else {
            push @nums, $_+0;
        }
    }
    die "summ: Please specify at least 1 number\n" unless @nums;

    require Statistics::Discrete;
    my $sd = Statistics::Discrete->new;
    $sd->add_data(@nums);

    if ($Opts{calc_count}) {
        printf "Count: %s\n", $sd->count;
    }
    if ($Opts{calc_mode}) {
        require Statistics::Basic;
        require Statistics::Basic::Mode;
        printf "Mode: %s\n", Statistics::Basic::mode(@nums);
    }
    if ($Opts{calc_min}) {
        printf "Minimum: %s\n", $sd->minimum;
    }
    if ($Opts{calc_max}) {
        printf "Maximum: %s\n", $sd->maximum;
    }
    if ($Opts{calc_mean}) {
        printf "Mean: %s\n", $sd->mean;
    }
    if ($Opts{calc_median}) {
        printf "Median: %s\n", $sd->median;
    }
    if ($Opts{calc_variance}) {
        printf "Variance: %s\n", $sd->variance;
    }
    if ($Opts{calc_stddev}) {
        printf "Std. dev.: %s\n", $sd->standard_deviation;
    }
    if (@{ $Opts{calc_percentiles} }) {
        require Lingua::EN::Numbers::Ordinate;
        for my $p (sort { $a <=> $b } @{ $Opts{calc_percentiles} }) {
            printf "%s percentile: %s\n",
                Lingua::EN::Numbers::Ordinate::ordinate($p),
                  $sd->percentile($p);
        }
    }
    if ($Opts{calc_covariance}) {
        require Statistics::Basic;
        printf "Covariance: %s\n", Statistics::Basic::covariance(
            \@nums, \@nums2);
    }
    if ($Opts{calc_correlation}) {
        require Statistics::Basic;
        printf "Correlation: %s\n", Statistics::Basic::correlation(
            \@nums, \@nums2) + 0;
    }
}

# MAIN

parse_cmdline();
run();

1;
# ABSTRACT: Print summary statistics of a series of numbers
# PODNAME: summ

__END__

=pod

=encoding UTF-8

=head1 NAME

summ - Print summary statistics of a series of numbers

=head1 VERSION

This document describes version 0.001 of summ (from Perl distribution App-summ), released on 2018-07-07.

=head1 SYNOPSIS

 summ [OPTION]... [FILE]...

=head1 DESCRIPTION

=head1 EXIT CODES

0 on success.

255 on I/O error.

99 on command-line options error.

=head1 OPTIONS

=over

=item * --no-count

Do not calculate count.

=item * --no-mode

Do not calculate mode.

=item * --no-max

Do not calculate maximum.

=item * --no-min

Do not calculate minimum.

=item * --no-mean

Do not calculate mean.

=item * --no-median

Do not calculate median.

=item * --no-variance

Do not calculate variance.

=item * --no-stddev

Do not calculate standard deviation.

=item * --no-percentile, -P

Do not calculate any percentiles. The default is to calculate 25th and 75th
percentiles.

=item * --percentile=P, -p P

Add a percentile to calculate, for example: C<-p 5 -p 95> to add calculating 5th
and 95th percentiles. The default is to only calculate 25th and 75th
percentiles.

=item * --covariance

Calculate covariance. This requires every line to contain two numbers intead of
one.

=item * --correlation

Calculate correlation. This requires every line to contain two numbers intead of
one.

=back

=head1 FAQ

=head1 HOMEPAGE

Please visit the project's homepage at L<https://metacpan.org/release/App-summ>.

=head1 SOURCE

Source repository is at L<https://github.com/perlancar/perl-App-summ>.

=head1 BUGS

Please report any bugs or feature requests on the bugtracker website L<https://rt.cpan.org/Public/Dist/Display.html?Name=App-summ>

When submitting a bug or request, please include a test-file or a
patch to an existing test-file that illustrates the bug or desired
feature.

=head1 SEE ALSO

L<Statistics::Basic>

L<Statistics::Discrete>

=head1 AUTHOR

perlancar <perlancar@cpan.org>

=head1 COPYRIGHT AND LICENSE

This software is copyright (c) 2018 by perlancar@cpan.org.

This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.

=cut