- 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.
240 lines
7.3 KiB
PHP
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";
|