getSize(); echo "Matrix size: {$size}x{$size}\n\n"; // 1. Check finder patterns echo "=== Finder Patterns ===\n"; $finderOk = true; $finderPositions = [ ['name' => 'Top-Left', 'row' => 0, 'col' => 0], ['name' => 'Top-Right', 'row' => 0, 'col' => 14], ['name' => 'Bottom-Left', 'row' => 14, 'col' => 0], ]; $expectedFinder = [ [1,1,1,1,1,1,1], [1,0,0,0,0,0,1], [1,0,1,1,1,0,1], [1,0,1,1,1,0,1], [1,0,1,1,1,0,1], [1,0,0,0,0,0,1], [1,1,1,1,1,1,1], ]; foreach ($finderPositions as $finder) { $errors = 0; for ($r = 0; $r < 7; $r++) { for ($c = 0; $c < 7; $c++) { $row = $finder['row'] + $r; $col = $finder['col'] + $c; $actual = $matrix->getModuleAt($row, $col)->isDark() ? 1 : 0; $expected = $expectedFinder[$r][$c]; if ($actual !== $expected) { $errors++; } } } if ($errors === 0) { echo "✅ {$finder['name']} finder pattern correct\n"; } else { echo "❌ {$finder['name']} finder pattern has {$errors} errors\n"; $finderOk = false; } } // 2. Check separators (row 7 and col 7 around finders) echo "\n=== Separators ===\n"; $separatorOk = true; // Top-left separator: row 7, cols 0-7 and col 7, rows 0-7 for ($i = 0; $i < 8; $i++) { if ($matrix->getModuleAt(7, $i)->isDark()) { echo "❌ Separator error: row 7, col {$i} should be light\n"; $separatorOk = false; } if ($matrix->getModuleAt($i, 7)->isDark()) { echo "❌ Separator error: row {$i}, col 7 should be light\n"; $separatorOk = false; } } // Top-right separator: row 7, cols 13-20 and col 13, rows 0-7 for ($i = 0; $i < 8; $i++) { if ($matrix->getModuleAt(7, 13 + $i)->isDark()) { echo "❌ Separator error: row 7, col " . (13 + $i) . " should be light\n"; $separatorOk = false; } if ($matrix->getModuleAt($i, 13)->isDark()) { echo "❌ Separator error: row {$i}, col 13 should be light\n"; $separatorOk = false; } } // Bottom-left separator: row 13, cols 0-7 and col 7, rows 13-20 for ($i = 0; $i < 8; $i++) { if ($matrix->getModuleAt(13, $i)->isDark()) { echo "❌ Separator error: row 13, col {$i} should be light\n"; $separatorOk = false; } if ($matrix->getModuleAt(13 + $i, 7)->isDark()) { echo "❌ Separator error: row " . (13 + $i) . ", col 7 should be light\n"; $separatorOk = false; } } if ($separatorOk) { echo "✅ Separators correct\n"; } // 3. Check timing patterns echo "\n=== Timing Patterns ===\n"; $timingOk = true; // Horizontal timing (row 6, cols 8-12) $expectedTiming = [1,0,1,0,1]; // Alternating for ($i = 0; $i < 5; $i++) { $col = 8 + $i; $actual = $matrix->getModuleAt(6, $col)->isDark() ? 1 : 0; $expected = $expectedTiming[$i]; if ($actual !== $expected) { echo "❌ Timing error: row 6, col {$col} should be {$expected}, got {$actual}\n"; $timingOk = false; } } // Vertical timing (col 6, rows 8-12) for ($i = 0; $i < 5; $i++) { $row = 8 + $i; $actual = $matrix->getModuleAt($row, 6)->isDark() ? 1 : 0; $expected = $expectedTiming[$i]; if ($actual !== $expected) { echo "❌ Timing error: row {$row}, col 6 should be {$expected}, got {$actual}\n"; $timingOk = false; } } if ($timingOk) { echo "✅ Timing patterns correct\n"; } // 4. Check format information echo "\n=== Format Information ===\n"; $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'; } $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 "Horizontal: {$formatH}\n"; echo "Vertical: {$formatV}\n"; if ($formatH === $formatV) { echo "✅ Format info matches\n"; // Decode format info $xorMask = '101010000010010'; $unmasked = ''; for ($i = 0; $i < 15; $i++) { $unmasked .= (int)$formatH[$i] ^ (int)$xorMask[$i]; } $ecBits = substr($unmasked, 0, 2); $maskBits = substr($unmasked, 2, 5); $ecLevel = match($ecBits) { '01' => 'L', '00' => 'M', '11' => 'Q', '10' => 'H', default => 'UNKNOWN' }; $maskPattern = bindec($maskBits); echo " EC Level: {$ecLevel}\n"; echo " Mask Pattern: {$maskPattern}\n"; if ($ecLevel === 'M') { echo "✅ EC Level correct\n"; } else { echo "❌ EC Level incorrect (expected M)\n"; } } else { echo "❌ Format info doesn't match!\n"; echo "This is a CRITICAL error - QR code won't scan!\n"; } // 5. Check dark module echo "\n=== Dark Module ===\n"; $darkModuleRow = 4 * 1 + 9; // 13 for version 1 $darkModuleCol = 8; $hasDarkModule = $matrix->getModuleAt($darkModuleRow, $darkModuleCol)->isDark(); if ($hasDarkModule) { echo "✅ Dark module present at ({$darkModuleRow}, {$darkModuleCol})\n"; } else { echo "❌ Dark module missing at ({$darkModuleRow}, {$darkModuleCol})\n"; } // 6. Summary echo "\n=== Summary ===\n"; $allOk = $finderOk && $separatorOk && $timingOk; if ($allOk && $formatH === $formatV && $hasDarkModule) { echo "✅ All critical structures are correct!\n"; echo "\nIf the QR code still doesn't scan, the issue might be:\n"; echo "1. Data encoding/placement\n"; echo "2. Reed-Solomon error correction\n"; echo "3. SVG rendering issues\n"; echo "4. Scanner app quality\n"; } else { echo "❌ Some structures are incorrect!\n"; echo "Fix these issues first before testing scanning.\n"; }