docs: update CLAUDE.md with recent bug fixes and improvements

- Documented critical ADIF parser fix for case-insensitive EOR delimiter
- Added LoTW duplicate detection fix (missing timeOn field)
- Documented DOK award filter support with examples
- Updated ADIF Parser section with implementation details
- Updated ADIF Format section with case-insensitive delimiter note

Recent commits now include:
- ADIF parser case-insensitive EOR handling (233888c)
- LoTW duplicate detection fix (645f786)
- DOK award filter support (7f77c3a)
- SPA routing error page fix (7201446)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-18 08:32:16 +01:00
parent af43f8954c
commit 0020f0318d

View File

@@ -183,6 +183,9 @@ The award system is JSON-driven and located in `award-definitions/` directory. E
**ADIF Parser**: `src/backend/utils/adif-parser.js` **ADIF Parser**: `src/backend/utils/adif-parser.js`
- `parseADIF(adifData)`: Parse ADIF format into QSO records - `parseADIF(adifData)`: Parse ADIF format into QSO records
- Handles case-insensitive `<EOR>` delimiters (supports `<EOR>`, `<eor>`, `<Eor>`)
- Uses `matchAll()` for reliable field parsing
- Skips header records automatically
- `parseDCLResponse(response)`: Parse DCL's JSON response format `{ "adif": "..." }` - `parseDCLResponse(response)`: Parse DCL's JSON response format `{ "adif": "..." }`
- `normalizeBand(band)`: Standardize band names (80m, 40m, etc.) - `normalizeBand(band)`: Standardize band names (80m, 40m, etc.)
- `normalizeMode(mode)`: Standardize mode names (CW, FT8, SSB, etc.) - `normalizeMode(mode)`: Standardize mode names (CW, FT8, SSB, etc.)
@@ -384,9 +387,10 @@ The DOK award type supports filters to create award variants. Examples:
Both LoTW and DCL return data in ADIF (Amateur Data Interchange Format): Both LoTW and DCL return data in ADIF (Amateur Data Interchange Format):
- Field format: `<FIELD_NAME:length>value` - Field format: `<FIELD_NAME:length>value`
- Record delimiter: `<EOR>` (end of record) - Record delimiter: `<EOR>` (end of record, case-insensitive)
- Header ends with: `<EOH>` (end of header) - Header ends with: `<EOH>` (end of header)
- Example: `<CALL:5>DK0MU<BAND:3>80m<QSO_DATE:8>20250621<EOR>` - Example: `<CALL:5>DK0MU<BAND:3>80m<QSO_DATE:8>20250621<EOR>`
- **Important**: Parser handles case-insensitive `<EOR>`, `<eor>`, `<Eor>` tags
**DCL-specific fields**: **DCL-specific fields**:
- `DCL_QSL_RCVD`: DCL confirmation status (Y/N/?) - `DCL_QSL_RCVD`: DCL confirmation status (Y/N/?)
@@ -397,6 +401,22 @@ Both LoTW and DCL return data in ADIF (Amateur Data Interchange Format):
### Recent Commits ### Recent Commits
- `233888c`: fix: make ADIF parser case-insensitive for EOR delimiter
- **Critical bug**: LoTW uses lowercase `<eor>` tags, parser was splitting on uppercase `<EOR>`
- Caused 242K+ QSOs to be parsed as 1 giant record with fields overwriting each other
- Changed to case-insensitive regex: `new RegExp('<eor>', 'gi')`
- Replaced `regex.exec()` while loop with `matchAll()` for-of iteration
- Now correctly imports all QSOs from large LoTW reports
- `645f786`: fix: add missing timeOn field to LoTW duplicate detection
- LoTW sync was missing `timeOn` in duplicate detection query
- Multiple QSOs with same callsign/date/band/mode but different times were treated as duplicates
- Now matches DCL sync logic: `userId, callsign, qsoDate, timeOn, band, mode`
- `7f77c3a`: feat: add filter support for DOK awards
- DOK award type now supports filtering by band, mode, and other QSO fields
- Allows creating award variants like DLD 80m, DLD CW, DLD 80m CW
- Uses existing filter system with eq, ne, in, nin, contains operators
- Example awards created: dld-80m, dld-40m, dld-cw, dld-80m-cw
- `9e73704`: docs: update CLAUDE.md with DLD award variants documentation
- `7201446`: fix: return proper HTML for SPA routes instead of Bun error page - `7201446`: fix: return proper HTML for SPA routes instead of Bun error page
- When accessing client-side routes (like /qsos) via curl or non-JS clients, - When accessing client-side routes (like /qsos) via curl or non-JS clients,
the server attempted to open them as static files, causing Bun to throw the server attempted to open them as static files, causing Bun to throw