Initial commit

This commit is contained in:
Zdeněk Burda
2026-01-09 21:26:40 +01:00
parent e83aec6dca
commit 41e3ce6f25
404 changed files with 61250 additions and 28 deletions

View File

@@ -0,0 +1,57 @@
<?php
namespace Database\Seeders;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
class BandEdiBandSeeder extends Seeder
{
/**
* Run the database seeds.
*/
public function run(): void
{
Schema::disableForeignKeyConstraints();
DB::table('bands_edi_bands')->truncate();
Schema::enableForeignKeyConstraints();
$this->call([
BandSeeder::class,
EdiBandSeeder::class,
]);
$bands_edi_bands = [
['band_id' => 1, 'edi_band_id' => 1],
['band_id' => 2, 'edi_band_id' => 2],
['band_id' => 2, 'edi_band_id' => 3],
['band_id' => 3, 'edi_band_id' => 4],
['band_id' => 3, 'edi_band_id' => 5],
['band_id' => 4, 'edi_band_id' => 6],
['band_id' => 4, 'edi_band_id' => 7],
['band_id' => 5, 'edi_band_id' => 8],
['band_id' => 5, 'edi_band_id' => 9],
['band_id' => 6, 'edi_band_id' => 10],
['band_id' => 7, 'edi_band_id' => 11],
['band_id' => 8, 'edi_band_id' => 12],
['band_id' => 9, 'edi_band_id' => 13],
['band_id' => 10, 'edi_band_id' => 14],
['band_id' => 11, 'edi_band_id' => 15],
['band_id' => 12, 'edi_band_id' => 16],
['band_id' => 12, 'edi_band_id' => 17],
['band_id' => 13, 'edi_band_id' => 18],
['band_id' => 13, 'edi_band_id' => 19],
['band_id' => 14, 'edi_band_id' => 20],
];
foreach ($bands_edi_bands as &$bands_edi_band) {
$bands_edi_band['created_at'] = now();
$bands_edi_band['updated_at'] = now();
};
DB::table('bands_edi_bands')->insert($bands_edi_bands);
}
}

View File

@@ -0,0 +1,132 @@
<?php
namespace Database\Seeders;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
use App\Models\Band;
use Illuminate\Support\Facades\Schema;
class BandSeeder extends Seeder
{
/**
* Run the database seeds.
*/
public function run(): void
{
Schema::disableForeignKeyConstraints();
DB::table('bands')->truncate();
Schema::enableForeignKeyConstraints();
$bands = [
[
'name' => '50 MHz',
'order' => 10,
'edi_band_begin' => 50,
'edi_band_end' => 54,
'has_power_category' => false,
],
[
'name' => '145 MHz',
'order' => 20,
'edi_band_begin' => 144,
'edi_band_end' => 148,
'has_power_category' => true,
],
[
'name' => '435 MHz',
'order' => 30,
'edi_band_begin' => 430,
'edi_band_end' => 440,
'has_power_category' => true,
],
[
'name' => '1,3 GHz',
'order' => 40,
'edi_band_begin' => 1240,
'edi_band_end' => 1300,
'has_power_category' => false,
],
[
'name' => '2,3 GHz',
'order' => 50,
'edi_band_begin' => 2300,
'edi_band_end' => 2450,
'has_power_category' => false,
],
[
'name' => '3,4 GHz',
'order' => 60,
'edi_band_begin' => 3400,
'edi_band_end' => 3600,
'has_power_category' => false,
],
[
'name' => '5,7 GHz',
'order' => 70,
'edi_band_begin' => 5650,
'edi_band_end' => 5850,
'has_power_category' => false,
],
[
'name' => '10 GHz',
'order' => 80,
'edi_band_begin' => 10000,
'edi_band_end' => 10500,
'has_power_category' => false,
],
[
'name' => '24 GHz',
'order' => 90,
'edi_band_begin' => 24000,
'edi_band_end' => 24250,
'has_power_category' => false,
],
[
'name' => '47 GHz',
'order' => 100,
'edi_band_begin' => 47000,
'edi_band_end' => 47200,
'has_power_category' => false,
],
[
'name' => '76 GHz',
'order' => 110,
'edi_band_begin' => 75500,
'edi_band_end' => 81000,
'has_power_category' => false,
],
[
'name' => '120 GHz',
'order' => 120,
'edi_band_begin' => 122250,
'edi_band_end' => 123000,
'has_power_category' => false,
],
[
'name' => '134 GHz',
'order' => 130,
'edi_band_begin' => 134000,
'edi_band_end' => 144000,
'has_power_category' => false,
],
[
'name' => '287 GHz',
'order' => 140,
'edi_band_begin' => 287000,
'edi_band_end' => 287000,
'has_power_category' => false,
],
];
foreach ($bands as &$band) {
$band['created_at'] = now();
$band['updated_at'] = now();
};
DB::table('bands')->insert($bands);
}
}

View File

@@ -0,0 +1,45 @@
<?php
namespace Database\Seeders;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
class CategoriesEdiCategoriesSeeder extends Seeder
{
/**
* Run the database seeds.
*/
public function run(): void
{
Schema::disableForeignKeyConstraints();
DB::table('categories_edi_categories')->truncate();
Schema::enableForeignKeyConstraints();
$this->call([
CategoriesSeeder::class,
EdiCategoriesSeeder::class,
]);
$categories_edi_categories = [
['category_id' => 1, 'edi_category_id' => 1],
['category_id' => 1, 'edi_category_id' => 2],
['category_id' => 1, 'edi_category_id' => 3],
['category_id' => 1, 'edi_category_id' => 4],
['category_id' => 1, 'edi_category_id' => 5],
['category_id' => 2, 'edi_category_id' => 6],
['category_id' => 2, 'edi_category_id' => 7],
['category_id' => 3, 'edi_category_id' => 8],
['category_id' => 3, 'edi_category_id' => 9],
];
foreach ($categories_edi_categories as &$categories_edi_category) {
$categories_edi_category['created_at'] = now();
$categories_edi_category['updated_at'] = now();
};
DB::table('categories_edi_categories')->insert($categories_edi_categories);
}
}

View File

@@ -0,0 +1,35 @@
<?php
namespace Database\Seeders;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
class CategoriesSeeder extends Seeder
{
/**
* Run the database seeds.
*/
public function run(): void
{
Schema::disableForeignKeyConstraints();
DB::table('categories')->truncate();
Schema::enableForeignKeyConstraints();
$categories = [
['name' => 'SINGLE', 'order' => 10],
['name' => 'MULTI', 'order' => 20],
['name' => 'CHECK', 'order' => 30],
];
foreach ($categories as &$category) {
$category['created_at'] = now();
$category['updated_at'] = now();
};
DB::table('categories')->insert($categories);
}
}

View File

@@ -0,0 +1,97 @@
<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
use App\Models\Contest;
use App\Models\ContestParameter;
use App\Models\Band;
use App\Models\Category;
use App\Models\PowerCategory;
use App\Models\EvaluationRuleSet;
class ContestSeeder extends Seeder
{
/**
* Run the database seeds.
*/
public function run(): void
{
Schema::disableForeignKeyConstraints();
DB::table('contests')->truncate();
DB::table('contests_bands')->truncate();
DB::table('contests_categories')->truncate();
DB::table('contests_power_categories')->truncate();
DB::table('contests_parameters')->truncate();
Schema::enableForeignKeyConstraints();
$bands = Band::all()->pluck('id')->toArray();
$categories = Category::all()->pluck('id')->toArray();
$powerCategories = PowerCategory::all()->pluck('id')->toArray();
$defaultRuleSetId = EvaluationRuleSet::where('code', 'default_vhf_compat')->value('id');
// základní parametry dle vzoru (Y/N -> bool)
$baseParams = [
'ignore_slash_part' => true,
'ignore_third_part' => true,
'letters_in_rst' => true,
'discard_qso_rec_diff_call' => true,
'discard_qso_sent_diff_call' => false,
'discard_qso_rec_diff_rst' => true,
'discard_qso_sent_diff_rst' => false,
'discard_qso_rec_diff_code' => true,
'discard_qso_sent_diff_code' => false,
'unique_qso' => false,
'time_tolerance' => 600,
];
for ($i = 1; $i <= 2; $i++) {
$contest = new Contest();
// lokalizované položky přes Spatie HasTranslations
$contest->setTranslations('name', [
'cs' => "VKV závod {$i}",
'en' => "VHF Contest {$i}",
]);
$contest->setTranslations('description', [
'cs' => "Oficiální VKV závod číslo {$i}.",
'en' => "The official VHF Contest number {$i}.",
]);
// nelokalizovaná data
$contest->evaluator = 'Český radioklub';
$contest->email = 'crk@crk.cz';
$contest->email2 = null;
$contest->is_mcr = true;
$contest->is_sixhr = $i % 2 === 0;
$contest->is_active = $i !== 5; // poslední neaktivní
$contest->start_time = '14:00:00';
$contest->duration = 24;
$contest->logs_deadline_days = 3;
$contest->rule_set_id = $defaultRuleSetId;
$contest->save();
// navázání všech pásem
$contest->bands()->attach($bands);
// navázání všech kategorií
$contest->categories()->attach($categories);
// navázání všech výkonových kategorií
$contest->powerCategories()->attach($powerCategories);
// contest parameters pro oba log typy
foreach (['STANDARD', 'CHECK'] as $logType) {
ContestParameter::create(array_merge(
$baseParams,
[
'contest_id' => $contest->id,
'log_type' => $logType,
]
));
}
}
}
}

View File

@@ -0,0 +1,33 @@
<?php
namespace Database\Seeders;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
use App\Models\CountryWwl;
class CountriesWwlSeeder extends Seeder
{
/**
* Run the database seeds.
*/
public function run(): void
{
CountryWwl::truncate();
$heading = true;
$input_file = fopen(base_path("database/seeders/countries_wwl.csv"), "r");
while (($record = fgetcsv($input_file, 10000, ";", '"', '\\')) !== FALSE)
{
if (!$heading)
{
$wwl = array(
"country_name" => $record['0'],
"wwl" => $record['1']
);
CountryWwl::create($wwl);
}
$heading = false;
}
fclose($input_file);
}
}

View File

