feat: add allowed_bands filter to award definitions
Adds a new "allowed_bands" key to award definitions that restricts which bands count toward an award. If absent, all bands are allowed (default behavior). Applied to DXCC award to only count HF bands (160m-10m), excluding VHF/UHF bands like 6m, 2m, and 70cm. Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -1,13 +1,14 @@
|
|||||||
{
|
{
|
||||||
"id": "dxcc",
|
"id": "dxcc",
|
||||||
"name": "DXCC",
|
"name": "DXCC",
|
||||||
"description": "Confirm 100 DXCC entities on any band/mode",
|
"description": "Confirm 100 DXCC entities on HF bands",
|
||||||
"caption": "Contact and confirm 100 different DXCC entities. Any band and mode combination counts. QSOs are confirmed when LoTW QSL is received.",
|
"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",
|
"category": "dxcc",
|
||||||
"rules": {
|
"rules": {
|
||||||
"type": "entity",
|
"type": "entity",
|
||||||
"entityType": "dxcc",
|
"entityType": "dxcc",
|
||||||
"target": 100,
|
"target": 100,
|
||||||
"displayField": "entity"
|
"displayField": "entity",
|
||||||
|
"allowed_bands": ["160m", "80m", "60m", "40m", "30m", "20m", "17m", "15m", "12m", "10m"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -139,11 +139,21 @@ export async function calculateAwardProgress(userId, award, options = {}) {
|
|||||||
logger.debug('QSOs after filters', { count: filteredQSOs.length });
|
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
|
// Calculate worked and confirmed entities
|
||||||
const workedEntities = new Set();
|
const workedEntities = new Set();
|
||||||
const confirmedEntities = new Set();
|
const confirmedEntities = new Set();
|
||||||
|
|
||||||
for (const qso of filteredQSOs) {
|
for (const qso of finalQSOs) {
|
||||||
const entity = getEntityValue(qso, rules.entityType);
|
const entity = getEntityValue(qso, rules.entityType);
|
||||||
|
|
||||||
if (entity) {
|
if (entity) {
|
||||||
@@ -708,11 +718,20 @@ export async function getAwardEntityBreakdown(userId, awardId) {
|
|||||||
// Apply filters
|
// Apply filters
|
||||||
const filteredQSOs = applyFilters(allQSOs, rules.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
|
// Group by (entity, band, mode) slot for entity awards
|
||||||
// This allows showing multiple QSOs per entity on different bands/modes
|
// This allows showing multiple QSOs per entity on different bands/modes
|
||||||
const slotMap = new Map(); // Key: "entity/band/mode" -> slot object
|
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);
|
const entity = getEntityValue(qso, rules.entityType);
|
||||||
|
|
||||||
if (!entity) continue;
|
if (!entity) continue;
|
||||||
|
|||||||
Reference in New Issue
Block a user