#!/usr/local/bin/perl ############################################################################### ############################################################################### ## ## ## cabrillo_vhf_rescore.pl Kenneth E. Harker WM5R ## ## wm5r@arrl.net ## ## 11 March 2004 ## ## A tool to rescore Cabrillo log files under ## ## different scoring formulas for VHF contests. ## ## ## ############################################################################### ############################################################################### $SEEN_START_OF_LOG = 0; $VERBOSE = 1; $DELIM = ","; $callsign = ""; $contest = ""; $arrl_section = ""; $category = ""; $claimed_score = ""; $operators = ""; $year = ""; $QSOs = ""; $current_qso_points = 0; $current_qso_mults = 0; $current_oldrover_qso_points = 0; $current_oldrover_qso_mults = 0; $current_oldrover_1ptrover_qso_points = 0; $current_oldrover_1ptrover_qso_mults = 0; $distance1_qso_points = 0; $distance1_qso_mults = 0; $distance1_oldrover_qso_points = 0; $distance1_oldrover_qso_mults = 0; $distance1_oldrover_1ptrover_qso_points = 0; $distance1_oldrover_1ptrover_qso_mults = 0; $current_lowbandsonly_qso_points = 0; $current_lowbandsonly_qso_mults = 0; $qsos1pt_lowbandsonly_qso_points = 0; $qsos1pt_lowbandsonly_qso_mults = 0; $multipliersCurrent = ""; $multipliersCurrentOldRover = ""; $multipliersCurrentOldRover1ptRoverQSOs = ""; $multipliersDistance1 = ""; $multipliersDistance1OldRover = ""; $multipliersDistance1OldRover1ptRoverQSOs = ""; $multipliersCurrentLowBandsOnly = ""; $multipliers1ptQSOsLowBandsOnly = ""; $visited_grids = ""; $visited_mult = 0; ## Used for determining adjacent grid locators $letter_up{"a"} = "b"; $letter_up{"b"} = "c"; $letter_up{"c"} = "d"; $letter_up{"d"} = "e"; $letter_up{"e"} = "f"; $letter_up{"f"} = "g"; $letter_up{"g"} = "h"; $letter_up{"h"} = "i"; $letter_up{"i"} = "j"; $letter_up{"j"} = "k"; $letter_up{"k"} = "l"; $letter_up{"l"} = "m"; $letter_up{"m"} = "n"; $letter_up{"n"} = "o"; $letter_up{"o"} = "p"; $letter_up{"p"} = "q"; $letter_up{"q"} = "r"; $letter_up{"r"} = "a"; $letter_down{"a"} = "r"; $letter_down{"b"} = "a"; $letter_down{"c"} = "b"; $letter_down{"d"} = "c"; $letter_down{"e"} = "d"; $letter_down{"f"} = "e"; $letter_down{"g"} = "f"; $letter_down{"h"} = "g"; $letter_down{"i"} = "h"; $letter_down{"j"} = "i"; $letter_down{"k"} = "j"; $letter_down{"l"} = "k"; $letter_down{"m"} = "l"; $letter_down{"n"} = "m"; $letter_down{"o"} = "n"; $letter_down{"p"} = "o"; $letter_down{"q"} = "p"; $letter_down{"r"} = "q"; ############################################################################### ############################################################################### ## ## ## Process Command Line Parameters ## ## ## ############################################################################### ############################################################################### ## If the first parameter asks for help, print usage. while ($param = shift) { if (($param eq "-v") || ($param eq "-verbose") || ($param eq "--verbose")) { $VERBOSE = 1; } elsif (($param eq "-q") || ($param eq "-quiet") || ($param eq "--quiet")) { $VERBOSE = 0; } elsif (($param eq "-c") || ($param eq "-comma") || ($param eq "--comma")) { $DELIM = ","; } elsif (($param eq "-s") || ($param eq "-space") || ($param eq "--space")) { $DELIM = " "; } elsif (($param eq "-h") || ($param eq "-help") || ($param eq "--help")) { usage(); } } ############################################################################### ############################################################################### ## ## ## Main Processing Loop ## ## ## ############################################################################### ############################################################################### while () { chomp; $line = $_; if ($line eq "") { next; } ## Ignore irrelevant log lines if (($line =~ /^CREATED-BY\:/) || ($line =~ /^NAME\:/) || ($line =~ /^ADDRESS\:/) || ($line =~ /^SOAPBOX\:/) || ($line =~ /^CLUB\:/)) { next; } ## Check for START-OF-LOG if ($SEEN_START_OF_LOG eq 0) { if ($line =~ /^START-OF-LOG\:/) { $SEEN_START_OF_LOG = 1; } else { print STDERR "No START-OF-LOG: tag.\n"; exit(1); } } ## Check for END-OF-LOG if ($line =~ /^END-OF-LOG\:/) { ## Generate labels for line scores $out_callsign = uc($orig_callsign); if ($category eq "SINGLE-OP-LOW") { $out_category = "SOLP"; } if ($category eq "SINGLE-OP-HIGH") { $out_category = "SOHP"; } if ($category eq "SINGLE-OP-PORTABLE") { $out_category = "SO/P"; } if ($category eq "ROVER") { $out_category = "R"; } if ($category eq "MULTI-LIMITED") { $out_category = "M/L"; } if ($category eq "MULTI-UNLIMITED") { $out_category = "M/U"; } if ($category eq "CHECKLOG") { $out_category = "CHK"; } if ($year eq "") { $year = "0000"; } if ($contest eq "ARRL-UHF-AUG") { $out_contest = $year . "-" ."Aug"; } if ($contest eq "ARRL-VHF-JAN") { $out_contest = $year . "-" ."Jan"; } if ($contest eq "ARRL-VHF-JUN") { $out_contest = $year . "-" ."Jun"; } if ($contest eq "ARRL-VHF-SEP") { $out_contest = $year . "-" ."Sep"; } $out_arrl_section = uc($arrl_section); ## Current score if ($category eq "ROVER") { $current_qso_mults = $current_qso_mults + $visited_mult; } $current_score = $current_qso_points * $current_qso_mults; ## Current+OldRover score $current_oldrover_score = $current_oldrover_qso_points * $current_oldrover_qso_mults; ## Current+OldRover+1ptRoverQSOs score $current_oldrover_1ptrover_score = $current_oldrover_1ptrover_qso_points * $current_oldrover_1ptrover_qso_mults; ## Distance1 score if ($category eq "ROVER") { $distance1_qso_mults = $distance1_qso_mults + $visited_mult; } $distance1_score = $distance1_qso_points * $distance1_qso_mults; ## Distance1+OldRover score $distance1_oldrover_score = $distance1_oldrover_qso_points * $distance1_oldrover_qso_mults; ## Distance1+OldRover+1ptRoverQSOs score $distance1_oldrover_1ptrover_score = $distance1_oldrover_1ptrover_qso_points * $distance1_oldrover_1ptrover_qso_mults; ## Current+LowBandsOnly score if ($category eq "ROVER") { $current_lowbandsonly_qso_mults = $current_lowbandsonly_qso_mults + $visited_mult; } $current_lowbandsonly_score = $current_lowbandsonly_qso_points * $current_lowbandsonly_qso_mults; ## 1ptQSOs+LowBandsOnly score if ($category eq "ROVER") { $qsos1pt_lowbandsonly_qso_mults = $qsos1pt_lowbandsonly_qso_mults + $visited_mult; } $qsos1pt_lowbandsonly_score = $qsos1pt_lowbandsonly_qso_points * $qsos1pt_lowbandsonly_qso_mults; ## Output line score if ($VERBOSE eq 1) { print "$out_contest"; print "$DELIM"; print "$out_callsign"; print "$DELIM"; print "$out_category"; print "$DELIM"; print "$out_arrl_section"; print "$DELIM"; print "$current_score"; print "$DELIM"; print "$current_oldrover_score"; print "$DELIM"; print "$current_oldrover_1ptrover_score"; print "$DELIM"; print "$distance1_score"; print "$DELIM"; print "$distance1_oldrover_score"; print "$DELIM"; print "$distance1_oldrover_1ptrover_score"; print "$DELIM"; print "$current_lowbandsonly_score"; print "$DELIM"; print "$qsos1pt_lowbandsonly_score\n"; } else { print "$out_callsign"; print "$DELIM"; print "$current_score"; print "$DELIM"; print "$current_oldrover_score"; print "$DELIM"; print "$current_oldrover_1ptrover_score"; print "$DELIM"; print "$distance1_score"; print "$DELIM"; print "$distance1_oldrover_score"; print "$DELIM"; print "$distance1_oldrover_1ptrover_score"; print "$DELIM"; print "$current_lowbandsonly_score"; print "$DELIM"; print "$qsos1pt_lowbandsonly_score\n"; } ## Prepare for next log $SEEN_START_OF_LOG = 0; $callsign = ""; $contest = ""; $arrl_section = ""; $category = ""; $claimed_score = ""; $operators = ""; $year = ""; foreach $k (keys(QSOs)) { $QSOs{$k} = 0; } foreach $k (keys(multipliersCurrent)) { $multipliersCurrent{$k} = 0; } foreach $k (keys(multipliersCurrentOldRover)) { $multipliersCurrentOldRover{$k} = 0; } foreach $k (keys(multipliersCurrentOldRover1ptRoverQSOs)) { $multipliersCurrentOldRover1ptRoverQSOs{$k} = 0; } foreach $k (keys(multipliersDistance1)) { $multipliersDistance1{$k} = 0; } foreach $k (keys(multipliersDistance1OldRover)) { $multipliersDistance1OldRover{$k} = 0; } foreach $k (keys(multipliersDistance1OldRover1ptRoverQSOs)) { $multipliersDistance1OldRover1ptRoverQSOs{$k} = 0; } foreach $k (keys(multipliersCurrentLowBandsOnly)) { $multipliersCurrentLowBandsOnly{$k} = 0; } foreach $k (keys(multipliers1ptQSOsLowBandsOnly)) { $multipliers1ptQSOsLowBandsOnly{$k} = 0; } foreach $k (keys(visited_grids)) { $visited_grids{$k} = 0; } $current_qso_points = 0; $current_qso_mults = 0; $current_oldrover_qso_points = 0; $current_oldrover_qso_mults = 0; $current_oldrover_1ptrover_qso_points = 0; $current_oldrover_1ptrover_qso_mults = 0; $distance1_qso_points = 0; $distance1_qso_mults = 0; $distance1_oldrover_qso_points = 0; $distance1_oldrover_qso_mults = 0; $distance1_oldrover_1ptrover_qso_points = 0; $distance1_oldrover_1ptrover_qso_mults = 0; $current_lowbandsonly_qso_points = 0; $current_lowbandsonly_qso_mults = 0; $qsos1pt_lowbandsonly_qso_points = 0; $qsos1pt_lowbandsonly_qso_mults = 0; $visited_mult = 0; ## Identify common EOL problem at end of log files when ## multiple logs are on STDIN. if ($line =~ /^END-OF-LOG\:.*START-OF-LOG\:/) { $SEEN_START_OF_LOG = 1; } } ## Record basic information if ($line =~ /^CALLSIGN\:\s+([\w\d\/]*)/) { $callsign = uc($1); if ($callsign =~ /(.*)\/R$/) { $callsign = $1; } if ($callsign =~ /(.*)\/ROVER$/) { $callsign = $1; } if ($callsign =~ /(.*)\/MM$/) { $callsign = $1; } if ($callsign =~ /(.*)\/P$/) { $callsign = $1; } if ($callsign =~ /(.*)\/\d$/) { $callsign = $1; } if ($callsign =~ /(.*)\/W\d$/) { $callsign = $1; } if ($callsign =~ /(.*)\/K\d$/) { $callsign = $1; } if ($callsign =~ /(.*)\/N\d$/) { $callsign = $1; } if ($callsign =~ /(.*)\/\w\w\d\d$/) { $callsign = $1; } $orig_callsign = $callsign; next; } if ($line =~ /^CONTEST\:\s+([\w\d\-]*)/) { $contest = $1; next; } if ($line =~ /^ARRL-SECTION\:\s+([\w]*)/) { $arrl_section = $1; next; } if ($line =~ /^CATEGORY\:\s+([\w\d\-]*)/) { $category = uc($1); unless (($category eq "SINGLE-OP") || ($category eq "SINGLE-OP-PORTABLE") || ($category eq "ROVER") || ($category eq "MULTI-LIMITED") || ($category eq "MULTI-UNLIMITED") || ($category eq "CHECKLOG")) { print STDERR "Invalid entry category: $category\n"; } if ($line =~ /^CATEGORY\:\s+SINGLE-OP\s+.*\s+(\w+)/) { $power = uc($1); $category = $category . "-" . $power; } next; } if ($line =~ /^CLAIMED-SCORE\:\s+(.*)/) { $claimed_score = $1; next; } if ($line =~ /^OPERATORS\:\s+(.*)/) { $operators = $1; next; } $callsign = lc($callsign); if ($callsign =~ /(.*)\/([^\/]*)$/) { $callsign = $1; } ## Process QSO Lines if ($line =~ /^QSO\:\s+(.*)/) { ## Check for missing year and dupes $qso_data = $1; if ($year eq "") { $year = get_year($qso_data); } if (dupe_check($qso_data) eq 1) { next; } ## Current $current_qso_points += score_qso("Current " . $qso_data); $current_qso_mults += mults_qso("Current " . $qso_data); ## Current+OldRoverRules $current_oldrover_qso_points += score_qso("CurrentOldRoverRules " . $qso_data); $current_oldrover_qso_mults += mults_qso("CurrentOldRoverRules " . $qso_data); ## Current+OldRoverRules+1ptRover $current_oldrover_1ptrover_qso_points += score_qso("CurrentOldRoverRules1ptRoverQSOs " . $qso_data); $current_oldrover_1ptrover_qso_mults += mults_qso("CurrentOldRoverRules1ptRoverQSOs " . $qso_data); ## Distance1 $distance1_qso_points += score_qso("Distance1 " . $qso_data); $distance1_qso_mults += mults_qso("Distance1 " . $qso_data); ## Distance1+OldRoverRules $distance1_oldrover_qso_points += score_qso("Distance1OldRoverRules " . $qso_data); $distance1_oldrover_qso_mults += mults_qso("Distance1OldRoverRules " . $qso_data); ## Distance1+OldRoverRules+1ptRover $distance1_oldrover_1ptrover_qso_points += score_qso("Distance1OldRoverRules1ptRoverQSOs " . $qso_data); $distance1_oldrover_1ptrover_qso_mults += mults_qso("Distance1OldRoverRules1ptRoverQSOs " . $qso_data); ## Current+LowBandsOnly $current_lowbandsonly_qso_points += score_qso("CurrentLowBandsOnly " . $qso_data); $current_lowbandsonly_qso_mults += mults_qso("CurrentLowBandsOnly " . $qso_data); ## 1ptQSOs+LowBandsOnly $qsos1pt_lowbandsonly_qso_points += score_qso("1ptQSOsLowBandsOnly " . $qso_data); $qsos1pt_lowbandsonly_qso_mults += mults_qso("1ptQSOsLowBandsOnly " . $qso_data); } } exit(0); ############################################################################### ############################################################################### ## ## ## get_year ## ## ## ## Extracts the year from the date field of a QSO data line ## ## ## ## Input: QSO data line ## ## ## ## Output: four-digit year ## ## ## ## Error: none. ## ## ## ############################################################################### ############################################################################### sub get_year { ## Extract data components and lowercase my ($qso_data) = @_; ($band, $mode, $date, $time, $mycall, $mygrid, $call, $grid) = split(" ",$qso_data); ($year,$month,$day) = split("-",$date); if ($year ne "") { return $year; } else { return 0; } } ############################################################################### ############################################################################### ## ## ## dupe_check ## ## ## ## Checks a QSO to see if it is a duplicate ## ## ## ## Input: QSO data line ## ## ## ## Output: 0 for non-dupe, 1 for dupe ## ## ## ## Error: none. ## ## ## ############################################################################### ############################################################################### sub dupe_check { ## Extract data components and lowercase my ($qso_data) = @_; ($band, $mode, $date, $time, $mycall, $mygrid, $call, $grid) = split(" ",$qso_data); $band = lc($band); $mode = lc($mode); $mycall = lc($mycall); $mygrid = lc($mygrid); $call = lc($call); ## Handle potential wierdness at end of line $grid = lc($grid); if ($grid =~ /(\w\w\d\d)/) { $grid = $1; } ## Massage and check callsigns if ($mycall =~ /(.*)\/r$/) { $mycall = $1; } if ($mycall =~ /(.*)\/rover$/) { $mycall = $1; } if ($mycall =~ /(.*)\/mm$/) { $mycall = $1; } if ($mycall =~ /(.*)\/p$/) { $mycall = $1; } if ($mycall =~ /(.*)\/\d$/) { $mycall = $1; } if ($mycall =~ /(.*)\/w\d$/) { $mycall = $1; } if ($mycall =~ /(.*)\/k\d$/) { $mycall = $1; } if ($mycall =~ /(.*)\/n\d$/) { $mycall = $1; } if ($mycall =~ /(.*)\/\w\w\d\d$/) { $mycall = $1; } if ($call =~ /(.*)\/r$/) { $call = $1; } if ($call =~ /(.*)\/rover$/) { $call = $1; } if ($call =~ /(.*)\/mm$/) { $call = $1; } if ($call =~ /(.*)\/p$/) { $call = $1; } if ($call =~ /(.*)\/\d$/) { $call = $1; } if ($call =~ /(.*)\/w\d$/) { $call = $1; } if ($call =~ /(.*)\/k\d$/) { $call = $1; } if ($call =~ /(.*)\/n\d$/) { $call = $1; } if ($call =~ /(.*)\/\w\w\d\d$/) { $call = $1; } ## Compute a unique label for the QSO and check against DB $current = $call . "_" . $grid . "_" . $band . "_" . $mygrid; if ($QSOs{$current} eq 1) { return 1; } else { $QSOs{$current} = 1; return 0; } return 0; } ############################################################################### ############################################################################### ## ## ## score_qso ## ## ## ## Computes the QSO points for a QSO ## ## ## ## Input: QSO data line ## ## ## ## Output: points to assign for the QSO ## ## ## ## Error: none. ## ## ## ############################################################################### ############################################################################### sub score_qso { ## Extract data components and lowercase my ($qso_data) = @_; ($formula, $band, $mode, $date, $time, $mycall, $mygrid, $call, $grid) = split(" ",$qso_data); ## Normalize the band indication $band = lc($band); $band = normalize_band($band); if ($band eq 0) { return 0; } ## Lowercase everything $mode = lc($mode); $mycall = lc($mycall); $mygrid = lc($mygrid); $call = lc($call); $grid = lc($grid); ## Handle potential wierdness $grid = lc($grid); if ($grid =~ /(\w\w\d\d)/) { $grid = $1; } if ($call =~ /(.*)\/\w\w\d\d$/) { $call = $1 . "/r"; } if ($call =~ /(.*)\/\d$/) { $call = $1; } if ($call =~ /(.*)\/w\d$/) { $call = $1; } if ($call =~ /(.*)\/k\d$/) { $call = $1; } if ($call =~ /(.*)\/n\d$/) { $call = $1; } if ($call =~ /(.*)\/mm$/) { $call = $1; } if ($call =~ /(.*)\/m$/) { $call = $1 . "/r"; } ## 1ptRoverQSOs formula if (($formula eq "CurrentOldRoverRules1ptRoverQSOs") || ($formula eq "Distance1OldRoverRules1ptRoverQSOs")) { if (($call =~ /.+\/r/) || ($call =~ /.+\/rover/)) { return 1; } } ## Current QSO point scoring formulas if (($formula eq "Current") || ($formula eq "CurrentOldRoverRules") || ($formula eq "CurrentOldRoverRules1ptRoverQSOs")) { if (($contest eq "ARRL-VHF-JUN") || ($contest eq "ARRL-VHF-SEP")) { if (($band eq "50") || ($band eq "144")) { return 1; } elsif (($band eq "222") || ($band eq "432")) { return 2; } elsif (($band eq "902") || ($band eq "1.2")) { return 3; } elsif (($band eq "2.3") || ($band eq "3.4") || ($band eq "5.7") || ($band eq "10") || ($band eq "24") || ($band eq "47") || ($band eq "75") || ($band eq "119") || ($band eq "142") || ($band eq "241") || ($band eq "300") || ($band eq "light")) { return 4; } else { return 0; } } elsif ($contest eq "ARRL-VHF-JAN") { if (($band eq "50") || ($band eq "144")) { return 1; } elsif (($band eq "222") || ($band eq "432")) { return 2; } elsif (($band eq "902") || ($band eq "1.2")) { return 4; } elsif (($band eq "2.3") || ($band eq "3.4") || ($band eq "5.7") || ($band eq "10") || ($band eq "24") || ($band eq "47") || ($band eq "75") || ($band eq "119") || ($band eq "142") || ($band eq "241") || ($band eq "300") || ($band eq "light")) { return 8; } else { return 0; } } } ## Distance-based QSO point scoring formulas if (($formula eq "Distance1") || ($formula eq "Distance1OldRoverRules") || ($formula eq "Distance1OldRoverRules1ptRoverQSOs")) { if (is_grid_adjacent($mygrid . " " . $grid) eq 1) { return 2; } else { return 3; } } ## Current QSO point scoring formulas if ($formula eq "CurrentLowBandsOnly") { if (($contest eq "ARRL-VHF-JUN") || ($contest eq "ARRL-VHF-SEP")) { if (($band eq "50") || ($band eq "144")) { return 1; } elsif (($band eq "222") || ($band eq "432")) { return 2; } elsif (($band eq "902") || ($band eq "1.2")) { return 4; } else { return 0; } } elsif ($contest eq "ARRL-VHF-JAN") { if (($band eq "50") || ($band eq "144")) { return 1; } elsif (($band eq "222") || ($band eq "432")) { return 2; } elsif (($band eq "902") || ($band eq "1.2")) { return 3; } else { return 0; } } } ## Current QSO point scoring formulas if ($formula eq "1ptQSOsLowBandsOnly") { if (($band eq "50") || ($band eq "144") || ($band eq "222") || ($band eq "432") || ($band eq "902") || ($band eq "1.2")) { return 1; } else { return 0; } } return 0; } ############################################################################### ############################################################################### ## ## ## mults_qso ## ## ## ## Computes the multipliers associated with a QSO ## ## ## ## Input: QSO data line ## ## ## ## Output: 1, if a new multiplier, 0 otherwise ## ## ## ## Error: none. ## ## ## ############################################################################### ############################################################################### sub mults_qso { ## Extract data components and lowercase my ($qso_data) = @_; ($formula, $band, $mode, $date, $time, $mycall, $mygrid, $call, $grid) = split(" ",$qso_data); $band = lc($band); $band = normalize_band($band); if ($band eq 0) { return 0; } $mode = lc($mode); $mycall = lc($mycall); $mygrid = lc($mygrid); $call = lc($call); $grid = lc($grid); ## Handle potential wierdness $grid = lc($grid); if ($grid =~ /(\w\w\d\d)/) { $grid = $1; } if ($call =~ /(.*)\/\w\w\d\d$/) { $call = $1 . "/r"; } if ($call =~ /(.*)\/\d$/) { $call = $1; } if ($call =~ /(.*)\/w\d$/) { $call = $1; } if ($call =~ /(.*)\/k\d$/) { $call = $1; } if ($call =~ /(.*)\/n\d$/) { $call = $1; } if ($call =~ /(.*)\/mm$/) { $call = $1; } if ($call =~ /(.*)\/m$/) { $call = $1 . "/r"; } ## Current scoring formula if ($formula eq "Current") { ## For rovers only if ($category eq "ROVER") { if ($visited_grids{$mygrid} ne 1) { $visited_grids{$mygrid} = 1; $visited_mult++; } } ## Each worked grid, per band, is a mult $grid_band = $grid . "_" . $band; if ($multipliersCurrent{$grid_band} eq 1) { return 0; } else { $multipliersCurrent{$grid_band} = 1; return 1; } } ## Current+OldROverRules scoring formula if ($formula eq "CurrentOldRoverRules") { ## Each worked grid per band per band-activated, is a mult $grid_band = $mygrid . "_" . $grid . "_" . $band; if ($multipliersCurrentOldRover{$grid_band} eq 1) { return 0; } else { $multipliersCurrentOldRover{$grid_band} = 1; return 1; } } ## Current+OldRoverRules+1ptRoverQSOs scoring formula if ($formula eq "CurrentOldRoverRules1ptRoverQSOs") { ## Each worked grid per band per band-activated, is a mult $grid_band = $mygrid . "_" . $grid . "_" . $band; if ($multipliersCurrentOldRover1ptRoverQSOs{$grid_band} eq 1) { return 0; } else { $multipliersCurrentOldRover1ptRoverQSOs{$grid_band} = 1; return 1; } } ## Distance1 scoring formula if ($formula eq "Distance1") { ## For rovers only if ($category eq "ROVER") { if ($visited_grids{$mygrid} ne 1) { $visited_grids{$mygrid} = 1; $visited_mult++; } } ## Each worked grid, per band, is a mult $grid_band = $grid . "_" . $band; if ($multipliersDistance1{$grid_band} eq 1) { return 0; } else { $multipliersDistance1{$grid_band} = 1; return 1; } } ## Distance1+OldROverRules scoring formula if ($formula eq "Distance1OldRoverRules") { ## Each worked grid per band per band-activated, is a mult $grid_band = $mygrid . "_" . $grid . "_" . $band; if ($multipliersDistance1OldRover{$grid_band} eq 1) { return 0; } else { $multipliersDistance1OldRover{$grid_band} = 1; return 1; } } ## Distance1+OldROverRules+1ptRoverQSOs scoring formula if ($formula eq "Distance1OldRoverRules1ptRoverQSOs") { ## Each worked grid per band per band-activated, is a mult $grid_band = $mygrid . "_" . $grid . "_" . $band; if ($multipliersDistance1OldRover1ptRoverQSOs{$grid_band} eq 1) { return 0; } else { $multipliersDistance1OldRover1ptRoverQSOs{$grid_band} = 1; return 1; } } ## Current scoring formula if ($formula eq "CurrentLowBandsOnly") { if (($band eq "50") || ($band eq "144") || ($band eq "222") || ($band eq "432") || ($band eq "902") || ($band eq "1.2")) { ## For rovers only if ($category eq "ROVER") { if ($visited_grids{$mygrid} ne 1) { $visited_grids{$mygrid} = 1; $visited_mult++; } } ## Each worked grid, per band, is a mult $grid_band = $grid . "_" . $band; if ($multipliersCurrentLowBandsOnly{$grid_band} eq 1) { return 0; } else { $multipliersCurrentLowBandsOnly{$grid_band} = 1; return 1; } } else { return 0; } } ## Current scoring formula if ($formula eq "1ptQSOsLowBandsOnly") { if (($band eq "50") || ($band eq "144") || ($band eq "222") || ($band eq "432") || ($band eq "902") || ($band eq "1.2")) { ## For rovers only if ($category eq "ROVER") { if ($visited_grids{$mygrid} ne 1) { $visited_grids{$mygrid} = 1; $visited_mult++; } } ## Each worked grid, per band, is a mult $grid_band = $grid . "_" . $band; if ($multipliers1ptQSOsLowBandsOnly{$grid_band} eq 1) { return 0; } else { $multipliers1ptQSOsLowBandsOnly{$grid_band} = 1; return 1; } } else { return 0; } } } ############################################################################### ############################################################################### ## ## ## normalize_band ## ## ## ## Takes in a string meant to represent a VHF/UHF band and outputs a ## ## correct band designator. ## ## ## ## Input: string ## ## ## ## Output: string ## ## ## ## Error: returns a 0 if the band input is not recognized ## ## ## ############################################################################### ############################################################################### sub normalize_band { ## Extract band data my ($band) = @_; $band = lc($band); if ($band =~ /^(50)\..*/) { return "50" } elsif ($band =~ /^50\d\d\d/) { return "50" } elsif ($band =~ /^50\..*/) { return "50" } elsif ($band eq "50") { return "50" } elsif ($band eq "a") { return "50" } elsif ($band =~ /^144\d\d\d/) { return "144" } elsif ($band =~ /^144\d\d/) { return "144" } elsif ($band =~ /^144\..*/) { return "144" } elsif ($band =~ /^145\d\d\d/) { return "144" } elsif ($band =~ /^145\..*/) { return "144" } elsif ($band =~ /^146\d\d\d/) { return "144" } elsif ($band =~ /^146\..*/) { return "144" } elsif ($band =~ /^147\d\d\d/) { return "144" } elsif ($band =~ /^147\..*/) { return "144" } elsif ($band eq "144") { return "144" } elsif ($band eq "145") { return "144" } elsif ($band eq "146") { return "144" } elsif ($band eq "147") { return "144" } elsif ($band eq "b") { return "144" } elsif ($band =~ /^222\d\d\d/) { return "222" } elsif ($band =~ /^222\..*/) { return "222" } elsif ($band =~ /^223\d\d\d/) { return "222" } elsif ($band =~ /^223\..*/) { return "222" } elsif ($band eq "220") { return "222" } elsif ($band eq "221") { return "222" } elsif ($band eq "222") { return "222" } elsif ($band eq "223") { return "222" } elsif ($band eq "224") { return "222" } elsif ($band eq "c") { return "222" } elsif ($band =~ /^432\d\d\d/) { return "432" } elsif ($band =~ /^432\..*/) { return "432" } elsif ($band eq "440") { return "432" } elsif ($band eq "446") { return "432" } elsif ($band eq "432") { return "432" } elsif ($band eq "d") { return "432" } elsif ($band eq "902") { return "902" } elsif ($band eq "903") { return "902" } elsif ($band eq "9") { return "902" } elsif ($band eq "1.2") { return "1.2" } elsif ($band eq "1200") { return "1.2" } elsif ($band eq "1294") { return "1.2" } elsif ($band eq "1296") { return "1.2" } elsif ($band eq "e") { return "1.2" } elsif ($band eq "2.3") { return "2.3" } elsif ($band eq "f") { return "2.3" } elsif ($band eq "3.4") { return "3.4" } elsif ($band eq "3.5") { return "3.4" } elsif ($band eq "g") { return "3.4" } elsif ($band eq "5.7") { return "5.7" } elsif ($band eq "h") { return "5.7" } elsif ($band eq "10") { return "10" } elsif ($band eq "10g") { return "10" } elsif ($band eq "i") { return "10" } elsif ($band eq "24") { return "24" } elsif ($band eq "24g") { return "24" } elsif ($band eq "j") { return "24" } elsif ($band eq "47") { return "47" } elsif ($band eq "47g") { return "47" } elsif ($band eq "k") { return "47" } elsif ($band eq "75") { return "75" } elsif ($band eq "75g") { return "75" } elsif ($band eq "76g") { return "75" } elsif ($band eq "l") { return "75" } elsif ($band eq "119") { return "119" } elsif ($band eq "m") { return "119" } elsif ($band eq "142") { return "142" } elsif ($band eq "n") { return "142" } elsif ($band eq "241") { return "241" } elsif ($band eq "o") { return "241" } elsif ($band eq "300") { return "300" } elsif ($band eq "p") { return "300" } elsif ($band eq "light") { return "light" } elsif ($band eq "laser") { return "light" } elsif ($band eq "lht") { return "light" } elsif ($band eq "ph") { return 0 } elsif ($band eq "cw") { return 0 } elsif ($band eq "ry") { return 0 } else { printf STDERR "Band designation $band unrecognized in log $callsign\n"; return 0; } } ############################################################################### ############################################################################### ## ## ## is_grid_adjacent ## ## ## ## Compares two four-digit grid locators and determines if they are ## ## adjacent to one another. ## ## ## ## Input: Two grid locators ## ## ## ## Output: 1 if adjacent, 0 otherwise ## ## ## ## Error: none. ## ## ## ############################################################################### ############################################################################### sub is_grid_adjacent { ## Extract data components and lowercase my ($two_grids) = @_; ($grid1, $grid2) = split(" ",$two_grids); ## If grid1 equals grid2, they are adjacent if ($grid1 eq $grid2) { return 1; } ## Check for poles if ((grid_north($grid1) eq "NPOL") && (grid_north($grid2) eq "NPOL")) { return 1; } if ((grid_south($grid1) eq "SPOL") && (grid_south($grid2) eq "SPOL")) { return 1; } ## Test adjacent grids if (grid_north($grid1) eq $grid2) { return 1; } if (grid_north(grid_east($grid1)) eq $grid2) { return 1; } if (grid_east($grid1) eq $grid2) { return 1; } if (grid_south(grid_east($grid1)) eq $grid2) { return 1; } if (grid_south($grid1) eq $grid2) { return 1; } if (grid_south(grid_west($grid1)) eq $grid2) { return 1; } if (grid_west($grid1) eq $grid2) { return 1; } if (grid_north(grid_west($grid1)) eq $grid2) { return 1; } ## If we haven't returned yet, grid1 and grid2 are not adjacent return 0; } ############################################################################### ############################################################################### ## ## ## grid_north ## ## ## ## Compute the grid locator to the north of the grid locator sent as ## ## the parameter value. ## ## ## ## Input: grid locator ## ## ## ## Output: grid locator ## ## ## ## Error: none. ## ## ## ############################################################################### ############################################################################### sub grid_north { ## Extract data components and lowercase my ($current_grid) = @_; $current_grid = lc($current_grid); ## Break down to components. if ($current_grid =~ /(\w)(\w)(\d)(\d)/) { $l1 = $1; $l2 = $2; $n1 = $3; $n2 = $4; } ## Check for north pole if (($l2 eq "r") && ($n2 eq 9)) { return "NPOL"; } ## Compute north grid if ($n2 eq 9) { $n2 = 0; $l2 = $letter_up{$l2}; } else { $n2++; } ## Output result $north_grid = $l1 . $l2 . $n1 . $n2; return $north_grid; } ############################################################################### ############################################################################### ## ## ## grid_south ## ## ## ## Compute the grid locator to the south of the grid locator sent as ## ## the parameter value. ## ## ## ## Input: grid locator ## ## ## ## Output: grid locator ## ## ## ## Error: none. ## ## ## ############################################################################### ############################################################################### sub grid_south { ## Extract data components and lowercase my ($current_grid) = @_; $current_grid = lc($current_grid); ## Break down to components. if ($current_grid =~ /(\w)(\w)(\d)(\d)/) { $l1 = $1; $l2 = $2; $n1 = $3; $n2 = $4; } ## Check for south pole if (($l2 eq "a") && ($n2 eq 0)) { return "SPOL"; } ## Compute south grid if ($n2 eq 0) { $n2 = 9; $l2 = $letter_down{$l2}; } else { $n2--; } ## Output result $south_grid = $l1 . $l2 . $n1 . $n2; return $south_grid; } ############################################################################### ############################################################################### ## ## ## grid_east ## ## ## ## Compute the grid locator to the east of the grid locator sent as ## ## the parameter value. ## ## ## ## Input: grid locator ## ## ## ## Output: grid locator ## ## ## ## Error: none. ## ## ## ############################################################################### ############################################################################### sub grid_east { ## Extract data components and lowercase my ($current_grid) = @_; $current_grid = lc($current_grid); ## Break down to components. if ($current_grid =~ /(\w)(\w)(\d)(\d)/) { $l1 = $1; $l2 = $2; $n1 = $3; $n2 = $4; } ## Compute east grid if ($n1 eq 9) { $n1 = 0; $l1 = $letter_up{$l1}; } else { $n1++; } ## Output result $east_grid = $l1 . $l2 . $n1 . $n2; return $east_grid; } ############################################################################### ############################################################################### ## ## ## grid_west ## ## ## ## Compute the grid locator to the west of the grid locator sent as ## ## the parameter value. ## ## ## ## Input: grid locator ## ## ## ## Output: grid locator ## ## ## ## Error: none. ## ## ## ############################################################################### ############################################################################### sub grid_west { ## Extract data components and lowercase my ($current_grid) = @_; $current_grid = lc($current_grid); ## Break down to components. if ($current_grid =~ /(\w)(\w)(\d)(\d)/) { $l1 = $1; $l2 = $2; $n1 = $3; $n2 = $4; } ## Compute west grid if ($n1 eq 0) { $n1 = 9; $l1 = $letter_down{$l1}; } else { $n1--; } ## Output result $west_grid = $l1 . $l2 . $n1 . $n2; return $west_grid; } ############################################################################### ############################################################################### ## ## ## usage ## ## ## ## Prints out usage information in response to -h or -help. ## ## ## ## Input: none. ## ## ## ## Output: none. ## ## ## ## Error: none. ## ## ## ############################################################################### ############################################################################### sub usage { print "\n$0:\n\n "; print "This script reads in Cabrillo format files and computes "; print "eight different\n contest scores based upon eight different "; print "scoring formulas for each log.\n Output is in space or "; print "comma-delimited format. The eight scoring formulas\n are:\n\n"; print " Current\n"; print " The current QSO point and multiplier formulas for all "; print "categories.\n"; print "\n"; print " Current+OldRoverRules\n"; print " QSO points are computed as they are in the current rules. "; print "Multipliers\n for stations in the rover category are computed"; print " according to the old\n rover rules.\n"; print "\n"; print " Current+OldRoverRules+1ptRoverQSOs\n"; print " QSO points are computed as they are in the current rules, "; print "except that\n all QSOs with rover stations are 1 point, "; print "regardless of band.\n Multipliers for stations in the rover "; print "category are computed according\n to the old rover rules.\n"; print "\n"; print " Distance1\n"; print " QSO points are computed according to the recent proposal: "; print "a QSO with\n a station in the same grid or one grid away "; print "from your location earns\n two points, a QSO with a station "; print "further away earns three points,\n regardless of band. "; print "Multipliers for all categories are computed as\n they are "; print "under the current rules.\n"; print "\n"; print " Distance1+OldRoverRules\n"; print " QSO points are computed according to the recent proposal: "; print "a QSO with\n a station in the same grid or one grid away "; print "from your location earns\n two points, a QSO with a station "; print "further away earns three points,\n regardless of band. "; print "Multipliers for stations in the rover category\n are "; print "computed according to the old rover rules.\n"; print "\n"; print " Distance1+OldRoverRules+1ptRoverQSOs\n"; print " QSO points are computed according to the recent proposal: "; print "a QSO with\n a station in the same grid or one grid away "; print "from your location earns\n two points, a QSO with a station "; print "further away earns three points,\n regardless of band, "; print "except that all QSOs with rover stations earn\n one point, "; print "regardless of band. Multipliers for stations in the rover\n "; print "category are computed according to the old rover rules.\n"; print "\n"; print " Current+LowBandsOnly\n"; print " QSO points are computed as they are in the current rules, "; print "except that\n only QSOs made on the 50 MHz, 144 MHz, 222 "; print "MHz, 432 MHz, 902 MHz, and\n 1.2 GHz bands count for QSO "; print "point or multiplier credit.\n"; print "\n"; print " 1ptQSOs+LowBandsOnly\n"; print " All QSOs count one point, regardless of band or distance, "; print "and only\n QSOs made on the 50 MHz, 144 MHz, 222 MHz, "; print "432 MHz, 902 MHz, and\n 1.2 GHz bands count for QSO point "; print "or multiplier credit.\n"; print "\n"; print "Usage:\n\n"; print " $0 < logfile.cbr > report.csv\n\n"; print "Options:\n\n"; print " -v, -verbose, --verbose:\n"; print " Verbose output: include contest, category, ARRL section "; print "(default.)\n\n"; print " -q, -quiet, --quiet:\n"; print " Reduced output: no contest, category, or ARRL section.\n\n"; print " -c, -comma, --comma:\n"; print " Separate output with commas (default.)\n\n"; print " -s, -space, --space:\n"; print " Separate output with spaces.\n\n"; print " -h, -help, --help:\n"; print " Print this help message.\n\n"; print "Verbose example output:\n"; print " 2003-Jun,WM5R,R,STX,49560,96229,95062,88680,172187,"; print "169156,49560,34920\n\n"; print "Quiet example output:\n"; print " WM5R,49560,96229,95062,88680,172187,169156,49560,34920\n\n"; print "Contact:\n"; print " Ken Harker WM5R\n"; print " wm5r@arrl.net\n\n"; exit(1); } ############################################################################### ############################################################################### ## ## ## End of rescore.pl ## ## ## ############################################################################### ###############################################################################