diff --git a/award-definitions/dxcc.json b/award-definitions/dxcc.json index a0b79f2..89e5f32 100644 --- a/award-definitions/dxcc.json +++ b/award-definitions/dxcc.json @@ -1,13 +1,14 @@ { "id": "dxcc", "name": "DXCC", - "description": "Confirm 100 DXCC entities on any band/mode", - "caption": "Contact and confirm 100 different DXCC entities. Any band and mode combination counts. QSOs are confirmed when LoTW QSL is received.", + "description": "Confirm 100 DXCC entities on HF bands", + "caption": "Contact and confirm 100 different DXCC entities on HF bands (160m-10m). Only HF band QSOs count toward this award. QSOs are confirmed when LoTW QSL is received.", "category": "dxcc", "rules": { "type": "entity", "entityType": "dxcc", "target": 100, - "displayField": "entity" + "displayField": "entity", + "allowed_bands": ["160m", "80m", "60m", "40m", "30m", "20m", "17m", "15m", "12m", "10m"] } } diff --git a/src/backend/services/awards.service.js b/src/backend/services/awards.service.js index 88dd5d7..1ea5a15 100644 --- a/src/backend/services/awards.service.js +++ b/src/backend/services/awards.service.js @@ -139,11 +139,21 @@ export async function calculateAwardProgress(userId, award, options = {}) { logger.debug('QSOs after filters', { count: filteredQSOs.length }); } + // Apply allowed_bands filter if present + let finalQSOs = filteredQSOs; + if (rules.allowed_bands && Array.isArray(rules.allowed_bands) && rules.allowed_bands.length > 0) { + finalQSOs = filteredQSOs.filter(qso => { + const band = qso.band; + return rules.allowed_bands.includes(band); + }); + logger.debug('QSOs after allowed_bands filter', { count: finalQSOs.length }); + } + // Calculate worked and confirmed entities const workedEntities = new Set(); const confirmedEntities = new Set(); - for (const qso of filteredQSOs) { + for (const qso of finalQSOs) { const entity = getEntityValue(qso, rules.entityType); if (entity) { @@ -708,11 +718,20 @@ export async function getAwardEntityBreakdown(userId, awardId) { // Apply filters const filteredQSOs = applyFilters(allQSOs, rules.filters); + // Apply allowed_bands filter if present + let finalQSOs = filteredQSOs; + if (rules.allowed_bands && Array.isArray(rules.allowed_bands) && rules.allowed_bands.length > 0) { + finalQSOs = filteredQSOs.filter(qso => { + const band = qso.band; + return rules.allowed_bands.includes(band); + }); + } + // 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 - for (const qso of filteredQSOs) { + for (const qso of finalQSOs) { const entity = getEntityValue(qso, rules.entityType); if (!entity) continue;