| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package CPAN::Testers::WWW::Statistics::Graphs; |
|
2
|
|
|
|
|
|
|
|
|
3
|
16
|
|
|
16
|
|
64276
|
use warnings; |
|
|
16
|
|
|
|
|
39
|
|
|
|
16
|
|
|
|
|
640
|
|
|
4
|
16
|
|
|
16
|
|
86
|
use strict; |
|
|
16
|
|
|
|
|
37
|
|
|
|
16
|
|
|
|
|
418
|
|
|
5
|
16
|
|
|
16
|
|
75
|
use vars qw($VERSION); |
|
|
16
|
|
|
|
|
36
|
|
|
|
16
|
|
|
|
|
903
|
|
|
6
|
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
$VERSION = '1.22'; |
|
8
|
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
#---------------------------------------------------------------------------- |
|
10
|
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
=head1 NAME |
|
12
|
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
CPAN::Testers::WWW::Statistics::Graphs - CPAN Testers Statistics graphs. |
|
14
|
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
=head1 SYNOPSIS |
|
16
|
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
my %hash = { config => 'options' }; |
|
18
|
|
|
|
|
|
|
my $obj = CPAN::Testers::WWW::Statistics->new(%hash); |
|
19
|
|
|
|
|
|
|
my $ct = CPAN::Testers::WWW::Statistics::Graphs->new(parent => $obj); |
|
20
|
|
|
|
|
|
|
$ct->create(); |
|
21
|
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
=head1 DESCRIPTION |
|
23
|
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
Using previously formatted data, generate graphs using the Google Chart API. |
|
25
|
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
Note that this package should not be called directly, but via its parent as: |
|
27
|
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
my %hash = { config => 'options' }; |
|
29
|
|
|
|
|
|
|
my $obj = CPAN::Testers::WWW::Statistics->new(%hash); |
|
30
|
|
|
|
|
|
|
$obj->make_graphs(); |
|
31
|
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
=cut |
|
33
|
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
# ------------------------------------- |
|
35
|
|
|
|
|
|
|
# Library Modules |
|
36
|
|
|
|
|
|
|
|
|
37
|
16
|
|
|
16
|
|
98
|
use File::Basename; |
|
|
16
|
|
|
|
|
41
|
|
|
|
16
|
|
|
|
|
1091
|
|
|
38
|
16
|
|
|
16
|
|
100
|
use File::Path; |
|
|
16
|
|
|
|
|
41
|
|
|
|
16
|
|
|
|
|
700
|
|
|
39
|
16
|
|
|
16
|
|
544
|
use HTML::Entities; |
|
|
16
|
|
|
|
|
4971
|
|
|
|
16
|
|
|
|
|
818
|
|
|
40
|
16
|
|
|
16
|
|
533
|
use IO::File; |
|
|
16
|
|
|
|
|
6933
|
|
|
|
16
|
|
|
|
|
1994
|
|
|
41
|
16
|
|
|
16
|
|
9446
|
use LWP::UserAgent; |
|
|
16
|
|
|
|
|
492641
|
|
|
|
16
|
|
|
|
|
632
|
|
|
42
|
16
|
|
|
16
|
|
174
|
use HTTP::Request; |
|
|
16
|
|
|
|
|
44
|
|
|
|
16
|
|
|
|
|
28778
|
|
|
43
|
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
# ------------------------------------- |
|
45
|
|
|
|
|
|
|
# Variables |
|
46
|
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
my %month = ( |
|
48
|
|
|
|
|
|
|
0 => 'January', 1 => 'February', 2 => 'March', 3 => 'April', |
|
49
|
|
|
|
|
|
|
4 => 'May', 5 => 'June', 6 => 'July', 7 => 'August', |
|
50
|
|
|
|
|
|
|
8 => 'September', 9 => 'October', 10 => 'November', 11 => 'December' |
|
51
|
|
|
|
|
|
|
); |
|
52
|
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
my ($backg,$foreg) = ('black','white'); |
|
54
|
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
my @graphs = ( |
|
56
|
|
|
|
|
|
|
['stats/stats1' ,'CPAN Testers Statistics - Reports' ,[qw(UPLOADS REPORTS PASS FAIL)],'TEST_RANGES' ,'month'], |
|
57
|
|
|
|
|
|
|
['stats/stats2' ,'CPAN Testers Statistics - Attributes' ,[qw(TESTERS PLATFORMS PERLS)] ,'TEST_RANGES' ,'month'], |
|
58
|
|
|
|
|
|
|
['stats/stats3' ,'CPAN Testers Statistics - Non-Passes' ,[qw(FAIL NA UNKNOWN)] ,'TEST_RANGES' ,'month'], |
|
59
|
|
|
|
|
|
|
['stats/stats4' ,'CPAN Testers Statistics - Testers' ,[qw(ALL FIRST LAST)] ,'TEST_RANGES' ,'month'], |
|
60
|
|
|
|
|
|
|
['stats/stats6' ,'CPAN Statistics - Uploads' ,[qw(AUTHORS DISTROS)] ,'CPAN_RANGES' ,'month'], |
|
61
|
|
|
|
|
|
|
['stats/stats12' ,'CPAN Statistics - New Uploads' ,[qw(AUTHORS DISTROS)] ,'CPAN_RANGES' ,'month'], |
|
62
|
|
|
|
|
|
|
['stats/build1' ,'CPAN Testers Performance Graph' ,[qw(REQUESTS PAGES REPORTS)] ,'NONE' ,'daily'], |
|
63
|
|
|
|
|
|
|
['stats/pcent1' ,'CPAN Testers Statistics - Percentages' ,[qw(FAIL OTHER PASS)] ,'TEST_RANGES' ,'month'], |
|
64
|
|
|
|
|
|
|
['rates/submit1' ,'CPAN Submissions - By Month' ,[qw(EXCLUSIVE INCLUSIVE)] ,'NONE' ,'index'], |
|
65
|
|
|
|
|
|
|
['rates/submit2' ,'CPAN Submissions - By Day of the Week' ,[qw(EXCLUSIVE INCLUSIVE)] ,'NONE' ,'index'], |
|
66
|
|
|
|
|
|
|
['rates/submit3' ,'CPAN Submissions - By Day of the Month' ,[qw(EXCLUSIVE INCLUSIVE)] ,'NONE' ,'index'], |
|
67
|
|
|
|
|
|
|
['rates/submit4' ,'CPAN Submissions - By Hour' ,[qw(EXCLUSIVE INCLUSIVE)] ,'NONE' ,'index'], |
|
68
|
|
|
|
|
|
|
); |
|
69
|
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
my $lwp = LWP::UserAgent->new(); |
|
71
|
|
|
|
|
|
|
$lwp->agent( 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4) Gecko/20030624' ); |
|
72
|
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
my $chart_api = 'http://chart.apis.google.com/chart?chs=640x300&cht=lc'; |
|
74
|
|
|
|
|
|
|
my $chart_titles = 'chtt=%s&chdl=%s'; |
|
75
|
|
|
|
|
|
|
my $chart_labels = 'chxt=x,x,y,r&chxl=0:|%s|1:|%s|2:|%s|3:|%s'; |
|
76
|
|
|
|
|
|
|
my $chart_data = 'chd=t:%s'; |
|
77
|
|
|
|
|
|
|
my $chart_colour = 'chco=%s'; |
|
78
|
|
|
|
|
|
|
my $chart_filler = 'chf=bg,s,dddddd'; |
|
79
|
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
my %COLOURS = ( |
|
81
|
|
|
|
|
|
|
white => [255,255,255], |
|
82
|
|
|
|
|
|
|
black => [0,0,0], |
|
83
|
|
|
|
|
|
|
red => [255,0,0], |
|
84
|
|
|
|
|
|
|
blue => [0,0,255], |
|
85
|
|
|
|
|
|
|
purple => [230,0,230], |
|
86
|
|
|
|
|
|
|
green => [0,255,0], |
|
87
|
|
|
|
|
|
|
grey => [128,128,128], |
|
88
|
|
|
|
|
|
|
light_grey => [170,170,170], |
|
89
|
|
|
|
|
|
|
dark_grey => [75,75,75], |
|
90
|
|
|
|
|
|
|
cream => [200,200,240], |
|
91
|
|
|
|
|
|
|
yellow => [255,255,0], |
|
92
|
|
|
|
|
|
|
orange => [255,128,0], |
|
93
|
|
|
|
|
|
|
); |
|
94
|
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
my @COLOURS = map {sprintf "%s%s%s", _dec2hex($COLOURS{$_}->[0]),_dec2hex($COLOURS{$_}->[1]),_dec2hex($COLOURS{$_}->[2])} qw(red blue green orange purple grey); |
|
96
|
|
|
|
|
|
|
my @MONTH = qw( - JANUARY FEBRUARY MARCH APRIL MAY JUNE JULY AUGUST SEPTEMBER OCTOBER NOVEMBER DECEMBER ); |
|
97
|
|
|
|
|
|
|
my @MONTHS = map {my @x = split(//); my $x = join(' ',@x); [split(//,$x)]} @MONTH; |
|
98
|
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
# ------------------------------------- |
|
100
|
|
|
|
|
|
|
# Subroutines |
|
101
|
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
=head1 INTERFACE |
|
103
|
|
|
|
|
|
|
|
|
104
|
|
|
|
|
|
|
=head2 The Constructor |
|
105
|
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
=over 4 |
|
107
|
|
|
|
|
|
|
|
|
108
|
|
|
|
|
|
|
=item * new |
|
109
|
|
|
|
|
|
|
|
|
110
|
|
|
|
|
|
|
Graph creation object. Checks to see whether the data files exist, and allows |
|
111
|
|
|
|
|
|
|
the user to turn or off the progress tracking. |
|
112
|
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
new() takes an option hash as an argument, which may contain 'progress => 1' |
|
114
|
|
|
|
|
|
|
to turn on the progress tracker and/or 'directory => $dir' to indicate the path |
|
115
|
|
|
|
|
|
|
to the data files. If no directory is supplied the current directory is |
|
116
|
|
|
|
|
|
|
assumed. |
|
117
|
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
=back |
|
119
|
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
=cut |
|
121
|
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
sub new { |
|
123
|
0
|
|
|
0
|
1
|
0
|
my $class = shift; |
|
124
|
0
|
|
|
|
|
0
|
my %hash = @_; |
|
125
|
|
|
|
|
|
|
|
|
126
|
0
|
0
|
|
|
|
0
|
die "Must specify the parent statistics object\n" unless(defined $hash{parent}); |
|
127
|
|
|
|
|
|
|
|
|
128
|
0
|
|
|
|
|
0
|
my $self = {parent => $hash{parent}}; |
|
129
|
0
|
|
|
|
|
0
|
bless $self, $class; |
|
130
|
|
|
|
|
|
|
|
|
131
|
0
|
|
|
|
|
0
|
$self->{parent}->_log("GRAPHS: new"); |
|
132
|
|
|
|
|
|
|
|
|
133
|
0
|
|
|
|
|
0
|
return $self; |
|
134
|
|
|
|
|
|
|
} |
|
135
|
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
=head2 Methods |
|
137
|
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
=over 4 |
|
139
|
|
|
|
|
|
|
|
|
140
|
|
|
|
|
|
|
=item * create |
|
141
|
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
Method to facilitate the creation of graphs. |
|
143
|
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
=back |
|
145
|
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
=cut |
|
147
|
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
sub create { |
|
149
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
|
150
|
0
|
|
|
|
|
0
|
my $status = 0; # assume success |
|
151
|
|
|
|
|
|
|
|
|
152
|
0
|
|
|
|
|
0
|
my $directory = $self->{parent}->directory; |
|
153
|
|
|
|
|
|
|
|
|
154
|
0
|
|
|
|
|
0
|
$self->{parent}->_log("create start"); |
|
155
|
|
|
|
|
|
|
|
|
156
|
0
|
|
|
|
|
0
|
for my $g (@graphs) { |
|
157
|
0
|
|
|
|
|
0
|
my $results = "$directory/$g->[0]"; |
|
158
|
0
|
|
|
|
|
0
|
my ($path,$file) = (dirname($results),basename($results)); |
|
159
|
0
|
|
|
|
|
0
|
mkpath($path); |
|
160
|
0
|
|
|
|
|
0
|
$g->[0] = $file; |
|
161
|
0
|
|
|
|
|
0
|
$g->[5] = $path; |
|
162
|
|
|
|
|
|
|
|
|
163
|
0
|
|
|
|
|
0
|
my $ranges = $self->{parent}->ranges($g->[3]); |
|
164
|
0
|
|
|
|
|
0
|
$self->{parent}->_log("writing graph - got range [$g->[3]] = " . (scalar(@$ranges)) . ", latest=$ranges->[-1]"); |
|
165
|
|
|
|
|
|
|
|
|
166
|
0
|
|
|
|
|
0
|
my $latest = $ranges->[-1]; |
|
167
|
|
|
|
|
|
|
|
|
168
|
0
|
|
|
|
|
0
|
for my $r (@$ranges) { |
|
169
|
0
|
|
|
|
|
0
|
$self->{parent}->_log("writing graph - $g->[0]-$r"); |
|
170
|
|
|
|
|
|
|
|
|
171
|
0
|
|
|
|
|
0
|
my $url = $self->_make_graph($r,@$g); |
|
172
|
0
|
0
|
|
|
|
0
|
next unless($url); |
|
173
|
|
|
|
|
|
|
|
|
174
|
0
|
|
|
|
|
0
|
$self->{parent}->_log("url - [".(length $url)."] $url"); |
|
175
|
|
|
|
|
|
|
# print "$url\n"; |
|
176
|
|
|
|
|
|
|
|
|
177
|
0
|
|
|
|
|
0
|
my $res; |
|
178
|
0
|
|
|
|
|
0
|
eval { |
|
179
|
0
|
|
|
|
|
0
|
my $req = HTTP::Request->new(GET => $url); |
|
180
|
0
|
|
|
|
|
0
|
$res = $lwp->request($req); |
|
181
|
|
|
|
|
|
|
}; |
|
182
|
|
|
|
|
|
|
|
|
183
|
0
|
0
|
0
|
|
|
0
|
if($@ || !$res->is_success()) { |
|
|
|
0
|
|
|
|
|
|
|
184
|
0
|
|
|
|
|
0
|
$file = "$results-$r.html"; |
|
185
|
0
|
|
|
|
|
0
|
$self->{parent}->_log("FAIL: $0 - Cannot access page - see '$file' [$url] [" . length($url) . "] [$@]\n"); |
|
186
|
0
|
|
|
|
|
0
|
_save_content($res,$file); |
|
187
|
0
|
|
|
|
|
0
|
$status = 1; |
|
188
|
|
|
|
|
|
|
} elsif($res->header('Content-Type') =~ /html/) { |
|
189
|
0
|
|
|
|
|
0
|
$file = "$results-$r.html"; |
|
190
|
0
|
|
|
|
|
0
|
$self->{parent}->_log("FAIL: $0 - request failed - see '$file'\n"); |
|
191
|
0
|
|
|
|
|
0
|
_save_content($res,$file); |
|
192
|
0
|
|
|
|
|
0
|
$status = 1; |
|
193
|
|
|
|
|
|
|
} else { |
|
194
|
0
|
|
|
|
|
0
|
$file = "$results-$r.png"; |
|
195
|
0
|
|
|
|
|
0
|
_save_content($res,$file); |
|
196
|
|
|
|
|
|
|
|
|
197
|
0
|
0
|
|
|
|
0
|
if($r eq $latest) { |
|
198
|
0
|
|
|
|
|
0
|
$file = "$results.png"; |
|
199
|
0
|
|
|
|
|
0
|
_save_content($res,$file); |
|
200
|
|
|
|
|
|
|
} |
|
201
|
|
|
|
|
|
|
} |
|
202
|
|
|
|
|
|
|
} |
|
203
|
|
|
|
|
|
|
} |
|
204
|
|
|
|
|
|
|
|
|
205
|
0
|
|
|
|
|
0
|
$self->{parent}->_log("finish = $status"); |
|
206
|
0
|
|
|
|
|
0
|
return $status; |
|
207
|
|
|
|
|
|
|
} |
|
208
|
|
|
|
|
|
|
|
|
209
|
|
|
|
|
|
|
sub _save_content { |
|
210
|
0
|
|
|
0
|
|
0
|
my ($res,$file) = @_; |
|
211
|
0
|
0
|
|
|
|
0
|
my $fh = IO::File->new(">$file") or die "$0 - Cannot write file [$file]: $!\n"; |
|
212
|
0
|
0
|
|
|
|
0
|
binmode($fh) if($file =~ /\.png$/); |
|
213
|
0
|
|
|
|
|
0
|
print $fh $res->content; |
|
214
|
0
|
|
|
|
|
0
|
$fh->close; |
|
215
|
|
|
|
|
|
|
} |
|
216
|
|
|
|
|
|
|
|
|
217
|
|
|
|
|
|
|
#=item _make_graph |
|
218
|
|
|
|
|
|
|
# |
|
219
|
|
|
|
|
|
|
#Creates and writes out a single graph. |
|
220
|
|
|
|
|
|
|
# |
|
221
|
|
|
|
|
|
|
#=cut |
|
222
|
|
|
|
|
|
|
|
|
223
|
|
|
|
|
|
|
sub _make_graph { |
|
224
|
0
|
|
|
0
|
|
0
|
my ($self,$r,$file,$title,$legend,$rcode,$type,$path) = @_; |
|
225
|
0
|
|
|
|
|
0
|
my (@dates1,@dates2); |
|
226
|
0
|
|
|
|
|
0
|
my $yr = 0; |
|
227
|
|
|
|
|
|
|
|
|
228
|
0
|
|
|
|
|
0
|
my @data = $self->_get_data("$path/$file.txt",$r); |
|
229
|
|
|
|
|
|
|
#use Data::Dumper; |
|
230
|
|
|
|
|
|
|
#print STDERR "#type=$type, file=$file.txt, data=".Dumper(\@data); |
|
231
|
|
|
|
|
|
|
|
|
232
|
0
|
|
|
|
|
0
|
$self->{parent}->_log("checkpoint 1"); |
|
233
|
0
|
0
|
|
|
|
0
|
return unless(@data); |
|
234
|
0
|
|
|
|
|
0
|
$self->{parent}->_log("checkpoint 2"); |
|
235
|
|
|
|
|
|
|
|
|
236
|
0
|
|
|
|
|
0
|
for my $date (@{$data[0]}) { |
|
|
0
|
|
|
|
|
0
|
|
|
237
|
0
|
0
|
|
|
|
0
|
if($type eq 'index') { |
|
|
|
0
|
|
|
|
|
|
|
238
|
0
|
|
|
|
|
0
|
push @dates1, "'"; |
|
239
|
0
|
|
|
|
|
0
|
push @dates2, $date; |
|
240
|
|
|
|
|
|
|
} elsif($type eq 'month') { |
|
241
|
0
|
|
|
|
|
0
|
my $year = substr($date,0,4); |
|
242
|
0
|
|
|
|
|
0
|
my $month = substr($date,4,2); |
|
243
|
0
|
0
|
|
|
|
0
|
push @dates1, ($month % 2 == 1 ? $MONTHS[$month][0] : ''); |
|
244
|
0
|
0
|
|
|
|
0
|
push @dates2, ($year != $yr ? $year : ''); |
|
245
|
0
|
|
|
|
|
0
|
$yr = $year; |
|
246
|
|
|
|
|
|
|
} else { |
|
247
|
0
|
|
|
|
|
0
|
my $year = substr($date,0,4); |
|
248
|
0
|
|
|
|
|
0
|
my $month = substr($date,4,2); |
|
249
|
0
|
|
|
|
|
0
|
my $day = substr($date,6,2); |
|
250
|
0
|
0
|
0
|
|
|
0
|
push @dates1, ($day == 1 || $day % 7 == 0 ? sprintf "%d", $day : "'"); |
|
251
|
0
|
|
0
|
|
|
0
|
push @dates2, ($MONTHS[$month][$day-1] || ''); |
|
252
|
|
|
|
|
|
|
} |
|
253
|
|
|
|
|
|
|
} |
|
254
|
|
|
|
|
|
|
|
|
255
|
0
|
|
|
|
|
0
|
my $max = 0; |
|
256
|
0
|
|
|
|
|
0
|
for my $inx (1 .. $#data) { |
|
257
|
0
|
|
|
|
|
0
|
for my $data (@{$data[$inx]}) { |
|
|
0
|
|
|
|
|
0
|
|
|
258
|
0
|
0
|
|
|
|
0
|
$max = $data if($max < $data); |
|
259
|
|
|
|
|
|
|
} |
|
260
|
|
|
|
|
|
|
} |
|
261
|
|
|
|
|
|
|
|
|
262
|
0
|
|
|
|
|
0
|
$max = _set_max($max); |
|
263
|
0
|
|
|
|
|
0
|
my $range = _set_range(0,$max); |
|
264
|
|
|
|
|
|
|
|
|
265
|
0
|
|
|
|
|
0
|
my (@d,@c); |
|
266
|
0
|
|
|
|
|
0
|
my @colours = @COLOURS; |
|
267
|
0
|
|
|
|
|
0
|
for my $inx (1 .. $#data) { |
|
268
|
0
|
|
|
|
|
0
|
push @c, shift @colours; |
|
269
|
|
|
|
|
|
|
# data needs to be expressed as a percentage of the max |
|
270
|
0
|
|
|
|
|
0
|
for(@{$data[$inx]}) { |
|
|
0
|
|
|
|
|
0
|
|
|
271
|
|
|
|
|
|
|
#print "pcent = $_ / $max * 100 = "; |
|
272
|
0
|
|
|
|
|
0
|
$_ = $_ / $max * 100; |
|
273
|
|
|
|
|
|
|
#print "$_ = "; |
|
274
|
0
|
|
|
|
|
0
|
$_ = int($_ * 1) / 1; |
|
275
|
|
|
|
|
|
|
#print "$_\n"; |
|
276
|
|
|
|
|
|
|
} |
|
277
|
|
|
|
|
|
|
|
|
278
|
0
|
|
|
|
|
0
|
push @d, join(',',@{$data[$inx]}); |
|
|
0
|
|
|
|
|
0
|
|
|
279
|
|
|
|
|
|
|
} |
|
280
|
0
|
|
|
|
|
0
|
my $d = join('|',@d); |
|
281
|
0
|
|
|
|
|
0
|
my $data = sprintf $chart_data, $d; |
|
282
|
|
|
|
|
|
|
|
|
283
|
0
|
|
|
|
|
0
|
my $dates1 = join('|', @dates1); |
|
284
|
0
|
|
|
|
|
0
|
my $dates2 = join('|', @dates2); |
|
285
|
|
|
|
|
|
|
|
|
286
|
0
|
|
|
|
|
0
|
my $colour = sprintf $chart_colour, join(',',@c); |
|
287
|
0
|
|
|
|
|
0
|
my $titles = sprintf $chart_titles, $title, join('|',@$legend); |
|
288
|
0
|
|
|
|
|
0
|
my $labels = sprintf $chart_labels, $dates1, $dates2, $range, $range; |
|
289
|
0
|
|
|
|
|
0
|
$titles =~ s/ /+/g; |
|
290
|
0
|
|
|
|
|
0
|
$labels =~ s/ /+/g; |
|
291
|
0
|
|
|
|
|
0
|
my @api = ($chart_api, $titles, $labels, $colour, $chart_filler, $data) ; |
|
292
|
|
|
|
|
|
|
|
|
293
|
0
|
|
|
|
|
0
|
my $url = join('&',@api); |
|
294
|
0
|
|
|
|
|
0
|
$self->{parent}->_log("checkpoint 3 - $url"); |
|
295
|
0
|
|
|
|
|
0
|
return $url; |
|
296
|
|
|
|
|
|
|
} |
|
297
|
|
|
|
|
|
|
|
|
298
|
|
|
|
|
|
|
#=item _get_data |
|
299
|
|
|
|
|
|
|
# |
|
300
|
|
|
|
|
|
|
#Reads and returns the contents of the graph data file. |
|
301
|
|
|
|
|
|
|
# |
|
302
|
|
|
|
|
|
|
#=cut |
|
303
|
|
|
|
|
|
|
|
|
304
|
|
|
|
|
|
|
sub _get_data { |
|
305
|
0
|
|
|
0
|
|
0
|
my ($self,$file,$range) = @_; |
|
306
|
0
|
|
|
|
|
0
|
my ($fdate,$tdate) = split('-',$range); |
|
307
|
|
|
|
|
|
|
|
|
308
|
0
|
|
|
|
|
0
|
$self->{parent}->_log("get data - range=$range, fdate=$fdate, tdate=$tdate, file=$file"); |
|
309
|
|
|
|
|
|
|
|
|
310
|
0
|
|
|
|
|
0
|
my @data; |
|
311
|
0
|
0
|
|
|
|
0
|
my $fh = IO::File->new($file) |
|
312
|
|
|
|
|
|
|
or return (); |
|
313
|
|
|
|
|
|
|
#or die "Cannot open data file [$file]: $!\n"; |
|
314
|
0
|
|
|
|
|
0
|
while(<$fh>) { |
|
315
|
0
|
|
|
|
|
0
|
s/\s*$//; |
|
316
|
0
|
0
|
|
|
|
0
|
next unless($_); |
|
317
|
0
|
0
|
0
|
|
|
0
|
next if(/^#/ || /^$/); |
|
318
|
0
|
|
|
|
|
0
|
my @values = split(",",$_); |
|
319
|
0
|
0
|
0
|
|
|
0
|
next if($values[0] < $fdate || $values[0] > $tdate); |
|
320
|
0
|
|
|
|
|
0
|
push @{$data[$_]}, $values[$_] for(0..$#values); |
|
|
0
|
|
|
|
|
0
|
|
|
321
|
|
|
|
|
|
|
} |
|
322
|
0
|
|
|
|
|
0
|
return @data; |
|
323
|
|
|
|
|
|
|
} |
|
324
|
|
|
|
|
|
|
|
|
325
|
|
|
|
|
|
|
sub _dec2hex { |
|
326
|
288
|
|
|
288
|
|
656
|
my $hexnum = sprintf("%x", $_[0]); |
|
327
|
288
|
50
|
|
|
|
691
|
return '00' if(length($hexnum) < 1); |
|
328
|
288
|
100
|
|
|
|
861
|
return '0'.$hexnum if(length($hexnum) < 2); |
|
329
|
160
|
|
|
|
|
431
|
return $hexnum; |
|
330
|
|
|
|
|
|
|
} |
|
331
|
|
|
|
|
|
|
|
|
332
|
|
|
|
|
|
|
sub _set_max { |
|
333
|
8
|
|
|
8
|
|
3394
|
my $max = shift; |
|
334
|
8
|
|
|
|
|
15
|
my $lmt = 10; |
|
335
|
|
|
|
|
|
|
|
|
336
|
8
|
100
|
|
|
|
31
|
return $lmt if($max <= $lmt); |
|
337
|
|
|
|
|
|
|
|
|
338
|
7
|
|
|
|
|
16
|
my $len = length("$max") - 1; |
|
339
|
7
|
|
|
|
|
15
|
my $num = substr("$max",0,1); |
|
340
|
|
|
|
|
|
|
|
|
341
|
7
|
100
|
|
|
|
18
|
if($max < 100_000) { |
|
342
|
5
|
|
|
|
|
14
|
my $lmt1 = (10**$len) * $num; |
|
343
|
5
|
|
|
|
|
13
|
my $lmt2 = ((10**$len) * $num) + ((1**($len-1)) * 5); |
|
344
|
5
|
|
|
|
|
11
|
my $lmt3 = (10**$len) * ($num + 1); |
|
345
|
|
|
|
|
|
|
|
|
346
|
5
|
100
|
|
|
|
23
|
return $lmt1 if($max <= $lmt1); |
|
347
|
1
|
50
|
|
|
|
4
|
return $lmt2 if($max <= $lmt2); |
|
348
|
1
|
50
|
|
|
|
7
|
return $lmt3 if($max <= $lmt3); |
|
349
|
|
|
|
|
|
|
} |
|
350
|
|
|
|
|
|
|
|
|
351
|
2
|
50
|
|
|
|
9
|
$num += ($num % 2) ? 1 : 2; |
|
352
|
|
|
|
|
|
|
|
|
353
|
2
|
|
|
|
|
11
|
return (10**$len) * $num; |
|
354
|
|
|
|
|
|
|
} |
|
355
|
|
|
|
|
|
|
|
|
356
|
|
|
|
|
|
|
sub _set_range { |
|
357
|
8
|
|
|
8
|
|
20
|
my ($min,$max) = @_; |
|
358
|
|
|
|
|
|
|
|
|
359
|
8
|
|
|
|
|
17
|
my $len = length("$max") - 2; |
|
360
|
8
|
|
|
|
|
17
|
my $pc0 = $max / 10; |
|
361
|
|
|
|
|
|
|
|
|
362
|
8
|
|
|
|
|
20
|
my $x1 = 10**$len * 1; |
|
363
|
8
|
|
|
|
|
77
|
my $x2 = 10**$len * 2; |
|
364
|
8
|
|
|
|
|
16
|
my $x5 = 10**$len * 5; |
|
365
|
8
|
|
|
|
|
19
|
my $x0 = 10**$len * 10; |
|
366
|
|
|
|
|
|
|
|
|
367
|
8
|
100
|
|
|
|
30
|
my $step = $pc0 <= $x1 ? $x1 : $pc0 <= $x2 ? $x2 : $pc0 <= $x5 ? $x5 : $x0; |
|
|
|
50
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
368
|
|
|
|
|
|
|
|
|
369
|
8
|
|
|
|
|
16
|
my @r; |
|
370
|
8
|
|
|
|
|
26
|
for(my $r = $min; $r < ($max+$step); $r += $step) { |
|
371
|
41
|
100
|
|
|
|
152
|
my $x = $r < 1000 ? $r : $r < 1000000 ? ($r/1000) . 'k' : ($r/1000000) . 'm'; |
|
|
|
100
|
|
|
|
|
|
|
372
|
41
|
|
|
|
|
106
|
push @r, $x; |
|
373
|
|
|
|
|
|
|
}; |
|
374
|
|
|
|
|
|
|
|
|
375
|
8
|
|
|
|
|
52
|
return join('|',@r); |
|
376
|
|
|
|
|
|
|
} |
|
377
|
|
|
|
|
|
|
|
|
378
|
|
|
|
|
|
|
q('Will code for a nice Balti Lamb Tikka Bhuna'); |
|
379
|
|
|
|
|
|
|
|
|
380
|
|
|
|
|
|
|
__END__ |
|
381
|
|
|
|
|
|
|
|
|
382
|
|
|
|
|
|
|
=head1 CPAN TESTERS FUND |
|
383
|
|
|
|
|
|
|
|
|
384
|
|
|
|
|
|
|
CPAN Testers wouldn't exist without the help and support of the Perl |
|
385
|
|
|
|
|
|
|
community. However, since 2008 CPAN Testers has grown far beyond the |
|
386
|
|
|
|
|
|
|
expectations of it's original creators. As a consequence it now requires |
|
387
|
|
|
|
|
|
|
considerable funding to help support the infrastructure. |
|
388
|
|
|
|
|
|
|
|
|
389
|
|
|
|
|
|
|
In early 2012 the Enlightened Perl Organisation very kindly set-up a |
|
390
|
|
|
|
|
|
|
CPAN Testers Fund within their donatation structure, to help the project |
|
391
|
|
|
|
|
|
|
cover the costs of servers and services. |
|
392
|
|
|
|
|
|
|
|
|
393
|
|
|
|
|
|
|
If you would like to donate to the CPAN Testers Fund, please follow the link |
|
394
|
|
|
|
|
|
|
below to the Enlightened Perl Organisation's donation site. |
|
395
|
|
|
|
|
|
|
|
|
396
|
|
|
|
|
|
|
F<https://members.enlightenedperl.org/drupal/donate-cpan-testers> |
|
397
|
|
|
|
|
|
|
|
|
398
|
|
|
|
|
|
|
If your company would like to support us, you can donate financially via the |
|
399
|
|
|
|
|
|
|
fund link above, or if you have servers or services that we might use, please |
|
400
|
|
|
|
|
|
|
send an email to admin@cpantesters.org with details. |
|
401
|
|
|
|
|
|
|
|
|
402
|
|
|
|
|
|
|
Our full list of current sponsors can be found at our I <3 CPAN Testers site. |
|
403
|
|
|
|
|
|
|
|
|
404
|
|
|
|
|
|
|
F<http://iheart.cpantesters.org> |
|
405
|
|
|
|
|
|
|
|
|
406
|
|
|
|
|
|
|
=head1 BUGS, PATCHES & FIXES |
|
407
|
|
|
|
|
|
|
|
|
408
|
|
|
|
|
|
|
There are no known bugs at the time of this release. However, if you spot a |
|
409
|
|
|
|
|
|
|
bug or are experiencing difficulties, that is not explained within the POD |
|
410
|
|
|
|
|
|
|
documentation, please send bug reports and patches to the RT Queue (see below). |
|
411
|
|
|
|
|
|
|
|
|
412
|
|
|
|
|
|
|
Fixes are dependent upon their severity and my availability. Should a fix not |
|
413
|
|
|
|
|
|
|
be forthcoming, please feel free to (politely) remind me. |
|
414
|
|
|
|
|
|
|
|
|
415
|
|
|
|
|
|
|
RT Queue - |
|
416
|
|
|
|
|
|
|
http://rt.cpan.org/Public/Dist/Display.html?Name=CPAN-Testers-WWW-Statistics |
|
417
|
|
|
|
|
|
|
|
|
418
|
|
|
|
|
|
|
=head1 SEE ALSO |
|
419
|
|
|
|
|
|
|
|
|
420
|
|
|
|
|
|
|
L<CPAN::Testers::Data::Generator>, |
|
421
|
|
|
|
|
|
|
L<CPAN::Testers::WWW::Reports> |
|
422
|
|
|
|
|
|
|
|
|
423
|
|
|
|
|
|
|
F<http://www.cpantesters.org/>, |
|
424
|
|
|
|
|
|
|
F<http://stats.cpantesters.org/>, |
|
425
|
|
|
|
|
|
|
F<http://wiki.cpantesters.org/> |
|
426
|
|
|
|
|
|
|
|
|
427
|
|
|
|
|
|
|
=head1 AUTHOR |
|
428
|
|
|
|
|
|
|
|
|
429
|
|
|
|
|
|
|
Barbie, <barbie@cpan.org> |
|
430
|
|
|
|
|
|
|
for Miss Barbell Productions <http://www.missbarbell.co.uk>. |
|
431
|
|
|
|
|
|
|
|
|
432
|
|
|
|
|
|
|
=head1 COPYRIGHT AND LICENSE |
|
433
|
|
|
|
|
|
|
|
|
434
|
|
|
|
|
|
|
Copyright (C) 2005-2017 Barbie for Miss Barbell Productions. |
|
435
|
|
|
|
|
|
|
|
|
436
|
|
|
|
|
|
|
This distribution is free software; you can redistribute it and/or |
|
437
|
|
|
|
|
|
|
modify it under the Artistic Licence v2. |
|
438
|
|
|
|
|
|
|
|
|
439
|
|
|
|
|
|
|
=cut |