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