route cache, wcy, wwv. ann caching
[spider.git] / perl / WCY.pm
1 #!/usr/bin/perl
2
3 # The WCY analog of the WWV geomagnetic information and calculation module
4 #
5 # Copyright (c) 2000 - Dirk Koopman G1TLH
6 #
7 #
8 #
9
10 package WCY;
11
12 use DXVars;
13 use DXUtil;
14 use DXLog;
15 use Julian;
16 use IO::File;
17 use DXDebug;
18 use Data::Dumper;
19
20 use strict;
21
22 use vars qw($date $sfi $k $expk $a $r $sa $gmf $au  @allowed @denied $fp $node $from 
23             $dirprefix $param
24             $duplth $dupage $filterdef);
25
26 $fp = 0;                                                # the DXLog fcb
27 $date = 0;                                              # the unix time of the WWV (notional)
28 $sfi = 0;                                               # the current SFI value
29 $k = 0;                                                 # the current K value
30 $a = 0;                                                 # the current A value
31 $r = 0;                                                 # the current R value
32 $sa = "";                                               # solar activity
33 $gmf = "";                                              # Geomag activity
34 $au = 'no';                                             # aurora warning
35 $node = "";                                             # originating node
36 $from = "";                                             # who this came from
37 @allowed = qw(DK0WCY);                                  # if present only these callsigns are regarded as valid WWV updators
38 @denied = ();                                   # if present ignore any wwv from these callsigns
39 $duplth = 20;                                   # the length of text to use in the deduping
40 $dupage = 12*3600;                              # the length of time to hold spot dups
41
42 $dirprefix = "$main::local_data/wcy";
43 $param = "$dirprefix/param";
44
45 our $maxcache = 20;
46 our @cache;
47
48
49 $filterdef = bless ([
50                           # tag, sort, field, priv, special parser 
51                           ['by', 'c', 11],
52                           ['origin', 'c', 12],
53                           ['channel', 'c', 13],
54                           ['by_dxcc', 'nc', 14],
55                           ['by_itu', 'ni', 15],
56                           ['by_zone', 'nz', 16],
57                           ['origin_dxcc', 'nc', 17],
58                           ['origin_itu', 'ni', 18],
59                           ['origin_zone', 'nz', 19],
60                          ], 'Filter::Cmd');
61
62 sub init
63 {
64         $fp = DXLog::new('wcy', 'dat', 'm');
65         do "$param" if -e "$param";
66         # read in existing data
67         @cache = readfile($main::systime);
68         shift @cache while @cache > $maxcache;
69         dbg(sprintf "WCY read in last %d records into cache", scalar @cache);   
70         confess $@ if $@;
71 }
72
73 # write the current data away
74 sub store
75 {
76         my $fh = new IO::File;
77         open $fh, "> $param" or confess "can't open $param $!";
78         print $fh "# WCY data parameter file last mod:", scalar gmtime, "\n";
79         my $dd = new Data::Dumper([ $date, $sfi, $a, $k, $expk, $r, $sa, $gmf, $au, $from, $node, \@denied, \@allowed ], [qw(date sfi a k expk r sa gmf au from node *denied *allowed)]);
80         $dd->Indent(1);
81         $dd->Terse(0);
82         $dd->Quotekeys(0);
83         $fh->print($dd->Dumpxs);
84         $fh->close;
85         
86         # log it
87         my $s =  "$date^$sfi^$a^$k^$expk^$r^$sa^$gmf^$au^$from^$node";
88         $fp->writeunix($date, $s);
89         push @cache, [ split /\^/, $s ];
90         shift @cache while @cache > $maxcache; 
91 }
92
93 # update WCY info in one go (usually from a PC23)
94 sub update
95 {
96         my ($mydate, $mytime, $mysfi, $mya, $myk, $myexpk, $myr, $mysa, $mygmf, $myau, $myfrom, $mynode) = @_;
97         $myfrom =~ s/-\d+$//;
98         if ((@allowed && grep {$_ eq $myfrom} @allowed) || 
99                 (@denied && !grep {$_ eq $myfrom} @denied) ||
100                 (@allowed == 0 && @denied == 0)) {
101                 
102                 #       my $trydate = cltounix($mydate, sprintf("%02d18Z", $mytime));
103                 if ($mydate >= $date) {
104                         if ($myr) {
105                                 $r = 0 + $myr;
106                         } else {
107                                 $r = 0 unless abs ($mysfi - $sfi) > 3;
108                         }
109                         $sfi = $mysfi;
110                         $a = $mya;
111                         $k = $myk;
112                         $expk = $myexpk;
113                         $r = $myr;
114                         $sa = $mysa;
115                         $gmf = $mygmf;
116                         $au = $myau;
117                         $date = $mydate;
118                         $from = $myfrom;
119                         $node = $mynode;
120                         
121                         store();
122                 }
123         }
124 }
125
126 # add or substract an allowed callsign
127 sub allowed
128 {
129         my $flag = shift;
130         if ($flag eq '+') {
131                 push @allowed, map {uc $_} @_;
132         } else {
133                 my $c;
134                 foreach $c (@_) {
135                         @allowed = map {$_ ne uc $c} @allowed; 
136                 } 
137         }
138         store();
139 }
140
141 # add or substract a denied callsign
142 sub denied
143 {
144         my $flag = shift;
145         if ($flag eq '+') {
146                 push @denied, map {uc $_} @_;
147         } else {
148                 my $c;
149                 foreach $c (@_) {
150                         @denied = map {$_ ne uc $c} @denied; 
151                 } 
152         }
153         store();
154 }
155
156 #
157 # print some items from the log backwards in time
158 #
159 # This command outputs a list of n lines starting from line $from to $to
160 #
161 sub search
162 {
163         my $from = shift;
164         my $to = shift;
165         my $t = shift;
166         my $date = $fp->unixtoj($t);
167         my $pattern = shift;
168         my $search;
169         my @out;
170         my $eval;
171         my $count;
172         my $i;
173
174         if ($t == $main::systime && ($to <= $maxcache)) {
175                 dbg("using wcy cache") if isdbg('wcy');
176                 @out = reverse @cache;
177                 pop @out while @out > $to;
178         } else {
179                 dbg("using wwv file(s))") if isdbg('wwv');
180                 $search = 1;
181                 $eval = qq(
182                            my \$c;
183                            my \$ref;
184                            for (\$c = \$#in; \$c >= 0; \$c--) {
185                                         \$ref = \$in[\$c];
186                                         if ($search) {
187                                                 \$count++;
188                                                 next if \$count < \$from;
189                                                 push \@out, \$ref;
190                                                 last if \$count >= \$to; # stop after n
191                                         }
192                                 }
193                           );
194                 
195                 $fp->close;                                     # close any open files
196                 my $fh = $fp->open($date); 
197                 for ($i = $count = 0; $count < $to; $i++ ) {
198                         my @in = ();
199                         if ($fh) {
200                                 while (<$fh>) {
201                                         chomp;
202                                         push @in, [ split '\^' ] if length > 2;
203                                 }
204                                 eval $eval;                     # do the search on this file
205                                 return ("Geomag search error", $@) if $@;
206                                 last if $count >= $to; # stop after n
207                         }
208                         $fh = $fp->openprev();  # get the next file
209                         last if !$fh;
210                 }
211         }
212         
213         return @out;
214 }
215
216 #
217 # the standard log printing interpreting routine.
218 #
219 # every line that is printed should call this routine to be actually visualised
220 #
221 # Don't really know whether this is the correct place to put this stuff, but where
222 # else is correct?
223 #
224 # I get a reference to an array of items
225 #
226 sub print_item
227 {
228         my $r = shift;
229         my $d = cldate($r->[0]);
230         my $t = (gmtime($r->[0]))[2];
231
232         return sprintf("$d   %02d %5d %3d %3d   %3d %3d %-5s %-5s %6s <%s>", 
233                                     $t, @$r[1..9]);
234 }
235
236 #
237 # read in this month's data
238 #
239 sub readfile
240 {
241         my $date = $fp->unixtoj(shift);
242         my $fh = $fp->open($date); 
243         my @spots = ();
244         my @in;
245         
246         if ($fh) {
247                 while (<$fh>) {
248                         chomp;
249                         push @in, [ split '\^' ] if length > 2;
250                 }
251         }
252         return @in;
253 }
254
255 # enter the spot for dup checking and return true if it is already a dup
256 sub dup
257 {
258         my ($d) = @_; 
259
260         # dump if too old
261         return 2 if $d < $main::systime - $dupage;
262  
263         my $dupkey = "C$d";
264         return DXDupe::check($dupkey, $main::systime+$dupage);
265 }
266
267 sub listdups
268 {
269         return DXDupe::listdups('C', $dupage, @_);
270 }
271 1;
272 __END__;
273