Skip to content

Instantly share code, notes, and snippets.

@YoOoster
Forked from gray/depuzzlefy.pl
Last active January 18, 2020 13:36
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save YoOoster/8ea3644bb24c531271188fa40c90879b to your computer and use it in GitHub Desktop.
Save YoOoster/8ea3644bb24c531271188fa40c90879b to your computer and use it in GitHub Desktop.
Solves sudoku and image jigsaw puzzles created by http://flash-gear.com/puzzle/ and https://www.jigidi.com/
use 5.012;
use strict;
use warnings;
use File::Temp qw(tempfile);
use IPC::System::Simple qw(capture system);
use LWP::UserAgent;
use URI::QueryParam;
use Win32::GUI;
use Data::Dumper;
use integer;
use constant false => 0;
use constant true => 1;
my $PicJigsaw = Win32::GUI::Bitmap->new("jigsaw.bmp");
my $PicSudoku = Win32::GUI::Bitmap->new("sudoku.bmp");
my @board;
my $solveCount = 0;
my $Window_Main;
my $Window_Jigsaw;
my $Window_Sudoku;
#########################################################
# Main Window #
#########################################################
sub Create_Window_Main {
my $W1 = Win32::GUI::Window->new(
-name => "WindowMain",
-title => "Depuzzlefy",
-size => [ 800, 475 ],
-pos => [ Win32::GUI::Width(Win32::GUI::GetDesktopWindow())/2-400, Win32::GUI::Height(Win32::GUI::GetDesktopWindow())/2-237.50 ],
-sizable => 0,
-hasmaximize => 0,
-maximizebox => 0,
-hasminimize => 0,
-minimizebox => 0,
);
$W1->AddButton(
-name => "ButtonMainJigsaw",
-text => "Jigsaw puzzles",
-align => "center",
-valign => "center",
-picture=> $PicJigsaw,
-pos => [ 25, 60 ],
-size => [ 350, 350],
);
$W1->AddButton(
-name => "ButtonMainSudoku",
-text => "Sudoku",
-align => "center",
-valign => "center",
-picture=> $PicSudoku,
-pos => [ 400, 60 ],
-size => [ 350, 350],
);
$W1->AddLabel(
-name => "LabelMainJigsaw",
-text => "Jigsaw Puzzles",
-pos => [175, 45],
-size => [350, 15],
);
$W1->AddLabel(
-name => "LabelMainSudoku",
-text => "Sudoku",
-pos => [550, 45],
-size => [350, 15],
);
return $W1;
}
sub WindowMain_Terminate {
return -1;
}
sub ButtonMainJigsaw_Click {
$Window_Main->Hide();
$Window_Jigsaw->DoModal();
}
sub ButtonMainSudoku_Click {
$Window_Main->Hide();
$Window_Sudoku->DoModal();
}
#########################################################
# Jigsaw Window #
#########################################################
sub Create_Window_Jigsaw {
my $W1 = Win32::GUI::Window->new(
-name => "WindowJigsaw",
-title => "Depuzzlefy - Jigsaw",
-size => [ 300, 150 ],
-pos => [ Win32::GUI::Width(Win32::GUI::GetDesktopWindow())/2-150, Win32::GUI::Height(Win32::GUI::GetDesktopWindow())/2-75 ],
-sizable=> 0,
-parent => $Window_Main,
-hasmaximize => 0,
-maximizebox => 0,
-hasminimize => 0,
-minimizebox => 0,
);
$W1->AddButton(
-name => "ButtonWJDepuzzlefy",
-text => "Depuzzlefy",
-pos => [ 20, 60 ],
-size => [ 250, 30],
);
$W1->AddLabel(
-name => "LabelWJUrl",
-text => "Insert URL",
-pos => [20, 20],
-size => [250, 20],
);
$W1->AddTextfield(
-name => "TextfieldWJUrl",
-pos => [20,40],
-size => [250, 20],
);
return $W1;
}
sub WindowJigsaw_Terminate {
$Window_Main->Show();
return -1;
}
sub ButtonWJDepuzzlefy_Click {
my $url = $Window_Jigsaw->TextfieldWJUrl->Text();
if ($url =~ m[flash-gear.com]gi) {
FlashGearRequest();
} elsif ($url =~ m[jigidi.com]gi) {
JigidiRequest();
} else {
$Window_Jigsaw->TextfieldWJUrl->SelectAll();
$Window_Jigsaw->TextfieldWJUrl->Clear();
print "Website isn't supported.'\n\n";
return;
}
}
#########################################################
# Sudoku Window #
#########################################################
sub Create_Window_Sudoku {
my $W1 = Win32::GUI::Window->new(
-name => "WindowSudoku",
-title => "Depuzzlefy - Sudoku",
-size => [ 315, 370 ],
-pos => [ Win32::GUI::Width(Win32::GUI::GetDesktopWindow())/2-157.5, Win32::GUI::Height(Win32::GUI::GetDesktopWindow())/2-185 ],
-sizable => 0,
-parent => $Window_Main,
-hasmaximize => 0,
-maximizebox => 0,
-hasminimize => 0,
-minimizebox => 0,
);
for (my $i = 0; $i < 9; $i++) {
for (my $j = 0; $j <9; $j++) {
my $tf = $W1->AddTextfield(
-name => "TextFieldSudoku$i$j",
-pos => [($j*30)+20, ($i*30)+30],
-size => [25,25],
-align => "center",
-number => 1,
);
$tf->MaxLength(1);
}
}
$W1->AddButton(
-name => "ButtonSudokuSolve",
-text => "Solve",
-pos => [ 120, 295 ],
-size => [ 85, 30 ],
);
return $W1;
}
sub WindowSudoku_Terminate {
$Window_Main->Show();
return -1;
}
sub ButtonSudokuSolve_Click {
undef @board;
$solveCount = 0;
for (my $i = 0; $i < 9; $i++) {
for (my $j = 0; $j < 9; $j++) {
my $method = "TextFieldSudoku$i$j";
if (($Window_Sudoku->$method->Text() + 0) != "") {
push @board, (($Window_Sudoku->$method->Text()) + 0);
} else {
push @board, 0;
}
}
}
SolveSudoku();
}
#########################################################
sub SolveSudoku {
printf "Trying to solve Sudoku. Count:%s\n", $solveCount++;
my $i;
foreach $i ( 0 .. 80 ) {
next if $board[$i];
my %t = map {
$_ / 9 == $i / 9 ||
$_ % 9 == $i % 9 ||
$_ / 27 == $i / 27 && $_ % 9 / 3 == $i % 9 / 3
? $board[$_] : 0,
1;
} 0 .. 80;
SolveSudoku( $board[$i] = $_ ) for grep !$t{$_}, 1 .. 9;
return $board[$i] = 0;
}
# $i = 0;
# foreach (@board) {
# print "-----+-----+-----\n" if !($i%27) && $i;
# print !($i%9) ? '': $i%3 ? ' ' : '|', $_;
# print "\n" unless ++$i%9;
# }
for (my $i = 0; $i < 9; $i++) {
for (my $j = 0; $j < 9; $j++) {
my $method = "TextFieldSudoku$i$j";
my $value = $board[($i * 9) + $j];
$Window_Sudoku->$method->SelectAll();
$Window_Sudoku->$method->Clear();
$Window_Sudoku->$method->Append("$value");
}
}
}
sub ClearHideJigsaw {
$Window_Jigsaw->TextfieldWJUrl->SelectAll();
$Window_Jigsaw->TextfieldWJUrl->Clear();
$Window_Jigsaw->Hide();
}
sub SetUserAgent {
my $ua = LWP::UserAgent->new();
$ua->agent('Mozilla/5.0 (Windows NT 6.1; WOW64; rv:24.0) Gecko/20100101 Firefox/24.0');
$ua->cookie_jar({});
$ua->protocols_allowed(['http','https']);
$ua->ssl_opts(verify_hostname => 0);
$ua->default_header('Accept-Encoding' => scalar HTTP::Message::decodable());
return $ua;
}
# TODO: Find a way to make use of the normal temp map. using c:/dpf but this map is getting deleted at the end. Might be troublesome if someone made a own map.
# Using c:/dpf because otherwise large puzzles were getting errors because of too long commandprompt commands.
# This may still happen on really large puzzles but I haven't encountered them yet.
sub FlashGearRequest {
my $url = $Window_Jigsaw->TextfieldWJUrl->Text();
ClearHideJigsaw();
print "Requesting URL data\n\n";
my $ua = SetUserAgent();
my $res = $ua->get($url);
if(!$res->is_success) {
printf "%s\n\n", $res->status_line;
$Window_Jigsaw->Show();
return;
}
my $content = $res->decoded_content // $res->content // die 'no content';
my @url = $content =~ m[<embed(?: [^>]*?)? src="([^"]+)"]gi;
if(!@url) {
print "No Flash file found. Please insert a correct URL\n\n";
$Window_Jigsaw->Show();
return;
}
print "Found Flash file\n\n";
print "Extracting pictures from the Flash file\n";
print "This may take a while depending on the size of the puzzle\n\n";
my $dir = "C:\\dpf";
my $img = '';
$url = $url[1];
my $uri = URI->new($url);
my ($h, $w, $id) = map $uri->query_param($_), qw(h w id);
next unless $h and $w and $id;
$uri->query_param(c => 'z');
my $swf = File::Temp->new(suffix => '.swf');
$res = $ua->get($uri, ':content_file' => $swf->filename);
my $out = capture swfextract => $swf;
my ($ids) = $out =~ /^\s*\[-j\] \d+ JPEGs: ID\(s\) (\d+,.*)/m;
my @ids = split(", ", $ids);
mkdir $dir, 0666;
foreach my $id (@ids) {
system swfextract => '-j', $id, '--outputformat', "$dir/%05d.%s", $swf;
}
# FIX: Other jpgs will crash it.
my @jpg = glob "$dir/*.jpg";
$out = capture identify => $jpg[0];
my ($x, $y) = $out =~ / JPEG (\d+)x(\d+)/;
next unless $x and $y and $x == $y;
$_ = int $_ / $x * 2 for $w, $h;
# The edges of each puzzle piece image need to be overlapped.
$_ = int $_ / 4 for $x, $y;
$img = "$id.jpg";
system montage => '-tile', "${w}x$h", '-geometry', "-$x-$y", @jpg, $img;
unlink @jpg;
system "cmd /c start $img";
print "Done\n\n";
$Window_Jigsaw->Show();
}
sub JigidiRequest {
my $url = $Window_Jigsaw->TextfieldWJUrl->Text();
ClearHideJigsaw();
my @id = $url =~ m[\?id=([^"]+)];
print "Requesting URL data\n\n";
my $ua = SetUserAgent();
my $res = $ua->get($url);
if(!$res->is_success) {
printf "%s\n\n", $res->status_line;
$Window_Jigsaw->Show();
return;
}
my $content = $res->decoded_content // $res->content // die 'no content\n';
my @token = $content =~ m[token:\"([^"]+)];
printf "%s\n\n", "Found token";
$res = $ua->get("https://www.jigidi.com/ajax/api/2/game_lookup.php?token=$token[0]");
if(!$res->is_success) {
printf "%s\n\n", $res->status_line;
$Window_Jigsaw->Show();
return;
}
$content = $res->decoded_content // $res->content // die 'no content\n';
my @pic = $content =~ m[image\":\"([^"]+)];
$pic[0] =~ s/[\\]//g ;
$pic[0] =~ s/.{5}$//;
print "Saving picture\n\n";
unlink "$id[0].jpg";
$res = $ua->mirror($pic[0], "$id[0].jpg");
unless($res->is_success) {
printf "%s\n\n", $res->status_line;
$Window_Jigsaw->Show();
return;
}
system "cmd /c start $id[0].jpg";
print "Done\n\n";
$Window_Jigsaw->Show();
}
$Window_Main = Create_Window_Main();
$Window_Jigsaw = Create_Window_Jigsaw();
$Window_Sudoku = Create_Window_Sudoku();
$Window_Main->Show();
Win32::GUI::Dialog();
@YoOoster
Copy link
Author

