Files
michaelschiemer/tests/debug/test-qr-debug-visualizer.php
Michael Schiemer fc3d7e6357 feat(Production): Complete production deployment infrastructure
- Add comprehensive health check system with multiple endpoints
- Add Prometheus metrics endpoint
- Add production logging configurations (5 strategies)
- Add complete deployment documentation suite:
  * QUICKSTART.md - 30-minute deployment guide
  * DEPLOYMENT_CHECKLIST.md - Printable verification checklist
  * DEPLOYMENT_WORKFLOW.md - Complete deployment lifecycle
  * PRODUCTION_DEPLOYMENT.md - Comprehensive technical reference
  * production-logging.md - Logging configuration guide
  * ANSIBLE_DEPLOYMENT.md - Infrastructure as Code automation
  * README.md - Navigation hub
  * DEPLOYMENT_SUMMARY.md - Executive summary
- Add deployment scripts and automation
- Add DEPLOYMENT_PLAN.md - Concrete plan for immediate deployment
- Update README with production-ready features

All production infrastructure is now complete and ready for deployment.
2025-10-25 19:18:37 +02:00

240 lines
7.3 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;
use App\Framework\QrCode\Structure\FinderPattern;
use App\Framework\QrCode\Structure\AlignmentPattern;
echo "=== QR Code Debug Visualizer ===\n\n";
// Test with simple data
$data = "HELLO";
$version = 1;
echo "Testing Data: '{$data}'\n";
echo "Version: {$version}\n";
echo "Length: " . strlen($data) . " bytes\n\n";
// Generate QR Code
$config = new QrCodeConfig(
version: QrCodeVersion::fromNumber($version),
errorCorrectionLevel: ErrorCorrectionLevel::M,
encodingMode: EncodingMode::BYTE
);
$matrix = QrCodeGenerator::generate($data, $config);
$size = $matrix->getSize();
echo "Matrix Size: {$size}x{$size}\n\n";
// Function to check if position is a function pattern
function isFunctionPattern(int $row, int $col, int $size, int $version): string
{
// Finder patterns + separators (9x9 areas)
if (
($row <= 8 && $col <= 8) || // Top-left
($row <= 8 && $col >= $size - 8) || // Top-right
($row >= $size - 8 && $col <= 8) // Bottom-left
) {
return 'FINDER';
}
// Timing patterns
if ($row === 6 || $col === 6) {
return 'TIMING';
}
// Dark module
$darkModuleRow = 4 * $version + 9;
if ($row === $darkModuleRow && $col === 8) {
return 'DARK';
}
// Format information positions
// Horizontal: row 8, cols 0-8 and size-8 to size-1
if ($row === 8 && ($col <= 8 || $col >= $size - 8)) {
return 'FORMAT';
}
// Vertical: col 8, rows 0-8 and size-7 to size-1
if ($col === 8 && ($row <= 8 || $row >= $size - 7)) {
return 'FORMAT';
}
// Alignment patterns (Version 2+)
if ($version >= 2) {
$alignmentLocations = AlignmentPattern::getLocations($version);
foreach ($alignmentLocations as $alignRow) {
foreach ($alignmentLocations as $alignCol) {
// Skip if overlaps with finder patterns
if ($alignRow <= 8 && $alignCol <= 8) {
continue;
}
if ($alignRow <= 8 && $alignCol >= $size - 8) {
continue;
}
if ($alignRow >= $size - 8 && $alignCol <= 8) {
continue;
}
// Check if within 5x5 alignment pattern
if (abs($row - $alignRow) <= 2 && abs($col - $alignCol) <= 2) {
return 'ALIGN';
}
}
}
}
return 'DATA';
}
// Visualize matrix with pattern types
echo "=== Matrix Visualization (Pattern Types) ===\n";
echo "Legend: F=Finder, T=Timing, A=Align, D=Dark, X=Format, .=Data(light), #=Data(dark)\n\n";
for ($row = 0; $row < $size; $row++) {
for ($col = 0; $col < $size; $col++) {
$patternType = isFunctionPattern($row, $col, $size, $version);
$isDark = $matrix->getModuleAt($row, $col)->isDark();
$char = match($patternType) {
'FINDER' => 'F',
'TIMING' => 'T',
'ALIGN' => 'A',
'DARK' => 'D',
'FORMAT' => 'X',
'DATA' => $isDark ? '#' : '.',
default => '?'
};
echo $char . ' ';
}
echo "\n";
}
echo "\n=== Data Region Analysis ===\n";
// Count data modules
$dataModules = 0;
$darkDataModules = 0;
for ($row = 0; $row < $size; $row++) {
for ($col = 0; $col < $size; $col++) {
if (isFunctionPattern($row, $col, $size, $version) === 'DATA') {
$dataModules++;
if ($matrix->getModuleAt($row, $col)->isDark()) {
$darkDataModules++;
}
}
}
}
echo "Total data modules: {$dataModules}\n";
echo "Dark data modules: {$darkDataModules}\n";
echo "Light data modules: " . ($dataModules - $darkDataModules) . "\n";
echo "Data dark ratio: " . round(($darkDataModules / $dataModules) * 100, 2) . "%\n\n";
// Show data bits in placement order (zig-zag pattern)
echo "=== Data Bits (Zig-Zag Placement Order) ===\n";
echo "First 64 data bits:\n";
$bitIndex = 0;
$bits = [];
for ($col = $size - 1; $col >= 1; $col -= 2) {
// Skip timing column
if ($col === 6) {
$col--;
}
// Zig-zag direction
$upward = ((int) (($size - 1 - $col) / 2) % 2) === 0;
for ($i = 0; $i < $size; $i++) {
$row = $upward ? ($size - 1 - $i) : $i;
// Check both columns of the pair
for ($c = 0; $c < 2; $c++) {
$currentCol = $col - $c;
if (isFunctionPattern($row, $currentCol, $size, $version) === 'DATA') {
$bit = $matrix->getModuleAt($row, $currentCol)->isDark() ? '1' : '0';
$bits[] = $bit;
$bitIndex++;
if ($bitIndex <= 64) {
echo $bit;
if ($bitIndex % 8 === 0) {
echo " ";
}
}
}
}
}
}
echo "\n\n";
// Decode first few bytes
echo "=== First Data Bytes (Binary -> Decimal) ===\n";
for ($i = 0; $i < min(8, count($bits) / 8); $i++) {
$byte = substr(implode('', $bits), $i * 8, 8);
$decimal = bindec($byte);
$char = $decimal >= 32 && $decimal < 127 ? chr($decimal) : '.';
echo "Byte " . ($i + 1) . ": {$byte} = {$decimal} ('{$char}')\n";
}
echo "\n=== Expected Encoding ===\n";
echo "Mode indicator (Byte): 0100\n";
echo "Character count (8 bits): " . str_pad(decbin(strlen($data)), 8, '0', STR_PAD_LEFT) . " = " . strlen($data) . "\n";
echo "Data bytes:\n";
for ($i = 0; $i < strlen($data); $i++) {
$byte = ord($data[$i]);
$binary = str_pad(decbin($byte), 8, '0', STR_PAD_LEFT);
echo " '{$data[$i]}': {$binary} = {$byte}\n";
}
echo "\n=== Format Information Analysis ===\n";
echo "Format info should encode: Error Correction Level + Mask Pattern\n";
echo "Located at: row 8 and col 8 (with redundancy)\n\n";
// Extract format information bits
$formatBits = [];
// Horizontal format info (row 8, skipping timing column at 6)
for ($col = 0; $col < 9; $col++) {
if ($col === 6) continue; // Skip timing column
$formatBits[] = $matrix->getModuleAt(8, $col)->isDark() ? '1' : '0';
}
echo "Horizontal format bits: " . implode('', $formatBits) . "\n";
// Vertical format info
$formatBitsVertical = [];
for ($row = $size - 1; $row >= $size - 7; $row--) {
$formatBitsVertical[] = $matrix->getModuleAt($row, 8)->isDark() ? '1' : '0';
}
for ($row = 7; $row >= 0; $row--) {
if ($row === 6) continue; // Skip timing column
$formatBitsVertical[] = $matrix->getModuleAt($row, 8)->isDark() ? '1' : '0';
}
echo "Vertical format bits: " . implode('', $formatBitsVertical) . "\n";
echo "\n=== Summary ===\n";
echo "✓ Matrix generated: {$size}x{$size}\n";
echo "✓ Function patterns placed\n";
echo "✓ Data region identified: {$dataModules} modules\n";
echo "✓ First data bits extracted and decoded\n\n";
echo "Next steps for debugging:\n";
echo "1. Compare expected vs actual data encoding\n";
echo "2. Verify format information is correct\n";
echo "3. Check if mask pattern was applied correctly\n";
echo "4. Validate error correction codewords\n";