<commit_before>/**
 * Copyright 2008 Toomas Römer
 *
 * Licensed under the Apache License, Version 2.0 (the "License")
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
**/

/*
	Representation of the PGN format. Different meta information
	about the actual game(s) plus the moves and result of the game.
*/
function Pgn(pgn) {
	// properties of the game eg players, ELOs etc
	this.props = new Object();
	this.validProps = ['Event','Site','Date','Round',
								'White','Black','Result','FEN',
								'WhiteElo','BlackElo','TimeControl'];
	// the moves, one move contains the black and white move
	this.moves = new Array();
	// the current move in the game
	this.currentMove = 0;
	// for outputting white and black moves separately
	this.skip = 0;

	// strip newlines
	this.pgnOrig = pgn;
	pgn = pgn.replace(/\n/g," ");

	// replace dollar signs
	//"!", "?", "!!", "!?", "?!", and "??"
	pgn = pgn.replace(/\ \$1[0-9]*/g, "!");
	pgn = pgn.replace(/\ \$2[0-9]*/g, "?");
	pgn = pgn.replace(/\ \$3[0-9]*/g, "!!");
	pgn = pgn.replace(/\ \$4[0-9]*/g, "??");
	pgn = pgn.replace(/\ \$5[0-9]*/g, "!?");
	pgn = pgn.replace(/\ \$6[0-9]*/g, "?!");
	pgn = pgn.replace(/\ \$[0-9]+/g, "");

	// make double spaces to single spaces
	pgn = pgn.replace(/\s+/g,' ');

	this.pgn = pgn;
	this.pgnRaw = pgn;
	if (isPGNBroken(pgn))
		this.pgnStripped = stripItBroken(pgn);
	else
		this.pgnStripped = stripIt(pgn);

	/* constructor */

	// strip comments
	if (isPGNBroken(pgn))
		this.pgn = stripItBroken(pgn,true);
	else
		this.pgn = stripIt(pgn,true);

	// Match all properties
	var reprop = /\[([^\]]*)\]/gi;
	var matches = this.pgn.match(reprop);
	if (matches) {
		// extract information from each matched property
		 for(var i = 0;i < matches.length; i++) {
			 // lose the brackets
			 tmpMatches = matches[i].substring(1, matches[i].length-1);
			 // split by the first space
			 var key = tmpMatches.substring(0, tmpMatches.indexOf(" "));
			 var value = tmpMatches.substring(tmpMatches.indexOf(" ")+1);
			 if (value.charAt(0) == '"')
				 value = value.substr(1);
			 if (value.charAt(value.length-1) == '"')
				 value = value.substr(0, value.length-1);

			 this.props[key] = value;
			 this.pgn = this.pgn.replace(matches[i], "");
		 }
	}

	// remove the properties
	this.pgn = this.pgn.replace(/\[[^\]]*\]/g,'');
	//trim
	this.pgn = this.pgn.replace(/^\s+|\s+$/g, '');

	var gameOverre = new Array(
		/1\/2-1\/2/,
		/0-1/,
		/1-0/,
		/\*/
	);

	// the moves;
	var themoves = this.pgn.split(" ");
	var tmp = new Array();
	tmp[1] = null;
	var tmpidx = 0;	//make this 1 if FEN and black to move
	if (this.props["FEN"]) {
		var fen = this.props['FEN'].split(/\/| /g);
		if (fen[8] == 'b') {
			tmpidx = 1;
			this.skip = 1;
		}
	}

	if (themoves.length>0 && themoves[themoves.length-1] == "...") {
		 themoves = themoves.slice(0, themoves.length-1);
	}

	var sizeOfTheMoves = themoves.length;
	if (themoves.length>0) {
		for (var i=0;i<gameOverre.length;i++) {
			if (themoves[themoves.length-1].match(gameOverre[i])) {
				sizeOfTheMoves = themoves.length-1;
				continue;
			}
		}
	}

	for (var i=0;i<sizeOfTheMoves;i++) {	//don't handle game end bit
		if (themoves[i]) {
			themoves[i] = themoves[i].replace(/^\s+|\s+$/g, '');
		}

		if (!themoves[i]) {
			continue;
		}

		if (themoves[i].indexOf("-") != -1
			 && !/[0|o]-[0|o]/i.test(themoves[i])
			 && !/[0|o]-[0|o]-[0|o]/i.test(themoves[i])
			) {
			var tmp2 = themoves[i].split("-");
			var matches = tmp2[0].match(/[0-9]*?\.?([A-Z])/);
			var newMove;
			if (matches != null) {
				 // we can just replace the - with nothing
				 newMove  = themoves[i].replace("-","");
			}
			else {
				matches = tmp2[0].match(/[0-9]+\./);
				if (matches) {
					newMove = matches[0]+tmp2[1];
				}
				else {
					newMove = tmp2[1];
				}
			}
			themoves[i] = newMove;
		}
		var c = themoves[i].charAt(0);
		if (c >= '1' && c <= '9') {	//move number
			c = themoves[i].charAt(themoves[i].length-1);
			if (c == '.') {	//ends with . so nothing but a move
				continue;
			}
			var found = false;
			for (var j=0;j<themoves[i].length;j++) {
				c = themoves[i].charAt(j);
				if (c >= '0' && c <= '9') {
					continue;
				}
				else {
					found = true;
					var idx = j;
					// 6.0-0 goes wrong as 0 is used for castling
					if (!(themoves[i].charAt(j) >= '0' && themoves[i].charAt(j)<='9')) {
						 idx = j+1;
				}
					themoves[i] = themoves[i].substring(idx);	//strip move number
					break;
				}
			}
			if (!found) {
				continue;
			}
		}
		tmp[tmpidx] = themoves[i];
		if (tmpidx == 1) {	//black's move or last move
			var move = new Move(tmp[0], tmp[1]);
			this.moves[this.moves.length] = move;
			tmpidx = 0;
			tmp = new Array();
			tmp[1] = null;
		}
		else {
			tmpidx = 1;
		}
	}

	if (tmp[0] || tmp[1]) {
		var move = new Move(tmp[0], tmp[1]);
		this.moves[this.moves.length] = move;
	}

	this.nextMove = function() {
		var rtrn = null;
		try{
			if (this.skip) {
				this.skip = 0;
				rtrn = new Array(this.moves[this.currentMove].black,
													'black');
				this.currentMove++;
			}
			else {
				this.skip = 1;
				rtrn = new Array(this.moves[this.currentMove].white,
											'white');
			}

			if (rtrn[0] == null || rtrn[0].length == 0)
				rtrn = null;
			return rtrn;
		}
		catch (e) {
			return null;
		}
	};

	this.getComment = function(move, idx) {
		var i = this.pgnStripped.indexOf(move,idx);
		if (i == -1) {
			//throw("getComment error, could not find move '"
			//				+move+"'"+", with index '"+idx+"'");
			return [null,idx];
		}

		for (var j=i+move.length;j<this.pgnStripped.length;j++) {
			var c = this.pgnStripped.charAt(j);
			switch (c) {
				case ' ':
					break;
				case '_':	//found comment
					for (var k=j;k<this.pgnStripped.length;k++) {
						var c2 = this.pgnStripped.charAt(k);
						switch (c2) {
							case '_':	//found comment
								break;
							default:	//no comment
								// we might have many comments separated with spaces
								// as we strip all double spaces to single ones we
								// can just check for the next char being '_'
								if (this.pgnStripped.length>k+1
									 	&& this.pgnStripped.charAt(k+1) == '_') {
									continue;
								}
								return [this.pgnRaw.substring(j,k),k];
						}
					}
					break;
				default:	//no comment
					return [null,idx];
			}
		}
		return [null,idx];
	};
};

function Move(white, black) {
	this.white = white;
	this.black = black;

	this.toString = function() {
		return this.white+" "+this.black;
	};
};

/*
	Strip game comments from a PGN string. If second
	parameter set false true then comments will be replaced
	by an underscore.
*/
function stripIt(val, strip) {
	var count = 0;
	var out = new Array();
	for (var i=0;i<val.length;i++) {
		var c = val.charAt(i);
		switch (c) {
			case '(':
				if (!strip) {
					out[out.length] = '_';
				}
				count++;
				break;
			case '{':
				if (!strip) {
					out[out.length] = '_';
				}
				count++;
				break;
			case '}':
				count--;
				if (!strip) {
					out[out.length] = '_';
				}
				break;
			case ')':
				count--;
				if (!strip) {
					out[out.length] = '_';
				}
				break;
			case '\t':
				out[out.length] = ' ';
				break;
			default:
				if (count > 0) {
					if (!strip) {
						out[out.length] = '_';
					}
				}
				else {
					out[out.length] = c;
				}
		}
	}
	return out.join("");
};

function isPGNBroken(val) {
	var pCount = 0;
	var cCount = 0;
	var lastOne = "";
	for (var i=0;i<val.length;i++) {
		var c = val.charAt(i);
		switch (c) {
			case '(':
				pCount++;
				lastOne = "p";
				break;
			case ')':
				// closing a non-existent curly brace
				if (pCount == 0)
					return false;
				// closing a curly instead of a parenthesis
				if (lastOne == "c")
					return false;
				lastOne = "";
				pCount--;
				break;
			case '{':
				cCount++;
				lastOne = "c";
				break;
			case '}':
				// closing a non-existent curly brace
				if (cCount == 0)
					return false;
				// if we're closing a parenthesis instead of a curly
				if (lastOne == "p")
					return false;
				lastOne = "";
				cCount--;
				break;
		}
	}
}

function stripItBroken(val, strip) {
	var count = 0;
	var out = new Array();
	/*
		At one point chesspastebin.com started getting cames
		with invalid PGNs, mostly in the form
		{ comment comment ( something between starting brackets}.
		As you can see, the ( is not closed.
		isOpen and isCurlyO are just for that to take normal
		guesses in that kind of situations.
	*/
	var isOpen = false;
	var isCurlyO = false;
	var curlyOpenedFst = false;
	for (var i=0;i<val.length;i++) {
		var c = val.charAt(i);
		switch (c) {
			case '(':
				if (!strip) {
					out[out.length] = '_';
				}
				count++;
				if (isOpen) {
					 	count--;
				}
				isOpen = true;
				break;
			case '{':
				isCurlyO = true;
				if (!strip) {
					out[out.length] = '_';
				}
				count++;
				if (!isOpen)
					 curlyOpenedFst=true;
				break;
			case '}':
				if (isOpen && isCurlyO && curlyOpenedFst) {
					// lets close the open (
					count--;
					isOpen = false;
				}
				isCurlyO = false;
				curlyOpenedFst = false;
				count--;
				if (!strip) {
					out[out.length] = '_';
				}
				break;
			case ')':
				if (isOpen) {
					 count--;
					 if (!strip) {
						 out[out.length] = '_';
					 }
					 isOpen = false;
				}
				break;
			case '\t':
				out[out.length] = ' ';
				break;
			default:
				if (count > 0) {
					if (!strip) {
						out[out.length] = '_';
					}
				}
				else {
					out[out.length] = c;
				}
		}
	}
	return out.join("");
};
<commit_msg>Support singleline comments<commit_after>/**
 * Copyright 2008 Toomas Römer
 *
 * Licensed under the Apache License, Version 2.0 (the "License")
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
**/

