use Julian;
use Prefix;
use DXDupe;
+use Data::Dumper;
use strict;
-use vars qw($fp $maxspots $defaultspots $maxdays $dirprefix $duplth $dupage $filterdef);
+use vars qw($fp $statp $maxspots $defaultspots $maxdays $dirprefix $duplth $dupage $filterdef);
$fp = undef;
+$statp = undef;
$maxspots = 50; # maximum spots to return
$defaultspots = 10; # normal number of spots to return
-$maxdays = 365; # normal maximum no of days to go back
+$maxdays = 100; # normal maximum no of days to go back
$dirprefix = "spots";
$duplth = 20; # the length of text to use in the deduping
$dupage = 3*3600; # the length of time to hold spot dups
{
mkdir "$dirprefix", 0777 if !-e "$dirprefix";
$fp = DXLog::new($dirprefix, "dat", 'd');
+ $statp = DXLog::new($dirprefix, "bys", 'd');
}
sub prefix
return $fp->{prefix};
}
-# add a spot to the data file (call as Spot::add)
-sub add
+# fix up the full spot data from the basic spot data
+sub prepare
{
- my @spot = @_; # $freq, $call, $t, $comment, $spotter = @_
- my @out = @spot[0..4]; # just up to the spotter
+ # $freq, $call, $t, $comment, $spotter = @_
+ my @out = @_[0..4]; # just up to the spotter
# normalise frequency
- $spot[0] = sprintf "%.f", $spot[0];
+ $_[0] = sprintf "%.1f", $_[0];
# remove ssids if present on spotter
$out[4] =~ s/-\d+$//o;
# remove leading and trailing spaces
- $spot[3] = unpad($spot[3]);
+ $_[3] = unpad($_[3]);
# add the 'dxcc' country on the end for both spotted and spotter, then the cluster call
my @dxcc = Prefix::extract($out[1]);
my $spotter_itu = (@dxcc > 0 ) ? $dxcc[1]->itu() : 0;
my $spotter_cq = (@dxcc > 0 ) ? $dxcc[1]->cq() : 0;
push @out, $spotter_dxcc;
- push @out, $spot[5];
-
- my $buf = join("\^", @out);
-
- # compare dates to see whether need to open another save file (remember, redefining $fp
- # automagically closes the output file (if any)).
- $fp->writeunix($out[2], $buf);
-
+ push @out, $_[5];
return (@out, $spotted_itu, $spotted_cq, $spotter_itu, $spotter_cq);
}
+sub add
+{
+ my $buf = join("\^", @_[0..7]);
+ $fp->writeunix($_[2], $buf);
+}
+
# search the spot database for records based on the field no and an expression
# this returns a set of references to the spots
#
my $ref;
my $i;
my $count;
- my @today = Julian::unixtoj(time());
- my @fromdate;
- my @todate;
+ my $today = Julian::Day->new(time());
+ my $fromdate;
+ my $todate;
$dayfrom = 0 if !$dayfrom;
- $dayto = $maxdays if !$dayto;
- @fromdate = Julian::sub(@today, $dayfrom);
- @todate = Julian::sub(@fromdate, $dayto);
+ $dayto = $maxdays unless $dayto;
+ $dayto = $dayfrom + $maxdays if $dayto < $dayfrom;
+ $fromdate = $today->sub($dayfrom);
+ $todate = $fromdate->sub($dayto);
$from = 0 unless $from;
$to = $defaultspots unless $to;
$hint = $hint ? "next unless $hint" : "";
$expr =~ s/\$f(\d)/\$ref->[$1]/g; # swap the letter n for the correct field name
# $expr =~ s/\$f(\d)/\$spots[$1]/g; # swap the letter n for the correct field name
- dbg("search", "expr='$expr', spotno=$from-$to, day=$dayfrom-$dayto\n");
+ dbg("hint='$hint', expr='$expr', spotno=$from-$to, day=$dayfrom-$dayto\n") if isdbg('search');
# build up eval to execute
$eval = qq(
$fp->close; # close any open files
for ($i = $count = 0; $i < $maxdays; ++$i) { # look thru $maxdays worth of files only
- my @now = Julian::sub(@fromdate, $i); # but you can pick which $maxdays worth
- last if Julian::cmp(@now, @todate) <= 0;
+ my $now = $fromdate->sub($i); # but you can pick which $maxdays worth
+ last if $now->cmp($todate) <= 0;
my @spots = ();
- my $fh = $fp->open(@now); # get the next file
+ my $fh = $fp->open($now); # get the next file
if ($fh) {
my $in;
eval $eval; # do the search on this file
my ($a, $b) = @_;
return undef unless $a < $b;
$b--;
+ my $d = $b - $a;
my @a = split //, $a;
my @b = split //, $b;
my $out;
while (@b) {
my $aa = shift @a;
my $bb = shift @b;
- if ($aa eq $bb) {
+ if (@b < (length $d) - 1) {
+ $out .= '\\d';
+ } elsif ($aa eq $bb) {
$out .= $aa;
} elsif ($aa < $bb) {
$out .= "[$aa-$bb]";
} else {
- $out .= "[$bb-$aa]";
+ $out .= "[0-$bb$aa-9]";
}
}
return $out;
#
# return all the spots from a day's file as an array of references
# the parameter passed is a julian day
-sub readfile
+sub readfile($)
{
my @spots;
- my $fh = $fp->open(@_);
+ my $fh = $fp->open(shift);
if ($fh) {
my $in;
while (<$fh>) {
{
return DXDupe::listdups('X', $dupage, @_);
}
+
+sub genstats($)
+{
+ my $date = shift;
+ my $in = $fp->open($date);
+ my $out = $statp->open($date, 'w');
+ my @freq = (
+ [0, Bands::get_freq('160m')],
+ [1, Bands::get_freq('80m')],
+ [2, Bands::get_freq('40m')],
+ [3, Bands::get_freq('30m')],
+ [4, Bands::get_freq('20m')],
+ [5, Bands::get_freq('17m')],
+ [6, Bands::get_freq('15m')],
+ [7, Bands::get_freq('12m')],
+ [8, Bands::get_freq('10m')],
+ [9, Bands::get_freq('6m')],
+ [10, Bands::get_freq('4m')],
+ [11, Bands::get_freq('2m')],
+ [12, Bands::get_freq('70cm')],
+ [13, Bands::get_freq('13cm')],
+ [14, Bands::get_freq('9cm')],
+ [15, Bands::get_freq('6cm')],
+ [16, Bands::get_freq('3cm')],
+ [17, Bands::get_freq('12mm')],
+ [18, Bands::get_freq('6cm')],
+ );
+ my %list;
+ my @tot;
+
+ if ($in && $out) {
+ while (<$in>) {
+ chomp;
+ my ($freq, $by, $dxcc) = (split /\^/)[0,4,6];
+ my $ref = $list{$by} || [0, $dxcc];
+ for (@freq) {
+ if ($freq >= $_->[1] && $freq <= $_->[2]) {
+ $$ref[$_->[0]+2]++;
+ $tot[$_->[0]+2]++;
+ $$ref[0]++;
+ $tot[0]++;
+ $list{$by} = $ref;
+ last;
+ }
+ }
+ }
+
+ my $i;
+ for ($i = 0; $i < @freq+2; $i++) {
+ $tot[$i] ||= 0;
+ }
+ $out->write(join('^', 'TOTALS', @tot) . "\n");
+
+ for (sort {$list{$b}->[0] <=> $list{$a}->[0]} keys %list) {
+ my $ref = $list{$_};
+ my $call = $_;
+ for ($i = 0; $i < @freq+2; ++$i) {
+ $ref->[$i] ||= 0;
+ }
+ $out->write(join('^', $call, @$ref) . "\n");
+ }
+ $out->close;
+ }
+}
+
+# return true if the stat file is newer than than the spot file
+sub checkstats($)
+{
+ my $date = shift;
+ my $in = $fp->mtime($date);
+ my $out = $statp->mtime($date);
+ return defined $out && defined $in && $out >= $in;
+}
+
+# daily processing
+sub daily
+{
+ my $date = Julian::Day->new($main::systime)->sub(1);
+ genstats($date) unless checkstats($date);
+}
1;