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