Skip to content

Instantly share code, notes, and snippets.

@catchouli
Last active October 26, 2024 21:49
Show Gist options
  • Save catchouli/a4451952f9af569904a0a89f97f604bb to your computer and use it in GitHub Desktop.
Save catchouli/a4451952f9af569904a0a89f97f604bb to your computer and use it in GitHub Desktop.
Anki chessground card with pgn seeking
{{FrontSide}}
<hr id=answer>
<div id="controls">placeholder text</div>
<script type="module">
import {
init,
classModule,
propsModule,
styleModule,
eventListenersModule,
h,
} from 'https://cdn.jsdelivr.net/npm/[email protected]/+esm';
import { Chess } from 'https://cdn.jsdelivr.net/npm/[email protected]/+esm';
const patch = init([
// Init patch function with chosen modules
classModule, // makes it easy to toggle classes
propsModule, // for setting properties on DOM elements
styleModule, // handles styling on elements with support for animations
eventListenersModule, // attaches event listeners
]);
function pgn_to_moves(pgn) {
return [...pgn.matchAll(/\d+\.\s+([^ ]+)\s+([^ ]+)\s+/g)].map(s => [s[1], s[2]]);
}
function seek(idx) {
cur_move = Math.max(0, Math.min(move_count, idx));
document.chessground.set({
fen: fens[cur_move],
lastMove: highlight_moves[cur_move],
});
render();
}
function controls_view() {
let move_list = [
h('span.move-pair', [
h(
'span' + (cur_move == 0 ? '.cur' : ''),
{ on: { click: _ => seek(0) } },
'...'
)
]),
];
let move_index = 1;
for (const move of moves) {
let idx = move_index * 2 - 1;
move_list.push(h('span.move-pair', [
move_index,
'.',
h(
'span.move' + (cur_move == idx ? '.cur' : ''),
{ on: { click: _ => seek(idx) } },
move[0]
),
' ',
h(
'span.move' + (cur_move == idx + 1 ? '.cur' : ''),
{ on: { click: _ => seek(idx+1) } },
move[1]
),
]));
move_index += 1;
}
return h('div', [
h('button', { on: { click: _ => seek(cur_move - 1) } }, '<<'),
h('button', { on: { click: _ => seek(cur_move + 1) } }, '>>'),
h('div#moves', move_list),
h('p', `{{Idea}}`)
]);
}
function render() {
vnode = patch(vnode, controls_view());
}
let vnode = controls;
let pgn = `{{Moves}}`;
let moves = pgn_to_moves(pgn);
let cur_move = 0;
let move_count = moves.flat().length;
let initial_fen = `{{Fen}}`;
let highlight_moves = [null];
let fens = [initial_fen];
let chess = new Chess(initial_fen);
for (const move of moves.flat()) {
try {
let res = chess.move(move);
highlight_moves.push([res.from, res.to]);
}
catch (e) {
console.error(e);
highlight_moves.push(null);
}
fens.push(chess.fen());
}
render();
</script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/assets/chessground.base.min.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/assets/chessground.brown.min.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/assets/chessground.cburnett.min.css">
<h1>Opening Ideas - {{Opening}}</h1>
<p>What is the key idea in this position?</p>
<div id="board">board</div>
<script type="module">
import { Chessground } from 'https://cdn.jsdelivr.net/npm/[email protected]/+esm';
document.chessground = Chessground(board, {
fen: "{{ Fen }}",
});
</script>
<p><a href="https://lichess.org/analysis/standard/{{Fen}}">Analyse</a></p>
.card {
font-family: arial;
font-size: 20px;
text-align: center;
color: black;
background-color: white;
}
#board {
width: 500px;
aspect-ratio: 1;
margin: auto;
}
button {
margin-top: 0;
}
.move-pair {
margin: 2pt;
}
.move {
padding: 2pt;
}
.cur {
background: #526452;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment