chess-moments 0.13.0 → 0.14.1

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,9 @@
1
+ const getNextMoments = require('./get-next-moments');
2
+ const getPrevMoment = require('./get-prev-moment');
3
+ const momentsToPgn = require('./moments-to-pgn');
4
+
5
+ module.exports = {
6
+ getNextMoments,
7
+ getPrevMoment,
8
+ momentsToPgn,
9
+ };
@@ -0,0 +1,158 @@
1
+ const fen = require('../fen');
2
+ const { getBrushCode } = require('../helpers');
3
+
4
+ /**
5
+ * Converts chess moments back to PGN format
6
+ * @param {Array} moments - Array of chess moment objects
7
+ * @returns {String} PGN string
8
+ */
9
+ const momentsToPgn = (moments) => {
10
+ if (!Array.isArray(moments) || moments.length === 0) {
11
+ return '';
12
+ }
13
+
14
+ let pgn = '';
15
+ let currentDepth = 1;
16
+ let variationStack = [];
17
+
18
+ // Check if we need to add FEN headers for non-standard starting position
19
+ const initialMoment = moments[0];
20
+ if (initialMoment && initialMoment.fen && initialMoment.fen !== fen.initial) {
21
+ pgn += `[SetUp "1"]\n`;
22
+ pgn += `[FEN "${initialMoment.fen}"]\n\n`;
23
+ }
24
+
25
+ for (let i = 0; i < moments.length; i++) {
26
+ const moment = moments[i];
27
+ const depth = moment.depth || 1;
28
+
29
+ // Handle moments without moves (initial position or variation breaks)
30
+ if (!moment.move) {
31
+ // If this is a variation marker (depth > 1) and not the initial position
32
+ if (depth > 1 && i > 0) {
33
+ // Check if we need to start a new variation at the same depth
34
+ if (depth === currentDepth) {
35
+ // Close current variation and start a new one at the same level
36
+ pgn += ') (';
37
+ } else if (depth > currentDepth) {
38
+ // Starting a new variation at a deeper level
39
+ variationStack.push(currentDepth);
40
+ pgn += ' (';
41
+ currentDepth = depth;
42
+ }
43
+ }
44
+
45
+ // Add initial comment if present
46
+ if (moment.comment) {
47
+ pgn += `{${moment.comment}} `;
48
+ }
49
+ continue;
50
+ }
51
+
52
+ // Determine who made this move and what move number it is from the FEN
53
+ const fenParts = moment.fen.split(' ');
54
+ const activeColorAfterMove = fenParts[1]; // 'w' or 'b' - who moves next
55
+ const fullmoveNumber = parseInt(fenParts[5]);
56
+
57
+ // If black is to move after this move, then white made this move
58
+ const moveWasByWhite = activeColorAfterMove === 'b';
59
+ // For white moves, the move number is the fullmove number
60
+ // For black moves, the move number is fullmove number - 1 (since fullmove increments after black's move)
61
+ const moveNumber = moveWasByWhite ? fullmoveNumber : fullmoveNumber - 1;
62
+
63
+ // Handle depth changes (variations)
64
+ if (depth > currentDepth) {
65
+ // Starting a new variation
66
+ variationStack.push(currentDepth);
67
+ pgn += ' (';
68
+ currentDepth = depth;
69
+ } else if (depth < currentDepth) {
70
+ // Ending variation(s) - close as many as needed to get to the right depth
71
+ while (currentDepth > depth) {
72
+ variationStack.pop();
73
+ pgn += ')';
74
+ currentDepth--;
75
+ }
76
+ if (pgn.endsWith(')')) {
77
+ pgn += ' ';
78
+ }
79
+ }
80
+
81
+ // Add move number for white moves or when starting a variation
82
+ if (moveWasByWhite || (depth > 1 && pgn.endsWith('('))) {
83
+ pgn += `${moveNumber}.`;
84
+ if (!moveWasByWhite) {
85
+ pgn += '..';
86
+ }
87
+ pgn += ' ';
88
+ }
89
+
90
+ // Add the move
91
+ pgn += moment.move;
92
+
93
+ // Add comment if present
94
+ if (moment.comment) {
95
+ pgn += ` {${moment.comment}}`;
96
+ }
97
+
98
+ // Add shapes if present
99
+ if (moment.shapes && moment.shapes.length > 0) {
100
+ let shapesComment = '';
101
+ const squareHighlights = moment.shapes.filter(
102
+ (s) => !s.dest || s.dest === ']'
103
+ );
104
+ const arrows = moment.shapes.filter((s) => s.dest && s.dest !== ']');
105
+
106
+ if (squareHighlights.length > 0) {
107
+ const coloredSquares = squareHighlights
108
+ .map((s) => {
109
+ const colorCode = getBrushCode(s.brush);
110
+ return `${colorCode}${s.orig}`;
111
+ })
112
+ .join(',');
113
+ shapesComment += `[%csl ${coloredSquares}]`;
114
+ }
115
+
116
+ if (arrows.length > 0) {
117
+ const coloredArrows = arrows
118
+ .map((s) => {
119
+ const colorCode = getBrushCode(s.brush);
120
+ return `${colorCode}${s.orig}${s.dest}`;
121
+ })
122
+ .join(',');
123
+ if (shapesComment) shapesComment += ' ';
124
+ shapesComment += `[%cal ${coloredArrows}]`;
125
+ }
126
+
127
+ if (shapesComment) {
128
+ if (moment.comment) {
129
+ // If there's already a comment, add shapes to it
130
+ pgn = pgn.replace(/\{([^}]*)\}$/, `{$1 ${shapesComment}}`);
131
+ } else {
132
+ pgn += ` {${shapesComment}}`;
133
+ }
134
+ }
135
+ }
136
+
137
+ // Add space after move if not the last move
138
+ if (i < moments.length - 1) {
139
+ const nextMoment = moments[i + 1];
140
+ if (nextMoment && nextMoment.move) {
141
+ pgn += ' ';
142
+ }
143
+ }
144
+ }
145
+
146
+ // Close any remaining variations
147
+ while (variationStack.length > 0) {
148
+ variationStack.pop();
149
+ pgn += ')';
150
+ }
151
+
152
+ // Add default result
153
+ pgn += ' *';
154
+
155
+ return pgn.trim();
156
+ };
157
+
158
+ module.exports = momentsToPgn;
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Convert brush color name to PGN color code
3
+ */
4
+ const getBrushCode = (brush) => {
5
+ const brushCodes = {
6
+ green: 'G',
7
+ red: 'R',
8
+ blue: 'B',
9
+ yellow: 'Y',
10
+ };
11
+ return brushCodes[brush] || 'G';
12
+ };
13
+
14
+ module.exports = getBrushCode;
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Convert PGN color code to brush color name
3
+ */
4
+ const getBrushColor = (letter) => {
5
+ const brushes = {
6
+ R: 'red',
7
+ Y: 'yellow',
8
+ G: 'green',
9
+ B: 'blue',
10
+ };
11
+
12
+ return brushes[letter] || 'green';
13
+ };
14
+
15
+ module.exports = getBrushColor;
@@ -0,0 +1,7 @@
1
+ const getBrushCode = require('./get-brush-code');
2
+ const getBrushColor = require('./get-brush-color');
3
+
4
+ module.exports = {
5
+ getBrushCode,
6
+ getBrushColor,
7
+ };
@@ -1,8 +1,5 @@
1
- const brush = require('./brush');
2
1
  const fen = require('./fen');
