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