# HG changeset patch # User Josef 'Jeff' Sipek # Date 1727354245 14400 # Thu Sep 26 08:37:25 2024 -0400 # Node ID e0ba19d76360dd692df22c2e97f7b61144a6f321 # Parent f5ab3ea9e7ec38e9cdbe15e4163b4473378c482d WIP: xlua: grid-based contests diff --git a/docs/lua-hlog-module.md b/docs/lua-hlog-module.md --- a/docs/lua-hlog-module.md +++ b/docs/lua-hlog-module.md @@ -58,6 +58,9 @@ ### `county(...)` TODO +### `grid(...}` +TODO + hlog.country ------------ diff --git a/xlua/CMakeLists.txt b/xlua/CMakeLists.txt --- a/xlua/CMakeLists.txt +++ b/xlua/CMakeLists.txt @@ -31,6 +31,7 @@ contests/NHQP contests/POTA helper-county + helper-grid prompt set startup-stats diff --git a/xlua/scripts/.hgignore b/xlua/scripts/.hgignore --- a/xlua/scripts/.hgignore +++ b/xlua/scripts/.hgignore @@ -8,6 +8,7 @@ contests/NHQP.{luac,c} contests/POTA.{luac,c} helper-county.{luac,c} +helper-grid.{luac,c} prompt.{luac,c} set.{luac,c} startup-stats.{luac,c} diff --git a/xlua/scripts/helper-grid.lua b/xlua/scripts/helper-grid.lua new file mode 100644 --- /dev/null +++ b/xlua/scripts/helper-grid.lua @@ -0,0 +1,159 @@ +-- +-- Copyright (c) 2024-2025 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. +-- + +local mt = { } + +local function grid(name, year, duphash) + local out = { } + + out['name'] = name -- contest name + out['year'] = year -- contest year + out['dups'] = hlog.set.new() -- set of dup hashes + + -- set up an object with the data + local obj = { + data = out, + duphash = duphash, + } + + setmetatable(obj, mt) + + return obj +end + +local function qso_load(self, qso, tx, rx) + local map = self.data + + tx = tx ~= nil and tx or qso.tx.grid + rx = rx ~= nil and rx or qso.rx.grid + + map['dups']:add(self.duphash(qso, tx, rx)) +end + +local function qso_done(self, qso, tx, rx) + local map = self.data + + qso.additional['contest-id'] = map['name'] + qso.additional['contest-year'] = map['year'] + + self:qso_load(qso, tx, rx) +end + +-- is the passed in qso a duplicate with a previous qso? +local function is_dup(self, qso, tx, rx) + local map = self.data + + tx = tx ~= nil and tx or qso.tx.grid + rx = rx ~= nil and rx or qso.rx.grid + + return map['dups']:has(self.duphash(qso, tx, rx)) +end + +local function export_prep(self, id, year, qpoints, qmult, qexchange) + local function do_add_entry(tx, rx, args) + local qp = args[1] + local all = args[2] + local ops = args[3] + local points = args[4] + local mults = args[5] + local qso = args[6] + + local tx_exch, tx_exch_ok = qexchange(qso.tx, tx) + local rx_exch, rx_exch_ok = qexchange(qso.rx, rx) + + -- accumulate points + if not self:is_dup(qso, tx, rx) and tx_exch_ok and rx_exch_ok then + points[1] = points[1] + qpoints(qso, tx, rx) + end + + -- add the mult + local m = qmult(qso, tx, rx) + if m ~= nil then + mults:add(m) + end + + -- add to list of all QSOs + table.insert(all, { qso, tx_exch, rx_exch, tx_exch_ok and rx_exch_ok }) + + -- stash for future dup detection + self:qso_done(qso, tx, rx) + + -- keep track of the operators + ops:add(qso.tx.operator_call) + end + + local function add_entry(id, year, station, all, ops, points, mults, qso) + if qso.additional['contest-id'] ~= id or + qso.additional['contest-year'] ~= year then + return + end + + if qso.tx.band == nil then + print(string.format("Error: %s QSO lacks band info", qso.uuid)) + return + end + + assert(qso.tx.station_call ~= nil) + station:add(qso.tx.station_call) + + hlog.utils.each_with_each(qso.tx.grid, + qso.rx.grid, + "+", do_add_entry, + { self, all, ops, points, mults, qso }) + end + + local station = hlog.set.new() + local all = {} + local ops = hlog.set.new() + local points = { 0 } + local mults = hlog.set.new() + + for qso in hlog.index.history(true) do + add_entry(id, year, station, all, ops, points, mults, qso) + end + + if station:count_items() ~= 1 then + error(string.format("Error: more than one station callsign used: %s", + station:tostring())) + end + + station = hlog.utils.join_ipairs(station:as_array(), ",") -- should be only 1 element + points = points[1] + + return all, station, ops, points, mults +end + +local function tostring(self) + return "Grid{" .. self.data:tostring() .. "}" +end + +mt.__index = { + qso_load = qso_load, + qso_done = qso_done, + is_dup = is_dup, + export_prep = export_prep, + tostring = tostring, +} + +return { + grid = grid, +} diff --git a/xlua/xlua.c b/xlua/xlua.c --- a/xlua/xlua.c +++ b/xlua/xlua.c @@ -68,6 +68,7 @@ { lua_newtable(L); xlua_merge_lua_funcs(L, "helper-county.lua"); + xlua_merge_lua_funcs(L, "helper-grid.lua"); } static void xlua_register(lua_State *L)