/*
	Representation of the PGN format. Different meta information
	about the actual game(s) plus the moves and result of the game.
*/
function Pgn(pgn) {
	// properties of the game eg players, ELOs etc
	this.props = new Object();
	this.validProps = ['Event','Site','Date','Round',
								'White','Black','Result','FEN',
								'WhiteElo','BlackElo','TimeControl'];
	// the moves, one move contains the black and white move
	this.moves = new Array();
	// the current move in the game
	this.currentMove = 0;
	// for outputting white and black moves separately
	this.skip = 0;

	this.pgnOrig = pgn;

        // strip newlines
        // also strip empty lines
        // also strip lines that are single line comments
        var pgnLines = pgn.split("\n");
        var newPgnLines = Array();
        for (var i = 0; i < pgnLines.length;i++) {
          if (pgnLines[i].trim().length == 0 || pgnLines[i].trim().charAt(0) == ';')
            continue;

          newPgnLines.push(pgnLines[i]);
        }
        pgn = newPgnLines.join(" ");

	// replace dollar signs
	//"!", "?", "!!", "!?", "?!", and "??"
	pgn = pgn.replace(/\ \$1[0-9]*/g, "!");
	pgn = pgn.replace(/\ \$2[0-9]*/g, "?");
	pgn = pgn.replace(/\ \$3[0-9]*/g, "!!");
	pgn = pgn.replace(/\ \$4[0-9]*/g, "??");
	pgn = pgn.replace(/\ \$5[0-9]*/g, "!?");
	pgn = pgn.replace(/\ \$6[0-9]*/g, "?!");
	pgn = pgn.replace(/\ \$[0-9]+/g, "");

	// make double spaces to single spaces
	pgn = pgn.replace(/\s+/g,' ');

	this.pgn = pgn;
	this.pgnRaw = pgn;
	if (isPGNBroken(pgn))
		this.pgnStripped = stripItBroken(pgn);
	else
		this.pgnStripped = stripIt(pgn);

	/* constructor */

	// strip comments
	if (isPGNBroken(pgn))
		this.pgn = stripItBroken(pgn,true);
	else
		this.pgn = stripIt(pgn,true);

	// Match all properties
	var reprop = /\[([^\]]*)\]/gi;
	var matches = this.pgn.match(reprop);
	if (matches) {
		// extract information from each matched property
		 for(var i = 0;i < matches.length; i++) {
			 // lose the brackets
			 tmpMatches = matches[i].substring(1, matches[i].length-1);
			 // split by the first space
			 var key = tmpMatches.substring(0, tmpMatches.indexOf(" "));
			 var value = tmpMatches.substring(tmpMatches.indexOf(" ")+1);
			 if (value.charAt(0) == '"')
				 value = value.substr(1);
			 if (value.charAt(value.length-1) == '"')
				 value = value.substr(0, value.length-1);

			 this.props[key] = value;
			 this.pgn = this.pgn.replace(matches[i], "");
		 }
	}

	// remove the properties
	this.pgn = this.pgn.replace(/\[[^\]]*\]/g,'');
	//trim
	this.pgn = this.pgn.replace(/^\s+|\s+$/g, '');

	var gameOverre = new Array(
		/1\/2-1\/2/,
		/0-1/,
		/1-0/,
		/\*/
	);

	// the moves;
	var themoves = this.pgn.split(" ");
	var tmp = new Array();
	tmp[1] = null;
	var tmpidx = 0;	//make this 1 if FEN and black to move
	if (this.props["FEN"]) {
		var fen = this.props['FEN'].split(/\/| /g);
		if (fen[8] == 'b') {
			tmpidx = 1;
			this.skip = 1;
		}
	}

	if (themoves.length>0 && themoves[themoves.length-1] == "...") {
		 themoves = themoves.slice(0, themoves.length-1);
	}

	var sizeOfTheMoves = themoves.length;
	if (themoves.length>0) {
		for (var i=0;i<gameOverre.length;i++) {
			if (themoves[themoves.length-1].match(gameOverre[i])) {
				sizeOfTheMoves = themoves.length-1;
				continue;
			}
		}
	}

	for (var i=0;i<sizeOfTheMoves;i++) {	//don't handle game end bit
		if (themoves[i]) {
			themoves[i] = themoves[i].replace(/^\s+|\s+$/g, '');
		}

		if (!themoves[i]) {
			continue;
		}

		if (themoves[i].indexOf("-") != -1
			 && !/[0|o]-[0|o]/i.test(themoves[i])
			 && !/[0|o]-[0|o]-[0|o]/i.test(themoves[i])
			) {
			var tmp2 = themoves[i].split("-");
			var matches = tmp2[0].match(/[0-9]*?\.?([A-Z])/);
			var newMove;
			if (matches != null) {
				 // we can just replace the - with nothing
				 newMove  = themoves[i].replace("-","");
			}
			else {
				matches = tmp2[0].match(/[0-9]+\./);
				if (matches) {
					newMove = matches[0]+tmp2[1];
				}
				else {
					newMove = tmp2[1];
				}
			}
			themoves[i] = newMove;
		}
		var c = themoves[i].charAt(0);
		if (c >= '1' && c <= '9') {	//move number
			c = themoves[i].charAt(themoves[i].length-1);
			if (c == '.') {	//ends with . so nothing but a move
				continue;
			}
			var found = false;
			for (var j=0;j<themoves[i].length;j++) {
				c = themoves[i].charAt(j);
				if (c >= '0' && c <= '9') {
					continue;
				}
				else {
					found = true;
					var idx = j;
					// 6.0-0 goes wrong as 0 is used for castling
					if (!(themoves[i].charAt(j) >= '0' && themoves[i].charAt(j)<='9')) {
						 idx = j+1;
				}
					themoves[i] = themoves[i].substring(idx);	//strip move number
					break;
				}
			}
			if (!found) {
				continue;
			}
		}
		tmp[tmpidx] = themoves[i];
		if (tmpidx == 1) {	//black's move or last move
			var move = new Move(tmp[0], tmp[1]);
			this.moves[this.moves.length] = move;
			tmpidx = 0;
			tmp = new Array();
			tmp[1] = null;
		}
		else {
			tmpidx = 1;
		}
	}

	if (tmp[0] || tmp[1]) {
		var move = new Move(tmp[0], tmp[1]);
		this.moves[this.moves.length] = move;
	}

	this.nextMove = function() {
		var rtrn = null;
		try{
			if (this.skip) {
				this.skip = 0;
				rtrn = new Array(this.moves[this.currentMove].black,
													'black');
				this.currentMove++;
			}
			else {
				this.skip = 1;
				rtrn = new Array(this.moves[this.currentMove].white,
											'white');
			}

			if (rtrn[0] == null || rtrn[0].length == 0)
				rtrn = null;
			return rtrn;
		}
		catch (e) {
			return null;
		}
	};

	this.getComment = function(move, idx) {
		var i = this.pgnStripped.indexOf(move,idx);
		if (i == -1) {
			//throw("getComment error, could not find move '"
			//				+move+"'"+", with index '"+idx+"'");
			return [null,idx];
		}

		for (var j=i+move.length;j<this.pgnStripped.length;j++) {
			var c = this.pgnStripped.charAt(j);
			switch (c) {
				case ' ':
					break;
				case '_':	//found comment
					for (var k=j;k<this.pgnStripped.length;k++) {
						var c2 = this.pgnStripped.charAt(k);
						switch (c2) {
							case '_':	//found comment
								break;
							default:	//no comment
								// we might have many comments separated with spaces
								// as we strip all double spaces to single ones we
								// can just check for the next char being '_'
								if (this.pgnStripped.length>k+1
									 	&& this.pgnStripped.charAt(k+1) == '_') {
									continue;
								}
								return [this.pgnRaw.substring(j,k),k];
						}
					}
					break;
				default:	//no comment
					return [null,idx];
			}
		}
		return [null,idx];
	};
};

function Move(white, black) {
	this.white = white;
	this.black = black;

	this.toString = function() {
		return this.white+" "+this.black;
	};
};

/*
	Strip game comments from a PGN string. If second
	parameter set false true then comments will be replaced
	by an underscore.
*/
function stripIt(val, strip) {
	var count = 0;
	var out = new Array();
	for (var i=0;i<val.length;i++) {
		var c = val.charAt(i);
		switch (c) {
			case '(':
				if (!strip) {
					out[out.length] = '_';
				}
				count++;
				break;
			case '{':
				if (!strip) {
					out[out.length] = '_';
				}
				count++;
				break;
			case '}':
				count--;
				if (!strip) {
					out[out.length] = '_';
				}
				break;
			case ')':
				count--;
				if (!strip) {
					out[out.length] = '_';
				}
				break;
			case '\t':
				out[out.length] = ' ';
				break;
			default:
				if (count > 0) {
					if (!strip) {
						out[out.length] = '_';
					}
				}
				else {
					out[out.length] = c;
				}
		}
	}
	return out.join("");
};

function isPGNBroken(val) {
	var pCount = 0;
	var cCount = 0;
	var lastOne = "";
	for (var i=0;i<val.length;i++) {
		var c = val.charAt(i);
		switch (c) {
			case '(':
				pCount++;
				lastOne = "p";
				break;
			case ')':
				// closing a non-existent curly brace
				if (pCount == 0)
					return false;
				// closing a curly instead of a parenthesis
				if (lastOne == "c")
					return false;
				lastOne = "";
				pCount--;
				break;
			case '{':
				cCount++;
				lastOne = "c";
				break;
			case '}':
				// closing a non-existent curly brace
				if (cCount == 0)
					return false;
				// if we're closing a parenthesis instead of a curly
				if (lastOne == "p")
					return false;
				lastOne = "";
				cCount--;
				break;
		}
	}
}

function stripItBroken(val, strip) {
	var count = 0;
	var out = new Array();
	/*
		At one point chesspastebin.com started getting cames
		with invalid PGNs, mostly in the form
		{ comment comment ( something between starting brackets}.
		As you can see, the ( is not closed.
		isOpen and isCurlyO are just for that to take normal
		guesses in that kind of situations.
	*/
	var isOpen = false;
	var isCurlyO = false;
	var curlyOpenedFst = false;
	for (var i=0;i<val.length;i++) {
		var c = val.charAt(i);
		switch (c) {
			case '(':
				if (!strip) {
					out[out.length] = '_';
				}
				count++;
				if (isOpen) {
					 	count--;
				}
				isOpen = true;
				break;
			case '{':
				isCurlyO = true;
				if (!strip) {
					out[out.length] = '_';
				}
				count++;
				if (!isOpen)
					 curlyOpenedFst=true;
				break;
			case '}':
				if (isOpen && isCurlyO && curlyOpenedFst) {
					// lets close the open (
					count--;
					isOpen = false;
				}
				isCurlyO = false;
				curlyOpenedFst = false;
				count--;
				if (!strip) {
					out[out.length] = '_';
				}
				break;
			case ')':
				if (isOpen) {
					 count--;
					 if (!strip) {
						 out[out.length] = '_';
					 }
					 isOpen = false;
				}
				break;
			case '\t':
				out[out.length] = ' ';
				break;
			default:
				if (count > 0) {
					if (!strip) {
						out[out.length] = '_';
					}
				}
				else {
					out[out.length] = c;
				}
		}
	}
	return out.join("");
};
<|endoftext|>


<commit_before>/* line-store.js
 *
 * the store to put track lines into
 * different stores subtly alter the physics
 * so there needs to be old versions to remain backwards compatible
 */

var _ = require('lodash');

var LINE = require('./line').LINE;

var { Grid, GridV62, GridV61 } = require('./grid');

const GRID_SIZE = 14;

/* LineStore
 * - basic line store, no grid
 *
 * public:
 * - lines
 * - addLine(line)
 * - removeLine(line)
 * - getLines(x1, y1, x2 | r, [y2])
 * - selectCollidingLines(x, y, handler(line))
 */
class LineStore {
  constructor() {
    // if performance problems, will make this array sorted
    this.lines = [];
  }

  addLine(line) {
    this.lines.push(line);
  }

  removeLine(line) {
    this.lines = _.without(this.lines, line);
  }

  // returns an array of lines in this bounding box or radius
  getLines(x1, y1, x2, y2) {
    if (y2 === undefined) {
      let r = x2;
      return this.getLinesInRadius(x1, y1, r);
    }
    return this.getLinesInBox(x1, y1, x2, y2);
  }

  getLinesInRadius(x, y, r) {
    return this.lines.filter(line => line.inCircle(x, y, r));
  }

  getLinesInBox(x1, y1, x2, y2) {
    return this.lines.filter(line => line.inBox(x1, y1, x2, y2));
  }

  // does something with each line around (x, y)
  // like do collisions on points
  // the ordering of the lines affects the physics
  selectCollidingLines(x, y, handler) {
    this.lines.forEach((line) => {
      if (line.type !== LINE.SCENERY) {
        handler(line);
      }
    });
    // return this.lines
  }

}