YoOoster commented May 9, 2017

This script only works on Windows
I edited this script to add a User Interface, so people don't need to keep changing the script manually.

Supported websites:
http://flash-gear.com/puzzle/
https://www.jigidi.com/
Write a comment here if you want to add a website.

Using installer:

I made a installer for this script
(Last updated December 10, 2017)

For this to work, you need to install the following:

  1. Imagemagick
  2. You might need Visual C++ 2013 Redistributable Package for ImageMagick to work properly.

That's all :)

FAQ:

Q: I get a "montage" unexpectedly returned exit value 1 error
A: You need to run the program as administator. You can do this by:

  • Navigate to the program folder. For example: C:\Program Files (x86)\Depuzzlefy\bin
  • Right-click the program icon (the depuzzlefy.exe file).
  • Choose Properties.
  • On the Compatibility tab, select the Run This Program As An Administrator option.
  • Click OK.
  • If you see a User Account Control prompt, accept it.

Q: I get a the system cannot find the file error
A: You need to run the program as administator. You can do this by:

  • Navigate to the program folder. For example: C:\Program Files (x86)\Depuzzlefy\bin
  • Right-click the program icon (the depuzzlefy.exe file).
  • Choose Properties.
  • On the Compatibility tab, select the Run This Program As An Administrator option.
  • Click OK.
  • If you see a User Account Control prompt, accept it.

