SVG.php

A simple php program, wich is able to read 2 arguments:

a max puzzle display number

29

and a solution string like

00:01:11,5 solNum=  1~AAIIFFFLDD GBBBBBHJJJ | AAAIIFLLLD GGGCCCHHHJ | EEEEIFKLDD EGCCKKKKHJ

 

Then we create an SVG output like this:

 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1 plus MathML 2.0 plus SVG 1.1//EN">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="565" height="360"
xmlns:xlink="http://www.w3.org/1999/xlink">
<symbol id="box_0">
    <path d="M100 100 L0 90 L0 190 L100 200 Z" style="fill:#F00000" />
    <path d="M100 100 L0 90 L55 40 L155 50 Z" style="fill:#FF0000" />
    <path d="M100 100 L155 50 L155 150 L100 200 Z" style="fill:#D00000" />
    <text style="fill:#FF0000; font-size:65px" transform="rotate(-42.3) skewX(-42.3) translate(176,201)" text-anchor="middle">A</text>
    <text style="fill:#D00000; font-size:90px" transform="skewY(5.7) translate(50,170)" text-anchor="middle">A</text>
    <text style="fill:#F00000; font-size:70px" transform="rotate(51) skewY(-45.7) translate(102,110)" text-anchor="middle">A</text>
</symbol>

 

....


<symbol id="box_11">
    <path d="M100 100 L0 90 L0 190 L100 200 Z" style="fill:#C0C000" />
    <path d="M100 100 L0 90 L55 40 L155 50 Z" style="fill:#CCCC00" />
    <path d="M100 100 L155 50 L155 150 L100 200 Z" style="fill:#A0A000" />
    <text style="fill:#CCCC00; font-size:65px" transform="rotate(-42.3) skewX(-42.3) translate(176,201)" text-anchor="middle">L</text>
    <text style="fill:#A0A000; font-size:90px" transform="skewY(5.7) translate(50,170)" text-anchor="middle">L</text>
    <text style="fill:#C0C000; font-size:70px" transform="rotate(51) skewY(-45.7) translate(102,110)" text-anchor="middle">L</text>
</symbol>



... and more for animation...

</g>
</svg>

Sourcecode:

<?php
// -------------------------------------------------------------------------
function head($x, $y, $z,  $scale,$max) {
    echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1 plus MathML 2.0 plus SVG 1.1//EN">' . "\n";
    echo '<svg version="1.1" ';
    echo 'xmlns="http://www.w3.org/2000/svg" width="' . intval(($x *100 + $y * 55) * $scale + 10) . '" height="' . intval((($x*10 + $y*50) + $z * 100) * $scale + 110) . '" ' . "\n";
    echo 'xmlns:xlink="http://www.w3.org/1999/xlink">' . "\n";

    $arrA=array("#F00000","#00F000","#0000F0","#00F0F0","#F000F0","#F0F000",
                "#C00000","#00C000","#0000C0","#00C0C0","#C000C0","#C0C000",
                "#00F080","#F00080","#F08000","#0080F0","#8000F0","#80F000", "#80F0F0","#F080F0", "#F0F080","#F0F0F0",
                "#800000","#008000","#000080","#008080","#800080","#808000","#808080");
    $arrB=array("#FF0000","#00FF00","#0000FF","#00FFFF","#FF00FF","#FFFF00",
                "#CC0000","#00CC00","#0000CC","#00CCCC","#CC00CC","#CCCC00",    
                "#00FF88","#FF0088","#FF8800","#0088FF","#8800FF","#88FF00", "#88FFFF","#FF88FF","#FFFF88","#FFFFFF",
                "#880000","#008800","#000088","#008888","#880088","#888800","#888888");  
    $arrC=array("#D00000","#00D000","#0000D0","#00D0D0","#D000D0","#D0D000",
                "#A00000","#00A000","#0000A0","#00A0A0","#A000A0","#A0A000",
                "#00D060","#D00060","#D06000","#0060D0","#6000D0","#60D000",  "#60D0D0","#D060D0","#D0D060","#D0D0D0",
                "#600000","#006000","#000060","#006060","#600060","#606000","#606060");
    
    for ($i=0;$i<$max;$i++ ) {
        echo '<symbol id="box_'.$i.'">'."\n\t";
    echo '<path d="M100 100 L0 90 L0 190 L100 200 Z" style="fill:'.$arrA[$i].'" />'."\n\t";
    echo '<path d="M100 100 L0 90 L55 40 L155 50 Z" style="fill:'.$arrB[$i].'" />'."\n\t";
    echo '<path d="M100 100 L155 50 L155 150 L100 200 Z" style="fill:'.$arrC[$i].'" />'."\n\t";
    echo '<text style="fill:'.$arrB[$i].'; font-size:65px" transform="rotate(-42.3) skewX(-42.3) translate(176,201)" text-anchor="middle">'.chr(65+$i).'</text>'."\n\t";
    echo '<text style="fill:'.$arrC[$i].'; font-size:90px" transform="skewY(5.7) translate(50,170)" text-anchor="middle">'.chr(65+$i).'</text>'."\n\t";
    echo '<text style="fill:'.$arrA[$i].'; font-size:70px" transform="rotate(51) skewY(-45.7) translate(102,110)" text-anchor="middle">'.chr(65+$i).'</text>'."\n";
    echo '</symbol>'."\n\n";
    }
}
// -------------------------------------------------------------------------
function add($color, &$dispSeq) {
    for ($i = 0; $i < strlen($dispSeq); $i++) {
        if (substr($dispSeq, $i, 1) == $color)
            return;
    }
    $dispSeq.=$color;
}
// -------------------------------------------------------------------------
function getDispSeq($maxX, $maxY, $maxZ, $charLine, &$dispSeq) {
    for ($z = $maxZ - 1; $z >= 0; $z--) {
        for ($y = 0; $y < $maxY; $y++) {
            for ($x = 0; $x < $maxX; $x++) {
                $ch = getColIdx( $x, $y, $z, $maxX, $maxY, $maxZ, $charLine);
                add($ch, $dispSeq);
            }
        }
    }
}
// -------------------------------------------------------------------------
function get(&$maxX, &$maxY, &$maxZ, $line) {
    $arr = explode("|", substr($line, strpos($line, "~")));
    $maxZ = sizeof($arr);
    $arr = explode(" ", trim($arr[0]));
    $maxY = sizeof($arr);
    $maxX = strlen(trim($arr[0], "~"));
}
// -------------------------------------------------------------------------
function getColIdx( $x, $y, $z, $maxX, $maxY, $maxZ, $charLine) {
    $n = substr($charLine, $x + $y * $maxX + $z * ($maxX * $maxY), 1);
    if ($n == '_')
        return '@';

    $idx = (ord($n) - ord("A"));

    return $n;
}

