feat: H26 award recognises each canton by its main cities (regex per reference)

Operators rarely write the canton in their address/QTH but do write the city.
Add a per-reference city regex to every one of the 26 cantons (same mechanism as
WAPC): the description match now fires on the canton NAME or any of its main
cities (Genève→GE, Lausanne→VD, Zürich→ZH, Bellinzona→TI, …), with accented and
ASCII/localised spellings. Scoped to DXCC 287 so cross-border city-name clashes
can't misfire. Catalog version bumped 1→2 so the update reaches anyone already
running H26 v1 (unless they've edited it).
This commit is contained in:
2026-07-24 16:29:59 +02:00
parent 3ea7f44fd1
commit bf4fba484a
2 changed files with 30 additions and 4 deletions
+2 -2
View File
@@ -4,7 +4,7 @@
"date": "2026-07-24", "date": "2026-07-24",
"en": [ "en": [
"Fixed a motorized-antenna bug that could leave a FlexRadio permanently unable to transmit (Interlock is preventing transmission). With a SteppIR whose status frequency reads intermittently (it flipped between the commanded frequency and its home value), the follow the rig loop re-sent a tune command on almost every poll, and each command re-armed the block TX while the antenna moves window — so the interlock never released. The follow loop now keys its deadband off the rigs frequency (only re-tuning when the RADIO actually QSYs), immune to a flaky antenna status. Also dropped an interlock set reason= command that SmartSDR rejects (its read-only) and only produced a harmless error line — the transmit-inhibit itself is unchanged and still holds TX safely while the elements move. New: a SteppIR Tunable range setting (Settings → Hardware → Antenna, default 1354 MHz = 20 m6 m) — on a band outside it OpsLog leaves the antenna and TX completely alone, so tuning to 30 m on a 20 m6 m SteppIR no longer tries to move it or touches the interlock.", "Fixed a motorized-antenna bug that could leave a FlexRadio permanently unable to transmit (Interlock is preventing transmission). With a SteppIR whose status frequency reads intermittently (it flipped between the commanded frequency and its home value), the follow the rig loop re-sent a tune command on almost every poll, and each command re-armed the block TX while the antenna moves window — so the interlock never released. The follow loop now keys its deadband off the rigs frequency (only re-tuning when the RADIO actually QSYs), immune to a flaky antenna status. Also dropped an interlock set reason= command that SmartSDR rejects (its read-only) and only produced a harmless error line — the transmit-inhibit itself is unchanged and still holds TX safely while the elements move. New: a SteppIR Tunable range setting (Settings → Hardware → Antenna, default 1354 MHz = 20 m6 m) — on a band outside it OpsLog leaves the antenna and TX completely alone, so tuning to 30 m on a 20 m6 m SteppIR no longer tries to move it or touches the interlock.",
"New built-in award: The Helvetia 26 Award (H26) — the 26 cantons of Switzerland (USKA). Ships with the full canton reference list; matches the canton from the QSO's address or QTH, on HF, for Swiss (HB) contacts. Enable it in Awards and rescan to see your standings.", "New built-in award: The Helvetia 26 Award (H26) — the 26 cantons of Switzerland (USKA), matched from the QSO's address or QTH on HF. Each canton also recognises its main cities (Genève, Lausanne, Zürich, Bellinzona…), since operators rarely write the canton itself.",
"FlexRadio panel: the RECEIVE card is shorter again. All the noise controls added recently made it tower, so only the everyday ones — NB, NR, ANF — now stay visible; WNB and the SmartSDR v4 DSP block (NRL/NRS/NRF/ANFL and the AI/FFT RNN & ANFT) tuck behind a 'DSP' button you expand when you need them. The button carries a dot and highlights when one of the hidden controls is switched on, so nothing active is ever out of sight, and its open/closed state is remembered.", "FlexRadio panel: the RECEIVE card is shorter again. All the noise controls added recently made it tower, so only the everyday ones — NB, NR, ANF — now stay visible; WNB and the SmartSDR v4 DSP block (NRL/NRS/NRF/ANFL and the AI/FFT RNN & ANFT) tuck behind a 'DSP' button you expand when you need them. The button carries a dot and highlights when one of the hidden controls is switched on, so nothing active is ever out of sight, and its open/closed state is remembered.",
"ADIF export can now pick exactly which fields to write. The global 'Export to ADIF' dialog gains a third choice, 'Choose fields…', alongside 'Standard ADIF fields' and 'All OpsLog fields'; and right-clicking selected QSOs adds 'Export selected — choose fields…'. The picker separates the official ADIF 3.1.7 fields (grouped by category) from OpsLog / non-standard tags actually present in your log, with All/None per group and a one-click reset to defaults. Your selection is remembered for next time.", "ADIF export can now pick exactly which fields to write. The global 'Export to ADIF' dialog gains a third choice, 'Choose fields…', alongside 'Standard ADIF fields' and 'All OpsLog fields'; and right-clicking selected QSOs adds 'Export selected — choose fields…'. The picker separates the official ADIF 3.1.7 fields (grouped by category) from OpsLog / non-standard tags actually present in your log, with All/None per group and a one-click reset to defaults. Your selection is remembered for next time.",
"Fixed 'Incorrect string value' (MySQL error 1366) when a QSO contained non-Latin characters — Cyrillic (Я), Polish ł, etc. — e.g. updating from QRZ. It happened when the shared MySQL database had been pre-created by the hosting panel as latin1, so OpsLog's tables couldn't store those letters. OpsLog now converts the database and its tables to utf8mb4 on connect (once, automatically), and everything stores correctly. Local SQLite logbooks were never affected.", "Fixed 'Incorrect string value' (MySQL error 1366) when a QSO contained non-Latin characters — Cyrillic (Я), Polish ł, etc. — e.g. updating from QRZ. It happened when the shared MySQL database had been pre-created by the hosting panel as latin1, so OpsLog's tables couldn't store those letters. OpsLog now converts the database and its tables to utf8mb4 on connect (once, automatically), and everything stores correctly. Local SQLite logbooks were never affected.",
@@ -17,7 +17,7 @@
], ],
"fr": [ "fr": [
"Correction d'un bug d'antenne motorisée qui pouvait laisser un FlexRadio définitivement incapable d'émettre (« Interlock is preventing transmission »). Avec une SteppIR dont la fréquence de statut se lit par intermittence (elle alternait entre la fréquence commandée et sa valeur de repos), la boucle de suivi renvoyait un ordre d'accord à presque chaque cycle, et chaque ordre réarmait la fenêtre « bloquer l'émission pendant que l'antenne bouge » — l'interlock ne se relâchait donc jamais. La boucle de suivi se base maintenant sur la fréquence de la RADIO (elle ne réaccorde que quand le poste change réellement de fréquence), insensible à un statut d'antenne erratique. Retrait aussi d'une commande « interlock set reason= » que SmartSDR refuse (champ en lecture seule) et qui ne produisait qu'une ligne d'erreur sans effet — l'inhibition d'émission elle-même est inchangée et protège toujours pendant le mouvement des éléments. Nouveau : un réglage « Plage accordable » pour la SteppIR (Réglages → Matériel → Antenne, défaut 13-54 MHz = 20 m-6 m) — sur une bande hors de cette plage, OpsLog laisse totalement l'antenne et l'émission tranquilles, donc passer sur 30 m avec une SteppIR 20 m-6 m ne tente plus de la bouger ni ne touche à l'interlock.", "Correction d'un bug d'antenne motorisée qui pouvait laisser un FlexRadio définitivement incapable d'émettre (« Interlock is preventing transmission »). Avec une SteppIR dont la fréquence de statut se lit par intermittence (elle alternait entre la fréquence commandée et sa valeur de repos), la boucle de suivi renvoyait un ordre d'accord à presque chaque cycle, et chaque ordre réarmait la fenêtre « bloquer l'émission pendant que l'antenne bouge » — l'interlock ne se relâchait donc jamais. La boucle de suivi se base maintenant sur la fréquence de la RADIO (elle ne réaccorde que quand le poste change réellement de fréquence), insensible à un statut d'antenne erratique. Retrait aussi d'une commande « interlock set reason= » que SmartSDR refuse (champ en lecture seule) et qui ne produisait qu'une ligne d'erreur sans effet — l'inhibition d'émission elle-même est inchangée et protège toujours pendant le mouvement des éléments. Nouveau : un réglage « Plage accordable » pour la SteppIR (Réglages → Matériel → Antenne, défaut 13-54 MHz = 20 m-6 m) — sur une bande hors de cette plage, OpsLog laisse totalement l'antenne et l'émission tranquilles, donc passer sur 30 m avec une SteppIR 20 m-6 m ne tente plus de la bouger ni ne touche à l'interlock.",
"Nouveau diplôme intégré : The Helvetia 26 Award (H26) — les 26 cantons de Suisse (USKA). Livré avec la liste complète des cantons ; il reconnaît le canton depuis l'adresse ou le QTH du QSO, en HF, pour les contacts suisses (HB). Active-le dans les Diplômes et relance un scan pour voir ton avancement.", "Nouveau diplôme intégré : The Helvetia 26 Award (H26) — les 26 cantons de Suisse (USKA), reconnus depuis l'adresse ou le QTH du QSO en HF. Chaque canton reconnaît aussi ses principales villes (Genève, Lausanne, Zürich, Bellinzone…), car les opérateurs écrivent rarement le canton lui-même.",
"Panneau FlexRadio : la carte RÉCEPTION est de nouveau plus compacte. Tous les contrôles de bruit ajoutés récemment la faisaient s'allonger, donc seuls ceux du quotidien — NB, NR, ANF — restent visibles ; le WNB et le bloc DSP SmartSDR v4 (NRL/NRS/NRF/ANFL ainsi que RNN & ANFT IA/FFT) se replient derrière un bouton « DSP » que tu déplies au besoin. Le bouton porte un point et s'illumine quand l'un des contrôles masqués est activé, pour ne jamais perdre de vue quelque chose d'actif, et son état ouvert/fermé est mémorisé.", "Panneau FlexRadio : la carte RÉCEPTION est de nouveau plus compacte. Tous les contrôles de bruit ajoutés récemment la faisaient s'allonger, donc seuls ceux du quotidien — NB, NR, ANF — restent visibles ; le WNB et le bloc DSP SmartSDR v4 (NRL/NRS/NRF/ANFL ainsi que RNN & ANFT IA/FFT) se replient derrière un bouton « DSP » que tu déplies au besoin. Le bouton porte un point et s'illumine quand l'un des contrôles masqués est activé, pour ne jamais perdre de vue quelque chose d'actif, et son état ouvert/fermé est mémorisé.",
"L'export ADIF permet maintenant de choisir précisément les champs à écrire. La fenêtre globale « Exporter en ADIF » gagne un troisième choix, « Choisir les champs… », à côté de « Champs ADIF standard » et « Tous les champs OpsLog » ; et le clic droit sur des QSO sélectionnés ajoute « Exporter la sélection — choisir les champs… ». Le sélecteur sépare les champs ADIF 3.1.7 officiels (regroupés par catégorie) des balises OpsLog / non standard réellement présentes dans ton log, avec Tout/Aucun par groupe et un retour aux valeurs par défaut en un clic. Ta sélection est mémorisée pour la prochaine fois.", "L'export ADIF permet maintenant de choisir précisément les champs à écrire. La fenêtre globale « Exporter en ADIF » gagne un troisième choix, « Choisir les champs… », à côté de « Champs ADIF standard » et « Tous les champs OpsLog » ; et le clic droit sur des QSO sélectionnés ajoute « Exporter la sélection — choisir les champs… ». Le sélecteur sépare les champs ADIF 3.1.7 officiels (regroupés par catégorie) des balises OpsLog / non standard réellement présentes dans ton log, avec Tout/Aucun par groupe et un retour aux valeurs par défaut en un clic. Ta sélection est mémorisée pour la prochaine fois.",
"Correction de « Incorrect string value » (erreur MySQL 1366) quand un QSO contenait des caractères non latins — cyrillique (Я), polonais ł, etc. — p. ex. lors d'une mise à jour depuis QRZ. Ça arrivait quand la base MySQL partagée avait été pré-créée en latin1 par le panel d'hébergement, empêchant les tables d'OpsLog de stocker ces lettres. OpsLog convertit désormais la base et ses tables en utf8mb4 à la connexion (une seule fois, automatiquement), et tout s'enregistre correctement. Les logbooks SQLite locaux n'étaient pas concernés.", "Correction de « Incorrect string value » (erreur MySQL 1366) quand un QSO contenait des caractères non latins — cyrillique (Я), polonais ł, etc. — p. ex. lors d'une mise à jour depuis QRZ. Ça arrivait quand la base MySQL partagée avait été pré-créée en latin1 par le panel d'hébergement, empêchant les tables d'OpsLog de stocker ces lettres. OpsLog convertit désormais la base et ses tables en utf8mb4 à la connexion (une seule fois, automatiquement), et tout s'enregistre correctement. Les logbooks SQLite locaux n'étaient pas concernés.",
+28 -2
View File
@@ -45,12 +45,13 @@
], ],
"total": 0, "total": 0,
"builtin": true, "builtin": true,
"version": 1 "version": 2
}, },
"references": [ "references": [
{ {
"code": "AG", "code": "AG",
"name": "Aargau", "name": "Aargau",
"pattern": "\\b(Aarau|Baden|Wettingen|Wohlen|Rheinfelden|Zofingen|Lenzburg|Brugg|Oftringen|Suhr|Spreitenbach)\\b",
"dxcc": 287, "dxcc": 287,
"group": "", "group": "",
"subgrp": "", "subgrp": "",
@@ -59,6 +60,7 @@
{ {
"code": "AI", "code": "AI",
"name": "Appenzell Innerrhoden", "name": "Appenzell Innerrhoden",
"pattern": "\\b(Appenzell|Oberegg)\\b",
"dxcc": 287, "dxcc": 287,
"group": "", "group": "",
"subgrp": "", "subgrp": "",
@@ -67,6 +69,7 @@
{ {
"code": "AR", "code": "AR",
"name": "Appenzell Ausserrhoden", "name": "Appenzell Ausserrhoden",
"pattern": "\\b(Herisau|Teufen|Speicher|Heiden|Gais|Urnäsch|Waldstatt)\\b",
"dxcc": 287, "dxcc": 287,
"group": "", "group": "",
"subgrp": "", "subgrp": "",
@@ -75,6 +78,7 @@
{ {
"code": "BE", "code": "BE",
"name": "Bern", "name": "Bern",
"pattern": "\\b(Bern|Berne|Thun|Biel|Bienne|Köniz|Burgdorf|Langenthal|Steffisburg|Münsingen|Spiez|Interlaken|Ostermundigen|Lyss|Zollikofen)\\b",
"dxcc": 287, "dxcc": 287,
"group": "", "group": "",
"subgrp": "", "subgrp": "",
@@ -83,6 +87,7 @@
{ {
"code": "BL", "code": "BL",
"name": "Basel-Landschaft", "name": "Basel-Landschaft",
"pattern": "\\b(Liestal|Allschwil|Reinach|Muttenz|Pratteln|Binningen|Münchenstein|Birsfelden|Aesch|Sissach|Oberwil)\\b",
"dxcc": 287, "dxcc": 287,
"group": "", "group": "",
"subgrp": "", "subgrp": "",
@@ -91,6 +96,7 @@
{ {
"code": "BS", "code": "BS",
"name": "Basel-Stadt", "name": "Basel-Stadt",
"pattern": "\\b(Basel|Bâle|Bale|Riehen|Bettingen)\\b",
"dxcc": 287, "dxcc": 287,
"group": "", "group": "",
"subgrp": "", "subgrp": "",
@@ -99,6 +105,7 @@
{ {
"code": "FR", "code": "FR",
"name": "Fribourg", "name": "Fribourg",
"pattern": "\\b(Fribourg|Freiburg|Bulle|Marly|Düdingen|Estavayer|Murten|Morat|Villars-sur-Glâne|Guin)\\b",
"dxcc": 287, "dxcc": 287,
"group": "", "group": "",
"subgrp": "", "subgrp": "",
@@ -107,6 +114,7 @@
{ {
"code": "GE", "code": "GE",
"name": "Geneva", "name": "Geneva",
"pattern": "\\b(Genève|Geneve|Geneva|Genf|Carouge|Vernier|Lancy|Meyrin|Onex|Thônex|Thonex|Versoix|Bernex|Plan-les-Ouates)\\b",
"dxcc": 287, "dxcc": 287,
"group": "", "group": "",
"subgrp": "", "subgrp": "",
@@ -115,6 +123,7 @@
{ {
"code": "GL", "code": "GL",
"name": "Glarus", "name": "Glarus",
"pattern": "\\b(Glarus|Glaris|Näfels|Netstal|Ennenda|Mollis)\\b",
"dxcc": 287, "dxcc": 287,
"group": "", "group": "",
"subgrp": "", "subgrp": "",
@@ -123,6 +132,7 @@
{ {
"code": "GR", "code": "GR",
"name": "Graubünden (Grisons)", "name": "Graubünden (Grisons)",
"pattern": "\\b(Chur|Coire|Davos|Sankt Moritz|St\\.? Moritz|Landquart|Arosa|Klosters|Ilanz|Thusis|Poschiavo|Domat|Ems)\\b",
"dxcc": 287, "dxcc": 287,
"group": "", "group": "",
"subgrp": "", "subgrp": "",
@@ -131,6 +141,7 @@
{ {
"code": "JU", "code": "JU",
"name": "Jura", "name": "Jura",
"pattern": "\\b(Delémont|Delemont|Porrentruy|Bassecourt|Courroux|Saignelégier|Alle)\\b",
"dxcc": 287, "dxcc": 287,
"group": "", "group": "",
"subgrp": "", "subgrp": "",
@@ -139,6 +150,7 @@
{ {
"code": "LU", "code": "LU",
"name": "Lucerne", "name": "Lucerne",
"pattern": "\\b(Luzern|Lucerne|Emmen|Kriens|Horw|Ebikon|Sursee|Hochdorf|Willisau|Rothenburg)\\b",
"dxcc": 287, "dxcc": 287,
"group": "", "group": "",
"subgrp": "", "subgrp": "",
@@ -147,6 +159,7 @@
{ {
"code": "NE", "code": "NE",
"name": "Neuchâtel", "name": "Neuchâtel",
"pattern": "\\b(Neuchâtel|Neuchatel|Neuenburg|La Chaux-de-Fonds|Chaux-de-Fonds|Le Locle|Peseux|Boudry|Colombier|Marin)\\b",
"dxcc": 287, "dxcc": 287,
"group": "", "group": "",
"subgrp": "", "subgrp": "",
@@ -155,6 +168,7 @@
{ {
"code": "NW", "code": "NW",
"name": "Nidwalden", "name": "Nidwalden",
"pattern": "\\b(Stans|Hergiswil|Buochs|Stansstad|Beckenried|Ennetbürgen)\\b",
"dxcc": 287, "dxcc": 287,
"group": "", "group": "",
"subgrp": "", "subgrp": "",
@@ -163,6 +177,7 @@
{ {
"code": "OW", "code": "OW",
"name": "Obwalden", "name": "Obwalden",
"pattern": "\\b(Sarnen|Kerns|Alpnach|Engelberg|Sachseln|Giswil)\\b",
"dxcc": 287, "dxcc": 287,
"group": "", "group": "",
"subgrp": "", "subgrp": "",
@@ -171,6 +186,7 @@
{ {
"code": "SG", "code": "SG",
"name": "St. Gallen", "name": "St. Gallen",
"pattern": "\\b(Sankt Gallen|Saint-Gall|Rapperswil|Wil|Gossau|Rorschach|Uzwil|Flawil|Altstätten|Jona)\\b",
"dxcc": 287, "dxcc": 287,
"group": "", "group": "",
"subgrp": "", "subgrp": "",
@@ -179,6 +195,7 @@
{ {
"code": "SH", "code": "SH",
"name": "Schaffhausen", "name": "Schaffhausen",
"pattern": "\\b(Schaffhausen|Schaffhouse|Neuhausen|Stein am Rhein|Thayngen)\\b",
"dxcc": 287, "dxcc": 287,
"group": "", "group": "",
"subgrp": "", "subgrp": "",
@@ -187,6 +204,7 @@
{ {
"code": "SO", "code": "SO",
"name": "Solothurn", "name": "Solothurn",
"pattern": "\\b(Solothurn|Soleure|Olten|Grenchen|Zuchwil|Dornach|Oensingen|Balsthal|Biberist)\\b",
"dxcc": 287, "dxcc": 287,
"group": "", "group": "",
"subgrp": "", "subgrp": "",
@@ -195,6 +213,7 @@
{ {
"code": "SZ", "code": "SZ",
"name": "Schwyz", "name": "Schwyz",
"pattern": "\\b(Schwyz|Einsiedeln|Freienbach|Küssnacht|Arth|Lachen|Wollerau|Brunnen|Goldau)\\b",
"dxcc": 287, "dxcc": 287,
"group": "", "group": "",
"subgrp": "", "subgrp": "",
@@ -203,6 +222,7 @@
{ {
"code": "TG", "code": "TG",
"name": "Thurgau", "name": "Thurgau",
"pattern": "\\b(Frauenfeld|Kreuzlingen|Arbon|Amriswil|Weinfelden|Romanshorn|Sirnach|Aadorf|Münchwilen)\\b",
"dxcc": 287, "dxcc": 287,
"group": "", "group": "",
"subgrp": "", "subgrp": "",
@@ -211,6 +231,7 @@
{ {
"code": "TI", "code": "TI",
"name": "Ticino", "name": "Ticino",
"pattern": "\\b(Lugano|Bellinzona|Locarno|Mendrisio|Chiasso|Biasca|Ascona|Losone|Minusio|Giubiasco|Massagno)\\b",
"dxcc": 287, "dxcc": 287,
"group": "", "group": "",
"subgrp": "", "subgrp": "",
@@ -219,6 +240,7 @@
{ {
"code": "UR", "code": "UR",
"name": "Uri", "name": "Uri",
"pattern": "\\b(Altdorf|Schattdorf|Erstfeld|Andermatt|Flüelen|Bürglen)\\b",
"dxcc": 287, "dxcc": 287,
"group": "", "group": "",
"subgrp": "", "subgrp": "",
@@ -227,6 +249,7 @@
{ {
"code": "VD", "code": "VD",
"name": "Vaud", "name": "Vaud",
"pattern": "\\b(Lausanne|Yverdon|Montreux|Nyon|Vevey|Renens|Morges|Gland|Pully|Prilly|Ecublens|Aigle|Payerne|Rolle|Lutry|Bussigny)\\b",
"dxcc": 287, "dxcc": 287,
"group": "", "group": "",
"subgrp": "", "subgrp": "",
@@ -235,6 +258,7 @@
{ {
"code": "VS", "code": "VS",
"name": "Valais", "name": "Valais",
"pattern": "\\b(Sion|Sitten|Martigny|Monthey|Sierre|Brig|Brigue|Naters|Visp|Viège|Conthey|Fully|Verbier|Zermatt|Crans-Montana|Saas-Fee|Savièse|Bagnes)\\b",
"dxcc": 287, "dxcc": 287,
"group": "", "group": "",
"subgrp": "", "subgrp": "",
@@ -243,6 +267,7 @@
{ {
"code": "ZG", "code": "ZG",
"name": "Zug", "name": "Zug",
"pattern": "\\b(Zug|Zoug|Baar|Cham|Steinhausen|Risch|Rotkreuz|Hünenberg|Unterägeri|Oberägeri)\\b",
"dxcc": 287, "dxcc": 287,
"group": "", "group": "",
"subgrp": "", "subgrp": "",
@@ -251,10 +276,11 @@
{ {
"code": "ZH", "code": "ZH",
"name": "Zurich", "name": "Zurich",
"pattern": "\\b(Zürich|Zurich|Winterthur|Uster|Dübendorf|Dietikon|Wetzikon|Kloten|Wädenswil|Horgen|Thalwil|Opfikon|Küsnacht|Meilen|Bülach|Regensdorf|Schlieren|Adliswil|Volketswil)\\b",
"dxcc": 287, "dxcc": 287,
"group": "", "group": "",
"subgrp": "", "subgrp": "",
"valid": true "valid": true
} }
] ]
} }