Files
OpsLog/internal/contest/contest.go
T

91 lines
4.0 KiB
Go

// Package contest holds a curated catalogue of the major amateur-radio contests
// with their official ADIF CONTEST_ID codes and a default exchange kind. It is
// deliberately a built-in static list (not an online fetch): the ADIF code is
// what must be written to each logged QSO's CONTEST_ID, and those codes don't
// change — bundling them means correct codes, offline, no fragile scraping.
//
// The Exchange field is only a UI hint for what a station typically sends; the
// operator can always override it (serial vs fixed, and the fixed kind) when
// activating the contest.
package contest
import "sort"
// Exchange kinds (UI prefill for the sent/received exchange).
const (
ExSerial = "serial" // RST + running serial number
ExCQZone = "cq-zone" // RST + CQ zone
ExITUZone = "itu-zone" // RST + ITU zone
ExState = "state" // RST + state / province
ExDept = "dept" // RST + département (REF)
ExGrid = "grid" // RST + Maidenhead grid
ExName = "name" // name + state (NAQP-style)
ExClassSection = "class-section" // Field Day: class + ARRL/RAC section
ExRST = "rst" // RST only
)
// Def is one contest: its ADIF CONTEST_ID, a readable name, and the exchange a
// station typically sends.
type Def struct {
Code string `json:"code"`
Name string `json:"name"`
Exchange string `json:"exchange"`
}
// catalogue is the built-in list. Codes are ADIF CONTEST_ID values.
var catalogue = []Def{
{"CQ-WW-CW", "CQ WW DX Contest (CW)", ExCQZone},
{"CQ-WW-SSB", "CQ WW DX Contest (SSB)", ExCQZone},
{"CQ-WW-RTTY", "CQ WW DX RTTY Contest", ExCQZone},
{"CQ-WPX-CW", "CQ WPX Contest (CW)", ExSerial},
{"CQ-WPX-SSB", "CQ WPX Contest (SSB)", ExSerial},
{"CQ-WPX-RTTY", "CQ WPX RTTY Contest", ExSerial},
{"CQ-160-CW", "CQ 160-Meter Contest (CW)", ExState},
{"CQ-160-SSB", "CQ 160-Meter Contest (SSB)", ExState},
{"CQ-VHF", "CQ WW VHF Contest", ExGrid},
{"ARRL-DX-CW", "ARRL International DX Contest (CW)", ExState},
{"ARRL-DX-SSB", "ARRL International DX Contest (SSB)", ExState},
{"ARRL-10", "ARRL 10-Meter Contest", ExState},
{"ARRL-160", "ARRL 160-Meter Contest", ExState},
{"ARRL-SS-CW", "ARRL Sweepstakes (CW)", ExSerial},
{"ARRL-SS-SSB", "ARRL Sweepstakes (SSB)", ExSerial},
{"ARRL-FIELD-DAY", "ARRL Field Day", ExClassSection},
{"ARRL-RTTY", "ARRL RTTY Roundup", ExState},
{"ARRL-DIGI", "ARRL Digital Contest", ExGrid},
{"ARRL-VHF-JAN", "ARRL January VHF Contest", ExGrid},
{"ARRL-VHF-JUN", "ARRL June VHF Contest", ExGrid},
{"ARRL-VHF-SEP", "ARRL September VHF Contest", ExGrid},
{"ARRL-UHF-AUG", "ARRL August UHF Contest", ExGrid},
{"IARU-HF", "IARU HF World Championship", ExITUZone},
{"WAE-DX-CW", "WAE DX Contest (CW)", ExSerial},
{"WAE-DX-SSB", "WAE DX Contest (SSB)", ExSerial},
{"WAE-DX-RTTY", "WAE DX Contest (RTTY)", ExSerial},
{"NAQP-CW", "North American QSO Party (CW)", ExName},
{"NAQP-SSB", "North American QSO Party (SSB)", ExName},
{"NAQP-RTTY", "North American QSO Party (RTTY)", ExName},
{"STEW-PERRY", "Stew Perry Topband Challenge", ExGrid},
{"REF-CW", "REF Contest (CW)", ExDept},
{"REF-SSB", "REF Contest (SSB)", ExDept},
{"REF-160M", "REF 160m Contest", ExDept},
{"OCEANIA-DX-CW", "Oceania DX Contest (CW)", ExSerial},
{"OCEANIA-DX-SSB", "Oceania DX Contest (SSB)", ExSerial},
{"HELVETIA", "Helvetia Contest", ExSerial},
{"UKRAINIAN-DX", "Ukrainian DX Contest", ExSerial},
{"WW-DIGI", "World Wide Digi DX Contest", ExGrid},
{"EU-HF-C", "EU HF Championship", ExSerial},
{"DARC-WAEDC", "WAEDC", ExSerial},
// EME (Earth-Moon-Earth) contests — the exchange is a signal report (TMO /
// RST), so there's no serial or fixed multiplier to prefill.
{"ARRL-EME", "ARRL EME Contest", ExRST},
{"DUBUS-REF-EME", "Dubus & REF EME Contest", ExRST},
{"ARI-EME", "ARI EME Contest", ExRST},
}
// List returns the catalogue sorted by name (copy — callers must not mutate).
func List() []Def {
out := make([]Def, len(catalogue))
copy(out, catalogue)
sort.Slice(out, func(i, j int) bool { return out[i].Name < out[j].Name })
return out
}