293 lines
12 KiB
Bash
293 lines
12 KiB
Bash
|
#!/bin/bash
|
||
|
|
||
|
## Title: CodeWord Maker 1.00
|
||
|
## Author: Ze'ev Schurmann
|
||
|
## License: This project is licensed under the GNU General Public License v3.0 only.
|
||
|
## License: URL
|
||
|
## Git: https://git.zaks.web.za/thisiszeev/ipuz-to-pdf
|
||
|
## https://github.com/thisiszeev/ipuz-to-pdf
|
||
|
|
||
|
## What is this script?
|
||
|
## This script will convert a ipuz crossword file into set of PDF files.
|
||
|
|
||
|
## Why did I make this script?
|
||
|
## I needed to create vector file of various ipuz files as per the defined ipuz standard.
|
||
|
## These vector files are for use in print publications. So I need a script, that can be
|
||
|
## run in batch jobs. Thus the script can be executed as:
|
||
|
## $ bash codeword-maker.sh {filename}.ipuz
|
||
|
|
||
|
## Where can I get software to create ipuz files?
|
||
|
## Crosswords: https://gitlab.gnome.org/jrb/crosswords
|
||
|
## Sudokus: https://invent.kde.org/games/ksudoku
|
||
|
|
||
|
## Where I can learn more about the ipuz format?
|
||
|
## ipuz is essentially a JSON format designed for storing puzzles.
|
||
|
## Website: https://libipuz.org/ipuz-spec.html
|
||
|
|
||
|
## What must I do first?
|
||
|
## First you need to install FontConfig, Inkscape, JQ and the Ubuntu Font Family or this
|
||
|
## script will not run.
|
||
|
## FontConfig: https://www.baeldung.com/linux/find-installed-fonts-command-line
|
||
|
## Inkscape: https://inkscape.org/
|
||
|
## JQ: https://jqlang.github.io/jq/
|
||
|
## Ubuntu Font Family: https://design.ubuntu.com/font
|
||
|
|
||
|
## Donations & Support:
|
||
|
## Left for last, as usual. If you want support, you can hit me up on Reddit u/thisiszeev.
|
||
|
## I will try help out when I get time. But donations are a major source of my income, as
|
||
|
## I need to eat.
|
||
|
|
||
|
## Paypal: https://paypal.me/thisiszeev
|
||
|
## $5 buys me a coffee
|
||
|
## $10 buys me a a nice burger
|
||
|
## $20 buys me a bottle of wine
|
||
|
|
||
|
## If you plan to use this script for commercial use, you are free to do so, but please
|
||
|
## remember I put a lot of work and effort into these scripts. I kindly urge you to
|
||
|
## please make a donation of at least $50. You will then get priority support for a
|
||
|
## period of 12 months.
|
||
|
|
||
|
## SVGHEADER ARRAY
|
||
|
svgheader=("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<!-- Created with Crossword Maker - Copyright 2024 GypsyWolf Trading (https://gwpuzzles.co.za) -->\n\n<svg\n width=\"" "mm\"\n height=\"" "mm\"\n viewBox=\"0 0 " "\"\n version=\"1.1\"\n id=\"crossword\"\n xmlns=\"http://www.w3.org/2000/svg\"\n xmlns:svg=\"http://www.w3.org/2000/svg\">")
|
||
|
|
||
|
## SVGFOOTER
|
||
|
svgfooter="</svg>"
|
||
|
|
||
|
## SVGCELL ARRAY AND START POSITION
|
||
|
svgcell=(" <rect\n style=\"fill:" ";stroke:#000000;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1\"\n width=\"20\"\n height=\"20\"\n x=\"" "\"\n y=\"" "\"\n id=\"cell" "\" />")
|
||
|
svgcellx="20"
|
||
|
svgcelly="20"
|
||
|
|
||
|
## SVGVAL ARRAY AND START POSITION
|
||
|
svgval=(" <text\n style=\"font-weight:bold;font-size:15.4799px;font-family:'Ubuntu Mono';-inkscape-font-specification:'Ubuntu Mono Bold';text-align:center;text-anchor:middle;fill:#000000;stroke:none\"\n x=\"" "\"\n y=\"" "\"\n id=\"val" "\">" "</text>")
|
||
|
svgvalx="30"
|
||
|
svgvaly="35"
|
||
|
|
||
|
## SVGNUM ARRAY AND START POSITION
|
||
|
svgnum=(" <text\n style=\"font-weight:bold;font-size:5.52401px;font-family:'Ubuntu Condensed';text-align:left;fill:#000000;stroke:none\"\n x=\"" "\"\n y=\"" "\"\n id=\"num" "\">" "</text>")
|
||
|
svgnumx="21"
|
||
|
svgnumxdec=".25"
|
||
|
svgnumy="25"
|
||
|
svgnumydec=".5"
|
||
|
|
||
|
## COLOUR PALETTE FOR FILLING CELLS
|
||
|
colblack="#000000"
|
||
|
colwhite="#FFFFFF"
|
||
|
|
||
|
## OFFSETS
|
||
|
offsetx="20"
|
||
|
offsety="20"
|
||
|
|
||
|
errorcode=""
|
||
|
|
||
|
temp=($(whereis inkscape))
|
||
|
|
||
|
if [[ $? != 0 ]]; then
|
||
|
echo "Unexpected Error: whereis not found?"
|
||
|
exit 3
|
||
|
fi
|
||
|
|
||
|
if [[ ${#temp[@]} == 1 ]]; then
|
||
|
echo "Please install Inscape : https://inkscape.org/"
|
||
|
errorcode="${errorcode}I"
|
||
|
fi
|
||
|
|
||
|
temp=($(whereis jq))
|
||
|
|
||
|
if [[ ${#temp[@]} == 1 ]]; then
|
||
|
echo "Please install JQ : https://jqlang.github.io/jq/"
|
||
|
errorcode="${errorcode}J"
|
||
|
fi
|
||
|
|
||
|
temp=($(whereis fc-match))
|
||
|
|
||
|
if [[ ${#temp[@]} == 1 ]]; then
|
||
|
echo "Please install FontConfig : https://www.baeldung.com/linux/find-installed-fonts-command-line"
|
||
|
errorcode="${errorcode}F"
|
||
|
else
|
||
|
temp2=$(fc-match "Ubuntu Mono")
|
||
|
if [[ $temp2 != 'UbuntuMono-R.ttf: "Ubuntu Mono" "Regular"' ]]; then
|
||
|
echo "Please install Ubuntu Font Family : https://design.ubuntu.com/font"
|
||
|
errorcode="${errorcode}U"
|
||
|
fi
|
||
|
fi
|
||
|
|
||
|
if [[ ! -z $errorcode ]] || [[ $errorcode != "" ]]; then
|
||
|
exit 2
|
||
|
fi
|
||
|
|
||
|
if [[ -z $1 ]] || [[ $1 == "" ]]; then
|
||
|
echo "Usage:"
|
||
|
echo " $ bash codeword-maker.sh {puzzlefile}.ipuz"
|
||
|
exit 1
|
||
|
fi
|
||
|
|
||
|
puzzlename="$1"
|
||
|
|
||
|
width=$(jq -r ".dimensions.width" "$puzzlename")
|
||
|
height=$(jq -r ".dimensions.height" "$puzzlename")
|
||
|
block=$(jq -r ".block" "$puzzlename")
|
||
|
empty=$(jq -r ".empty" "$puzzlename")
|
||
|
|
||
|
echo "Puzzle is $width by $height in size!"
|
||
|
|
||
|
declare -A gridarray
|
||
|
declare -A valuearray
|
||
|
|
||
|
echo "Loading Grid..."
|
||
|
|
||
|
for ((y=0; y<$height; y++)); do
|
||
|
for ((x=0; x<$width; x++)); do
|
||
|
#gridarray[$x,$y]=$(jq -r ".puzzle[$y][$x]" "$puzzlename")
|
||
|
valuearray[$x,$y]=$(jq -r ".solution[$y][$x]" "$puzzlename")
|
||
|
#echo "$x, $y = ${gridarray[$x,$y]} = ${valuearray[$x,$y]}"
|
||
|
done
|
||
|
done
|
||
|
|
||
|
echo "Puzzle Data:"
|
||
|
|
||
|
for ((y=0; y<$height; y++)); do
|
||
|
for ((x=0; x<$width; x++)); do
|
||
|
if [[ ${valuearray[$x,$y]} == "null" ]]; then
|
||
|
echo -n " "
|
||
|
else
|
||
|
echo -n " ${valuearray[$x,$y]}"
|
||
|
fi
|
||
|
done
|
||
|
echo
|
||
|
done
|
||
|
|
||
|
echo "Converting letters to numbers..."
|
||
|
|
||
|
string=""
|
||
|
|
||
|
for ((y=0; y<$height; y++)); do
|
||
|
for ((x=0; x<$width; x++)); do
|
||
|
if [[ ${valuearray[$x,$y]} != "null" ]]; then
|
||
|
test=$(echo "$string" | grep ${valuearray[$x,$y]})
|
||
|
if [[ -z $test ]] || [[ $test == "" ]]; then
|
||
|
string=$string${valuearray[$x,$y]}
|
||
|
fi
|
||
|
gridarray[$x,$y]=$(expr index "$string" ${valuearray[$x,$y]})
|
||
|
else
|
||
|
gridarray[$x,$y]=$block
|
||
|
fi
|
||
|
done
|
||
|
done
|
||
|
|
||
|
ongrid=${#string}
|
||
|
|
||
|
echo "$ongrid - $string"
|
||
|
|
||
|
randnum[0]=$(((RANDOM%$ongrid)+1))
|
||
|
randnum[1]=${randnum[0]}
|
||
|
while [[ ${randnum[0]} == ${randnum[1]} ]]; do
|
||
|
randnum[1]=$(((RANDOM%$ongrid)+1))
|
||
|
done
|
||
|
randnum[2]=${randnum[0]}
|
||
|
while [[ ${randnum[0]} == ${randnum[2]} ]] || [[ ${randnum[1]} == ${randnum[2]} ]]; do
|
||
|
randnum[2]=$(((RANDOM%$ongrid)+1))
|
||
|
done
|
||
|
|
||
|
for ((c=0; c<3; c++)); do
|
||
|
echo "${randnum[$c]} - ${string:$((randnum[$c]-1)):1}"
|
||
|
done
|
||
|
|
||
|
echo "Building SVG Files..."
|
||
|
|
||
|
pagex=$((width * offsetx + offsetx + offsetx))
|
||
|
pagey=$((height * offsety + offsety + offsety))
|
||
|
|
||
|
outputfile="CodeWord-${puzzlename%.*}"
|
||
|
|
||
|
echo -e "${svgheader[0]}$pagex${svgheader[1]}$pagey${svgheader[2]}$pagex $pagey${svgheader[3]}" > "$outputfile.puzzle.svg"
|
||
|
echo -e "${svgheader[0]}$pagex${svgheader[1]}$pagey${svgheader[2]}$pagex $pagey${svgheader[3]}" > "$outputfile.solution.svg"
|
||
|
echo -e "${svgheader[0]}300${svgheader[1]}80${svgheader[2]}300 80${svgheader[3]}" > "$outputfile.legendbottom.svg"
|
||
|
echo -e "${svgheader[0]}80${svgheader[1]}300${svgheader[2]}80 300${svgheader[3]}" > "$outputfile.legendside.svg"
|
||
|
|
||
|
for ((n=0; n<13; n++)); do
|
||
|
if [[ $n -lt $ongrid ]]; then
|
||
|
echo -e "${svgcell[0]}$colwhite${svgcell[1]}$((n*20+svgcellx))${svgcell[2]}$((svgcelly))${svgcell[3]}leg$((n+1))${svgcell[4]}" >> "$outputfile.legendbottom.svg"
|
||
|
echo -e "${svgcell[0]}$colwhite${svgcell[1]}$((svgcellx))${svgcell[2]}$((n*20+svgcelly))${svgcell[3]}leg$((n+1))${svgcell[4]}" >> "$outputfile.legendside.svg"
|
||
|
echo -e "${svgnum[0]}$((n*20+svgnumx))$svgnumxdec${svgnum[1]}$((svgnumy))$svgnumydec${svgnum[2]}leg$((n+1))${svgnum[3]}$((n+1))${svgnum[4]}" >> "$outputfile.legendbottom.svg"
|
||
|
echo -e "${svgnum[0]}$((svgnumx))$svgnumxdec${svgnum[1]}$((n*20+svgnumy))$svgnumydec${svgnum[2]}leg$((n+1))${svgnum[3]}$((n+1))${svgnum[4]}" >> "$outputfile.legendside.svg"
|
||
|
for ((c=0; c<3; c++)); do
|
||
|
if [[ $((n+1)) == ${randnum[$c]} ]]; then
|
||
|
echo -e "${svgval[0]}$((n*20+svgvalx))${svgval[1]}$((svgvaly))${svgval[2]}leg$((n+1))${svgval[3]}${string:$n:1}${svgval[4]}" >> "$outputfile.legendbottom.svg"
|
||
|
echo -e "${svgval[0]}$((svgvalx))${svgval[1]}$((n*20+svgvaly))${svgval[2]}leg$((n+1))${svgval[3]}${string:$n:1}${svgval[4]}" >> "$outputfile.legendside.svg"
|
||
|
fi
|
||
|
done
|
||
|
else
|
||
|
echo -e "${svgcell[0]}$colblack${svgcell[1]}$((n*20+svgcellx))${svgcell[2]}$((svgcelly))${svgcell[3]}leg$((n+1))${svgcell[4]}" >> "$outputfile.legendbottom.svg"
|
||
|
echo -e "${svgcell[0]}$colblack${svgcell[1]}$((svgcellx))${svgcell[2]}$((n*20+svgcelly))${svgcell[3]}leg$((n+1))${svgcell[4]}" >> "$outputfile.legendside.svg"
|
||
|
fi
|
||
|
done
|
||
|
|
||
|
for ((n=0; n<13; n++)); do
|
||
|
if [[ $((n+13)) -lt $ongrid ]]; then
|
||
|
echo -e "${svgcell[0]}$colwhite${svgcell[1]}$((n*20+svgcellx))${svgcell[2]}$((20+svgcelly))${svgcell[3]}leg$((n+14))${svgcell[4]}" >> "$outputfile.legendbottom.svg"
|
||
|
echo -e "${svgcell[0]}$colwhite${svgcell[1]}$((20+svgcellx))${svgcell[2]}$((n*20+svgcelly))${svgcell[3]}leg$((n+14))${svgcell[4]}" >> "$outputfile.legendside.svg"
|
||
|
echo -e "${svgnum[0]}$((n*20+svgnumx))$svgnumxdec${svgnum[1]}$((20+svgnumy))$svgnumydec${svgnum[2]}leg$((n+14))${svgnum[3]}$((n+14))${svgnum[4]}" >> "$outputfile.legendbottom.svg"
|
||
|
echo -e "${svgnum[0]}$((20+svgnumx))$svgnumxdec${svgnum[1]}$((n*20+svgnumy))$svgnumydec${svgnum[2]}leg$((n+14))${svgnum[3]}$((n+14))${svgnum[4]}" >> "$outputfile.legendside.svg"
|
||
|
for ((c=0; c<3; c++)); do
|
||
|
if [[ $((n+14)) == ${randnum[$c]} ]]; then
|
||
|
echo -e "${svgval[0]}$((n*20+svgvalx))${svgval[1]}$((20+svgvaly))${svgval[2]}leg$((n+14))${svgval[3]}${string:$((n+13)):1}${svgval[4]}" >> "$outputfile.legendbottom.svg"
|
||
|
echo -e "${svgval[0]}$((20+svgvalx))${svgval[1]}$((n*20+svgvaly))${svgval[2]}leg$((n+14))${svgval[3]}${string:$((n+13)):1}${svgval[4]}" >> "$outputfile.legendside.svg"
|
||
|
fi
|
||
|
done
|
||
|
else
|
||
|
echo -e "${svgcell[0]}$colblack${svgcell[1]}$((n*20+svgcellx))${svgcell[2]}$((20+svgcelly))${svgcell[3]}leg$((n+14))${svgcell[4]}" >> "$outputfile.legendbottom.svg"
|
||
|
echo -e "${svgcell[0]}$colblack${svgcell[1]}$((20+svgcellx))${svgcell[2]}$((n*20+svgcelly))${svgcell[3]}leg$((n+14))${svgcell[4]}" >> "$outputfile.legendside.svg"
|
||
|
fi
|
||
|
done
|
||
|
|
||
|
for ((y=0; y<$height; y++)); do
|
||
|
if [[ $y -lt 10 ]]; then
|
||
|
idy="0$y"
|
||
|
else
|
||
|
idy="$y"
|
||
|
fi
|
||
|
for ((x=0; x<$width; x++)); do
|
||
|
if [[ $x -lt 10 ]]; then
|
||
|
idx="0$x"
|
||
|
else
|
||
|
idx="$x"
|
||
|
fi
|
||
|
if [[ ${gridarray[$x,$y]} == $block ]]; then
|
||
|
echo -e "${svgcell[0]}$colblack${svgcell[1]}$((x*20+svgcellx))${svgcell[2]}$((y*20+svgcelly))${svgcell[3]}$idx$idy${svgcell[4]}" >> "$outputfile.puzzle.svg"
|
||
|
echo -e "${svgcell[0]}$colblack${svgcell[1]}$((x*20+svgcellx))${svgcell[2]}$((y*20+svgcelly))${svgcell[3]}$idx$idy${svgcell[4]}" >> "$outputfile.solution.svg"
|
||
|
else
|
||
|
echo -e "${svgcell[0]}$colwhite${svgcell[1]}$((x*20+svgcellx))${svgcell[2]}$((y*20+svgcelly))${svgcell[3]}$idx$idy${svgcell[4]}" >> "$outputfile.puzzle.svg"
|
||
|
echo -e "${svgcell[0]}$colwhite${svgcell[1]}$((x*20+svgcellx))${svgcell[2]}$((y*20+svgcelly))${svgcell[3]}$idx$idy${svgcell[4]}" >> "$outputfile.solution.svg"
|
||
|
if [[ ${gridarray[$x,$y]} != $block ]] && [[ ${gridarray[$x,$y]} != $empty ]]; then
|
||
|
echo -e "${svgnum[0]}$((x*20+svgnumx))$svgnumxdec${svgnum[1]}$((y*20+svgnumy))$svgnumydec${svgnum[2]}$idx$idy${svgnum[3]}${gridarray[$x,$y]}${svgnum[4]}" >> "$outputfile.puzzle.svg"
|
||
|
echo -e "${svgnum[0]}$((x*20+svgnumx))$svgnumxdec${svgnum[1]}$((y*20+svgnumy))$svgnumydec${svgnum[2]}$idx$idy${svgnum[3]}${gridarray[$x,$y]}${svgnum[4]}" >> "$outputfile.solution.svg"
|
||
|
fi
|
||
|
for ((c=0; c<3; c++)); do
|
||
|
if [[ ${gridarray[$x,$y]} == ${randnum[$c]} ]]; then
|
||
|
echo -e "${svgval[0]}$((x*20+svgvalx))${svgval[1]}$((y*20+svgvaly))${svgval[2]}$idx$idy${svgval[3]}${valuearray[$x,$y]}${svgval[4]}" >> "$outputfile.puzzle.svg"
|
||
|
fi
|
||
|
done
|
||
|
echo -e "${svgval[0]}$((x*20+svgvalx))${svgval[1]}$((y*20+svgvaly))${svgval[2]}$idx$idy${svgval[3]}${valuearray[$x,$y]}${svgval[4]}" >> "$outputfile.solution.svg"
|
||
|
fi
|
||
|
done
|
||
|
done
|
||
|
|
||
|
echo -e "$svgfooter" >> "$outputfile.puzzle.svg"
|
||
|
echo -e "$svgfooter" >> "$outputfile.solution.svg"
|
||
|
echo -e "$svgfooter" >> "$outputfile.legendbottom.svg"
|
||
|
echo -e "$svgfooter" >> "$outputfile.legendside.svg"
|
||
|
|
||
|
echo "Converting SVG files to PDF files..."
|
||
|
|
||
|
inkscape "$outputfile.puzzle.svg" --export-filename="$outputfile.puzzle.pdf" --export-area-drawing --export-type=pdf --export-text-to-path
|
||
|
inkscape "$outputfile.solution.svg" --export-filename="$outputfile.solution.pdf" --export-area-drawing --export-type=pdf --export-text-to-path
|
||
|
inkscape "$outputfile.legendbottom.svg" --export-filename="$outputfile.legendbottom.pdf" --export-area-drawing --export-type=pdf --export-text-to-path
|
||
|
inkscape "$outputfile.legendside.svg" --export-filename="$outputfile.legendside.pdf" --export-area-drawing --export-type=pdf --export-text-to-path
|
||
|
|
||
|
echo "Cleaning up..."
|
||
|
|
||
|
rm "$outputfile.puzzle.svg" "$outputfile.solution.svg" "$outputfile.legendbottom.svg" "$outputfile.legendside.svg"
|
||
|
|
||
|
echo "DONE!!!"
|