Skip to content

Commit

Permalink
324 refactor contest specific logging code (#325)
Browse files Browse the repository at this point in the history
This will merge two refactoring steps:

1. refactor - Add TContest.ValidateEnteredQsoData
- move code from from TLog to TContest.ValidateEnteredQsoData
- allows derived contests to implement special behaviors (e.g ARRL
Sweepstakes).

2. refactor - Add TContest.SaveEnteredExchToQso
- moves code from Log.pas into Contest.pas
- allows contest-specific exchange information to be handled by derived
contests (e.g. ARRL Sweepstakes).
  • Loading branch information
w7sst authored Jun 25, 2024
2 parents 5fd1dd9 + 799bd9a commit 1c349a1
Show file tree
Hide file tree
Showing 2 changed files with 106 additions and 72 deletions.
91 changes: 91 additions & 0 deletions Contest.pas
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@ 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;

function ValidateEnteredQsoData(const ACall, AExch1, AExch2: string) : boolean; virtual;
procedure SaveEnteredExchToQso(var Qso: TQso; const AExch1, AExch2: string); virtual;
procedure FindQsoErrors(var Qso: TQso; var ACorrections: TStringList);
function ExtractMultiplier(Qso: PQso) : string; virtual;
function Minute: Single;
Expand Down Expand Up @@ -376,6 +379,94 @@ procedure TContest.FindQsoErrors(var Qso: TQso; var ACorrections: TStringList);
end;


{
ValidateEnteredQsoData is called by SaveQSO (see Log.pas).
SaveQSO is called when the QSO is complete and the user has sent 'TU'.
}
function TContest.ValidateEnteredQsoData(const ACall, AExch1, AExch2: string) : boolean;
// Adding a contest: validate contest-specific exchange fields
//validate Exchange 1 (Edit2) field lengths
function ValidateExchField1(const text: string): Boolean;
begin
Result := false;
case Mainform.RecvExchTypes.Exch1 of
etRST: Result := Length(text) = 3;
etOpName: Result := Length(text) > 1;
etFdClass: Result := Length(text) > 1;
else
assert(false, 'missing case');
end;
end;

//validate Exchange 2 (Edit3) field lengths
function ValidateExchField2(const text: string): Boolean;
begin
Result := false;
case Mainform.RecvExchTypes.Exch2 of
etSerialNr: Result := Length(text) > 0;
etGenericField:Result := Length(text) > 0;
etArrlSection: Result := Length(text) > 1;
etStateProv: Result := Length(text) > 1;
etCqZone: Result := Length(text) > 0;
etItuZone: Result := Length(text) > 0;
//etAge:
etPower: Result := Length(text) > 0;
etJaPref: Result := Length(text) > 2;
etJaCity: Result := Length(text) > 3;
etNaQpExch2: Result := Length(text) > 0;
etNaQpNonNaExch2: Result := Length(text) >= 0;
else
assert(false, 'missing case');
end;
end;

begin
Result := ValidateExchField1(AExch1) and ValidateExchField2(AExch2);
end;


{
SaveEnteredExchToQso will save contest-specific exchange values into a QSO.
This is called to enter the completed QSO into the log.
This virtual function can be overriden by specialized contests as needed
(see ARRL Sweepstakes).
}
procedure TContest.SaveEnteredExchToQso(var Qso: TQso; const AExch1, AExch2: string);
begin
// Adding a contest: save contest-specific exchange values into QsoList
//save Exchange 1 (Edit2)
case Mainform.RecvExchTypes.Exch1 of
etRST: Qso.Rst := StrToInt(AExch1);
etOpName: Qso.Exch1 := AExch1;
etFdClass: Qso.Exch1 := AExch1;
else
assert(false, 'missing case');
end;

//save Exchange2 (Edit3)
case Mainform.RecvExchTypes.Exch2 of
etSerialNr: Qso.Nr := StrToInt(AExch2);
etGenericField:Qso.Exch2 := AExch2;
etArrlSection: Qso.Exch2 := AExch2;
etStateProv: Qso.Exch2 := AExch2;
etCqZone: Qso.NR := StrToInt(AExch2);
etItuZone: Qso.Exch2 := AExch2;
//etAge:
etPower: Qso.Exch2 := AExch2;
etJaPref: Qso.Exch2 := AExch2;
etJaCity: Qso.Exch2 := AExch2;
etNaQpExch2: Qso.Exch2 := AExch2;
etNaQpNonNaExch2:
if AExch2 = '' then
Qso.Exch2 := 'DX'
else
Qso.Exch2 := AExch2;
else
assert(false, 'missing case');
end;
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
87 changes: 15 additions & 72 deletions Log.pas
Original file line number Diff line number Diff line change
Expand Up @@ -650,51 +650,23 @@ function ExtractPrefix(Call: string; DeleteTrailingLetters: boolean): string;

procedure SaveQso;
var
Call: string;
i: integer;
Qso: PQso;

// Adding a contest: validate contest-specific exchange fields
//validate Exchange 1 (Edit2) field lengths
function ValidateExchField1(const text: string): Boolean;
begin
Result := false;
case Mainform.RecvExchTypes.Exch1 of
etRST: Result := Length(text) = 3;
etOpName: Result := Length(text) > 1;
etFdClass: Result := Length(text) > 1;
else
assert(false, 'missing case');
end;
end;

//validate Exchange 2 (Edit3) field lengths
function ValidateExchField2(const text: string): Boolean;
begin
Result := false;
case Mainform.RecvExchTypes.Exch2 of
etSerialNr: Result := Length(text) > 0;
etGenericField:Result := Length(text) > 0;
etArrlSection: Result := Length(text) > 1;
etStateProv: Result := Length(text) > 1;
etCqZone: Result := Length(text) > 0;
etItuZone: Result := Length(text) > 0;
//etAge:
etPower: Result := Length(text) > 0;
etJaPref: Result := Length(text) > 2;
etJaCity: Result := Length(text) > 3;
etNaQpExch2: Result := Length(text) > 0;
etNaQpNonNaExch2: Result := Length(text) >= 0;
else
assert(false, 'missing case');
end;
end;

begin
with MainForm do
begin
if (Length(Edit1.Text) < 3) or
not ValidateExchField1(Edit2.Text) or
not ValidateExchField2(Edit3.Text) then
Call := StringReplace(Edit1.Text, '?', '', [rfReplaceAll]);

// This is too late for this check. The user has already sent 'TU'.
// If the entered information is incomplete, this is an error. This code
// results in an entry not being entered in the log and the DxStation
// is already gone after receiving the user's 'TU'.
//
// ValidateEnteredQsoData below is a virtual function to allow specialized
// contests to apply special processing (e.g. ARRL Sweepstakes).
if (Length(Call) < 3) or
not Tst.ValidateEnteredQsoData(Call, Edit2.Text, Edit3.Text) then
begin
{Beep;}
Exit;
Expand All @@ -706,39 +678,10 @@ procedure SaveQso;

//save data
Qso.T := BlocksToSeconds(Tst.BlockNumber) / 86400;
Qso.Call := StringReplace(Edit1.Text, '?', '', [rfReplaceAll]);

// Adding a contest: save contest-specific exchange values into QsoList
//save Exchange 1 (Edit2)
case Mainform.RecvExchTypes.Exch1 of
etRST: Qso.Rst := StrToInt(Edit2.Text);
etOpName: Qso.Exch1 := Edit2.Text;
etFdClass: Qso.Exch1 := Edit2.Text;
else
assert(false, 'missing case');
end;
Qso.Call := Call;

//save Exchange2 (Edit3)
case Mainform.RecvExchTypes.Exch2 of
etSerialNr: Qso.Nr := StrToInt(Edit3.Text);
etGenericField:Qso.Exch2 := Edit3.Text;
etArrlSection: Qso.Exch2 := Edit3.Text;
etStateProv: Qso.Exch2 := Edit3.Text;
etCqZone: Qso.NR := StrToInt(Edit3.Text);
etItuZone: Qso.Exch2 := Edit3.Text;
//etAge:
etPower: Qso.Exch2 := Edit3.Text;
etJaPref: Qso.Exch2 := Edit3.Text;
etJaCity: Qso.Exch2 := Edit3.Text;
etNaQpExch2: Qso.Exch2 := Edit3.Text;
etNaQpNonNaExch2:
if Edit3.Text = '' then
Qso.Exch2 := 'DX'
else
Qso.Exch2 := Edit3.Text;
else
assert(false, 'missing case');
end;
//save contest-specific exchange values into QSO
Tst.SaveEnteredExchToQso(Qso^, Edit2.Text, Edit3.Text);

Qso.Points := 1; // defaults to 1; override in ExtractMultiplier()
Qso.RawCallsign:= ExtractCallsign(Qso.Call);
Expand Down

0 comments on commit 1c349a1

Please sign in to comment.