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