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