1
Fork 0
lorchess.ru/_assets/vendor/pgn4web/puzzler.php

488 lines
15 KiB
PHP

<?php
/*
* pgn4web javascript chessboard
* copyright (C) 2009-2013 Paolo Casaschi
* see README file and http://pgn4web.casaschi.net
* for credits, license and more details
*/
error_reporting(E_ALL | E_STRICT);
// add temporarily blocked sites here
$blockedReferrers = array();
$referrerHost = isset($_SERVER['HTTP_REFERER']) ? parse_url($_SERVER['HTTP_REFERER'], PHP_URL_HOST) : "";
if ($referrerHost) {
foreach ($blockedReferrers as $blockedReferrer) {
if (strstr($referrerHost, $blockedReferrer)) {
$thisPage = curPageURL();
$thisPage .= ((strstr($thisPage, "?") ? "&" : "?") . "selfReferred=true");
print <<<END
<!DOCTYPE HTML>
<html>
<head>
</head>
<body style="padding:10px; font-size:x-small; font-family:sans-serif;">
<p style="font-weight:bold;">pgn4web chess puzzler: warning</p><p>Your site generates a substantial load on the pgn4web chess puzzler server. Please install the pgn4web chess puzzler on your own server following these <a href="http://code.google.com/p/pgn4web/wiki/ServiceAvailability#Use_on_a_professional_site" target="_blank">instructions</a>. Sorry for any inconvenience, previous attempts contacting your site's administrators were unsuccessful.</p><p>Click <a href="$thisPage">here</a> to view the pgn4web chess puzzler.</p>
</body>
</html>
END;
exit;
}
}
}
$debugInfo = "\n";
function get_param($param, $shortParam, $default) {
if (isset($_REQUEST[$param])) { return $_REQUEST[$param]; }
if (isset($_REQUEST[$shortParam])) { return $_REQUEST[$shortParam]; }
return $default;
}
$pgnData = get_param("pgnData", "pd", "tactics.pgn");
function get_pgnText($pgnUrl) {
if (strpos($pgnUrl, ":") || (strpos($pgnUrl, "%3A"))) { return "[Event \"error: invalid pgnData parameter\"]\n"; }
$fileLimitBytes = 10000000; // 10Mb
$pgnText = file_get_contents($pgnUrl, NULL, NULL, 0, $fileLimitBytes + 1);
if (!$pgnText) { return "[Event \"error: failed to get pgnData content\"]\n"; }
$pgnText = str_replace(array("&", "<", ">"), array("&amp;", "&lt;", "&gt;"), $pgnText);
return $pgnText;
}
$pgnText = get_pgnText($pgnData);
// for simplicity, remove all comments from the game text
// to avoid spurious [ in comments breaking the regular expression
// splitting the PGN data into games
$pgnText = preg_replace("/{[^}]*}/", "", $pgnText);
$pgnText = preg_replace("/;[^\n$]*/", "", $pgnText);
$pgnText = preg_replace("/(\n|^)%[^\n$]*/", "", $pgnText);
$numGames = preg_match_all("/(\s*\[\s*(\w+)\s*\"([^\"]*)\"\s*\]\s*)+[^\[]*/", $pgnText, $games );
$gameNum = get_param("gameNum", "gn", "");
$expiresDate = "";
if ($gameNum == "random") { $gameNum = rand(1, $numGames); }
else if (!preg_match("/^\d+$/", $gameNum)) {
$timeNow = time();
$expiresDate = gmdate("D, d M Y H:i:s", (floor($timeNow / (60 * 60 * 24)) + 1) * (60 * 60 * 24)) . " GMT";
if (!preg_match("/^[ +-]\d+$/", $gameNum)) { $gameNum = 0; } // space is needed since + is urldecoded as space
$gameNum = floor(($gameNum + ($timeNow / (60 * 60 * 24))) % $numGames) + 1;
}
else if ($gameNum < 1) { $gameNum = 1; }
else if ($gameNum > $numGames) { $gameNum = $numGames; }
$debugInfo .= "#" . ($gameNum ^ $numGames) . "." . $numGames . "\n";
$gameNum -= 1;
$pgnGame = $games[0][$gameNum];
$lightColorHex = get_param("lightColorHex", "lch", "EFF4EC"); // FFCC99
$lightColorHexCss = "#" . $lightColorHex;
$darkColorHex = get_param("darkColorHex", "dch", "C6CEC3"); // CC9966
$darkColorHexCss = "#" . $darkColorHex;
$controlBackgroundColorHex = get_param("controlBackgroundColorHex", "cbch", "EFF4EC"); // FFCC99
$controlBackgroundColorHexCss = "#" . $controlBackgroundColorHex;
$controlTextColorHex = get_param("controlTextColorHex", "ctch", "888888"); // 663300
$controlTextColorHexCss = "#" . $controlTextColorHex;
$squareSize = get_param("squareSize", "ss", "30");
$squareSizeCss = $squareSize . "px";
if ($squareSize < 20) { $squareSize = 20; }
if ($squareSize < 30) {
$borderStyleCss = "none";
$highlightBorderStyleCss = "none";
$borderSize = 0;
$borderSizeCss = $borderSize;
} else {
$borderStyleCss = "solid";
$highlightBorderStyleCss = "inset";
$borderSize = ceil($squareSize / 50);
$borderSizeCss = $borderSize . "px";
}
$bareSquareSize = $squareSize - 2 * $borderSize;
$bareSquareSizeCss = $bareSquareSize . "px";
function defaultPieceSize($ss) {
$pieceSizeOptions = array(20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 52, 56, 60, 64, 72, 80, 88, 96, 112, 128, 144, 300);
$targetPieceSize = floor(0.8 * $ss);
for ($ii=count($pieceSizeOptions)-1; $ii>=0; $ii--) {
if ($pieceSizeOptions[$ii] <= $targetPieceSize) { return $pieceSizeOptions[$ii]; }
}
return $pieceSizeOptions[0];
}
$pieceSize = defaultPieceSize($squareSize - 2 * $borderSize);
$pieceSizeCss = $pieceSize . "px";
$pieceFont = get_param("pieceFont", "pf", "default");
if ($pieceFont == "a") { $pieceFont = "alpha"; }
if ($pieceFont == "m") { $pieceFont = "merida"; }
if ($pieceFont == "u") { $pieceFont = "uscf"; }
if (($pieceFont == "random") || ($pieceFont == "r")) {
$randomPiece = rand(0, 2);
switch ($randomPiece) {
case 1: $pieceFont = "alpha"; break;
case 2: $pieceFont = "merida"; break;
default: $pieceFont = "uscf"; break;
}
}
if (($pieceFont == "hash") || ($pieceFont == "h")) {
// $hashPiece = strlen($pgnGame) % 3;
$hashPiece = $gameNum % 3;
switch ($hashPiece) {
case 1: $pieceFont = "alpha"; break;
case 2: $pieceFont = "merida"; break;
default: $pieceFont = "uscf"; break;
}
}
if (($pieceFont == "default") || ($pieceFont == "d")) {
if ($pieceSize < 28) { $pieceFont = "uscf"; }
else {
if ($pieceSize > 39) { $pieceFont = "merida"; }
else { $pieceFont = "alpha"; }
}
}
$boardSize = $squareSize * 8;
$boardSizeCss = $boardSize . "px";
$buttonHeight = $squareSize;
$buttonHeightCss = $buttonHeight . "px";
$buttonWidth = $squareSize * 4;
$buttonWidthCss = $buttonWidth . "px";
$buttonFontSize = floor($squareSize / 2.5);
if ($buttonFontSize < 10) { $buttonFontSize = 10; }
$buttonFontSizeCss = $buttonFontSize . "px";
$buttonPadding = floor($squareSize / 10);
$sidetomoveBorder = floor($buttonFontSize / 18) + 1;
$sidetomoveBorderCss = $sidetomoveBorder . "px";
$sidetomoveHeight = floor(0.8 * $buttonFontSize - 2 * $sidetomoveBorder);
$sidetomoveHeightCss = $sidetomoveHeight . "px";
$sidetomoveWidth = $sidetomoveHeight;
$sidetomoveWidthCss = $sidetomoveWidth . "px";
$frameBorderColorHex = get_param("frameBorderColorHex", "fbch", "C6CEC3");
if ($frameBorderColorHex == "none") {
$frameBorderStyleCss = "none";
$frameBorderWidth = 0;
$frameBorderWidthCss = "0";
$frameBorderColorHex = "000000";
} else {
$frameBorderStyleCss = "outset";
$frameBorderWidth = ceil($squareSize / 50);
$frameBorderWidthCss = $frameBorderWidth . "px";
}
$frameBorderColorHexCss = "#" . $frameBorderColorHex;
$frameWidth = $boardSize;
$frameWidthCss = $frameWidth . "px";
$frameHeight = $boardSize + $buttonHeight;
$frameHeightCss = $frameHeight . "px";
// undocumented features
$backgroundColorHex = get_param("backgroundColorHex", "bch", "transparent");
if (preg_match("/^[0123456789ABCDEF]{6}$/i", $backgroundColorHex)) {
$backgroundColorHexCss = "#" . $backgroundColorHex;
} else {
$backgroundColorHexCss = $backgroundColorHex;
}
$framePadding = get_param("framePadding", "fp", 0);
if ($framePadding != 0) {
$framePaddingCss = $framePadding . "px";
} else {
$framePaddingCss = $framePadding;
}
$rawGame = "";
$fenString = get_param("fenString", "fs", "");
if (($fenString == "true") || ($fenString == "t")) {
if (preg_match('/\[\s*FEN\s*"([^"]*)"\s*\]/', $pgnGame, $matches)) { $rawGame = $matches[1]; }
}
$pgnOnly = get_param("pgnOnly", "po", "");
if (($pgnOnly == "true") || ($pgnOnly == "t")) {
$rawGame = $pgnGame;
}
$pgnOnlyMini = get_param("pgnOnlyMini", "pom", "");
if (($pgnOnlyMini == "true") || ($pgnOnlyMini == "t")) {
if (preg_match('/\[\s*FEN\s*"[^"]*"\s*\]/', $pgnGame, $matches)) { $rawGame = "[SetUp \"1\"]\n" . $matches[0] . "\n\n"; }
$rawGame = $rawGame . preg_replace('/\[\s*\w+\s*"[^"]*"\s*\]\s*/', "", $pgnGame);
}
// end of undocumented features
$outerFrameWidth = $frameWidth + 2 * $frameBorderWidth + 2 * $framePadding;
$outerFrameHeight = $frameHeight + 2 * $frameBorderWidth + 2 * $framePadding;
function curPageURL() {
if ((isset($_SERVER["SERVER_NAME"])) && (isset($_SERVER["REQUEST_URI"]))) {
$pageURL = 'http';
if ((isset($_SERVER["HTTPS"])) && ($_SERVER["HTTPS"] == "on")) { $pageURL .= "s"; }
$pageURL .= "://";
if ((isset($_SERVER["SERVER_PORT"])) && ($_SERVER["SERVER_PORT"] != "80")) {
$pageURL .= $_SERVER["SERVER_NAME"].":".$_SERVER["SERVER_PORT"].$_SERVER["REQUEST_URI"];
} else {
$pageURL .= $_SERVER["SERVER_NAME"].$_SERVER["REQUEST_URI"];
}
} else {
$pageURL = "";
}
return $pageURL;
}
$thisPage = curPageURL();
$expiresMeta = "";
if ($expiresDate) {
header("expires: " . $expiresDate);
$expiresMeta = "<meta http-equiv=\"expires\" content=\"" . $expiresDate . "\">";
}
if ($rawGame) {
header("content-type: application/x-chess-pgn");
header("content-disposition: inline; filename=puzzler.pgn");
print $rawGame;
exit;
}
header("content-type: text/html; charset=utf-8");
print <<<END
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
$expiresMeta
<title>chess puzzler</title>
<!-- debug info
$debugInfo
end of debug info -->
<style type="text/css">
html,
body {
margin: 0px;
padding: 0px;
}
body {
padding: $framePaddingCss;
background: $backgroundColorHexCss;
}
.container {
width: $frameWidthCss;
height: $frameHeightCss;
border-style: $frameBorderStyleCss;
border-width: $frameBorderWidthCss;
border-color: $frameBorderColorHexCss;
}
.boardTable {
width: $boardSizeCss;
height: $boardSizeCss;
border-width: 0px;
}
.pieceImage {
width: $pieceSizeCss;
height: $pieceSizeCss;
}
.whiteSquare,
.blackSquare,
.highlightWhiteSquare,
.highlightBlackSquare {
width: $bareSquareSizeCss;
height: $bareSquareSizeCss;
border-style: $borderStyleCss;
border-width: $borderSizeCss;
}
.whiteSquare,
.highlightWhiteSquare {
border-color: $lightColorHexCss;
background: $lightColorHexCss;
}
.blackSquare,
.highlightBlackSquare {
border-color: $darkColorHexCss;
background: $darkColorHexCss;
}
.highlightWhiteSquare,
.highlightBlackSquare {
border-style: $highlightBorderStyleCss;
}
.buttonTable {
width: $boardSizeCss;
height: $buttonHeightCss;
background-color: $controlBackgroundColorHexCss;
}
.buttonCell {
width: $buttonWidthCss;
height: $buttonHeightCss;
white-space: nowrap;
overflow: hidden;
}
.buttonCellLink {
font-family: sans-serif;
font-size: $buttonFontSizeCss;
font-weight: 900;
color: $controlTextColorHexCss;
text-decoration: none;
}
.sidetomoveBox {
width: $sidetomoveWidthCss;
height: $sidetomoveHeightCss;
border-style: solid;
border-width: $sidetomoveBorderCss;
border-color: $controlTextColorHexCss;
}
</style>
<link rel="shortcut icon" href="pawn.ico" />
<script src="pgn4web.js" type="text/javascript"></script>
<script type="text/javascript">
"use strict";
SetImagePath("images/$pieceFont/$pieceSize");
SetShortcutKeysEnabled(false);
function displayPuzzlerHelp() {
var puzzlerHelp = "pgn4web chess puzzler" + "\\n\\n";
puzzlerHelp += "- the white or black small square below the chessboard's left side indicates the side to move" + "\\n\\n";
puzzlerHelp += "- show the puzzler's solution step by step on the chessboard by clicking the > button below the chessboard's right side" + "\\n\\n";
puzzlerHelp += "- step backwards one move by clicking the < button below the chessboard's left side" + "\\n\\n";
puzzlerHelp += "click OK for more information, including how to add the chess puzzler to a website or blog";
if (confirm(puzzlerHelp)) { window.open("http://code.google.com/p/pgn4web/wiki/Example_Puzzler", "_blank"); }
}
boardShortcut("F8", "chess puzzler help", function(t,e){ displayPuzzlerHelp(); });
clearShortcutSquares("E", "8");
clearShortcutSquares("BCDEFGH", "7");
clearShortcutSquares("ABCDEFGH", "23456");
clearShortcutSquares("BCFG", "1");
function solutionSoFar() {
var sol = "";
for (var thisPly = StartPly; thisPly < CurrentPly; thisPly++) {
var moveCount = Math.floor(thisPly/2)+1;
if ((thisPly % 2 === 0) || (thisPly === StartPly)) {
sol += (Math.floor(thisPly/2)+1) + ".";
if (thisPly % 2) { sol += ".."; }
sol += " ";
}
sol += Moves[thisPly] + " ";
}
return sol;
}
function customFunctionOnMove() {
var res, outcome;
if (CurrentPly == StartPly) {
document.getElementById("leftButtonLink").innerHTML = "<img class='sidetomoveBox' style='background-color:" + (CurrentPly % 2 ? "black" : "white" ) + ";' src='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoEAYAAADcbmQuAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAAZiS0dEAMAAwADAGp0HVAAAAAlwSFlzAAAASAAAAEgARslrPgAAAAl2cEFnAAAAKAAAACgAo3CU+AAAACNJREFUaN7twQENAAAAwqD3T20PBxQAAAAAAAAAAAAAAAAPBjIoAAFxtd2pAAAAAElFTkSuQmCC'>";
document.getElementById("leftButton").title = ((CurrentPly % 2) ? "Black" : "White") + " to play: find the best move";
} else {
document.getElementById("leftButtonLink").innerHTML = "&nbsp;&nbsp;&nbsp;&nbsp;&lt;&nbsp;&nbsp;&nbsp;&nbsp;";
document.getElementById("leftButton").title = "click < to step backwards one move";
}
if (CurrentPly == StartPly+PlyNumber) {
switch (res = gameResult[currentGame]) {
case "1-0": outcome = "white wins"; break;
case "0-1": outcome = "black wins"; break;
case "1/2-1/2": outcome = "draw"; break;
default: outcome = "end"; res = "*"; break;
}
document.getElementById("rightButtonLink").innerHTML = "&nbsp;&nbsp;&nbsp;&nbsp;" + res + "&nbsp;&nbsp;&nbsp;&nbsp;";
document.getElementById("rightButton").title = solutionSoFar() + " ..." + outcome;
} else {
document.getElementById("rightButtonLink").innerHTML = "&nbsp;&nbsp;&nbsp;&nbsp;&gt;&nbsp;&nbsp;&nbsp;&nbsp;";
if (CurrentPly == StartPly) {
document.getElementById("rightButton").title = "click > to show the puzzler's solution step by step on the chessboard";
} else {
document.getElementById("rightButton").title = solutionSoFar() + " ...click > to continue showing the puzzler's solution step by step on the chessboard";
}
}
}
</script>
<!-- DeploymentCheck: google analytics code -->
<!-- end DeploymentCheck -->
</head>
<body>
<!-- paste your PGN below and make sure you dont specify an external source with SetPgnUrl() -->
<form style="display: none;"><textarea style="display: none;" id="pgnText">
$pgnGame
</textarea></form>
<!-- paste your PGN above and make sure you dont specify an external source with SetPgnUrl() -->
<center>
<div class="container">
<div id="GameBoard"></div>
<table class="buttonTable" border="0" cellspacing="0" cellpadding="0">
<tr>
<td id="leftButton" title="" class="buttonCell" onClick="javascript:GoToMove(CurrentPly - 1);" align="center" valign="middle">
<a id="leftButtonLink" class="buttonCellLink" href="javascript:void(0);" onfocus="blur();"></a>
</td>
<td id="rightButton" title="" class="buttonCell" onClick="javascript:GoToMove(CurrentPly + 1);" align="center" valign="middle">
<a id="rightButtonLink" class="buttonCellLink" href="javascript:void(0);" onfocus="blur();"></a>
</td>
</tr>
</table>
</div>
</center>
</body>
</html>
END;
?>