From 1342cb6cce78681889ec45cdaa66f272afb0aef7 Mon Sep 17 00:00:00 2001 From: Niklas Fiekas Date: Mon, 5 Feb 2024 21:33:40 +0100 Subject: [PATCH] add very basic helpers to Node as methods --- CHANGELOG.md | 8 ++++++++ package.json | 2 +- src/pgn.test.ts | 10 ++++------ src/pgn.ts | 36 +++++++++++++++++++----------------- 4 files changed, 32 insertions(+), 24 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ed7079f4..b6b4057c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog for chessops +## v0.14.0 + +- Change package layout to hybrid cjs/esm with subpath exports. +- `chessops/pgn`: + - Add `Node.mainlineNodes()`. + - Add `node.end()`. + - Add `extend()`. + ## v0.13.0 - `Position.fromSetup()` now only checks minimum validity requirements. diff --git a/package.json b/package.json index e130f5b5..2ef8ce99 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "chessops", - "version": "0.13.0", + "version": "0.14.0", "description": "Chess and chess variant rules and operations", "keywords": [ "chess", diff --git a/src/pgn.test.ts b/src/pgn.test.ts index 8a039b08..3a918679 100644 --- a/src/pgn.test.ts +++ b/src/pgn.test.ts @@ -9,8 +9,6 @@ import { extend, Game, isChildNode, - mainline, - mainlineEnd, makeComment, makePgn, Node, @@ -85,7 +83,7 @@ test('make pgn', () => { test('extend mainline', () => { const game: Game = defaultGame(emptyHeaders); - extend(mainlineEnd(game.moves), 'e4 d5 a3 h6 Bg5'.split(' ').map(san => ({ san }))); + extend(game.moves.end(), 'e4 d5 a3 h6 Bg5'.split(' ').map(san => ({ san }))); expect(makePgn(game)).toEqual('1. e4 d5 2. a3 h6 3. Bg5 *\n'); }); @@ -161,7 +159,7 @@ testPgnFile( }, game => { expect(game.headers.get('Variant')).toBe('Antichess'); - expect(Array.from(mainline(game.moves)).map(move => move.san)).toStrictEqual(['e3', 'e6', 'b4', 'Bxb4', 'Qg4']); + expect(Array.from(game.moves.mainline()).map(move => move.san)).toStrictEqual(['e3', 'e6', 'b4', 'Bxb4', 'Qg4']); }, ); testPgnFile( @@ -188,12 +186,12 @@ testPgnFile( allValid: true, }, game => { - expect(Array.from(mainline(game.moves)).map(move => move.san)).toStrictEqual(['e4', 'e5', 'Nf3', 'Nc6', 'Bb5']); + expect(Array.from(game.moves.mainline()).map(move => move.san)).toStrictEqual(['e4', 'e5', 'Nf3', 'Nc6', 'Bb5']); }, ); test('tricky tokens', () => { - const steps = Array.from(mainline(parsePgn('O-O-O !! 0-0-0# ??')[0].moves)); + const steps = Array.from(parsePgn('O-O-O !! 0-0-0# ??')[0].moves.mainline()); expect(steps[0].san).toBe('O-O-O'); expect(steps[0].nags).toEqual([3]); expect(steps[1].san).toBe('O-O-O#'); diff --git a/src/pgn.ts b/src/pgn.ts index cd623ff7..5944f9a4 100644 --- a/src/pgn.ts +++ b/src/pgn.ts @@ -120,32 +120,34 @@ export const defaultGame = (initHeaders: () => Map = defaultH export class Node { children: ChildNode[] = []; -} -export class ChildNode extends Node { - constructor(public data: T) { - super(); + *mainlineNodes(): Iterable> { + let node: Node = this; + while (node.children.length) { + const child = node.children[0]; + yield child; + node = child; + } } -} -export const isChildNode = (node: Node): node is ChildNode => node instanceof ChildNode; + *mainline(): Iterable { + for (const child of this.mainlineNodes()) yield child.data; + } -export function* mainlineNodes(node: Node): Iterable> { - while (node.children.length) { - const child = node.children[0]; - yield child; - node = child; + end(): Node { + let node: Node = this; + while (node.children.length) node = node.children[0]; + return node; } } -export function* mainline(node: Node): Iterable { - for (const child of mainlineNodes(node)) yield child.data; +export class ChildNode extends Node { + constructor(public data: T) { + super(); + } } -export function mainlineEnd(node: Node): Node { - while (node.children.length) node = node.children[0]; - return node; -} +export const isChildNode = (node: Node): node is ChildNode => node instanceof ChildNode; export const extend = (node: Node, data: T[]): Node => { for (const d of data) {