@@ -0,0 +1,169 @@
<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
class CtySeeder extends Seeder
{
public function run(): void
{
$path = storage_path('data/cty_wt_mod.dat.gz');
if (! file_exists($path)) {
$path = storage_path('data/cty_wt.dat.gz');
}
if (! file_exists($path)) {
return;
}
DB::table('cty')->truncate();
$handle = gzopen($path, 'rb');
if (! $handle) {
return;
}
$dxcc = null;
$current = null;
$prefixBuffer = '';
$batch = [];
$batchSize = 500;
$source = 'cty_wt.dat';
$now = now();
$flush = function () use (&$batch) {
if (! $batch) {
return;
}
DB::table('cty')->upsert(
$batch,
['prefix'],
[
'country_name',
'dxcc',
'cq_zone',
'itu_zone',
'continent',
'latitude',
'longitude',
'time_offset',
'prefix_norm',
'precise',
'source',
'updated_at',
]
);
$batch = [];
};
$addPrefix = function (string $token, array $current, bool $preciseOverride = false) use (&$batch, $batchSize, $now, $flush) {
$rawToken = trim($token);
if ($rawToken === '') {
return;
}
$precise = $preciseOverride || str_starts_with($rawToken, '=');
$prefix = $rawToken;
$normToken = $rawToken;
if (str_starts_with($normToken, '=')) {
$normToken = substr($normToken, 1);
}
$normToken = trim($normToken);
$normToken = preg_split('/[\\(\\[<\\{~]/', $normToken, 2)[0] ?? '';
$normToken = strtoupper(trim($normToken));
if ($normToken === '') {
return;
}
$batch[] = [
'country_name' => $current['country_name'],
'dxcc' => $current['dxcc'],
'cq_zone' => $current['cq_zone'],
'itu_zone' => $current['itu_zone'],
'continent' => $current['continent'],
'latitude' => $current['latitude'],
'longitude' => $current['longitude'],
'time_offset' => $current['time_offset'],
'prefix' => $prefix,
'prefix_norm' => $normToken,
'precise' => $precise,
'source' => $current['source'],
'created_at' => $now,
'updated_at' => $now,
];
if (count($batch) >= $batchSize) {
$flush();
}
};
while (($line = gzgets($handle)) !== false) {
$line = rtrim($line, "\r\n");
if ($line === '') {
continue;
}
if (str_starts_with($line, '#')) {
if (preg_match('/ADIF\\s+(\\d+)/', $line, $match)) {
$dxcc = (int) $match[1];
}
continue;
}
if (! preg_match('/^\\s/', $line)) {
$prefixBuffer = '';
if (preg_match(
'/^([^:]+):\\s*([0-9]+):\\s*([0-9]+):\\s*([A-Z]{2}):\\s*([0-9\\.-]+):\\s*([0-9\\.-]+):\\s*([0-9\\.-]+):\\s*([^:]+):/',
$line,
$match
)) {
$current = [
'country_name' => trim($match[1]),
'dxcc' => $dxcc,
'cq_zone' => (int) $match[2],
'itu_zone' => (int) $match[3],
'continent' => trim($match[4]),
'latitude' => (float) $match[5],
'longitude' => (float) $match[6],
'time_offset' => (float) $match[7],
'source' => $source,
];
$primaryPrefix = trim($match[8]);
if ($primaryPrefix !== '') {
$addPrefix($primaryPrefix, $current);
}
} else {
$current = null;
}
continue;
}
if (! $current) {
continue;
}
$segment = trim($line);
if ($segment === '') {
continue;
}
$prefixBuffer .= ' ' . $segment;
if (str_contains($segment, ';')) {
$prefixBuffer = rtrim($prefixBuffer, ';');
$tokens = array_map('trim', explode(',', $prefixBuffer));
foreach ($tokens as $token) {
$addPrefix($token, $current);
}
$prefixBuffer = '';
}
}
$flush();
gzclose($handle);
}
}

View File

@@ -0,0 +1,42 @@
<?php
namespace Database\Seeders;
use App\Models\User;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
class DatabaseSeeder extends Seeder
{
use WithoutModelEvents;
/**
* Seed the application's database.
*/
public function run(): void
{
// User::factory(10)->create();
User::factory()->create([
'name' => 'Test User',
'email' => 'test@test.com',
'is_admin' => true
]);
$this->call([
BandEdiBandSeeder::class,
CategoriesEdiCategoriesSeeder::class,
PowerCategoriesSeeder::class,
CtySeeder::class,
CountriesWwlSeeder::class,
ContestSeeder::class,
RoundSeeder::class,
EvaluationRuleSetSeeder::class,
NewsPostSeeder::class
]);
if (env('RUN_EVAL_REGRESSION_SEEDER')) {
$this->call(EvaluationPipelineRegressionSeeder::class);
}
}
}

View File

@@ -0,0 +1,52 @@
<?php
namespace Database\Seeders;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
class EdiBandSeeder extends Seeder
{
/**
* Run the database seeds.
*/
public function run(): void
{
Schema::disableForeignKeyConstraints();
DB::table('edi_bands')->truncate();
Schema::enableForeignKeyConstraints();
$edi_bands = [
['value' => '50 Mhz'], //1
['value' => '144 Mhz'], //2
['value' => '145 Mhz'], //3
['value' => '432 Mhz'], //4
['value' => '435 Mhz'], //5
['value' => '1.2 Ghz'], //6
['value' => '1.3 Ghz'], //7
['value' => '2.3 Ghz'], //8
['value' => '2.4 Ghz'], //9
['value' => '3.4 Ghz'], //10
['value' => '5.7 Ghz'], //11
['value' => '10 Ghz'], //12
['value' => '24 Ghz'], //13
['value' => '47 Ghz'], //14
['value' => '76 Ghz'], //15
['value' => '120 Ghz'], //16
['value' => '122 Ghz'], //17
['value' => '134 Ghz'], //18
['value' => '144 Ghz'], //19
['value' => '248 Ghz'], //20
];
foreach ($edi_bands as &$edi_band) {
$edi_band['created_at'] = now();
$edi_band['updated_at'] = now();
};
DB::table('edi_bands')->insert($edi_bands);
}
}

View File

@@ -0,0 +1,44 @@
<?php
namespace Database\Seeders;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
class EdiCategoriesSeeder extends Seeder
{
/**
* Run the database seeds.
*/
public function run(): void
{
Schema::disableForeignKeyConstraints();
DB::table('edi_categories')->truncate();
Schema::enableForeignKeyConstraints();
$ediCategories = [
[
'value' => 'SINGLE',
'regex_pattern' => '^[\\w\\s-]*\\b(?:single|so)\\b'
], //1
['value' => 'SINGLE-OP', 'regex_pattern' => '' ], //2
['value' => 'SO', 'regex_pattern' => '' ], //3
['value' => 'SINGLE QRP', 'regex_pattern' => '' ], //4
['value' => 'SO-LP', 'regex_pattern' => '' ], //5
['value' => 'MULTI', 'regex_pattern' => '^[\w\s-]*\b(?:multi|mo)\b' ], //6
['value' => 'MO-LP', 'regex_pattern' => '' ], //7
['value' => 'CHECK', 'regex_pattern' => '' ], //8
['value' => 'CHECKLOG', 'regex_pattern' => '' ], //9
];
foreach ($ediCategories as &$ediCategory) {
$ediCategory['created_at'] = now();
$ediCategory['updated_at'] = now();
};
DB::table('edi_categories')->insert($ediCategories);
}
}

View File

