+ dbg(sprintf("RBN: spot selection for $dxchan->{call} mode: '$mode' want: $want flags rbn:%d ft:%d bcn:%d cw:%d psk:%d rtty:%d",
+ $user->wantrbn,
+ $user->wantft,
+ $user->wantbeacon,
+ $user->wantcw,
+ $user->wantpsk,
+ $user->wantrtty,
+ )) if isdbg('rbnll');
+
+ # send one spot to one user out of the ones that we have
+ $self->dx_spot($dxchan, $quality, $spot) if $want;
+ }
+}
+
+sub dx_spot
+{
+ my $self = shift;
+ my $dxchan = shift;
+ my $quality = shift;
+ my $spot = shift;
+ my $call = $dxchan->{call};
+
+
+ my $strength = 100; # because it could if we talk about FTx
+ my $saver;
+
+ my %zone;
+ my %qrg;
+ my $respot;
+ my $qra;
+
+ ++$self->{nousers}->{$call};
+ ++$self->{nousers10}->{$call};
+ ++$self->{nousershour}->{$call};
+
+ my $filtered;
+ my $rf = $dxchan->{rbnfilter} || $dxchan->{spotsfilter};
+ foreach my $r (@$spot) {
+ # $r = [$origin, $qrg, $call, $mode, $s, $t, $utz, $respot, $qra];
+ # Spot::prepare($qrg, $call, $utz, $comment, $origin);
+
+ my $comment = sprintf "%-3s %2ddB $quality", $r->[RMode], $r->[RStrength];
+ $respot = 1 if $r->[Respot];
+ $qra = $r->[RQra] if !$qra && $r->[RQra] && is_qra($r->[RQra]);
+
+ my $s = $r->[RSpotData]; # the prepared spot
+ $s->[SComment] = $comment; # apply new generated comment
+
+
+ ++$zone{$s->[SZone]}; # save the spotter's zone
+ ++$qrg{$s->[SQrg]}; # and the qrg
+
+
+ # save the lowest strength one
+ if ($r->[RStrength] < $strength) {
+ $strength = $r->[RStrength];
+ $saver = $s;
+ dbg("RBN: STRENGTH spot: $s->[SCall] qrg: $s->[SQrg] origin: $s->[SOrigin] dB: $r->[RStrength] < $strength") if isdbg 'rbnll';
+ }
+
+ if ($rf) {
+ my ($want, undef) = $rf->it($s);
+ dbg("RBN: FILTERING for $call spot: $s->[SCall] qrg: $s->[SQrg] origin: $s->[SOrigin] dB: $r->[RStrength] com: '$s->[SComment]' want: " . ($want ? 'YES':'NO')) if isdbg 'rbnll';
+ next unless $want;
+ $filtered = $s;
+# last;
+ }
+ }
+
+ if ($rf) {
+ $saver = $filtered; # if nothing passed the filter's lips then $saver == $filtered == undef !
+ }
+
+ if ($saver) {
+ my $buf;
+ # create a zone list of spotters
+ delete $zone{$saver->[SZone]}; # remove this spotter's zone (leaving all the other zones)
+ my $z = join ',', sort {$a <=> $b} keys %zone;
+
+ # determine the most likely qrg and then set it
+ my $mv = 0;
+ my $fk;
+ my $c = 0;
+ while (my ($k, $v) = each %qrg) {
+ $fk = $k, $mv = $v if $v > $mv;
+ ++$c;
+ }
+ $saver->[SQrg] = $fk;
+ $saver->[SComment] .= '*' if $c > 1;
+ $saver->[SComment] .= '+' if $respot;
+ $saver->[SComment] .= " Z:$z" if $z;
+
+ dbg("RBN: SENDING to $call spot: $saver->[SCall] qrg: $saver->[SQrg] origin: $saver->[SOrigin] $saver->[SComment]") if isdbg 'rbnll';
+ if ($dxchan->{ve7cc}) {
+ my $call = $saver->[SOrigin];
+ $saver->[SOrigin] .= '-#';
+ $buf = VE7CC::dx_spot($dxchan, @$saver);
+ $saver->[SOrigin] = $call;
+ } else {
+ my $call = $saver->[SOrigin];
+ $saver->[SOrigin] = substr($call, 0, 6);
+ $saver->[SOrigin] .= '-#';
+ $buf = $dxchan->format_dx_spot(@$saver);
+ $saver->[SOrigin] = $call;
+ }
+# $buf =~ s/^DX/RB/;
+ $dxchan->local_send('N', $buf);
+
+ ++$self->{nospot};
+ ++$self->{nospot10};
+ ++$self->{nospothour};
+
+ if ($qra) {
+ my $user = DXUser::get_current($saver->[SCall]) || DXUser->new($saver->[SCall]);
+ unless ($user->qra && is_qra($user->qra)) {
+ $user->qra($qra);
+ dbg("RBN: update qra on $saver->[SCall] to $qra");
+ $user->put;
+ }
+ }
+ }
+}