CGI/Perl Guide | Learning Center | Forums | Advertise | Login
Site Search: in

  Main Index MAIN
INDEX
Search Posts SEARCH
POSTS
Who's Online WHO'S
ONLINE
Log in LOG
IN

Home: Perl Programming Help: Intermediate: Re: [stuckinarut] HASH-O-RAMA Data Processing Problem: Edit Log



Zhris
Enthusiast

Feb 26, 2015, 1:35 PM


Views: 31935
Re: [stuckinarut] HASH-O-RAMA Data Processing Problem

Hi,

Firstly, thank you for the background information on amateur radio sports. It helps me to understand the purpose of this task and enables me to provide more valuable suggestions. I have also looked at your website and familiarized myself with the rules ( I look forward to that reward you "promised" just for reading them! ).

When the time comes, we certainly can adjust to code to incooporate bonus points for contacting up to three volunteer secret stations across both bands. It has also become apparent that you have to do alot of pre and post processing i.e. pre processing includes adjusting contestants logs into the Cabrillo format, and post processing includes using excel to decipher the top scorers under each category. Perhaps this could be handled by our Perl script too.

With regards to namespacing, the whole logcall and callsign can be pretty baffling, afterall they are the same thing, but represent whether they are the transmitter or the receiver. I would have thought the namespaces of transmittercall for logcall and receivercall for callsign might be more appropriate, but what do I know.

Like alot of problems, the more you think about them, the more you realise their complexity. Before I read your reply, I had realised that we hadn't incoporated name and mult into the mix of things when attempting to automate the process of deciphering valid but unsubmitted logcalls. One example of many scenarios that must be considered is, if two contestants contacted an unsubmitted callsign, but logged conflicting callnames and/or callmults, we have no idea which is valid. I could also imagine a group of cheaters agreeing to log non existant callsigns in order to increase their weighting. Etc etc etc.

I propose we break the problem up into two phases.

- The first phase produces a log of all valid contestants callsigns, callnames and calllogs, whether they submitted their entries or not. Based on yours and my own ideas this can be automated to some level of accuracy, but an option to manually check and adjust this log is necessary.
----- The automated process will generate the log of all contestants using configurable threshold(s).
----- The manual process will generate a log of confirmed contestants, and unconfirmed contestants with relevant information in order to decide to keep or eliminate by eye. The resultant log will need to be in the same format as the one generated by the automated process.
- Now that we have the log generated in the first phase, the second phase of actually scoring each contestant will be a piece of cake.

This two phase process also simplifies the process and eliminates the need for the ignore and potential non submitters hashes.

I really need to get my head round phase one and re-read your concepts / ideas. For now I have thrown together code which handles confirming easily confirmable contestants, then lays out the unconfirmed contestants in a potentially suitable structure ready to be processed automatically or logged for manual processing. I will try to figure out the automation side of things.


Code
use strict; 
use warnings;
use Data::Dumper;

#local $/ = "\r\n";
local $, = "\t";
local $\ = "\n";

#####

# fh open.

my $string_output_scores = '';
my $string_output_errors = '';

my $handle_input_entries = \*DATA;
open my $handle_output_scores, '>', \$string_output_scores;
open my $handle_output_errors, '>', \$string_output_errors;

# headings.
print $handle_output_scores 'LOGCALL', 'QSOS', 'MULT', 'NAME';
print $handle_output_errors 'LOGCALL', 'CALLSIGN', 'BAND', 'TIME', 'ERRORTYPES';

#####

# init.

my $configuration =
{
handle_input_entries => $handle_input_entries,
#handle_input_contestants => $handle_input_contestants,
#handle_output_contestants => $handle_output_contestants,
handle_output_scores => $handle_output_scores,
handle_output_errors => $handle_output_errors,
case_sensitive => 0,
band_lookup => { 3 => '80M', 7 => '40M' },
automate_unconfirmed => 1,
automate_threshold => 2,
};

my $phase_dispatch =
{
1 => \&phase1,
2 => \&phase2,
};

#####

# phase.

my $phase = 1; # $ARGV[0];

$phase_dispatch->{$phase}->( $configuration );

#####

# fh close.

close $handle_input_entries;
close $handle_output_scores;
close $handle_output_errors;

# print.
#print $string_output_scores;
#print $string_output_errors;

#####

# functions.

