Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor exchange error checking code #304

Merged
merged 1 commit into from
Apr 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 21 additions & 3 deletions Contest.pas
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ TContest = class
const AStationCallsign : string) : TExchTypes; virtual;
procedure SendMsg(const AStn: TStation; const AMsg: TStationMessage); virtual;
procedure SendText(const AStn: TStation; const AMsg: string); virtual;
procedure FindQsoErrors(var Qso: TQso);
function ExtractMultiplier(Qso: PQso) : string; virtual;
function Minute: Single;
function GetAudio: TSingleArray;
Expand Down Expand Up @@ -356,6 +357,22 @@ procedure TContest.SendText(const AStn: TStation; const AMsg: string);
end;


{
Find exchange errors in the current Qso.
Called at end of each Qso during Qso validaiton.
This virtual procedure can be overriden to perform special exchange
validation behaviors.

Side Effects:
- sets Qso.Exch1Error and Qso.Exch2Error
}
procedure TContest.FindQsoErrors(var Qso: TQso);
begin
Qso.CheckExch1;
Qso.CheckExch2;
end;


{
Extract multiplier string for a given contest. Default behavior will
return the QSO.Pfx string (which implies this method must be called
Expand Down Expand Up @@ -485,12 +502,13 @@ function TContest.GetAudio: TSingleArray;
if Stations[i] is TDxStation then
with Stations[i] as TDxStation do
if (Oper.State = osDone) and (QsoList <> nil) and (MyCall = QsoList[High(QsoList)].Call) then begin
// grab Qso's "True" data (e.g. TrueCall, TrueExch1, TrueExch2)
DataToLastQso; // deletes this TDxStation from Stations[]
//with MainForm.RichEdit1.Lines do Delete(Count-1);
// Delete(Count-1);
//Log.LastQsoToScreen;

// rerun error check and update Err string on screen log
Log.CheckErr;
Log.ScoreTableUpdateCheck;

{ TODO -omikeb -cfeature : Clean up status bar code. }
if Ini.RunMode = RmHst then
Log.UpdateStatsHst
Expand Down
181 changes: 124 additions & 57 deletions Log.pas
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ function ExtractPrefix0(Call: string): string;
{$endif}

type
TLogError = (leNONE, leNIL, leDUP, leCALL, leRST,
leNAME, leCLASS, leNR, leSEC, leQTH,
leZN, leSOC, leST, lePWR, leERR);

PQso = ^TQso;
TQso = record
T: TDateTime;
Expand All @@ -43,8 +47,14 @@ TQso = record
Pfx: string; // extracted call prefix
MultStr: string; // contest-specific multiplier (e.g. Pfx, dxcc)
Points: integer; // points for this QSO
Dupe: boolean;
Err: string;
Dupe: boolean; // this qso is a DUP.
ExchError: TLogError; // Callsign error code
Exch1Error: TLogError; // Exchange 1 qso error code
Exch2Error: TLogError; // Exchange 2 qso error code
Err: string; // Qso error string (e.g. corrections)

procedure CheckExch1;
procedure CheckExch2;
end;

THisto= class(TObject)
Expand Down Expand Up @@ -673,7 +683,7 @@ procedure SaveQso;
with Tst.Stations[i] as TDxStation do
if (Oper.State = osDone) and (MyCall = Qso.Call) then
begin
DataToLastQso; //deletes this dx station!
DataToLastQso; //grab "True" data and delete this dx station!
Break;
end;

Expand All @@ -696,6 +706,12 @@ procedure SaveQso;
end;


{
Adds last Qso to log as displayed on the screen. The Error information
is not yet complete, so the Err column is not rendered at this time.
The error will be updated by DataToLastQso after the DxStation has been
confirmed and removed by TContest.GetAudio().
}
procedure LastQsoToScreen;
begin
with QsoList[High(QsoList)] do begin
Expand Down Expand Up @@ -758,7 +774,23 @@ procedure LastQsoToScreen;
end;


procedure CheckErr;
procedure TQso.CheckExch1;
begin
Exch1Error := leNONE;

// Adding a contest: check for contest-specific exchange field 1 errors
case Mainform.RecvExchTypes.Exch1 of
etRST: if TrueRst <> Rst then Exch1Error := leRST;
etOpName: if TrueExch1 <> Exch1 then Exch1Error := leNAME;
etFdClass: if TrueExch1 <> Exch1 then Exch1Error := leCLASS;
else
assert(false, 'missing exchange 1 case');
end;
end;


procedure TQso.CheckExch2;

// Reduce Power characters (T, O, A, N) to (0, 0, 1, 9) respectively.
function ReducePowerStr(const text: string): string;
begin
Expand All @@ -770,65 +802,100 @@ procedure CheckErr;
end;

begin
with QsoList[High(QsoList)] do begin
Err := '';
if TrueCall = '' then
Err := 'NIL';
if Err.IsEmpty and Dupe then
Err := 'DUP';
if Err.IsEmpty then
// Adding a contest: check for contest-specific exchange field 1 errors
case Mainform.RecvExchTypes.Exch1 of
etRST: if TrueRst <> Rst then Err := 'RST';
etOpName: if TrueExch1 <> Exch1 then Err := 'NAME';
etFdClass: if TrueExch1 <> Exch1 then Err := 'CL ';
else
assert(false, 'missing exchange 1 case');
end;
if Err.IsEmpty then
// Adding a contest: check for contest-specific exchange field 2 errors
case Mainform.RecvExchTypes.Exch2 of
etSerialNr: if TrueNr <> NR then Err := 'NR ';
etGenericField:
// Adding a contest: implement comparison for Generic Field type
case Ini.SimContest of
scCwt:
if TrueExch2 <> Exch2 then
Err := IfThen(IsNum(TrueExch2), 'NR ', 'QTH');
scSst:
if TrueExch2 <> Exch2 then
Err := 'QTH';
scIaruHf:
// need to add ReduceNumeric...
if TrueExch2 <> Exch2 then
Err := IfThen(IsNum(TrueExch2), 'ZN ', 'Soc');
Exch2Error := leNONE;

// Adding a contest: check for contest-specific exchange field 2 errors
case Mainform.RecvExchTypes.Exch2 of
etSerialNr: if TrueNr <> NR then Exch2Error := leNR;
etGenericField:
// Adding a contest: implement comparison for Generic Field type
case Ini.SimContest of
scCwt:
if TrueExch2 <> Exch2 then
if IsNum(TrueExch2) then
Exch2Error := leNR
else
if TrueExch2 <> Exch2 then
Err := 'ERR';
end;
etCqZone: if TrueNr <> NR then Err := 'ZN ';
etArrlSection: if TrueExch2 <> Exch2 then Err := 'SEC';
etStateProv: if TrueExch2 <> Exch2 then Err := 'ST ';
etItuZone: if TrueExch2 <> Exch2 then Err := 'ZN ';
//etAge:
etPower: if ReducePowerStr(TrueExch2) <> ReducePowerStr(Exch2) then
Err := 'PWR';
etJaPref: if TrueExch2 <> Exch2 then Err := 'NR ';
etJaCity: if TrueExch2 <> Exch2 then Err := 'NR ';
etNaQpExch2: if TrueExch2 <> Exch2 then Err := 'ST ';
etNaQpNonNaExch2:
// Non-NA stations do not send a location (typically logged as DX)
if not (TrueExch2.Equals(Exch2) or
(Exch2.Equals('DX') and TrueExch2.IsEmpty)) then
Err := 'ST ';
Exch2Error := leQTH;
scSst:
if TrueExch2 <> Exch2 then
Exch2Error := leQTH;
scIaruHf:
// need to add ReduceNumeric...
if TrueExch2 <> Exch2 then
if IsNum(TrueExch2) then
Exch2Error := leZN
else
Exch2Error := leSOC;
else
assert(false, 'missing exchange 2 case');
if TrueExch2 <> Exch2 then
Exch2Error := leERR;
end;
if Err.IsEmpty then
Err := ' ';
etCqZone: if TrueNr <> NR then Exch2Error := leZN;
etArrlSection: if TrueExch2 <> Exch2 then Exch2Error := leSEC;
etStateProv: if TrueExch2 <> Exch2 then Exch2Error := leST;
etItuZone: if TrueExch2 <> Exch2 then Exch2Error := leZN;
//etAge:
etPower: if ReducePowerStr(TrueExch2) <> ReducePowerStr(Exch2) then
Exch2Error := lePWR;
etJaPref: if TrueExch2 <> Exch2 then Exch2Error := leNR;
etJaCity: if TrueExch2 <> Exch2 then Exch2Error := leNR;
etNaQpExch2: if TrueExch2 <> Exch2 then Exch2Error := leST;
etNaQpNonNaExch2:
// Non-NA stations do not send a location (typically logged as DX)
if not (TrueExch2.Equals(Exch2) or
(Exch2.Equals('DX') and TrueExch2.IsEmpty)) then
Exch2Error := leST;
else
assert(false, 'missing exchange 2 case');
end;
end;


procedure CheckErr;
const
ErrorStrs: array[TLogError] of string = (
'', 'NIL', 'DUP', 'CALL', 'RST',
'NAME', 'CL', 'NR', 'SEC', 'QTH',
'ZN', 'SOC', 'ST', 'PWR', 'ERR');
begin
with QsoList[High(QsoList)] do begin
// form the legacy Err String (e.g. RST, NR, CL, SEC, etc)
if TrueCall = '' then
ExchError := leNIL
else if TrueCall <> Call then
begin
ExchError := leCALL;
end
else if Dupe then
ExchError := leDUP // todo - list this in column, but not as error
else
begin
ExchError := leNONE;

// find exchange errors for the current Qso
Tst.FindQsoErrors(QsoList[High(QsoList)]);
end;

// NIL or DUP errors have priority over showing corrected exchange
if ExchError in [leNIL, leDUP] then
begin
Err := ErrorStrs[ExchError];
end
else
begin
if Exch1Error <> leNONE then
Err := ErrorStrs[Exch1Error]
else if Exch2Error <> leNONE then
Err := ErrorStrs[Exch2Error]
else
Err := '';
end;

if Err.IsEmpty then
Err := ' ';
end; // end with QsoList[High(QsoList)]
end;

{
procedure PaintHisto;
var
Expand Down