Initial commit
This commit is contained in:
57
database/seeders/BandEdiBandSeeder.php
Normal file
57
database/seeders/BandEdiBandSeeder.php
Normal 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);
|
||||
}
|
||||
}
|
||||
132
database/seeders/BandSeeder.php
Normal file
132
database/seeders/BandSeeder.php
Normal 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);
|
||||
}
|
||||
}
|
||||
45
database/seeders/CategoriesEdiCategoriesSeeder.php
Normal file
45
database/seeders/CategoriesEdiCategoriesSeeder.php
Normal 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);
|
||||
}
|
||||
}
|
||||
35
database/seeders/CategoriesSeeder.php
Normal file
35
database/seeders/CategoriesSeeder.php
Normal 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);
|
||||
}
|
||||
}
|
||||
97
database/seeders/ContestSeeder.php
Normal file
97
database/seeders/ContestSeeder.php
Normal 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,
|
||||
]
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
33
database/seeders/CountriesWwlSeeder.php
Normal file
33
database/seeders/CountriesWwlSeeder.php
Normal 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);
|
||||
}
|
||||
}
|
||||
169
database/seeders/CtySeeder.php
Normal file
169
database/seeders/CtySeeder.php
Normal 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);
|
||||
}
|
||||
}
|
||||
42
database/seeders/DatabaseSeeder.php
Normal file
42
database/seeders/DatabaseSeeder.php
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
52
database/seeders/EdiBandSeeder.php
Normal file
52
database/seeders/EdiBandSeeder.php
Normal 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);
|
||||
}
|
||||
}
|
||||
44
database/seeders/EdiCategoriesSeeder.php
Normal file
44
database/seeders/EdiCategoriesSeeder.php
Normal 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);
|
||||
}
|
||||
}
|
||||
504
database/seeders/EvaluationPipelineRegressionSeeder.php
Normal file
504
database/seeders/EvaluationPipelineRegressionSeeder.php
Normal 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',
|
||||
]);
|
||||
}
|
||||
}
|
||||
107
database/seeders/EvaluationRuleSetSeeder.php
Normal file
107
database/seeders/EvaluationRuleSetSeeder.php
Normal 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,
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
136
database/seeders/NewsPostSeeder.php
Normal file
136
database/seeders/NewsPostSeeder.php
Normal 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:00–23: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:00–23: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:00–23:00 CET.',
|
||||
'en' => 'Planned downtime on 15 Dec 2025 between 22:00–23: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();
|
||||
}
|
||||
}
|
||||
}
|
||||
36
database/seeders/PowerCategoriesSeeder.php
Normal file
36
database/seeders/PowerCategoriesSeeder.php
Normal 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);
|
||||
}
|
||||
}
|
||||
88
database/seeders/RoundSeeder.php
Normal file
88
database/seeders/RoundSeeder.php
Normal 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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
934
database/seeders/countries_wwl.csv
Normal file
934
database/seeders/countries_wwl.csv
Normal 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
|
||||
|
Reference in New Issue
Block a user