chess-moments 1.4.8 → 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
const glyphs = {
|
|
2
|
+
$7: '□', // Only move
|
|
3
|
+
$22: '⨀', // Zugzwang
|
|
4
|
+
$10: '=', // Equal position
|
|
5
|
+
$13: '∞', // Unclear position
|
|
6
|
+
$14: '⩲', // White is slightly better
|
|
7
|
+
$15: '⩱', // Black is slightly better
|
|
8
|
+
$16: '±', // White is better
|
|
9
|
+
$17: '∓', // Black is better
|
|
10
|
+
$18: '+−', // White is winning
|
|
11
|
+
$19: '-+', // Black is winning
|
|
12
|
+
$146: 'N', // Novelty
|
|
13
|
+
$32: '↑↑', // Development
|
|
14
|
+
$36: '↑', // Initiative
|
|
15
|
+
$40: '→', // Attack
|
|
16
|
+
$132: '⇆', // Counterplay
|
|
17
|
+
$138: '⊕', // Time trouble
|
|
18
|
+
$44: '=∞', // With compensation
|
|
19
|
+
$140: '∆', // With the idea
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
module.exports = glyphs;
|
|
@@ -1,7 +1,17 @@
|
|
|
1
1
|
const prettify = require('./prettify');
|
|
2
2
|
const shape = require('./shape');
|
|
3
3
|
|
|
4
|
-
module.exports = ({
|
|
4
|
+
module.exports = ({
|
|
5
|
+
depth,
|
|
6
|
+
move,
|
|
7
|
+
fen,
|
|
8
|
+
comment,
|
|
9
|
+
suffix,
|
|
10
|
+
glyph,
|
|
11
|
+
from,
|
|
12
|
+
to,
|
|
13
|
+
headers,
|
|
14
|
+
}) => {
|
|
5
15
|
const moment = { depth, fen };
|
|
6
16
|
if (move) {
|
|
7
17
|
moment.move = move;
|
|
@@ -23,6 +33,12 @@ module.exports = ({ depth, move, fen, comment, suffix, from, to }) => {
|
|
|
23
33
|
if (suffix) {
|
|
24
34
|
moment.suffix = suffix;
|
|
25
35
|
}
|
|
36
|
+
if (glyph) {
|
|
37
|
+
moment.glyph = glyph;
|
|
38
|
+
}
|
|
39
|
+
if (headers) {
|
|
40
|
+
moment.headers = headers;
|
|
41
|
+
}
|
|
26
42
|
|
|
27
43
|
return moment;
|
|
28
44
|
};
|
|
@@ -21,9 +21,46 @@ const momentsToPgn = (moments) => {
|
|
|
21
21
|
let currentDepth = 1;
|
|
22
22
|
let variationStack = [];
|
|
23
23
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
const headers = moments[0].headers;
|
|
25
|
+
const standardHeaders = [
|
|
26
|
+
'Event',
|
|
27
|
+
'Site',
|
|
28
|
+
'Date',
|
|
29
|
+
'Round',
|
|
30
|
+
'White',
|
|
31
|
+
'Black',
|
|
32
|
+
'Result',
|
|
33
|
+
];
|
|
34
|
+
|
|
35
|
+
if (headers) {
|
|
36
|
+
// Add standard headers (excluding placeholder values)
|
|
37
|
+
for (const key of standardHeaders) {
|
|
38
|
+
if (
|
|
39
|
+
headers[key] &&
|
|
40
|
+
headers[key] !== '?' &&
|
|
41
|
+
headers[key] !== '????.??.??'
|
|
42
|
+
) {
|
|
43
|
+
pgn += `[${key} "${headers[key]}"]\n`;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Add custom headers
|
|
48
|
+
for (const key in headers) {
|
|
49
|
+
if (!standardHeaders.includes(key) && key !== 'FEN' && key !== 'SetUp') {
|
|
50
|
+
pgn += `[${key} "${headers[key]}"]\n`;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const fenString = headers?.FEN || moments[0].fen;
|
|
56
|
+
|
|
57
|
+
if (fenString !== fen.initial) {
|
|
58
|
+
const setUp = headers?.SetUp || '1';
|
|
59
|
+
pgn += `[SetUp "${setUp}"]\n`;
|
|
60
|
+
pgn += `[FEN "${fenString}"]\n`;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
pgn += '\n';
|
|
27
64
|
|
|
28
65
|
for (let i = 0; i < moments.length; i++) {
|
|
29
66
|
const moment = moments[i];
|
|
@@ -105,6 +142,11 @@ const momentsToPgn = (moments) => {
|
|
|
105
142
|
pgn += moment.suffix;
|
|
106
143
|
}
|
|
107
144
|
|
|
145
|
+
// Add glyph if present (keep as NAG code from original PGN)
|
|
146
|
+
if (moment.glyph) {
|
|
147
|
+
pgn += ` ${moment.glyph}`;
|
|
148
|
+
}
|
|
149
|
+
|
|
108
150
|
// Add comment if present
|
|
109
151
|
if (moment.comment) {
|
|
110
152
|
pgn += ` {${moment.comment}}`;
|
|
@@ -164,8 +206,8 @@ const momentsToPgn = (moments) => {
|
|
|
164
206
|
pgn += ')';
|
|
165
207
|
}
|
|
166
208
|
|
|
167
|
-
// Add default
|
|
168
|
-
pgn += '
|
|
209
|
+
// Add result from headers if available, otherwise default to *
|
|
210
|
+
pgn += ` ${headers?.Result || '*'}`;
|
|
169
211
|
|
|
170
212
|
return pgn.trim();
|
|
171
213
|
};
|
|
@@ -5,7 +5,11 @@ const pgn = require('./pgn');
|
|
|
5
5
|
const split = require('./split');
|
|
6
6
|
|
|
7
7
|
const make = (sloppyPgn) => {
|
|
8
|
-
|
|
8
|
+
let normalizedPgn = pgn.normalize(sloppyPgn);
|
|
9
|
+
// when PGN is empty, create a default one with initial FEN
|
|
10
|
+
if (!normalizedPgn) {
|
|
11
|
+
normalizedPgn = pgn.build([], fen.initial);
|
|
12
|
+
}
|
|
9
13
|
|
|
10
14
|
// load PGN and check headers for existing FEN
|
|
11
15
|
const chess = new Chess(); // can throw if PGN is invalid
|
|
@@ -18,7 +22,7 @@ const make = (sloppyPgn) => {
|
|
|
18
22
|
};
|
|
19
23
|
|
|
20
24
|
const history = new Map();
|
|
21
|
-
const variations = split(normalizedPgn).map(({ moves, depth }) => {
|
|
25
|
+
const variations = split(normalizedPgn).map(({ moves, depth }, index) => {
|
|
22
26
|
// find previous FEN
|
|
23
27
|
if (history.get(store.depth)) {
|
|
24
28
|
store.fen = fen.previous(history, moves, depth, store.depth);
|
|
@@ -26,7 +30,13 @@ const make = (sloppyPgn) => {
|
|
|
26
30
|
store.depth = depth;
|
|
27
31
|
|
|
28
32
|
// parse current moves with the computed FEN
|
|
29
|
-
|
|
33
|
+
// only pass headers to the first move
|
|
34
|
+
const moments = parser(
|
|
35
|
+
moves,
|
|
36
|
+
store.fen,
|
|
37
|
+
depth,
|
|
38
|
+
index === 0 ? headers : null
|
|
39
|
+
);
|
|
30
40
|
|
|
31
41
|
// set history for the current depth
|
|
32
42
|
history.set(depth, fen.history(moments, history, depth));
|
package/functions/parser.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
const { Chess } = require('chess.js');
|
|
2
|
+
const { invert } = require('lodash');
|
|
2
3
|
const { initial } = require('./fen');
|
|
3
4
|
const pgn = require('./pgn');
|
|
4
5
|
const moment = require('./moment');
|
|
6
|
+
const glyphs = require('../constants/glyphs');
|
|
5
7
|
|
|
6
|
-
module.exports = (moves, fen = initial, depth = 1) => {
|
|
8
|
+
module.exports = (moves, fen = initial, depth = 1, headers = null) => {
|
|
7
9
|
const chess = new Chess();
|
|
8
10
|
chess.loadPgn(pgn.build(moves, fen)); // can throw if PGN is invalid
|
|
9
11
|
|
|
@@ -17,6 +19,7 @@ module.exports = (moves, fen = initial, depth = 1) => {
|
|
|
17
19
|
depth,
|
|
18
20
|
comment: chess.getComment(),
|
|
19
21
|
fen: chess.fen(),
|
|
22
|
+
headers,
|
|
20
23
|
});
|
|
21
24
|
|
|
22
25
|
const moments = history.map((item) => {
|
|
@@ -29,13 +32,14 @@ module.exports = (moves, fen = initial, depth = 1) => {
|
|
|
29
32
|
to: item.to,
|
|
30
33
|
comment: chess.getComment(),
|
|
31
34
|
suffix: chess.getSuffixAnnotation(),
|
|
35
|
+
glyph: invert(glyphs)[chess.getGlyph()],
|
|
32
36
|
fen: chess.fen(),
|
|
33
37
|
});
|
|
34
38
|
});
|
|
35
39
|
|
|
36
40
|
// finally, add the first chess "moment" when needed
|
|
37
|
-
const
|
|
38
|
-
if (
|
|
41
|
+
const pgnHeaders = chess.getHeaders();
|
|
42
|
+
if (pgnHeaders.FEN || fen === initial || first.comment || first.shapes) {
|
|
39
43
|
moments.unshift(first);
|
|
40
44
|
}
|
|
41
45
|
|
package/package.json
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "chess-moments",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.0",
|
|
4
4
|
"description": "PGN parser that transforms PGN files into chess \"moments\"",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"files": [
|
|
7
7
|
"index.js",
|
|
8
8
|
"chess.js",
|
|
9
|
-
"functions/**/*.js"
|
|
9
|
+
"functions/**/*.js",
|
|
10
|
+
"constants/**/*.js"
|
|
10
11
|
],
|
|
11
12
|
"scripts": {
|
|
12
13
|
"test": "mocha",
|
|
@@ -24,7 +25,7 @@
|
|
|
24
25
|
],
|
|
25
26
|
"license": "MIT",
|
|
26
27
|
"dependencies": {
|
|
27
|
-
"chess.js": "github:
|
|
28
|
+
"chess.js": "github:brobert1/chess.js#master"
|
|
28
29
|
},
|
|
29
30
|
"devDependencies": {
|
|
30
31
|
"chai": "^4.3.7",
|