// -------------------------------------------------------------------------
// MAIN ENTRY
// -------------------------------------------------------------------------
// get Command Line arguments
if (isset($_GET['max']))
    $max = $_GET['max'];  // argLine
else {
    $max = 29;
}

if (isset($_GET['line']))
    $line = $_GET['line'];
else {
    $line = "00:01:11,5 solNum=  1~AAIIFFFLDD GBBBBBHJJJ | AAAIIFLLLD GGGCCCHHHJ | EEEEIFKLDD EGCCKKKKHJ";
}


/*
 *  move X:     x+=DX y+=  DY
 *  move y:     x-=DZ y+=  DX/2
 *  move z:     x+=0  y+=  DX
 */
$DX=100;
$DY=10;
$DZ=55;
//$dx = 87;  // sqrt(3)/2 *100
//$dy = 50;

get($maxX, $maxY, $maxZ, $line);

// header line
$xl =  ($maxY-1) * $DZ;
$y = 20;
$scale = 0.5;

head($maxX, $maxY, $maxZ, $scale,$max);

$charLine = trim(str_replace("|", "", str_replace(" ", "", substr($line, strpos($line, "~")))), "~");
$dispSeq = "";

getDispSeq($maxX, $maxY, $maxZ, $charLine, $dispSeq);


$max = strlen($dispSeq);


echo '<g transform="scale(' . $scale . ') translate(' . $xl . ',' . $y . ')">' . "\n";
echo '<text x="' . (-$xl + 10) . '" y="-200" style="font-size:50px;fill:black" >' . "\n";
echo "puzzle animation";
$delay=$max/4;
$delay2=$max/4    +$max*5;
echo '<set attributeName="y" to="20" begin="'.$delay.'s" />'."\n";
echo '<set attributeName="y" to="-200" begin="'.$delay2.'s" />'."\n";
echo "</text>\n";


echo '<text x="' . (-$xl + 10) . '" y="-200" style="font-size:50px;fill:black" >' . "\n";
echo "puzzle solved";

echo '<set attributeName="y" to="20" begin="'.$delay2.'s" />'."\n";
echo '<set attributeName="y" to="-200" begin="'.($delay2+5).'s" />'."\n";
echo "</text>\n";



for ($x = 0; $x < $maxX; $x++) {
    for ($y = 0; $y < $maxY; $y++) {
        for ($z = $maxZ - 1; $z >= 0; $z--) {
            $ch = getColIdx( $x, $y, $z, $maxX, $maxY, $maxZ, $charLine);

            if (strpos(substr($dispSeq, 0, $max), $ch) === false) {
                ; // echo "ignore $ch, not found in $dispSeq looking till $max\n";
            } else if ($ch > '@') {
                $nbrToShow =  strpos(substr($dispSeq, 0, $max), $ch);
         
                $X = ( $x * 100 - $y * 55);
                $Y = ( $x * 10 + $y * 50 + $z * 100);
                $YOfs = 100+( $maxX * 10 + $maxY * 50 + $maxZ * 100);
                $delay=$max/4    +$nbrToShow*5;
                $delPreview=$nbrToShow/4;
                echo '<use  x="'.($X).'" y="'.($Y-$YOfs).'" xlink:href="#box_'.(ord($ch)-ord('A')).'" >'."\n";
                    echo '<set attributeName="y" to="'.$Y.'" begin="'.$delPreview.'s" />'."\n";
                    echo '<set attributeName="y" to="'.($Y-$YOfs).'" begin="'.($delPreview+0.25).'s" />'."\n";
                    echo '<animate attributeName="y" begin="'.$delay.'s" dur="5s" from="'.($Y-$YOfs).'" to="'.$Y.'" fill="freeze"/>'."\n";
                echo '</use>'."\n";
            }
        }
    }
}
?>


</g>
</svg>