Socialify

Folder ..

Viewing pgnParser.js
121 lines (112 loc) • 2.9 KB

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
// ECMAScript 5 strict mode
/* jshint globalstrict: true*/
/* global WHITE,BLACK */
"use strict";
(function() {
	/*
		var WHITE = 1;
		var BLACK = 0;
	*/
	function Move(piece,color,from,to,promotion,result,str) {
		this.piece     = piece ? piece : "P";
		this.color     = color;
		this.from      = from;
		this.to        = to;
		this.promotion = promotion;
		this.result    = result;
		this.str       = str;
	}

	String.prototype.removeBrackets = function(open,close) {
		var count = 0;
		var newString = "";
		for (var i = 0; i < this.length; i++) {
			var c = this.charAt(i);
			if (c === open) {
				count++;
				continue;
			}
			if (c === close)  {
				count--;
				continue;
			}
			if (count === 0) {
				newString += c;
			}
		}
		return newString;
	};

	function parsePGN(pgn) {
		var moves = {};
		moves.fen = null;
		moves.sequence = [];
		moves.startColor = WHITE;

		var color = WHITE;

		//var re_fen = /[pnbrqkPNBRQK1-8]+(\/[pnbrqkPNBRQK1-8]+){7} +[wb] +([KQ]{1,2}|-) *([kq]{1,2}|-)( +(([a-h][1-8])|-))? +\d+ +\d+/
		var re_fen = /\[FEN *" *([pnbrqkPNBRQK1-8]+(?:\/[pnbrqkPNBRQK1-8]+){7} +([wb]) +(?:[KQ]{1,2}|-) *(?:[kq]{1,2}|-)(?: +(?:(?:[a-h][1-8])|-))? +\d+ +\d+) *" *\]/;
		var match = pgn.match(re_fen);
		if (match) {
			moves.fen = match[1];
			color = match[2] === "w" ? WHITE : BLACK;
			moves.startColor = color;
		}

		var cleanPGN = pgn
			.removeBrackets("[","]")		// removes metadata
			.removeBrackets("{","}")		// removes comments
			.removeBrackets("(",")")		// removes comments
			.replace(/\$\d+/g,'')			// removes this thing
			.replace(/\d+\.{1,3}/g,'')		// removes move numbers
			.replace(/\s+/g,' ')			// replaces multiple whitespaces by simple spaces
			.trim()							// removes front and back whitespaces
			.replace(/(0-1)$/g,'')			// result black won
			.replace(/(1-0)$/g,'')			// result white won
			.replace(/(1\/2-1\/2)$/g,'')	// result draw
			.replace(/(\*)$/g,'')			// result ongoing
			.trim()
			.split(' ');                    // split moves 

		// regex for basic moves
		//                     |pieces | |src col/row|  |dest col/row|  promo   |check|
		var re_pieceMove    =/^([NBRQK])?([a-h]?[1-8]?)?x?([a-h][1-8])(=[NBRQK])?([+#])?/;
		// regex for castling
		var re_castling = "(O-O(?:-O)?)([+#])?";
		var castling = {
			"O-O"  : {
				from:['e8','e1'],
				to:['g8','g1']
			},
			"O-O-O":  {
				from:['e8','e1'],
				to:['c8','c1']
			}
		};

		cleanPGN.forEach(function(move) {
			var info=[];

			info = move.match(re_pieceMove);
			if(info) {
				moves.sequence.push(new Move(
					info[1],
					color,
					info[2],
					info[3],
					info[4],
					info[5],
					move
				));
			}

			info = move.match(re_castling);
			if(info) {
				moves.sequence.push(new Move(
					"K",
					color,
					castling[info[1]].from[color],
					castling[info[1]].to[color],
					undefined,
					info[2],
					move
				));
			}
			color = 1-color;
		});

		return moves;
	}
	window.parsePGN = parsePGN;
})();