feat: add filter support for DOK awards
The DOK award type (used for DLD award) now supports filtering by band, mode, and other QSO fields. This allows creating award variants like: - DLD on specific bands (80m, 40m, etc.) - DLD on specific modes (CW, SSB, etc.) - DLD with combined filters (e.g., 80m + CW) Changes: - Modified calculateDOKAwardProgress() to apply filters before processing - Added example awards: dld-80m, dld-40m, dld-cw, dld-80m-cw - Filter system uses existing applyFilters() function Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
19
award-definitions/dld-40m.json
Normal file
19
award-definitions/dld-40m.json
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"id": "dld-40m",
|
||||||
|
"name": "DLD 40m",
|
||||||
|
"description": "Confirm 100 unique DOKs on 40m",
|
||||||
|
"caption": "Contact and confirm stations with 100 unique DOKs (DARC Ortsverband Kennung) on the 40m band. Only DCL-confirmed QSOs with valid DOK information on 40m count toward this award.",
|
||||||
|
"category": "darc",
|
||||||
|
"rules": {
|
||||||
|
"type": "dok",
|
||||||
|
"target": 100,
|
||||||
|
"confirmationType": "dcl",
|
||||||
|
"displayField": "darcDok",
|
||||||
|
"filters": {
|
||||||
|
"operator": "AND",
|
||||||
|
"filters": [
|
||||||
|
{ "field": "band", "operator": "eq", "value": "40m" }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
20
award-definitions/dld-80m-cw.json
Normal file
20
award-definitions/dld-80m-cw.json
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"id": "dld-80m-cw",
|
||||||
|
"name": "DLD 80m CW",
|
||||||
|
"description": "Confirm 100 unique DOKs on 80m using CW",
|
||||||
|
"caption": "Contact and confirm stations with 100 unique DOKs (DARC Ortsverband Kennung) on the 80m band using CW mode. Only DCL-confirmed QSOs with valid DOK information on 80m CW count toward this award.",
|
||||||
|
"category": "darc",
|
||||||
|
"rules": {
|
||||||
|
"type": "dok",
|
||||||
|
"target": 100,
|
||||||
|
"confirmationType": "dcl",
|
||||||
|
"displayField": "darcDok",
|
||||||
|
"filters": {
|
||||||
|
"operator": "AND",
|
||||||
|
"filters": [
|
||||||
|
{ "field": "band", "operator": "eq", "value": "80m" },
|
||||||
|
{ "field": "mode", "operator": "eq", "value": "CW" }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
19
award-definitions/dld-80m.json
Normal file
19
award-definitions/dld-80m.json
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"id": "dld-80m",
|
||||||
|
"name": "DLD 80m",
|
||||||
|
"description": "Confirm 100 unique DOKs on 80m",
|
||||||
|
"caption": "Contact and confirm stations with 100 unique DOKs (DARC Ortsverband Kennung) on the 80m band. Only DCL-confirmed QSOs with valid DOK information on 80m count toward this award.",
|
||||||
|
"category": "darc",
|
||||||
|
"rules": {
|
||||||
|
"type": "dok",
|
||||||
|
"target": 100,
|
||||||
|
"confirmationType": "dcl",
|
||||||
|
"displayField": "darcDok",
|
||||||
|
"filters": {
|
||||||
|
"operator": "AND",
|
||||||
|
"filters": [
|
||||||
|
{ "field": "band", "operator": "eq", "value": "80m" }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
19
award-definitions/dld-cw.json
Normal file
19
award-definitions/dld-cw.json
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"id": "dld-cw",
|
||||||
|
"name": "DLD CW",
|
||||||
|
"description": "Confirm 100 unique DOKs using CW mode",
|
||||||
|
"caption": "Contact and confirm stations with 100 unique DOKs (DARC Ortsverband Kennung) using CW (Morse code). Each unique DOK on CW counts separately. Only DCL-confirmed QSOs with valid DOK information count toward this award.",
|
||||||
|
"category": "darc",
|
||||||
|
"rules": {
|
||||||
|
"type": "dok",
|
||||||
|
"target": 100,
|
||||||
|
"confirmationType": "dcl",
|
||||||
|
"displayField": "darcDok",
|
||||||
|
"filters": {
|
||||||
|
"operator": "AND",
|
||||||
|
"filters": [
|
||||||
|
{ "field": "mode", "operator": "eq", "value": "CW" }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -27,6 +27,10 @@ function loadAwardDefinitions() {
|
|||||||
'sat-rs44.json',
|
'sat-rs44.json',
|
||||||
'special-stations.json',
|
'special-stations.json',
|
||||||
'dld.json',
|
'dld.json',
|
||||||
|
'dld-80m.json',
|
||||||
|
'dld-40m.json',
|
||||||
|
'dld-cw.json',
|
||||||
|
'dld-80m-cw.json',
|
||||||
];
|
];
|
||||||
|
|
||||||
for (const file of files) {
|
for (const file of files) {
|
||||||
@@ -173,9 +177,9 @@ export async function calculateAwardProgress(userId, award, options = {}) {
|
|||||||
async function calculateDOKAwardProgress(userId, award, options = {}) {
|
async function calculateDOKAwardProgress(userId, award, options = {}) {
|
||||||
const { includeDetails = false } = options;
|
const { includeDetails = false } = options;
|
||||||
const { rules } = award;
|
const { rules } = award;
|
||||||
const { target, displayField } = rules;
|
const { target, displayField, filters } = rules;
|
||||||
|
|
||||||
logger.debug('Calculating DOK-based award progress', { userId, awardId: award.id, target });
|
logger.debug('Calculating DOK-based award progress', { userId, awardId: award.id, target, hasFilters: !!filters });
|
||||||
|
|
||||||
// Get all QSOs for user
|
// Get all QSOs for user
|
||||||
const allQSOs = await db
|
const allQSOs = await db
|
||||||
@@ -185,10 +189,17 @@ async function calculateDOKAwardProgress(userId, award, options = {}) {
|
|||||||
|
|
||||||
logger.debug('Total QSOs for user', { count: allQSOs.length });
|
logger.debug('Total QSOs for user', { count: allQSOs.length });
|
||||||
|
|
||||||
|
// Apply filters if defined
|
||||||
|
let filteredQSOs = allQSOs;
|
||||||
|
if (filters) {
|
||||||
|
filteredQSOs = applyFilters(allQSOs, filters);
|
||||||
|
logger.debug('QSOs after DOK award filters', { count: filteredQSOs.length });
|
||||||
|
}
|
||||||
|
|
||||||
// Track unique (DOK, band, mode) combinations
|
// Track unique (DOK, band, mode) combinations
|
||||||
const dokCombinations = new Map(); // Key: "DOK/band/mode" -> detail object
|
const dokCombinations = new Map(); // Key: "DOK/band/mode" -> detail object
|
||||||
|
|
||||||
for (const qso of allQSOs) {
|
for (const qso of filteredQSOs) {
|
||||||
const dok = qso.darcDok;
|
const dok = qso.darcDok;
|
||||||
if (!dok) continue; // Skip QSOs without DOK
|
if (!dok) continue; // Skip QSOs without DOK
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user