File Coverage

blib/lib/Mock/Populate.pm
Criterion Covered Total %
statement 174 185 94.0
branch 13 24 54.1
condition 29 57 50.8
subroutine 26 26 100.0
pod 10 10 100.0
total 252 302 83.4


line stmt bran cond sub pod time code
1             package Mock::Populate;
2             our $AUTHORITY = 'cpan:GENE';
3              
4             # ABSTRACT: Mock data creation
5              
6             our $VERSION = '0.1702';
7              
8 1     1   605 use strict;
  1         2  
  1         24  
9 1     1   4 use warnings;
  1         1  
  1         23  
10              
11 1     1   19 use constant NDATA => 10;
  1         1  
  1         89  
12 1     1   5 use constant PREC => 2;
  1         2  
  1         45  
13 1     1   5 use constant DOF => 2;
  1         2  
  1         35  
14 1     1   4 use constant SIZE => 8;
  1         1  
  1         31  
15              
16 1     1   342 use Data::SimplePassword ();
  1         66102  
  1         25  
17 1     1   362 use Date::Range ();
  1         747  
  1         22  
18 1     1   384 use Date::Simple qw(date today);
  1         4119  
  1         51  
19 1     1   329 use Image::Dot qw(dot_PNG_RGB);
  1         807  
  1         48  
20 1     1   353 use Mock::Person ();
  1         2987  
  1         17  
21 1     1   351 use Statistics::Distributions ();
  1         2508  
  1         19  
22 1     1   372 use Text::Password::Pronounceable ();
  1         1534  
  1         25  
23 1     1   403 use Text::Unidecode qw(unidecode);
  1         1468  
  1         53  
24 1     1   383 use Time::Local qw(timegm);
  1         1809  
  1         1797  
