811a708034f471070d824e7a71d95cbe31a3f736
[spider.git] / perl / spot.pm
1 #
2 # the dx spot handler
3 #
4 # Copyright (c) - 1998 Dirk Koopman G1TLH
5 #
6 # $Id$
7 #
8
9 package spot;
10
11 use FileHandle;
12 use DXVars;
13 use DXDebug;
14 use julian;
15
16 @ISA = qw(julian);
17
18 use strict;
19
20 my $fp;
21 my $maxdays = 60;    # maximum no of days to store spots in the table
22 my $prefix = "$main::data/spots";
23 my @table = ();      # the list of spots (held in reverse order)
24
25 # read in n days worth of dx spots into memory
26 sub init
27 {
28   my @today = julian->unixtoj(time);        # get the julian date now
29   my @first = julian->sub(@today, $maxdays);     # get the date $maxdays ago
30   my $count;
31   
32   mkdir($prefix, 0777) if ! -e $prefix;     # create the base directory if required
33   for (my $i = 0; $i < $maxdays; ++$i) {
34     my $ref = spot->open(@first);
35         if ($ref) {
36           my $fh = $ref->{fh};
37           while (<$fh>) {
38             chomp;
39             my @ent = split /\^/;
40             unshift @spot::table, [ @ent ];                # stick this ref to anon list on the FRONT of the table
41                 ++$count;
42           }
43         }
44     @first = julian->add(@first, 1);
45   }
46   return $count;
47 }
48
49 # create a new spot on the front of the list, add it to the data file
50 sub new
51 {
52   my $pkg = shift;
53   my @spot = @_;    # $freq, $call, $t, $comment, $spotter = @_
54
55   # sure that the numeric things are numeric now (saves time later)
56   $spot[0] = 0 + $spot[0];
57   $spot[2] = 0 + $spot[2];
58   
59   # save it on the front of the list
60   unshift @spot::table, [ @spot ];
61   
62   # compare dates to see whether need to open a other save file
63   my @date = julian->unixtoj($spot[2]);
64   $fp = spot->open(@date, ">>") if (!$fp || julian->cmp(@date, $fp->{year}, $fp->{day}));
65   my $fh = $fp->{fh};
66   $fh->print(join("\^", @spot), "\n");
67 }
68
69 # purge all the spots older than $maxdays - this is fairly approximate
70 # this should be done periodically from some cron task
71 sub purge
72 {
73   my $old = time - ($maxdays * 86400);
74   my $ref;
75   
76   while (@spot::table) {
77     my $ref = pop @spot::table;
78         if (${$ref}[2] > $old) {
79           push @spot::table, $ref;        # put it back
80           last;                     # and leave
81         }
82   }
83 }
84
85 # search the spot database for records based on the field no and an expression
86 # this returns a set of references to the spots
87 #
88 # for string fields supply a pattern to match
89 # for numeric fields supply a range of the format 'n > x  && n < y' (the n will
90 # changed to the correct field name) [ n is literally the letter 'n' ]
91 #
92 sub search
93 {
94   my ($pkg, $field, $expr) = @_;
95   my $eval;
96   my @out;
97   my $ref;
98  
99   dbg('spot', "input expr = $expr\n");
100   if ($field == 0 || $field == 2) {              # numeric fields
101     $expr =~ s/n/\$ref->[$field]/g;               # swap the letter n for the correct field name
102   } else {
103     $expr = qq(\$ref->[$field] =~ /$expr/oi);      # alpha expressions
104   }
105   dbg('spot', "expr now = $expr\n");
106   
107   # build up eval to execute
108   $eval = qq(foreach \$ref (\@spot::table) {
109     push \@out, \$ref if $expr;
110   });
111   dbg('spot', "eval = $eval\n");
112   eval $eval;                                   # execute it
113   return @out;
114 }
115
116 # open a spot file of the julian day
117 sub open
118 {
119   my $pkg = shift;
120   return julian->open("spot", $prefix, @_);
121 }
122
123 # close a spot file
124 sub close
125 {
126   # do nothing, unreferencing or overwriting the $self will close it  
127 }
128
129 1;