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