Skip to content

Commit

Permalink
Implement ARRL Sweepstakes Contest #55
Browse files Browse the repository at this point in the history
  • Loading branch information
w7sst committed Aug 30, 2024
1 parent 4b52c69 commit 9db58b9
Show file tree
Hide file tree
Showing 12 changed files with 1,332 additions and 21 deletions.
413 changes: 413 additions & 0 deletions ArrlSS.pas

Large diffs are not rendered by default.

10 changes: 9 additions & 1 deletion DxStn.pas
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ procedure TDxStation.SendMsg(AMsg: TStationMessage);
if BDebugExchSettings and (AMsg in [msgNR, msgR_NR, msgR_NR2,
msgDeMyCallNr1, msgDeMyCallNr2, msgMyCallNr1, msgMyCallNr2]) then
begin
if (Mainform.Edit2.Text = '') then
if (Mainform.Edit2.Text = '') and not (SimContest in [scArrlSS]) then
Mainform.Edit2.Text := Exch1;
if (Mainform.Edit3.Text = '') and
((SimContest <> scNaQp) or (Exch2 <> 'DX')) then
Expand All @@ -240,6 +240,10 @@ procedure TDxStation.DataToLastQso;
etRST: TrueExch1 := IntToStr(Self.RST);
etOpName: TrueExch1 := Self.OpName;
etFdClass: TrueExch1 := Self.Exch1;
etSSNrPrecedence: begin
TrueNR := Self.NR;
TruePrec := Self.Prec;
end;
else
assert(false);
end;
Expand All @@ -255,6 +259,10 @@ procedure TDxStation.DataToLastQso;
etJaPref: TrueExch2 := Self.Exch2;
etJaCity: TrueExch2 := Self.Exch2;
etNaQpExch2, etNaQpNonNaExch2: TrueExch2 := Self.Exch2;
etSSCheckSection: begin
TrueCheck := Self.Chk; // check (e.g. 72)
TrueSect := Self.Sect; // section (e.g. OR)
end
else
assert(false);
end;
Expand Down
8 changes: 6 additions & 2 deletions ExchFields.pas
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@ interface

type
// Exchange Field #1 types
TExchange1Type = (etRST, etOpName, etFdClass);
TExchange1Type = (etRST, etOpName, etFdClass, etSSNrPrecedence);

// Exchange Field #2 Types
TExchange2Type = (etSerialNr, etGenericField, etArrlSection, etStateProv,
etCqZone, etItuZone, etAge, etPower, etJaPref, etJaCity,
etNaQpExch2, etNaQpNonNaExch2);
etNaQpExch2, etNaQpNonNaExch2, etSSCheckSection);

{
Defines the characteristics and behaviors of an exchange field.
Expand All @@ -44,6 +44,8 @@ TFieldDefinition = record
(C: 'RST'; R: '[1-5E][1-9N][1-9N]'; L: 3; T:Ord(etRST))
,(C: 'Name'; R: '[A-Z][A-Z]*'; L: 10; T:Ord(etOpName))
,(C: 'Class'; R: '[1-9][0-9]*[A-F]'; L: 3; T:Ord(etFdClass))
// ARRL SS does not parse user-entered Exchange 1 field; Exchange 2 field is used.
,(C: ''; R: '([0-9]+|#)? *[QABUMS]'; L: 4; T:Ord(etSSNrPrecedence))
);

// Exchange Field 2 settings/rules
Expand All @@ -63,6 +65,8 @@ TFieldDefinition = record
// Non-NA stations send name only
,(C: 'State'; R: '([0-9A-Z/]*)'; L: 6; T:Ord(etNaQpExch2))
,(C: 'State'; R: '()|([0-9A-Z/]*)'; L: 6; T:Ord(etNaQpNonNaExch2))
,(C: 'Nr Prec Call CK Sect';
R: '[0-9ONT]{1,2} +[A-Z]+'; L: 32; T:Ord(etSSCheckSection))
);

implementation
Expand Down
22 changes: 20 additions & 2 deletions Ini.pas
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ interface
type
// Adding a contest: Append new TSimContest enum value for each contest.
TSimContest = (scWpx, scCwt, scFieldDay, scNaQp, scHst, scCQWW, scArrlDx,
scSst, scAllJa, scAcag, scIaruHf);
scSst, scAllJa, scAcag, scIaruHf, scArrlSS);
TRunMode = (rmStop, rmPileup, rmSingle, rmWpx, rmHst);

