Files
michaelschiemer/tests/debug/test-qr-data-placement-order.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

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";
}