25              
26              
27             sub date_ranger {
28 1     1 1 484 my %args = @_;
29             # Set defaults.
30 1   50     6 $args{start} ||= '1970-01-01';
31 1   33     6 $args{end} ||= today();
32 1   50     87 $args{N} ||= NDATA;
33              
34             # Convert the dates into a range.
35 1         2 my $date1 = date($args{start});
36 1         36 my $date2 = date($args{end});
37 1         19 my $range = Date::Range->new($date1, $date2);
38              
39             # Bucket for our result list.
40 1         25 my @results;
41              
42 1         3 for(1 .. $args{N}) {
43             # Get a random number of days in the range.
44 10         45 my $offset = int(rand $range->length);
45              
46             # Save the stringified start date plus the offest.
47 10         119 my $date = $date1 + $offset;
48 10         183 push @results, "$date";
49             }
50              
51 1         11 return \@results;
52             }
53              
54              
55             sub date_modifier {
56             # Get the number of days and the date list.
57 1     1 1 1011 my ($offset, @dates) = @_;
58              
59             # Bucket for our result list.
60 1         2 my @results;
61              
62 1         2 for my $date (@dates) {
63             # Cast the current date string as an object.
64 10         38 my $current = date($date);
65              
66             # Get a random number of days.
67 10         209 my $m = int(rand $offset) + 1;
68              
69             # Save the stringified date plus the offest.
70 10         28 $date = $current + $m;
71 10         178 push @results, "$date";
72             }
73              
74 1         5 return \@results;
75             }
76              
77              
78             sub time_ranger {
79 1     1 1 901 my %args = @_;
80             # Set defaults.
81 1   50     7 $args{stamp} //= 1;
82 1   50     4 $args{start} ||= '00:00:00';
83 1   50     5 $args{end} ||= '';
84 1   50     7 $args{N} ||= NDATA;
85              
86             # Split the :-separated times.
87 1         2 my @start = split ':', $args{start};
88 1 50       5 my @end = $args{end} ? split(':', $args{end}) : _now();
89             #warn "S->E: @start -> @end\n";
90              
91             # Compute the number of seconds between start and end.
92 1         15 my $start_time = timegm(@start[2, 1, 0], (localtime(time))[3, 4, 5]);
93 1         44 my $end_time = timegm(@end[2, 1, 0], (localtime(time))[3, 4, 5]);
94 1         22 my $range = $end_time - $start_time;
95             #warn "R: $end_time (@end) - $start_time (@start) = $range\n";
96              
97             # Bucket for our result list.
98 1         1 my @results;
99              
100             # Generate a time, N times.
101 1         3 for(1 .. $args{N}) {
102             # Get a random number of seconds in the range.
103 10         17 my $offset = int(rand $range);
104              
105             # Print the start time plus the offest seconds.
106 10 50       19 if ($args{stamp}) {
107             # In HH:MM::SS format.
108 10         127 my $time = scalar localtime($start_time + $offset);
109 10         62 push @results, (split /\s+/, $time)[3];
110             }
111             else {
112             # As a number of seconds from the "epoc."
113 0         0 push @results, $start_time + $offset;
114             }
115             #use Data::Dumper;warn(__PACKAGE__,' ',__LINE__," MARK: ",Dumper\@results);
116             }
117              
118 1         5 return \@results;
119             }
120              
121             sub _now { # Return hour, minute, second.
122 1     1   22 return (localtime(time))[2, 1, 0];
123             }
124              
125              
126             sub number_ranger {
127 1     1 1 896 my %args = @_;
128             # Set defaults.
129 1   50     7 $args{start} //= 1;
130 1   50     4 $args{end} //= NDATA;
131 1   50     4 $args{prec} //= PREC;
132 1   50     3 $args{random} //= 1;
133 1   50     4 $args{N} ||= NDATA;
134              
135             # Bucket for our result list.
136 1         1 my @results;
137              
138             # Do we want random numbers?
139 1 50       3 if ($args{random}) {
140             # Roll!
141 1         3 for(1 .. $args{N}) {
142             # Get our random candidate.
143 10         12 my $x = rand($args{end});
144             # Make sure it is above the start value.
145 10         17 while ($x < $args{start}) {
146 0         0 $x = rand($args{end});
147             }
148 10         28 $x = sprintf '%.*f', $args{prec}, $x;
149 10         18 push @results, $x;
150             }
151             }
152             else {
153             # Use a contiguous sequence.
154 0         0 @results = ($args{start} .. $args{end});
155 0         0 for ( @results ) {
156 0         0 $_ = sprintf '%.*f', $args{prec}, $_;
157             }
158             }
159              
160 1         3 return \@results;
161             }
162              
163              
164             sub name_ranger {
165 1     1 1 903 my %args = @_;
166             # Set defaults.
167 1   50     7 $args{gender} ||= 'b';
168 1   50     4 $args{names} ||= 2;
169 1   50     6 $args{country} ||= 'us';
170 1   50     4 $args{N} ||= NDATA;
171              
172             # Bucket for our result list.
173 1         1 my @results;
174              
175             # Roll!
176 1         3 for my $i (1 .. $args{N}) {
177             # Get our random person.
178 10         12 my $p = '';
179             # If gender is 'both' alternate male/female.
180 10 100 66     37 if (($args{gender} eq 'b' && $i % 2) || $args{gender} eq 'f') {
      66        
181 5         10 $p = Mock::Person::name(sex => 'female', country => $args{country});
182             }
183             else {
184 5         9 $p = Mock::Person::name(sex => 'male', country => $args{country});
185             }
186             # Only use the requested number of names.
187 10         253 my @names = split / /, $p;
188 10 50       20 if ($args{names} == 1) {
    50          
189 0         0 push @results, $names[-1];
190             }
191             elsif ($args{names} == 2) {
192 10         28 push @results, "@names[0,-1]";
193             }
194             else {
195 0         0 push @results, $p;
196             }
197             }
198              
199 1         4 return \@results;
200             }
201              
202              
203             sub email_modifier {
204 1     1 1 918 my @people = @_;
205              
206 1         3 my @tld = qw( com net org edu );
207              
208             # Bucket for our results.
209 1         2 my @results = ();
210              
211 1         2 for my $p (@people) {
212             # Break up the name.
213 10         24 my @name = split / /, $p;
214              
215 10         12 for ( @name ) {
216             # Turn any unicode characters into something ascii.
217 20         34 $_ = unidecode($_);
218             # Remove non-alpha_nums
219 20         1509 s/\W//g;
220             }
221              
222             # Add an email address for the person.
223 10         14 my $email = lc($name[0]);
224 10 50       24 $email .= '.'. lc($name[-1]) if @name > 1;
225 10         37 $email .= '@example.' . $tld[int rand @tld];
226 10         21 push @results, $email;
227             }
228              
229 1         4 return \@results;
230             }
231              
232              
233             sub distributor {
234 1     1 1 925 my %args = @_;
235             # Set defaults.
236 1   50     7 $args{type} ||= 'u';
237 1   50     4 $args{prec} //= PREC;
238 1   50     6 $args{dof} //= DOF;
239 1   50     4 $args{N} ||= NDATA;
240              
241             # Separate numerator/denominator for F degs-of-freedom.
242 1         2 my $e = 1;
243 1 50       3 ($args{dof}, $e) = split(/\//, $args{dof}) if $args{type} eq 'f';
244              
245             # Bucket for our result list.
246 1         1 my @results;
247              
248             # Roll!
249 1         3 for(1 .. $args{N}) {
250 10         10 my $x;
251              
252             # Select distribution.
253 10 50       22 if ($args{type} eq 'c') {
    50          
    50          
254             # Chi-squared
255 0         0 $x = Statistics::Distributions::chisqrdistr($args{dof}, rand);
256             }
257             elsif ($args{type} eq 's') {
258             # Student's T
259 0         0 $x = Statistics::Distributions::tdistr($args{dof}, rand);
260             }
261             elsif ($args{type} eq 'f') {
262             # F distribution
263 0         0 $x = Statistics::Distributions::fdistr($args{dof}, $e, rand);
264             }
265             else {
266             # Normal
267 10         20 $x = Statistics::Distributions::udistr(rand);
268             }
269              
270 10         252 $x = sprintf '%.*f', $args{prec}, $x;
271 10         19 push @results, $x;
272             }
273              
274 1         5 return \@results;
275             }
276              
277              
278             sub string_ranger {
279 1     1 1 855 my %args = @_;
280             # Set defaults.
281 1   50     7 $args{length} ||= SIZE;
282 1   50     4 $args{type} ||= 'default';
283 1   50     4 $args{N} ||= NDATA;
284              
285             # Declare a pw instance.
286 1         9 my $sp = Data::SimplePassword->new;
287              
288             # Declare the types (lifted directly from rndpassword).
289             my $chars = {
290             default => [ 0..9, 'a'..'z', 'A'..'Z' ],
291 1         1246 ascii => [ map { sprintf "%c", $_ } 33 .. 126 ],
  94         215  
292             base64 => [ 0..9, 'a'..'z', 'A'..'Z', qw(+ /) ],
293             path => [ 0..9, 'a'..'z', 'A'..'Z', qw(. /) ],
294             simple => [ 0..9, 'a'..'z' ],
295             alpha => [ 'a'..'z' ],
296             digit => [ 0..9 ],
297             binary => [ qw(0 1) ],
298             morse => [ qw(. -) ],
299             hex => [ 0..9, 'a'..'f' ],
300             pron => [],
301             };
302             # Set the chars based on the given type.
303 1         7 $sp->chars( @{ $chars->{$args{type}} } );
  1         8  
304              
305             # Declare a bucket for our results.
306 1         99 my @results = ();
307              
308             # Roll!
309 1         3 for(1 .. $args{N}) {
310 10 50       8696 if ($args{type} eq 'pron') {
311             push @results, Text::Password::Pronounceable->generate(
312             $args{length}, $args{length}
313 0         0 );
314             }
315             else {
316 10         30 push @results, $sp->make_password($args{length});
317             }
318             }
319              
320 1         665 return \@results;
321             }
322              
323              
324             sub image_ranger {
325 1     1 1 1028 my %args = @_;
326             # Set defaults.
327 1   50     9 $args{size} ||= SIZE;
328 1   50     5 $args{N} ||= NDATA;
329              
330             # Declare a bucket for our results.
331 1         1 my @results = ();
332              
333             # Start with a 1x1 pixel image.
334 1         24 my $img = dot_PNG_RGB(0, 0, 0);
335              
336             # XXX This is naive and sad:
337             # Pull-apart the image data.
338 1         66 (my $head = $img) =~ s/^(.*?IDAT).*$/$1/ms;
339 1         6 (my $tail = $img) =~ s/^.*?(IEND.*)$/$1/ms;
340 1         13 $img =~ s/^.*?IDAT(.*?)IEND.*$/$1/ms;
341              
342 1         5 for (1 .. $args{N}) {
343             # Increase the byte size (not dimension).
344 10         25 my $i = $head . ($img x int(rand $args{size})) . $tail;
345             #warn "L: ",length($i), "\n";
346              
347             # Save the result.
348 10         15 push @results, $i;
349             }
350              
351 1         5 return \@results;
352             }
353              
354              
355             sub collate {
356             # Accept any number of columns.
357 1     1 1 1505 my @columns = @_;
358              
359             # Declare the bucket for our arrayrefs.
360 1         2 my @results = ();
361              
362             # Add each list item to rows of collated.
363 1         3 for my $list (@columns) {
364 2         4 for my $i (0 .. @$list - 1) {
365 20         21 push @{ $results[$i] }, $list->[$i];
  20         33  
366             }
367             }
368              
369 1         4 return \@results;
370             }
371              
372             1;
373              
374             __END__