Q: I get a "identify" failed to start error
A: You have installed a newer version ImageMagick which no longer has the identify tool.
Uninstall ImageMagick and use the link above

Manual way:

For this script to work, you need to install the following:

  1. Imagemagick
  2. Swftools
  3. Perl
  4. You might need Visual C++ 2013 Redistributable Package for ImageMagick to work properly.

After you have installed all these things you need to add Swftools to your PATH.
You do this by opening your system settings. You can do it ONE of the following ways:

  • If you have Windows 8 or 10, you can right click on your start button and select System. OR
  • Right click on Computer and select properties. OR
  • Press your windows key + Pause/Break.

You then open Advanced system settings on the left.
Then you click on Enviroment Variables on the bottom of the screen.
You will see atleast 2 or more variables (depends which Windows version) on the top part of the screen.
The two important ones are TEMP and TMP.

Select TEMP
On the bottom of your screen select Path. Press Edit.
You either get one of the following screens depending on your Windows version:

  1. A small screen with two textboxes:
    Make sure you don't delete anything here. It will f*ck up your Windows
    Add ;C:\Program Files (x86)\SWFTools; to the end of the value textbox.

  2. A big screen with a list and multiple buttons at the right side:
    Press the New button and fill in C:\Program Files (x86)\SWFTools

