Files
vkv/database/seeders/CtySeeder.php
Zdeněk Burda 41e3ce6f25 Initial commit
2026-01-09 21:26:40 +01:00

170 lines
5.1 KiB
PHP

<?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);
}
}