@@ -0,0 +1,504 @@
<?php
namespace Database\Seeders;
use App\Jobs\BuildWorkingSetJob;
use App\Jobs\DuplicateResolutionJob;
use App\Jobs\MatchQsoGroupJob;
use App\Jobs\PrepareRunJob;
use App\Jobs\ScoreGroupJob;
use App\Jobs\UnpairedClassificationJob;
use App\Models\Band;
use App\Models\Category;
use App\Models\Contest;
use App\Models\EvaluationRuleSet;
use App\Models\EvaluationRun;
use App\Models\Log;
use App\Models\LogQso;
use App\Models\PowerCategory;
use App\Models\QsoResult;
use App\Models\Round;
use App\Models\WorkingQso;
use Illuminate\Database\Seeder;
use Illuminate\Support\Carbon;
use RuntimeException;
/**
* Seeder: EvaluationPipelineRegressionSeeder
*
* Vytváří mini dataset a spouští klíčové kroky pipeline synchronně.
* Slouží jako minimální regresní scénáře bez plného test frameworku.
*/
class EvaluationPipelineRegressionSeeder extends Seeder
{
public function run(): void
{
$band = Band::firstOrCreate(
['name' => '145 MHz'],
[
'order' => 1,
'edi_band_begin' => 144.0,
'edi_band_end' => 146.0,
'has_power_category' => true,
]
);
$category = Category::firstOrCreate(
['name' => 'SINGLE'],
[
'order' => 1,
]
);
$power = PowerCategory::firstOrCreate(
['name' => 'LP'],
[
'order' => 1,
'power_level' => 100,
]
);
$ruleSetUnique = EvaluationRuleSet::firstOrCreate(
['code' => 'REG_UNIQUE'],
[
'name' => 'Regression UNIQUE',
'scoring_mode' => 'FIXED_POINTS',
'points_per_qso' => 1,
'use_multipliers' => false,
'dup_qso_policy' => 'ZERO_POINTS',
'nil_qso_policy' => 'ZERO_POINTS',
'busted_call_policy' => 'ZERO_POINTS',
'busted_exchange_policy' => 'ZERO_POINTS',
'time_tolerance_sec' => 60,
'require_unique_qso' => true,
]
);
$ruleSetNoUnique = EvaluationRuleSet::firstOrCreate(
['code' => 'REG_DUP'],
[
'name' => 'Regression DUP',
'scoring_mode' => 'FIXED_POINTS',
'points_per_qso' => 1,
'use_multipliers' => false,
'dup_qso_policy' => 'ZERO_POINTS',
'nil_qso_policy' => 'ZERO_POINTS',
'busted_call_policy' => 'ZERO_POINTS',
'busted_exchange_policy' => 'ZERO_POINTS',
'time_tolerance_sec' => 60,
'require_unique_qso' => false,
]
);
$ruleSetTimeMismatch = EvaluationRuleSet::firstOrCreate(
['code' => 'REG_TIME_MISMATCH'],
[
'name' => 'Regression TIME_MISMATCH',
'scoring_mode' => 'FIXED_POINTS',
'points_per_qso' => 1,
'use_multipliers' => false,
'dup_qso_policy' => 'ZERO_POINTS',
'nil_qso_policy' => 'ZERO_POINTS',
'busted_call_policy' => 'ZERO_POINTS',
'busted_exchange_policy' => 'ZERO_POINTS',
'time_tolerance_sec' => 60,
'allow_time_mismatch_pairing' => true,
'time_mismatch_max_sec' => 600,
'time_mismatch_policy' => 'ZERO_POINTS',
]
);
$ruleSetFlags = EvaluationRuleSet::firstOrCreate(
['code' => 'REG_FLAGS'],
[
'name' => 'Regression FLAGS',
'scoring_mode' => 'FIXED_POINTS',
'points_per_qso' => 1,
'use_multipliers' => false,
'dup_qso_policy' => 'ZERO_POINTS',
'nil_qso_policy' => 'ZERO_POINTS',
'busted_call_policy' => 'ZERO_POINTS',
'busted_exchange_policy' => 'ZERO_POINTS',
'exchange_requires_report' => true,
'exchange_requires_serial' => true,
'rst_ignore_third_char' => true,
'ignore_slash_part' => true,
'callsign_suffix_max_len' => 4,
'callsign_levenshtein_max' => 1,
'discard_qso_rec_diff_rst' => true,
'discard_qso_rec_diff_serial' => true,
'time_tolerance_sec' => 60,
]
);
$contest = Contest::create([
'name' => ['cs' => 'Regression Contest', 'en' => 'Regression Contest'],
'description' => ['cs' => 'Regresní sada', 'en' => 'Regression set'],
'is_active' => false,
'is_test' => true,
'rule_set_id' => $ruleSetUnique->id,
]);
$contest->bands()->sync([$band->id]);
$contest->categories()->sync([$category->id]);
$contest->powerCategories()->sync([$power->id]);
$this->scenarioUniqueGlobal($contest, $band, $category, $power, $ruleSetUnique);
$this->scenarioUniqueNotGlobal($contest, $band, $category, $power, $ruleSetUnique);
$this->scenarioDuplicateResolution($contest, $band, $category, $power, $ruleSetNoUnique);
$this->scenarioTimeMismatchPolicy($contest, $band, $category, $power, $ruleSetTimeMismatch);
$this->scenarioFlagCoverage($contest, $band, $category, $power, $ruleSetFlags);
}
private function scenarioUniqueGlobal(
Contest $contest,
Band $band,
Category $category,
PowerCategory $power,
EvaluationRuleSet $ruleSet
): void {
$round = $this->makeRound($contest, $ruleSet, 'UNIQUE global');
$this->attachRoundScopes($round, $band, $category, $power);
$log = $this->makeLog($round, 'OK1AAA', 'JN79AB', '145');
$qso = LogQso::create([
'log_id' => $log->id,
'qso_index' => 1,
'time_on' => Carbon::parse($round->start_time)->addMinutes(5),
'freq_khz' => 144000,
'my_call' => 'OK1AAA',
'dx_call' => 'UNIQUE1',
'my_locator' => 'JN79AB',
'rx_wwl' => 'JN79AB',
]);
$run = $this->makeRun($round, $ruleSet);
$this->runPipeline($run);
$errorCode = QsoResult::where('evaluation_run_id', $run->id)
->where('log_qso_id', $qso->id)
->value('error_code');
if ($errorCode !== 'UNIQUE') {
throw new RuntimeException("Regression UNIQUE global selhal: očekáván UNIQUE, got {$errorCode}.");
}
}
private function scenarioUniqueNotGlobal(
Contest $contest,
Band $band,
Category $category,
PowerCategory $power,
EvaluationRuleSet $ruleSet
): void {
$round = $this->makeRound($contest, $ruleSet, 'UNIQUE not global');
$this->attachRoundScopes($round, $band, $category, $power);
$logA = $this->makeLog($round, 'OK1AAB', 'JN79AB', '145');
$logB = $this->makeLog($round, 'OK1AAC', 'JN79AB', '145');
$qsoA = LogQso::create([
'log_id' => $logA->id,
'qso_index' => 1,
'time_on' => Carbon::parse($round->start_time)->addMinutes(5),
'freq_khz' => 144000,
'my_call' => 'OK1AAB',
'dx_call' => 'X2AAA',
'my_locator' => 'JN79AB',
'rx_wwl' => 'JN79AB',
]);
LogQso::create([
'log_id' => $logB->id,
'qso_index' => 1,
'time_on' => Carbon::parse($round->start_time)->addMinutes(6),
'freq_khz' => 144000,
'my_call' => 'OK1AAC',
'dx_call' => 'X2AAA',
'my_locator' => 'JN79AB',
'rx_wwl' => 'JN79AB',
]);
$run = $this->makeRun($round, $ruleSet);
$this->runPipeline($run);
$errorCode = QsoResult::where('evaluation_run_id', $run->id)
->where('log_qso_id', $qsoA->id)
->value('error_code');
if ($errorCode === 'UNIQUE') {
throw new RuntimeException('Regression UNIQUE not global selhal: UNIQUE nesmí vzniknout.');
}
}
private function scenarioDuplicateResolution(
Contest $contest,
Band $band,
Category $category,
PowerCategory $power,
EvaluationRuleSet $ruleSet
): void {
$round = $this->makeRound($contest, $ruleSet, 'DUP resolution');
$this->attachRoundScopes($round, $band, $category, $power);
$log = $this->makeLog($round, 'OK1DUP', 'JN79AB', '145');
LogQso::create([
'log_id' => $log->id,
'qso_index' => 1,
'time_on' => Carbon::parse($round->start_time)->addMinutes(5),
'freq_khz' => 144000,
'my_call' => 'OK1DUP',
'dx_call' => 'DUP1',
'my_locator' => 'JN79AB',
'rx_wwl' => 'JN79AB',
]);
LogQso::create([
'log_id' => $log->id,
'qso_index' => 2,
'time_on' => Carbon::parse($round->start_time)->addMinutes(6),
'freq_khz' => 144000,
'my_call' => 'OK1DUP',
'dx_call' => 'DUP1',
'my_locator' => 'JN79AB',
'rx_wwl' => 'JN79AB',
]);
$run = $this->makeRun($round, $ruleSet);
$this->runPipeline($run);
$dupCount = QsoResult::where('evaluation_run_id', $run->id)
->where('error_code', 'DUP')
->count();
if ($dupCount !== 1) {
throw new RuntimeException("Regression DUP selhal: očekáván 1 DUP, got {$dupCount}.");
}
}
private function scenarioTimeMismatchPolicy(
Contest $contest,
Band $band,
Category $category,
PowerCategory $power,
EvaluationRuleSet $ruleSet
): void {
$round = $this->makeRound($contest, $ruleSet, 'TIME_MISMATCH policy');
$this->attachRoundScopes($round, $band, $category, $power);
$logA = $this->makeLog($round, 'OK1TMA', 'JN79AB', '145');
$logB = $this->makeLog($round, 'OK1TMB', 'JN79AB', '145');
$timeA = Carbon::parse($round->start_time)->addMinutes(5);
$timeB = Carbon::parse($round->start_time)->addMinutes(9);
$qsoA = LogQso::create([
'log_id' => $logA->id,
'qso_index' => 1,
'time_on' => $timeA,
'freq_khz' => 144000,
'my_call' => 'OK1TMA',
'dx_call' => 'OK1TMB',
'my_serial' => '001',
'dx_serial' => '002',
'my_locator' => 'JN79AB',
'rx_wwl' => 'JN79AB',
]);
LogQso::create([
'log_id' => $logB->id,
'qso_index' => 1,
'time_on' => $timeB,
'freq_khz' => 144000,
'my_call' => 'OK1TMB',
'dx_call' => 'OK1TMA',
'my_serial' => '002',
'dx_serial' => '001',
'my_locator' => 'JN79AB',
'rx_wwl' => 'JN79AB',
]);
$run = $this->makeRun($round, $ruleSet);
$this->runPipeline($run);
$result = QsoResult::where('evaluation_run_id', $run->id)
->where('log_qso_id', $qsoA->id)
->first();
if (! $result || $result->error_code !== 'TIME_MISMATCH') {
throw new RuntimeException('Regression TIME_MISMATCH selhal: očekáván TIME_MISMATCH.');
}
if (! $result->is_valid || (int) $result->points !== 0) {
throw new RuntimeException('Regression TIME_MISMATCH selhal: očekáván validní QSO s 0 body.');
}
}
private function scenarioFlagCoverage(
Contest $contest,
Band $band,
Category $category,
PowerCategory $power,
EvaluationRuleSet $ruleSet
): void {
$round = $this->makeRound($contest, $ruleSet, 'FLAGS coverage');
$this->attachRoundScopes($round, $band, $category, $power);
$logSuffix = $this->makeLog($round, 'OK1AAA/P', 'JN79AB', '145');
$qsoFuzzySource = LogQso::create([
'log_id' => $logSuffix->id,
'qso_index' => 1,
'time_on' => Carbon::parse($round->start_time)->addMinutes(2),
'freq_khz' => 144000,
'my_call' => 'OK1AAA/P',
'dx_call' => 'OK1AAB',
'my_rst' => '599',
'dx_rst' => '599',
'my_serial' => '001',
'dx_serial' => '002',
'my_locator' => 'JN79AB',
'rx_wwl' => 'JN79AB',
]);
$logFuzzy = $this->makeLog($round, 'OK1AAB', 'JN79AB', '145');
$qsoFuzzy = LogQso::create([
'log_id' => $logFuzzy->id,
'qso_index' => 1,
'time_on' => Carbon::parse($round->start_time)->addMinutes(2),
'freq_khz' => 144000,
'my_call' => 'OK1AAB',
'dx_call' => 'OK1AAX',
'my_rst' => '599',
'dx_rst' => '599',
'my_serial' => '002',
'dx_serial' => '001',
'my_locator' => 'JN79AB',
'rx_wwl' => 'JN79AB',
]);
$logSerial = $this->makeLog($round, 'OK1SER', 'JN79AB', '145');
$qsoSerialMismatch = LogQso::create([
'log_id' => $logSuffix->id,
'qso_index' => 2,
'time_on' => Carbon::parse($round->start_time)->addMinutes(3),
'freq_khz' => 144000,
'my_call' => 'OK1AAA/P',
'dx_call' => 'OK1SER',
'my_rst' => '599',
'dx_rst' => '599',
'my_serial' => '005',
'dx_serial' => '006',
'my_locator' => 'JN79AB',
'rx_wwl' => 'JN79AB',
]);
LogQso::create([
'log_id' => $logSerial->id,
'qso_index' => 1,
'time_on' => Carbon::parse($round->start_time)->addMinutes(3),
'freq_khz' => 144000,
'my_call' => 'OK1SER',
'dx_call' => 'OK1AAA',
'my_rst' => '599',
'dx_rst' => '599',
'my_serial' => '007',
'dx_serial' => '008',
'my_locator' => 'JN79AB',
'rx_wwl' => 'JN79AB',
]);
$run = $this->makeRun($round, $ruleSet);
$this->runPipeline($run);
$suffixNorm = \App\Models\WorkingQso::where('evaluation_run_id', $run->id)
->where('log_id', $logSuffix->id)
->value('call_norm');
if ($suffixNorm !== 'OK1AAA') {
throw new RuntimeException('Regression FLAGS selhal: callsign suffix nebyl normalizován.');
}
$fuzzyResult = QsoResult::where('evaluation_run_id', $run->id)
->where('log_qso_id', $qsoFuzzy->id)
->first();
if (! $fuzzyResult || $fuzzyResult->match_type !== 'MATCH_FUZZY_CALL_1') {
throw new RuntimeException('Regression FLAGS selhal: callsign_levenshtein_max neovlivňuje matching.');
}
if ($fuzzyResult->error_code === 'BUSTED_RST') {
throw new RuntimeException('Regression FLAGS selhal: rst_ignore_third_char nebylo zohledněno.');
}
$serialResult = QsoResult::where('evaluation_run_id', $run->id)
->where('log_qso_id', $qsoSerialMismatch->id)
->where('error_code', 'BUSTED_SERIAL')
->first();
if (! $serialResult) {
throw new RuntimeException('Regression FLAGS selhal: discard_qso_rec_diff_serial nebylo zohledněno.');
}
}
private function runPipeline(EvaluationRun $run): void
{
(new PrepareRunJob($run->id))->handle();
(new BuildWorkingSetJob($run->id))->handle();
$run = EvaluationRun::find($run->id);
$group = $run && isset($run->scope['groups'][0])
? $run->scope['groups'][0]
: [
'key' => 'b0',
'band_id' => null,
'category_id' => null,
'power_category_id' => null,
];
if (! ($group['band_id'] ?? null)) {
$workingBandId = WorkingQso::where('evaluation_run_id', $run->id)
->whereNotNull('band_id')
->value('band_id');
if ($workingBandId) {
$group['band_id'] = (int) $workingBandId;
$group['key'] = 'b' . $workingBandId;
}
}
$groupKey = $group['key'] ?? 'b0';
(new MatchQsoGroupJob($run->id, $groupKey, $group, 1))->handle();
(new MatchQsoGroupJob($run->id, $groupKey, $group, 2))->handle();
(new UnpairedClassificationJob($run->id))->handle();
(new DuplicateResolutionJob($run->id))->handle();
(new ScoreGroupJob($run->id, $groupKey, $group))->handle();
}
private function makeRound(Contest $contest, EvaluationRuleSet $ruleSet, string $label): Round
{
$start = now()->subDays(1);
$end = now()->subDays(1)->addHours(5);
return Round::create([
'contest_id' => $contest->id,
'rule_set_id' => $ruleSet->id,
'name' => ['cs' => "Regrese {$label}", 'en' => "Regression {$label}"],
'description' => ['cs' => 'Regresní běh', 'en' => 'Regression run'],
'is_test' => true,
'is_active' => false,
'start_time' => $start,
'end_time' => $end,
'logs_deadline' => now(),
]);
}
private function attachRoundScopes(Round $round, Band $band, Category $category, PowerCategory $power): void
{
$round->bands()->sync([$band->id]);
$round->categories()->sync([$category->id]);
$round->powerCategories()->sync([$power->id]);
}
private function makeLog(Round $round, string $pcall, string $pwwlo, string $pband): Log
{
return Log::create([
'round_id' => $round->id,
'pcall' => $pcall,
'pwwlo' => $pwwlo,
'pband' => $pband,
'power_category_id' => PowerCategory::first()?->id,
]);
}
private function makeRun(Round $round, EvaluationRuleSet $ruleSet): EvaluationRun
{
return EvaluationRun::create([
'round_id' => $round->id,
'rule_set_id' => $ruleSet->id,
'status' => 'PENDING',
'current_step' => 'seed',
'is_official' => false,
'result_type' => 'TEST',
]);
}
}

