Remove WireGuard integration from production deployment to simplify infrastructure: - Remove docker-compose-direct-access.yml (VPN-bound services) - Remove VPN-only middlewares from Grafana, Prometheus, Portainer - Remove WireGuard middleware definitions from Traefik - Remove WireGuard IPs (10.8.0.0/24) from Traefik forwarded headers All monitoring services now publicly accessible via subdomains: - grafana.michaelschiemer.de (with Grafana native auth) - prometheus.michaelschiemer.de (with Basic Auth) - portainer.michaelschiemer.de (with Portainer native auth) All services use Let's Encrypt SSL certificates via Traefik.
148 lines
4.3 KiB
PHP
148 lines
4.3 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
require_once __DIR__ . '/../../vendor/autoload.php';
|
|
|
|
use App\Framework\QrCode\QrCodeGenerator;
|
|
use App\Framework\QrCode\QrCodeRenderer;
|
|
use App\Framework\QrCode\ValueObjects\ErrorCorrectionLevel;
|
|
use App\Framework\QrCode\ValueObjects\QrCodeConfig;
|
|
use App\Framework\QrCode\ValueObjects\QrCodeVersion;
|
|
use App\Framework\QrCode\ValueObjects\EncodingMode;
|
|
use App\Framework\QrCode\ValueObjects\QrCodeStyle;
|
|
|
|
echo "=== Testing SVG Coordinate Rendering ===\n\n";
|
|
|
|
$config = new QrCodeConfig(
|
|
version: QrCodeVersion::fromNumber(1),
|
|
errorCorrectionLevel: ErrorCorrectionLevel::M,
|
|
encodingMode: EncodingMode::BYTE
|
|
);
|
|
|
|
$matrix = QrCodeGenerator::generate('HELLO', $config);
|
|
$size = $matrix->getSize();
|
|
|
|
echo "Matrix size: {$size}x{$size}\n\n";
|
|
|
|
// Check top-left finder pattern in matrix
|
|
echo "=== Top-Left Finder Pattern in Matrix ===\n";
|
|
echo "Expected pattern (7x7):\n";
|
|
echo "███████\n";
|
|
echo "█░░░░░█\n";
|
|
echo "█░███░█\n";
|
|
echo "█░███░█\n";
|
|
echo "█░███░█\n";
|
|
echo "█░░░░░█\n";
|
|
echo "███████\n\n";
|
|
|
|
echo "Actual pattern from matrix:\n";
|
|
for ($r = 0; $r < 7; $r++) {
|
|
echo " ";
|
|
for ($c = 0; $c < 7; $c++) {
|
|
$isDark = $matrix->getModuleAt($r, $c)->isDark();
|
|
echo $isDark ? '█' : '░';
|
|
}
|
|
echo "\n";
|
|
}
|
|
|
|
echo "\n";
|
|
|
|
// Now render SVG and check coordinates
|
|
$style = QrCodeStyle::large();
|
|
$renderer = new QrCodeRenderer();
|
|
$svg = $renderer->renderCustom($matrix, $style, false);
|
|
|
|
// Extract rectangles for top-left finder (should be around x=80, y=80)
|
|
echo "=== Top-Left Finder Pattern in SVG ===\n";
|
|
echo "Expected: Should start at x=80, y=80 (quiet zone 80px)\n";
|
|
echo "Looking for rectangles in area x=80-220, y=80-220:\n\n";
|
|
|
|
preg_match_all('/<rect x="(\d+\.?\d*)" y="(\d+\.?\d*)" width="(\d+\.?\d*)" height="(\d+\.?\d*)" fill="black"/', $svg, $matches, PREG_SET_ORDER);
|
|
|
|
$finderRects = [];
|
|
foreach ($matches as $m) {
|
|
$x = (float)$m[1];
|
|
$y = (float)$m[2];
|
|
if ($x >= 80 && $x <= 220 && $y >= 80 && $y <= 220) {
|
|
$finderRects[] = [
|
|
'x' => $x,
|
|
'y' => $y,
|
|
'row' => (int)(($y - 80) / 20),
|
|
'col' => (int)(($x - 80) / 20),
|
|
];
|
|
}
|
|
}
|
|
|
|
// Sort by row, then col
|
|
usort($finderRects, function($a, $b) {
|
|
if ($a['row'] !== $b['row']) {
|
|
return $a['row'] <=> $b['row'];
|
|
}
|
|
return $a['col'] <=> $b['col'];
|
|
});
|
|
|
|
echo "Found " . count($finderRects) . " rectangles in finder pattern area\n\n";
|
|
|
|
// Check if coordinates match expected pattern
|
|
echo "First row (should be all dark at y=80):\n";
|
|
$firstRowRects = array_filter($finderRects, fn($r) => $r['row'] === 0);
|
|
foreach ($firstRowRects as $rect) {
|
|
echo " x={$rect['x']}, y={$rect['y']}, row={$rect['row']}, col={$rect['col']}\n";
|
|
}
|
|
|
|
if (count($firstRowRects) === 7) {
|
|
echo "✅ First row has 7 modules (correct)\n";
|
|
} else {
|
|
echo "❌ First row has " . count($firstRowRects) . " modules (expected 7)\n";
|
|
}
|
|
|
|
// Check if row/col match matrix
|
|
echo "\n=== Coordinate Verification ===\n";
|
|
$errors = 0;
|
|
foreach ($finderRects as $rect) {
|
|
$matrixRow = $rect['row'];
|
|
$matrixCol = $rect['col'];
|
|
|
|
if ($matrixRow >= 0 && $matrixRow < 7 && $matrixCol >= 0 && $matrixCol < 7) {
|
|
$isDark = $matrix->getModuleAt($matrixRow, $matrixCol)->isDark();
|
|
if (!$isDark) {
|
|
echo "❌ Error: Matrix at ({$matrixRow}, {$matrixCol}) is LIGHT, but SVG has dark rect at ({$rect['x']}, {$rect['y']})\n";
|
|
$errors++;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($errors === 0) {
|
|
echo "✅ All SVG coordinates match matrix positions\n";
|
|
} else {
|
|
echo "❌ Found {$errors} coordinate mismatches\n";
|
|
}
|
|
|
|
// Check timing pattern
|
|
echo "\n=== Timing Pattern Check ===\n";
|
|
echo "Timing pattern should be at row 6, alternating modules\n";
|
|
echo "Matrix row 6:\n";
|
|
echo " ";
|
|
for ($c = 0; $c < $size; $c++) {
|
|
$isDark = $matrix->getModuleAt(6, $c)->isDark();
|
|
echo $isDark ? '█' : '░';
|
|
}
|
|
echo "\n";
|
|
|
|
// Check if timing pattern is rendered in SVG
|
|
$timingY = 80 + 6 * 20; // 200
|
|
$timingRects = array_filter($matches, function($m) use ($timingY) {
|
|
$y = (float)$m[2];
|
|
return abs($y - $timingY) < 0.1;
|
|
});
|
|
|
|
echo "SVG rectangles at y={$timingY} (timing row):\n";
|
|
foreach ($timingRects as $m) {
|
|
$x = (float)$m[1];
|
|
$col = (int)(($x - 80) / 20);
|
|
echo " x={$x}, col={$col}\n";
|
|
}
|
|
|
|
|