- 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.
197 lines
4.9 KiB
PHP
197 lines
4.9 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 "=== Data Placement Order Verification ===\n\n";
|
|
|
|
$data = "HELLO WORLD";
|
|
$config = new QrCodeConfig(
|
|
version: QrCodeVersion::fromNumber(1),
|
|
errorCorrectionLevel: ErrorCorrectionLevel::M,
|
|
encodingMode: EncodingMode::BYTE
|
|
);
|
|
|
|
$matrix = QrCodeGenerator::generate($data, $config);
|
|
$size = $matrix->getSize();
|
|
|
|
echo "Testing Data Placement for Version 1 (21x21)\n\n";
|
|
|
|
// Laut ISO/IEC 18004: Data placement beginnt bottom-right, geht nach oben
|
|
// Dann zwei Spalten nach links, geht nach unten, usw.
|
|
|
|
// Simulate data placement to verify order
|
|
function isOccupied(int $row, int $col, int $size): bool
|
|
{
|
|
// Finder patterns + separators
|
|
if (
|
|
($row <= 8 && $col <= 8) ||
|
|
($row <= 7 && $col >= $size - 8) ||
|
|
($row >= $size - 8 && $col <= 7)
|
|
) {
|
|
return true;
|
|
}
|
|
|
|
// Timing patterns
|
|
if ($row === 6 || $col === 6) return true;
|
|
|
|
// Format information
|
|
if ($row === 8 || $col === 8) return true;
|
|
|
|
// Dark module
|
|
if ($row === 13 && $col === 8) return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
echo "First 20 data positions (should be in zigzag pattern):\n";
|
|
$positions = [];
|
|
$count = 0;
|
|
|
|
for ($col = $size - 1; $col >= 1 && $count < 20; $col -= 2) {
|
|
if ($col === 6) $col--;
|
|
|
|
$upward = ((int)(($size - 1 - $col) / 2) % 2) === 0;
|
|
|
|
for ($i = 0; $i < $size && $count < 20; $i++) {
|
|
$row = $upward ? ($size - 1 - $i) : $i;
|
|
|
|
for ($c = 0; $c < 2 && $count < 20; $c++) {
|
|
$currentCol = $col - $c;
|
|
|
|
if (isOccupied($row, $currentCol, $size)) continue;
|
|
|
|
$count++;
|
|
$positions[] = "({$row},{$currentCol})";
|
|
|
|
if ($count <= 20) {
|
|
echo sprintf("Position %2d: (%2d,%2d)\n", $count, $row, $currentCol);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
echo "\n=== Expected vs Actual First Bits ===\n";
|
|
|
|
// Expected data (from encoding):
|
|
// Mode: 0100 (Byte)
|
|
// Count: 00001011 (11 characters)
|
|
// First char 'H': 01001000
|
|
|
|
$expectedBits = "0100" . "00001011" . "01001000";
|
|
echo "Expected first 20 bits: {$expectedBits}\n";
|
|
|
|
// Get actual bits from matrix
|
|
function applyMask(int $row, int $col, int $mask): bool
|
|
{
|
|
return match ($mask) {
|
|
2 => $col % 3 === 0, // Current mask
|
|
default => false
|
|
};
|
|
}
|
|
|
|
$actualBits = '';
|
|
$count = 0;
|
|
|
|
for ($col = $size - 1; $col >= 1 && $count < 20; $col -= 2) {
|
|
if ($col === 6) $col--;
|
|
|
|
$upward = ((int)(($size - 1 - $col) / 2) % 2) === 0;
|
|
|
|
for ($i = 0; $i < $size && $count < 20; $i++) {
|
|
$row = $upward ? ($size - 1 - $i) : $i;
|
|
|
|
for ($c = 0; $c < 2 && $count < 20; $c++) {
|
|
$currentCol = $col - $c;
|
|
|
|
if (isOccupied($row, $currentCol, $size)) continue;
|
|
|
|
$module = $matrix->getModuleAt($row, $currentCol);
|
|
$bit = $module->isDark() ? 1 : 0;
|
|
|
|
// Unmask
|
|
if (applyMask($row, $currentCol, 2)) {
|
|
$bit = $bit === 1 ? 0 : 1;
|
|
}
|
|
|
|
$actualBits .= $bit;
|
|
$count++;
|
|
}
|
|
}
|
|
}
|
|
|
|
echo "Actual first 20 bits: {$actualBits}\n\n";
|
|
|
|
// Compare
|
|
$matches = 0;
|
|
for ($i = 0; $i < 20; $i++) {
|
|
if ($expectedBits[$i] === $actualBits[$i]) {
|
|
$matches++;
|
|
} else {
|
|
echo "❌ Bit {$i}: expected {$expectedBits[$i]}, got {$actualBits[$i]}\n";
|
|
}
|
|
}
|
|
|
|
echo "\nMatch: {$matches}/20 bits\n";
|
|
|
|
if ($matches === 20) {
|
|
echo "✅ Data placement order is CORRECT!\n";
|
|
} else {
|
|
echo "❌ Data placement order is WRONG!\n";
|
|
}
|
|
|
|
// Visualisiere die ersten Data-Positionen
|
|
echo "\n=== Visual Data Placement Map ===\n";
|
|
echo "Legend: # = Function Pattern, D = Data (numbered)\n\n";
|
|
|
|
$dataMap = [];
|
|
for ($r = 0; $r < $size; $r++) {
|
|
$dataMap[$r] = [];
|
|
for ($c = 0; $c < $size; $c++) {
|
|
$dataMap[$r][$c] = isOccupied($r, $c, $size) ? '#' : ' ';
|
|
}
|
|
}
|
|
|
|
// Mark first 20 data positions
|
|
$count = 0;
|
|
for ($col = $size - 1; $col >= 1 && $count < 20; $col -= 2) {
|
|
if ($col === 6) $col--;
|
|
|
|
$upward = ((int)(($size - 1 - $col) / 2) % 2) === 0;
|
|
|
|
for ($i = 0; $i < $size && $count < 20; $i++) {
|
|
$row = $upward ? ($size - 1 - $i) : $i;
|
|
|
|
for ($c = 0; $c < 2 && $count < 20; $c++) {
|
|
$currentCol = $col - $c;
|
|
|
|
if (isOccupied($row, $currentCol, $size)) continue;
|
|
|
|
$count++;
|
|
$dataMap[$row][$currentCol] = (string)($count % 10);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Print map
|
|
echo " ";
|
|
for ($c = 0; $c < $size; $c++) {
|
|
echo str_pad((string)$c, 2, ' ', STR_PAD_LEFT);
|
|
}
|
|
echo "\n";
|
|
|
|
for ($r = 0; $r < $size; $r++) {
|
|
echo str_pad((string)$r, 2, ' ', STR_PAD_LEFT) . ' ';
|
|
for ($c = 0; $c < $size; $c++) {
|
|
echo $dataMap[$r][$c] . ' ';
|
|
}
|
|
echo "\n";
|
|
}
|