Files
michaelschiemer/tests/debug/test-mask-pattern-issue.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

109 lines
3.4 KiB
PHP

<?php
declare(strict_types=1);
require_once __DIR__ . '/../../vendor/autoload.php';
use App\Framework\QrCode\QrCodeGenerator;
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 "=== Mask Pattern Issue Analysis ===\n\n";
$testData = 'HELLO WORLD';
$config = new QrCodeConfig(
version: QrCodeVersion::fromNumber(1),
errorCorrectionLevel: ErrorCorrectionLevel::M,
encodingMode: EncodingMode::BYTE
);
$matrix = QrCodeGenerator::generate($testData, $config);
// Decode format information
$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';
}
$xorMask = "101010000010010";
$unmasked = '';
for ($i = 0; $i < 15; $i++) {
$unmasked .= (int)$formatH[$i] ^ (int)$xorMask[$i];
}
$maskBits = substr($unmasked, 2, 5);
$maskPattern = bindec($maskBits);
echo "Decoded Mask Pattern: {$maskPattern}\n";
echo "Mask Bits: {$maskBits}\n\n";
if ($maskPattern > 7) {
echo "❌ PROBLEM: Mask Pattern is {$maskPattern}, but should be 0-7!\n";
echo "This means the format information is incorrect.\n";
echo "The mask bits are 5 bits, so max value is 31.\n";
echo "But QR codes only use mask patterns 0-7 (3 bits).\n\n";
// Check what the actual mask pattern should be
echo "Checking what mask pattern should be used...\n";
// The mask pattern selection should be based on penalty scoring
// Let's check what mask pattern was actually applied
} else {
echo "✅ Mask Pattern is valid (0-7)\n";
}
// Check if we can identify which mask pattern was actually used
// by checking the data placement pattern
echo "\n=== Checking Data Placement ===\n";
echo "For Version 1, Level M, we have 16 data codewords + 10 EC codewords = 26 total\n";
echo "Each codeword is 8 bits, so 26 * 8 = 208 bits of data\n";
echo "Plus mode (4 bits) + count (8 bits) = 12 bits overhead\n";
echo "Total data bits: 220 bits\n\n";
// Count dark modules in data area (excluding function patterns)
$dataAreaDark = 0;
$dataAreaTotal = 0;
for ($row = 0; $row < 21; $row++) {
for ($col = 0; $col < 21; $col++) {
// Skip function patterns
if (
// Finder patterns
($row <= 8 && $col <= 8) ||
($row <= 7 && $col >= 13) ||
($row >= 13 && $col <= 7) ||
// Timing patterns
$row === 6 || $col === 6 ||
// Format info
($row === 8 && ($col <= 8 || $col >= 13)) ||
($col === 8 && ($row <= 7 || $row >= 9)) ||
// Dark module
($row === 13 && $col === 8)
) {
continue;
}
$dataAreaTotal++;
if ($matrix->getModuleAt($row, $col)->isDark()) {
$dataAreaDark++;
}
}
}
echo "Data area modules: {$dataAreaTotal}\n";
echo "Dark modules in data area: {$dataAreaDark}\n";
echo "Light modules in data area: " . ($dataAreaTotal - $dataAreaDark) . "\n";
echo "Dark ratio: " . number_format(($dataAreaDark / $dataAreaTotal) * 100, 2) . "%\n\n";
// For a scannable QR code, the dark ratio should be around 50%
// But with masking, it can vary
if ($dataAreaDark > 0 && $dataAreaTotal > 0) {
echo "✅ Data area has modules\n";
} else {
echo "❌ Data area is empty - this is a problem!\n";
}