// Serial NR types
Expand Down Expand Up @@ -200,7 +200,22 @@ TContestDefinition = record
ExchFieldEditable: True;
ExchDefault: '5NN 6';
Msg: '''RST <Itu-zone|IARU Society>'' (e.g. 5NN 6)';
T:scIaruHf)
T:scIaruHf),

(Name: 'ARRL Sweepstakes';
Key: 'SSCW';
ExchType1: etSSNrPrecedence; // full exchange info is entered via Exch2; or my serial number (sent)
ExchType2: etSSCheckSection;
ExchFieldEditable: True;
ExchDefault: 'A 72 OR';
Msg: '''[#|123] <precedence> <check> <section>'' (e.g. A 72 OR)';
T:scArrlSS)
// Entered Exchange: # <precedence> * <check> <section>
// where precedence={Q,A,B,U,M,S}, check='year licenced', ARRL/RAC section.
// Sent Exchange: # A W7SST 72 OR
// Fields: NR:numeric, Prec:string, Check:numeric, Section:string
// N1MM default ordering w/ call history: 72 OR. I type 123A
// N1MM automatic rendering: 123A <call> 72 OR
);

var
Expand Down Expand Up @@ -239,6 +254,7 @@ TContestDefinition = record
NoActivityCnt: integer=0;
NoStopActivity: integer=0;
GetWpmUsesGaussian: boolean = false;
ShowCheckSection: integer=50;

Duration: integer = 30;
RunMode: TRunMode = rmStop;
Expand Down Expand Up @@ -417,6 +433,7 @@ procedure FromIni(cb : TErrMessageCallback);
WpmStepRate := Max(1, Min(20, ReadInteger(SEC_SET, 'WpmStepRate', WpmStepRate)));
RitStepIncr := ReadInteger(SEC_SET, 'RitStepIncr', RitStepIncr);
RitStepIncr := Max(-500, Min(500, RitStepIncr));
ShowCheckSection := ReadInteger(SEC_SET, 'ShowCheckSection', ShowCheckSection);

// [Debug]
DebugExchSettings := ReadBool(SEC_DBG, 'DebugExchSettings', DebugExchSettings);
Expand Down Expand Up @@ -499,6 +516,7 @@ procedure ToIni;
WriteInteger(SEC_SET, 'FarnsworthCharacterRate', FarnsworthCharRate);
WriteInteger(SEC_SET, 'WpmStepRate', WpmStepRate);
WriteInteger(SEC_SET, 'RitStepIncr', RitStepIncr);
WriteInteger(SEC_SET, 'ShowCheckSection', ShowCheckSection);

finally
Free;
Expand Down
52 changes: 48 additions & 4 deletions Log.pas
Original file line number Diff line number Diff line change
Expand Up @@ -47,14 +47,18 @@ procedure DebugLnExit(const AFormat: string; const AArgs: array of const) overlo
type
TLogError = (leNONE, leNIL, leDUP, leCALL, leRST,
leNAME, leCLASS, leNR, leSEC, leQTH,
leZN, leSOC, leST, lePWR, leERR);
leZN, leSOC, leST, lePWR, leERR,
lePREC, leCHK);

PQso = ^TQso;
TQso = record
T: TDateTime;
Call, TrueCall, RawCallsign: string;
Rst, TrueRst: integer;
Nr, TrueNr: integer;
Prec, TruePrec: string; // SS' Precedence character
Check, TrueCheck: integer; // SS' Chk (year licensed)
Sect, TrueSect: string; // SS' Arrl/RAC Section
Exch1, TrueExch1: string; // exchange 1 (e.g. 3A, OpName)
Exch2, TrueExch2: string; // exchange 2 (e.g. OR, CWOPSNum)
TrueWpm: string; // WPM of sending DxStn (reported in log)
Expand Down Expand Up @@ -175,6 +179,9 @@ implementation
WPX_EXCH_COL = 'Exch,6,L';
HST_EXCH_COL = 'Exch,6,L';
CQ_ZONE_COL = 'CQ-Zone,7,L';
SS_PREC_COL = 'Pr,2,C';
SS_CHECK_COL = 'Chk,3,C';
SS_SECT_COL = 'Sect,4,L';

{$ifdef DEBUG}
DEBUG_INDENT: Integer = 3;
Expand Down Expand Up @@ -249,6 +256,7 @@ function FormatScore(const AScore: integer):string;

procedure TQso.SetColumnErrorFlag(AColumnInx: integer);
begin
assert((AColumnInx > -1) and (AColumnInx < 32));
if AColumnInx <> -1 then
ColumnErrorFlags := ColumnErrorFlags or (1 shl AColumnInx);
end;
Expand All @@ -259,7 +267,7 @@ function TQso.TestColumnErrorFlag(ColumnInx: Integer): Boolean;
end;

