award
This commit is contained in:
@@ -0,0 +1,98 @@
|
||||
// Shared helpers for per-QSO award references.
|
||||
//
|
||||
// In the UI a QSO's manually-assigned award references are edited as a single
|
||||
// semicolon-delimited string of "CODE@REF" entries, e.g.
|
||||
// "POTA@FR-11553;IOTA@EU-064"
|
||||
// On save each entry is routed to the QSO field its award actually reads from
|
||||
// (see internal/award/award.go): POTA/SOTA/IOTA have dedicated columns; WWFF
|
||||
// and custom awards live in uppercase ADIF extras keys.
|
||||
|
||||
// parseAwardRefs turns "POTA@FR-11553;IOTA@EU-064" into
|
||||
// { POTA: "FR-11553", IOTA: "EU-064" }. Repeated codes join with commas.
|
||||
export function parseAwardRefs(v: string): Record<string, string> {
|
||||
const out: Record<string, string> = {};
|
||||
for (const entry of (v ?? '').split(';').filter(Boolean)) {
|
||||
const at = entry.indexOf('@');
|
||||
if (at <= 0) continue;
|
||||
const code = entry.slice(0, at).toUpperCase();
|
||||
const ref = entry.slice(at + 1).trim().toUpperCase();
|
||||
if (!ref) continue;
|
||||
out[code] = out[code] ? `${out[code]},${ref}` : ref;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
// appendTokens adds space-separated tokens (a "A,B" ref string) to a text field,
|
||||
// skipping any already present, so re-picking is idempotent.
|
||||
function appendTokens(existing: string | undefined, refs: string): string {
|
||||
let out = (existing ?? '').trim();
|
||||
for (const tok of refs.split(',').map((s) => s.trim()).filter(Boolean)) {
|
||||
const re = new RegExp(`(^|\\s)${tok.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}(\\s|$)`, 'i');
|
||||
if (!re.test(out)) out = out ? `${out} ${tok}` : tok;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
// applyAwardRefs writes picked references onto a QSO payload using each award's
|
||||
// scanned field. fieldOf maps an award CODE (uppercase) to its field name.
|
||||
export function applyAwardRefs(payload: any, awardRefs: string, fieldOf: Record<string, string>) {
|
||||
const byCode = parseAwardRefs(awardRefs);
|
||||
const extras: Record<string, string> = { ...(payload.extras ?? {}) };
|
||||
for (const [code, ref] of Object.entries(byCode)) {
|
||||
const field = fieldOf[code] || code.toLowerCase();
|
||||
switch (field) {
|
||||
case 'iota': payload.iota = ref; break;
|
||||
case 'sota_ref': payload.sota_ref = ref; break;
|
||||
case 'pota_ref': payload.pota_ref = ref; break;
|
||||
case 'wwff':
|
||||
extras['WWFF_REF'] = ref;
|
||||
extras['SIG'] = 'WWFF';
|
||||
extras['SIG_INFO'] = ref;
|
||||
break;
|
||||
// QSOFIELDS awards read their reference from a free-text field (e.g. DDFM
|
||||
// scans the note for "D06"). Picking such a reference appends its code(s)
|
||||
// to that field so the matcher finds it.
|
||||
case 'note': case 'notes':
|
||||
payload.notes = appendTokens(payload.notes, ref);
|
||||
break;
|
||||
case 'comment':
|
||||
payload.comment = appendTokens(payload.comment, ref);
|
||||
break;
|
||||
default:
|
||||
extras[field.toUpperCase()] = ref;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (Object.keys(extras).length > 0) payload.extras = extras;
|
||||
}
|
||||
|
||||
// awardRefValue reads a single award's stored reference from a QSO, inverse of
|
||||
// applyAwardRefs. Used to seed the editor when opening an existing QSO.
|
||||
export function awardRefValue(qso: any, code: string, field: string): string {
|
||||
switch (field) {
|
||||
case 'iota': return (qso.iota ?? '').toUpperCase();
|
||||
case 'sota_ref': return (qso.sota_ref ?? '').toUpperCase();
|
||||
case 'pota_ref': return (qso.pota_ref ?? '').toUpperCase();
|
||||
case 'wwff': {
|
||||
const ex = qso.extras ?? {};
|
||||
if (ex['WWFF_REF']) return String(ex['WWFF_REF']).toUpperCase();
|
||||
if (String(ex['SIG'] ?? '').toUpperCase() === 'WWFF') return String(ex['SIG_INFO'] ?? '').toUpperCase();
|
||||
return '';
|
||||
}
|
||||
default: {
|
||||
const ex = qso.extras ?? {};
|
||||
return String(ex[field.toUpperCase()] ?? '').toUpperCase();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// buildAwardRefs reconstructs the "CODE@REF;…" editor string from a QSO for the
|
||||
// given pickable awards (code → field). Only awards with a stored value appear.
|
||||
export function buildAwardRefs(qso: any, pickable: Array<{ code: string; field: string }>): string {
|
||||
const out: string[] = [];
|
||||
for (const { code, field } of pickable) {
|
||||
const v = awardRefValue(qso, code, field);
|
||||
if (v) out.push(`${code.toUpperCase()}@${v}`);
|
||||
}
|
||||
return out.join(';');
|
||||
}
|
||||
Reference in New Issue
Block a user