File Coverage

blib/lib/Geomag/Kyoto/Dst.pm
Criterion Covered Total %
statement 77 117 65.8
branch 17 42 40.4
condition 6 23 26.0
subroutine 11 15 73.3
pod 3 3 100.0
total 114 200 57.0


line stmt bran cond sub pod time code
1             package Geomag::Kyoto::Dst;
2              
3 1     1   26972 use 5.008;
  1         4  
  1         33  
4 1     1   5 use strict;
  1         1  
  1         28  
5 1     1   4 use warnings;
  1         6  
  1         26  
6 1     1   1272 use LWP::Simple;
  1         138127  
  1         11  
7 1     1   672 use Time::Local;
  1         4  
  1         2125  
8              
9             @Geomag::Kyoto::Dst::FILES = qw(Dstqthism.html Dstqlastm.html);
10             $Geomag::Kyoto::Dst::BASE = 'http://swdcdb.kugi.kyoto-u.ac.jp/dstdir/dst1/q/';
11              
12             our $VERSION = '0.01';
13              
14             #
15             # Values stored in a hash: $time => $dst_val
16             #
17              
18             sub new {
19 1   50 1 1 12 my $class = shift || 'Geomag::Kyoto::Dst';
20 1         5 my $dst = bless { values => {}}, $class;
21 1         4 my %args = (@_);
22             # default if no args is to fetch thism and lastm
23 1 50       3 if (!@_) {
24 0         0 return $dst->_parse_base(base=>$Geomag::Kyoto::Dst::BASE, files=> [@Geomag::Kyoto::Dst::FILES]);
25             }
26             # if we have a single file => arg, then parse that file only
27 1 50       3 if (@_ == 2) {
28 1 50       3 if ($args{file}) {
29 1         6 return $dst->_parse_file($args{file});
30             }
31 0 0       0 if ($args{url}) {
32 0         0 return $dst->_parse_url($args{url});
33             }
34 0 0       0 if ($args{files}) {
35 0         0 foreach (@{$args{files}}) {
  0         0  
36 0         0 $dst->_parse_file($_);
37             }
38 0         0 return $dst;
39             }
40             }
41              
42 0 0       0 if (@_ == 4) {
43 0 0 0     0 $dst->_except("bad args to new()") unless $args{base} && $args{files};
44 0         0 return $dst->_parse_base(base=>$args{base}, files => $args{files});
45             }
46 0         0 $dst->_except("bad args to new()");
47             }
48              
49             sub get_array {
50 2     2 1 1880 my $dst = shift;
51 2         5 my @vals;
52 2         3 while (my ($time,$val) = each %{$dst->{values}}) {
  116         255  
53 114         261 push @vals, [$time, $val];
54             }
55 2 100       25 if (@_) {
56 1         3 my %args = @_;
57 1 50       4 if (my $start = $args{start}) {
58 1         2 @vals = grep {$_->[0] >= $start} @vals;
  57         115  
59             }
60 1 50       6 if (my $end = $args{end}) {
61 1         3 @vals = grep {$_->[0] <= $end} @vals;
  33         59  
62             }
63             }
64 2         12 @vals = sort {$a->[0] <=> $b->[0]} @vals;
  344         348  
65 2         7 return \@vals;
66             }
67              
68             sub get_hash {
69 0     0 1 0 my $dst = shift;
70             # no limits...
71 0 0       0 if (!@_) {
72 0         0 return $dst->{values};
73             }
74 0         0 my %args = @_;
75 0         0 my %ret;
76 0         0 my ($start, $end) = @args{qw(start end)};
77 0         0 while(my($time, $val) = each %{$dst->{values}}) {
  0         0  
78 0 0 0     0 if (!$start || $time >= $start) {
79 0 0 0     0 if (!$end || $time <= $end) {
80 0         0 $ret{$time} = $val;
81             }
82             }
83             }
84 0         0 return \%ret;
85             }
86              
87             sub _parse_file {
88 1     1   1 my $dst = shift;
89 1         1 my $file = shift;
90              
91 1 50       39 open(my $fh, "<$file") or $dst->_except("Cannot open $file $!");
92 1         2 my $contents = do {local $/; <$fh>};
  1         3  
  1         31  
93 1         7 close($fh);
94              
95 1         6 return $dst->_parse_scalar($contents);
96             }
97              
98             sub _parse_url {
99 0     0   0 my $dst =shift;
100 0         0 my $url = shift;
101              
102 0         0 my $contents = get($url);
103 0 0       0 $dst->_except("Failed to get $url") unless defined $contents;
104            
105 0         0 return $dst->_parse_scalar($contents);
106             }
107              
108             sub _parse_base {
109 0     0   0 my $dst = shift;
110 0         0 my %args = @_; # base, files
111              
112 0         0 my $base = $args{base};
113 0         0 my @files = @{$args{files}};
  0         0  
114 0         0 foreach my $file (@files) {
115 0         0 $dst->_parse_url("$base/$file");
116             }
117 0         0 return $dst;
118             }
119              
120             sub _parse_scalar {
121 1     1   1 my $dst = shift;
122 1         2 my $data = shift;
123 1         64 my @lines = split(/\n|\r\n|\r/, $data);
124              
125 1         4 my ($mon, $year, $day);
126 1         4 my @months = qw(january february march
127             april may june
128             july august september
129             october november december);
130 1         3 my $mnths = join("|", @months);
131 1         1 my $i = 0;
132 1         3 my %m_num = map {$_ => $i++} @months;
  12         25  
133              
134 1         4 foreach (@lines) {
135 68 100       397 /^\s+($mnths)\s+(\d{4})/i && do {
136 1         4 $mon = $m_num{lc($1)};
137 1         2 $year = +$2;
138 1         3 next;
139             };
140 67 50 66     155 if (/^DAY/ && !defined($mon) && !defined($year)) {
      33        
141 0         0 $dst->_except("Did not find month or year in data");
142             }
143             # optional space, day num, space 8 4 char groups, space, 8 4 char groups, space, 8 4 char groups
144 67 100       214 /^ ?(\d{1,2}) ([ 0-9-]{32}) ([ 0-9-]{32}) ([ 0-9-]{32})/ && do {
145 31         49 $day = $1;
146 31         118 $dst->_parse_vals($year, $mon, $day, "$2$3$4");
147             };
148             }
149 1         21 return $dst;
150             }
151              
152             sub _parse_vals {
153 31     31   34 my $dst = shift;
154 31         50 my ($year, $mon, $day, $sval) = @_;
155 31 50 33     176 $dst->_except("No year, mon or day") unless defined($year) && defined($mon) && defined($day);
      33        
156              
157             # four character groups
158 31         61 for (my $hour = 0; $hour < 24; $hour++) {
159 744         927 my $val = substr($sval, $hour*4, 4);
160             # only add valid values
161 744 100       1760 next if ($val eq "9999");
162 57 50       82 next if ($val eq " ");
163 57         124 $dst->_add_val($year, $mon, $day, $hour, $val);
164             }
165 31         79 return $dst;
166             }
167              
168             # expects values to be valid
169             sub _add_val {
170 57     57   77 my($dst, $year, $mon, $day, $hour, $val) = @_;
171             # only here do we alter into computer time values
172 57         121 my $epoch = timegm(0,0,$hour, $day, $mon, $year-1900);
173 57         1025 $dst->{values}->{$epoch} = $val;
174             }
175              
176             # placeholder for proper exceptions
177             sub _except {
178 0     0     my $self = shift;
179 0           die "DST: Exception: $_[0]";
180             }
181              
182             1;
183             __END__