# HG changeset patch # User Josef 'Jeff' Sipek # Date 1688411413 14400 # Mon Jul 03 15:10:13 2023 -0400 # Node ID 1faecf267ffec92dc39fc0f6db4bc6da826fb33d # Parent d2f26abb0a0bbd2ef843257b15d49c43e7aa1735 xlua: a very rudimentary K1USN SST contest script Signed-off-by: Josef 'Jeff' Sipek diff --git a/xlua/CMakeLists.txt b/xlua/CMakeLists.txt --- a/xlua/CMakeLists.txt +++ b/xlua/CMakeLists.txt @@ -25,6 +25,7 @@ contests/ARRL-VHF-JUN contests/ARRL-VHF-SEP contests/CQ-WW-VHF + contests/K1USN-SST contests/NEQP contests/POTA startup-stats diff --git a/xlua/scripts/.hgignore b/xlua/scripts/.hgignore --- a/xlua/scripts/.hgignore +++ b/xlua/scripts/.hgignore @@ -2,6 +2,7 @@ contests/ARRL-VHF-{JAN,JUN,SEP}.{luac,c} contests/CQ-WW-VHF.{luac,c} +contests/K1USN-SST.{luac,c} contests/NEQP.{luac,c} contests/POTA.{luac,c} startup-stats.{luac,c} diff --git a/xlua/scripts/contests/K1USN-SST.lua b/xlua/scripts/contests/K1USN-SST.lua new file mode 100644 --- /dev/null +++ b/xlua/scripts/contests/K1USN-SST.lua @@ -0,0 +1,167 @@ +-- +-- Copyright (c) 2023 Josef 'Jeff' Sipek +-- +-- Permission is hereby granted, free of charge, to any person obtaining a copy +-- of this software and associated documentation files (the "Software"), to deal +-- in the Software without restriction, including without limitation the rights +-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +-- copies of the Software, and to permit persons to whom the Software is +-- furnished to do so, subject to the following conditions: +-- +-- The above copyright notice and this permission notice shall be included in +-- all copies or substantial portions of the Software. +-- +-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +-- SOFTWARE. +-- + +-- Rules & info at http://www.k1usn.com/sst.html + +local allowed_bands = { + [160000] = true, + [80000] = true, + [40000] = true, + [20000] = true, + [15000] = true, + [10000] = true, +} + +local function hash(qso) + return string.format("%s-%u", qso.rx.station_call, qso.rx.band) +end + +local function getmult(qso) + if qso.rx.dxcc == 1 or qso.rx.dxcc == 291 then + return string.format("ST:%s", qso.rx.state) + else + return string.format("DX:%u", qso.rx.dxcc) + end +end + +local function export_qso(qso, qs, mults) + local key = hash(qso) + local mult = getmult(qso) + + qs[key] = qso + mults[mult] = true +end + +local function export(outfile) + local days = {} + local mults = {} + local qs = {} + + for qso in hlog.index.history(true) do + if qso.additional['contest-id'] == 'K1USN-SST' then + local day = string.format('%04u-%02u-%02u', qso.start_time.year, + qso.start_time.month, qso.start_time.day) + + if mults[day] == nil then + mults[day] = {} + end + if qs[day] == nil then + qs[day] = {} + end + + export_qso(qso, qs[day], mults[day]) + end + end + + for _, day in ipairs(hlog.utils.sorted_keys(qs)) do + local m = mults[day] + local q = qs[day] + + local nm = hlog.utils.count_items(m) + local nq = hlog.utils.count_items(q) + + print(string.format("K1USN SST %s: %2u Qs * %2u Mults = %u", + day, nq, nm, nq * nm)) + end +end + +local function startup_fill_template(template) + print("K1USN SST contest script") + + local state + local name + + repeat + print() + print("Enter name used in contest (e.g., Jeff):") + + name = io.stdin:read() + if name == "" then + print("Name cannot be empty.") + next() + else + name = name:upper() + end + until name ~= nil + + repeat + print() + print("Enter state abbreviation (e.g., MA):") + + state = io.stdin:read() + state = state:upper() + until state ~= nil + + local exch = string.format("%s %s", name, state) + + print("Using exchange: " .. exch) + template.tx.state = state -- FIXME: US/CA only + template.additional['contest-id'] = 'K1USN-SST' + template.additional['contest-tx'] = exch + + contest.lcd(exch) +end + +local function field_changed(qso, fields, field) + local value = fields[field] + + if field == "rx.station_call" then + qso.rx.station_call = value + elseif field == "rx.name" then + qso.rx.name = value + + qso.additional['contest-rx'] = string.format("%s %s", qso.rx.name:upper(), qso.rx.state) + elseif field == "rx.state" then + value = value:upper() + if value ~= "DX" then + qso.rx.state = value + end + + qso.additional['contest-rx'] = string.format("%s %s", qso.rx.name:upper(), qso.rx.state) + elseif field == "comment" then + qso.comment = value + else + error(string.format("Unknown field '%s' encountered", field)) + end +end + +return { + labels = { + { 0, 0, "St. Call" }, + { 0, 11, "Name" }, + { 0, 25, "St" }, + { 0, 28, "Comment" }, + }, + + fields = { + { 1, 0, 10, "rx.station_call", }, + { 1, 11, 13, "rx.name", }, + { 1, 25, 2, "rx.state", }, + { 1, 28, 24, "comment", }, + }, + + events = { + export = export, + startup = startup_fill_template, + field_changed = field_changed, + }, +}