Introduction
Introduction Statistics Contact Development Disclaimer Help
valentine.sh - chess-puzzles - chess puzzle book generator
git clone git://git.codemadness.org/chess-puzzles
Log
Files
Refs
README
LICENSE
---
valentine.sh (8866B)
---
1 #!/bin/sh
2
3 fenbin="./fen"
4 db="lichess_db_puzzle.csv"
5 # default, green, grey
6 theme="love"
7 lang="nl" # en, nl
8 fenopts="-d" # dutch mode (for speak output)
9
10 # texts / localization.
11 # English
12 if [ "$lang" = "en" ]; then
13 text_solutions="Solutions"
14 text_solutionstxtlabel="Text listing of solutions"
15 text_puzzles="Attraction puzzles for valentine 💕"
16 text_puzzle="Puzzle"
17 text_puzzlerating="Puzzel rating"
18 text_point="point"
19 text_points="points"
20 text_whitetomove="white to move"
21 text_blacktomove="black to move"
22 text_title="${text_puzzles}"
23 text_header="${text_puzzles}!"
24 pgnmapping="KQRBN"
25 fi
26
27 # Dutch
28 if [ "$lang" = "nl" ]; then
29 text_solutions="Oplossingen"
30 text_solutionstxtlabel="Tekstbestand, lijst met oplossingen"
31 text_puzzles="Aantrekkingspuzzles voor valentijn 💕"
32 text_puzzle="Puzzel"
33 text_puzzlerating="Puzzel moeilijkheidsgraad"
34 text_point="punt"
35 text_points="punten"
36 text_whitetomove="wit aan zet"
37 text_blacktomove="zwart aan zet"
38 text_title="${text_puzzles}"
39 text_header="${text_puzzles}!"
40 # Dutch: (K)oning, (D)ame, (T)oren, (L)oper, (P)aard.
41 pgnmapping="KDTLP"
42 fi
43
44 if ! test -f "$db"; then
45 printf 'File "%s" not found, run `make db` to update it\n' "$db"…
46 exit 1
47 fi
48
49 index="puzzles/index.html"
50 indexvt="puzzles/index.vt"
51
52 # clean previous files.
53 rm -rf puzzles
54 mkdir -p puzzles/solutions
55
56 solutions="$(mktemp)"
57 seedfile="$(mktemp)"
58 seed=20240201 # must be a integer value
59 # seed for random sorting, makes it deterministic for the same system
60 # seed must be sufficiently long.
61 echo "${seed}_chess_puzzles" > "$seedfile"
62
63 # shuffle(file, amount)
64 shuffle() {
65 f="$1"
66 total="$2"
67 nlines="$(wc -l < "$f")"
68 nlines="$((nlines + 0))"
69 results="$(mktemp)"
70
71 # generate list of lines to use. Not perfectly random but good enough.
72 LC_ALL=C awk -v "seed=$seed" -v "nlines=$nlines" -v "total=$total" '
73 BEGIN {
74 srand(seed);
75 for (i = 0; i < total; i++)
76 sel[int(rand() * nlines)] = 1;
77 }
78 sel[NR] {
79 print $0;
80 }' "$f" > "$results"
81
82 # now we have less results we can use the slow sort -R.
83 sort -R --random-source "$seedfile" "$results"
84 rm -f "$results"
85 }
86
87 # solutions.txt header.
88 solutionstxt="puzzles/solutions.txt"
89 printf '%s\n\n' "${text_solutions}" >> "$solutionstxt"
90
91 cat > "$indexvt" <<!
92 ${text_header}
93
94 !
95
96 cat > "$index" <<!
97 <!DOCTYPE html>
98 <html dir="ltr" lang="${lang}">
99 <head>
100 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
101 <title>${text_title}</title>
102 <style type="text/css">
103 body {
104 font-family: sans-serif;
105 width: 775px;
106 margin: 0 auto;
107 padding: 0 10px;
108 background-color: pink;
109 color: #ff0000;
110 }
111 a {
112 color: #ff0000;
113 }
114 h2 a {
115 color: #ff0000;
116 text-decoration: none;
117 }
118 h2 a:hover:after {
119 content: " #";
120 }
121 .puzzle {
122 float: left;
123 margin-right: 25px;
124 }
125 footer {
126 clear: both;
127 }
128 details summary {
129 cursor: pointer; /* show hand */
130 }
131 </style>
132 </head>
133 <body>
134 <header>
135 <h1>${text_header}</h1>
136 </header>
137 <main>
138 !
139
140 # shuffle, some sort of order and point system based on rating of puzzle.
141 count=1
142
143 groupsdir="$(mktemp -d)"
144 test "$groupsdir" = "" && exit 1
145
146 grep 'attraction' "$db" > "$groupsdir/attraction.csv"
147 LC_ALL=C awk -F ',' 'int($4) < 1500 { print $0 }' "$groupsdir/attraction…
148 LC_ALL=C awk -F ',' 'int($4) >= 1500 && int($4) < 2000 { print $0 }' "$g…
149 LC_ALL=C awk -F ',' 'int($4) >= 2000 { print $0 }' "$groupsdir/attractio…
150 (
151 shuffle "$groupsdir/attraction_lt_1500.csv" 100 | sed 20q | LC_ALL=C awk…
152 shuffle "$groupsdir/attraction_lt_2000.csv" 100 | sed 15q | LC_ALL=C awk…
153 shuffle "$groupsdir/attraction_ge_2000.csv" 100 | sed 5q | LC_ALL=C awk …
154 rm -rf "$groupsdir"
155 ) | \
156 while read -r line; do
157 i="$count"
158 fen=$(printf '%s' "$line" | cut -f 2 -d ',')
159
160 tomove=$(printf '%s' "$line" | cut -f 2 -d ',' | cut -f 2 -d ' ')
161 allmoves="$(printf '%s' "$line" | cut -f 3 -d ',')"
162 firstmove=$(printf '%s' "$line" | cut -f 3 -d ',' | cut -f 1 -d …
163 rating=$(printf '%s' "$line" | cut -f 4 -d ',')
164 ratingdev=$(printf '%s' "$line" | cut -f 5 -d ',')
165 lichess=$(printf '%s' "$line" | cut -f 9 -d ',')
166
167 case "$tomove" in
168 "w") tomove="w";;
169 "b") tomove="b";;
170 *) tomove="w";; # default
171 esac
172
173 # first move is played so flip when white (not black).
174 flip=""
175 test "$tomove" = "w" && flip="-f"
176
177 # added field: points
178 points=$(printf '%s' "$line" | cut -f "11" -d ',')
179 if [ "$points" = "1" ]; then
180 points="$points ${text_point}"
181 else
182 points="$points ${text_points}"
183 fi
184
185 img="$i.svg"
186 txt="$i.txt"
187 vt="$i.vt"
188 destfen="puzzles/$i.fen"
189 destsvg="puzzles/$img"
190 desttxt="puzzles/$txt"
191 destvt="puzzles/$vt"
192
193 "$fenbin" $fenopts -m "$pgnmapping" -t "$theme" $flip -o svg "$f…
194 "$fenbin" $fenopts -m "$pgnmapping" -t "$theme" $flip -o ascii "…
195 "$fenbin" $fenopts -m "$pgnmapping" -t "$theme" $flip -o tty "$f…
196 "$fenbin" $fenopts -m "$pgnmapping" -t "$theme" $flip -o fen "$f…
197 pgn=$("$fenbin" $fenopts -l -m "$pgnmapping" -o pgn "$fen" "$fir…
198
199 printf '<div class="puzzle" id="puzzle-%s">\n' "$i" >> "$index"
200 printf '<h2><a href="#puzzle-%s">%s %s</a></h2>\n' "$i" "${text_…
201 test "$lichess" != "" && printf '<a href="%s">' "$lichess" >> "$…
202
203 title=""
204 test "$rating" != "" && title="${text_puzzlerating}: $rating"
205
206 printf '<img src="%s" alt="%s #%s" title="%s" width="360" height…
207 "$img" "${text_puzzle}" "$i" "$title" >> "$index"
208 test "$lichess" != "" && printf '</a>' >> "$index"
209 echo "" >> "$index"
210
211 movetext=""
212 # if there is a first move, inverse to move.
213 if test "$firstmove" != ""; then
214 case "$tomove" in
215 "w") movetext=", ${text_blacktomove}";;
216 "b") movetext=", ${text_whitetomove}";;
217 esac
218 else
219 case "$tomove" in
220 "w") movetext=", ${text_whitetomove}";;
221 "b") movetext=", ${text_blacktomove}";;
222 esac
223 fi
224
225 printf '<p><b>%s</b>%s</p>\n' "$points" "$movetext" >> "$index"
226 printf '%s%s\n' "$points" "$movetext" >> "$desttxt"
227 printf '\n%s%s\n' "$points" "$movetext" >> "$destvt"
228
229 # vt
230 printf 'Puzzle %s\n\n' "$i" >> "$indexvt"
231 cat "$destvt" >> "$indexvt"
232 printf '\n\n' >> "$indexvt"
233
234 # solutions per puzzle.
235 printf '<div class="puzzle-solution">\n' >> "$solutions"
236 printf '<h2><a href="#puzzle-%s">%s %s</a></h2>\n' "$i" "${text_…
237
238 m="${allmoves}"
239 movecount=0
240 # create a move list, removing one move each step, for generating
241 # the solution images.
242
243 # add initial puzzle aswell for context.
244 ptitlespeak="$("$fenbin" $fenopts -l -o speak "$fen" "$firstmove…
245 printf '<img src="%s" width="180" height="180" loading="lazy" al…
246 "${i}.svg" "$ptitlespeak" "$pgn, $ptitlespeak" >> "$solu…
247
248 # solution PGN
249 pgn_solution="$("$fenbin" $fenopts -m "$pgnmapping" -o pgn "$fen…
250
251 destsolpgn="puzzles/solutions/${i}.pgn"
252 printf '%s\n' "$pgn_solution" > "$destsolpgn"
253
254 # printf 'DEBUG: #%s: "%s" "%s"\n' "$i" "$fen" "$allmoves" >&2
255
256 while [ "$m" != "" ]; do
257 prevmoves="$m"
258
259 echo "$m"
260
261 m="${m% }"
262 m="${m%[^ ]*}"
263 m="${m% }"
264
265 test "$prevmoves" = "$m" && break # same, break also
266 done | sort | while read -r movelist; do
267 # first move is already shown, skip it.
268 if test "$movecount" = "0"; then
269 movecount=$((movecount + 1))
270 continue
271 fi
272
273 # process move list in sequence.
274 destsolsvg="puzzles/solutions/${i}_${movecount}.svg"
275 "$fenbin" $fenopts -m "$pgnmapping" -t "$theme" $flip -o…
276
277 # PGN of moves so far.
278 pgn="$("$fenbin" $fenopts $fenopts -l -m "$pgnmapping" -…
279 ptitlespeak="$("$fenbin" $fenopts -l -o speak "$fen" "$m…
280
281 printf '<img src="%s" width="180" height="180" loading="…
282 "solutions/${i}_${movecount}.svg" "$ptitlespeak"…
283
284 movecount=$((movecount + 1))
285 done
286
287 printf '<p><b>PGN:</b> %s</p>\n' "${pgn_solution}" >> "$solution…
288 printf '</div>\n' >> "$solutions"
289
290 printf '</div>\n' >> "$index"
291
292 # add PGN solution to solutions text file.
293 printf '%s. %s\n' "$i" "${pgn_solution}" >> "$solutionstxt"
294
295 count=$((count + 1))
296 done
297
298 # solutions / spoilers
299 printf '<footer><br/><br/><details>\n<summary>%s</summary>\n' "$text_sol…
300 printf '<p><a href="solutions.txt">%s</a></p>\n' "${text_solutionstxtlab…
301
302 # add solutions HTML to index page.
303 cat "$solutions" >> "$index"
304 echo "</details>\n<br/><br/></footer>\n" >> "$index"
305
306 # add solutions to vt index page.
307 printf '\n\n\n\n\n\n\n\n\n\n' >> "$indexvt"
308 printf '\n\n\n\n\n\n\n\n\n\n' >> "$indexvt"
309 printf '\n\n\n\n\n' >> "$indexvt"
310 cat "$solutionstxt" >> "$indexvt"
311
312 cat >> "$index" <<!
313 </main>
314 </body>
315 </html>
316 !
317
318 rm -f "$solutions" "$seedfile"
You are viewing proxied material from codemadness.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.