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>
<?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>