/* GridStore
 * - revision 6.2
 *
 * public:
 * - lines
 * - addLine(line) <- this adds property 'cells' to line
 * - removeLine(line)
 * - getLines(x1, y1, x2 | r, [y2])
 * - selectCollidingLines(x, y, handler(line))
 *
 * private:
 * - grid
 */
class GridStore extends LineStore {
  constructor() {
    super();

    // for solid lines
    this.solidGrid = new GridV62(GRID_SIZE, true);

    // for all lines
    // darn there was a clever data structure for this stuff what was it
    // i think it was 2d sorted arrays?
    // i'll do it later
    this.grid = new Grid(GRID_SIZE * 4, false);
  }

  addLine(line) {
    super.addLine(line);

    this.grid.addLine(line);

    if (line.isSolid) {
      this.solidGrid.addLine(line);
    }
  }

  removeLine(line) {
    super.removeLine(line);

    this.grid.removeLine(line);

    if (line.isSolid) {
      this.solidGrid.removeLine(line);
    }
  }

  getSolidLinesAt(x, y, debug = false) {
    let cellPos = this.solidGrid.getCellPos(x, y);
    let range = [-1, 0, 1];
    let lines = [];

    _.forEach(range, i =>
      _.forEach(range, j => {
        let cPos = {x: i + cellPos.x, y: j + cellPos.y };
        _.forEach(this.solidGrid.getLinesFromCell(cPos), line =>
          lines.push(debug ? { line: line, cellPos: cPos } : line)
        );
      })
    );

    return lines;
  }

}

/* OldGridStore
 * - revision 6.1
 * - grid bugs as feature
 *
 * public:
 * - lines
 * - addLine(line)
 * - removeLine(line)
 * - getLines(x1, y1, x2 | r, [y2])
 * - selectCollidingLines(x, y, handler(line))
 *
 * private:
 * - grid
 */
class OldGridStore extends GridStore {
  constructor() {
    super();

    this.solidGrid = new GridV61(GRID_SIZE, true);
  }

}

module.exports = {
  GRID_SIZE: GRID_SIZE,
  LineStore: LineStore,
  GridStore: GridStore,
  OldGridStore: OldGridStore
};
<commit_msg>Update line-store.js, replace native filter with _.filter + replace _.forEach with for-loop + cache solid lines<commit_after>/* line-store.js
 *
 * the store to put track lines into
 * different stores subtly alter the physics
 * so there needs to be old versions to remain backwards compatible
 */

var _ = require('lodash');

var { Grid, GridV62, GridV61, getCellHash } = require('./grid');

const GRID_SIZE = 14;

/* LineStore
 * - basic line store, no grid
 *
 * public:
 * - lines
 * - addLine(line)
 * - removeLine(line)
 * - getLines(x1, y1, x2 | r, [y2])
 * - selectCollidingLines(x, y, handler(line))
 */
class LineStore {
  constructor() {
    // if performance problems, will make this array sorted
    this.lines = [];
  }

  addLine(line) {
    this.lines.push(line);
  }

  removeLine(line) {
    this.lines = _.without(this.lines, line);
  }

  // returns an array of lines in this bounding box or radius
  getLines(x1, y1, x2, y2) {
    if (y2 === undefined) {
      let r = x2;
      return this.getLinesInRadius(x1, y1, r);
    }
    return this.getLinesInBox(x1, y1, x2, y2);
  }

  getLinesInRadius(x, y, r) {
    return _.filter(this.lines, line => line.inCircle(x, y, r));
  }

  getLinesInBox(x1, y1, x2, y2) {
    return _.filter(this.lines, line => line.inBox(x1, y1, x2, y2));
  }

  // the ordering of the lines affects the physics
  getSolidLinesAt(x, y, debug = false) {
    return _.filter(this.lines, line => line.isSolid);
  }

}

/* GridStore
 * - revision 6.2
 *
 * public:
 * - lines
 * - addLine(line) <- this adds property 'cells' to line
 * - removeLine(line)
 * - getLines(x1, y1, x2 | r, [y2])
 * - selectCollidingLines(x, y, handler(line))
 *
 * private:
 * - grid
 */
class GridStore extends LineStore {
  constructor() {
    super();

    // for solid lines
    this.solidGrid = new GridV62(GRID_SIZE, true);

    // for all lines
    // darn there was a clever data structure for this stuff what was it
    // i think it was 2d sorted arrays?
    // i'll do it later
    this.grid = new Grid(GRID_SIZE * 4, false);

    // for some reason, querying the grid is time consuming, so caching improves performance
    this.resetSolidLinesCache();
  }

  addLine(line) {
    super.addLine(line);

    this.grid.addLine(line);

    if (line.isSolid) {
      this.solidGrid.addLine(line);
    }
  }

  removeLine(line) {
    super.removeLine(line);

    this.grid.removeLine(line);

    if (line.isSolid) {
      this.solidGrid.removeLine(line);
    }
  }

  getSolidLinesAt(x, y, debug = false) {
    let cellPos = this.solidGrid.getCellPos(x, y);

    let key = getCellHash(cellPos.x, cellPos.y);
    let lines = this.solidLinesCache[key];
    if (lines) {
      return lines;
    }
    lines = [];

    let addLine = line => lines.push(line);

    // normally i would avoid for loops but lots of iterations here
    for (let i = -1; i <= 1; i++) {
      for (let j = -1; j <= 1; j++) {
        let lines = this.solidGrid.getLinesFromCell(i + cellPos.x, j + cellPos.y);
        for (let k = 0; k < lines.length; k++) {
          addLine(lines[k]);
        }
      }
    }

    this.solidLinesCache[key] = lines;

    return lines;
  }

  getLines(cPos) {
    return this.solidGrid.getLinesFromCell(cPos);
  }

  resetSolidLinesCache() {
    this.solidLinesCache = Object.create(null);
  }

}

/* OldGridStore
 * - revision 6.1
 * - grid bugs as feature
 *
 * public:
 * - lines
 * - addLine(line)
 * - removeLine(line)
 * - getLines(x1, y1, x2 | r, [y2])
 * - selectCollidingLines(x, y, handler(line))
 *
 * private:
 * - grid
 */
class OldGridStore extends GridStore {
  constructor() {
    super();

    this.solidGrid = new GridV61(GRID_SIZE, true);
  }

}

module.exports = {
  GRID_SIZE: GRID_SIZE,
  LineStore: LineStore,
  GridStore: GridStore,
  OldGridStore: OldGridStore
};
<|endoftext|>


<commit_before>var mdns = require('mdns2');
var fs = require('fs');
var path = require('path');
var os = require('os');

// private functions and variables
var addresses = [];
// controls how service names are resolved to ip addresses
// see mdns2
var mdnsResolverSequence = [
  mdns.rst.DNSServiceResolve(),
  mdns.rst.getaddrinfo({ families: [4] })
];

//credits: http://stackoverflow.com/questions/10750303/how-can-i-get-the-local-ip-address-in-node-js
function setMyAddresses() {
  var interfaces = os.networkInterfaces();
  for (var k in interfaces) {
    for (var k2 in interfaces[k]) {
      var address = interfaces[k][k2];
      if (address.family === 'IPv4' && !address.internal) {
        addresses.push(address.address);
      }
    }
  }
}

// class
function EdisonMDNS() {
  "use strict";
}

// public variables
EdisonMDNS.prototype.components = ["discovery"];
EdisonMDNS.prototype.name = "edisonMdns";
EdisonMDNS.prototype.type = "local";

// public functions
EdisonMDNS.prototype.advertiseServices = function (serviceDirPath) {
	fs.readdir(serviceDirPath, function (err, serviceSpecs) {
		for (var i in serviceSpecs) {
			var serviceSpec = JSON.parse(fs.readFileSync(path.join(serviceDirPath, serviceSpecs[i])));
			var ad = mdns.createAdvertisement(serviceSpec.type, serviceSpec.port,
					{txtRecord: serviceSpec.properties, name: serviceSpec.name});
			//var ad = mdns.createAdvertisement(mdns.tcp('http'), 4321);
			ad.start();
			console.log("Advertised service specified in " + serviceSpecs[i]);
		}
	});
};

EdisonMDNS.prototype.discoverServices = function (serviceType, callback) {
	// todo: needs fix: multiple subtypes in the serviceType causes errors.
	// make sure your serviceType contains only *one* subtype
	var browser = mdns.createBrowser(serviceType, { resolverSequence: mdnsResolverSequence });

	browser.on('serviceUp', function(service) {

		callback(service);
	});

	browser.start();
};

EdisonMDNS.prototype.findService = function () {

};

// export the class
module.exports = EdisonMDNS;<commit_msg>Filter duplicate services. Report a service only if it is alive.<commit_after>var mdns = require('mdns2');
var fs = require('fs');
var path = require('path');
var os = require('os');
var net = require('net');

var LOCAL_IP_STRING = "local";

// private functions and variables
var myaddresses = [];

// service cache to remove duplicate services
var serviceCache = {};

// controls how service names are resolved to ip addresses
// see mdns2
var mdnsResolverSequence = [
  mdns.rst.DNSServiceResolve(),
  mdns.rst.getaddrinfo({ families: [4] })
];

//credits: http://stackoverflow.com/questions/10750303/how-can-i-get-the-local-ip-address-in-node-js
function setMyAddresses() {
  var interfaces = os.networkInterfaces();
  for (var k in interfaces) {
    for (var k2 in interfaces[k]) {
      var address = interfaces[k][k2];
      if (address.family === 'IPv4' && !address.internal) {
        myaddresses.push(address.address);
      }
    }
  }
}

function resolveToLocal(address) {
  "use strict";

  if (!address) {
    return address;
  }

  var isLocal = myaddresses.some(function (myaddress) {
    if (address === myaddress) {
      return true;
    }

    return false;

  });

  if (isLocal) {
    return LOCAL_IP_STRING;
  }

  return address;
}

// class
function EdisonMDNS() {
  "use strict";
}

// public variables
EdisonMDNS.prototype.components = ["discovery"];
EdisonMDNS.prototype.name = "edisonMdns";
EdisonMDNS.prototype.type = "local";

// public functions
EdisonMDNS.prototype.advertiseServices = function (serviceDirPath) {
	fs.readdir(serviceDirPath, function (err, serviceSpecs) {
		for (var i in serviceSpecs) {
			var serviceSpec = JSON.parse(fs.readFileSync(path.join(serviceDirPath, serviceSpecs[i])));
			var ad = mdns.createAdvertisement(serviceSpec.type, serviceSpec.port,
					{txtRecord: serviceSpec.properties, name: serviceSpec.name});
			//var ad = mdns.createAdvertisement(mdns.tcp('http'), 4321);
			ad.start();
			console.log("Advertised service specified in " + serviceSpecs[i]);
		}
	});
};

EdisonMDNS.prototype.discoverServices = function (serviceType, callback) {
  setMyAddresses();
  console.log(myaddresses);

	// todo: needs fix: multiple subtypes in the serviceType causes errors.
	// make sure your serviceType contains only *one* subtype
	var browser = mdns.createBrowser(serviceType, { resolverSequence: mdnsResolverSequence });

  browser.on('serviceUp', function(service) {

    if (!service.addresses) {
      return;
    }

    var address = service.addresses[0];
    var ip = resolveToLocal(address);

    console.log(address);
    console.log(ip);

    if (!serviceCache[service.name + ip + service.port]) {
      if (service.type.protocol === "tcp") {
        net.createConnection(service.port, address).on("connect", function() {
          serviceCache[service.name + ip + service.port] = {};
          callback(service);
          console.log("success");
        }).on("error", function(e) {
            // do nothing
            console.log(e);
          });
      } else {
        serviceCache[service.name + address + service.port] = {};
        callback(service);
      }
    }

  });

  browser.on('serviceDown', function(service) {
    "use strict";

    if (!service.addresses) {
      return;
    }

    service.addresses.forEach(function (address, i, thisArray) {
      "use strict";
      var ip = resolveToLocal(address);
      delete serviceCache[service.name + ip + service.port];
    });

  });

	browser.start();

};