View File

@@ -0,0 +1,107 @@
<?php
namespace Database\Seeders;
use App\Models\EvaluationRuleSet;
use Illuminate\Database\Seeder;
class EvaluationRuleSetSeeder extends Seeder
{
public function run(): void
{
// Compat profil: co nejvyšší matching coverage, neshody řeší až scoring policy.
// Pro přísnější režim: zapnout match_require_* a penalizace, snížit toleranci času,
// případně zapnout multiplikátory.
EvaluationRuleSet::updateOrCreate(
['code' => 'default_vhf_compat'],
[
'name' => 'Default VHF (compat)',
'description' => 'Permisivní profil maximalizuje matching, mismatchy řeší policy ve scoringu.',
'scoring_mode' => 'DISTANCE',
'points_per_qso' => 1,
'points_per_km' => 1.0,
'use_multipliers' => false,
'multiplier_type' => 'WWL',
'dup_qso_policy' => 'ZERO_POINTS',
'nil_qso_policy' => 'ZERO_POINTS',
'no_counterpart_log_policy' => 'FLAG_ONLY',
'not_in_counterpart_log_policy' => 'ZERO_POINTS',
'unique_qso_policy' => 'FLAG_ONLY',
'busted_call_policy' => 'ZERO_POINTS',
'busted_exchange_policy' => 'ZERO_POINTS',
'busted_serial_policy' => 'ZERO_POINTS',
'busted_locator_policy' => 'ZERO_POINTS',
'busted_rst_policy' => 'ZERO_POINTS',
'penalty_busted_rst_points' => 0,
'penalty_dup_points' => 0,
'penalty_nil_points' => 0,
'penalty_busted_call_points' => 0,
'penalty_busted_exchange_points' => 0,
'penalty_busted_serial_points' => 0,
'penalty_busted_locator_points' => 0,
'dupe_scope' => 'BAND',
'callsign_normalization' => 'IGNORE_SUFFIX',
'distance_rounding' => 'CEIL',
'min_distance_km' => 1,
'require_locators' => false,
'out_of_window_policy' => 'INVALID',
'penalty_out_of_window_points' => 0,
'exchange_type' => 'SERIAL_WWL',
'exchange_requires_wwl' => true,
'exchange_requires_serial' => true,
'exchange_requires_report' => true,
'exchange_pattern' => null,
'ignore_slash_part' => true,
'ignore_third_part' => true,
'letters_in_rst' => false,
'rst_ignore_third_char' => true,
'discard_qso_rec_diff_call' => true,
'discard_qso_sent_diff_call' => false,
'discard_qso_rec_diff_rst' => true,
'discard_qso_sent_diff_rst' => false,
'discard_qso_rec_diff_code' => true,
'discard_qso_sent_diff_code' => false,
'discard_qso_rec_diff_serial' => true,
'discard_qso_sent_diff_serial' => false,
'discard_qso_rec_diff_wwl' => true,
'discard_qso_sent_diff_wwl' => false,
'match_tiebreak_order' => [
'time_diff',
'exchange_match',
'locator_match',
'report_match',
'log_qso_id',
],
'match_require_locator_match' => false,
'match_require_exchange_match' => false,
'multiplier_scope' => 'PER_BAND',
'multiplier_source' => 'VALID_ONLY',
'wwl_multiplier_level' => 'LOCATOR_6',
'checklog_matching' => true,
'out_of_window_dq_threshold' => 600,
'time_diff_dq_threshold_percent' => 30,
'time_diff_dq_threshold_sec' => 600,
'bad_qso_dq_threshold_percent' => 30,
'time_tolerance_sec' => 600,
'require_unique_qso' => true,
'allow_time_mismatch_pairing' => false,
'time_mismatch_max_sec' => null,
'allow_time_shift_one_hour' => true,
'time_shift_seconds' => 3600,
'time_mismatch_policy' => 'ZERO_POINTS',
'callsign_suffix_max_len' => 4,
'callsign_levenshtein_max' => 0,
'dup_resolution_strategy' => [
'paired_first',
'ok_first',
'earlier_time',
'lower_id',
],
'operating_window_mode' => 'NONE',
'operating_window_hours' => null,
'sixhr_ranking_mode' => 'IARU',
'options' => null,
]
);
}
}

View File

@@ -0,0 +1,136 @@
<?php
namespace Database\Seeders;
use App\Models\NewsPost;
use Illuminate\Database\Seeder;
use Illuminate\Support\Str;
class NewsPostSeeder extends Seeder
{
public function run(): void
{
// Pozor: pokud už máš v produkci data, truncate nepoužívej.
NewsPost::truncate();
$items = [
[
'title' => [
'cs' => 'Vývojová verze nového vyhodnocovacího systému VKV závodů',
'en' => 'Development version of the new VHF contest evaluation system',
],
'content' => [
'cs' => <<<MD
## Vývojová verze
Tento systém pro vyhodnocování VKV závodů je aktuálně ve vývojové verzi.
**Co to znamená:**
- mohou se objevit chyby nebo nekompletní funkce
- data a výsledky se mohou ještě měnit
- budeme rádi za zpětnou vazbu a nahlášené problémy
MD,
'en' => <<<MD
## Development version
This VHF contest evaluation system is currently a development version.
**What this means:**
- features may be incomplete and bugs may appear
- data and results may still change
- we welcome feedback and reported issues
MD,
],
'excerpt' => [
'cs' => 'Nový systém pro vyhodnocování VKV závodů je ve vývoji.',
'en' => 'The new VHF contest evaluation system is in development.',
],
'is_published' => true,
'published_at' => now()->subDays(7),
],
[
'title' => [
'cs' => 'Plánovaná údržba systému',
'en' => 'Planned system maintenance',
],
'content' => [
'cs' => <<<MD
## Plánovaná údržba
Systém bude nedostupný **15. 12. 2025** mezi *22:0023:00 CET* z důvodu údržby databáze.
Po dobu odstávky nebude možné:
- odesílat logy
- prohlížet výsledky
MD,
'en' => <<<MD
## Planned maintenance
The system will be unavailable on **15 Dec 2025** between *22:0023:00 CET* due to database maintenance.
During this window it will not be possible to:
- submit logs
- view results
MD,
],
'excerpt' => [
'cs' => 'Plánovaná odstávka systému 15. 12. 2025 mezi 22:0023:00 CET.',
'en' => 'Planned downtime on 15 Dec 2025 between 22:0023:00 CET.',
],
'is_published' => false,
'published_at' => now()->subDays(3),
],
[
'title' => [
'cs' => 'Testovací novinka pouze v češtině',
'en' => 'Test news item (Czech only translation)',
],
'content' => [
'cs' => <<<MD
## Testovací novinka
Tato novinka slouží k otestování zobrazení lokalizovaného obsahu v uživatelském rozhraní.
MD,
'en' => <<<MD
## Test news item
This news entry is used to test localized content rendering in the user interface.
MD,
],
'excerpt' => [
'cs' => 'Testovací novinka pro ověření lokalizace.',
'en' => 'Test news item for localization checks.',
],
'is_published' => false,
'published_at' => now()->subDay(),
],
];
foreach ($items as $item) {
// slug vygenerujeme z českého titulku (nebo fallback na en)
$titleForSlug = $item['title']['cs']
?? $item['title']['en']
?? reset($item['title']);
$slug = Str::slug($titleForSlug);
$news = new NewsPost();
// lokalizované položky nastavíme explicitně jako překlady
$news->setTranslations('title', $item['title']);
$news->setTranslations('content', $item['content']);
$news->setTranslations('excerpt', $item['excerpt']);
$news->slug = $slug;
$news->is_published = $item['is_published'];
$news->published_at = $item['published_at'];
$news->author_id = null; // nebo nějaký konkrétní user_id
$news->save();
}
}
}

View File

@@ -0,0 +1,36 @@
<?php
namespace Database\Seeders;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
class PowerCategoriesSeeder extends Seeder
{
/**
* Run the database seeds.
*/
public function run(): void
{
Schema::disableForeignKeyConstraints();
DB::table('power_categories')->truncate();
Schema::enableForeignKeyConstraints();
$powerCategories = [
['name' => 'LP', 'order' => 10, 'power_level' => 100],
['name' => 'QRP', 'order' => 20, 'power_level' => 5],
['name' => 'N', 'order' => 30, 'power_level' => 10],
['name' => 'A', 'order' => 40, 'power_level' => 100000000],
];
foreach ($powerCategories as &$powerCategory) {
$powerCategory['created_at'] = now();
$powerCategory['updated_at'] = now();
};
DB::table('power_categories')->insert($powerCategories);
}
}

View File

@@ -0,0 +1,88 @@
<?php
namespace Database\Seeders;
use App\Models\Contest;
use App\Models\Round;
use App\Models\Band;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
class RoundSeeder extends Seeder
{
/**
* Run the database seeds.
*/
public function run(): void
{
Schema::disableForeignKeyConstraints();
DB::table('rounds')->truncate();
DB::table('rounds_bands')->truncate();
DB::table('rounds_categories')->truncate();
DB::table('rounds_power_categories')->truncate();
DB::table('evaluation_runs')->truncate();
Schema::enableForeignKeyConstraints();
$bands = Band::all()->pluck('id')->toArray();
$contests = Contest::with(['categories', 'powerCategories'])->get();
if ($contests->isEmpty()) {
// contest se zakládá přes ContestSeeder pokud chybí, nic neseedujeme
return;
}
$globalStart = now()->startOfMonth()->setTime(14, 0);
foreach ($contests as $contestIndex => $contest) {
$baseStart = (clone $globalStart)->addMonths($contestIndex * 2);
for ($i = 0; $i < 2; $i++) {
$start = (clone $baseStart)->addMonths($i);
$end = (clone $start)->addHours(24);
$deadline = (clone $end)->addDays(3);
$round = new Round();
$round->contest_id = $contest->id;
$round->rule_set_id = $contest->rule_set_id;
$round->setTranslations('name', [
'cs' => 'Kolo ' . ($i + 1) . ' ' . $contest->getTranslation('name', 'cs'),
'en' => 'Round ' . ($i + 1) . ' ' . $contest->getTranslation('name', 'en'),
]);
$round->setTranslations('description', [
'cs' => 'Testovací kolo číslo ' . ($i + 1) . ' pro závod ' . $contest->getTranslation('name', 'cs'),
'en' => 'Test round number ' . ($i + 1) . ' for contest ' . $contest->getTranslation('name', 'en'),
]);
$round->is_active = $i < 8; // poslední dvě kola jako neaktivní
$round->is_test = $i === 0; // první kolo jako testovací
$round->is_sixhr = $i % 2 === 1; // lichá kola jako 6h
$round->start_time = $start;
$round->end_time = $end;
$round->logs_deadline = $deadline;
$round->save();
// napojení pásem stejné jako u contestu (všechna dostupná)
if (!empty($bands)) {
$round->bands()->attach($bands);
}
// napojení kategorií stejné jako u contestu
$categoryIds = $contest->categories->pluck('id')->toArray();
if (!empty($categoryIds)) {
$round->categories()->attach($categoryIds);
}
// výkonové kategorie stejně jako u contestu
$powerCategoryIds = $contest->powerCategories->pluck('id')->toArray();
if (!empty($powerCategoryIds)) {
$round->powerCategories()->attach($powerCategoryIds);
}
}
}
}
}

