Files
michaelschiemer/tests/debug/analyze-problematic-qrcode.php
Michael Schiemer 95147ff23e refactor(deployment): Remove WireGuard VPN dependency and restore public service access
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.
2025-11-05 12:48:25 +01:00

165 lines
5.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;
echo "=== Analyzing Problematic QR Code ===\n\n";
// Parse the SVG to understand what data it contains
// The SVG shows a 580x580 canvas with 20x20 modules
// Quiet zone: 80px = 4 modules
// Actual matrix: 29x29 modules? No, that doesn't match
// Let's calculate: 580 - 2*80 = 420, so 420/20 = 21 modules
// So it's Version 1 (21x21 modules)
echo "SVG Analysis:\n";
echo " Canvas size: 580x580\n";
echo " Module size: 20x20\n";
echo " Quiet zone: 80px (4 modules)\n";
echo " Matrix size: (580-160)/20 = 21x21 (Version 1)\n\n";
// Generate a QR code with same parameters
$config = new QrCodeConfig(
version: QrCodeVersion::fromNumber(1),
errorCorrectionLevel: ErrorCorrectionLevel::M,
encodingMode: EncodingMode::BYTE
);
// Try to decode what data might be in the problematic QR code
// We'll generate our own and compare
$testData = 'HELLO WORLD'; // Standard test
$matrix = QrCodeGenerator::generate($testData, $config);
echo "Generated QR Code:\n";
echo " Data: '{$testData}'\n";
echo " Version: 1\n";
echo " Error Correction: M\n";
echo " Matrix size: {$matrix->getSize()}x{$matrix->getSize()}\n\n";
// Check critical areas
echo "=== Critical Area Checks ===\n\n";
// 1. Format Information (horizontal)
$formatCols = [0, 1, 2, 3, 4, 5, 7, 8, 20, 19, 18, 17, 16, 15, 14];
$formatH = '';
foreach ($formatCols as $col) {
$formatH .= $matrix->getModuleAt(8, $col)->isDark() ? '1' : '0';
}
echo "Format Info (Horizontal): {$formatH}\n";
// 2. Format Information (vertical)
$formatRows = [20, 19, 18, 17, 16, 15, 14, 8, 7, 5, 4, 3, 2, 1, 0];
$formatV = '';
foreach ($formatRows as $row) {
$formatV .= $matrix->getModuleAt($row, 8)->isDark() ? '1' : '0';
}
echo "Format Info (Vertical): {$formatV}\n";
if ($formatH === $formatV) {
echo "✅ Format info matches\n\n";
} else {
echo "❌ Format info doesn't match!\n";
echo "This is a CRITICAL error - QR code won't scan!\n\n";
}
// 3. Check finder patterns
echo "=== Finder Pattern Check ===\n";
$finderPositions = [
['name' => 'Top-Left', 'row' => 0, 'col' => 0],
['name' => 'Top-Right', 'row' => 0, 'col' => 14],
['name' => 'Bottom-Left', 'row' => 14, 'col' => 0],
];
foreach ($finderPositions as $finder) {
$pattern = '';
for ($r = 0; $r < 7; $r++) {
for ($c = 0; $c < 7; $c++) {
$pattern .= $matrix->getModuleAt($finder['row'] + $r, $finder['col'] + $c)->isDark() ? '1' : '0';
}
}
$expected = '1111111100000110111110110111110110111110110000011111111';
if ($pattern === $expected) {
echo "{$finder['name']} finder pattern correct\n";
} else {
echo "{$finder['name']} finder pattern incorrect\n";
echo " Got: {$pattern}\n";
echo " Expected: {$expected}\n";
}
}
echo "\n";
// 4. Generate SVG with same parameters
$renderer = new QrCodeRenderer();
$svg = $renderer->renderSvg($matrix);
// Check module size and quiet zone in generated SVG
if (preg_match('/<rect x="(\d+\.?\d*)" y="(\d+\.?\d*)" width="(\d+\.?\d*)" height="(\d+\.?\d*)" fill="white"/', $svg, $matches)) {
$quietZone = (float)$matches[1];
$moduleSize = (float)$matches[3];
echo "Generated SVG:\n";
echo " Quiet zone: {$quietZone}px\n";
echo " Module size: {$moduleSize}px\n";
echo " Total size: " . ($matrix->getSize() * $moduleSize + 2 * $quietZone) . "px\n\n";
}
// 5. Check if there's a dark module (Version 1 requirement)
$darkModuleRow = 4 * 1 + 9; // 13 for version 1
$darkModuleCol = 8;
$hasDarkModule = $matrix->getModuleAt($darkModuleRow, $darkModuleCol)->isDark();
echo "Dark module (row {$darkModuleRow}, col {$darkModuleCol}): " . ($hasDarkModule ? "✅ Present" : "❌ Missing") . "\n\n";
// 6. Output comparison SVG
$outputDir = __DIR__ . '/test-qrcodes';
$comparisonFile = $outputDir . '/comparison-correct.svg';
file_put_contents($comparisonFile, $svg);
echo "✅ Saved comparison QR code: {$comparisonFile}\n";
echo " Compare this with the problematic QR code to find differences.\n\n";
// 7. Check data placement
echo "=== Data Placement Check ===\n";
echo "Checking if data bits are placed correctly...\n";
// Count dark modules in data area
$dataAreaDark = 0;
$dataAreaTotal = 0;
for ($row = 0; $row < $matrix->getSize(); $row++) {
for ($col = 0; $col < $matrix->getSize(); $col++) {
// Skip function patterns
if (
($row <= 8 && $col <= 8) ||
($row <= 7 && $col >= 13) ||
($row >= 13 && $col <= 7) ||
$row === 6 || $col === 6
) {
continue;
}
$dataAreaTotal++;
if ($matrix->getModuleAt($row, $col)->isDark()) {
$dataAreaDark++;
}
}
}
echo "Data area: {$dataAreaDark} dark / {$dataAreaTotal} total modules\n";
$darkRatio = $dataAreaDark / $dataAreaTotal;
echo "Dark ratio: " . number_format($darkRatio * 100, 2) . "%\n";
if ($darkRatio > 0.3 && $darkRatio < 0.7) {
echo "✅ Dark ratio is reasonable (should be ~40-60%)\n";
} else {
echo "⚠️ Dark ratio seems unusual\n";
}