awards
This commit is contained in:
+43
-1
@@ -152,7 +152,7 @@ func Migrate(defs []Def) ([]Def, bool) {
|
||||
func Fields() []string {
|
||||
return []string{
|
||||
"dxcc", "cqz", "ituz", "prefix", "callsign",
|
||||
"state", "cont", "country", "grid",
|
||||
"state", "cont", "country", "grid", "grid4",
|
||||
"iota", "sota_ref", "pota_ref", "wwff",
|
||||
"name", "qth", "address", "comment", "note",
|
||||
}
|
||||
@@ -421,6 +421,12 @@ func MatchQSO(d Def, metas []RefMeta, q *qso.QSO) []string {
|
||||
// sources (lotw|qsl|eqsl). Exported for the statistics view.
|
||||
func Confirmed(q *qso.QSO, sources []string) bool { return confirmed(q, sources) }
|
||||
|
||||
// InScope reports whether a QSO falls within an award's scope (DXCC entity,
|
||||
// bands, modes, emission, dates) — independent of whether a reference was
|
||||
// found. Used to surface "in scope but no reference" gaps (e.g. a French QSO
|
||||
// missing its department for DDFM).
|
||||
func InScope(d Def, q *qso.QSO) bool { return inScope(&d, q) }
|
||||
|
||||
// EmissionOf maps an ADIF mode to its broad category (CW|PHONE|DIGITAL).
|
||||
func EmissionOf(mode string) string { return emissionOf(mode) }
|
||||
|
||||
@@ -709,6 +715,11 @@ func fieldRaw(field string, q *qso.QSO) string {
|
||||
return q.Country
|
||||
case "grid":
|
||||
return q.Grid
|
||||
case "grid4":
|
||||
// VUCC: distinct 4-character grid squares. A QSO on a grid line carries
|
||||
// several in VUCC_GRIDS; otherwise the 4-char prefix of GRIDSQUARE. The
|
||||
// comma-joined result is split into one reference per square downstream.
|
||||
return grid4Refs(q)
|
||||
case "iota":
|
||||
return q.IOTA
|
||||
case "sota_ref":
|
||||
@@ -738,6 +749,37 @@ func fieldRaw(field string, q *qso.QSO) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// grid4Refs returns the distinct 4-character grid squares a QSO contributes —
|
||||
// from VUCC_GRIDS (a comma list when the contact straddles grid lines) if set,
|
||||
// else the 4-char prefix of GRIDSQUARE. Joined with commas so the matcher
|
||||
// counts each square separately (VUCC awards).
|
||||
func grid4Refs(q *qso.QSO) string {
|
||||
src := strings.TrimSpace(q.VUCCGrids)
|
||||
if src == "" {
|
||||
src = strings.TrimSpace(q.Grid)
|
||||
}
|
||||
if src == "" {
|
||||
return ""
|
||||
}
|
||||
seen := map[string]struct{}{}
|
||||
var out []string
|
||||
for _, tok := range strings.FieldsFunc(src, func(r rune) bool { return r == ',' || r == ';' || r == ' ' }) {
|
||||
g := strings.ToUpper(strings.TrimSpace(tok))
|
||||
if len(g) > 4 {
|
||||
g = g[:4]
|
||||
}
|
||||
if g == "" {
|
||||
continue
|
||||
}
|
||||
if _, ok := seen[g]; ok {
|
||||
continue
|
||||
}
|
||||
seen[g] = struct{}{}
|
||||
out = append(out, g)
|
||||
}
|
||||
return strings.Join(out, ",")
|
||||
}
|
||||
|
||||
func dxccAllowed(dxcc *int, filter []int) bool {
|
||||
if dxcc == nil {
|
||||
return false
|
||||
|
||||
@@ -128,6 +128,24 @@ func TestComputeMatchByDescription(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// VUCC: a grid4 award counts distinct 4-char grid squares, and a QSO on a grid
|
||||
// line (VUCC_GRIDS) contributes several. grid4 derives from VUCC_GRIDS else the
|
||||
// 4-char prefix of GRIDSQUARE.
|
||||
func TestComputeGrid4VUCC(t *testing.T) {
|
||||
def := Def{Code: "VUCC", Type: TypeGrid, Field: "grid4", Dynamic: true,
|
||||
Confirm: []string{"lotw", "qsl"}, Valid: true}
|
||||
qsos := []qso.QSO{
|
||||
{Callsign: "K1ABC", Band: "6m", Grid: "FN31PR", LOTWRcvd: "Y"}, // → FN31
|
||||
{Callsign: "W2DEF", Band: "6m", VUCCGrids: "FN20,FN21,FN30,FN31"}, // grid-line: 4 squares
|
||||
{Callsign: "W3GHI", Band: "2m", Grid: "FN20XX"}, // → FN20 (dup of above)
|
||||
}
|
||||
r := Compute([]Def{def}, qsos, nil, nil)[0]
|
||||
// Distinct squares: FN31, FN20, FN21, FN30 = 4
|
||||
if r.Worked != 4 {
|
||||
t.Errorf("VUCC worked = %d, want 4 (%v)", r.Worked, refCodes(r))
|
||||
}
|
||||
}
|
||||
|
||||
func refCodes(r Result) []string {
|
||||
out := make([]string, 0, len(r.Refs))
|
||||
for _, rf := range r.Refs {
|
||||
|
||||
Reference in New Issue
Block a user