use Carp;
use strict;
+
+# create a log object that contains all the useful info needed
+# prefix is the main directory off of the data directory
+# sort is 'm' for monthly, 'd' for daily
+sub new
+{
+ my ($prefix, $suffix, $sort) = @_;
+ my $ref = {};
+ $ref->{prefix} = "$main::data/$prefix";
+ $ref->{suffix} = $suffix if $suffix;
+ $ref->{sort} = $sort;
+
+ # make sure the directory exists
+ mkdir($ref->{prefix}, 0777) if ! -e $ref->{prefix};
+ return bless $ref;
+}
+
+# open the appropriate data file
+sub open
+{
+ my ($self, $year, $thing, $mode) = @_;
+
+ # if we are writing, check that the directory exists
+ if (defined $mode) {
+ my $dir = "$self->{prefix}/$year";
+ mkdir($dir, 0777) if ! -e $dir;
+ $self->{mode} = $mode;
+ } else {
+ delete $self->{mode};
+ }
+
+ $self->{fn} = sprintf "$self->{prefix}/$year/%03d", $thing;
+ $self->{fn} .= ".$self->{suffix}" if $self->{suffix};
+
+ $mode = 'r' if !$mode;
+ my $fh = new FileHandle $self->{fn}, $mode;
+ return undef if !$fh;
+ $fh->autoflush(1) if $mode ne 'r'; # make it autoflushing if writable
+ $self->{fh} = $fh;
+
+ $self->{year} = $year;
+ $self->{thing} = $thing;
+
+ dbg("dxlog", "opening $self->{fn}\n");
+
+ return $self->{fh};
+}
+
+# open the previous log file in sequence
+sub openprev
+{
+ my $self = shift;
+ if ($self->{sort} eq 'm') {
+ ($self->{year}, $self->{thing}) = Julian::subm($self->{year}, $self->{thing}, 1);
+ } elsif ($self->{sort} eq 'd') {
+ ($self->{year}, $self->{thing}) = Julian::sub($self->{year}, $self->{thing}, 1);
+ }
+ return $self->open($self->{year}, $self->{thing}, @_);
+}
+
+# open the next log file in sequence
+sub opennext
+{
+ my $self = shift;
+ if ($self->{sort} eq 'm') {
+ ($self->{year}, $self->{thing}) = Julian::addm($self->{year}, $self->{thing}, 1);
+ } elsif ($self->{sort} eq 'd') {
+ ($self->{year}, $self->{thing}) = Julian::add($self->{year}, $self->{thing}, 1);
+ }
+ return $self->open($self->{year}, $self->{thing}, @_);
+}
+
+# write (actually append) to a file, opening new files as required
+sub write
+{
+ my ($self, $year, $thing, $line) = @_;
+ $self->open($year, $thing, ">>") if (!$self->{fh} ||
+ $self->{mode} ne ">>" ||
+ $year != $self->{year} ||
+ $thing != $self->{thing})
+ or confess "can't open $self->{fn} $!";
+
+ $self->{fh}->print("$line\n");
+ return $self;
+}
+
+# write (actually append) using the current date to a file, opening new files as required
+sub writenow
+{
+ my ($self, $line) = @_;
+ my @date = unixtoj(time) if $self->{sort} = 'd';
+ @date = unixtojm(time) if $self->{sort} = 'm';
+
+ return $self->write(@date, $line);
+}
+
+# close the log file handle
+sub close
+{
+ my $self = shift;
+ undef $self->{fh}; # close the filehandle
+ delete $self->{fh};
+ delete $self->{mode};
+}
+
+sub DESTROY # catch undefs and do what is required further do the tree
+{
+ my $self = shift;
+ dbg("dxlog", "closing $self->{fn}\n");
+ undef $self->{fh} if defined $self->{fh};
+}
+1;
# take a unix date and transform it into a julian day (ie (1998, 13) = 13th day of 1998)
sub unixtoj
{
- my ($t) = @_;
- my ($day, $mon, $year) = (gmtime($t))[3..5];
- my $jday;
+ my $t = shift;
+ my ($year, $day) = (gmtime($t))[5,7];
- # set the correct no of days for february
if ($year < 100) {
$year += ($year < 50) ? 2000 : 1900;
}
- $days[1] = isleap($year) ? 29 : 28;
- for (my $i = 0, $jday = 0; $i < $mon; $i++) {
- $jday += $days[$i];
- }
- $jday += $day;
- return ($year, $jday);
+ return ($year, $day+1);
+}
+
+# take a unix and return a julian month from it
+sub unixtojm
+{
+ my $t = shift;
+ my ($mon, $year) = (gmtime($t))[4..5];
+ return ($year, $mon);
}
# take a julian date and subtract a number of days from it, returning the julian date
return ($year, $day);
}
+# take a julian month and subtract a number of months from it, returning the julian month
+sub subm
+{
+ my ($year, $mon, $amount) = @_;
+ $mon -= $amount;
+ while ($mon <= 0) {
+ $mon += 12;
+ $year -= 1;
+ }
+ return ($year, $mon);
+}
+
+sub addm
+{
+ my ($year, $mon, $amount) = @_;
+ $mon += $amount;
+ while ($mon > 12) {
+ $mon -= 12;
+ $year += 1;
+ }
+ return ($year, $mon);
+}
+
sub cmp
{
my ($y1, $d1, $y2, $d2) = @_;
return ($year % 4 == 0 && ($year % 100 != 0 || $year % 400 == 0)) ? 1 : 0;
}
-# this section deals with files that are julian date based
-
-# open a data file with prefix $fn/$year/$day.dat and return an object to it
-sub open
-{
- my ($pkg, $fn, $year, $day, $mode) = @_;
-
- # if we are writing, check that the directory exists
- if (defined $mode) {
- my $dir = "$fn/$year";
- mkdir($dir, 0777) if ! -e $dir;
- }
- my $self = {};
- $self->{fn} = sprintf "$fn/$year/%03d.dat", $day;
- $mode = 'r' if !$mode;
- my $fh = new FileHandle $self->{fn}, $mode;
- return undef if !$fh;
- $fh->autoflush(1) if $mode ne 'r'; # make it autoflushing if writable
- $self->{fh} = $fh;
- $self->{year} = $year;
- $self->{day} = $day;
- dbg("julian", "opening $self->{fn}\n");
-
- return bless $self, $pkg;
-}
-
-# close the data file
-sub close
-{
- my $self = shift;
- undef $self->{fh}; # close the filehandle
- delete $self->{fh};
-}
-
-sub DESTROY # catch undefs and do what is required further do the tree
-{
- my $self = shift;
- dbg("julian", "closing $self->{fn}\n");
- undef $self->{fh} if defined $self->{fh};
-}
1;
use DXVars;
use DXDebug;
use DXUtil;
+use DXLog;
use Julian;
use Prefix;
use Carp;
-@ISA = qw(Julian);
-
use strict;
use vars qw($fp $maxspots $defaultspots $maxdays $dirprefix);
$maxspots = 50; # maximum spots to return
$defaultspots = 10; # normal number of spots to return
$maxdays = 35; # normal maximum no of days to go back
-$dirprefix = "$main::data/spots";
+$dirprefix = "spots";
sub init
{
- mkdir "$dirprefix", 0777 if !-e "$dirprefix";
+ mkdir "$dirprefix", 0777 if !-e "$dirprefix";
+ $fp = DXLog::new($dirprefix, "dat", 'd')
}
sub prefix
{
- return $dirprefix;
+ return $fp->{prefix};
}
# add a spot to the data file (call as Spot::add)
# remove ssid if present on spotter
$spot[4] =~ s/-\d+$//o;
- # compare dates to see whether need to open another save file (remember, redefining $fp
- # automagically closes the output file (if any))
- my @date = Julian::unixtoj($spot[2]);
- $fp = Spot->open(@date, ">>") if (!$fp || Julian::cmp(@date, $fp->{year}, $fp->{day}));
-
- # save it
- my $fh = $fp->{fh};
-
# add the 'dxcc' country on the end
my @dxcc = Prefix::extract($spot[1]);
push @spot, (@dxcc > 0 ) ? $dxcc[1]->dxcc() : 0;
my $buf = join("\^", @spot);
- $fh->print($buf, "\n");
+
+ # compare dates to see whether need to open another save file (remember, redefining $fp
+ # automagically closes the output file (if any)).
+ my @date = Julian::unixtoj($spot[2]);
+ $fp->write(@date, $buf);
return $buf;
}
# build up eval to execute
$eval = qq(
-# while (<\$fh>) {
-# chomp;
-# my \@spots = split /\\^/o;
-# if ($expr) { # note NO \$expr
-# \$count++;
-# next if \$count < \$from; # wait until from
-# push(\@out, \\\@spots);
-# last LOOP if \$count >= \$to; # stop after to
-# }
-# }
my \$c;
my \$ref;
for (\$c = \$#spots; \$c >= 0; \$c--) {
}
);
+ $fp->close; # close any open files
+
LOOP:
for ($i = 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 @spots = ();
- my $fp = Spot->open(@now); # get the next file
- if ($fp) {
- my $fh = $fp->{fh};
+ my $fh = $fp->open(@now); # get the next file
+ if ($fh) {
my $in;
- foreach $in (<$fh>) {
- chomp $in;
- push @spots, [ split('\^', $in) ];
+ while (<$fh>) {
+ chomp;
+ push @spots, [ split '\^' ];
}
eval $eval; # do the search on this file
return ("Spot search error", $@) if $@;
return @out;
}
-# open a spot file of the Julian day
-sub open
-{
- my $pkg = shift;
- return Julian::open("spot", $dirprefix, @_);
-}
-
-# close a spot file
-sub close
-{
- # do nothing, unreferencing or overwriting the $self will close it
-}
-
# format a spot for user output in 'broadcast' mode
sub formatb
{