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

341 improve exchange error reporting #342

Merged
merged 2 commits into from
Aug 25, 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
40 changes: 35 additions & 5 deletions Contest.pas
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,10 @@ TContest = class
procedure SendMsg(const AStn: TStation; const AMsg: TStationMessage); virtual;
procedure SendText(const AStn: TStation; const AMsg: string); virtual;

function ValidateEnteredExchange(const ACall, AExch1, AExch2: string) : boolean; virtual;
function CheckEnteredCallLength(const ACall: string;
out AExchError: String) : boolean; virtual;
function ValidateEnteredExchange(const ACall, AExch1, AExch2: string;
out AExchError: 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;
Expand Down Expand Up @@ -446,12 +449,31 @@ procedure TContest.FindQsoErrors(var Qso: TQso; var ACorrections: TStringList);
end;


{
Performs simple length check on a callsign.
Returns true for callsigns with 3 or more characters; false otherwise.
Upon error, AExchError will contain a simple error message.
}
function TContest.CheckEnteredCallLength(const ACall: string;
out AExchError: String) : boolean;
begin
Result := ACall.Length >= 3;
if not Result then
AExchError := 'Invalid callsign';
end;


{
ValidateEnteredExchange is called prior to sending the final 'TU' and calling
SaveQSO (see Log.pas). This virtual function can be overriden for complex
exchange information (e.g. ARRL Sweepstakes).
SaveQSO (see Log.pas). The basic validation is a length test where each
exchange is checked against a minimum length requirement.
This is contest with original 1.68 behaviors.

This virtual function can be overriden for complex exchange information
(e.g. ARRL Sweepstakes).
}
function TContest.ValidateEnteredExchange(const ACall, AExch1, AExch2: string) : boolean;
function TContest.ValidateEnteredExchange(const ACall, AExch1, AExch2: string;
out AExchError: String) : boolean;
// Adding a contest: validate contest-specific exchange fields
//validate Exchange 1 (Edit2) field lengths
function ValidateExchField1(const text: string): Boolean;
Expand Down Expand Up @@ -489,7 +511,15 @@ function TContest.ValidateEnteredExchange(const ACall, AExch1, AExch2: string) :
end;

begin
Result := ValidateExchField1(AExch1) and ValidateExchField2(AExch2);
if not ValidateExchField1(AExch1) then
AExchError := format('Missing/Invalid %s',
[Exchange1Settings[Mainform.RecvExchTypes.Exch1].C])
else if not ValidateExchField2(AExch2) then
AExchError := format('Missing/Invalid %s',
[Exchange2Settings[Mainform.RecvExchTypes.Exch2].C])
else
AExchError := '';
Result := AExchError.IsEmpty;
end;


Expand Down
29 changes: 20 additions & 9 deletions Log.pas
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,7 @@ procedure UpdateSbar(const ACallsign: string);
end;

// during debug, use status bar to show CW stream
Mainform.sbar.Font.Color := clDefault;
if not s.IsEmpty and (BDebugCwDecoder or BDebugGhosting) then
Mainform.sbar.Caption:= LeftStr(Mainform.sbar.Caption, 40) + ' -- ' + s
else
Expand Down Expand Up @@ -721,27 +722,37 @@ function ExtractPrefix(Call: string; DeleteTrailingLetters: boolean): string;
end;


{
Save QSO data into the Log.

Called by either:
- 'Enter' key (after sending 'TU' to caller).
- 'Shift-Enter', 'Cntl-Enter' or 'Alt-Enter' (without sending 'TU' to caller).
}
procedure SaveQso;
var
Call: string;
ExchError: string;
i: integer;
Qso: PQso;
begin
with MainForm do
begin
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'.
//
// ValidateEnteredExchange below is a virtual function to allow specialized
// contests to apply special processing (e.g. ARRL Sweepstakes).
if (Length(Call) < 3) or
not Tst.ValidateEnteredExchange(Call, Edit2.Text, Edit3.Text) then
// Virtual functions used below allow special processing as needed
// for some contests (e.g. ARRL Sweepstakes).
if not Tst.CheckEnteredCallLength(Call, ExchError) or
not Tst.ValidateEnteredExchange(Call, Edit2.Text, Edit3.Text, ExchError) then
begin
{Beep;}
if not ExchError.IsEmpty then
begin
sbar.Caption := ExchError;
sbar.Align:= alBottom;
sbar.Visible:= true;
sbar.Font.Color := clRed;
end;
Exit;
end;

Expand Down
21 changes: 17 additions & 4 deletions Main.pas
Original file line number Diff line number Diff line change
Expand Up @@ -850,6 +850,7 @@ procedure TMainForm.ProcessSpace;
procedure TMainForm.ProcessEnter;
var
C, N, R, Q: boolean;
ExchError: string;
begin
if ActiveControl = ExchangeEdit then
begin
Expand All @@ -872,6 +873,9 @@ procedure TMainForm.ProcessEnter;
end;
MustAdvance := false;

sbar.Font.Color := clDefault;

// 'Control-Enter', 'Shift-Enter' and 'Alt-Enter' are shortcuts to SaveQSO
if (GetKeyState(VK_CONTROL) or GetKeyState(VK_SHIFT) or GetKeyState(VK_MENU)) < 0 then
begin
Log.SaveQso;
Expand Down Expand Up @@ -914,6 +918,19 @@ procedure TMainForm.ProcessEnter;

if R and Q and (C or N) then
begin
// validate Exchange before sending TU and logging the QSO
if not Tst.ValidateEnteredExchange(Edit1.Text, Edit2.Text, Edit3.Text, ExchError) then
begin
if not ExchError.IsEmpty then
begin
sbar.Caption := ExchError;
sbar.Align:= alBottom;
sbar.Visible:= true;
sbar.Font.Color := clRed;
end;
Exit;
end;

SendMsg(msgTU);
Log.SaveQso;
end
Expand Down Expand Up @@ -1080,16 +1097,12 @@ function TMainForm.SetMyExchange(const AExchange: string) : Boolean;
sl: TStringList;
ExchError: string;
SentExchTypes : TExchTypes;
Field1Def: PFieldDefinition;
Field2Def: PFieldDefinition;
begin
sl:= TStringList.Create;
try
assert(Tst.Me.SentExchTypes = Tst.GetSentExchTypes(skMyStation, Ini.Call),
'set by TMainForm.SetMyCall');
SentExchTypes := Tst.Me.SentExchTypes;
Field1Def := @Exchange1Settings[SentExchTypes.Exch1];
Field2Def := @Exchange2Settings[SentExchTypes.Exch2];

// parse into two strings [Exch1, Exch2]
// validate sent exchange strings
Expand Down