d78ff2cd3f007fd67cd7b5233ec3db33551ff699
[spider.git] / perl / Geomag.pm
1 #!/usr/bin/perl
2
3 # The geomagnetic information and calculation module
4 # a chanfe
5 #
6 # Copyright (c) 1998 - Dirk Koopman G1TLH
7 #
8 # $Id$
9 #
10
11 package Geomag;
12
13 use DXVars;
14 use DXUtil;
15 use DXLog;
16 use Julian;
17 use IO::File;
18 use Carp;
19
20 use strict;
21 use vars qw($date $sfi $k $a $r $forecast @allowed @denied $fp $node $from);
22
23 $fp = 0;                                                # the DXLog fcb
24 $date = 0;                                              # the unix time of the WWV (notional)
25 $sfi = 0;                                               # the current SFI value
26 $k = 0;                                                 # the current K value
27 $a = 0;                                                 # the current A value
28 $r = 0;                                                 # the current R value
29 $forecast = "";                                 # the current geomagnetic forecast
30 $node = "";                                             # originating node
31 $from = "";                                             # who this came from
32 @allowed = ();                                  # if present only these callsigns are regarded as valid WWV updators
33 @denied = ();                                   # if present ignore any wwv from these callsigns
34 my $dirprefix = "$main::data/wwv";
35 my $param = "$dirprefix/param";
36
37 sub init
38 {
39         $fp = DXLog::new('wwv', 'dat', 'm');
40         mkdir $dirprefix, 0777 if !-e $dirprefix; # now unnecessary DXLog will create it
41         do "$param" if -e "$param";
42         confess $@ if $@;
43 }
44
45 # write the current data away
46 sub store
47 {
48         my $fh = new IO::File;
49         open $fh, "> $param" or confess "can't open $param $!";
50         print $fh "# Geomagnetic data parameter file last mod:", scalar gmtime, "\n";
51         print $fh "\$date = $date;\n";
52         print $fh "\$sfi = $sfi;\n";
53         print $fh "\$a = $a;\n";
54         print $fh "\$k = $k;\n";
55         print $fh "\$r = $r;\n";
56         print $fh "\$from = '$from';\n";
57         print $fh "\$node = '$node';\n";
58         print $fh "\@denied = qw(", join(' ', @denied), ");\n" if @denied > 0;
59         print $fh "\@allowed = qw(", join(' ', @allowed), ");\n" if @allowed > 0;
60         close $fh;
61         
62         # log it
63         $fp->writeunix($date, "$from^$date^$sfi^$a^$k^$forecast^$node^$r");
64 }
65
66 # update WWV info in one go (usually from a PC23)
67 sub update
68 {
69         my ($mydate, $mytime, $mysfi, $mya, $myk, $myforecast, $myfrom, $mynode, $myr) = @_;
70         if ((@allowed && grep {$_ eq $from} @allowed) || 
71                 (@denied && !grep {$_ eq $from} @denied) ||
72                 (@allowed == 0 && @denied == 0)) {
73                 
74                 #       my $trydate = cltounix($mydate, sprintf("%02d18Z", $mytime));
75                 if ($mydate >= $date) {
76                         $sfi = 0 + $mysfi;
77             $r = 0 + $myr unless !$r && $myk == $k;
78                         $k = 0 + $myk;
79                         $a = 0 + $mya;
80                         $forecast = $myforecast;
81                         $date = $mydate;
82                         $from = $myfrom;
83                         $node = $mynode;
84                         
85                         store();
86                 }
87         }
88 }
89
90 # add or substract an allowed callsign
91 sub allowed
92 {
93         my $flag = shift;
94         if ($flag eq '+') {
95                 push @allowed, map {uc $_} @_;
96         } else {
97                 my $c;
98                 foreach $c (@_) {
99                         @allowed = map {$_ ne uc $c} @allowed; 
100                 } 
101         }
102         store();
103 }
104
105 # add or substract a denied callsign
106 sub denied
107 {
108         my $flag = shift;
109         if ($flag eq '+') {
110                 push @denied, map {uc $_} @_;
111         } else {
112                 my $c;
113                 foreach $c (@_) {
114                         @denied = map {$_ ne uc $c} @denied; 
115                 } 
116         }
117         store();
118 }
119
120 # accessor routines (when I work how symbolic refs work I might use one of those!)
121 sub sfi
122 {
123         @_ ? $sfi = shift : $sfi ;
124 }
125
126 sub k
127 {
128         @_ ? $k = shift : $k ;
129 }
130
131 sub r
132 {
133         @_ ? $r = shift : $r ;
134 }
135
136 sub a
137 {
138         @_ ? $a = shift : $a ;
139 }
140
141 sub forecast
142 {
143         @_ ? $forecast = shift : $forecast ;
144 }
145
146
147 #
148 # print some items from the log backwards in time
149 #
150 # This command outputs a list of n lines starting from line $from to $to
151 #
152 sub search
153 {
154         my $from = shift;
155         my $to = shift;
156         my @date = $fp->unixtoj(shift);
157         my $pattern = shift;
158         my $search;
159         my @out;
160         my $eval;
161         my $count;
162         
163         $search = 1;
164         $eval = qq(
165                            my \$c;
166                            my \$ref;
167                            for (\$c = \$#in; \$c >= 0; \$c--) {
168                                         \$ref = \$in[\$c];
169                                         if ($search) {
170                                                 \$count++;
171                                                 next if \$count < \$from;
172                                                 push \@out, \$ref;
173                                                 last if \$count >= \$to; # stop after n
174                                         }
175                                 }
176                           );
177         
178         $fp->close;                                     # close any open files
179         
180         my $fh = $fp->open(@date); 
181         for ($count = 0; $count < $to; ) {
182                 my @in = ();
183                 if ($fh) {
184                         while (<$fh>) {
185                                 chomp;
186                                 push @in, [ split '\^' ] if length > 2;
187                         }
188                         eval $eval;                     # do the search on this file
189                         return ("Geomag search error", $@) if $@;
190                         last if $count >= $to; # stop after n
191                 }
192                 $fh = $fp->openprev();  # get the next file
193                 last if !$fh;
194         }
195         
196         return @out;
197 }
198
199 #
200 # the standard log printing interpreting routine.
201 #
202 # every line that is printed should call this routine to be actually visualised
203 #
204 # Don't really know whether this is the correct place to put this stuff, but where
205 # else is correct?
206 #
207 # I get a reference to an array of items
208 #
209 sub print_item
210 {
211         my $r = shift;
212         my @ref = @$r;
213         my $d = cldate($ref[1]);
214         my ($t) = (gmtime($ref[1]))[2];
215         
216         return sprintf("$d   %02d %5d %3d %3d %-37s <%s>", $t, $ref[2], $ref[3], $ref[4], $ref[5], $ref[0]);
217 }
218
219 #
220 # read in this month's data
221 #
222 sub readfile
223 {
224         my @date = $fp->unixtoj(shift);
225         my $fh = $fp->open(@date); 
226         my @spots = ();
227         my @in;
228         
229         if ($fh) {
230                 while (<$fh>) {
231                         chomp;
232                         push @in, [ split '\^' ] if length > 2;
233                 }
234         }
235         return @in;
236 }
237 1;
238 __END__;