From 8550b912554d769e1291d57684337838f2a339cb Mon Sep 17 00:00:00 2001 From: Joerg Date: Thu, 22 Jan 2026 08:25:13 +0100 Subject: [PATCH] feat: add DXCC SAT award for satellite-only QSOs Added new award "DXCC SAT" that only counts satellite QSOs (QSOs with satName field set). This adds a new "satellite_only" key to award definitions that filters to only include satellite communications. Award definition: - ID: dxcc-sat - Name: DXCC SAT - Target: 100 DXCC entities - Only satellite QSOs count Co-Authored-By: Claude --- award-definitions/dxcc-sat.json | 14 ++++++++++++++ src/backend/services/awards.service.js | 12 ++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 award-definitions/dxcc-sat.json diff --git a/award-definitions/dxcc-sat.json b/award-definitions/dxcc-sat.json new file mode 100644 index 0000000..38dec70 --- /dev/null +++ b/award-definitions/dxcc-sat.json @@ -0,0 +1,14 @@ +{ + "id": "dxcc-sat", + "name": "DXCC SAT", + "description": "Confirm 100 DXCC entities via satellite", + "caption": "Contact and confirm 100 different DXCC entities using satellite communications. Only satellite QSOs count toward this award. QSOs are confirmed when LoTW QSL is received.", + "category": "dxcc", + "rules": { + "type": "entity", + "entityType": "dxcc", + "target": 100, + "displayField": "entity", + "satellite_only": true + } +} diff --git a/src/backend/services/awards.service.js b/src/backend/services/awards.service.js index e78c9d3..0168922 100644 --- a/src/backend/services/awards.service.js +++ b/src/backend/services/awards.service.js @@ -22,6 +22,7 @@ function loadAwardDefinitions() { try { const files = [ 'dxcc.json', + 'dxcc-sat.json', 'was.json', 'vucc-sat.json', 'sat-rs44.json', @@ -145,6 +146,12 @@ export async function calculateAwardProgress(userId, award, options = {}) { logger.debug('QSOs after allowed_bands filter', { count: finalQSOs.length }); } + // Apply satellite_only filter if present + if (rules.satellite_only) { + finalQSOs = finalQSOs.filter(qso => qso.satName); + logger.debug('QSOs after satellite_only filter', { count: finalQSOs.length }); + } + // Calculate worked and confirmed entities const workedEntities = new Set(); const confirmedEntities = new Set(); @@ -723,6 +730,11 @@ export async function getAwardEntityBreakdown(userId, awardId) { }); } + // Apply satellite_only filter if present + if (rules.satellite_only) { + finalQSOs = finalQSOs.filter(qso => qso.satName); + } + // Group by (entity, band, mode) slot for entity awards // This allows showing multiple QSOs per entity on different bands/modes const slotMap = new Map(); // Key: "entity/band/mode" -> slot object