$main::build += $VERSION;
$main::branch += $BRANCH;
-use vars qw(%list %valid $filterdef);
+use vars qw(%list %valid $filterdef $default_metric);
%valid = (
call => "0,Callsign",
cq => '0,CQ Zone',
state => '0,State',
city => '0,City',
+ dxchan => '0,DXChans,parray',
+ links => '0,Node Links,parray',
);
+
$filterdef = bless ([
# tag, sort, field, priv, special parser
['channel', 'c', 0],
['by_state', 'ns', 9],
], 'Filter::Cmd');
+$default_metric = 10;
sub new
{
return $r ? 1 : 0;
}
-sub parents
-{
- my $self = shift;
- return @{$self->{parent}};
-}
-
#
# display routines
#
{
my $self = shift;
my $nodes_only = shift;
- my $level = shift;
+ my $level = shift || 0;
my $seen = shift;
my @out;
my $line;
- my $call = $self->user_call;
+ my $ucall = $self->user_call;
+ my $call = $self->{call};
my $printit = 1;
+
+ return if $level > 1 && DXChannel->get($call);
+
+# my @seen = @$seen || ();
+# return if $level > 1 && grep $call eq $_, @seen;
+# push @seen, @{$self->{links}};
+
# allow ranges
if (@_) {
}
if ($printit) {
- $line = ' ' x ($level*2) . "$call";
- $call = ' ' x length $call;
+ $line = ' ' x ($level*3) . "$ucall";
+ push @out, $line;
+# push @$seen, $call;
- # recursion detector
- if ((DXChannel->get($self->{call}) && $level > 1) || grep $self->{call} eq $_, @$seen) {
- $line .= ' ...';
- push @out, $line;
- return @out;
- }
- push @$seen, $self->{call};
-
- # print users
- unless ($nodes_only) {
- if (@{$self->{users}}) {
- $line .= '->';
- foreach my $ucall (sort @{$self->{users}}) {
- my $uref = Route::User::get($ucall);
- my $c;
- if ($uref) {
- $c = $uref->user_call;
- } else {
- $c = "$ucall?";
- }
- if ((length $line) + (length $c) + 1 < 79) {
- $line .= $c . ' ';
- } else {
- $line =~ s/\s+$//;
- push @out, $line;
- $line = ' ' x ($level*2) . "$call->$c ";
- }
+ foreach my $ncall (sort @{$self->{links}}) {
+ my $nref = Route::Node::get($ncall);
+
+ if ($nref) {
+ my $c = $nref->user_call;
+ dbg("recursing from $call -> $c (" . (join ',', @$seen) . ")") if isdbg('routec');
+
+ unless (grep $ncall eq $_, @$seen) {
+# push @seen, $call;
+ push @$seen, $ncall;
+ push @out, $nref->config($nodes_only, $level+1, $seen, @_);
+# pop @$seen;
+# pop @seen;
+ } else {
+# $line .= "->$ncall" if $line !~ $ncall;
+# push @out, $line;
}
+ } else {
+ push @out, ' ' x (($level+1)*2) . "$ncall?" if @_ == 0 || (@_ && grep $ncall =~ m|$_|, @_);
}
}
- $line =~ s/->$//g;
- $line =~ s/\s+$//;
- push @out, $line if length $line;
- }
-
- # deal with more nodes
- foreach my $ncall (sort @{$self->{nodes}}) {
- my $nref = Route::Node::get($ncall);
-
- if ($nref) {
- my $c = $nref->user_call;
-# dbg("recursing from $call -> $c") if isdbg('routec');
- push @out, $nref->config($nodes_only, $level+1, $seen, @_);
- } else {
- push @out, ' ' x (($level+1)*2) . "$ncall?" if @_ == 0 || (@_ && grep $ncall =~ m|$_|, @_);
- }
+# pop @$seen;
}
return @out;
return Route::Node::get($call) || Route::User::get($call);
}
+sub _distance
+{
+ my $self = shift;
+ my $ah = shift;
+ my $call = $self->{call};
+
+ if (DXChannel->get($call)) {
+ my $n = scalar @_ || 0;
+ my $o = $ah->{$call} || 9999;
+ $ah->{$call} = $n if $n < $o;
+ dbg("_distance hit: $call = $n") if isdbg('routech');
+ return;
+ }
+
+ dbg("_distance miss $call: " . join(',', @_)) if isdbg('routech');
+
+ foreach my $c (@{$self->{links}}) {
+ next if $c eq $call || $c eq $main::mycall;
+ next if grep $c eq $_, @_;
+
+ my $n = get($c);
+ _distance($n, $ah, @_, $c);
+ }
+ return;
+}
+
+sub _ordered_routes
+{
+ my $self = shift;
+ my @routes;
+
+ if (exists $self->{dxchan}) {
+ dbg("stored routes for $self->{call}: " . join(',', @{$self->{dxchan}})) if isdbg('routech');
+ return @{$self->{dxchan}} if exists $self->{dxchan};
+ }
+
+ my %ah;
+ _distance($self, \%ah);
+
+ @routes = sort {$ah{$a} <=> $ah{$b}} keys %ah;
+ $self->{dxchan} = \@routes;
+ dbg("new routes for $self->{call}: " . join(',', @routes)) if isdbg('routech');
+ return @routes;
+}
+
# find all the possible dxchannels which this object might be on
sub alldxchan
{
my $self = shift;
my @dxchan;
-# dbg("Trying node $self->{call}") if isdbg('routech');
my $dxchan = DXChannel->get($self->{call});
push @dxchan, $dxchan if $dxchan;
-
- # it isn't, build up a list of dxchannels and possible ping times
- # for all the candidates.
- unless (@dxchan) {
- foreach my $p (@{$self->{parent}}) {
-# dbg("Trying parent $p") if isdbg('routech');
- next if $p eq $main::mycall; # the root
- my $dxchan = DXChannel->get($p);
- if ($dxchan) {
- push @dxchan, $dxchan unless grep $dxchan == $_, @dxchan;
- } else {
- next if grep $p eq $_, @_;
- my $ref = Route::Node::get($p);
-# dbg("Next node $p " . ($ref ? 'Found' : 'NOT Found') if isdbg('routech') );
- push @dxchan, $ref->alldxchan($self->{call}, @_) if $ref;
- }
- }
- }
-# dbg('routech', "Got dxchan: " . join(',', (map{ $_->call } @dxchan)) );
+
+ @dxchan = map {DXChannel->get($_)} _ordered_routes($self) unless @dxchan;
return @dxchan;
}
return $dxchan;
}
+sub _addlink
+{
+ my $self = shift;
+ delete $self->{dxchan};
+ return $self->_addlist('links', @_);
+}
+sub _dellink
+{
+ my $self = shift;
+ delete $self->{dxchan};
+ return $self->_dellist('links', @_);
+}
+
+sub haslink
+{
+ my $self = shift;
+ my $other = shift->{call};
+ return grep $other eq $_, @{$self->{links}};
+}
#
# track destruction