#!/usr/bin/perl
#
# This file is part of sudognu.
#
# Copyright (C) 2007 Todd Lyons, California, USA.
# Copyright (C) 2007 Jens Baaran, Germany.
#
# For questions about this program please contact tlyons@ivenue.com
#
# THERE IS NO WARRANTY FOR THIS PROGRAM, TO THE EXTENT PERMITTED
# BY APPLICABLE LAW.
#
# See the GPL Version 2 (http://www.gnu.org/licenses/gpl.html)
# or the file COPYING for details
# ******************************************************************************
use strict;
use warnings;
use CGI;
$|=1;
# --Variables-- you may need to edit these.
my $BASEDIR='/var/www/vhosts/www.mrball.net';
my $TMPDIR='/sudognu';
my $CGIPATH="/cgi-bin";
my $BINSUDOKU='/usr/local/bin/sudognu';
# --End Variables-- do not edit past this line.
chdir "$BASEDIR$TMPDIR";
system "rm -f `find $BASEDIR$TMPDIR -type f -mmin +60` ";
my $fn=`date +%H%M%S`;
chomp $fn;
my $WCGI = CGI::url(-absolute=>1);
my $count = 0;
my ($parameters,$command,@OUTPUT);
sub printContentType {
print "Content-type: text/html\n\n";
}
sub printHeader {
my $title = shift();
printContentType();
print <<END;
<html>
<head>
<title>$title</title>
<style type="text/css">
body { background-color:white; color:black; }
td { text-align:left; padding:2px 1ex 2px 1ex; }
table { text-align:center; }
a { text-decoration:underline; color:#00E; cursor:pointer; }
.ctr { text-align:center; }
.lft { text-align:left; }
.shortsolution {
display: none;
padding-left: 2em;
}
.clickme a:hover {
cursor: pointer;
}
</style>
<script language="javascript" type="text/javascript">
var state = 'none';
function showhide(layer_ref) {
if (state == 'block') {
state = 'none';
}
else {
state = 'block';
}
if (document.all) { //IS IE 4 or 5 (or 6 beta)
eval( "document.all." + layer_ref + ".style.display = state");
}
if (document.layers) { //IS NETSCAPE 4 or below
document.layers[layer_ref].display = state;
}
if (document.getElementById &&!document.all) {
hza = document.getElementById(layer_ref);
hza.style.display = state;
}
}
function newWindow(url,name) {
window.open(url,name);
}
</script>
</head>
<body>
END
}
sub printLegend {
print <<' END';
<pre>Click <a class='clickme' onclick=showhide('legend')>Here</a> for a Legend
<div id='legend' style='display:none'> . hidden single
- single
d hidden double
D double
b line-block interaction
B block-line interaction
t hidden triple
T triple
q quadruple
Q hidden quadruple
X X-wing
S swordfish
J jellyfish
F forcing chain to a common value with length of forcing chain
f forcing chain to a contradiction for one of the branches
e forcing chain to the end of the sudoku
g guess during backtracking process
w last guess turned out to be wrong.
The default order for applying the solution steps is to start with hid-
den singles and singles before trying to eliminate candidates with hid-
den tuples and tuples from doubles to quadruples. Line-block interac-
tions are applied between doubles and triples. Then the more complex
techniques X-wing, swordfish and jellyfish are used and if all these
fail, forcing chains are tried, before reverting to guessing and start-
ing a backtracking process.
END
}
sub printFooter {
print "</body></html>";
}
# Main loop
foreach ( CGI::param() ) {
$parameters->{$_} = CGI::param($_);
}
if ( $parameters->{'showsolution'} &&
$parameters->{'showsolution'} =~ /\d{81}/ ) {
printHeader("Sudoku Solution");
$command = "echo " . $parameters->{'showsolution'} .
" | $BINSUDOKU -s -v 11 -f $WCGI 2>&1";
} elsif ( $parameters->{'sudoku'} &&
$parameters->{'sudoku'} =~ /\d{81}/ ) {
printContentType();
$fn .= '.html';
$command = "echo " . $parameters->{'sudoku'} .
" | $BINSUDOKU -w -f $WCGI -o $fn &>/dev/null";
} else {
printHeader("Creating Sudokus ...");
$fn .= '.pdf';
$command = "$BINSUDOKU -c -o $fn 2>&1";
}
open SUDOKU, "-|", "$command";
print "<pre>\n";
push (@OUTPUT,"<pre>\n");
while (<SUDOKU>) {
my $line = $_;
if ( $parameters->{'showsolution'} ) {
print $line;
} elsif ( $parameters->{'sudoku'} ) {
# Never gets here
} else {
# Print creation status in real time.
print "$line" if $line =~ /Creating/;
# Save output and generated URLs for later.
if ( $line =~ /^(\d{81})\s+(\S+)\s+(\d{81})\s+(\d+)\s+(\d+)/ ) {
$count eq 0 && push (@OUTPUT, "Solutions for:\n");
$count++;
push (@OUTPUT, "<a href='javascript:newWindow(\"$WCGI?showsolution=$1\",\"sudoku\");'>Puzzle $count</a> - <a class='clickme' $5</a>\n");
push (@OUTPUT, "<div class='shortsolution' id='solution${count}'>Short Solution: $2</div>");
}
}
}
push (@OUTPUT, "</pre>\n");
print "</pre>";
close SUDOKU;
if ( $parameters->{'sudoku'} ) {
open TMPFILE, "<", "$fn";
while (<TMPFILE>) {
# Just setting a little bit nicer title
if ( $_ =~ /<title>/ ) {
s/sudoku/Sudoku Individual Step/;
}
print $_;
}
close TMPFILE;
}
if ( ! ( $parameters->{'showsolution'} || $parameters->{'sudoku'} ) ) {
# Print links to original puzzles first.
if ( -f "$BASEDIR$TMPDIR/$fn" ) {
print "<a href='$TMPDIR/$fn'>pdf</a> ";
}
print "<a href='javascript:newWindow(\"$TMPDIR/$fn.svg\",\"svg\");'>svg</a>";
# Then print links to solutions for puzzles.
foreach my $line (@OUTPUT) {
print $line;
}
printLegend();
}
printFooter();