feat: added Worked All Italian Provinces award and FFMA
This commit is contained in:
+16
-9
@@ -1180,22 +1180,29 @@ export default function App() {
|
|||||||
// Effective antenna heading(s): the rotor azimuth, transformed by the
|
// Effective antenna heading(s): the rotor azimuth, transformed by the
|
||||||
// Ultrabeam pattern when one is active — reversed (180°) points opposite,
|
// Ultrabeam pattern when one is active — reversed (180°) points opposite,
|
||||||
// bidirectional radiates both ways, normal is the heading itself.
|
// bidirectional radiates both ways, normal is the heading itself.
|
||||||
|
// Headings are rounded to whole degrees: a rotor reports a jittering float, and
|
||||||
|
// a fraction of a degree changes nothing on a compass or a beam lobe — but it
|
||||||
|
// does invalidate every memo downstream and force the map to rebuild its whole
|
||||||
|
// overlay on each reading.
|
||||||
|
const rotorAz = useMemo<number | null>(() => (
|
||||||
|
rotatorHeading.enabled && rotatorHeading.ok
|
||||||
|
? Math.round((((rotatorHeading.azimuth % 360) + 360) % 360)) % 360
|
||||||
|
: null
|
||||||
|
), [rotatorHeading.enabled, rotatorHeading.ok, rotatorHeading.azimuth]);
|
||||||
|
|
||||||
const beamHeadings = useMemo<number[]>(() => {
|
const beamHeadings = useMemo<number[]>(() => {
|
||||||
if (!(rotatorHeading.enabled && rotatorHeading.ok)) return [];
|
if (rotorAz == null) return [];
|
||||||
const base = ((rotatorHeading.azimuth % 360) + 360) % 360;
|
|
||||||
if (ubStatus.enabled && ubStatus.connected) {
|
if (ubStatus.enabled && ubStatus.connected) {
|
||||||
if (ubStatus.direction === 1) return [(base + 180) % 360];
|
if (ubStatus.direction === 1) return [(rotorAz + 180) % 360];
|
||||||
if (ubStatus.direction === 2) return [base, (base + 180) % 360];
|
if (ubStatus.direction === 2) return [rotorAz, (rotorAz + 180) % 360];
|
||||||
}
|
}
|
||||||
return [base];
|
return [rotorAz];
|
||||||
}, [rotatorHeading.enabled, rotatorHeading.ok, rotatorHeading.azimuth, ubStatus.enabled, ubStatus.connected, ubStatus.direction]);
|
}, [rotorAz, ubStatus.enabled, ubStatus.connected, ubStatus.direction]);
|
||||||
|
|
||||||
// Mechanical boom (rotor) heading + Ultrabeam pattern — so the compass/map can
|
// Mechanical boom (rotor) heading + Ultrabeam pattern — so the compass/map can
|
||||||
// show where the antenna physically points (boom) vs where it radiates when
|
// show where the antenna physically points (boom) vs where it radiates when
|
||||||
// the Ultrabeam is reversed/bidirectional.
|
// the Ultrabeam is reversed/bidirectional.
|
||||||
const boomHeading = useMemo<number | null>(() => (
|
const boomHeading = rotorAz;
|
||||||
rotatorHeading.enabled && rotatorHeading.ok ? ((rotatorHeading.azimuth % 360) + 360) % 360 : null
|
|
||||||
), [rotatorHeading.enabled, rotatorHeading.ok, rotatorHeading.azimuth]);
|
|
||||||
const ubPattern = useMemo<'normal' | 'reverse' | 'bi' | null>(() => {
|
const ubPattern = useMemo<'normal' | 'reverse' | 'bi' | null>(() => {
|
||||||
if (!(ubStatus.enabled && ubStatus.connected)) return null;
|
if (!(ubStatus.enabled && ubStatus.connected)) return null;
|
||||||
return ubStatus.direction === 1 ? 'reverse' : ubStatus.direction === 2 ? 'bi' : 'normal';
|
return ubStatus.direction === 1 ? 'reverse' : ubStatus.direction === 2 ? 'bi' : 'normal';
|
||||||
|
|||||||
@@ -742,10 +742,11 @@ function ReferencesPanel({ code, presets, meta, onUpdateOnline, updating, onChan
|
|||||||
<button className="text-muted-foreground hover:text-destructive" onClick={() => delRef(sel.code)}><Trash2 className="size-4" /></button>
|
<button className="text-muted-foreground hover:text-destructive" onClick={() => delRef(sel.code)}><Trash2 className="size-4" /></button>
|
||||||
</div>
|
</div>
|
||||||
<Field2 label={t('awed.description')}><Input className="h-8" value={sel.name ?? ''} onChange={(e) => patchSel({ name: e.target.value })} /></Field2>
|
<Field2 label={t('awed.description')}><Input className="h-8" value={sel.name ?? ''} onChange={(e) => patchSel({ name: e.target.value })} /></Field2>
|
||||||
<div className="grid grid-cols-2 gap-3">
|
{/* One per row: side by side, each half spends 120px of its width on
|
||||||
|
the label column and the input is left too narrow to read a group
|
||||||
|
name ("Basilicata" → "Basili"). */}
|
||||||
<Field2 label={t('awed.group')}><Input className="h-8" value={sel.group ?? ''} onChange={(e) => patchSel({ group: e.target.value })} /></Field2>
|
<Field2 label={t('awed.group')}><Input className="h-8" value={sel.group ?? ''} onChange={(e) => patchSel({ group: e.target.value })} /></Field2>
|
||||||
<Field2 label={t('awed.subgroup')}><Input className="h-8" value={sel.subgrp ?? ''} onChange={(e) => patchSel({ subgrp: e.target.value })} /></Field2>
|
<Field2 label={t('awed.subgroup')}><Input className="h-8" value={sel.subgrp ?? ''} onChange={(e) => patchSel({ subgrp: e.target.value })} /></Field2>
|
||||||
</div>
|
|
||||||
<Field2 label="DXCC"><Input type="number" className="h-8 w-32 font-mono" value={sel.dxcc || ''} onChange={(e) => patchSel({ dxcc: parseInt(e.target.value, 10) || 0 })} /></Field2>
|
<Field2 label="DXCC"><Input type="number" className="h-8 w-32 font-mono" value={sel.dxcc || ''} onChange={(e) => patchSel({ dxcc: parseInt(e.target.value, 10) || 0 })} /></Field2>
|
||||||
<Field2 label={t('awed.patternRegex')}><Input className="h-8 font-mono text-xs" value={sel.pattern ?? ''} onChange={(e) => patchSel({ pattern: e.target.value })} placeholder={t('awed.perRefRegex')} /></Field2>
|
<Field2 label={t('awed.patternRegex')}><Input className="h-8 font-mono text-xs" value={sel.pattern ?? ''} onChange={(e) => patchSel({ pattern: e.target.value })} placeholder={t('awed.perRefRegex')} /></Field2>
|
||||||
<div className="grid grid-cols-3 gap-3">
|
<div className="grid grid-cols-3 gap-3">
|
||||||
|
|||||||
@@ -64,6 +64,24 @@ function loadBasemap(): BasemapKey {
|
|||||||
return v === 'voyager' || v === 'street' || v === 'satellite' ? v : 'light';
|
return v === 'voyager' || v === 'street' || v === 'satellite' ? v : 'light';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// addBasemap (re)installs the imagery layer and, for satellite, its transparent
|
||||||
|
// place-name overlay. updateWhenIdle/keepBuffer keep the number of live tiles
|
||||||
|
// down: satellite loads TWO tile layers, so its tile count — and the composited
|
||||||
|
// layers WebView2 has to hold — is double every other basemap's.
|
||||||
|
function addBasemap(
|
||||||
|
m: L.Map,
|
||||||
|
key: BasemapKey,
|
||||||
|
base: React.MutableRefObject<L.TileLayer | null>,
|
||||||
|
labels: React.MutableRefObject<L.TileLayer | null>,
|
||||||
|
) {
|
||||||
|
if (base.current) { m.removeLayer(base.current); base.current = null; }
|
||||||
|
if (labels.current) { m.removeLayer(labels.current); labels.current = null; }
|
||||||
|
const bm = BASEMAPS[key];
|
||||||
|
const opts: L.TileLayerOptions = { maxZoom: 19, updateWhenIdle: true, updateWhenZooming: false, keepBuffer: 1 };
|
||||||
|
base.current = L.tileLayer(bm.url, { ...opts, attribution: bm.attr, subdomains: bm.subdomains ?? 'abc' }).addTo(m);
|
||||||
|
if (bm.labelsUrl) labels.current = L.tileLayer(bm.labelsUrl, opts).addTo(m);
|
||||||
|
}
|
||||||
|
|
||||||
function dot(color: string): L.DivIcon {
|
function dot(color: string): L.DivIcon {
|
||||||
return L.divIcon({
|
return L.divIcon({
|
||||||
className: '',
|
className: '',
|
||||||
@@ -103,11 +121,14 @@ export function WorldMap({ fromGrid, toGrid, fromLabel, toLabel, beamAzimuths, b
|
|||||||
// One-time map creation.
|
// One-time map creation.
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (worldRef.current && !worldMap.current) {
|
if (worldRef.current && !worldMap.current) {
|
||||||
const m = L.map(worldRef.current, { zoomControl: true, attributionControl: true, worldCopyJump: true })
|
// preferCanvas: the beam lobe is a dense FAN of translucent radials — up to
|
||||||
|
// ~120 thick strokes with a bidirectional Ultrabeam. As SVG that is ~120
|
||||||
|
// composited paths re-rasterised on every pan, zoom and redraw, which is
|
||||||
|
// enough to blow WebView2's raster budget and leave the window painting in
|
||||||
|
// patches. On canvas it is a single layer.
|
||||||
|
const m = L.map(worldRef.current, { zoomControl: true, attributionControl: true, worldCopyJump: true, preferCanvas: true })
|
||||||
.setView([20, 0], 1);
|
.setView([20, 0], 1);
|
||||||
const bm = BASEMAPS[basemap];
|
addBasemap(m, basemap, baseLayer, labelsLayer);
|
||||||
baseLayer.current = L.tileLayer(bm.url, { attribution: bm.attr, subdomains: bm.subdomains ?? 'abc', maxZoom: 19 }).addTo(m);
|
|
||||||
if (bm.labelsUrl) labelsLayer.current = L.tileLayer(bm.labelsUrl, { maxZoom: 19 }).addTo(m);
|
|
||||||
worldOverlay.current = L.layerGroup().addTo(m);
|
worldOverlay.current = L.layerGroup().addTo(m);
|
||||||
worldMap.current = m;
|
worldMap.current = m;
|
||||||
const sv = loadMapView();
|
const sv = loadMapView();
|
||||||
@@ -115,7 +136,12 @@ export function WorldMap({ fromGrid, toGrid, fromLabel, toLabel, beamAzimuths, b
|
|||||||
m.on('moveend', () => { if (!autoZoomRef.current) saveMapView(m); });
|
m.on('moveend', () => { if (!autoZoomRef.current) saveMapView(m); });
|
||||||
}
|
}
|
||||||
const t = window.setTimeout(() => { worldMap.current?.invalidateSize(); }, 80);
|
const t = window.setTimeout(() => { worldMap.current?.invalidateSize(); }, 80);
|
||||||
return () => window.clearTimeout(t);
|
// Resizing the pane is the ONLY thing that needs invalidateSize. Calling it on
|
||||||
|
// every overlay redraw (as before) forced a full repaint of the map each time
|
||||||
|
// the rotor moved a degree.
|
||||||
|
const ro = new ResizeObserver(() => worldMap.current?.invalidateSize());
|
||||||
|
if (worldRef.current) ro.observe(worldRef.current);
|
||||||
|
return () => { window.clearTimeout(t); ro.disconnect(); };
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
// Swap the basemap (and its optional place-name overlay) when the operator
|
// Swap the basemap (and its optional place-name overlay) when the operator
|
||||||
@@ -123,12 +149,7 @@ export function WorldMap({ fromGrid, toGrid, fromLabel, toLabel, beamAzimuths, b
|
|||||||
// overlayPane, always above any tile layer, so nothing to re-stack there.
|
// overlayPane, always above any tile layer, so nothing to re-stack there.
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const m = worldMap.current;
|
const m = worldMap.current;
|
||||||
if (!m) return;
|
if (m) addBasemap(m, basemap, baseLayer, labelsLayer);
|
||||||
if (baseLayer.current) { m.removeLayer(baseLayer.current); baseLayer.current = null; }
|
|
||||||
if (labelsLayer.current) { m.removeLayer(labelsLayer.current); labelsLayer.current = null; }
|
|
||||||
const bm = BASEMAPS[basemap];
|
|
||||||
baseLayer.current = L.tileLayer(bm.url, { attribution: bm.attr, subdomains: bm.subdomains ?? 'abc', maxZoom: 19 }).addTo(m);
|
|
||||||
if (bm.labelsUrl) labelsLayer.current = L.tileLayer(bm.labelsUrl, { maxZoom: 19 }).addTo(m);
|
|
||||||
}, [basemap]);
|
}, [basemap]);
|
||||||
|
|
||||||
// Redraw overlays whenever the operator/DX grids (or beam) change.
|
// Redraw overlays whenever the operator/DX grids (or beam) change.
|
||||||
@@ -224,9 +245,14 @@ export function WorldMap({ fromGrid, toGrid, fromLabel, toLabel, beamAzimuths, b
|
|||||||
wm.setView([from.lat, from.lon], 3);
|
wm.setView([from.lat, from.lon], 3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
setTimeout(() => { wm.invalidateSize(); }, 0);
|
// No invalidateSize() here — a ResizeObserver handles the only case that needs
|
||||||
|
// it. Forcing a full map repaint on every redraw is what made a moving rotor
|
||||||
|
// thrash the compositor.
|
||||||
|
// Headings are rounded in the deps: a rotor reports a jittering float, and a
|
||||||
|
// tenth of a degree is invisible on a 5500 km lobe but rebuilds every polyline.
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [fromGrid, toGrid, fromLabel, toLabel, (beamAzimuths ?? []).map((a) => Math.round(a)).join(','), beamWidth, boomAzimuth, autoZoom, zoomSignal]);
|
}, [fromGrid, toGrid, fromLabel, toLabel, (beamAzimuths ?? []).map((a) => Math.round(a)).join(','), beamWidth,
|
||||||
|
boomAzimuth == null ? null : Math.round(boomAzimuth), autoZoom, zoomSignal]);
|
||||||
|
|
||||||
const path = pathBetween(fromGrid, toGrid);
|
const path = pathBetween(fromGrid, toGrid);
|
||||||
|
|
||||||
|
|||||||
+28
-12
@@ -693,7 +693,15 @@ func candidates(d *Def, re *regexp.Regexp, q *qso.QSO, rl refList, hasList bool)
|
|||||||
// only while nothing has matched yet, and stop at the first that yields a
|
// only while nothing has matched yet, and stop at the first that yields a
|
||||||
// reference (short-circuit). So a province already found by NAME isn't also
|
// reference (short-circuit). So a province already found by NAME isn't also
|
||||||
// re-derived, possibly differently, from a later city-regex rule.
|
// re-derived, possibly differently, from a later city-regex rule.
|
||||||
found := searchOne(d.Field, d.MatchBy, re, d.ExactMatch, d.LeadingStr, d.TrailingStr, "", q, rl, predefined)
|
//
|
||||||
|
// The short-circuit tests what a rule REALLY yielded — the references that
|
||||||
|
// survive the predefined list — not its raw candidates. A rule can always
|
||||||
|
// produce a raw candidate and still find nothing: "the whole ADDRESS field is
|
||||||
|
// the code" hands back "SERIATE (BG) 24068 ITALY", which is not a province.
|
||||||
|
// Testing the raw candidate would call that a hit, skip every fallback, and
|
||||||
|
// only then drop it as unlisted — leaving the QSO unmatched even though the
|
||||||
|
// next rule ("find the code inside the QTH") would have found BG.
|
||||||
|
found := keepRefs(predefined, rl, searchOne(d.Field, d.MatchBy, re, d.ExactMatch, d.LeadingStr, d.TrailingStr, "", q, rl, predefined))
|
||||||
for i := 0; len(found) == 0 && i < len(d.OrRules); i++ {
|
for i := 0; len(found) == 0 && i < len(d.OrRules); i++ {
|
||||||
r := &d.OrRules[i]
|
r := &d.OrRules[i]
|
||||||
var rre *regexp.Regexp
|
var rre *regexp.Regexp
|
||||||
@@ -704,7 +712,7 @@ func candidates(d *Def, re *regexp.Regexp, q *qso.QSO, rl refList, hasList bool)
|
|||||||
}
|
}
|
||||||
rre = c
|
rre = c
|
||||||
}
|
}
|
||||||
found = searchOne(r.Field, r.MatchBy, rre, r.ExactMatch, r.LeadingStr, r.TrailingStr, r.Prefix, q, rl, predefined)
|
found = keepRefs(predefined, rl, searchOne(r.Field, r.MatchBy, rre, r.ExactMatch, r.LeadingStr, r.TrailingStr, r.Prefix, q, rl, predefined))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Merge operator-assigned references (manual override, ManualRefsKey). Lets
|
// Merge operator-assigned references (manual override, ManualRefsKey). Lets
|
||||||
@@ -714,18 +722,26 @@ func candidates(d *Def, re *regexp.Regexp, q *qso.QSO, rl refList, hasList bool)
|
|||||||
// hand. Applied HERE (not just in MatchQSO) so Compute — which powers the
|
// hand. Applied HERE (not just in MatchQSO) so Compute — which powers the
|
||||||
// awards panel and the per-QSO refs editor — honours overrides too. For a
|
// awards panel and the per-QSO refs editor — honours overrides too. For a
|
||||||
// predefined award the ref is still validated against the list below.
|
// predefined award the ref is still validated against the list below.
|
||||||
for _, c := range manualRefs(q, d.Code) {
|
found = append(found, keepRefs(predefined, rl, manualRefs(q, d.Code))...)
|
||||||
found = append(found, normalizeRef(c))
|
|
||||||
}
|
|
||||||
|
|
||||||
if !predefined {
|
|
||||||
return dedupe(found)
|
return dedupe(found)
|
||||||
}
|
}
|
||||||
// Enforce the predefined list: keep only listed, valid references. The
|
|
||||||
// award-level DXCCFilter already scopes which QSOs are considered (see
|
// keepRefs reduces a rule's raw candidates to the references that actually count.
|
||||||
// inScope), so we do NOT additionally require the QSO's entity to match the
|
// For a predefined award that means the codes on the list, enabled. The
|
||||||
// reference's own DXCC — that wrongly excluded e.g. WAS Alaska (state AK is
|
// award-level DXCCFilter already scopes which QSOs are considered (see inScope),
|
||||||
// DXCC entity 6, not 291). Per-reference DXCC stays metadata for the picker.
|
// so we do NOT additionally require the QSO's entity to match the reference's own
|
||||||
|
// DXCC — that wrongly excluded e.g. WAS Alaska (state AK is DXCC entity 6, not
|
||||||
|
// 291). Per-reference DXCC stays metadata for the picker.
|
||||||
|
func keepRefs(predefined bool, rl refList, found []string) []string {
|
||||||
|
if !predefined {
|
||||||
|
out := make([]string, 0, len(found))
|
||||||
|
for _, c := range found {
|
||||||
|
if c = normalizeRef(c); c != "" {
|
||||||
|
out = append(out, c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dedupe(out)
|
||||||
|
}
|
||||||
var out []string
|
var out []string
|
||||||
seen := map[string]struct{}{}
|
seen := map[string]struct{}{}
|
||||||
for _, c := range found {
|
for _, c := range found {
|
||||||
|
|||||||
@@ -354,6 +354,36 @@ func TestCatalogFFMA(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WAIP: the primary rule takes the WHOLE address as the province code (exact
|
||||||
|
// match), which can never be one — but it does produce a raw candidate. The OR
|
||||||
|
// fallback (find the code inside the QTH, "SERIATE (BG)") is the rule that works,
|
||||||
|
// and it must still run: a rule that yields nothing VALID is not a hit.
|
||||||
|
func TestComputeOrFallbackAfterUnlistedPrimary(t *testing.T) {
|
||||||
|
def := Def{
|
||||||
|
Code: "WAIP", Name: "Worked All Italian Provinces", Valid: true,
|
||||||
|
Type: TypeReference, Field: "address", MatchBy: "code", ExactMatch: true,
|
||||||
|
OrRules: []OrRule{{Field: "qth", MatchBy: "code"}}, // not exact → search inside the field
|
||||||
|
Confirm: []string{"lotw", "qsl"},
|
||||||
|
}
|
||||||
|
metas := []RefMeta{
|
||||||
|
{Code: "BG", Name: "Bergamo", Valid: true},
|
||||||
|
{Code: "MI", Name: "Milano", Valid: true},
|
||||||
|
}
|
||||||
|
qsos := []qso.QSO{
|
||||||
|
{Callsign: "I2IFT", Band: "30m", QTH: "SERIATE (BG)", Address: "Seriate (Bg) 24068 Italy", LOTWRcvd: "Y"},
|
||||||
|
}
|
||||||
|
r := Compute([]Def{def}, qsos, map[string][]RefMeta{"WAIP": metas}, nil)[0]
|
||||||
|
if r.Worked != 1 {
|
||||||
|
t.Fatalf("WAIP worked = %d, want 1 (BG, from the QTH fallback)", r.Worked)
|
||||||
|
}
|
||||||
|
for _, rf := range r.Refs {
|
||||||
|
if rf.Ref == "BG" && rf.Worked {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
t.Errorf("BG not worked; refs = %v", refCodes(r))
|
||||||
|
}
|
||||||
|
|
||||||
func refCodes(r Result) []string {
|
func refCodes(r Result) []string {
|
||||||
out := make([]string, 0, len(r.Refs))
|
out := make([]string, 0, len(r.Refs))
|
||||||
for _, rf := range r.Refs {
|
for _, rf := range r.Refs {
|
||||||
|
|||||||
@@ -0,0 +1,929 @@
|
|||||||
|
{
|
||||||
|
"version": 1,
|
||||||
|
"exported_at": "2026-07-13T21:57:23Z",
|
||||||
|
"awards": [
|
||||||
|
{
|
||||||
|
"def": {
|
||||||
|
"code": "WAIP",
|
||||||
|
"name": "ARI Worked All Italian Provinces",
|
||||||
|
"valid": true,
|
||||||
|
"url": "https://ari.it/en/english-area/awards/1734-waip-worked-all-italian-provinces.html",
|
||||||
|
"ref_url": "https://ari.it/en/english-area/awards/1734-waip-worked-all-italian-provinces.html",
|
||||||
|
"type": "REFERENCE",
|
||||||
|
"field": "qth",
|
||||||
|
"match_by": "code",
|
||||||
|
"exact_match": true,
|
||||||
|
"pattern": "",
|
||||||
|
"or_rules": [
|
||||||
|
{
|
||||||
|
"field": "qth",
|
||||||
|
"match_by": "description"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"field": "address",
|
||||||
|
"match_by": "code"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"field": "address",
|
||||||
|
"match_by": "description"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"dxcc_filter": [
|
||||||
|
248
|
||||||
|
],
|
||||||
|
"confirm": [
|
||||||
|
"lotw",
|
||||||
|
"qsl"
|
||||||
|
],
|
||||||
|
"validate": [
|
||||||
|
"lotw",
|
||||||
|
"qsl"
|
||||||
|
],
|
||||||
|
"total": 0,
|
||||||
|
"builtin": false
|
||||||
|
},
|
||||||
|
"references": [
|
||||||
|
{
|
||||||
|
"code": "AG",
|
||||||
|
"name": "Agrigento",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Sicilia",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "AL",
|
||||||
|
"name": "Alessandria",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Piemonte",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "AN",
|
||||||
|
"name": "Ancona",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Marche",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "AO",
|
||||||
|
"name": "Aosta",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Val d'Aosta",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "AP",
|
||||||
|
"name": "Ascoli Piceno",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Marche",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "AQ",
|
||||||
|
"name": "L'Aquila",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Abruzzo",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "AR",
|
||||||
|
"name": "Arezzo",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Toscana",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "AT",
|
||||||
|
"name": "Asti",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Piemonte",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "AV",
|
||||||
|
"name": "Avellino",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Campania",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "BA",
|
||||||
|
"name": "Bari",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Puglia",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "BG",
|
||||||
|
"name": "Bergamo",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Lombardia",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "BI",
|
||||||
|
"name": "Biella",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Piemonte",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "BL",
|
||||||
|
"name": "Belluno",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Veneto",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "BN",
|
||||||
|
"name": "Benevento",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Campania",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "BO",
|
||||||
|
"name": "Bologna",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Emilia-Romagna",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "BR",
|
||||||
|
"name": "Brindisi",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Puglia",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "BS",
|
||||||
|
"name": "Brescia",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Lombardia",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "BT",
|
||||||
|
"name": "Barletta-Andria-Trani",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Puglia",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "BZ",
|
||||||
|
"name": "Bolzano/Bozen",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Trentino-AltoAdige/Südtirol",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "CA",
|
||||||
|
"name": "Cagliari",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Sardegna",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "CB",
|
||||||
|
"name": "Campobasso",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Molise",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "CE",
|
||||||
|
"name": "Caserta",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Campania",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "CH",
|
||||||
|
"name": "Chieti",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Abruzzo",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "CI",
|
||||||
|
"name": "Carbonia-Iglesias",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Sardegna",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "CL",
|
||||||
|
"name": "Caltanissetta",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Sicilia",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "CN",
|
||||||
|
"name": "Cuneo",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Piemonte",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "CO",
|
||||||
|
"name": "Como",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Lombardia",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "CR",
|
||||||
|
"name": "Cremona",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Lombardia",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "CS",
|
||||||
|
"name": "Cosenza",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Calabria",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "CT",
|
||||||
|
"name": "Catania",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Sicilia",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "CZ",
|
||||||
|
"name": "Catanzaro",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Calabria",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "EN",
|
||||||
|
"name": "Enna",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Sicilia",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "FC",
|
||||||
|
"name": "Forlì-Cesena",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Emilia-Romagna",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "FE",
|
||||||
|
"name": "Ferrara",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Emilia-Romagna",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "FG",
|
||||||
|
"name": "Foggia",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Puglia",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "FI",
|
||||||
|
"name": "Firenze",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Toscana",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "FM",
|
||||||
|
"name": "Fermo",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Marche",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "FR",
|
||||||
|
"name": "Frosinone",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Lazio",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "GE",
|
||||||
|
"name": "Genova",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Liguria",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "GO",
|
||||||
|
"name": "Gorizia",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Friuli-Venezia Giulia",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "GR",
|
||||||
|
"name": "Grosseto",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Toscana",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "IM",
|
||||||
|
"name": "Imperia",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Liguria",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "IS",
|
||||||
|
"name": "Isernia",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Molise",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "KR",
|
||||||
|
"name": "Crotone",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Calabria",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "LC",
|
||||||
|
"name": "Lecco",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Lombardia",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "LE",
|
||||||
|
"name": "Lecce",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Puglia",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "LI",
|
||||||
|
"name": "Livorno",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Toscana",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "LO",
|
||||||
|
"name": "Lodi",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Lombardia",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "LT",
|
||||||
|
"name": "Latina",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Lazio",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "LU",
|
||||||
|
"name": "Lucca",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Toscana",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "MB",
|
||||||
|
"name": "Monza e Brianza",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Lombardia",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "MC",
|
||||||
|
"name": "Macerata",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Marche",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "ME",
|
||||||
|
"name": "Messina",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Sicilia",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "MI",
|
||||||
|
"name": "Milano",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Lombardia",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "MN",
|
||||||
|
"name": "Mantova",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Lombardia",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "MO",
|
||||||
|
"name": "Modena",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Emilia-Romagna",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "MS",
|
||||||
|
"name": "Massa-Carrara",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Toscana",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "MT",
|
||||||
|
"name": "Matera",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Basilicata",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "NA",
|
||||||
|
"name": "Napoli",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Campania",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "NO",
|
||||||
|
"name": "Novara",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Piemonte",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "NU",
|
||||||
|
"name": "Nuoro",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Sardegna",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "OG",
|
||||||
|
"name": "Ogliastra",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Sardegna",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "OR",
|
||||||
|
"name": "Oristano",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Sardegna",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "OT",
|
||||||
|
"name": "Olbia-Tempio",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Sardegna",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "PA",
|
||||||
|
"name": "Palermo",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Sicilia",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "PC",
|
||||||
|
"name": "Piacenza",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Emilia-Romagna",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "PD",
|
||||||
|
"name": "Padova",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Veneto",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "PE",
|
||||||
|
"name": "Pescara",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Abruzzo",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "PG",
|
||||||
|
"name": "Perugia",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Umbria",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "PI",
|
||||||
|
"name": "Pisa",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Toscana",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "PN",
|
||||||
|
"name": "Pordenone",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Friuli-Venezia Giulia",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "PO",
|
||||||
|
"name": "Prato",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Toscana",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "PR",
|
||||||
|
"name": "Parma",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Emilia-Romagna",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "PT",
|
||||||
|
"name": "Pistoia",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Toscana",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "PU",
|
||||||
|
"name": "Pesaro-Urbino",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Marche",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "PV",
|
||||||
|
"name": "Pavia",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Lombardia",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "PZ",
|
||||||
|
"name": "Potenza",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Basilicata",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "RA",
|
||||||
|
"name": "Ravenna",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Emilia-Romagna",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "RC",
|
||||||
|
"name": "Reggio Calabria",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Calabria",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "RE",
|
||||||
|
"name": "Reggio Emilia",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Emilia-Romagna",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "RG",
|
||||||
|
"name": "Ragusa",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Sicilia",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "RI",
|
||||||
|
"name": "Rieti",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Lazio",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "RM",
|
||||||
|
"name": "Roma",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Lazio",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "RN",
|
||||||
|
"name": "Rimini",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Emilia-Romagna",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "RO",
|
||||||
|
"name": "Rovigo",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Veneto",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "SA",
|
||||||
|
"name": "Salerno",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Campania",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "SI",
|
||||||
|
"name": "Siena",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Toscana",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "SO",
|
||||||
|
"name": "Sondrio",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Lombardia",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "SP",
|
||||||
|
"name": "La Spezia",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Liguria",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "SR",
|
||||||
|
"name": "Siracusa",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Sicilia",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "SS",
|
||||||
|
"name": "Sassari",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Sardegna",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "SV",
|
||||||
|
"name": "Savona",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Liguria",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "TA",
|
||||||
|
"name": "Taranto",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Puglia",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "TE",
|
||||||
|
"name": "Teramo",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Abruzzo",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "TN",
|
||||||
|
"name": "Trento",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Trentino-AltoAdige/Südtirol",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "TO",
|
||||||
|
"name": "Torino",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Piemonte",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "TP",
|
||||||
|
"name": "Trapani",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Sicilia",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "TR",
|
||||||
|
"name": "Terni",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Umbria",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "TS",
|
||||||
|
"name": "Trieste",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Friuli-Venezia Giulia",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "TV",
|
||||||
|
"name": "Treviso",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Veneto",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "UD",
|
||||||
|
"name": "Udine",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Friuli-Venezia Giulia",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "VA",
|
||||||
|
"name": "Varese",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Lombardia",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "VB",
|
||||||
|
"name": "Verbano-Cusio-Ossola",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Piemonte",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "VC",
|
||||||
|
"name": "Vercelli",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Piemonte",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "VE",
|
||||||
|
"name": "Venezia",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Veneto",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "VI",
|
||||||
|
"name": "Vicenza",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Veneto",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "VR",
|
||||||
|
"name": "Verona",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Veneto",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "VS",
|
||||||
|
"name": "Medio Campidano",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Sardegna",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "VT",
|
||||||
|
"name": "Viterbo",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Lazio",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"code": "VV",
|
||||||
|
"name": "Vibo Valentia",
|
||||||
|
"dxcc": 248,
|
||||||
|
"group": "Calabria",
|
||||||
|
"subgrp": "",
|
||||||
|
"valid": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user