EdisonMDNS.prototype.findService = function () {

};

// export the class
module.exports = EdisonMDNS;<|endoftext|>


<commit_before>Polymer({

  is: 'polymer-d3',

  properties: {
    // List of available charts
    availableCharts: {
      type: Array,
      value: function() {
        // This list if used when available charts aren' fed from zeppelin-viewer
        // Callback defined in charts and are called after the chart is initated
        // using PolymerD3.utilities.attachElement
        // examples => @{{this._selectedChanged}}
        // barchart.js@{{initStackedBarChart}}
        if (!this.availableCharts) {
          return [{
            label: 'Stacked Bar Chart',
            icon: 'chart:stacked-bar-chart',
            element: 'bar-chart',
            callBack: 'initStackedBarChart'
          }, {
            label: 'Grouped Bar Chart',
            icon: 'chart:grouped-bar-chart',
            element: 'bar-chart',
            callBack: 'initGroupedBarChart'
          }, {
            label: 'Waterfall Chart',
            icon: 'chart:waterfall-chart',
            element: 'bar-chart',
            callBack: 'initWaterfallChart'
          }, {
            label: 'Difference',
            icon: 'chart:difference-chart',
            element: 'bar-chart',
            callBack: 'initDiffrenceChart'
          }, {
            label: 'Pie Chart',
            icon: 'chart:pieChart',
            element: 'pie-chart',
            callBack: 'setPieSettings'
          }, {
            label: 'Heat Map',
            icon: 'chart:heatMap',
            element: 'bar-chart',
            callBack: 'initHeatMap'
          }, {
            label: 'Area Chart',
            icon: 'chart:area-chart',
            element: 'area-chart',
            callBack: 'setAreaSettings'
          }, {
            label: 'Sankey Chart',
            icon: 'chart:sankey-chart',
            element: 'sankey-chart',
            callBack: 'setSankeySettings'
          }, {
            label: 'Radar Chart',
            icon: 'chart:radar-chart',
            element: 'radar-chart',
            // callBack: 'radar'
          }, {
            label: 'Scatter Plot Chart',
            icon: 'chart:scatter-plot',
            element: 'scatter-plot'
          }, {
            label: 'Calendar View Chart',
            icon: 'chart:calendar-chart',
            element: 'calendar-chart'
          }, {
            label: 'Pareto Chart',
            icon: 'chart:calendar-chart',
            element: 'pareto-chart'
          }];
        }
      }
    },
    // Object desctibing selected chart type
    selectedChart: {
      type: Object,
      value: () => { return {};}
    },
    selectedChartObj: {
      type: Object,
      value: () => { return {};}
    },
    // Flag to display settngs components
    settingsVisible: {
      type: Boolean,
      value: false
    },
    // Inputs
    externals: {
      type: Array,
      value: () => { return [];}
    },
    inputs: {
      type:Array,
      notify: true,
      value: () => {return [];}
    },
    // Data
    source: {
      type: Array,
      value: () => {return [];}
    },

    // settings
    settings: {
      type: Array,
      value: () => {return [];}
    },

    // State container
    stateContainer: {
      type: Object,
      value: () => {return {};}
    },
    editMode: {
      type: Boolean,
      value: false
    },
    legendSettingsFlag: {
      type: Boolean,
      value: false
    },
    legendSettings: {
      type: Object,
      value: () => {return {};}
    }
  },

  observers: [
    '_selectedChanged(selectedChart)',
    '_inputsChanged(inputs.*)',
    '_modeObserver(editMode)',
  ],

  // edit mode
  _modeObserver: function(editMode) {
    if (!editMode) {
      if (this.selectedChartObj && this.selectedChartObj.extractData) {
        this.selectedChartObj.viewMode = true;
      }
      this.set('settingsVisible', false);
    } else {
      if (this.selectedChartObj && this.selectedChartObj.extractData) {
        this.selectedChartObj.viewMode = false;
      }
    }
  },

  // on inputs change
  _inputsChanged: function(i) {
    if (this.selectedChart && this.selectedChart.element) {
      this.$$(this.selectedChart.element).draw();
    }
  },

  // on selected chart changed
  // is also used to draw first chart
  _selectedChanged: function(selectedChart) {
    let elem;
    if (this.selectedChartObj && !PolymerD3.utilities.isEmptyObject(this.selectedChartObj)) {
      this.selectedChartObj.chartInfo.settings = this.selectedChartObj.extractData();
    }
    this.set('settingsVisible', true);
    if (selectedChart && !PolymerD3.utilities.isEmptyObject(selectedChart)) {
      this.$$('.chartHolder').innerHTML = '';
      elem = PolymerD3.utilities.attachElement.call(
        this,
        selectedChart.element,
        '.chartHolder',
        selectedChart.callBack
      );

      elem.set('source', this.source);
      elem.set('externals', this.externals);
      this.selectedChartObj = elem;
      this.selectedChartObj.chartInfo = this.selectedChart;
      if (selectedChart.settings) {
        elem.setData(selectedChart.settings);
      }
    }
  },

  // might be dead code
  // not deleted because this is a good utility to merge two objects
  _mergeSettings: function(from, to) {
    let mergeSettings = this._persistData('input', 'selectedValue');
    mergeSettings(from, to);
  },

  // Creates a utility function that
  // copies valueToChange from 'from' to 'to', both are array of objects
  // identifier is the key which uniquely identifies objects
  _persistData: function(identifier, valeToChange) {
    return (from, to) => {
      from.forEach(f => {
        // Short circuits to.loop
        // http://stackoverflow.com/a/2641374/5154397
        to.some(t => {
          if (t[identifier] == f[identifier]) {
            t[valeToChange] = f[valeToChange];
            return true;
          }
        });
      });
    }
  },

  showInputSettings: function() {
    if (this.selectedChartObj) {
      this.selectedChartObj.toggleSettingsVisibility();
    }
  },

  // Bootstraps element as per mode(view/edit)
  // This meathod avoids crazy rwo-way binding side effects
  bootstrapCharts: function(config) {
    // data and externals are always required
    this.set('externals', config.externals);
    this.set('source', config.source);
    if (config.availableCharts) {
      this.availableCharts = config.availableCharts;
    }
    if (config.mode === 'create') {
      // Fresh Polymer d3
      this.set('editMode', true);
    } else {
      this.set('selectedChart', config.selectedChart);
      this.set('settings', config.settings);
      this.set('inputs', config.inputs);
      if (config.mode === 'edit') {
        // Edit mode settings
        this.set('editMode', true);
      } else {
        this.set('editMode', false);
      }
      // Find why legend settings has to added twice
      this.set('legendSettings', config.legendSettings);
      this.selectedChartObj.set('legendSettings', config.legendSettings);
      // To set inputs to selected chart manually
      this.selectedChartObj.set('inputs', config.inputs);
      this.selectedChartObj.draw();
      this.async(() => {
        this.selectedChartObj.chartInfo.settings = this.selectedChartObj.extractData();
        // gives color to selected chart
        if(!this.editMode){
          this.$$('chart-selector').setSelectedChart('[title="' + config.selectedChart.label +'"]');
        }
      }, 500);
    }
  },

  // retrives current state of polymer-d3
  // is used to save data back to zeppelin
  getSettings: function() {
    var selectedChart = this.selectedChart;
    selectedChart.settings = this.selectedChartObj.extractData();
    return {
      selectedChart: selectedChart,
      availableCharts: this.availableCharts
    };
  }
});
<commit_msg>Fix issue in new chart create process<commit_after>Polymer({

  is: 'polymer-d3',

  properties: {
    // List of available charts
    availableCharts: {
      type: Array,
      value: function() {
        // This list if used when available charts aren' fed from zeppelin-viewer
        // Callback defined in charts and are called after the chart is initated
        // using PolymerD3.utilities.attachElement
        // examples => @{{this._selectedChanged}}
        // barchart.js@{{initStackedBarChart}}
        if (!this.availableCharts) {
          return [{
            label: 'Stacked Bar Chart',
            icon: 'chart:stacked-bar-chart',
            element: 'bar-chart',
            callBack: 'initStackedBarChart'
          }, {
            label: 'Grouped Bar Chart',
            icon: 'chart:grouped-bar-chart',
            element: 'bar-chart',
            callBack: 'initGroupedBarChart'
          }, {
            label: 'Waterfall Chart',
            icon: 'chart:waterfall-chart',
            element: 'bar-chart',
            callBack: 'initWaterfallChart'
          }, {
            label: 'Difference',
            icon: 'chart:difference-chart',
            element: 'bar-chart',
            callBack: 'initDiffrenceChart'
          }, {
            label: 'Pie Chart',
            icon: 'chart:pieChart',
            element: 'pie-chart',
            callBack: 'setPieSettings'
          }, {
            label: 'Heat Map',
            icon: 'chart:heatMap',
            element: 'bar-chart',
            callBack: 'initHeatMap'
          }, {
            label: 'Area Chart',
            icon: 'chart:area-chart',
            element: 'area-chart',
            callBack: 'setAreaSettings'
          }, {
            label: 'Sankey Chart',
            icon: 'chart:sankey-chart',
            element: 'sankey-chart',
            callBack: 'setSankeySettings'
          }, {
            label: 'Radar Chart',
            icon: 'chart:radar-chart',
            element: 'radar-chart',
            // callBack: 'radar'
          }, {
            label: 'Scatter Plot Chart',
            icon: 'chart:scatter-plot',
            element: 'scatter-plot'
          }, {
            label: 'Calendar View Chart',
            icon: 'chart:calendar-chart',
            element: 'calendar-chart'
          }, {
            label: 'Pareto Chart',
            icon: 'chart:calendar-chart',
            element: 'pareto-chart'
          }];
        }
      }
    },
    // Object desctibing selected chart type
    selectedChart: {
      type: Object,
      value: () => { return {};}
    },
    selectedChartObj: {
      type: Object,
      value: () => { return {};}
    },
    // Flag to display settngs components
    settingsVisible: {
      type: Boolean,
      value: false
    },
    // Inputs
    externals: {
      type: Array,
      value: () => { return [];}
    },
    inputs: {
      type:Array,
      notify: true,
      value: () => {return [];}
    },
    // Data
    source: {
      type: Array,
      value: () => {return [];}
    },

    // settings
    settings: {
      type: Array,
      value: () => {return [];}
    },

    // State container
    stateContainer: {
      type: Object,
      value: () => {return {};}
    },
    editMode: {
      type: Boolean,
      value: false
    },
    legendSettingsFlag: {
      type: Boolean,
      value: false
    },
    legendSettings: {
      type: Object,
      value: () => {return {};}
    }
  },

  observers: [
    '_selectedChanged(selectedChart)',
    '_inputsChanged(inputs.*)',
    '_modeObserver(editMode)',
  ],

  // edit mode
  _modeObserver: function(editMode) {
    if (!editMode) {
      if (this.selectedChartObj && this.selectedChartObj.extractData) {
        this.selectedChartObj.viewMode = true;
      }
      this.set('settingsVisible', false);
    } else {
      if (this.selectedChartObj && this.selectedChartObj.extractData) {
        this.selectedChartObj.viewMode = false;
      }
    }
  },

  // on inputs change
  _inputsChanged: function(i) {
    if (this.selectedChart && this.selectedChart.element) {
      this.$$(this.selectedChart.element).draw();
    }
  },

  // on selected chart changed
  // is also used to draw first chart
  _selectedChanged: function(selectedChart) {
    let elem;
    if (this.selectedChartObj && !PolymerD3.utilities.isEmptyObject(this.selectedChartObj)) {
      this.selectedChartObj.chartInfo.settings = this.selectedChartObj.extractData();
    }
    this.set('settingsVisible', true);
    if (selectedChart && !PolymerD3.utilities.isEmptyObject(selectedChart)) {
      this.$$('.chartHolder').innerHTML = '';
      elem = PolymerD3.utilities.attachElement.call(
        this,
        selectedChart.element,
        '.chartHolder',
        selectedChart.callBack
      );

      elem.set('source', this.source);
      elem.set('externals', this.externals);
      this.selectedChartObj = elem;
      this.selectedChartObj.chartInfo = this.selectedChart;
      if (selectedChart.settings) {
        elem.setData(selectedChart.settings);
      }
    }
  },

  // might be dead code
  // not deleted because this is a good utility to merge two objects
  _mergeSettings: function(from, to) {
    let mergeSettings = this._persistData('input', 'selectedValue');
    mergeSettings(from, to);
  },

  // Creates a utility function that
  // copies valueToChange from 'from' to 'to', both are array of objects
  // identifier is the key which uniquely identifies objects
  _persistData: function(identifier, valeToChange) {
    return (from, to) => {
      from.forEach(f => {
        // Short circuits to.loop
        // http://stackoverflow.com/a/2641374/5154397
        to.some(t => {
          if (t[identifier] == f[identifier]) {
            t[valeToChange] = f[valeToChange];
            return true;
          }
        });
      });
    }
  },

  showInputSettings: function() {
    if (this.selectedChartObj) {
      this.selectedChartObj.toggleSettingsVisibility();
    }
  },

  // Bootstraps element as per mode(view/edit)
  // This meathod avoids crazy rwo-way binding side effects
  bootstrapCharts: function(config) {
    // data and externals are always required
    this.set('externals', config.externals);
    this.set('source', config.source);
    if (config.availableCharts) {
      this.availableCharts = config.availableCharts;
    }
    if (config.mode === 'create') {
      // Fresh Polymer d3
      this.set('editMode', false);
    } else {
      this.set('selectedChart', config.selectedChart);
      this.set('settings', config.settings);
      this.set('inputs', config.inputs);
      if (config.mode === 'edit') {
        // Edit mode settings
        this.set('editMode', true);
      } else {
        this.set('editMode', false);
      }
      // Find why legend settings has to added twice
      this.set('legendSettings', config.legendSettings);
      this.selectedChartObj.set('legendSettings', config.legendSettings);
      // To set inputs to selected chart manually
      this.selectedChartObj.set('inputs', config.inputs);
      this.selectedChartObj.draw();
      this.async(() => {
        this.selectedChartObj.chartInfo.settings = this.selectedChartObj.extractData();
        // gives color to selected chart
        if(!this.editMode){
          this.$$('chart-selector').setSelectedChart('[title="' + config.selectedChart.label +'"]');
        }
      }, 500);
    }
  },

  // retrives current state of polymer-d3
  // is used to save data back to zeppelin
  getSettings: function() {
    var selectedChart = this.selectedChart;
    selectedChart.settings = this.selectedChartObj.extractData();
    return {
      selectedChart: selectedChart,
      availableCharts: this.availableCharts
    };
  }
});
<|endoftext|>