Press OK

Do the same thing with TMP

@pejekaa
Copy link

pejekaa commented Dec 9, 2017

Including the completion message would be very, very nice for me too!
Is there a possibility?

@YoOoster
Copy link
Author

Updated the program. Link

  • It now gets the high definition picture of jigidi puzzles.
  • I'm still figuring out how to get the completion message
  • I added a sudoku solver. Some sudoku might not be solvable by it.

@paneteworld
Copy link

paneteworld commented Dec 11, 2017

I'll wait if there is a chance to get the completion message in jigidi too. Thank you!

@Rhoenbussard
Copy link

I tried to use depuzzlefy, but after a first correct picture, I get a message that the picture isn't found. The next message is
depuzzlefy_2
There are two pictures in the bin folder "C:\Program Files (x86)\Depuzzlefy\bin\4067529-0.jpg" and "C:\Program Files (x86)\Depuzzlefy\bin\4067529-1.jpg"
Please help me

@Rhoenbussard
Copy link

I tried the new version, but there is no difference. My pictures look like this
4169225-0
4169225-1

What can I do?

@kaischmitt
Copy link

I have the same problems as Rhoenbussard.
The puzzles always split in two files xxxx-0 and xxxx-1.
Followed by the error code that it can#T find the file withe the name xxxx.

Thanks for your help!
Kai

@YoOoster
Copy link
Author

@kaischmitt
Which puzzle?

@schettina
Copy link

@lingkau
Copy link

lingkau commented Jul 9, 2018

I have the same problem with this URL: http://six.flash-gear.com/npuz/puz.php?c=v&id=3544876&k=77212470.
I've installed the latest version on the latest version of Windows10. Maybe that helps a little.

@Skiet
Copy link

Skiet commented Aug 31, 2018

I had it working in the past, i tried it on a certain puzzle on flash-gear.com wich i tried to solve again today, but as the others above, i get two files and the same kind of pictures
4163607-0
4163607-1

@PepePellini
Copy link

PepePellini commented Jan 1, 2019

Super Tool! I am also interested in a completion message. Is there any posibility?

@rickrich
Copy link

Super Tool! I am also interested in a completion message. Is there any posibility?

Ditto!

@pinkunicorn
Copy link

Apart from the completion message which many people have already asked for, I'd very much like a non-windows option.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment