Read the rest of what a .udc file says, and score what N1MM scores
Two pieces of work on the scoring engine. The .udc reader now takes N1MM's published scoring vocabulary: the full PointsPerContact condition set, the PointsMultBy family, PowerMult, BonusPoints, the multiplier sources and the settings that say which stations bring a multiplier in. MultMult is a weight rather than a switch, as in N1MM's ComputeScore. The entry categories and the sent exchange reach the rules in a new ContestEntry, so a contest can score by the power category it is entered in or by what this station sends. Then every contest in a real N1MM log was scored again from these rules and compared with the points and multiplier flags N1MM wrote. That found five bugs: ARRL DX and IARU read the exchange from the wrong column, a stored " " was read as a value rather than as empty, CQ WW RTTY's own Canadian area names were not counted, a maritime mobile scored nothing, and a contact in a mode the contest does not run scored as if it were in the contest. docs/n1mm-interop.md has the check and what still differs. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RoGtneMQaz4M9w7Kk49AVD
This commit is contained in:
@@ -79,3 +79,50 @@ opened. The name carries the mode, so it beats whatever `ModeCategory` says.
|
||||
|
||||
Older N1MM versions wrote the CW running of CQ WW as plain `CQWW`. That name is
|
||||
still in the registry, so those logs open.
|
||||
|
||||
## Which column an exchange lands in
|
||||
|
||||
N1MM keeps the received exchange of ARRL DX, IARU and WAE in `Sect`, not in
|
||||
`Exchange1`, whatever the entry window calls the box. A contest that reads the
|
||||
wrong column scores every contact as if the operator had typed nothing, so the
|
||||
rule reads the column N1MM writes and the entry window points its box at the
|
||||
same place.
|
||||
|
||||
N1MM also writes a single space into a text column it has nothing for, so
|
||||
`Continent` comes back as `" "` rather than empty. Reading it as a value rather
|
||||
than as empty makes every contact look like another continent. The store trims
|
||||
what it reads.
|
||||
|
||||
## Scoring checked against a real log
|
||||
|
||||
`om5m.s3db` in the repo root is a station's own N1MM log: 78 contest instances
|
||||
from 2019 to 2026, 57,000 contacts, 28 contest names. Replaying it is how the
|
||||
scoring rules are checked — every contact is scored again from our rules and
|
||||
compared with the points and multiplier flags N1MM wrote.
|
||||
|
||||
26 of the 37 instances whose contest we have rules for now agree on every
|
||||
contact and on the totals. What the check found and fixed:
|
||||
|
||||
| What | Was |
|
||||
|---|---|
|
||||
| ARRL DX and IARU read the wrong column | no multipliers at all, and IARU scored every contact 1 point |
|
||||
| a stored `" "` was read as a value | 181 contacts in one log scored as another continent |
|
||||
| the CQ WW RTTY area list | `NF` and `LB` are that contest's own names for the Canadian areas, and were not counted |
|
||||
| ARRL DX province spellings | `QB`, `NF` and `LB` count as Quebec and as Newfoundland and Labrador |
|
||||
| a maritime mobile scored nothing | it counts for no country and still scores by continent |
|
||||
| a contact in a mode the contest does not run | scored as if it were in the contest; N1MM scores it zero and keeps its multiplier |
|
||||
|
||||
What still differs, and why:
|
||||
|
||||
- **The country file of the day.** A 2019 log holds calls that today's
|
||||
`wl_cty.dat` places elsewhere, and the multiplier moves to another contact
|
||||
with it. This is most of the difference in the 2019 CQ WW SSB log.
|
||||
- **N1MM counts a call it cannot place as a multiplier with an empty value**,
|
||||
and we do not. Same as the WAE difference already written down.
|
||||
- **N1MM counts `NF` and `LB` as two ARRL DX multipliers.** They are one
|
||||
province, and we count one.
|
||||
- **A maritime mobile brings no country multiplier here**, which is the
|
||||
published CQ WW rule; N1MM counts one for it.
|
||||
- **Stale cached points.** N1MM caches points in the row and does not always
|
||||
work them out again after a callsign is corrected, so a handful of rows hold
|
||||
a number that its own rules do not produce.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# What is not finished, and what has not been tested
|
||||
|
||||
Two separate lists. A feature can be finished and untested, or half-built and
|
||||
exercised every day. Written 2026-08-27.
|
||||
exercised every day. Written 2026-08-27, updated 2026-08-31.
|
||||
|
||||
## Never run against the real thing
|
||||
|
||||
@@ -107,10 +107,24 @@ needs QTC traffic, IOTA needs island references as multipliers, and CQ WW RTTY
|
||||
needed a third multiplier and its own points table because it shares a name
|
||||
with the CW and SSB running of the contest.
|
||||
|
||||
What `.udc` cannot say here yet: an exchange that differs by the other
|
||||
station's country (the OK/OM district against a serial number from everyone
|
||||
else), points that depend on a zone or a distance, and multiplier sources
|
||||
beyond country, prefix, zone, section, exchange, grid and continent.
|
||||
`.udc` settings that are still passed over. `CallHist` as a multiplier source,
|
||||
which takes the value from the call history file. `BonusPoints2`, which reads
|
||||
the bonus callsigns from a file. `MultiplierBands`, `MultWindowType` and
|
||||
`QsoErrorString`, which are about the windows rather than the score.
|
||||
`CabrilloString`, `CabrilloFormat` and `GenericPrintString`, so a contest whose
|
||||
Cabrillo line is not callsign, report and one exchange value comes out in the
|
||||
default shape. The session, off-time and band-change settings
|
||||
(`MultipleSessions`, `MinimumOffTime`, the `…BandChange…` family,
|
||||
`DupeQSOMinutesAgo`) are read by nothing, so a contest with periods is logged
|
||||
as one long session.
|
||||
|
||||
N1MM's `.udc` format has no way to say that the exchange itself differs by the
|
||||
other station's country, as the OK/OM DX contest asks a district from OK and OM
|
||||
stations and a serial number from everyone else. That one needs code, as it
|
||||
does in N1MM, and `Contest.SkipsField` is where it goes. A contest scored by
|
||||
what this station sends — YOTA counts the sent exchange — needs code too, and
|
||||
reads `QsoContext.Entry`, which carries the entry categories and the sent
|
||||
exchange.
|
||||
|
||||
## Known rough edges
|
||||
|
||||
|
||||
Reference in New Issue
Block a user