Improve output padding.
[usenet/newsstats.git] / groupstats.pl
CommitLineData
2832c235
TH
1#! /usr/bin/perl -W
2#
3# groupstats.pl
4#
5# This script will get statistical data on newgroup usage
d3b6810d 6# from a database.
2832c235
TH
7#
8# It is part of the NewsStats package.
9#
edd250f2 10# Copyright (c) 2010-2012 Thomas Hochstein <thh@inter.net>
2832c235
TH
11#
12# It can be redistributed and/or modified under the same terms under
13# which Perl itself is published.
14
15BEGIN {
16 our $VERSION = "0.01";
17 use File::Basename;
18 push(@INC, dirname($0));
19}
20use strict;
21
edd250f2 22use NewsStats qw(:DEFAULT :TimePeriods :Output :SQLHelper ReadGroupList);
2832c235
TH
23
24use DBI;
edd250f2
TH
25use Getopt::Long qw(GetOptions);
26Getopt::Long::config ('bundling');
2832c235
TH
27
28################################# Main program #################################
29
30### read commandline options
edd250f2
TH
31my ($OptBoundType,$OptCaptions,$OptCheckgroupsFile,$OptComments,
32 $OptFileTemplate,$OptFormat,$OptGroupBy,$OptGroupsDB,$LowBound,$OptMonth,
33 $OptNewsgroups,$OptOrderBy,$OptReportType,$OptSums,$UppBound);
34GetOptions ('b|boundary=s' => \$OptBoundType,
35 'c|captions!' => \$OptCaptions,
36 'checkgroups=s' => \$OptCheckgroupsFile,
37 'comments!' => \$OptComments,
38 'filetemplate=s' => \$OptFileTemplate,
39 'f|format=s' => \$OptFormat,
40 'g|group-by=s' => \$OptGroupBy,
41 'groupsdb=s' => \$OptGroupsDB,
42 'l|lower=i' => \$LowBound,
43 'm|month=s' => \$OptMonth,
44 'n|newsgroups=s' => \$OptNewsgroups,
45 'o|order-by=s' => \$OptOrderBy,
46 'r|report=s' => \$OptReportType,
47 's|sums!' => \$OptSums,
48 'u|upper=i' => \$UppBound,
49 'h|help' => \&ShowPOD,
50 'V|version' => \&ShowVersion) or exit 1;
51# parse parameters
52# $OptComments defaults to TRUE
53$OptComments = 1 if (!defined($OptComments));
54# force --nocomments when --filetemplate is used
55$OptComments = 0 if ($OptFileTemplate);
56# parse $OptBoundType
57if ($OptBoundType) {
58 if ($OptBoundType =~ /level/i) {
59 $OptBoundType = 'level';
60 } elsif ($OptBoundType =~ /av(era)?ge?/i) {
61 $OptBoundType = 'average';
62 } elsif ($OptBoundType =~ /sums?/i) {
63 $OptBoundType = 'sum';
64 } else {
65 $OptBoundType = 'default';
66 }
67}
68# parse $OptReportType
69if ($OptReportType) {
70 if ($OptReportType =~ /av(era)?ge?/i) {
71 $OptReportType = 'average';
72 } elsif ($OptReportType =~ /sums?/i) {
73 $OptReportType = 'sum';
74 } else {
75 $OptReportType = 'default';
76 }
77}
78# read list of newsgroups from --checkgroups
79# into a hash reference
80my $ValidGroups = &ReadGroupList($OptCheckgroupsFile) if $OptCheckgroupsFile;
2832c235
TH
81
82### read configuration
edd250f2 83my %Conf = %{ReadConfig($HomePath.'/newsstats.conf')};
2832c235
TH
84
85### override configuration via commandline options
86my %ConfOverride;
edd250f2 87$ConfOverride{'DBTableGrps'} = $OptGroupsDB if $OptGroupsDB;
2832c235
TH
88&OverrideConfig(\%Conf,\%ConfOverride);
89
f2ddfd8a
TH
90### init database
91my $DBHandle = InitDB(\%Conf,1);
92
edd250f2
TH
93### get time period and newsgroups, prepare SQL 'WHERE' clause
94# get time period
95# and set caption for output and expression for SQL 'WHERE' clause
96my ($CaptionPeriod,$SQLWherePeriod) = &GetTimePeriod($OptMonth);
97# bail out if --month is invalid
98&Bleat(2,"--month option has an invalid format - ".
99 "please use 'YYYY-MM', 'YYYY-MM:YYYY-MM' or 'ALL'!") if !$CaptionPeriod;
100# get list of newsgroups and set expression for SQL 'WHERE' clause
101# with placeholders as well as a list of newsgroup to bind to them
102my ($SQLWhereNewsgroups,@SQLBindNewsgroups) = &SQLGroupList($OptNewsgroups)
103 if $OptNewsgroups;;
104
105### build SQL WHERE clause (and HAVING clause, if needed)
106my ($SQLWhereClause,$SQLHavingClause);
107# $OptBoundType 'level'
108if ($OptBoundType and $OptBoundType ne 'default') {
109 $SQLWhereClause = SQLBuildClause('where',$SQLWherePeriod,
110 $SQLWhereNewsgroups,&SQLHierarchies($OptSums));
111 $SQLHavingClause = SQLBuildClause('having',&SQLSetBounds($OptBoundType,
112 $LowBound,$UppBound));
113# $OptBoundType 'threshold' / 'default' or none
f2ddfd8a 114} else {
edd250f2
TH
115 $SQLWhereClause = SQLBuildClause('where',$SQLWherePeriod,
116 $SQLWhereNewsgroups,&SQLHierarchies($OptSums),
117 &SQLSetBounds('default',$LowBound,$UppBound));
118}
2832c235 119
edd250f2
TH
120### get sort order and build SQL 'ORDER BY' clause
121# default to 'newsgroup' for $OptBoundType 'level' or 'average'
122$OptGroupBy = 'newsgroup' if (!$OptGroupBy and
123 $OptBoundType and $OptBoundType ne 'default');
124# force to 'month' for $OptReportType 'average' or 'sum'
125$OptGroupBy = 'month' if ($OptReportType and $OptReportType ne 'default');
126# parse $OptGroupBy to $GroupBy, create ORDER BY clause $SQLOrderClause
127my ($GroupBy,$SQLOrderClause) = SQLSortOrder($OptGroupBy, $OptOrderBy);
128# $GroupBy will contain 'month' or 'newsgroup' (parsed result of $OptGroupBy)
129# set it to 'month' or 'key' for OutputData()
130$GroupBy = ($GroupBy eq 'month') ? 'month' : 'key';
131
132### get report type and build SQL 'SELECT' query
133my $SQLSelect;
134my $SQLGroupClause = '';
135my $Precision = 0; # number of digits right of decimal point for output
136if ($OptReportType and $OptReportType ne 'default') {
137 $SQLGroupClause = 'GROUP BY newsgroup';
138 # change $SQLOrderClause: replace everything before 'postings'
139 $SQLOrderClause =~ s/BY.+postings/BY postings/;
140 if ($OptReportType eq 'average') {
141 $SQLSelect = "'All months',newsgroup,AVG(postings)";
142 $Precision = 2;
143 # change $SQLOrderClause: replace 'postings' with 'AVG(postings)'
144 $SQLOrderClause =~ s/postings/AVG(postings)/;
145 } elsif ($OptReportType eq 'sum') {
146 $SQLSelect = "'All months',newsgroup,SUM(postings)";
147 # change $SQLOrderClause: replace 'postings' with 'SUM(postings)'
148 $SQLOrderClause =~ s/postings/SUM(postings)/;
149 }
150 } else {
151 $SQLSelect = 'month,newsgroup,postings';
2832c235
TH
152};
153
edd250f2
TH
154### get length of longest newsgroup name delivered by query
155### for formatting purposes
156my $Field = ($GroupBy eq 'month') ? 'newsgroup' : 'month';
b342fcf0
TH
157my ($MaxLength,$MaxValLength) = &GetMaxLength($DBHandle,$Conf{'DBTableGrps'},
158 $Field,'postings',$SQLWhereClause,
159 $SQLHavingClause,
160 @SQLBindNewsgroups);
edd250f2
TH
161
162### build and execute SQL query
163my ($DBQuery);
164# special query preparation for $OptBoundType 'level', 'average' or 'sums'
165if ($OptBoundType and $OptBoundType ne 'default') {
166 # prepare and execute first query:
167 # get list of newsgroups meeting level conditions
168 $DBQuery = $DBHandle->prepare(sprintf('SELECT newsgroup FROM %s.%s %s '.
169 'GROUP BY newsgroup %s',
170 $Conf{'DBDatabase'},$Conf{'DBTableGrps'},
171 $SQLWhereClause,$SQLHavingClause));
172 $DBQuery->execute(@SQLBindNewsgroups)
173 or &Bleat(2,sprintf("Can't get groups data for %s from %s.%s: %s\n",
174 $CaptionPeriod,$Conf{'DBDatabase'},$Conf{'DBTableGrps'},
175 $DBI::errstr));
b802bc3d
TH
176 # add newsgroups to a comma-seperated list ready for IN(...) query
177 my $GroupList;
178 while (my ($Newsgroup) = $DBQuery->fetchrow_array) {
edd250f2 179 $GroupList .= ',' if $GroupList;
b802bc3d
TH
180 $GroupList .= "'$Newsgroup'";
181 };
edd250f2
TH
182 # enhance $WhereClause
183 if ($GroupList) {
184 $SQLWhereClause = SQLBuildClause('where',$SQLWhereClause,
185 sprintf('newsgroup IN (%s)',$GroupList));
186 } else {
187 # condition cannot be satisfied;
188 # force query to fail by adding '0=1'
189 $SQLWhereClause = SQLBuildClause('where',$SQLWhereClause,'0=1');
190 }
191}
192
193# prepare query
194$DBQuery = $DBHandle->prepare(sprintf('SELECT %s FROM %s.%s %s %s %s',
195 $SQLSelect,
196 $Conf{'DBDatabase'},$Conf{'DBTableGrps'},
197 $SQLWhereClause,$SQLGroupClause,$
198 SQLOrderClause));
2832c235
TH
199
200# execute query
edd250f2
TH
201$DBQuery->execute(@SQLBindNewsgroups)
202 or &Bleat(2,sprintf("Can't get groups data for %s from %s.%s: %s\n",
203 $CaptionPeriod,$Conf{'DBDatabase'},$Conf{'DBTableGrps'},
204 $DBI::errstr));
205
206### output results
207# set default to 'pretty'
208$OptFormat = 'pretty' if !$OptFormat;
209# print captions if --caption is set
210if ($OptCaptions && $OptComments) {
211 # print time period with report type
212 my $CaptionReportType= '(number of postings for each month)';
213 if ($OptReportType and $OptReportType ne 'default') {
214 $CaptionReportType= '(average number of postings for each month)'
215 if $OptReportType eq 'average';
216 $CaptionReportType= '(number of all postings for that time period)'
217 if $OptReportType eq 'sum';
218 }
219 printf("# ----- Report for %s %s\n",$CaptionPeriod,$CaptionReportType);
220 # print newsgroup list if --newsgroups is set
221 printf("# ----- Newsgroups: %s\n",join(',',split(/:/,$OptNewsgroups)))
222 if $OptNewsgroups;
223 # print boundaries, if set
224 my $CaptionBoundary= '(counting only month fulfilling this condition)';
225 if ($OptBoundType and $OptBoundType ne 'default') {
226 $CaptionBoundary= '(every single month)' if $OptBoundType eq 'level';
227 $CaptionBoundary= '(on average)' if $OptBoundType eq 'average';
228 $CaptionBoundary= '(all month summed up)' if $OptBoundType eq 'sum';
229 }
230 printf("# ----- Threshold: %s %s x %s %s %s\n",
231 $LowBound ? $LowBound : '',$LowBound ? '=>' : '',
232 $UppBound ? '<=' : '',$UppBound ? $UppBound : '',$CaptionBoundary)
233 if ($LowBound or $UppBound);
234 # print primary and secondary sort order
235 printf("# ----- Grouped by %s (%s), sorted %s%s\n",
236 ($GroupBy eq 'month') ? 'Months' : 'Newsgroups',
237 ($OptGroupBy and $OptGroupBy =~ /-?desc$/i) ? 'descending' : 'ascending',
238 ($OptOrderBy and $OptOrderBy =~ /posting/i) ? 'by number of postings ' : '',
239 ($OptOrderBy and $OptOrderBy =~ /-?desc$/i) ? 'descending' : 'ascending');
240}
241
242# output data
243&OutputData($OptFormat,$OptComments,$GroupBy,$Precision,
244 $OptCheckgroupsFile ? $ValidGroups : '',
b342fcf0 245 $OptFileTemplate,$DBQuery,$MaxLength,$MaxValLength);
2832c235
TH
246
247### close handles
248$DBHandle->disconnect;
249
250__END__
251
252################################ Documentation #################################
253
254=head1 NAME
255
256groupstats - create reports on newsgroup usage
257
258=head1 SYNOPSIS
259
edd250f2 260B<groupstats> [B<-Vhcs> B<--comments>] [B<-m> I<YYYY-MM>[:I<YYYY-MM>] | I<all>] [B<-n> I<newsgroup(s)>] [B<--checkgroups> I<checkgroups file>] [B<-r> I<report type>] [B<-l> I<lower boundary>] [B<-u> I<upper boundary>] [B<-b> I<boundary type>] [B<-g> I<group by>] [B<-o> I<order by>] [B<-f> I<output format>] [B<--filetemplate> I<filename template>] [B<--groupsdb> I<database table>]
2832c235
TH
261
262=head1 REQUIREMENTS
263
edd250f2 264See L<doc/README>.
2832c235
TH
265
266=head1 DESCRIPTION
267
268This script create reports on newsgroup usage (number of postings per
269group per month) taken from result tables created by
edd250f2 270B<gatherstats.pl>.
2832c235 271
edd250f2 272=head2 Features and options
2832c235 273
edd250f2 274=head3 Time period and newsgroups
2832c235 275
edd250f2
TH
276The time period to act on defaults to last month; you can assign another
277time period or a single month (or drop all time constraints) via the
278B<--month> option (see below).
2832c235 279
edd250f2
TH
280B<groupstats> will process all newsgroups by default; you can limit
281processing to only some newsgroups by supplying a list of those groups via
282B<--newsgroups> option (see below). You can include hierarchy levels in
283the output by adding the B<--sums> switch (see below). Optionally
284newsgroups not present in a checkgroups file can be excluded from output,
285sse B<--checkgroups> below.
286
287=head3 Report type
288
289You can choose between different B<--report> types: postings per month,
290average postings per month or all postings summed up; for details, see
291below.
292
293=head3 Upper and lower boundaries
294
295Furthermore you can set an upper and/or lower boundary to exclude some
296results from output via the B<--lower> and B<--upper> options,
297respectively. By default, all newsgroups with more and/or less postings
298per month will be excluded from the result set (i.e. not shown and not
299considered for average and sum reports). You can change the meaning of
300those boundaries with the B<--boundary> option. For details, please see
301below.
302
303=head3 Sorting and formatting the output
304
305By default, all results are grouped by month; you can group results by
306newsgroup instead via the B<--groupy-by> option. Within those groups, the
307list of newsgroups (or months) is sorted alphabetically (or
308chronologically, respectively) ascending. You can change that order (and
309sort by number of postings) with the B<--order-by> option. For details and
310exceptions, please see below.
311
312The results will be formatted as a kind of table; you can change the
313output format to a simple list or just a list of newsgroups and number of
314postings with the B<--format> option. Captions will be added by means of
315the B<--caption> option; all comments (and captions) can be supressed by
316using B<--nocomments>.
317
318Last but not least you can redirect all output to a number of files, e.g.
319one for each month, by submitting the B<--filetemplate> option, see below.
320Captions and comments are automatically disabled in this case.
2832c235
TH
321
322=head2 Configuration
323
f2ddfd8a 324B<groupstats> will read its configuration from F<newsstats.conf>
2832c235
TH
325which should be present in the same directory via Config::Auto.
326
327See doc/INSTALL for an overview of possible configuration options.
328
edd250f2 329You can override some configuration options via the B<--groupsdb> option.
2832c235
TH
330
331=head1 OPTIONS
332
333=over 3
334
edd250f2 335=item B<-V>, B<--version>
2832c235 336
edd250f2 337Print out version and copyright information and exit.
2832c235 338
edd250f2 339=item B<-h>, B<--help>
2832c235
TH
340
341Print this man page and exit.
342
edd250f2 343=item B<-m>, B<--month> I<YYYY-MM[:YYYY-MM]|all>
2832c235 344
edd250f2
TH
345Set processing period to a single month in YYYY-MM format or to a time
346period between two month in YYYY-MM:YYYY-MM format (two month, separated
347by a colon). By using the keyword I<all> instead, you can set no
348processing period to process the whole database.
2832c235 349
edd250f2 350=item B<-n>, B<--newsgroups> I<newsgroup(s)>
2832c235
TH
351
352Limit processing to a certain set of newsgroups. I<newsgroup(s)> can
353be a single newsgroup name (de.alt.test), a newsgroup hierarchy
354(de.alt.*) or a list of either of these, separated by colons, for
355example
356
357 de.test:de.alt.test:de.newusers.*
358
edd250f2 359=item B<-s>, B<--sums|--nosums> (sum per hierarchy level)
2832c235 360
edd250f2
TH
361Include "virtual" groups for every hierarchy level in output, for
362example:
2832c235 363
edd250f2
TH
364 de.alt.ALL 10
365 de.alt.test 5
366 de.alt.admin 7
2832c235 367
edd250f2 368See the B<gatherstats> man page for details.
2832c235 369
edd250f2 370=item B<--checkgroups> I<filename>
2832c235 371
edd250f2
TH
372Restrict output to those newgroups present in a file in checkgroups format
373(one newgroup name per line; everything after the first whitespace on each
374line is ignored). All other newsgroups will be removed from output.
2832c235 375
edd250f2 376=item B<-r>, B<--report> I<default|average|sums>
2832c235 377
edd250f2 378Choose the report type: I<default>, I<average> or I<sums>
2832c235 379
edd250f2
TH
380By default, B<groupstats> will report the number of postings for each
381newsgroup in each month. But it can also report the average number of
382postings per group for all months or the total sum of postings per group
383for all months.
2832c235 384
edd250f2
TH
385For report types I<average> and I<sums>, the B<group-by> option has no
386meaning and will be silently ignored (see below).
2832c235 387
edd250f2 388=item B<-l>, B<--lower> I<lower boundary>
2832c235 389
edd250f2 390Set the lower boundary. See B<--boundary> below.
2832c235 391
edd250f2 392=item B<-l>, B<--upper> I<upper boundary>
2832c235 393
edd250f2 394Set the upper boundary. See B<--boundary> below.
2832c235 395
edd250f2
TH
396=item B<-b>, B<--boundary> I<boundary type>
397
398Set the boundary type to one of I<default>, I<level>, I<average> or
399I<sums>.
400
401By default, all newsgroups with more postings per month than the upper
402boundary and/or less postings per month than the lower boundary will be
403excluded from further processing. For the default report that means each
404month only newsgroups with a number of postings between the boundaries
405will be displayed. For the other report types, newsgroups with a number of
406postings exceeding the boundaries in all (!) months will not be
407considered.
408
409For example, lets take a list of newsgroups like this:
410
411 ----- 2012-01:
412 de.comp.datenbanken.misc 6
413 de.comp.datenbanken.ms-access 84
414 de.comp.datenbanken.mysql 88
415 ----- 2012-02:
416 de.comp.datenbanken.misc 8
417 de.comp.datenbanken.ms-access 126
418 de.comp.datenbanken.mysql 21
419 ----- 2012-03:
420 de.comp.datenbanken.misc 24
421 de.comp.datenbanken.ms-access 83
422 de.comp.datenbanken.mysql 36
423
424With C<groupstats --month 2012-01:2012-03 --lower 25 --report sums>,
425you'll get the following result:
2832c235 426
edd250f2
TH
427 ----- All months:
428 de.comp.datenbanken.ms-access 293
429 de.comp.datenbanken.mysql 124
2832c235 430
edd250f2
TH
431de.comp.datenbanken.misc has not been considered even though it has 38
432postings in total, because it has less than 25 postings in every single
433month. If you want to list all newsgroups with more than 25 postings U<in
434total>, you'll have to set the boundary type to I<sum>, see below.
628a183c 435
edd250f2
TH
436A boundary type of I<level> will show only those newsgroups - at all -
437that satisfy the boundaries in each and every single month. With the above
438list of newsgroups and
439C<groupstats --month 2012-01:2012-03 --lower 25 --boundary level --report sums>,
440you'll get this result:
2832c235 441
edd250f2
TH
442 ----- All months:
443 de.comp.datenbanken.ms-access 293
2832c235 444
edd250f2
TH
445de.comp.datenbanken.mysql has not been considered because it had less than
44625 postings in 2012-02.
2832c235 447
edd250f2
TH
448You can use that to get a list of newsgroups that have more (or less) then
449x postings during the whole reporting period.
2832c235 450
edd250f2
TH
451A boundary type of I<average> will show only those newsgroups - at all -that
452satisfy the boundaries on average. With the above list of newsgroups and
453C<groupstats --month 2012-01:2012-03 --lower 25 --boundary avg --report sums>,
454you'll get this result:
78389b28 455
edd250f2
TH
456 ----- All months:
457 de.comp.datenbanken.ms-access 293
458 de.comp.datenbanken.mysql 145
2832c235 459
edd250f2 460The average number of postings in the three groups is:
2832c235 461
edd250f2
TH
462 de.comp.datenbanken.misc 12.67
463 de.comp.datenbanken.ms-access 97.67
464 de.comp.datenbanken.mysql 48.33
2832c235 465
edd250f2
TH
466Last but not least, a boundary type of I<sums> will show only those
467newsgroups - at all - that satisfy the boundaries with the total sum of
468all postings during the reporting period. With the above list of
469newsgroups and
470C<groupstats --month 2012-01:2012-03 --lower 25 --boundary sum --report sums>,
471you'll finally get this result:
2832c235 472
edd250f2
TH
473 ----- All months:
474 de.comp.datenbanken.misc 38
475 de.comp.datenbanken.ms-access 293
476 de.comp.datenbanken.mysql 145
2832c235 477
2832c235 478
edd250f2 479=item B<-g>, B<--group-by> I<month[-desc]|newsgroups[-desc]>
2832c235 480
edd250f2
TH
481By default, all results are grouped by month, sorted chronologically in
482ascending order, like this:
78389b28 483
edd250f2
TH
484 ----- 2012-01:
485 de.comp.datenbanken.ms-access 84
486 de.comp.datenbanken.mysql 88
487 ----- 2012-02:
488 de.comp.datenbanken.ms-access 126
489 de.comp.datenbanken.mysql 21
78389b28 490
edd250f2
TH
491The results can be grouped by newsgroups instead via
492B<--group-by> I<newsgroup>:
493
494 ----- de.comp.datenbanken.ms-access:
495 2012-01 84
496 2012-02 126
497 ----- de.comp.datenbanken.mysql:
498 2012-01 88
499 2012-02 21
500
501By appending I<-desc> to the group-by option parameter, you can reverse
502the sort order - e.g. B<--group-by> I<month-desc> will give:
503
504 ----- 2012-02:
505 de.comp.datenbanken.ms-access 126
506 de.comp.datenbanken.mysql 21
507 ----- 2012-01:
508 de.comp.datenbanken.ms-access 84
509 de.comp.datenbanken.mysql 88
510
511Average and sums reports (see above) will always be grouped by months;
512this option will therefore be ignored.
513
514=item B<-o>, B<--order-by> I<default[-desc]|postings[-desc]>
515
516Within each group (a single month or single newsgroup, see above), the
517report will be sorted by newsgroup names in ascending alphabetical order
518by default. You can change the sort order to descending or sort by number
519of postings instead.
520
521=item B<-f>, B<--format> I<pretty|list|dump>
522
523Select the output format, I<pretty> being the default:
524
525 ----- 2012-01:
526 de.comp.datenbanken.ms-access 84
527 de.comp.datenbanken.mysql 88
528 ----- 2012-02:
529 de.comp.datenbanken.ms-access 126
530 de.comp.datenbanken.mysql 21
531
532I<list> format looks like this:
533
534 2012-01 de.comp.datenbanken.ms-access 84
535 2012-01 de.comp.datenbanken.mysql 88
536 2012-02 de.comp.datenbanken.ms-access 126
537 2012-02 de.comp.datenbanken.mysql 21
538
539And I<dump> format looks like this:
540
541 # 2012-01:
542 de.comp.datenbanken.ms-access 84
543 de.comp.datenbanken.mysql 88
544 # 2012-02:
545 de.comp.datenbanken.ms-access 126
546 de.comp.datenbanken.mysql 21
547
548You can remove the comments by using B<--nocomments>, see below.
549
550=item B<-c>, B<--captions|--nocaptions>
551
552Add captions to output, like this:
553
554 ----- Report for 2012-01 to 2012-02 (number of postings for each month)
555 ----- Newsgroups: de.comp.datenbanken.*
556 ----- Threshold: 10 => x <= 20 (on average)
557 ----- Grouped by Newsgroups (ascending), sorted by number of postings descending
558
559False by default.
560
561=item B<--comments|--nocomments>
562
563Add comments (group headers) to I<dump> and I<pretty> output. True by default.
564
565Use I<--nocomments> to suppress anything except newsgroup names/months and
566numbers of postings. This is enforced when using B<--filetemplate>, see below.
567
568=item B<--filetemplate> I<filename template>
569
570Save output to file(s) instead of dumping it to STDOUT. B<groupstats> will
571create one file for each month (or each newsgroup, accordant to the
572setting of B<--group-by>, see above), with filenames composed by adding
573year and month (or newsgroup names) to the I<filename template>, for
574example with B<--filetemplate> I<stats>:
575
576 stats-2012-01
577 stats-2012-02
78389b28
TH
578 ... and so on
579
edd250f2 580B<--nocomments> is enforced, see above.
78389b28 581
edd250f2 582=item B<--groupsdb> I<database table>
2832c235
TH
583
584Override I<DBTableGrps> from F<newsstats.conf>.
585
586=back
587
588=head1 INSTALLATION
589
edd250f2 590See L<doc/INSTALL>.
2832c235
TH
591
592=head1 EXAMPLES
593
edd250f2 594Show number of postings per group for lasth month in I<pretty> format:
2832c235
TH
595
596 groupstats
597
598Show that report for January of 2010 and de.alt.* plus de.test,
599including display of hierarchy levels:
600
edd250f2 601 groupstats --month 2010-01 --newsgroups de.alt.*:de.test --sums
2832c235 602
edd250f2
TH
603Only show newsgroups with 30 postings or less last month, ordered
604by number of postings, descending, in I<pretty> format:
2832c235 605
edd250f2 606 groupstats --upper 30 --order-by postings-desc
2832c235 607
edd250f2
TH
608Show the total of all postings for the year of 2010 for all groups that
609had 30 postings or less in every single month in that year, ordered by
610number of postings in descending order:
611
612 groupstats -m 2010-01:2010-12 -u 30 -b level -r sums -o postings-desc
2832c235 613
edd250f2 614The same for the average number of postings in the year of 2010:
2832c235 615
edd250f2 616 groupstats -m 2010-01:2010-12 -u 30 -b level -r avg -o postings-desc
2832c235 617
edd250f2
TH
618List number of postings per group for eacht month of 2010 and redirect
619output to one file for each month, namend stats-2010-01 and so on, in
620machine-readable form (without formatting):
2832c235 621
edd250f2 622 groupstats -m 2010-01:2010-12 -f dump --filetemplate stats
2832c235 623
2832c235
TH
624
625=head1 FILES
626
627=over 4
628
629=item F<groupstats.pl>
630
631The script itself.
632
633=item F<NewsStats.pm>
634
635Library functions for the NewsStats package.
636
637=item F<newsstats.conf>
638
edd250f2 639Runtime configuration file.
2832c235
TH
640
641=back
642
643=head1 BUGS
644
645Please report any bugs or feature requests to the author or use the
646bug tracker at L<http://bugs.th-h.de/>!
647
648=head1 SEE ALSO
649
650=over 2
651
652=item -
653
edd250f2 654L<doc/README>
2832c235
TH
655
656=item -
657
edd250f2 658l>doc/INSTALL>
2832c235
TH
659
660=item -
661
662gatherstats -h
663
664=back
665
666This script is part of the B<NewsStats> package.
667
668=head1 AUTHOR
669
670Thomas Hochstein <thh@inter.net>
671
672=head1 COPYRIGHT AND LICENSE
673
edd250f2 674Copyright (c) 2010-2012 Thomas Hochstein <thh@inter.net>
2832c235
TH
675
676This program is free software; you may redistribute it and/or modify it
677under the same terms as Perl itself.
678
679=cut
This page took 0.047949 seconds and 4 git commands to generate.