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