Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add support for annotations #235

Merged
merged 1 commit into from
Jun 11, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 93 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -635,6 +635,99 @@ chess.validate_fen('4r3/8/X12XPk/1p6/pP2p1R1/P1B5/2P2K2/3r4 w - - 1 45')
// error: '1st field (piece positions) is invalid [invalid piece].' }
```

### .get_comment()

Retrieve the comment for the current position, if it exists.

```js
const chess = new Chess()

chess.load_pgn("1. e4 e5 2. Nf3 Nc6 3. Bc4 Bc5 {giuoco piano} *")

chess.get_comment()
// -> "giuoco piano"
```

### .set_comment(comment)

Comment on the current position.

```js
const chess = new Chess()

chess.move("e4")
chess.set_comment("king's pawn opening")

chess.pgn()
// -> "1. e4 {king's pawn opening}"
```

### .delete_comment()

Delete and return the comment for the current position, if it exists.

```js
const chess = new Chess()

chess.load_pgn("1. e4 e5 2. Nf3 Nc6 3. Bc4 Bc5 {giuoco piano} *")

chess.get_comment()
// -> "giuoco piano"

chess.delete_comment()
// -> "giuoco piano"

chess.get_comment()
// -> undefined
```

### .get_comments()

Retrieve comments for all positions.

```js
const chess = new Chess()

chess.load_pgn("1. e4 e5 {king's pawn opening} 2. Nf3 Nc6 3. Bc4 Bc5 {giuoco piano} *")

chess.get_comments()
// -> [
// {
// fen: "rnbqkbnr/pppp1ppp/8/4p3/4P3/8/PPPP1PPP/RNBQKBNR w KQkq e6 0 2",
// comment: "king's pawn opening"
// },
// {
// fen: "r1bqkbnr/pppp1ppp/2n5/4p3/4P3/5N2/PPPP1PPP/RNBQKB1R w KQkq - 2 3",
// comment: "giuoco piano"
// }
// ]
```

### .delete_comments()

Delete and return comments for all positions.

```js
const chess = new Chess()

chess.load_pgn("1. e4 e5 {king's pawn opening} 2. Nf3 Nc6 3. Bc4 Bc5 {giuoco piano} *")

chess.delete_comments()
// -> [
// {
// fen: "rnbqkbnr/pppp1ppp/8/4p3/4P3/8/PPPP1PPP/RNBQKBNR w KQkq e6 0 2",
// comment: "king's pawn opening"
// },
// {
// fen: "r1bqkbnr/pppp1ppp/2n5/4p3/4P3/5N2/PPPP1PPP/RNBQKB1R w KQkq - 2 3",
// comment: "giuoco piano"
// }
// ]

