Refactor postingstats.
- Make all text configurable (i18n). - Generalize to make it usable for HostStats. - Fallback to last month if no month is given. - Add option handling, import VERSION, add POD. Signed-off-by: Thomas Hochstein <thh@thh.name>
This commit is contained in:
parent
83d4da5e30
commit
29e9784048
|
@ -2,88 +2,93 @@
|
|||
#
|
||||
# postingstats.pl
|
||||
#
|
||||
# This script will create a posting statistic for de.admin.lists
|
||||
# from NewsStats output.
|
||||
# This script will create statistic postings from NewsStats output.
|
||||
# It defaults to statistics for de.* posted to de.admin.lists, but
|
||||
# defaults can be changed at ----- configuration -----.
|
||||
#
|
||||
# It is part of the NewsStats package.
|
||||
#
|
||||
# Copyright (c) 2010-2012 Thomas Hochstein <thh@inter.net>
|
||||
# Copyright (c) 2010-2012, 2025 Thomas Hochstein <thh@thh.name>
|
||||
#
|
||||
# It can be redistributed and/or modified under the same terms under
|
||||
# which Perl itself is published.
|
||||
#
|
||||
# $~ groupstats.pl --nocomments --sums --format dump | postingstats.pl xxxx-xx
|
||||
# Usage:
|
||||
# $~ groupstats.pl --nocomments --sums --format dump | postingstats.pl -t groups
|
||||
# $~ cliservstats.pl -t server --nocomments --sums --format dump | postingstats.pl -t hosts
|
||||
#
|
||||
|
||||
BEGIN {
|
||||
use File::Basename;
|
||||
# we're in .../bin, so our module is in ../lib
|
||||
push(@INC, dirname($0).'/../lib');
|
||||
}
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use NewsStats qw(:DEFAULT LastMonth);
|
||||
|
||||
use Getopt::Long qw(GetOptions);
|
||||
Getopt::Long::config ('bundling');
|
||||
|
||||
use constant TABLEWIDTH => 28; # width of table without newsgroup name
|
||||
|
||||
our $VERSION = '0.01';
|
||||
##### ----- pre-config -----------------------------------------------
|
||||
### read commandline options
|
||||
my ($Month, $Type);
|
||||
GetOptions ('m|month=s' => \$Month,
|
||||
't|type=s' => \$Type,
|
||||
'h|help' => \&ShowPOD,
|
||||
'V|version' => \&ShowVersion) or exit 1;
|
||||
$Month = &LastMonth if !$Month;
|
||||
if ($Month !~ /^\d{4}-\d{2}$/) {
|
||||
$Month = &LastMonth;
|
||||
&Bleat(1,"--month option has an invalid format - set to $Month.");
|
||||
};
|
||||
# parse $Type
|
||||
if (!$Type) {
|
||||
# default
|
||||
$Type = 'GroupStats';
|
||||
} elsif ($Type =~ /(news)?groups?/i) {
|
||||
$Type = 'GroupStats';
|
||||
} elsif ($Type =~ /(host|server)s?/i) {
|
||||
$Type = 'HostStats';
|
||||
};
|
||||
my $Timestamp = time;
|
||||
|
||||
##### ----- subroutines -----
|
||||
|
||||
sub percentage {
|
||||
# calculate percentage rate from base value and percentage
|
||||
my ($base,$percentage) = @_;
|
||||
return ($percentage * 100 / $base);
|
||||
}
|
||||
|
||||
sub divider {
|
||||
# build a divider line of $symbol as wide as the table is
|
||||
my ($symbol,$maxlength) = @_;
|
||||
return ':' . $symbol x ($maxlength+TABLEWIDTH) . ":\n";
|
||||
}
|
||||
|
||||
##### ----- main loop -----
|
||||
|
||||
# get $month from ARGV
|
||||
my $month = shift;
|
||||
|
||||
# read from STDIN
|
||||
my (%postings, $hierarchy, $maxlength);
|
||||
|
||||
while(<>) {
|
||||
my ($group, $postings) = split;
|
||||
$hierarchy = $postings if $group eq 'de.ALL';
|
||||
next if $group =~ /ALL$/;
|
||||
$postings{$group} = $postings;
|
||||
$maxlength = length($group) if length($group) > $maxlength;
|
||||
}
|
||||
|
||||
# print to STDOUT
|
||||
my $heading = ' Postingstatistik fuer de.* im Monat '.$month;
|
||||
my $padding = ' ' x (($maxlength+TABLEWIDTH-2-length($heading))/2);
|
||||
my $timestamp = time;
|
||||
my $counter = 0;
|
||||
|
||||
print <<HEADER;
|
||||
From: Thomas Hochstein <thh\@inter.net>
|
||||
Newsgroups: de.admin.news.misc
|
||||
Subject: Postingstatistik fuer de.* im Monat $month
|
||||
Message-ID: <destat-postings-$month.$timestamp\@mid.news.szaf.org>
|
||||
##### ----- configuration --------------------------------------------
|
||||
my $TLH = 'de';
|
||||
my %Heading = ('GroupStats' => 'Postingstatistik fuer de.* im Monat '.$Month,
|
||||
'HostStats' => 'Serverstatistik fuer de.* im Monat '.$Month
|
||||
);
|
||||
my %TH = ('counter' => 'Nr.',
|
||||
'value' => 'Anzahl',
|
||||
'percentage' => 'Prozent'
|
||||
);
|
||||
my %LeadIn = ('GroupStats' => <<GROUPSIN, 'HostStats' => <<HOSTSIN);
|
||||
From: Thomas Hochstein <thh\@thh.name>
|
||||
Newsgroups: local.test
|
||||
Subject: Postingstatistik fuer de.* im Monat $Month
|
||||
Message-ID: <destat-postings-$Month.$Timestamp\@mid.news.szaf.org>
|
||||
Approved: thh\@thh.name
|
||||
Mime-Version: 1.0
|
||||
Content-Type: text/plain; charset=ISO-8859-1
|
||||
Content-Type: text/plain; charset=us-ascii
|
||||
Content-Transfer-Encoding: 7bit
|
||||
User-Agent: postingstats.pl/$VERSION (NewsStats)
|
||||
|
||||
HEADER
|
||||
GROUPSIN
|
||||
From: Thomas Hochstein <thh\@thh.name>
|
||||
Newsgroups: local.test
|
||||
Subject: Serverstatistik fuer de.* im Monat $Month
|
||||
Message-ID: <destat-hosts-$Month.$Timestamp\@mid.news.szaf.org>
|
||||
Approved: thh\@thh.name
|
||||
Mime-Version: 1.0
|
||||
Content-Type: text/plain; charset=us-ascii
|
||||
Content-Transfer-Encoding: 7bit
|
||||
User-Agent: postingstats.pl/$VERSION (NewsStats)
|
||||
|
||||
print ÷r('=',$maxlength);
|
||||
printf(": %s%s%s :\n",$padding,$heading,$padding);
|
||||
print ÷r('=',$maxlength);
|
||||
printf(": Nr. : Anzahl : Prozent : %-*s :\n",$maxlength,'Newsgroup');
|
||||
print ÷r('-',$maxlength);
|
||||
|
||||
foreach my $group (sort { $postings{$b} <=> $postings {$a}} keys %postings) {
|
||||
$counter++;
|
||||
printf(": %3u. : %6u : %6.2f%% : %-*s :\n",$counter,$postings{$group},&percentage($hierarchy,$postings{$group}),$maxlength,$group);
|
||||
}
|
||||
|
||||
print ÷r('-',$maxlength);
|
||||
printf(": : %6u : %s : %-*s :\n",$hierarchy,'100.00%',$maxlength,'de.*');
|
||||
print ÷r('=',$maxlength);
|
||||
|
||||
print <<LEADOUT;
|
||||
HOSTSIN
|
||||
my %LeadOut = ('GroupStats' => <<GROUPSOUT, 'HostStats' => <<HOSTSOUT);
|
||||
|
||||
Alle Zahlen wurden ermittelt auf einem Newsserver mit redundanter Anbin-
|
||||
dung fuer de.* unter Anwendung ueblicher Filtermassnahmen. Steuernach-
|
||||
|
@ -96,4 +101,253 @@ Summe der Postinganzahlen der Einzelgruppen.
|
|||
|
||||
Die Daten stehen graphisch aufbereitet unter <http://usenet.dex.de/> zur
|
||||
Verfuegung.
|
||||
LEADOUT
|
||||
GROUPSOUT
|
||||
|
||||
Alle Zahlen wurden ermittelt auf einem Newsserver mit redundanter Anbin-
|
||||
dung fuer de.* unter Anwendung ueblicher Filtermassnahmen. Steuernach-
|
||||
richten werden nicht erfasst; Postings, die supersedet oder gecancelt
|
||||
wurden, bleiben erfasst, sofern sie das System ueberhaupt (und vor der
|
||||
Loeschnachricht) erreicht haben.
|
||||
HOSTSOUT
|
||||
|
||||
##### ----- subroutines ----------------------------------------------
|
||||
|
||||
sub Percentage {
|
||||
# calculate percentage rate from base value and percentage
|
||||
my ($Base,$Percentage) = @_;
|
||||
return ($Percentage * 100 / $Base);
|
||||
}
|
||||
|
||||
sub Divider {
|
||||
# build a divider line of $Symbol as wide as the table is
|
||||
my ($Symbol,$MaxLength) = @_;
|
||||
return ':' . $Symbol x ($MaxLength+TABLEWIDTH) . ":\n";
|
||||
}
|
||||
|
||||
##### ----- main loop ------------------------------------------------
|
||||
|
||||
my (%Value, $SumName, $SumTotal, $MaxLength);
|
||||
$MaxLength = 0;
|
||||
if ($Type eq 'GroupStats') {
|
||||
$SumName = "$TLH.ALL";
|
||||
$TH{'name'} = 'Newsgroup'
|
||||
} elsif ($Type eq 'HostStats') {
|
||||
$SumName = 'ALL';
|
||||
$TH{'name'} = 'Server'
|
||||
}
|
||||
|
||||
# read from STDIN
|
||||
while(<>) {
|
||||
my ($Name, $Value) = split;
|
||||
$SumTotal = $Value if $Name eq $SumName;
|
||||
next if $Name =~ /ALL$/;
|
||||
$Value{$Name} = $Value;
|
||||
$MaxLength = length($Name) if length($Name) > $MaxLength;
|
||||
}
|
||||
|
||||
# print to STDOUT
|
||||
my $PaddingLeft = ' ' x int((($MaxLength+TABLEWIDTH-2-length($Heading{$Type}))/2));
|
||||
my $PaddingRight = $PaddingLeft;
|
||||
$PaddingLeft .= ' ' if (length($Heading{$Type}) + (length($PaddingLeft) * 2) < $MaxLength+TABLEWIDTH);
|
||||
my $Counter = 0;
|
||||
|
||||
print $LeadIn{$Type};
|
||||
|
||||
print &Divider('=',$MaxLength);
|
||||
printf(": %s%s%s :\n",$PaddingLeft,$Heading{$Type},$PaddingRight);
|
||||
print &Divider('=',$MaxLength);
|
||||
printf(": %-3s : %-6s : %-7s : %-*s :\n",
|
||||
substr($TH{'counter'},0,3),
|
||||
substr($TH{'value'},0,6),
|
||||
substr($TH{'percentage'},0,7),
|
||||
$MaxLength,$TH{'name'});
|
||||
print &Divider('-',$MaxLength);
|
||||
|
||||
foreach my $Name (sort { $Value{$b} <=> $Value {$a}} keys %Value) {
|
||||
$Counter++;
|
||||
printf(": %3u. : %6u : %6.2f%% : %-*s :\n",$Counter,$Value{$Name},&Percentage($SumTotal,$Value{$Name}),$MaxLength,$Name);
|
||||
}
|
||||
|
||||
print &Divider('-',$MaxLength);
|
||||
printf(": : %6u : %s : %-*s :\n",$SumTotal,'100.00%',$MaxLength,'');
|
||||
print &Divider('=',$MaxLength);
|
||||
|
||||
print $LeadOut{$Type};
|
||||
|
||||
__END__
|
||||
|
||||
################################ Documentation #################################
|
||||
|
||||
=head1 NAME
|
||||
|
||||
postingstats - format and post reports
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
B<postingstats> B<-t> I<groups|hosts> [B<-Vh> [B<-m> I<YYYY-MM>]
|
||||
|
||||
=head1 REQUIREMENTS
|
||||
|
||||
See L<doc/README>.
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This script will re-format reports on newsgroup usage created by
|
||||
B<groupstats.pl> or B<cliservstats.pl> and create a message that can
|
||||
be posted to Usenet.
|
||||
|
||||
=head2 Features and options
|
||||
|
||||
B<postingstats> will create a table with entries numbered from most
|
||||
to least and percentages calculated from the sum total of all values.
|
||||
|
||||
It depends on a sorted list on STDIN in I<dump> format with I<sums>.
|
||||
|
||||
B<postingstats> needs a B<--type> and a B<--month> to create a caption
|
||||
and select matching lead-ins and lead-outs. B<--type> is also needed
|
||||
to catch the correct sum total from input.
|
||||
|
||||
It will default to posting statistics (number of postings per group)
|
||||
and last month.
|
||||
|
||||
Output from B<postingstats> can be piped to any C<inews> implementation,
|
||||
e.g. C<tinews.pl> from L<ftp://ftp.tin.org/pub/news/clients/tin/tools/tinews.pl>.
|
||||
|
||||
=head2 Configuration
|
||||
|
||||
Configuration is done by changing the code in the
|
||||
C<----- configuration -----> section.
|
||||
|
||||
=over 3
|
||||
|
||||
=item C<$TLH>
|
||||
|
||||
Top level hierarchy the report was created for. Used for display and
|
||||
sum total.
|
||||
|
||||
=item C<%Heading>
|
||||
|
||||
Hash with keys for I<GroupStats> and I<HostStats>. Used to display a
|
||||
heading.
|
||||
|
||||
=item C<%TH>
|
||||
|
||||
Hash with keys for I<counter>, I<value> and I<percentage>. Used to
|
||||
create the table header for I<number>, I<quantity> and I<percentage>.
|
||||
|
||||
I<counter> must not be longer than 3 characters, I<value> no longer
|
||||
than 6 characters and I<percentage> no longer than 7 characters.
|
||||
Output will be truncated otherwise.
|
||||
|
||||
=item C<%LeadIn>
|
||||
|
||||
Hash with keys for I<GroupStats> and I<HostStats>. Used to create the
|
||||
headers for our posting. Can contain other text that will be shown
|
||||
before C<%Heading>.
|
||||
|
||||
=item C<%LeadOut>
|
||||
|
||||
Hash with keys for I<GroupStats> and I<HostStats>. Will be shown at the
|
||||
end of our posting.
|
||||
|
||||
=back
|
||||
|
||||
=head1 OPTIONS
|
||||
|
||||
=over 3
|
||||
|
||||
=item B<-V>, B<--version>
|
||||
|
||||
Print out version and copyright information and exit.
|
||||
|
||||
=item B<-h>, B<--help>
|
||||
|
||||
Print this man page and exit.
|
||||
|
||||
=item B<-t>, B<--type> I<groups|hosts>
|
||||
|
||||
Set report type to posting statistics or hosts statistics accordingly.
|
||||
|
||||
=item B<-m>, B<--month> I<YYYY-MM>
|
||||
|
||||
Set month for display.
|
||||
|
||||
=back
|
||||
|
||||
=head1 INSTALLATION
|
||||
|
||||
See L<doc/INSTALL>.
|
||||
|
||||
=head1 USAGE
|
||||
|
||||
Create a posting from a posting statistics report for last month:
|
||||
|
||||
groupstats.pl --nocomments --sums --format dump | postingstats.pl -t groups
|
||||
|
||||
Create a posting from a posting statistics report for 2012-01:
|
||||
|
||||
groupstats.pl --nocomments --sums --format dump | postingstats.pl -t groups -m 2012-01
|
||||
|
||||
Create a posting from a host statistics report for last month:
|
||||
|
||||
cliservstats.pl -t server --nocomments --sums --format dump | postingstats.pl -t hosts
|
||||
|
||||
=head1 FILES
|
||||
|
||||
=over 4
|
||||
|
||||
=item F<bin/postingstats.pl>
|
||||
|
||||
The script itself.
|
||||
|
||||
=item F<lib/NewsStats.pm>
|
||||
|
||||
Library functions for the NewsStats package.
|
||||
|
||||
=item F<etc/newsstats.conf>
|
||||
|
||||
Runtime configuration file.
|
||||
|
||||
=back
|
||||
|
||||
=head1 BUGS
|
||||
|
||||
Please report any bugs or feature requests to the author or use the
|
||||
bug tracker at L<https://code.virtcomm.de/thh/newsstats/issues>!
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
=over 2
|
||||
|
||||
=item -
|
||||
|
||||
L<doc/README>
|
||||
|
||||
=item -
|
||||
|
||||
l>doc/INSTALL>
|
||||
|
||||
=item -
|
||||
|
||||
groupstats -h
|
||||
|
||||
=item -
|
||||
|
||||
cliservstats -h
|
||||
|
||||
=back
|
||||
|
||||
This script is part of the B<NewsStats> package.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Thomas Hochstein <thh@thh.name>
|
||||
|
||||
=head1 COPYRIGHT AND LICENSE
|
||||
|
||||
Copyright (c) 2010-2012, 2025 Thomas Hochstein <thh@thh.name>
|
||||
|
||||
This program is free software; you may redistribute it and/or modify it
|
||||
under the same terms as Perl itself.
|
||||
|
||||
=cut
|
||||
|
|
Loading…
Reference in a new issue