<commit_before>import _ from 'lodash';

function tableify(obj, columns, parents) {
  const buf = [];
  const type = typeof obj;
  let cols;

  parents = parents || [];

  if (type !== 'object' || obj == null || obj === undefined) {
    // nothing
  } else if (~parents.indexOf(obj)) {
    return '[Circular]';
  } else {
    parents.push(obj);
  }

  if (Array.isArray(obj)) {
    if (Array.isArray(obj[0]) && obj.every(Array.isArray)) {
      buf.push('
', '
');
      cols = [];

      if (!_.isEmpty(obj)) {
        // 2D array is an array of rows
        obj.forEach((row, ix) => {
          cols.push(ix);

          buf.push('
');

          row.forEach((val) => {
            buf.push(`<td${getClass(val)}>`, tableify(val, cols, parents), '	');
          });

          buf.push('
');
        });
      }

      buf.push('
', '
');
    } else if (typeof obj[0] === 'object') {
      buf.push('
', '
', '
');

      // loop through every object and get unique keys
      const keys = {};

      if (!_.isEmpty(obj)) {
        obj.forEach((o) => {
          if (typeof o === 'object' && !Array.isArray(o)) {
            Object.keys(o).forEach((k) => {
              keys[k] = true;
            });
          }
        });
      }

      cols = Object.keys(keys);

      if (!_.isEmpty(cols)) {
        cols.forEach((key) => {
          buf.push(`<th${getClass(obj[0][key])}>`, key, '	');
        });
      }

      buf.push('
', '
', '
');

      if (!_.isEmpty(obj)) {
        obj.forEach((record) => {
          buf.push('
');
          buf.push(tableify(record, cols, parents));
          buf.push('
');
        });
      }

      buf.push('

');
    } else {
      buf.push('
', '
');
      cols = [];

      if (!_.isEmpty(obj)) {
        obj.forEach((val, ix) => {
          cols.push(ix);
          buf.push('
', `<td${getClass(val)}>`, tableify(val, cols, parents), '	', '
');
        });
      }

      buf.push('
', '
');
    }

  } else if (obj && typeof obj === 'object' && !Array.isArray(obj) && !(obj instanceof Date)) {
    if (!columns) {
      buf.push('
');

      Object.keys(obj).forEach((key) => {
        buf.push('
', `<th${getClass(obj[key])}>`, key, '	', `<td${getClass(obj[key])}>`, tableify(obj[key], false, parents), '	', '
');
      });

      buf.push('
');
    } else if (!_.isEmpty(columns)) {
      columns.forEach((key) => {
        if (typeof obj[key] === 'object' && !Array.isArray(obj[key])) {
          buf.push(`<td${getClass(obj[key])}>`, tableify(obj[key], false, parents), '	');
        } else {
          buf.push(`<td${getClass(obj[key])}>`, tableify(obj[key], columns, parents), '	');
        }
      });

    }
  } else {
    buf.push(obj);
  }

  if (type !== 'object' || obj == null || obj === undefined) {
    // nothing
  } else {
    parents.pop(obj);
  }

  return buf.join('');
}

function getClass(obj) {
  return ` class="${
    ((obj && obj.constructor && obj.constructor.name)
      ? obj.constructor.name
      : typeof obj || ''
    ).toLowerCase()
  }${(obj === null)
    ? ' null'
    : ''
  }"`;
}

export default tableify;
<commit_msg>Minor fix in the table visualizer.<commit_after>import _ from 'lodash';

function tableify(obj, columns, parents) {
  const buf = [];
  const type = typeof obj;
  let cols;

  parents = parents || [];

  if (type !== 'object' || obj == null || obj === undefined) {
    // nothing
  } else if (~parents.indexOf(obj)) {
    return '[Circular]';
  } else {
    parents.push(obj);
  }

  if (Array.isArray(obj)) {
    if (Array.isArray(obj[0]) && obj.every(Array.isArray)) {
      buf.push('
', '
');
      cols = [];

      if (!_.isEmpty(obj)) {
        // 2D array is an array of rows
        obj.forEach((row, ix) => {
          cols.push(ix);

          buf.push('
');

          row.forEach((val) => {
            buf.push(`<td${getClass(val)}>`, tableify(val, cols, parents), '	');
          });

          buf.push('
');
        });
      }

      buf.push('
', '
');
    } else if (typeof obj[0] === 'object') {
      buf.push('
', '
', '
');

      // loop through every object and get unique keys
      const keys = {};

      if (!_.isEmpty(obj)) {
        obj.forEach((o) => {
          if (typeof o === 'object' && !Array.isArray(o)) {
            if (!_.isEmpty(o)) {
              Object.keys(o).forEach((k) => {
                keys[k] = true;
              });
            }
          }
        });
      }

      cols = Object.keys(keys);

      if (!_.isEmpty(cols)) {
        cols.forEach((key) => {
          buf.push(`<th${getClass(obj[0][key])}>`, key, '	');
        });
      }

      buf.push('
', '
', '
');

      if (!_.isEmpty(obj)) {
        obj.forEach((record) => {
          buf.push('
');
          buf.push(tableify(record, cols, parents));
          buf.push('
');
        });
      }

      buf.push('

');
    } else {
      buf.push('
', '
');
      cols = [];

      if (!_.isEmpty(obj)) {
        obj.forEach((val, ix) => {
          cols.push(ix);
          buf.push('
', `<td${getClass(val)}>`, tableify(val, cols, parents), '	', '
');
        });
      }

      buf.push('
', '
');
    }

  } else if (obj && typeof obj === 'object' && !Array.isArray(obj) && !(obj instanceof Date)) {
    if (!columns) {
      buf.push('
');

      if (!_.isEmpty(obj)) {
        Object.keys(obj).forEach((key) => {
          buf.push('
', `<th${getClass(obj[key])}>`, key, '	', `<td${getClass(obj[key])}>`, tableify(obj[key], false, parents), '	', '
');
        });
      }

      buf.push('
');
    } else if (!_.isEmpty(columns)) {
      columns.forEach((key) => {
        if (typeof obj[key] === 'object' && !Array.isArray(obj[key])) {
          buf.push(`<td${getClass(obj[key])}>`, tableify(obj[key], false, parents), '	');
        } else {
          buf.push(`<td${getClass(obj[key])}>`, tableify(obj[key], columns, parents), '	');
        }
      });

    }
  } else {
    buf.push(obj);
  }

  if (type !== 'object' || obj == null || obj === undefined) {
    // nothing
  } else {
    parents.pop(obj);
  }

  return buf.join('');
}

function getClass(obj) {
  return ` class="${
    ((obj && obj.constructor && obj.constructor.name)
      ? obj.constructor.name
      : typeof obj || ''
    ).toLowerCase()
  }${(obj === null)
    ? ' null'
    : ''
  }"`;
}

export default tableify;
<|endoftext|>


<commit_before>var primesieve = (function() {
    "use strict";
    var Primesieve = {};
    var primelimit = 0;
    var buffer;
    var primesieve;
    var primesizelimit = 0x800000; // 1 megabyte

    // works with normal arrays, too
    if (typeof Uint32Array === 'undefined') Uint32Array = Array;

    // 30*log(113)/113 see also http://oeis.org/A209883
    var LN_113 = 1.25505871293247979696870747618124469168920275806274;
    // Rosser, J. B. and Schoenfeld, L. "Approximate Formulas for Some
    // Functions of Prime Numbers." Illinois J. Math. 6, 64-97, 1962
    // http://projecteuclid.org/DPubS?service=UI&version=1.0&verb=Display&handle=euclid.ijm/1255631807
    var approx_pi = function(limit){
        // Math.ceil(5*x/(4*Math.log(x))) // would be more exact for large x
        return Math.ceil( (LN_113 * limit) / Math.log(limit) ) + 2;
    };
    var approx_limit = function(prime_pi){
        if(prime_pi < 10){
          return 30;
        }
        // see first term of expansion of li(x)-li(2)
        return Math.ceil( prime_pi * ( Math.log( prime_pi * Math.log( prime_pi))));
    };
    var isInt = function(x) {
        if (isNaN(x)) {
            return false;
        }
        if (x > -9007199254740992 && x < 9007199254740992 && Math.floor(
                x) == x) {
            return true;
        }
    };
    var clear = function(where) {
        primesieve[where >>> 5] &= ~((1 << (31 - (where & 31))) );
    };
    var get = function(where) {
        return ((primesieve[where >>> 5] >>> ((31 - (where & 31)))) & 1);
    };
    var nextset = function(from) {
        while (from < primelimit && !get(from)) {
            from++;
        }
        if (from === primelimit && !get(from)) {
            return -1;
        }
        return from;
    };
    var prevset = function(from) {
        while (from >= 0 && !get(from)) {
            from--;
        }
        if (from == 0 && !get(from)) {
            return -1;
        }
        return from;
    };
    var fillsieve = function(n) {
        var k, r, j;
        n = n + 1;
        primelimit = n - 1;
        k = Math.ceil(n / 32);
        buffer = new ArrayBuffer(k * 4);
        primesieve = new Uint32Array(buffer);
        while (k--) {
            primesieve[k] = 0xffffffff;
        }
        clear(0);
        clear(1);
        for (k = 4; k < n; k += 2) {
            clear(k);
        }
        r = Math.floor(Math.sqrt(n));
        k = 0;
        while (k < n) {
            k = nextset(k + 1);
            if (k > r || k < 0) {
                break;
            }
            for (j = k * k; j < n; j += 2 * k) {
                clear(j);
            }
        }
    };
    var E_SUCCESS = 0;
    var E_ARG_NO_INT = 1;
    var E_ARG_TOO_LOW = 2;
    var E_ARG_TOO_HIGH = 3;
    var E_ABOVE_LIMIT = 4;
    Primesieve.error = 0;
    Primesieve.strerror = function(){
        var strerrors = [
            "Success",
            "Argument not an integer",
            "Argument too low",
            "Argument too high",
            "Prime wanted is higher than the limit ",
            "Unknown error"
                        ];
        var e = Primesieve.error;
        if(e == 0){
            return strerrors[ 0 ];
        }
        if(e < 0 || e > strerrors.length - 1){
            return strerrors[ strerrors.length - 1 ];
        }
        if(e == E_ABOVE_LIMIT){
            return strerrors[ E_ABOVE_LIMIT ] + primesizelimit;
        } else {
            return strerrors[e];
        }
    };
    Primesieve.isSmallPrime = function(prime) {
        if (!isInt(prime)) {
            Primesieve.error = E_ARG_NO_INT;
            return undefined;
        } else if (prime < 2 ) {
            Primesieve.error = E_ARG_TOO_LOW;
            return undefined;
        }
        if (prime > primelimit) {
            Primesieve.grow(prime + 100);
            if(Primesieve.error ==  E_ABOVE_LIMIT){
                return undefined;
            }
        }
        Primesieve.error = E_SUCCESS;
        if (get(prime) == 1) {
            return true;
        }
        return false;
    };
    Primesieve.nextPrime = function(prime) {
        if (!isInt(prime)) {
            Primesieve.error = E_ARG_NO_INT;
            return undefined;
        }
        if (prime < 0) {
            return 2;
        }
        if (prime > primelimit) {
            Primesieve.grow(prime + 100);
            if(Primesieve.error ==  E_ABOVE_LIMIT){
                return undefined;
            }
        }
        Primesieve.error = E_SUCCESS;
        return nextset(prime);
    };
    Primesieve.precPrime = function(prime) {
        if (!isInt(prime)) {
            Primesieve.error = E_ARG_NO_INT;
            return undefined;
        } else if (prime < 2 ) {
            Primesieve.error = E_ARG_TOO_LOW;
            return undefined;
        }
        if (prime > primelimit) {
            Primesieve.grow(prime + 100);
            if(Primesieve.error ==  E_ABOVE_LIMIT){
                return undefined;
            }
        }
        Primesieve.error = E_SUCCESS;
        return prevset(prime);
    };
    Primesieve.primePi = function(prime) {
        var k = 0;
        var ct = 0;

        if (!isInt(prime)) {
            Primesieve.error = E_ARG_NO_INT;
            return undefined;
        } else if (prime < 2 ) {
            Primesieve.error = E_ARG_TOO_LOW;
            return undefined;
        }

        if (prime > primelimit) {
            Primesieve.grow(prime + 100);
            if(Primesieve.error ==  E_ABOVE_LIMIT){
                return undefined;
            }
        }
        while (k < prime) {
            k = nextset(k + 1);
            if (k > primelimit || k < 0 || k > prime) {
                break;
            }
            ct++;
        }
        Primesieve.error = E_SUCCESS;
        return ct;
    };
    Primesieve.primePiApprox = function(prime) {
        if (!isInt(prime)) {
            Primesieve.error = E_ARG_NO_INT;
            return undefined;
        } else if (prime < 2 ) {
            Primesieve.error = E_ARG_TOO_LOW;
            return undefined;
        }
        Primesieve.error = E_SUCCESS;
        return approx_pi(prime);
    };
    Primesieve.primeRange = function(low, high) {
        var down = 0,
            up = 0,
            ret = [],
            i = 1;

        if (!isInt(low) || !isInt(high)) {
            Primesieve.error = E_ARG_NO_INT;
            return undefined;
        } else if (low < 0 ) {
            Primesieve.error = E_ARG_TOO_LOW;
            return undefined;
        } else if ( low > high ) {
            /* try again, maybe just a fluke */
            return Primesieve.primeRange(high,low);
        }

        if(primelimit < high){
             Primesieve.grow(high + 100);
            if(Primesieve.error ==  E_ABOVE_LIMIT){
                return undefined;
            }
        }
        down = nextset(low);
        up = prevset(high);
        ret[0] = down;
        if (down == up) {
            return ret;
        }
        while (down < up) {
            down = nextset(down + 1);
            if (down > high || down < 0) {
                break;
            }
            ret[i++] = down;
        }
        Primesieve.error = E_SUCCESS;
        return ret;
    };
    Primesieve.primes = function(prime) {
        var ret, k, count, limit,i;
        limit = approx_limit(prime);

        if (!isInt(prime)) {
            Primesieve.error = E_ARG_NO_INT;
            return undefined;
        } else if (prime < 2) {
            Primesieve.error = E_ARG_TOO_LOW;
            return undefined;
        }

        if(primelimit < limit){
            Primesieve.grow(limit);
            if(Primesieve.error ==  E_ABOVE_LIMIT){
                return undefined;
            }
        }
        ret = [];
        k = 0;
        i = 0;
        count = prime;
        while (count--) {
            k = nextset(k + 1);
            if (k > primelimit || k < 0) {
                break;
            }
            ret[i++] = k;
        }
        Primesieve.error = E_SUCCESS;
        return ret;
    };
    Primesieve.grow = function(alot) {
        if (!isInt(alot)) {
            Primesieve.error = E_ARG_NO_INT;
            return undefined;
        } else if (alot < 2) {
            Primesieve.error = E_ARG_TOO_LOW;
            return undefined;
        } else if (alot > primesizelimit) {
            Primesieve.error = E_ABOVE_LIMIT;
            return undefined;
        } else if(alot > primelimit){
            Primesieve.error = E_SUCCESS;
            fillsieve(alot);
        } /* else {
           Do nothing for now
        }*/
    };
    Primesieve.fill = Primesieve.grow;
    Primesieve.raiseLimit = function(raise) {
        if (!isInt(raise)) {
            Primesieve.error = E_ARG_NO_INT;
            return undefined;
        } else if (raise < 2) {
            Primesieve.error = E_ARG_TOO_LOW;
            return undefined;
        } else if (raise > primesizelimit) {
            Primesieve.error = E_SUCCESS;
            primesizelimit = raise;
        }
    };
    return Primesieve;
})(/* You may place a start-size here */);

if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') {
    module.exports = primesieve;
} else {
    if (typeof define === 'function' && define.amd) {
        define([], function() { return primesieve; });
    } else {
        window.primesieve = primesieve;
    }
}
<commit_msg>ADDED: function to get the raw sieve<commit_after>var primesieve = (function() {
    "use strict";
    var Primesieve = {};
    var primelimit = 0;
    var buffer;
    var primesieve;
    var primesizelimit = 0x800000; // 1 megabyte

    // works with normal arrays, too
    if (typeof Uint32Array === 'undefined') Uint32Array = Array;

    // 30*log(113)/113 see also http://oeis.org/A209883
    var LN_113 = 1.25505871293247979696870747618124469168920275806274;
    // Rosser, J. B. and Schoenfeld, L. "Approximate Formulas for Some
    // Functions of Prime Numbers." Illinois J. Math. 6, 64-97, 1962
    // http://projecteuclid.org/DPubS?service=UI&version=1.0&verb=Display&handle=euclid.ijm/1255631807
    var approx_pi = function(limit){
        // Math.ceil(5*x/(4*Math.log(x))) // would be more exact for large x
        return Math.ceil( (LN_113 * limit) / Math.log(limit) ) + 2;
    };
    var approx_limit = function(prime_pi){
        if(prime_pi < 10){
          return 30;
        }
        // see first term of expansion of li(x)-li(2)
        return Math.ceil( prime_pi * ( Math.log( prime_pi * Math.log( prime_pi))));
    };
    var isInt = function(x) {
        if (isNaN(x)) {
            return false;
        }
        if (x > -9007199254740992 && x < 9007199254740992 && Math.floor(
                x) == x) {
            return true;
        }
    };
    var clear = function(where) {
        primesieve[where >>> 5] &= ~((1 << (31 - (where & 31))) );
    };
    var get = function(where) {
        return ((primesieve[where >>> 5] >>> ((31 - (where & 31)))) & 1);
    };
    var nextset = function(from) {
        while (from < primelimit && !get(from)) {
            from++;
        }
        if (from === primelimit && !get(from)) {
            return -1;
        }
        return from;
    };
    var prevset = function(from) {
        while (from >= 0 && !get(from)) {
            from--;
        }
        if (from == 0 && !get(from)) {
            return -1;
        }
        return from;
    };
    var fillsieve = function(n) {
        var k, r, j;
        n = n + 1;
        primelimit = n - 1;
        k = Math.ceil(n / 32);
        buffer = new ArrayBuffer(k * 4);
        primesieve = new Uint32Array(buffer);
        while (k--) {
            primesieve[k] = 0xffffffff;
        }
        clear(0);
        clear(1);
        for (k = 4; k < n; k += 2) {
            clear(k);
        }
        r = Math.floor(Math.sqrt(n));
        k = 0;
        while (k < n) {
            k = nextset(k + 1);
            if (k > r || k < 0) {
                break;
            }
            for (j = k * k; j < n; j += 2 * k) {
                clear(j);
            }
        }
    };
    var E_SUCCESS = 0;
    var E_ARG_NO_INT = 1;
    var E_ARG_TOO_LOW = 2;
    var E_ARG_TOO_HIGH = 3;
    var E_ABOVE_LIMIT = 4;
    Primesieve.error = 0;
    Primesieve.strerror = function(){
        var strerrors = [
            "Success",
            "Argument not an integer",
            "Argument too low",
            "Argument too high",
            "Prime wanted is higher than the limit ",
            "Unknown error"
                        ];
        var e = Primesieve.error;
        if(e == 0){
            return strerrors[ 0 ];
        }
        if(e < 0 || e > strerrors.length - 1){
            return strerrors[ strerrors.length - 1 ];
        }
        if(e == E_ABOVE_LIMIT){
            return strerrors[ E_ABOVE_LIMIT ] + primesizelimit;
        } else {
            return strerrors[e];
        }
    };
    Primesieve.isSmallPrime = function(prime) {
        if (!isInt(prime)) {
            Primesieve.error = E_ARG_NO_INT;
            return undefined;
        } else if (prime < 2 ) {
            Primesieve.error = E_ARG_TOO_LOW;
            return undefined;
        }
        if (prime > primelimit) {
            Primesieve.grow(prime + 100);
            if(Primesieve.error ==  E_ABOVE_LIMIT){
                return undefined;
            }
        }
        Primesieve.error = E_SUCCESS;
        if (get(prime) == 1) {
            return true;
        }
        return false;
    };
    Primesieve.nextPrime = function(prime) {
        if (!isInt(prime)) {
            Primesieve.error = E_ARG_NO_INT;
            return undefined;
        }
        if (prime < 0) {
            return 2;
        }
        if (prime > primelimit) {
            Primesieve.grow(prime + 100);
            if(Primesieve.error ==  E_ABOVE_LIMIT){
                return undefined;
            }
        }
        Primesieve.error = E_SUCCESS;
        return nextset(prime);
    };
    Primesieve.precPrime = function(prime) {
        if (!isInt(prime)) {
            Primesieve.error = E_ARG_NO_INT;
            return undefined;
        } else if (prime < 2 ) {
            Primesieve.error = E_ARG_TOO_LOW;
            return undefined;
        }
        if (prime > primelimit) {
            Primesieve.grow(prime + 100);
            if(Primesieve.error ==  E_ABOVE_LIMIT){
                return undefined;
            }
        }
        Primesieve.error = E_SUCCESS;
        return prevset(prime);
    };
    Primesieve.primePi = function(prime) {
        var k = 0;
        var ct = 0;

        if (!isInt(prime)) {
            Primesieve.error = E_ARG_NO_INT;
            return undefined;
        } else if (prime < 2 ) {
            Primesieve.error = E_ARG_TOO_LOW;
            return undefined;
        }

        if (prime > primelimit) {
            Primesieve.grow(prime + 100);
            if(Primesieve.error ==  E_ABOVE_LIMIT){
                return undefined;
            }
        }
        while (k < prime) {
            k = nextset(k + 1);
            if (k > primelimit || k < 0 || k > prime) {
                break;
            }
            ct++;
        }
        Primesieve.error = E_SUCCESS;
        return ct;
    };
    Primesieve.primePiApprox = function(prime) {
        if (!isInt(prime)) {
            Primesieve.error = E_ARG_NO_INT;
            return undefined;
        } else if (prime < 2 ) {
            Primesieve.error = E_ARG_TOO_LOW;
            return undefined;
        }
        Primesieve.error = E_SUCCESS;
        return approx_pi(prime);
    };
    Primesieve.primeRange = function(low, high) {
        var down = 0,
            up = 0,
            ret = [],
            i = 1;

        if (!isInt(low) || !isInt(high)) {
            Primesieve.error = E_ARG_NO_INT;
            return undefined;
        } else if (low < 0 ) {
            Primesieve.error = E_ARG_TOO_LOW;
            return undefined;
        } else if ( low > high ) {
            /* try again, maybe just a fluke */
            return Primesieve.primeRange(high,low);
        }

        if(primelimit < high){
             Primesieve.grow(high + 100);
            if(Primesieve.error ==  E_ABOVE_LIMIT){
                return undefined;
            }
        }
        down = nextset(low);
        up = prevset(high);
        ret[0] = down;
        if (down == up) {
            return ret;
        }
        while (down < up) {
            down = nextset(down + 1);
            if (down > high || down < 0) {
                break;
            }
            ret[i++] = down;
        }
        Primesieve.error = E_SUCCESS;
        return ret;
    };
    Primesieve.primes = function(prime) {
        var ret, k, count, limit,i;
        limit = approx_limit(prime);

        if (!isInt(prime)) {
            Primesieve.error = E_ARG_NO_INT;
            return undefined;
        } else if (prime < 2) {
            Primesieve.error = E_ARG_TOO_LOW;
            return undefined;
        }

        if(primelimit < limit){
            Primesieve.grow(limit);
            if(Primesieve.error ==  E_ABOVE_LIMIT){
                return undefined;
            }
        }
        ret = [];
        k = 0;
        i = 0;
        count = prime;
        while (count--) {
            k = nextset(k + 1);
            if (k > primelimit || k < 0) {
                break;
            }
            ret[i++] = k;
        }
        Primesieve.error = E_SUCCESS;
        return ret;
    };
    Primesieve.grow = function(alot) {
        if (!isInt(alot)) {
            Primesieve.error = E_ARG_NO_INT;
            return undefined;
        } else if (alot < 2) {
            Primesieve.error = E_ARG_TOO_LOW;
            return undefined;
        } else if (alot > primesizelimit) {
            Primesieve.error = E_ABOVE_LIMIT;
            return undefined;
        } else if(alot > primelimit){
            Primesieve.error = E_SUCCESS;
            fillsieve(alot);
        } /* else {
           Do nothing for now
        }*/
    };
    Primesieve.fill = Primesieve.grow;
    Primesieve.raiseLimit = function(raise) {
        if (!isInt(raise)) {
            Primesieve.error = E_ARG_NO_INT;
            return undefined;
        } else if (raise < 2) {
            Primesieve.error = E_ARG_TOO_LOW;
            return undefined;
        } else if (raise > primesizelimit) {
            Primesieve.error = E_SUCCESS;
            primesizelimit = raise;
        }
    };
    Primesieve.sieve = function() {
        return primesieve;
    };
    return Primesieve;
})(/* You may place a start-size here */);

if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') {
    module.exports = primesieve;
} else {
    if (typeof define === 'function' && define.amd) {
        define([], function() { return primesieve; });
    } else {
        window.primesieve = primesieve;
    }
}
<|endoftext|>


<commit_before>var utils = require("@/common/utils");
var _const = require("@/common/const");
var uikit = require("./uikit");
var apiHelper = require("./apis");
var channel = require("./channel");
var profile = require("@/app/tools/profile");
var eventListener = require("@/app/tools/eventListener");
var loading = require("./uikit/loading");
var getToHost = require("@/app/common/transfer");

var dom;
var starsUl;
var resolvedBtn;
var commentDom;
var tagContainer;
var dialog;

var starList;

var session;
var invite;
var score;
var evaluationDegreeId;
var isSingleTag;
var resolvedDom;
var resolveTip;
var resolvedId = 1;
var _initOnce = _.once(_init);
var evaluateType; // 评价方式
var sessionResolved;// 问题解决评价
var fiveStarState;//默认五星评价
var defaultScore;

module.exports = {
	init: init,
	show: show,
};

function _init(){
	loading.show("satisfaction");
	//默认五星评价的开关
	apiHelper.getDefaultFiveStarEnable()
	.then(function(resp){
		fiveStarState = resp;
	});
	apiHelper.getSatisfactionTipWord().then(function(tipWord){
		dom = sessionResolved ? utils.createElementFromHTML([
			"
",
			"
" + resolveTip + "",
			"
" + __("evaluation.resolved") + "",
			"" + __("evaluation.unsolved") + "

",
			"" + tipWord + "",
			"

",
			"

",
			"<textarea spellcheck=\"false\" placeholder=\"" + __("evaluation.review") + "\"></textarea>",
			"
"
		].join(""))
			:
			utils.createElementFromHTML([
				"
",
				"" + tipWord + "",
				"

",
				"

",
				"<textarea spellcheck=\"false\" placeholder=\"" + __("evaluation.review") + "\"></textarea>",
				"
"
			].join(""));
		starsUl = dom.querySelector("ul");
		commentDom = dom.querySelector("textarea");
		tagContainer = dom.querySelector(".tag-container");
		resolvedBtn = dom.querySelectorAll(".resolve-btn");
		resolvedDom = dom.querySelector(".resolved");

		utils.live(".resolve-btn", "click", function(){
			utils.removeClass(resolvedBtn, "selected");
			utils.addClass(this, "selected");
			resolvedId = this.dataset.num;
			if(fiveStarState){
				if(resolvedId == 1){
					utils.addClass(starList, "sel");
					score = defaultScore;
				}
				else{
					utils.removeClass(starList, "sel");
					score = false;
				}
			}
		});

		utils.live("li", "click", function(){
			var level = +this.getAttribute("data-level");

			evaluationDegreeId = this.getAttribute("data-evaluate-id");
			score = this.getAttribute("data-score");
			isSingleTag = this.getAttribute("data-isSingleTag");
			level && _.each(starList, function(elem, i){
				utils.toggleClass(elem, "sel", i < level);
			});

			evaluationDegreeId && _createLabel(evaluationDegreeId);
		}, starsUl);

		utils.live("span.tag", "click", function(){
			var selectedTagNodeList = tagContainer.querySelectorAll(".selected");
			if(isSingleTag == "true"){
				utils.removeClass(selectedTagNodeList, "selected");
				utils.toggleClass(this, "selected");
			}
			else{
				utils.toggleClass(this, "selected");
			}

		}, tagContainer);

		dialog = uikit.createDialog({
			contentDom: dom,
			className: "satisfaction"
		}).addButton({
			confirmText: __("common.submit"),
			confirm: _confirm,
		});
		loading.hide("satisfaction");
		dialog.show();

		// 火狐浏览器 _setSatisfaction时找不到starsUl，所以必须先执行完init
		_setSatisfaction();
	});
}

function _clear(){
	commentDom.blur();
	commentDom.value = "";
	score = null;
	// clear stars
	utils.removeClass(starList, "sel");
	// clear label
	tagContainer.innerHTML = "";
	// clear resolvedBtn
	utils.removeClass(resolvedBtn, "selected");
	utils.addClass(resolvedDom, "selected");
	resolvedId = 1;

}

function _sendSatisfaction(score, content, session, invite, appraiseTags, resolutionParam, evaluationDegreeId){
	var data = {
		ext: {
			weichat: {
				ctrlType: "enquiry",
				ctrlArgs: {
					// 后端类型要求，inviteId必须传数字
					inviteId: invite || 0,
					serviceSessionId: session || profile.currentOfficialAccount.sessionId || "",
					detail: content,
					summary: score,
					appraiseTags: appraiseTags,
					resolutionParam: resolutionParam,
					evaluationDegreeId: evaluationDegreeId,
					// 评价方式，由前端传入：visitor - 访客主动评价; agent - 坐席邀请; system - 强制邀请,访客点击关闭窗口或会话结束
					evaluateWay: evaluateType
				}
			}
		}
	};
	if(!sessionResolved){
		delete data.ext.weichat.ctrlArgs.resolutionParam;
	}
	channel.sendText("", data);
}

function _setSatisfaction(){
	apiHelper.getEvaluationDegrees().then(function(entities){
		var labelID;
		var lastScore;
		starsUl.innerHTML = _.chain(entities)
		.sortBy("level")
		.map(function(elem, index){
			// stat level 1-based
			var level = index + 1;
			var name = elem.name;
			var id = elem.id;
			var score = elem.score;
			var isSingleTag = elem.isSingleTag;
			labelID = id;
			lastScore = score;

			return "
H
";
		})
		.value()
		.join("");

		starList = starsUl.querySelectorAll("li");
		defaultScore = lastScore
		if(fiveStarState){
			if(resolvedId == 1){
				utils.addClass(starList, "sel");
				//创建评价标签
				_createLabel(labelID);
				score = defaultScore;
			}
			else{
				utils.removeClass(starList, "sel");
				score = false;
			}
		}

	});
}

function _createLabel(evaluateId){
	apiHelper.getAppraiseTags(evaluateId).then(function(entities){
		tagContainer.innerHTML = _.map(entities, function(elem){
			var name = elem.name;
			var id = elem.id;

			return "" + name + "";
		}).join("");
		utils.removeClass(tagContainer, "hide");
	});
}

function _confirm(){
	var selectedTagNodeList = tagContainer.querySelectorAll(".selected");
	var tagNodeList = tagContainer.querySelectorAll(".tag");
	var content = commentDom.value;
	var appraiseTags = _.map(selectedTagNodeList, function(elem){
		return {
			id: elem.getAttribute("data-label-id"),
			name: elem.innerText
		};
	});
	var resolutionParam = [{
		id: resolvedId,
		name: resolvedId == 1 ? "已解决" : "未解决",
		score: resolvedId,
		resolutionParamTags: []
	}];

	// 必须选择星级
	if(!score){
		uikit.tip(__("evaluation.select_level_please"));
		// 防止对话框关闭
		return false;
	}
	// 若有标签则至少选择一个
	else if(tagNodeList.length > 0 && selectedTagNodeList.length === 0){
		uikit.tip(__("evaluation.select_tag_please"));
		// 防止对话框关闭
		return false;
	}

	_sendSatisfaction(score, content, session, invite, appraiseTags, resolutionParam, evaluationDegreeId);
	uikit.showSuccess(__("evaluation.submit_success"));
	getToHost.send({ event: _const.EVENTS.EVALUATIONSUBMIT });
	// 强制评价点击确定关闭会话框
	setTimeout(function(){
		// 关闭会话
		if(evaluateType === "system"){
			// 取消轮询接口
			eventListener.trigger(_const.SYSTEM_EVENT.CHAT_CLOSED);
			profile.currentOfficialAccount.sessionId && apiHelper.closeChatDialog({ serviceSessionId: profile.currentOfficialAccount.sessionId });
			getToHost.send({ event: _const.EVENTS.CLOSE });
		}
	}, 2000);
	_clear();
}

function show(inviteId, serviceSessionId, evaluateWay){

	apiHelper.getEvaluteSolveWord().then(function(tip){
		resolveTip = tip;
	});
	apiHelper.getServiceSessionResolved()
	.then(function(resp){
		sessionResolved = resp;
		_initOnce();
	});

	session = serviceSessionId;
	invite = inviteId;
	evaluateType = evaluateWay;

	dialog && dialog.show();
}

function init(){
	eventListener.add(
		_const.SYSTEM_EVENT.SATISFACTION_EVALUATION_MESSAGE_RECEIVED,
		function(officialAccount, inviteId, serviceSessionId){
			if(officialAccount !== profile.currentOfficialAccount) return;
			show(inviteId, serviceSessionId, "system");
		}
	);
}
<commit_msg>CLOUD-20603【敦煌网】网页渠道评价默认选中五星问题<commit_after>var utils = require("@/common/utils");
var _const = require("@/common/const");
var uikit = require("./uikit");
var apiHelper = require("./apis");
var channel = require("./channel");
var profile = require("@/app/tools/profile");
var eventListener = require("@/app/tools/eventListener");
var loading = require("./uikit/loading");
var getToHost = require("@/app/common/transfer");

var dom;
var starsUl;
var resolvedBtn;
var commentDom;
var tagContainer;
var dialog;

var starList;

var session;
var invite;
var score;
var evaluationDegreeId;
var isSingleTag;
var resolvedDom;
var resolveTip;
var resolvedId = 1;
var _initOnce = _.once(_init);
var evaluateType; // 评价方式
var sessionResolved;// 问题解决评价
var fiveStarState;//默认五星评价
var defaultScore;

module.exports = {
	init: init,
	show: show,
};

function _init(){
	loading.show("satisfaction");
	//默认五星评价的开关
	apiHelper.getDefaultFiveStarEnable()
	.then(function(resp){
		fiveStarState = resp;
	});
	apiHelper.getSatisfactionTipWord().then(function(tipWord){
		dom = sessionResolved ? utils.createElementFromHTML([
			"
",
			"
" + resolveTip + "",
			"
" + __("evaluation.resolved") + "",
			"" + __("evaluation.unsolved") + "

",
			"" + tipWord + "",
			"

",
			"

",
			"<textarea spellcheck=\"false\" placeholder=\"" + __("evaluation.review") + "\"></textarea>",
			"
"
		].join(""))
			:
			utils.createElementFromHTML([
				"
",
				"" + tipWord + "",
				"

",
				"

",
				"<textarea spellcheck=\"false\" placeholder=\"" + __("evaluation.review") + "\"></textarea>",
				"
"
			].join(""));
		starsUl = dom.querySelector("ul");
		commentDom = dom.querySelector("textarea");
		tagContainer = dom.querySelector(".tag-container");
		resolvedBtn = dom.querySelectorAll(".resolve-btn");
		resolvedDom = dom.querySelector(".resolved");

		utils.live(".resolve-btn", "click", function(){
			utils.removeClass(resolvedBtn, "selected");
			utils.addClass(this, "selected");
			resolvedId = this.dataset.num;
			if(fiveStarState){
				if(resolvedId == 1){
					utils.addClass(starList, "sel");
					score = defaultScore;
				}
				else{
					utils.removeClass(starList, "sel");
					score = false;
				}
			}
		});

		utils.live("li", "click", function(){
			var level = +this.getAttribute("data-level");

			evaluationDegreeId = this.getAttribute("data-evaluate-id");
			score = this.getAttribute("data-score");
			isSingleTag = this.getAttribute("data-isSingleTag");
			level && _.each(starList, function(elem, i){
				utils.toggleClass(elem, "sel", i < level);
			});

			evaluationDegreeId && _createLabel(evaluationDegreeId);
		}, starsUl);

		utils.live("span.tag", "click", function(){
			var selectedTagNodeList = tagContainer.querySelectorAll(".selected");
			if(isSingleTag == "true"){
				utils.removeClass(selectedTagNodeList, "selected");
				utils.toggleClass(this, "selected");
			}
			else{
				utils.toggleClass(this, "selected");
			}

		}, tagContainer);

		dialog = uikit.createDialog({
			contentDom: dom,
			className: "satisfaction"
		}).addButton({
			confirmText: __("common.submit"),
			confirm: _confirm,
		});
		loading.hide("satisfaction");
		dialog.show();

		// 火狐浏览器 _setSatisfaction时找不到starsUl，所以必须先执行完init
		_setSatisfaction();
	});
}

function _clear(){
	commentDom.blur();
	commentDom.value = "";
	score = null;
	// clear stars
	utils.removeClass(starList, "sel");
	// clear label
	tagContainer.innerHTML = "";
	// clear resolvedBtn
	utils.removeClass(resolvedBtn, "selected");
	utils.addClass(resolvedDom, "selected");
	resolvedId = 1;

}

function _sendSatisfaction(score, content, session, invite, appraiseTags, resolutionParam, evaluationDegreeId){
	var data = {
		ext: {
			weichat: {
				ctrlType: "enquiry",
				ctrlArgs: {
					// 后端类型要求，inviteId必须传数字
					inviteId: invite || 0,
					serviceSessionId: session || profile.currentOfficialAccount.sessionId || "",
					detail: content,
					summary: score,
					appraiseTags: appraiseTags,
					resolutionParam: resolutionParam,
					evaluationDegreeId: evaluationDegreeId,
					// 评价方式，由前端传入：visitor - 访客主动评价; agent - 坐席邀请; system - 强制邀请,访客点击关闭窗口或会话结束
					evaluateWay: evaluateType
				}
			}
		}
	};
	if(!sessionResolved){
		delete data.ext.weichat.ctrlArgs.resolutionParam;
	}
	channel.sendText("", data);
}

function _setSatisfaction(){
	apiHelper.getEvaluationDegrees().then(function(entities){
		var labelID;
		var lastScore;
		starsUl.innerHTML = _.chain(entities)
		.sortBy("level")
		.map(function(elem, index){
			// stat level 1-based
			var level = index + 1;
			var name = elem.name;
			var id = elem.id;
			var score = elem.score;
			var isSingleTag = elem.isSingleTag;
			labelID = id;
			lastScore = score;

			return "
H
";
		})
		.value()
		.join("");

		starList = starsUl.querySelectorAll("li");
		defaultScore = lastScore
		if(fiveStarState){
			if(resolvedId == 1){
				utils.addClass(starList, "sel");
				//创建评价标签
				_createLabel(labelID);
				score = defaultScore;
			}
			else{
				utils.removeClass(starList, "sel");
				score = false;
			}
		}

	});
}

function _createLabel(evaluateId){
	apiHelper.getAppraiseTags(evaluateId).then(function(entities){
		tagContainer.innerHTML = _.map(entities, function(elem){
			var name = elem.name;
			var id = elem.id;

			return "" + name + "";
		}).join("");
		utils.removeClass(tagContainer, "hide");
	});
}

function _confirm(){
	var selectedTagNodeList = tagContainer.querySelectorAll(".selected");
	var tagNodeList = tagContainer.querySelectorAll(".tag");
	var content = commentDom.value;
	var appraiseTags = _.map(selectedTagNodeList, function(elem){
		return {
			id: elem.getAttribute("data-label-id"),
			name: elem.innerText
		};
	});
	var resolutionParam = [{
		id: resolvedId,
		name: resolvedId == 1 ? "已解决" : "未解决",
		score: resolvedId,
		resolutionParamTags: []
	}];

	// 必须选择星级
	if(!score){
		uikit.tip(__("evaluation.select_level_please"));
		// 防止对话框关闭
		return false;
	}
	// 若有标签则至少选择一个
	else if(tagNodeList.length > 0 && selectedTagNodeList.length === 0){
		uikit.tip(__("evaluation.select_tag_please"));
		// 防止对话框关闭
		return false;
	}

	_sendSatisfaction(score, content, session, invite, appraiseTags, resolutionParam, evaluationDegreeId);
	uikit.showSuccess(__("evaluation.submit_success"));
	getToHost.send({ event: _const.EVENTS.EVALUATIONSUBMIT });
	// 强制评价点击确定关闭会话框
	setTimeout(function(){
		// 关闭会话
		if(evaluateType === "system"){
			// 取消轮询接口
			eventListener.trigger(_const.SYSTEM_EVENT.CHAT_CLOSED);
			profile.currentOfficialAccount.sessionId && apiHelper.closeChatDialog({ serviceSessionId: profile.currentOfficialAccount.sessionId });
			getToHost.send({ event: _const.EVENTS.CLOSE });
		}
	}, 2000);
	_clear();
}

function show(inviteId, serviceSessionId, evaluateWay){

	apiHelper.getEvaluteSolveWord().then(function(tip){
		resolveTip = tip;
	});
	apiHelper.getServiceSessionResolved()
	.then(function(resp){
		sessionResolved = resp;
		_initOnce();
	});

	session = serviceSessionId;
	invite = inviteId;
	evaluateType = evaluateWay;
	_setDefaultScore();
	dialog && dialog.show();
}

function _setDefaultScore(){
	if(!starsUl){
		return false;
	}
	starList = starsUl.querySelectorAll("li");
	if(fiveStarState){
		if(resolvedId == 1){
			utils.addClass(starList, "sel");
			score = defaultScore;
		}
		else{
			utils.removeClass(starList, "sel");
			score = false;
		}
	}
}

function init(){
	eventListener.add(
		_const.SYSTEM_EVENT.SATISFACTION_EVALUATION_MESSAGE_RECEIVED,
		function(officialAccount, inviteId, serviceSessionId){
			if(officialAccount !== profile.currentOfficialAccount) return;
			show(inviteId, serviceSessionId, "system");
		}
	);
}
<|endoftext|>


<commit_before>import postcss from 'postcss';
import balanced from 'balanced-match';
import _ from 'lodash';

const VAR_FUNC_IDENTIFIER = 'var';
const maps = {};

function resolveValue(value) {
	const start = value.indexOf(`${VAR_FUNC_IDENTIFIER}(`);
	if (start === -1) {
		return value;
	}

	value.match(/var\(\S*\)/g).map(match => {
		const matches = balanced('(', ')', match);
		const reg = new RegExp(`${VAR_FUNC_IDENTIFIER}.(${matches.body}.)`, 'g');
		const property = maps[matches.body] || match;

		value = value.replace(reg, property);
	});
	return value;
}

module.exports = postcss.plugin('postcss-at-rules-variables', options => {
	const DEFAULT = {
		atRules: ['for', 'if', 'else', 'each']
	};

	const mergeOoptions = _.merge(DEFAULT, options, (a, b) => {
		if (_.isArray(a)) {
			return a.concat(b);
		}
	});

	return css => {
		const reg = new RegExp(mergeOoptions.atRules.join('|'));

		css.walkRules(rule => {
			if (rule.selectors[0] !== ':root') {
				return;
			}

			rule.each(decl => {
				const prop = decl.prop;
				const value = decl.value;
				maps[prop] = value;
			});
		});

		css.walkAtRules(reg, rules => {
			rules.params = resolveValue(rules.params);
		});
	};
});
<commit_msg>Fixed xo report error<commit_after>import postcss from 'postcss';
import balanced from 'balanced-match';
import _ from 'lodash';

const VAR_FUNC_IDENTIFIER = 'var';
const maps = {};

function resolveValue(value) {
	const start = value.indexOf(`${VAR_FUNC_IDENTIFIER}(`);
	if (start === -1) {
		return value;
	}

	value.match(/var\(\S*\)/g).map(match => {
		const matches = balanced('(', ')', match);
		const reg = new RegExp(`${VAR_FUNC_IDENTIFIER}.(${matches.body}.)`, 'g');
		const property = maps[matches.body] || match;

		value = value.replace(reg, property);
		return true;
	});
	return value;
}

module.exports = postcss.plugin('postcss-at-rules-variables', options => {
	const DEFAULT = {
		atRules: ['for', 'if', 'else', 'each']
	};

	const mergeOoptions = _.merge(DEFAULT, options, (a, b) => {
		if (_.isArray(a)) {
			return a.concat(b);
		}
	});

	return css => {
		const reg = new RegExp(mergeOoptions.atRules.join('|'));

		css.walkRules(rule => {
			if (rule.selectors[0] !== ':root') {
				return;
			}

			rule.each(decl => {
				const prop = decl.prop;
				const value = decl.value;
				maps[prop] = value;
			});
		});

		css.walkAtRules(reg, rules => {
			rules.params = resolveValue(rules.params);
		});
	};
});
<|endoftext|>