chess-moments 1.2.2 → 1.3.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.
- package/functions/extras/index.js +2 -0
- package/functions/extras/promote-mainline.js +117 -0
- package/index.js +2 -0
- package/package.json +1 -1
|
@@ -4,6 +4,7 @@ const getNextMoments = require('./get-next-moments');
|
|
|
4
4
|
const getPrevMoment = require('./get-prev-moment');
|
|
5
5
|
const momentsToPgn = require('./moments-to-pgn');
|
|
6
6
|
const moveTrainer = require('./move-trainer');
|
|
7
|
+
const promoteMainline = require('./promote-mainline');
|
|
7
8
|
|
|
8
9
|
module.exports = {
|
|
9
10
|
addMomentToTree,
|
|
@@ -12,4 +13,5 @@ module.exports = {
|
|
|
12
13
|
getPrevMoment,
|
|
13
14
|
momentsToPgn,
|
|
14
15
|
moveTrainer,
|
|
16
|
+
promoteMainline,
|
|
15
17
|
};
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
const promoteMainline = (moments, current) => {
|
|
2
|
+
if (!current || current.depth === 1) return moments;
|
|
3
|
+
|
|
4
|
+
const currentDepth = current.depth;
|
|
5
|
+
const targetDepth = currentDepth - 1;
|
|
6
|
+
|
|
7
|
+
// Find sideline position marker
|
|
8
|
+
let sidelinePositionIndex = -1;
|
|
9
|
+
for (let i = 0; i < current.index; i++) {
|
|
10
|
+
if (moments[i].depth === currentDepth && !moments[i].move) {
|
|
11
|
+
sidelinePositionIndex = i;
|
|
12
|
+
break;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
if (sidelinePositionIndex === -1) return moments;
|
|
16
|
+
|
|
17
|
+
// Find end of sideline window (end of a window = next position at the same depth OR first lower depth)
|
|
18
|
+
let sidelineEndIndex = moments.length;
|
|
19
|
+
for (let i = sidelinePositionIndex + 1; i < moments.length; i++) {
|
|
20
|
+
if (
|
|
21
|
+
(moments[i].depth === currentDepth && !moments[i].move) ||
|
|
22
|
+
moments[i].depth < currentDepth
|
|
23
|
+
) {
|
|
24
|
+
sidelineEndIndex = i;
|
|
25
|
+
break;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Find mainline move to replace
|
|
30
|
+
let targetMoveIndex = -1;
|
|
31
|
+
for (let i = sidelinePositionIndex - 1; i >= 0; i--) {
|
|
32
|
+
if (moments[i].depth === targetDepth && moments[i].move) {
|
|
33
|
+
targetMoveIndex = i;
|
|
34
|
+
break;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
if (targetMoveIndex === -1) return moments;
|
|
38
|
+
|
|
39
|
+
// Find end of mainline segment to demote
|
|
40
|
+
let targetSegmentEndIndex = moments.length;
|
|
41
|
+
let seenTargetDepthMove = false;
|
|
42
|
+
for (let i = targetMoveIndex + 1; i < moments.length; i++) {
|
|
43
|
+
const moment = moments[i];
|
|
44
|
+
|
|
45
|
+
if (moment.depth === targetDepth && moment.move) {
|
|
46
|
+
seenTargetDepthMove = true;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (moment.depth < targetDepth) {
|
|
50
|
+
targetSegmentEndIndex = i;
|
|
51
|
+
break;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (moment.depth === targetDepth && !moment.move && seenTargetDepthMove) {
|
|
55
|
+
targetSegmentEndIndex = i;
|
|
56
|
+
break;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const demotedIndices = new Set([targetMoveIndex]);
|
|
61
|
+
const demotedMoves = [{ ...moments[targetMoveIndex], depth: currentDepth }];
|
|
62
|
+
|
|
63
|
+
for (let i = targetMoveIndex + 1; i < targetSegmentEndIndex; i++) {
|
|
64
|
+
if (moments[i].depth === targetDepth && moments[i].move) {
|
|
65
|
+
demotedIndices.add(i);
|
|
66
|
+
demotedMoves.push({ ...moments[i], depth: currentDepth });
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Rebuild the moments array by promoting the current move to the mainline depth,
|
|
71
|
+
// demoting the old mainline sequence into the sideline, preserving order of
|
|
72
|
+
// unaffected moves, and adjusting depths/indices accordingly.
|
|
73
|
+
const result = [];
|
|
74
|
+
|
|
75
|
+
for (let i = 0; i < targetMoveIndex; i++) {
|
|
76
|
+
result.push({ ...moments[i] });
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
result.push({ ...moments[current.index], depth: targetDepth });
|
|
80
|
+
|
|
81
|
+
for (let i = targetMoveIndex + 1; i < sidelinePositionIndex; i++) {
|
|
82
|
+
if (!demotedIndices.has(i)) {
|
|
83
|
+
result.push({ ...moments[i] });
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
result.push({ ...moments[sidelinePositionIndex] });
|
|
88
|
+
for (const move of demotedMoves) {
|
|
89
|
+
result.push(move);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
for (let i = sidelinePositionIndex + 1; i < sidelineEndIndex; i++) {
|
|
93
|
+
if (i === current.index) continue;
|
|
94
|
+
|
|
95
|
+
const moment = moments[i];
|
|
96
|
+
if (moment.depth === currentDepth && moment.move) {
|
|
97
|
+
result.push({ ...moment, depth: targetDepth });
|
|
98
|
+
} else {
|
|
99
|
+
result.push({ ...moment });
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
for (let i = sidelineEndIndex; i < moments.length; i++) {
|
|
104
|
+
if (!demotedIndices.has(i)) {
|
|
105
|
+
result.push({ ...moments[i] });
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Reassign indices
|
|
110
|
+
result.forEach((m, i) => {
|
|
111
|
+
m.index = i;
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
return result;
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
module.exports = promoteMainline;
|
package/index.js
CHANGED