3
2
  const flat = require('./flat');
4
- const getNextMoments = require('./get-next-moments');
5
- const getPrevMoment = require('./get-prev-moment');
6
3
  const lines = require('./lines');
7
4
  const moment = require('./moment');
8
5
  const parser = require('./parser');
@@ -15,11 +12,8 @@ const train = require('./train');
15
12
  const tree = require('./tree');
16
13
 
17
14
  module.exports = {
18
- brush,
19
15
  fen,
20
16
  flat,
21
- getNextMoments,
22
- getPrevMoment,
23
17
  lines,
24
18
  moment,
25
19
  parser,
@@ -1,4 +1,4 @@
1
- const brush = require('./brush');
1
+ const { getBrushColor } = require('./helpers');
2
2
 
3
3
  module.exports = (comment) => {
4
4
  try {
@@ -16,7 +16,7 @@ module.exports = (comment) => {
16
16
 
17
17
  for (const target of shapes.join('').split(',')) {
18
18
  draw.push({
19
- brush: brush(target.substr(0, 1)),
19
+ brush: getBrushColor(target.substr(0, 1)),
20
20
  orig: target.substr(1, 2),
21
21
  dest: target.substr(3, 2),
22
22
  });
package/index.js CHANGED
@@ -1,12 +1,9 @@
1
+ const { fen, pgn, flat, train, tree } = require('./functions');
1
2
  const {
2
- fen,
3
- pgn,
4
- flat,
5
- train,
6
- tree,
7
3
  getNextMoments,
8
4
  getPrevMoment,
9
- } = require('./functions');
5
+ momentsToPgn,
6
+ } = require('./functions/extras');
10
7
 
11
8
  module.exports = {
12
9
  fen,
@@ -16,4 +13,5 @@ module.exports = {
16
13
  tree,
17
14
  getNextMoments,
18
15
  getPrevMoment,
16
+ momentsToPgn,
19
17
  };
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "chess-moments",
3
- "version": "0.13.0",
3
+ "version": "0.14.1",
4
4
  "description": "PGN parser that transforms PGN files into chess \"moments\"",
5
5
  "main": "dist/index.js",
6
6
  "files": [
7
7
  "index.js",
8
8
  "chess.js",
9
- "functions/*.js"
9
+ "functions/**/*.js"
10
10
  ],
11
11
  "scripts": {
12
12
  "test": "mocha",
@@ -1,9 +0,0 @@
1
- module.exports = (letter) => {
2
- const brushes = {
3
- R: 'red',
4
- Y: 'yellow',
5
- G: 'green',
6
- };
7
-
8
- return brushes[letter] || 'green';
9
- };