{
Initialize the Log Report.
Initialize the Call Log Report.
An array of ColDefs is passed in with one entry for each column.
Each column definition string is defined as follows:
Expand Down Expand Up @@ -446,6 +454,11 @@ procedure Clear;
ScoreTableInit([UTC_COL, CALL_COL, NAME_COL, SST_EXCH_COL, CORRECTIONS_COL, WPM_FARNS_COL]);
scFieldDay:
ScoreTableInit([UTC_COL, CALL_COL, FD_CLASS_COL, ARRL_SECT_COL, CORRECTIONS_COL, WPM_COL]);
scArrlSS:
begin
ScoreTableInit([UTC_COL, CALL_COL, NR_COL, SS_PREC_COL, SS_CHECK_COL, ARRL_SECT_COL, CORRECTIONS_COL, WPM_COL]);
SetExchColumns(2, 4, 3, 5);
end;
scNaQp:
ScoreTableInit([UTC_COL, 'Call,8,L', NAME_COL, STATE_PROV_COL, PREFIX_COL, CORRECTIONS_COL, WPM_COL]);
scCQWW:
Expand Down Expand Up @@ -818,7 +831,8 @@ procedure SaveQso;
MainForm.WipeBoxes;

//inc NR
if Tst.Me.SentExchTypes.Exch2 = etSerialNr then
if (Tst.Me.SentExchTypes.Exch1 in [etSSNrPrecedence]) or
(Tst.Me.SentExchTypes.Exch2 in [etSerialNr]) then
Inc(Tst.Me.NR);
end;

Expand Down Expand Up @@ -898,6 +912,13 @@ procedure LastQsoToScreen;
, format('%.3d', [Rst])
, Exch2
, Err, format('%3s', [TrueWpm]));
scArrlSS:
ScoreTableInsert(FormatDateTime('hh:nn:ss', t), Call
, format('%4d', [NR])
, Prec
, format('%.2d', [Check])
, Sect
, Err, format('%3s', [TrueWpm]));
else
assert(false, 'missing case');
end;
Expand All @@ -915,16 +936,25 @@ procedure TQso.CheckExch1(var ACorrections: TStringList);
etRST: if TrueRst <> Rst then Exch1Error := leRST;
etOpName: if TrueExch1 <> Exch1 then Exch1Error := leNAME;
etFdClass: if TrueExch1 <> Exch1 then Exch1Error := leCLASS;
etSSNrPrecedence: begin
// For ARRL SS, exchange 1 tests the raw NR and Prec values
if TrueNR <> NR then Exch1Error := leNR;
if TruePrec <> Prec then Exch1ExError := lePrec;
end
else
assert(false, 'missing exchange 1 case');
end;

case Exch1Error of
leNONE: ;
leRST: ACorrections.Add(Format('%d', [TrueRst]));
leNR: ACorrections.Add(Format('%d', [TrueNR]));
else
ACorrections.Add(TrueExch1);
end;
case Exch1ExError of
lePrec: ACorrections.Add(TruePrec);
end;
end;


Expand Down Expand Up @@ -985,6 +1015,10 @@ procedure TQso.CheckExch2(var ACorrections: TStringList);
if not (TrueExch2.Equals(Exch2) or
(Exch2.Equals('DX') and TrueExch2.IsEmpty)) then
Exch2Error := leST;
etSSCheckSection: begin
if TrueCheck <> Check then Exch2Error := leCHK;
if TrueSect <> Sect then Exch2ExError := leSEC;
end
else
assert(false, 'missing exchange 2 case');
end;
Expand All @@ -997,14 +1031,23 @@ procedure TQso.CheckExch2(var ACorrections: TStringList);
assert(Mainform.RecvExchTypes.Exch2 = etSerialNr);
ACorrections.Add(format('%.4d', [TrueNR]));
end
else if (SimContest = scArrlSS) then
ACorrections.Add(TrueSect)
else
ACorrections.Add(TrueExch2);
leCHK:
ACorrections.Add(format('%.02d', [TrueCheck]));
else
ACorrections.Add(TrueExch2);
end;

case Exch2ExError of
leNONE: ;
leSEC:
begin
assert(SimContest = scArrlSS);
ACorrections.Add(TrueSect);
end;
else
assert(false);
end;
Expand All @@ -1016,7 +1059,8 @@ procedure CheckErr;
ErrorStrs: array[TLogError] of string = (
'', 'NIL', 'DUP', 'CALL', 'RST',
'NAME', 'CL', 'NR', 'SEC', 'QTH',
'ZN', 'SOC', 'ST', 'PWR', 'ERR');
'ZN', 'SOC', 'ST', 'PWR', 'ERR',
'PREC', 'CHK');
var
Corrections: TStringList;
begin
Expand Down
Loading

0 comments on commit 9db58b9

Please sign in to comment.