View File

@@ -0,0 +1,934 @@
"country_name";"wwl"
African Italy;IM56
African Italy;IM66
Aland Islands;JP90
Aland Islands;KO09
Aland Islands;KP00
Albania;JM99
Albania;JN90
Albania;JN91
Albania;JN92
Albania;KM09
Albania;KN00
Albania;KN01
Albania;KN02
Andorra;JN02
Austria;JN46
Austria;JN47
Austria;JN56
Austria;JN57
Austria;JN66
Austria;JN67
Austria;JN68
Austria;JN76
Austria;JN77
Austria;JN78
Austria;JN79
Austria;JN86
Austria;JN87
Austria;JN88
Balearic Islands;JM08
Balearic Islands;JM09
Balearic Islands;JM19
Balearic Islands;JM29
Balearic Islands;JN10
Balearic Islands;JN20
Belarus;KO11
Belarus;KO12
Belarus;KO13
Belarus;KO21
Belarus;KO22
Belarus;KO23
Belarus;KO24
Belarus;KO31
Belarus;KO32
Belarus;KO33
Belarus;KO34
Belarus;KO35
Belarus;KO36
Belarus;KO41
Belarus;KO42
Belarus;KO43
Belarus;KO44
Belarus;KO45
Belarus;KO46
Belarus;KO51
Belarus;KO52
Belarus;KO53
Belarus;KO54
Belarus;KO55
Belarus;KO63
Belgium;JN29
Belgium;JO10
Belgium;JO11
Belgium;JO20
Belgium;JO21
Belgium;JO30
Bosnia-Herzegovina;JN74
Bosnia-Herzegovina;JN75
Bosnia-Herzegovina;JN82
Bosnia-Herzegovina;JN83
Bosnia-Herzegovina;JN84
Bosnia-Herzegovina;JN85
Bosnia-Herzegovina;JN92
Bosnia-Herzegovina;JN93
Bosnia-Herzegovina;JN94
Bosnia-Herzegovina;JN95
Bulgaria;KN11
Bulgaria;KN12
Bulgaria;KN13
Bulgaria;KN14
Bulgaria;KN21
Bulgaria;KN22
Bulgaria;KN23
Bulgaria;KN31
Bulgaria;KN32
Bulgaria;KN33
Bulgaria;KN34
Bulgaria;KN41
Bulgaria;KN42
Bulgaria;KN43
Ceuta & Melilla;IM75
Ceuta & Melilla;IM85
Corsica;JN41
Corsica;JN42
Corsica;JN43
Crete;KM15
Crete;KM24
Crete;KM25
Crete;KM34
Crete;KM35
Croatia;JN64
Croatia;JN65
Croatia;JN73
Croatia;JN74
Croatia;JN75
Croatia;JN76
Croatia;JN82
Croatia;JN83
Croatia;JN84
Croatia;JN85
Croatia;JN86
Croatia;JN92
Croatia;JN94
Croatia;JN95
Cyprus;KM64
Cyprus;KM65
Cyprus;KM74
Cyprus;KM75
Czech Republic;JN68
Czech Republic;JN69
Czech Republic;JN78
Czech Republic;JN79
Czech Republic;JN88
Czech Republic;JN89
Czech Republic;JN99
Czech Republic;JO60
Czech Republic;JO70
Czech Republic;JO71
Czech Republic;JO80
Czech Republic;JO90
Denmark;JO44
Denmark;JO45
Denmark;JO46
Denmark;JO47
Denmark;JO54
Denmark;JO55
Denmark;JO56
Denmark;JO57
Denmark;JO64
Denmark;JO65
Denmark;JO66
Denmark;JO75
Dodecanese;KM35
England;IN69
England;IN79
England;IN89
England;IO70
England;IO71
England;IO80
England;IO81
England;IO82
England;IO83
England;IO84
England;IO85
England;IO90
England;IO91
England;IO92
England;IO93
England;IO94
England;IO95
England;JO00
England;JO01
England;JO02
England;JO03
Estonia;KO07
Estonia;KO08
Estonia;KO17
Estonia;KO18
Estonia;KO19
Estonia;KO27
Estonia;KO28
Estonia;KO29
Estonia;KO37
Estonia;KO38
Estonia;KO39
Estonia;KO49
European Russia;KN84
European Russia;KN85
European Russia;KN86
European Russia;KN93
European Russia;KN94
European Russia;KN95
European Russia;KN96
European Russia;KN97
European Russia;KN98
European Russia;KN99
European Russia;KO36
European Russia;KO37
European Russia;KO38
European Russia;KO39
European Russia;KO45
European Russia;KO46
European Russia;KO47
European Russia;KO48
European Russia;KO49
European Russia;KO52
European Russia;KO53
European Russia;KO54
European Russia;KO55
European Russia;KO56
European Russia;KO57
European Russia;KO58
European Russia;KO59
European Russia;KO62
European Russia;KO63
European Russia;KO64
European Russia;KO65
European Russia;KO67
European Russia;KO68
European Russia;KO69
European Russia;KO70
European Russia;KO71
European Russia;KO72
European Russia;KO73
European Russia;KO74
European Russia;KO75
European Russia;KO76
European Russia;KO77
European Russia;KO78
European Russia;KO79
European Russia;KO80
European Russia;KO81
European Russia;KO82
European Russia;KO83
European Russia;KO84
European Russia;KO85
European Russia;KO86
European Russia;KO87
European Russia;KO88
European Russia;KO89
European Russia;KO90
European Russia;KO91
European Russia;KO92
European Russia;KO93
European Russia;KO94
European Russia;KO95
European Russia;KO96
European Russia;KO97
European Russia;KO98
European Russia;KO99
European Russia;LN03
European Russia;LN04
European Russia;LN05
European Russia;LN06
European Russia;LN07
European Russia;LN08
European Russia;LN09
European Russia;LN12
European Russia;LN13
European Russia;LN14
European Russia;LN15
European Russia;LN16
European Russia;LN17
European Russia;LN18
European Russia;LN19
European Russia;LN22
European Russia;LN23
European Russia;LN24
European Russia;LN25
European Russia;LN26
European Russia;LN27
European Russia;LN28
European Russia;LN29
European Russia;LN31
European Russia;LN32
European Russia;LN33
European Russia;LN34
European Russia;LN35
European Russia;LN36
European Russia;LN37
European Russia;LN38
European Russia;LN39
European Russia;LN41
European Russia;LN42
European Russia;LN43
European Russia;LN44
European Russia;LN45
European Russia;LN46
European Russia;LN47
European Russia;LN48
European Russia;LN49
European Russia;LO00
European Russia;LO01
European Russia;LO02
European Russia;LO03
European Russia;LO04
European Russia;LO05
European Russia;LO06
European Russia;LO07
European Russia;LO08
European Russia;LO09
European Russia;LO10
European Russia;LO11
European Russia;LO12
European Russia;LO13
European Russia;LO14
European Russia;LO15
European Russia;LO16
European Russia;LO17
European Russia;LO18
European Russia;LO19
European Russia;LO20
European Russia;LO21
European Russia;LO22
European Russia;LO23
European Russia;LO24
European Russia;LO25
European Russia;LO26
European Russia;LO27
European Russia;LO28
European Russia;LO29
European Russia;LO30
European Russia;LO31
European Russia;LO32
European Russia;LO33
European Russia;LO34
European Russia;LO35
European Russia;LO36
European Russia;LO37
European Russia;LO38
European Russia;LO39
European Russia;LO40
European Russia;LO41
European Russia;LO42
European Russia;LO43
European Russia;LO44
European Russia;LO45
European Russia;LO46
European Russia;LO47
European Russia;LO48
European Russia;LO49
Faroe Islands;IP61
Faroe Islands;IP62
Fed. Rep. of Germany;JN37
Fed. Rep. of Germany;JN38
Fed. Rep. of Germany;JN39
Fed. Rep. of Germany;JN47
Fed. Rep. of Germany;JN48
Fed. Rep. of Germany;JN49
Fed. Rep. of Germany;JN57
Fed. Rep. of Germany;JN58
Fed. Rep. of Germany;JN59
Fed. Rep. of Germany;JN67
Fed. Rep. of Germany;JN68
Fed. Rep. of Germany;JN69
Fed. Rep. of Germany;JO20
Fed. Rep. of Germany;JO21
Fed. Rep. of Germany;JO30
Fed. Rep. of Germany;JO31
Fed. Rep. of Germany;JO32
Fed. Rep. of Germany;JO33
Fed. Rep. of Germany;JO34
Fed. Rep. of Germany;JO40
Fed. Rep. of Germany;JO41
Fed. Rep. of Germany;JO42
Fed. Rep. of Germany;JO43
Fed. Rep. of Germany;JO44
Fed. Rep. of Germany;JO50
Fed. Rep. of Germany;JO51
Fed. Rep. of Germany;JO52
Fed. Rep. of Germany;JO53
Fed. Rep. of Germany;JO54
Fed. Rep. of Germany;JO60
Fed. Rep. of Germany;JO61
Fed. Rep. of Germany;JO62
Fed. Rep. of Germany;JO63
Fed. Rep. of Germany;JO64
Fed. Rep. of Germany;JO70
Fed. Rep. of Germany;JO71
Fed. Rep. of Germany;JO72
Fed. Rep. of Germany;JO73
Fed. Rep. of Germany;JO74
Finland;JP90
Finland;KN09
Finland;KO19
Finland;KO29
Finland;KP00
Finland;KP01
Finland;KP02
Finland;KP03
Finland;KP08
Finland;KP09
Finland;KP10
Finland;KP11
Finland;KP12
Finland;KP13
Finland;KP14
Finland;KP16
Finland;KP17
Finland;KP18
Finland;KP20
Finland;KP21
Finland;KP22
Finland;KP23
Finland;KP24
Finland;KP25
Finland;KP26
Finland;KP27
Finland;KP28
Finland;KP29
Finland;KP30
Finland;KP31
Finland;KP32
Finland;KP33
Finland;KP34
Finland;KP35
Finland;KP36
Finland;KP37
Finland;KP38
Finland;KP39
Finland;KP40
Finland;KP41
Finland;KP42
Finland;KP43
Finland;KP44
Finland;KP46
Finland;KP47
Finland;KP48
Finland;KP49
Finland;KP51
Finland;KP52
Finland;KP53
Finland;KP54
Finland;KP55
Finland;KP56
Finland;KP57
Finland;KQ30
Finland;KQ40
France;IN77
France;IN78
France;IN86
France;IN87
France;IN88
France;IN92
France;IN93
France;IN94
France;IN95
France;IN96
France;IN97
France;IN98
France;IN99
France;JN02
France;JN03
France;JN04
France;JN05
France;JN06
France;JN07
France;JN08
France;JN09
France;JN12
France;JN13
France;JN14
France;JN15
France;JN16
France;JN17
France;JN18
France;JN19
France;JN23
France;JN24
France;JN25
France;JN26
France;JN27
France;JN28
France;JN29
France;JN32
France;JN33
France;JN34
France;JN35
France;JN36
France;JN37
France;JN38
France;JN39
France;JN48
France;JN49
France;JO00
France;JO10
France;JO11
France;JO20
Gibraltar;IM76
Greece;JM99
Greece;KM06
Greece;KM07
Greece;KM08
Greece;KM09
Greece;KM15
Greece;KM16
Greece;KM17
Greece;KM18
Greece;KM19
Greece;KM25
Greece;KM26
Greece;KM27
Greece;KM28
Greece;KM29
Greece;KN00
Greece;KN01
Greece;KN10
Greece;KN11
Greece;KN20
Greece;KN21
Greece;KN30
Greece;KN31
Guernsey;IN89
Hungary;JN85
Hungary;JN86
Hungary;JN87
Hungary;JN88
Hungary;JN95
Hungary;JN96
Hungary;JN97
Hungary;JN98
Hungary;KN06
Hungary;KN07
Hungary;KN08
Hungary;KN17
Hungary;KN18
Ireland;IO41
Ireland;IO42
Ireland;IO43
Ireland;IO44
Ireland;IO51
Ireland;IO52
Ireland;IO53
Ireland;IO54
Ireland;IO55
Ireland;IO61
Ireland;IO62
Ireland;IO63
Ireland;IO64
Ireland;IO65
Ireland;IO72
Isle of Man;IO74
Italy;JM68
Italy;JM77
Italy;JM78
Italy;JM79
Italy;JM87
Italy;JM88
Italy;JM89
Italy;JM99
Italy;JN33
Italy;JN34
Italy;JN35
Italy;JN40
Italy;JN43
Italy;JN44
Italy;JN45
Italy;JN46
Italy;JN51
Italy;JN52
Italy;JN53
Italy;JN54
Italy;JN55
Italy;JN56
Italy;JN57
Italy;JN60
Italy;JN61
Italy;JN62
Italy;JN63
Italy;JN64
Italy;JN65
Italy;JN66
Italy;JN67
Italy;JN70
Italy;JN71
Italy;JN72
Italy;JN80
Italy;JN81
Italy;JN90
ITU HQ;JN36
Jan Mayen;IO50
Jan Mayen;IO60
Jan Mayen;IO61
Jersey;IN89
Kaliningrad;JO94
Kaliningrad;KO04
Kaliningrad;KO05
Kaliningrad;KO14
Kaliningrad;KO15
Latvia;KO06
Latvia;KO07
Latvia;KO16
Latvia;KO17
Latvia;KO27
Latvia;KO28
Latvia;KO35
Latvia;KO36
Latvia;KO37
Latvia;KO46
Liechtenstein;JN47
Lithuania;KO05
Lithuania;KO06
Lithuania;KO13
Lithuania;KO14
Lithuania;KO15
Lithuania;KO16
Lithuania;KO23
Lithuania;KO24
Lithuania;KO25
Lithuania;KO26
Lithuania;KO34
Lithuania;KO35
Luxembourg;JN29
Luxembourg;JN39
Luxembourg;JO20
Luxembourg;JO30
Macedonia;KN00
Macedonia;KN01
Macedonia;KN02
Macedonia;KN11
Macedonia;KN12
Malta;JM75
Malta;JM76
Moldova;KN37
Moldova;KN38
Moldova;KN45
Moldova;KN46
Moldova;KN47
Moldova;KN48
Moldova;KN56
Monaco;JN33
Montenegro;JN91
Montenegro;JN92
Montenegro;JN93
Montenegro;KN02
Montenegro;KN03
Netherlands;JO11
Netherlands;JO20
Netherlands;JO21
Netherlands;JO22
Netherlands;JO23
Netherlands;JO30
Netherlands;JO31
Netherlands;JO32
Netherlands;JO33
Northern Ireland;IO54
Northern Ireland;IO64
Northern Ireland;IO65
Northern Ireland;IO74
Northern Ireland;IO75
Poland;JN89
Poland;JN99
Poland;JO70
Poland;JO71
Poland;JO72
Poland;JO73
Poland;JO74
Poland;JO80
Poland;JO81
Poland;JO82
Poland;JO83
Poland;JO84
Poland;JO90
Poland;JO91
Poland;JO92
Poland;JO93
Poland;JO94
Poland;KN09
Poland;KN19
Poland;KO00
Poland;KO01
Poland;KO02
Poland;KO03
Poland;KO04
Poland;KO10
Poland;KO11
Poland;KO12
Poland;KO13
Poland;KO14
Poland;KO20
Portugal;IM56
Portugal;IM57
Portugal;IM58
Portugal;IM59
Portugal;IM66
Portugal;IM67
Portugal;IM68
Portugal;IM69
Portugal;IN50
Portugal;IN51
Portugal;IN52
Portugal;IN60
Portugal;IN61
Romania;KN04
Romania;KN05
Romania;KN06
Romania;KN07
Romania;KN13
Romania;KN14
Romania;KN15
Romania;KN16
Romania;KN17
Romania;KN18
Romania;KN23
Romania;KN24
Romania;KN25
Romania;KN26
Romania;KN27
Romania;KN33
Romania;KN34
Romania;KN35
Romania;KN36
Romania;KN37
Romania;KN38
Romania;KN43
Romania;KN44
Romania;KN45
Romania;KN46
Romania;KN47
Sardinia;JM48
Sardinia;JM49
Sardinia;JN40
Sardinia;JN41
Scotland;IO65
Scotland;IO66
Scotland;IO67
Scotland;IO68
Scotland;IO74
Scotland;IO75
Scotland;IO76
Scotland;IO77
Scotland;IO78
Scotland;IO84
Scotland;IO85
Scotland;IO86
Scotland;IO87
Scotland;IO88
Scotland;IO89
Scotland;IO97
Scotland;IO99
Scotland;IP90
Serbia;JN93
Serbia;JN94
Serbia;JN95
Serbia;JN96
Serbia;KN01
Serbia;KN02
Serbia;KN03
Serbia;KN04
Serbia;KN05
Serbia;KN06
Serbia;KN12
Serbia;KN13
Serbia;KN14
Sicily;JM67
Sicily;JM68
Sicily;JM76
Sicily;JM77
Sicily;JM78
Slovak Republic;JN87
Slovak Republic;JN88
Slovak Republic;JN89
Slovak Republic;JN97
Slovak Republic;JN98
Slovak Republic;JN99
Slovak Republic;KN08
Slovak Republic;KN09
Slovak Republic;KN18
Slovak Republic;KN19
Slovenia;JN64
Slovenia;JN65
Slovenia;JN66
Slovenia;JN73
Slovenia;JN74
Slovenia;JN75
Slovenia;JN76
Slovenia;JN82
Slovenia;JN83
Slovenia;JN84
Slovenia;JN85
Slovenia;JN86
Slovenia;JN92
Spain;IM66
Spain;IM67
Spain;IM68
Spain;IM69
Spain;IM76
Spain;IM77
Spain;IM78
Spain;IM79
Spain;IM86
Spain;IM87
Spain;IM88
Spain;IM89
Spain;IM96
Spain;IM97
Spain;IM98
Spain;IM99
Spain;IN51
Spain;IN52
Spain;IN53
Spain;IN60
Spain;IN61
Spain;IN62
Spain;IN63
Spain;IN70
Spain;IN71
Spain;IN72
Spain;IN73
Spain;IN80
Spain;IN81
Spain;IN82
Spain;IN83
Spain;IN90
Spain;IN91
Spain;IN92
Spain;IN93
Spain;JM08
Spain;JM09
Spain;JN00
Spain;JN01
Spain;JN02
Spain;JN11
Spain;JN12
Svalbard;JQ58
Svalbard;JQ59
Svalbard;JQ67
Svalbard;JQ68
Svalbard;JQ69
Svalbard;JQ76
Svalbard;JQ77
Svalbard;JQ78
Svalbard;JQ79
Svalbard;JQ86
Svalbard;JQ87
Svalbard;JQ88
Svalbard;JQ89
Svalbard;JQ97
Svalbard;JQ98
Svalbard;JQ99
Svalbard;JR80
Svalbard;JR90
Svalbard;KQ07
Svalbard;KQ08
Svalbard;KQ09
Svalbard;KQ17
Svalbard;KQ18
Svalbard;KQ19
Svalbard;KQ26
Svalbard;KQ27
Svalbard;KQ29
Svalbard;KQ38
Svalbard;KQ39
Svalbard;KQ48
Svalbard;KQ49
Svalbard;KR00
Svalbard;KR06
Svalbard;KR07
Svalbard;KR10
Svalbard;KR20
Svalbard;KR30
Sweden;JO57
Sweden;JO58
Sweden;JO59
Sweden;JO65
Sweden;JO66
Sweden;JO67
Sweden;JO68
Sweden;JO69
Sweden;JO74
Sweden;JO75
Sweden;JO76
Sweden;JO77
Sweden;JO78
Sweden;JO79
Sweden;JO86
Sweden;JO87
Sweden;JO88
Sweden;JO89
Sweden;JO96
Sweden;JO97
Sweden;JO98
Sweden;JO99
Sweden;JP53
Sweden;JP60
Sweden;JP61
Sweden;JP62
Sweden;JP63
Sweden;JP64
Sweden;JP70
Sweden;JP71
Sweden;JP72
Sweden;JP73
Sweden;JP74
Sweden;JP75
Sweden;JP76
Sweden;JP80
Sweden;JP81
Sweden;JP82
Sweden;JP83
Sweden;JP84
Sweden;JP85
Sweden;JP86
Sweden;JP87
Sweden;JP88
Sweden;JP90
Sweden;JP92
Sweden;JP93
Sweden;JP94
Sweden;JP95
Sweden;JP96
Sweden;JP97
Sweden;JP98
Sweden;KP03
Sweden;KP04
Sweden;KP05
Sweden;KP06
Sweden;KP07
Sweden;KP08
Sweden;KP09
Sweden;KP15
Sweden;KP16
Sweden;KP17
Sweden;KP18
Sweden;KP25
Switzerland;JN26
Switzerland;JN35
Switzerland;JN36
Switzerland;JN37
Switzerland;JN45
Switzerland;JN46
Switzerland;JN47
Switzerland;JN56
UK Base Areas on Cyprus;KM64
UK Base Areas on Cyprus;KM65
Vatican City;JN61
Vienna Intl Ctr;JN88
Wales;IO71
Wales;IO72
Wales;IO73
Wales;IO81
Wales;IO82
Wales;IO83
Wales;IO93
1 country_name wwl
2 African Italy IM56
3 African Italy IM66
4 Aland Islands JP90
5 Aland Islands KO09
6 Aland Islands KP00
7 Albania JM99
8 Albania JN90
9 Albania JN91
10 Albania JN92
11 Albania KM09
12 Albania KN00
13 Albania KN01
14 Albania KN02
15 Andorra JN02
16 Austria JN46
17 Austria JN47
18 Austria JN56
19 Austria JN57
20 Austria JN66
21 Austria JN67
22 Austria JN68
23 Austria JN76
24 Austria JN77
25 Austria JN78
26 Austria JN79
27 Austria JN86
28 Austria JN87
29 Austria JN88
30 Balearic Islands JM08
31 Balearic Islands JM09
32 Balearic Islands JM19
33 Balearic Islands JM29
34 Balearic Islands JN10
35 Balearic Islands JN20
36 Belarus KO11
37 Belarus KO12
38 Belarus KO13
39 Belarus KO21
40 Belarus KO22
41 Belarus KO23
42 Belarus KO24
43 Belarus KO31
44 Belarus KO32
45 Belarus KO33
46 Belarus KO34
47 Belarus KO35
48 Belarus KO36
49 Belarus KO41
50 Belarus KO42
51 Belarus KO43
52 Belarus KO44
53 Belarus KO45
54 Belarus KO46
55 Belarus KO51
56 Belarus KO52
57 Belarus KO53
58 Belarus KO54
59 Belarus KO55
60 Belarus KO63
61 Belgium JN29
62 Belgium JO10
63 Belgium JO11
64 Belgium JO20
65 Belgium JO21
66 Belgium JO30
67 Bosnia-Herzegovina JN74
68 Bosnia-Herzegovina JN75
69 Bosnia-Herzegovina JN82
70 Bosnia-Herzegovina JN83
71 Bosnia-Herzegovina JN84
72 Bosnia-Herzegovina JN85
73 Bosnia-Herzegovina JN92
74 Bosnia-Herzegovina JN93
75 Bosnia-Herzegovina JN94
76 Bosnia-Herzegovina JN95
77 Bulgaria KN11
78 Bulgaria KN12
79 Bulgaria KN13
80 Bulgaria KN14
81 Bulgaria KN21
82 Bulgaria KN22
83 Bulgaria KN23
84 Bulgaria KN31
85 Bulgaria KN32
86 Bulgaria KN33
87 Bulgaria KN34
88 Bulgaria KN41
89 Bulgaria KN42
90 Bulgaria KN43
91 Ceuta & Melilla IM75
92 Ceuta & Melilla IM85
93 Corsica JN41
94 Corsica JN42
95 Corsica JN43
96 Crete KM15
97 Crete KM24
98 Crete KM25
99 Crete KM34
100 Crete KM35
101 Croatia JN64
102 Croatia JN65
103 Croatia JN73
104 Croatia JN74
105 Croatia JN75
106 Croatia JN76
107 Croatia JN82
108 Croatia JN83
109 Croatia JN84
110 Croatia JN85
111 Croatia JN86
112 Croatia JN92
113 Croatia JN94
114 Croatia JN95
115 Cyprus KM64
116 Cyprus KM65
117 Cyprus KM74
118 Cyprus KM75
119 Czech Republic JN68
120 Czech Republic JN69
121 Czech Republic JN78
122 Czech Republic JN79
123 Czech Republic JN88
124 Czech Republic JN89
125 Czech Republic JN99
126 Czech Republic JO60
127 Czech Republic JO70
128 Czech Republic JO71
129 Czech Republic JO80
130 Czech Republic JO90
131 Denmark JO44
132 Denmark JO45
133 Denmark JO46
134 Denmark JO47
135 Denmark JO54
136 Denmark JO55
137 Denmark JO56
138 Denmark JO57
139 Denmark JO64
140 Denmark JO65
141 Denmark JO66
142 Denmark JO75
143 Dodecanese KM35
144 England IN69
145 England IN79
146 England IN89
147 England IO70
148 England IO71
149 England IO80
150 England IO81
151 England IO82
152 England IO83
153 England IO84
154 England IO85
155 England IO90
156 England IO91
157 England IO92
158 England IO93
159 England IO94
160 England IO95
161 England JO00
162 England JO01
163 England JO02
164 England JO03
165 Estonia KO07
166 Estonia KO08
167 Estonia KO17
168 Estonia KO18
169 Estonia KO19
170 Estonia KO27
171 Estonia KO28
172 Estonia KO29
173 Estonia KO37
174 Estonia KO38
175 Estonia KO39
176 Estonia KO49
177 European Russia KN84
178 European Russia KN85
179 European Russia KN86
180 European Russia KN93
181 European Russia KN94
182 European Russia KN95
183 European Russia KN96
184 European Russia KN97
185 European Russia KN98
186 European Russia KN99
187 European Russia KO36
188 European Russia KO37
189 European Russia KO38
190 European Russia KO39
191 European Russia KO45
192 European Russia KO46
193 European Russia KO47
194 European Russia KO48
195 European Russia KO49
196 European Russia KO52
197 European Russia KO53
198 European Russia KO54
199 European Russia KO55
200 European Russia KO56
201 European Russia KO57
202 European Russia KO58
203 European Russia KO59
204 European Russia KO62
205 European Russia KO63
206 European Russia KO64
207 European Russia KO65
208 European Russia KO67
209 European Russia KO68
210 European Russia KO69
211 European Russia KO70
212 European Russia KO71
213 European Russia KO72
214 European Russia KO73
215 European Russia KO74
216 European Russia KO75
217 European Russia KO76
218 European Russia KO77
219 European Russia KO78
220 European Russia KO79
221 European Russia KO80
222 European Russia KO81
223 European Russia KO82
224 European Russia KO83
225 European Russia KO84
226 European Russia KO85
227 European Russia KO86
228 European Russia KO87
229 European Russia KO88
230 European Russia KO89
231 European Russia KO90
232 European Russia KO91
233 European Russia KO92
234 European Russia KO93
235 European Russia KO94
236 European Russia KO95
237 European Russia KO96
238 European Russia KO97
239 European Russia KO98
240 European Russia KO99
241 European Russia LN03
242 European Russia LN04
243 European Russia LN05
244 European Russia LN06
245 European Russia LN07
246 European Russia LN08
247 European Russia LN09
248 European Russia LN12
249 European Russia LN13
250 European Russia LN14
251 European Russia LN15
252 European Russia LN16
253 European Russia LN17
254 European Russia LN18
255 European Russia LN19
256 European Russia LN22
257 European Russia LN23
258 European Russia LN24
259 European Russia LN25
260 European Russia LN26
261 European Russia LN27
262 European Russia LN28
263 European Russia LN29
264 European Russia LN31
265 European Russia LN32
266 European Russia LN33
267 European Russia LN34
268 European Russia LN35
269 European Russia LN36
270 European Russia LN37
271 European Russia LN38
272 European Russia LN39
273 European Russia LN41
274 European Russia LN42
275 European Russia LN43
276 European Russia LN44
277 European Russia LN45
278 European Russia LN46
279 European Russia LN47
280 European Russia LN48
281 European Russia LN49
282 European Russia LO00
283 European Russia LO01
284 European Russia LO02
285 European Russia LO03
286 European Russia LO04
287 European Russia LO05
288 European Russia LO06
289 European Russia LO07
290 European Russia LO08
291 European Russia LO09
292 European Russia LO10
293 European Russia LO11
294 European Russia LO12
295 European Russia LO13
296 European Russia LO14
297 European Russia LO15
298 European Russia LO16
299 European Russia LO17
300 European Russia LO18
301 European Russia LO19
302 European Russia LO20
303 European Russia LO21
304 European Russia LO22
305 European Russia LO23
306 European Russia LO24
307 European Russia LO25
308 European Russia LO26
309 European Russia LO27
310 European Russia LO28
311 European Russia LO29
312 European Russia LO30
313 European Russia LO31
314 European Russia LO32
315 European Russia LO33
316 European Russia LO34
317 European Russia LO35
318 European Russia LO36
319 European Russia LO37
320 European Russia LO38
321 European Russia LO39
322 European Russia LO40
323 European Russia LO41
324 European Russia LO42
325 European Russia LO43
326 European Russia LO44
327 European Russia LO45
328 European Russia LO46
329 European Russia LO47
330 European Russia LO48
331 European Russia LO49
332 Faroe Islands IP61
333 Faroe Islands IP62
334 Fed. Rep. of Germany JN37
335 Fed. Rep. of Germany JN38
336 Fed. Rep. of Germany JN39
337 Fed. Rep. of Germany JN47
338 Fed. Rep. of Germany JN48
339 Fed. Rep. of Germany JN49
340 Fed. Rep. of Germany JN57
341 Fed. Rep. of Germany JN58
342 Fed. Rep. of Germany JN59
343 Fed. Rep. of Germany JN67
344 Fed. Rep. of Germany JN68
345 Fed. Rep. of Germany JN69
346 Fed. Rep. of Germany JO20
347 Fed. Rep. of Germany JO21
348 Fed. Rep. of Germany JO30
349 Fed. Rep. of Germany JO31
350 Fed. Rep. of Germany JO32
351 Fed. Rep. of Germany JO33
352 Fed. Rep. of Germany JO34
353 Fed. Rep. of Germany JO40
354 Fed. Rep. of Germany JO41
355 Fed. Rep. of Germany JO42
356 Fed. Rep. of Germany JO43
357 Fed. Rep. of Germany JO44
358 Fed. Rep. of Germany JO50
359 Fed. Rep. of Germany JO51
360 Fed. Rep. of Germany JO52
361 Fed. Rep. of Germany JO53
362 Fed. Rep. of Germany JO54
363 Fed. Rep. of Germany JO60
364 Fed. Rep. of Germany JO61
365 Fed. Rep. of Germany JO62
366 Fed. Rep. of Germany JO63
367 Fed. Rep. of Germany JO64
368 Fed. Rep. of Germany JO70
369 Fed. Rep. of Germany JO71
370 Fed. Rep. of Germany JO72
371 Fed. Rep. of Germany JO73
372 Fed. Rep. of Germany JO74
373 Finland JP90
374 Finland KN09
375 Finland KO19
376 Finland KO29
377 Finland KP00
378 Finland KP01
379 Finland KP02
380 Finland KP03
381 Finland KP08
382 Finland KP09
383 Finland KP10
384 Finland KP11
385 Finland KP12
386 Finland KP13
387 Finland KP14
388 Finland KP16
389 Finland KP17
390 Finland KP18
391 Finland KP20
392 Finland KP21
393 Finland KP22
394 Finland KP23
395 Finland KP24
396 Finland KP25
397 Finland KP26
398 Finland KP27
399 Finland KP28
400 Finland KP29
401 Finland KP30
402 Finland KP31
403 Finland KP32
404 Finland KP33
405 Finland KP34
406 Finland KP35
407 Finland KP36
408 Finland KP37
409 Finland KP38
410 Finland KP39
411 Finland KP40
412 Finland KP41
413 Finland KP42
414 Finland KP43
415 Finland KP44
416 Finland KP46
417 Finland KP47
418 Finland KP48
419 Finland KP49
420 Finland KP51
421 Finland KP52
422 Finland KP53
423 Finland KP54
424 Finland KP55
425 Finland KP56
426 Finland KP57
427 Finland KQ30
428 Finland KQ40
429 France IN77
430 France IN78
431 France IN86
432 France IN87
433 France IN88
434 France IN92
435 France IN93
436 France IN94
437 France IN95
438 France IN96
439 France IN97
440 France IN98
441 France IN99
442 France JN02
443 France JN03
444 France JN04
445 France JN05
446 France JN06
447 France JN07
448 France JN08
449 France JN09
450 France JN12
451 France JN13
452 France JN14
453 France JN15
454 France JN16
455 France JN17
456 France JN18
457 France JN19
458 France JN23
459 France JN24
460 France JN25
461 France JN26
462 France JN27
463 France JN28
464 France JN29
465 France JN32
466 France JN33
467 France JN34
468 France JN35
469 France JN36
470 France JN37
471 France JN38
472 France JN39
473 France JN48
474 France JN49
475 France JO00
476 France JO10
477 France JO11
478 France JO20
479 Gibraltar IM76
480 Greece JM99
481 Greece KM06
482 Greece KM07
483 Greece KM08
484 Greece KM09
485 Greece KM15
486 Greece KM16
487 Greece KM17
488 Greece KM18
489 Greece KM19
490 Greece KM25
491 Greece KM26
492 Greece KM27
493 Greece KM28
494 Greece KM29
495 Greece KN00
496 Greece KN01
497 Greece KN10
498 Greece KN11
499 Greece KN20
500 Greece KN21
501 Greece KN30
502 Greece KN31
503 Guernsey IN89
504 Hungary JN85
505 Hungary JN86
506 Hungary JN87
507 Hungary JN88
508 Hungary JN95
509 Hungary JN96
510 Hungary JN97
511 Hungary JN98
512 Hungary KN06
513 Hungary KN07
514 Hungary KN08
515 Hungary KN17
516 Hungary KN18
517 Ireland IO41
518 Ireland IO42
519 Ireland IO43
520 Ireland IO44
521 Ireland IO51
522 Ireland IO52
523 Ireland IO53
524 Ireland IO54
525 Ireland IO55
526 Ireland IO61
527 Ireland IO62
528 Ireland IO63
529 Ireland IO64
530 Ireland IO65
531 Ireland IO72
532 Isle of Man IO74
533 Italy JM68
534 Italy JM77
535 Italy JM78
536 Italy JM79
537 Italy JM87
538 Italy JM88
539 Italy JM89
540 Italy JM99
541 Italy JN33
542 Italy JN34
543 Italy JN35
544 Italy JN40
545 Italy JN43
546 Italy JN44
547 Italy JN45
548 Italy JN46
549 Italy JN51
550 Italy JN52
551 Italy JN53
552 Italy JN54
553 Italy JN55
554 Italy JN56
555 Italy JN57
556 Italy JN60
557 Italy JN61
558 Italy JN62
559 Italy JN63
560 Italy JN64
561 Italy JN65
562 Italy JN66
563 Italy JN67
564 Italy JN70
565 Italy JN71
566 Italy JN72
567 Italy JN80
568 Italy JN81
569 Italy JN90
570 ITU HQ JN36
571 Jan Mayen IO50
572 Jan Mayen IO60
573 Jan Mayen IO61
574 Jersey IN89
575 Kaliningrad JO94
576 Kaliningrad KO04
577 Kaliningrad KO05
578 Kaliningrad KO14
579 Kaliningrad KO15
580 Latvia KO06
581 Latvia KO07
582 Latvia KO16
583 Latvia KO17
584 Latvia KO27
585 Latvia KO28
586 Latvia KO35
587 Latvia KO36
588 Latvia KO37
589 Latvia KO46
590 Liechtenstein JN47
591 Lithuania KO05
592 Lithuania KO06
593 Lithuania KO13
594 Lithuania KO14
595 Lithuania KO15
596 Lithuania KO16
597 Lithuania KO23
598 Lithuania KO24
599 Lithuania KO25
600 Lithuania KO26
601 Lithuania KO34
602 Lithuania KO35
603 Luxembourg JN29
604 Luxembourg JN39
605 Luxembourg JO20
606 Luxembourg JO30
607 Macedonia KN00
608 Macedonia KN01
609 Macedonia KN02
610 Macedonia KN11
611 Macedonia KN12
612 Malta JM75
613 Malta JM76
614 Moldova KN37
615 Moldova KN38
616 Moldova KN45
617 Moldova KN46
618 Moldova KN47
619 Moldova KN48
620 Moldova KN56
621 Monaco JN33
622 Montenegro JN91
623 Montenegro JN92
624 Montenegro JN93
625 Montenegro KN02
626 Montenegro KN03
627 Netherlands JO11
628 Netherlands JO20
629 Netherlands JO21
630 Netherlands JO22
631 Netherlands JO23
632 Netherlands JO30
633 Netherlands JO31
634 Netherlands JO32
635 Netherlands JO33
636 Northern Ireland IO54
637 Northern Ireland IO64
638 Northern Ireland IO65
639 Northern Ireland IO74
640 Northern Ireland IO75
641 Poland JN89
642 Poland JN99
643 Poland JO70
644 Poland JO71
645 Poland JO72
646 Poland JO73
647 Poland JO74
648 Poland JO80
649 Poland JO81
650 Poland JO82
651 Poland JO83
652 Poland JO84
653 Poland JO90
654 Poland JO91
655 Poland JO92
656 Poland JO93
657 Poland JO94
658 Poland KN09
659 Poland KN19
660 Poland KO00
661 Poland KO01
662 Poland KO02
663 Poland KO03
664 Poland KO04
665 Poland KO10
666 Poland KO11
667 Poland KO12
668 Poland KO13
669 Poland KO14
670 Poland KO20
671 Portugal IM56
672 Portugal IM57
673 Portugal IM58
674 Portugal IM59
675 Portugal IM66
676 Portugal IM67
677 Portugal IM68
678 Portugal IM69
679 Portugal IN50
680 Portugal IN51
681 Portugal IN52
682 Portugal IN60
683 Portugal IN61
684 Romania KN04
685 Romania KN05
686 Romania KN06
687 Romania KN07
688 Romania KN13
689 Romania KN14
690 Romania KN15
691 Romania KN16
692 Romania KN17
693 Romania KN18
694 Romania KN23
695 Romania KN24
696 Romania KN25
697 Romania KN26
698 Romania KN27
699 Romania KN33
700 Romania KN34
701 Romania KN35
702 Romania KN36
703 Romania KN37
704 Romania KN38
705 Romania KN43
706 Romania KN44
707 Romania KN45
708 Romania KN46
709 Romania KN47
710 Sardinia JM48
711 Sardinia JM49
712 Sardinia JN40
713 Sardinia JN41
714 Scotland IO65
715 Scotland IO66
716 Scotland IO67
717 Scotland IO68
718 Scotland IO74
719 Scotland IO75
720 Scotland IO76
721 Scotland IO77
722 Scotland IO78
723 Scotland IO84
724 Scotland IO85
725 Scotland IO86
726 Scotland IO87
727 Scotland IO88
728 Scotland IO89
729 Scotland IO97
730 Scotland IO99
731 Scotland IP90
732 Serbia JN93
733 Serbia JN94
734 Serbia JN95
735 Serbia JN96
736 Serbia KN01
737 Serbia KN02
738 Serbia KN03
739 Serbia KN04
740 Serbia KN05
741 Serbia KN06
742 Serbia KN12
743 Serbia KN13
744 Serbia KN14
745 Sicily JM67
746 Sicily JM68
747 Sicily JM76
748 Sicily JM77
749 Sicily JM78
750 Slovak Republic JN87
751 Slovak Republic JN88
752 Slovak Republic JN89
753 Slovak Republic JN97
754 Slovak Republic JN98
755 Slovak Republic JN99
756 Slovak Republic KN08
757 Slovak Republic KN09
758 Slovak Republic KN18
759 Slovak Republic KN19
760 Slovenia JN64
761 Slovenia JN65
762 Slovenia JN66
763 Slovenia JN73
764 Slovenia JN74
765 Slovenia JN75
766 Slovenia JN76
767 Slovenia JN82
768 Slovenia JN83
769 Slovenia JN84
770 Slovenia JN85
771 Slovenia JN86
772 Slovenia JN92
773 Spain IM66
774 Spain IM67
775 Spain IM68
776 Spain IM69
777 Spain IM76
778 Spain IM77
779 Spain IM78
780 Spain IM79
781 Spain IM86
782 Spain IM87
783 Spain IM88
784 Spain IM89
785 Spain IM96
786 Spain IM97
787 Spain IM98
788 Spain IM99
789 Spain IN51
790 Spain IN52
791 Spain IN53
792 Spain IN60
793 Spain IN61
794 Spain IN62
795 Spain IN63
796 Spain IN70
797 Spain IN71
798 Spain IN72
799 Spain IN73
800 Spain IN80
801 Spain IN81
802 Spain IN82
803 Spain IN83
804 Spain IN90
805 Spain IN91
806 Spain IN92
807 Spain IN93
808 Spain JM08
809 Spain JM09
810 Spain JN00
811 Spain JN01
812 Spain JN02
813 Spain JN11
814 Spain JN12
815 Svalbard JQ58
816 Svalbard JQ59
817 Svalbard JQ67
818 Svalbard JQ68
819 Svalbard JQ69
820 Svalbard JQ76
821 Svalbard JQ77
822 Svalbard JQ78
823 Svalbard JQ79
824 Svalbard JQ86
825 Svalbard JQ87
826 Svalbard JQ88
827 Svalbard JQ89
828 Svalbard JQ97
829 Svalbard JQ98
830 Svalbard JQ99
831 Svalbard JR80
832 Svalbard JR90
833 Svalbard KQ07
834 Svalbard KQ08
835 Svalbard KQ09
836 Svalbard KQ17
837 Svalbard KQ18
838 Svalbard KQ19
839 Svalbard KQ26
840 Svalbard KQ27
841 Svalbard KQ29
842 Svalbard KQ38
843 Svalbard KQ39
844 Svalbard KQ48
845 Svalbard KQ49
846 Svalbard KR00
847 Svalbard KR06
848 Svalbard KR07
849 Svalbard KR10
850 Svalbard KR20
851 Svalbard KR30
852 Sweden JO57
853 Sweden JO58
854 Sweden JO59
855 Sweden JO65
856 Sweden JO66
857 Sweden JO67
858 Sweden JO68
859 Sweden JO69
860 Sweden JO74
861 Sweden JO75
862 Sweden JO76
863 Sweden JO77
864 Sweden JO78
865 Sweden JO79
866 Sweden JO86
867 Sweden JO87
868 Sweden JO88
869 Sweden JO89
870 Sweden JO96
871 Sweden JO97
872 Sweden JO98
873 Sweden JO99
874 Sweden JP53
875 Sweden JP60
876 Sweden JP61
877 Sweden JP62
878 Sweden JP63
879 Sweden JP64
880 Sweden JP70
881 Sweden JP71
882 Sweden JP72
883 Sweden JP73
884 Sweden JP74
885 Sweden JP75
886 Sweden JP76
887 Sweden JP80
888 Sweden JP81
889 Sweden JP82
890 Sweden JP83
891 Sweden JP84
892 Sweden JP85
893 Sweden JP86
894 Sweden JP87
895 Sweden JP88
896 Sweden JP90
897 Sweden JP92
898 Sweden JP93
899 Sweden JP94
900 Sweden JP95
901 Sweden JP96
902 Sweden JP97
903 Sweden JP98
904 Sweden KP03
905 Sweden KP04
906 Sweden KP05
907 Sweden KP06
908 Sweden KP07
909 Sweden KP08
910 Sweden KP09
911 Sweden KP15
912 Sweden KP16
913 Sweden KP17
914 Sweden KP18
915 Sweden KP25
916 Switzerland JN26
917 Switzerland JN35
918 Switzerland JN36
919 Switzerland JN37
920 Switzerland JN45
921 Switzerland JN46
922 Switzerland JN47
923 Switzerland JN56
924 UK Base Areas on Cyprus KM64
925 UK Base Areas on Cyprus KM65
926 Vatican City JN61
927 Vienna Intl Ctr JN88
928 Wales IO71
929 Wales IO72
930 Wales IO73
931 Wales IO81
932 Wales IO82
933 Wales IO83
934 Wales IO93