sub phase1
{
my ( $configuration ) = @_;

my $handle_input_entries = $configuration->{handle_input_entries};
my $case_sensitive = $configuration->{case_sensitive};
#my $band_lookup = $configuration->{band_lookup};
my $automate_unconfirmed = $configuration->{automate_unconfirmed};

my $hash = { };

while ( my $line = <$handle_input_entries> )
{
# ignore blank or comment lines.
next if $line =~ m/^(\s*#|\s*$)/;

# remove any whitespace on the end of the line ( spaces, carriage return, newline ). This is more intuative than chomp.
$line =~ s/\s+$//;

# split line, extracting only values we need into list and upper casing them if not case sensitive.
my ( $freq, $time, $logcall, $logname, $logmult, $callsign, $callname, $callmult ) =
map { $_ = uc $_ unless $case_sensitive; $_ }
( split( ' ', $line ) )[1,4..10];

# lookup band via frequency.
#my $band = $band_lookup->{substr( $freq, 0, 1 )}; # todo: // error.

# log* are automatically confirmed.
$hash->{confirmed}->{$logcall} = { logname => $logname, logmult => $logmult } unless exists $hash->{confirmed}->{$logcall};

# call* are not confirmed yet.
$hash->{unconfirmed}->{$callsign}->{$callname}->{$callmult}++;
}

for my $callsign ( keys %{$hash->{unconfirmed}} )
{
# if the unconfirmed callsign exists as a confirmed logcall, delete this unconfirmed entry as it is now confirmed.
if ( exists $hash->{confirmed}->{$callsign} )
{
delete $hash->{unconfirmed}->{$callsign};
}
elsif ( $automate_unconfirmed )
{
# ...
}
}

print Dumper $hash;

return 1;
}

sub phase2
{

}

#####

__DATA__
QSO: 7040 CW 2015-01-22 0200 W7WHY Tom OR N6ZFO BILL CA
QSO: 7040 CW 2015-01-22 0200 W7WHY Tom OR N6ZFO BILL CA
QSO: 7040 CW 2015-01-22 0200 W7WHY Tom OR N6ZFO BILL CA
QSO: 7040 CW 2015-01-22 0201 W7WHY Tom OR W9RE MIKE IL
QSO: 3542 CW 2015-01-22 0231 W7WHY Tom OR N6ZF BILL CA
QSO: 3540 CW 2015-01-22 0232 W7WHY Tom OR W6NV OLI CA
QSO: 3542 CW 2015-01-22 0246 W7WHY Tom OR W9RE MIKE IN
QSO: 7000 CW 2015-01-22 0201 W9RE MIKE IN W7WHY TOM Or
QSO: 7000 CW 2015-01-22 0221 W9RE MIKE IN N6ZFO BILL Ca
QSO: 3500 CW 2015-01-22 0231 W9RE MIKE IN N6ZFO BIL Ca
QSO: 3500 CW 2015-01-22 0246 W9RE MIKE IN W7WHY TOM Or
QSO: 3500 CW 2015-01-22 0249 W9RE MIKE IN W6NV OLI Ca
QSO: 7040 CW 2015-01-22 0201 N6ZFO BILL CA W7WHY TOM OR
QSO: 7040 CW 2015-01-22 0221 N6ZFO BILL CA W9RR MIKE IN
QSO: 7040 CW 2015-01-22 0221 N6ZFO BILL CA W9RR MIKE ON
QSO: 7040 CW 2015-01-22 0221 N6ZFO BILL CA W9RR MIKEY IF
QSO: 7042 CW 2015-01-22 0222 N6ZFO BILL CA N2NL DAVE FL
QSO: 3543 CW 2015-01-22 0231 N6ZFO BILL CA W9RE MIKE IN
QSO: 3542 CW 2015-01-22 0231 N6ZFO BILL CA W7WHY TOM OR
QSO: 3544 CW 2015-01-22 0235 N6ZFO BILL CA W6NV OLI CA


Output:

Code
$VAR1 = { 
'confirmed' => {
'N6ZFO' => {
'logname' => 'BILL',
'logmult' => 'CA'
},
'W7WHY' => {
'logname' => 'TOM',
'logmult' => 'OR'
},
'W9RE' => {
'logname' => 'MIKE',
'logmult' => 'IN'
}
},
'unconfirmed' => {
'N6ZF' => {
'BILL' => {
'CA' => 1
}
},
'W9RR' => {
'MIKE' => {
'ON' => 1,
'IN' => 1
},
'MIKEY' => {
'IF' => 1
}
},
'N2NL' => {
'DAVE' => {
'FL' => 1
}
},
'W6NV' => {
'OLI' => {
'CA' => 3
}
}
}
};


Regards,

Chris


(This post was edited by Zhris on Feb 26, 2015, 1:46 PM)


Edit Log:
Post edited by Zhris (Enthusiast) on Feb 26, 2015, 1:37 PM
Post edited by Zhris (Enthusiast) on Feb 26, 2015, 1:38 PM
Post edited by Zhris (Enthusiast) on Feb 26, 2015, 1:40 PM
Post edited by Zhris (Enthusiast) on Feb 26, 2015, 1:41 PM
Post edited by Zhris (Enthusiast) on Feb 26, 2015, 1:42 PM
Post edited by Zhris (Enthusiast) on Feb 26, 2015, 1:42 PM
Post edited by Zhris (Enthusiast) on Feb 26, 2015, 1:43 PM
Post edited by Zhris (Enthusiast) on Feb 26, 2015, 1:45 PM
Post edited by Zhris (Enthusiast) on Feb 26, 2015, 1:46 PM


Search for (options) Powered by Gossamer Forum v.1.2.0

Web Applications & Managed Hosting Powered by Gossamer Threads
Visit our Mailing List Archives