chess.get_comments()
// -> []
```

## Sites Using chess.js

- [chess.com](http://www.chess.com/)
Expand Down
283 changes: 283 additions & 0 deletions __tests__/chess.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -810,6 +810,289 @@ describe("Load PGN", function() {

});

describe("Manipulate Comments", function() {
var is_empty = function (object) {
for (var property in object) {
if (object.hasOwnProperty(property)) {
return false;
}
}
return true;
};

it('no comments', function() {
var chess = new Chess();
expect(chess.get_comment())
.toBeUndefined();
expect(chess.get_comments())
.toEqual([]);
chess.move('e4');
expect(chess.get_comment())
.toBeUndefined();
expect(chess.get_comments())
.toEqual([]);
expect(chess.pgn())
.toEqual('1. e4');
});

it('comment for initial position', function() {
var chess = new Chess();
chess.set_comment('starting position');
expect(chess.get_comment())
.toEqual('starting position');
expect(chess.get_comments())
.toEqual([{fen: chess.fen(), comment: 'starting position'}]);
expect(chess.pgn())
.toEqual('{starting position}');
});

it('comment for first move', function() {
var chess = new Chess();
chess.move('e4');
var e4 = chess.fen();
chess.set_comment('good move');
expect(chess.get_comment())
.toEqual('good move');
expect(chess.get_comments())
.toEqual([{fen: e4, comment: 'good move'}]);
chess.move('e5');
expect(chess.get_comment())
.toBeUndefined();
expect(chess.get_comments())
.toEqual([{fen: e4, comment: 'good move'}]);
expect(chess.pgn())
.toEqual('1. e4 {good move} e5');
});

it('comment for last move', function() {
var chess = new Chess();
chess.move('e4');
chess.move('e6');
chess.set_comment('dubious move');
expect(chess.get_comment())
.toEqual('dubious move');
expect(chess.get_comments())
.toEqual([{fen: chess.fen(), comment: 'dubious move'}]);
expect(chess.pgn())
.toEqual('1. e4 e6 {dubious move}');
});

it('comment with brackets', function() {
var chess = new Chess();
chess.set_comment('{starting position}');
expect(chess.get_comment())
.toEqual('[starting position]');
});

it('comments for everything', function() {
var chess = new Chess();

var initial = chess.fen();
chess.set_comment('starting position');
expect(chess.get_comment())
.toEqual('starting position');
expect(chess.get_comments())
.toEqual([{fen: initial, comment: 'starting position'}]);
expect(chess.pgn())
.toEqual('{starting position}');

chess.move('e4');
var e4 = chess.fen();
chess.set_comment('good move');
expect(chess.get_comment())
.toEqual('good move');
expect(chess.get_comments())
.toEqual([
{fen: initial, comment: 'starting position'},
{fen: e4, comment: 'good move'}
]);
expect(chess.pgn())
.toEqual('{starting position} 1. e4 {good move}');

chess.move('e6');
var e6 = chess.fen();
chess.set_comment('dubious move');
expect(chess.get_comment())
.toEqual('dubious move');
expect(chess.get_comments())
.toEqual([
{fen: initial, comment: 'starting position'},
{fen: e4, comment: 'good move'},
{fen: e6, comment: 'dubious move'}
]);
expect(chess.pgn())
.toEqual('{starting position} 1. e4 {good move} e6 {dubious move}');
});

it('delete comments', function() {
var chess = new Chess();
expect(chess.delete_comment())
.toBeUndefined();
expect(chess.delete_comments())
.toEqual([]);
var initial = chess.fen();
chess.set_comment('starting position');
chess.move('e4');
var e4 = chess.fen();
chess.set_comment('good move');
chess.move('e6');
var e6 = chess.fen();
chess.set_comment('dubious move');
expect(chess.get_comments())
.toEqual([
{fen: initial, comment: 'starting position'},
{fen: e4, comment: 'good move'},
{fen: e6, comment: 'dubious move'}
]);
expect(chess.delete_comment())
.toEqual('dubious move');
expect(chess.pgn())
.toEqual('{starting position} 1. e4 {good move} e6');
expect(chess.delete_comment())
.toBeUndefined();
expect(chess.delete_comments())
.toEqual([
{fen: initial, comment: 'starting position'},
{fen: e4, comment: 'good move'}
]);
expect(chess.pgn())
.toEqual('1. e4 e6');
});

it('prune comments', function() {
var chess = new Chess();
chess.move('e4');
chess.set_comment('tactical');
chess.undo();
chess.move('d4');
chess.set_comment('positional');
expect(chess.get_comments())
.toEqual([{fen: chess.fen(), comment: 'positional'}]);
expect(chess.pgn())
.toEqual('1. d4 {positional}');
});

it('clear comments', function() {
var test = function(fn) {
var chess = new Chess();
chess.move('e4');
chess.set_comment('good move');
expect(chess.get_comments())
.toEqual([{fen: chess.fen(), comment: 'good move'}]);
fn(chess);
expect(chess.get_comments())
.toEqual([]);
};
test(function(chess) { chess.reset(); });
test(function(chess) { chess.clear(); });
test(function(chess) { chess.load(chess.fen()); });
test(function(chess) { chess.load_pgn('1. e4'); });
});

});

describe('Format Comments', function() {
it('wrap comments', function() {
var chess = new Chess();
chess.move('e4');
chess.set_comment('good move');
chess.move('e5');
chess.set_comment('classical response');
expect(chess.pgn())
.toEqual('1. e4 {good move} e5 {classical response}');
expect(chess.pgn({max_width: 16}))
.toEqual([
'1. e4 {good',
'move} e5',
'{classical',
'response}'
].join('\n'));
expect(chess.pgn({max_width: 2}))
.toEqual([
'1.',
'e4',
'{good',
'move}',
'e5',
'{classical',
'response}'
].join('\n'));
});
});

describe('Load Comments', function() {
var tests = [
{
name: 'bracket comments',
input: '1. e4 {good move} e5 {classical response}',
output: '1. e4 {good move} e5 {classical response}'
},
{
name: 'semicolon comments',
input: '1. e4 e5; romantic era\n 2. Nf3 Nc6; common continuation',
output: '1. e4 e5 {romantic era} 2. Nf3 Nc6 {common continuation}'
},
{
name: 'bracket and semicolon comments',
input: '1. e4 {good!} e5; standard response\n 2. Nf3 Nc6 {common}',
output: '1. e4 {good!} e5 {standard response} 2. Nf3 Nc6 {common}'
},
{
name: 'bracket comments with newlines',
input: '1. e4 {good\nmove} e5 {classical\nresponse}',
output: '1. e4 {good move} e5 {classical response}'
},
{
name: 'initial comment',
input: '{ great game }\n1. e4 e5',
output: '{ great game } 1. e4 e5'
},
{
name: 'empty bracket comment',
input: '1. e4 {}',
output: '1. e4 {}'
},
{
name: 'empty semicolon comment',
input: '1. e4;\ne5',
output: '1. e4 {} e5'
},
{
name: 'unicode comment',
input: '1. e4 {Δ, Й, ק ,م, ๗, あ, 叶, 葉, and 말}',
output: '1. e4 {Δ, Й, ק ,م, ๗, あ, 叶, 葉, and 말}'
},
{
name: 'semicolon in bracket comment',
input: '1. e4 { a classic; well-studied } e5',
output: '1. e4 { a classic; well-studied } e5'
},
{
name: 'bracket in semicolon comment',
input: '1. e4 e5 ; a classic {well-studied}',
output: '1. e4 e5 {a classic {well-studied}}'
},
{
name: 'markers in bracket comment',
input: '1. e4 e5 {($1) 1. e4 is good}',
output: '1. e4 e5 {($1) 1. e4 is good}'
},
{
name: 'markers in semicolon comment',
input: '1. e4 e5; ($1) 1. e4 is good',
output: '1. e4 e5 {($1) 1. e4 is good}'
}
];

tests.forEach(function(test) {
it(`load ${test.name}`, function() {
var chess = new Chess();
chess.load_pgn(test.input);
expect(chess.pgn())
.toEqual(test.output);
});
});
});

describe("Make Move", function() {

Expand Down
Loading