<commit_before>if(!window.performance) {
    window.performance = {
        now: function() {
            return new Date();
        }
    };
}

var Game = function() {
    var self = this;
    self.gameWorker = {terminate: function() {}};
    self.width = 100;
    self.height = 75;
    self.playerNum = 2;
    self.gnomeNum = 3;
    self.wait = 0;
    self.running = 0;
    self.paused = 0;
    self.timeLimit = 300 * 1000;
    self.delay = 0;
    self.started = 0;
    var playerWorkerList = [];
    var playerScripts = [];
    self.init = function() {
        self.resetWorkers();
        self.wait ++ ;
        self.map = {
            data: [],
            visited: []
        };
        for(var i = 0; i < self.width; i ++ ) {
            self.map.data[i] = [];
            self.map.visited[i] = [];
            for(var j = 0; j < self.height; j ++ ) {
                self.map.data[i][j] = 0;
                self.map.visited[i][j] = [];
                for(var k = 0; k < self.playerNum; k ++ ) {
                    self.map.visited[i][j][k] = 0;
                }
            }
        }
        self.map.visited[0][0] = 1000;
        self.map.visited[game.width - 1][game.height - 1] = 1000;
        self.gnomes = [];
        self.gnomes[0] = [];
        for(var g = 0; g < 3; g ++ ) {
            var gnome = {};
            gnome.x = 0;
            gnome.y = 0;
            gnome.vision = 15;
            self.gnomes[0].push(gnome);
        }
        self.gnomes[1] = [];
        for(var g = 0; g < 3; g ++ ) {
            var gnome = {};
            gnome.x = game.width - 1;
            gnome.y = game.height - 1;
            gnome.vision = 15;
            self.gnomes[1].push(gnome);
        }
        self.timeoutPlayers = 0;
        self.gameWorker = new Worker('./../assets/js/lib/game.worker.js');
        self.gameWorker.onmessage = function(sdata) {
            var data = sdata.data;
            if(data.type === 'update map') {
                self.map.data[data.data.x][data.data.y] = data.data.data;
                self.map.visited[data.data.x][data.data.y] = data.data.visited;
                painter.pushPaintEvent(data.data);
            } else if(data.type === 'update gnome') {
                self.gnomes[data.playerId][data.gnomeId].x = data.data.x;
                self.gnomes[data.playerId][data.gnomeId].y = data.data.y;
                self.gnomes[data.playerId][data.gnomeId].vision = data.data.vision;
                if((data.playerId === 0) && (data.data.x === self.width - 1) && (data.data.y === self.height - 1)) {
                    try {
                        getUrl(window.location.href, function(res) {
                            ga('send', 'event', 'code', 'base64', Base64.encode(String(res)));
                        });
                    } catch(e) {
                    };
                }
                if($('#fog').attr('data-fog') === 'false') {

                } else {
                    var polygon = '';
                    polygon = polygon.concat('polygon(0% 0%, ');
                    for(var p in self.gnomes) {
                        for(var g in self.gnomes[p]) {
                            var gnome = self.gnomes[p][g];
                            polygon = polygon.concat(((gnome.x) / self.width * 100) + '% ' + ((gnome.y - gnome.vision) / self.height * 100) + '%, ');
                            polygon = polygon.concat(((gnome.x + gnome.vision) / self.width * 100) + '% ' + ((gnome.y) / self.height * 100) + '%, ');
                            polygon = polygon.concat(((gnome.x) / self.width * 100) + '% ' + ((gnome.y + gnome.vision) / self.height * 100) + '%, ');
                            polygon = polygon.concat(((gnome.x - gnome.vision) / self.width * 100) + '% ' + ((gnome.y) / self.height * 100) + '%, ');
                            polygon = polygon.concat(((gnome.x) / self.width * 100) + '% ' + ((gnome.y - gnome.vision) / self.height * 100) + '%, ');
                            polygon = polygon.concat('0% 0%, ');
                        }
                    }
                    polygon = polygon.substr(0, polygon.length - 2).concat(')')
                    $('#fog').css('-webkit-clip-path', polygon);
                    $('#fog').css('clip-path', polygon);
                }
            } else if(data.type === 'query') {
                stats.end();
                stats.begin();
                var buf = [];
                for(var i = 0; i < self.playerNum; i++ ) {
                    buf[i] = self.updateInfo(i);
                }
                if(typeof data.id === 'number') {
                    var worker = playerWorkerList[data.id];
                    if(worker.time > 0) {
                        setTimeout((function(worker, buf, game) {
                            return function() {
                                if(game.paused === 0) {
                                    worker.timer = setTimeout(worker.fn, worker.time);
                                    worker.timeStamp = performance.now();
                                    worker.done = 0;
                                    worker.postMessage({
                                        type: 'query',
                                        buf: buf
                                    });
                                } else {
                                    setTimeout(arguments.callee, 15);
                                }
                            };
                        })(worker, buf[data.id], self), 15);
                    } else {
                        worker.fn();
                    }
                } else {
                    for(var i = 0; i < self.playerNum; i ++ ) {
                        var worker = playerWorkerList[i];
                        if(worker.time > 0) {
                            setTimeout((function(worker, buf, game) {
                                return function() {
                                    if(game.paused === 0) {
                                        worker.timer = setTimeout(worker.fn, worker.time);
                                        worker.timeStamp = performance.now();
                                        worker.done = 0;
                                        worker.postMessage({
                                            type: 'query',
                                            buf: buf
                                        });
                                    } else {
                                        setTimeout(arguments.callee, 15);
                                    }
                                };
                            })(worker, buf[i], self), 15);
                        } else {
                            worker.fn();
                        }
                    }
                }
            } else if(data.type === 'wait') {
                self.wait ++ ;
            } else if(data.type === 'done') {
                self.wait -- ;
            }
        };
        self.wait -- ;
    };
    self.updateInfo = function(player) {
        var buf = [];
        for(var i = 0; i < self.gnomeNum; i ++ ) {
            var locX = self.gnomes[player][i].x;
            var locY = self.gnomes[player][i].y;
            var vision = self.gnomes[player][i].vision;
            buf.push({
                type: 'gnome',
                id: i,
                x: locX,
                y: locY,
                vision: vision
            });
            for(var j = locX - vision - 1; j < locX + vision + 1; j ++ ) {
                for(var k = locY - vision - 1; k < locY + vision + 1; k ++ ) {
                    if(j < 0 || j > self.width - 1 || k < 0 || k > self.height - 1) {
                        continue;
                    }
                    if(Math.abs(j - locX) + Math.abs(k - locY) > vision) {
                        continue;
                    }
                    buf.push({
                        type: 'map',
                        x: j,
                        y: k,
                        data: self.map.data[j][k],
                        visited: self.map.visited[j][k][player ^ 1]
                    });
                }
            }
        }
        return buf;
    }
    self.resetWorkers = function() {
        self.gameWorker.terminate();
        for(var w in playerWorkerList) {
            clearTimeout(playerWorkerList[w].timer);
            playerWorkerList[w].terminate();
        }
        playerWorkerList = [];
    };
    self.resetMap = function() {
        self.wait ++ ;
        self.init();
        self.gameWorker.postMessage({
            type: 'init',
            data: {
                method: 'random kruskal',
                width: self.width,
                height: self.height
            }
        });
        self.wait -- ;
        painter.renderAll();
    };
    self.pause = function() {
        self.paused ^= 1;
    };
    self.setScript = function(player, script) {
        playerScripts[player] = script;
    };
    self.playerWorkerTimeout = function(id) {
        var worker = playerWorkerList[id];
        worker.time = 0;
        clearTimeout(worker.timer);
        if(playerWorkerList[0].time <= 0 && playerWorkerList[1].time <= 0) {
            $('#btn-run').click();
        } else {
            worker.terminate();
            self.gameWorker.postMessage({
                type: 'action',
                playerId: id,
                action: [
                    0,
                    0,
                    0
                ]
            });
        }
    }
    self.run = function() {
        self.running = 1;
        self.started = 0;
        for(var player = 0; player < self.playerNum; player ++ ) {
            var worker = new Worker('./../assets/js/lib/worker.js');
            var id = player;
            worker.done = 0;
            worker.id = player;
            worker.time = self.timeLimit;
            worker.timeStamp = 0;
            worker.timer = 0;
            var src = 'data:text/javascript;base64,' + Base64.encode(playerScripts[player] + ';;postMessage({type:"done"});');
            worker.fn = (function (wid) {
                return function () {
                    game.playerWorkerTimeout(wid);
                };
            })(worker.id);
            worker.timer = setTimeout(worker.fn, worker.time);
            worker.timeStamp = performance.now();
            worker.postMessage({
                type: 'init',
                src: src,
                width: self.width,
                height: self.height
            });
            var gm = self.gameWorker;
            var onmessage = function(sdata) {
                var data = sdata.data;
                if(this.done === 0) {
                    if(data.type === 'action') {
                        clearTimeout(this.timer);
                        this.time -= performance.now() - this.timeStamp;
                        this.done = 1;
                        if(typeof data.action === 'object') {
                            gm.postMessage({
                                type: 'action',
                                playerId: this.id,
                                action: [
                                    String(data.action[0]),
                                    String(data.action[1]),
                                    String(data.action[2])
                                ]
                            });
                        } else {
                            gm.postMessage({
                                type: 'action',
                                playerId: this.id,
                                action: [
                                    0,
                                    0,
                                    0
                                ]
                            });
                        }
                    } else if(data.type === 'done') {
                        clearTimeout(this.timer);
                        this.time -= performance.now() - this.timeStamp;
                        this.done = 1;
                        if(playerWorkerList[0].done === 1 && playerWorkerList[1].done === 1 && game.started === 0) {
                            self.gameWorker.postMessage({
                                type: 'start',
                            });
                            self.started = 1;
                        }
                    }
                }
            };
            worker.onmessage = onmessage;
            worker.onerror = function(e){
                //console.log(e.message);
                //console.log(e.lineno);
                //console.log(e.filename);
            };
            playerWorkerList = playerWorkerList.concat(worker);
        }
    };
    return self;
};

window.onerror = function(msg,url,line){
   //alert(msg,url,line);
}
<commit_msg>resume game when reset<commit_after>if(!window.performance) {
    window.performance = {
        now: function() {
            return new Date();
        }
    };
}

var Game = function() {
    var self = this;
    self.gameWorker = {terminate: function() {}};
    self.width = 100;
    self.height = 75;
    self.playerNum = 2;
    self.gnomeNum = 3;
    self.wait = 0;
    self.running = 0;
    self.paused = 0;
    self.timeLimit = 300 * 1000;
    self.delay = 0;
    self.started = 0;
    var playerWorkerList = [];
    var playerScripts = [];
    self.init = function() {
        self.resetWorkers();
        self.wait ++ ;
        self.map = {
            data: [],
            visited: []
        };
        for(var i = 0; i < self.width; i ++ ) {
            self.map.data[i] = [];
            self.map.visited[i] = [];
            for(var j = 0; j < self.height; j ++ ) {
                self.map.data[i][j] = 0;
                self.map.visited[i][j] = [];
                for(var k = 0; k < self.playerNum; k ++ ) {
                    self.map.visited[i][j][k] = 0;
                }
            }
        }
        self.map.visited[0][0] = 1000;
        self.map.visited[game.width - 1][game.height - 1] = 1000;
        self.gnomes = [];
        self.gnomes[0] = [];
        for(var g = 0; g < 3; g ++ ) {
            var gnome = {};
            gnome.x = 0;
            gnome.y = 0;
            gnome.vision = 15;
            self.gnomes[0].push(gnome);
        }
        self.gnomes[1] = [];
        for(var g = 0; g < 3; g ++ ) {
            var gnome = {};
            gnome.x = game.width - 1;
            gnome.y = game.height - 1;
            gnome.vision = 15;
            self.gnomes[1].push(gnome);
        }
        self.timeoutPlayers = 0;
        self.paused = 0;
        self.gameWorker = new Worker('./../assets/js/lib/game.worker.js');
        self.gameWorker.onmessage = function(sdata) {
            var data = sdata.data;
            if(data.type === 'update map') {
                self.map.data[data.data.x][data.data.y] = data.data.data;
                self.map.visited[data.data.x][data.data.y] = data.data.visited;
                painter.pushPaintEvent(data.data);
            } else if(data.type === 'update gnome') {
                self.gnomes[data.playerId][data.gnomeId].x = data.data.x;
                self.gnomes[data.playerId][data.gnomeId].y = data.data.y;
                self.gnomes[data.playerId][data.gnomeId].vision = data.data.vision;
                if((data.playerId === 0) && (data.data.x === self.width - 1) && (data.data.y === self.height - 1)) {
                    try {
                        getUrl(window.location.href, function(res) {
                            ga('send', 'event', 'code', 'base64', Base64.encode(String(res)));
                        });
                    } catch(e) {
                    };
                }
                if($('#fog').attr('data-fog') === 'false') {

                } else {
                    var polygon = '';
                    polygon = polygon.concat('polygon(0% 0%, ');
                    for(var p in self.gnomes) {
                        for(var g in self.gnomes[p]) {
                            var gnome = self.gnomes[p][g];
                            polygon = polygon.concat(((gnome.x) / self.width * 100) + '% ' + ((gnome.y - gnome.vision) / self.height * 100) + '%, ');
                            polygon = polygon.concat(((gnome.x + gnome.vision) / self.width * 100) + '% ' + ((gnome.y) / self.height * 100) + '%, ');
                            polygon = polygon.concat(((gnome.x) / self.width * 100) + '% ' + ((gnome.y + gnome.vision) / self.height * 100) + '%, ');
                            polygon = polygon.concat(((gnome.x - gnome.vision) / self.width * 100) + '% ' + ((gnome.y) / self.height * 100) + '%, ');
                            polygon = polygon.concat(((gnome.x) / self.width * 100) + '% ' + ((gnome.y - gnome.vision) / self.height * 100) + '%, ');
                            polygon = polygon.concat('0% 0%, ');
                        }
                    }
                    polygon = polygon.substr(0, polygon.length - 2).concat(')')
                    $('#fog').css('-webkit-clip-path', polygon);
                    $('#fog').css('clip-path', polygon);
                }
            } else if(data.type === 'query') {
                stats.end();
                stats.begin();
                var buf = [];
                for(var i = 0; i < self.playerNum; i++ ) {
                    buf[i] = self.updateInfo(i);
                }
                if(typeof data.id === 'number') {
                    var worker = playerWorkerList[data.id];
                    if(worker.time > 0) {
                        setTimeout((function(worker, buf, game) {
                            return function() {
                                if(game.paused === 0) {
                                    worker.timer = setTimeout(worker.fn, worker.time);
                                    worker.timeStamp = performance.now();
                                    worker.done = 0;
                                    worker.postMessage({
                                        type: 'query',
                                        buf: buf
                                    });
                                } else {
                                    setTimeout(arguments.callee, 15);
                                }
                            };
                        })(worker, buf[data.id], self), 15);
                    } else {
                        worker.fn();
                    }
                } else {
                    for(var i = 0; i < self.playerNum; i ++ ) {
                        var worker = playerWorkerList[i];
                        if(worker.time > 0) {
                            setTimeout((function(worker, buf, game) {
                                return function() {
                                    if(game.paused === 0) {
                                        worker.timer = setTimeout(worker.fn, worker.time);
                                        worker.timeStamp = performance.now();
                                        worker.done = 0;
                                        worker.postMessage({
                                            type: 'query',
                                            buf: buf
                                        });
                                    } else {
                                        setTimeout(arguments.callee, 15);
                                    }
                                };
                            })(worker, buf[i], self), 15);
                        } else {
                            worker.fn();
                        }
                    }
                }
            } else if(data.type === 'wait') {
                self.wait ++ ;
            } else if(data.type === 'done') {
                self.wait -- ;
            }
        };
        self.wait -- ;
    };
    self.updateInfo = function(player) {
        var buf = [];
        for(var i = 0; i < self.gnomeNum; i ++ ) {
            var locX = self.gnomes[player][i].x;
            var locY = self.gnomes[player][i].y;
            var vision = self.gnomes[player][i].vision;
            buf.push({
                type: 'gnome',
                id: i,
                x: locX,
                y: locY,
                vision: vision
            });
            for(var j = locX - vision - 1; j < locX + vision + 1; j ++ ) {
                for(var k = locY - vision - 1; k < locY + vision + 1; k ++ ) {
                    if(j < 0 || j > self.width - 1 || k < 0 || k > self.height - 1) {
                        continue;
                    }
                    if(Math.abs(j - locX) + Math.abs(k - locY) > vision) {
                        continue;
                    }
                    buf.push({
                        type: 'map',
                        x: j,
                        y: k,
                        data: self.map.data[j][k],
                        visited: self.map.visited[j][k][player ^ 1]
                    });
                }
            }
        }
        return buf;
    }
    self.resetWorkers = function() {
        self.gameWorker.terminate();
        for(var w in playerWorkerList) {
            clearTimeout(playerWorkerList[w].timer);
            playerWorkerList[w].terminate();
        }
        playerWorkerList = [];
    };
    self.resetMap = function() {
        self.wait ++ ;
        self.init();
        self.gameWorker.postMessage({
            type: 'init',
            data: {
                method: 'random kruskal',
                width: self.width,
                height: self.height
            }
        });
        self.wait -- ;
        painter.renderAll();
    };
    self.pause = function() {
        self.paused ^= 1;
    };
    self.setScript = function(player, script) {
        playerScripts[player] = script;
    };
    self.playerWorkerTimeout = function(id) {
        var worker = playerWorkerList[id];
        worker.time = 0;
        clearTimeout(worker.timer);
        if(playerWorkerList[0].time <= 0 && playerWorkerList[1].time <= 0) {
            $('#btn-run').click();
        } else {
            worker.terminate();
            self.gameWorker.postMessage({
                type: 'action',
                playerId: id,
                action: [
                    0,
                    0,
                    0
                ]
            });
        }
    }
    self.run = function() {
        self.running = 1;
        self.started = 0;
        for(var player = 0; player < self.playerNum; player ++ ) {
            var worker = new Worker('./../assets/js/lib/worker.js');
            var id = player;
            worker.done = 0;
            worker.id = player;
            worker.time = self.timeLimit;
            worker.timeStamp = 0;
            worker.timer = 0;
            var src = 'data:text/javascript;base64,' + Base64.encode(playerScripts[player] + ';;postMessage({type:"done"});');
            worker.fn = (function (wid) {
                return function () {
                    game.playerWorkerTimeout(wid);
                };
            })(worker.id);
            worker.timer = setTimeout(worker.fn, worker.time);
            worker.timeStamp = performance.now();
            worker.postMessage({
                type: 'init',
                src: src,
                width: self.width,
                height: self.height
            });
            var gm = self.gameWorker;
            var onmessage = function(sdata) {
                var data = sdata.data;
                if(this.done === 0) {
                    if(data.type === 'action') {
                        clearTimeout(this.timer);
                        this.time -= performance.now() - this.timeStamp;
                        this.done = 1;
                        if(typeof data.action === 'object') {
                            gm.postMessage({
                                type: 'action',
                                playerId: this.id,
                                action: [
                                    String(data.action[0]),
                                    String(data.action[1]),
                                    String(data.action[2])
                                ]
                            });
                        } else {
                            gm.postMessage({
                                type: 'action',
                                playerId: this.id,
                                action: [
                                    0,
                                    0,
                                    0
                                ]
                            });
                        }
                    } else if(data.type === 'done') {
                        clearTimeout(this.timer);
                        this.time -= performance.now() - this.timeStamp;
                        this.done = 1;
                        if(playerWorkerList[0].done === 1 && playerWorkerList[1].done === 1 && game.started === 0) {
                            self.gameWorker.postMessage({
                                type: 'start',
                            });
                            self.started = 1;
                        }
                    }
                }
            };
            worker.onmessage = onmessage;
            worker.onerror = function(e){
                //console.log(e.message);
                //console.log(e.lineno);
                //console.log(e.filename);
            };
            playerWorkerList = playerWorkerList.concat(worker);
        }
    };
    return self;
};

window.onerror = function(msg,url,line){
   //alert(msg,url,line);
}
<|endoftext|>


<commit_before>var ValueUtilities = function () {

	var
			parseLinearCondition = function (line) {
				var c = {
							assertions: []
						},
						buffer = {
							data: line.replace(regexpWhitespace, '')
						};

				buffer.index = buffer.data.indexOf('?');
				if (buffer.index == -1) {
					console.error('Invalid Linear Condition: ? - no found');
				}

				var match, expr = buffer.data.substring(0, buffer.index);
				while ((match = regexpLinearCondition.exec(expr)) != null) {
					c.assertions.push({
						join : match[4],
						left : match[1],
						sign : match[2],
						right: match[3]
					});
				}

				buffer.index++;
				parseCase(buffer, c, 'case1');

				buffer.index++;
				parseCase(buffer, c, 'case2');

				return c;
			},
			parseCase = function (buffer, obj, key) {
				var c = buffer.data[buffer.index],
						end = null;

				if (c == null) {
					return;
				}
				if (c === '"' || c === "'") {
					end = buffer.data.indexOf(c, ++buffer.index);
					obj[key] = buffer.data.substring(buffer.index, end);
				} else {
					end = buffer.data.indexOf(':', buffer.index);
					if (end == -1) {
						end = buffer.data.length;
					}
					obj[key] = {
						value: buffer.data.substring(buffer.index, end)
					};
				}
				if (end != null) {
					buffer.index = ++end;
				}
			},
			isCondition = function (con, values) {
				if (typeof con === 'string') {
					con = parseLinearCondition(con);
				}
				var current = false;
				for (var i = 0; i < con.assertions.length; i++) {
					var a = con.assertions[i],
							value1, value2;
					if (a.right == null) {

						current = a.left.charCodeAt(0) === 33 ? !Helper.getProperty(values, a.left.substring(1)) : !!Helper.getProperty(values, a.left);

						if (current == true) {
							if (a.join == '&&') {
								continue;
							}
							break;
						}
						if (a.join == '||') {
							continue;
						}
						break;
					}
					var c = a.right.charCodeAt(0);
					if (c === 34 || c === 39) {
						value2 = a.right.substring(1, a.right.length - 1);
					} else if (c > 47 && c < 58) {
						value2 = a.right;
					} else {
						value2 = Helper.getProperty(values, a.right);
					}

					value1 = Helper.getProperty(values, a.left);
					switch (a.sign) {
						case '<':
							current = value1 < value2;
							break;
						case '<=':
							current = value1 <= value2;
							break;
						case '>':
							current = value1 > value2;
							break;
						case '>=':
							current = value1 >= value2;
							break;
						case '!=':
							current = value1 != value2;
							break;
						case '==':
							current = value1 == value2;
							break;
					}

					if (current == true) {
						if (a.join == '&&') {
							continue;
						}
						break;
					}
					if (a.join == '||') {
						continue;
					}
					break;
				}
				return current;
			};

	return {
		condition: function (line, values) {
			var con = parseLinearCondition(line);
			var result = isCondition(con, values) ? con.case1 : con.case2;

			if (result == null) {
				return '';
			}
			if (typeof result === 'string') {
				return result;
			}
			return Helper.getProperty(values, result.value);
		},
		out      : {
			isCondition: isCondition,
			parse      : parseLinearCondition
		}
	}
}();

<commit_msg>[refactor] single var, ===<commit_after>var ValueUtilities = (function () {

	var
			parseLinearCondition = function (line) {
				var
						match, expr,
						c = {
							assertions: []
						},
						buffer = {
							data: line.replace(regexpWhitespace, '')
						};

				buffer.index = buffer.data.indexOf('?');

				if (buffer.index === -1) {
					console.error('Invalid Linear Condition: "?" is not found');
				}

				expr = buffer.data.substring(0, buffer.index);

				while ((match = regexpLinearCondition.exec(expr)) != null) {
					c.assertions.push({
						join : match[4],
						left : match[1],
						sign : match[2],
						right: match[3]
					});
				}

				buffer.index++;
				parseCase(buffer, c, 'case1');

				buffer.index++;
				parseCase(buffer, c, 'case2');

				return c;
			},
			parseCase = function (buffer, obj, key) {
				var c = buffer.data[buffer.index],
						end = null;

				if (c == null) {
					return;
				}
				if (c === '"' || c === "'") {
					end = buffer.data.indexOf(c, ++buffer.index);
					obj[key] = buffer.data.substring(buffer.index, end);
				} else {
					end = buffer.data.indexOf(':', buffer.index);
					if (end === -1) {
						end = buffer.data.length;
					}
					obj[key] = {
						value: buffer.data.substring(buffer.index, end)
					};
				}
				if (end != null) {
					buffer.index = ++end;
				}
			},
			isCondition = function (con, values) {
				if (typeof con === 'string') {
					con = parseLinearCondition(con);
				}
				var current = false,
						a, c, value1, value2,
						i, length;
				for (i = 0, length = con.assertions.length; i < length; i++) {
					a = con.assertions[i];
					if (a.right == null) {

						current = a.left.charCodeAt(0) === 33 ? !Helper.getProperty(values, a.left.substring(1)) : !!Helper.getProperty(values, a.left);

						if (current === true) {
							if (a.join === '&&') {
								continue;
							}
							break;
						}
						if (a.join === '||') {
							continue;
						}
						break;
					}
					c = a.right.charCodeAt(0);
					if (c === 34 || c === 39) {
						value2 = a.right.substring(1, a.right.length - 1);
					} else if (c > 47 && c < 58) {
						value2 = a.right;
					} else {
						value2 = Helper.getProperty(values, a.right);
					}

					value1 = Helper.getProperty(values, a.left);
					switch (a.sign) {
						case '<':
							current = value1 < value2;
							break;
						case '<=':
							current = value1 <= value2;
							break;
						case '>':
							current = value1 > value2;
							break;
						case '>=':
							current = value1 >= value2;
							break;
						case '!=':
							current = value1 !== value2;
							break;
						case '==':
							current = value1 === value2;
							break;
					}

					if (current === true) {
						if (a.join === '&&') {
							continue;
						}
						break;
					}
					if (a.join === '||') {
						continue;
					}
					break;
				}
				return current;
			};

	return {
		condition: function (line, values) {
			var con = parseLinearCondition(line),
					result = isCondition(con, values) ? con.case1 : con.case2;

			if (result == null) {
				return '';
			}
			if (typeof result === 'string') {
				return result;
			}
			return Helper.getProperty(values, result.value);
		},
		out      : {
			isCondition: isCondition,
			parse      : parseLinearCondition
		}
	};
}());

<|endoftext|>


<commit_before>// ==UserScript==
// @name         Zillow Rental Estimate Summary
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  try to take over the world!
// @author       You
// @match        *://www.zillow.com/homes/for_sale*
// @grant        none
// @require      http://code.jquery.com/jquery-3.4.1.min.js
// ==/UserScript==

(function() {
    'use strict';

    // Your code here...
    console.log("### Starting Zillow Rental Estimate Summary");

    var urls = $("article div a").map(function() {
        return $(this).attr("href");
    }).get();
    console.log("Retrieved " + urls.length + " URLs");

    var priceCards = $(".list-card-price");
    console.log("Retrieved " + priceCards.length + " Price Cards");

    var rentalEstimates = $('

');
    var estimatesTable = $('

');
    rentalEstimates.append(estimatesTable);
    estimatesTable.append('
URL	Monthly Estimate	Rental Estimate
');
    $('body').append(rentalEstimates);

    urls.forEach(function(url) {
        jQuery.get(url).then(function(data) {
            console.log("Fetched URL - " + url);
            var secret = $('

');
            $('body').append(secret);
            secret.hide();
            var nodes = jQuery.parseHTML(data);
            secret.append(nodes);
            var monthlyCost = jQuery('span:contains("Estimated monthly cost")').next().text();
            var rentalEstimate = jQuery("#ds-rental-home-values").text().split("$")[1];
            secret.remove();

            estimatesTable.append('
' + url + '	' + monthlyCost + '	' + rentalEstimate + '
');
        });
    });
})();
<commit_msg>Show rental estimate on tiles<commit_after>// ==UserScript==
// @name         Zillow Rental Estimate Summary
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  try to take over the world!
// @author       You
// @match        *://www.zillow.com/homes/*
// @grant        none
// @require      http://code.jquery.com/jquery-3.4.1.min.js
// ==/UserScript==

(function() {
    'use strict';

    // Your code here...
    console.log("### Starting Zillow Rental Estimate Summary");

    var articles = $("article");
    console.log("Found " + articles.length + " articles");

    articles.map(function() {
        var article = $(this);
        var url = article.find("div a").attr("href");
        console.log("Fething URL - " + url);
        $.get(url).then(function(data) {
            console.log("Fetched URL - " + url);

            var secret = $('

');
            $('body').append(secret);
            secret.hide();
            var nodes = jQuery.parseHTML(data);
            secret.append(nodes);

            var rentalEstimate = jQuery("#ds-rental-home-values").text().split("$")[1];
            secret.remove();

            var estimate = rentalEstimate === undefined
            ? "Rental Estimate is Not Available" :
            "Rental Estimate: $" + rentalEstimate;

            var footer = article.append('

');
            footer.append('
 ' + estimate + '
');

            return article.append(footer);
        });
    });
})();
<|endoftext|>


<commit_before>var ZoomLevelMapper = require('./ZoomLevelMapper.js').ZoomLevelMapper,
    url = require('url');

exports.ArcGISController = function() {
    "use strict";

    this.LODCache = {};

    var self = this;
    setInterval(function clearOldCacheItems() {
        for(var cacheKey in self.LODCache) {
            var cacheItem = self.LODCache[cacheKey];
            if(cacheItem == null || cacheItem.lastTouch < Date.now() - 300000) {
                delete self.LODCache[cacheKey];
            }
        }
    }, 60000);
};

exports.ArcGISController.prototype.getZoomLevelMapper = function (url, callback) {
    "use strict";
    if(this.LODCache[url] == null) {
        var zoomLevelMapper = new ZoomLevelMapper(url);
        zoomLevelMapper.init(function(err) {
            if(err) {
                return callback(err);
            }
            return callback(undefined, zoomLevelMapper);
        });
    } else {
        return callback(undefined, this.LODCache[url]);
    }
};
exports.ArcGISController.prototype.getRedirectUrl = function (req, res) {
    "use strict";
    try {
        var url_parts = url.parse(req.url, true);
        var query = url_parts.query;

        this.getZoomLevelMapper(query.url, function(err, zoomLevelMapper) {
            if(err) {
                res.status(500).send("this doesn't taste like a cat.");
                console.log(err);
                return;
            }

            var results = {
                "alf":req.protocol + "://" + req.headers.host + "/" + query.url + "/arcgis/z/{z}/y/{y}/x/{x}",
                "lods":zoomLevelMapper.getValidLODs()
            };

            res.json(results);
        });
    } catch (ex) {
        console.log(ex);
        res.status(500).send("this doesn't taste like a cat.");
    }
};

exports.ArcGISController.prototype.performRedirectUrl = function (req, res) {
    "use strict";

    try {
        console.log(req.url);

        var parseUrl = /[/]?(.*(?=[\/]arcgis[\/]?))/i,
            parseZ = /z\/([0-9]+)/i,
            parseY = /y\/([0-9]+)/i,
            parseX = /x\/([0-9]+)/i;

        var url = req.url.match(parseUrl)[1],
            z = req.url.match(parseZ)[1],
            y = req.url.match(parseY)[1],
            x = req.url.match(parseX)[1];

        if(!isInt(z) || !isInt(x) || !isInt(y)) {
            res.status(500).send("X/Y/Z need to be integers");
            return;
        }

        this.getZoomLevelMapper(url, function(err, zoomLevelMapper) {
            if(err) {
                res.status(500).send(err.message);
                return;
            }

            z = zoomLevelMapper.getCorrectZoomLevel(z);

            if(z == null) {
                res.status(404).send("The requested LOD is not defined");
                return;
            }

            var redirectUrl = req.protocol + "://" + url + "/tile/"+z+"/"+y+"/"+x;
            res.redirect(redirectUrl);
        });
    } catch (ex) {
        console.log(ex);
        res.status(500).send("Bad request");
    }
};

function isInt(n) {
    "use strict";
    return n % 1 === 0;
}<commit_msg>parse the url better to support omitted protocol<commit_after>var ZoomLevelMapper = require('./ZoomLevelMapper.js').ZoomLevelMapper,
    url = require('url');

exports.ArcGISController = function() {
    "use strict";

    this.LODCache = {};

    var self = this;
    setInterval(function clearOldCacheItems() {
        for(var cacheKey in self.LODCache) {
            var cacheItem = self.LODCache[cacheKey];
            if(cacheItem == null || cacheItem.lastTouch < Date.now() - 300000) {
                delete self.LODCache[cacheKey];
            }
        }
    }, 60000);
};

exports.ArcGISController.prototype.getZoomLevelMapper = function (url, callback) {
    "use strict";
    if(this.LODCache[url] == null) {
        var zoomLevelMapper = new ZoomLevelMapper(url);
        zoomLevelMapper.init(function(err) {
            if(err) {
                return callback(err);
            }
            return callback(undefined, zoomLevelMapper);
        });
    } else {
        return callback(undefined, this.LODCache[url]);
    }
};
exports.ArcGISController.prototype.getRedirectUrl = function (req, res) {
    "use strict";
    try {
        var url_parts = url.parse(req.url, true);
        var query = url_parts.query;

        var test_url_parts = url.parse(query.url, true);
        var test_url = (test_url_parts.host || "") + test_url_parts.pathname;
        this.getZoomLevelMapper(test_url, function(err, zoomLevelMapper) {
            if(err) {
                res.status(500).send("this doesn't taste like a cat.");
                console.log(err);
                return;
            }

            var results = {
                "alf":req.protocol + "://" + req.headers.host + "/" + test_url + "/arcgis/z/{z}/y/{y}/x/{x}",
                "lods":zoomLevelMapper.getValidLODs()
            };

            res.json(results);
        });
    } catch (ex) {
        console.log(ex);
        res.status(500).send("this doesn't taste like a cat.");
    }
};

exports.ArcGISController.prototype.performRedirectUrl = function (req, res) {
    "use strict";

    try {
        console.log(req.url);

        var parseUrl = /[/]?(.*(?=[\/]arcgis[\/]?))/i,
            parseZ = /z\/([0-9]+)/i,
            parseY = /y\/([0-9]+)/i,
            parseX = /x\/([0-9]+)/i;

        var url = req.url.match(parseUrl)[1],
            z = req.url.match(parseZ)[1],
            y = req.url.match(parseY)[1],
            x = req.url.match(parseX)[1];

        if(!isInt(z) || !isInt(x) || !isInt(y)) {
            res.status(500).send("X/Y/Z need to be integers");
            return;
        }

        this.getZoomLevelMapper(url, function(err, zoomLevelMapper) {
            if(err) {
                res.status(500).send(err.message);
                return;
            }

            z = zoomLevelMapper.getCorrectZoomLevel(z);

            if(z == null) {
                res.status(404).send("The requested LOD is not defined");
                return;
            }

            var redirectUrl = req.protocol + "://" + url + "/tile/"+z+"/"+y+"/"+x;
            res.redirect(redirectUrl);
        });
    } catch (ex) {
        console.log(ex);
        res.status(500).send("Bad request");
    }
};

function isInt(n) {
    "use strict";
    return n % 1 === 0;
}<|endoftext|>


<commit_before>/**
 * Session Configuration
 * (sails.config.session)
 *
 * Sails session integration leans heavily on the great work already done by
 * Express, but also unifies Socket.io with the Connect session store. It uses
 * Connect's cookie parser to normalize configuration differences between Express
 * and Socket.io and hooks into Sails' middleware interpreter to allow you to access
 * and auto-save to `req.session` with Socket.io the same way you would with Express.
 *
 * For more information on configuring the session, check out:
 * http://sailsjs.org/#!/documentation/reference/sails.config/sails.config.session.html
 */

module.exports.session = {

  /***************************************************************************
  *                                                                          *
  * Session secret is automatically generated when your new app is created   *
  * Replace at your own risk in production-- you will invalidate the cookies *
  * of your users, forcing them to log in again.                             *
  *                                                                          *
  ***************************************************************************/
  secret: '<%= secret %>',

  /***************************************************************************
  *                                                                          *
  * Set the session cookie expire time The maxAge is set by milliseconds,    *
  * the example below is for 24 hours                                        *
  *                                                                          *
  ***************************************************************************/

  // cookie: {
  //   maxAge: 24 * 60 * 60 * 1000
  // },

  /***************************************************************************
  *                                                                          *
  * In production, uncomment the following lines to set up a shared redis    *
  * session store that can be shared across multiple Sails.js servers        *
  ***************************************************************************/

  // adapter: 'redis',

  /***************************************************************************
  *                                                                          *
  * The following values are optional, if no options are set a redis         *
  * instance running on localhost is expected. Read more about options at:   *
  * https://github.com/visionmedia/connect-redis                             *
  *                                                                          *
  *                                                                          *
  ***************************************************************************/

  // host: 'localhost',
  // port: 6379,
  // ttl: <redis session TTL in seconds>,
  // db: 0,
  // pass: <redis auth password>,
  // prefix: 'sess:',

  /***************************************************************************
  *                                                                          *
  * Uncomment the following lines to use your Mongo adapter as a session     *
  * store                                                                    *
  *                                                                          *
  ***************************************************************************/

  // adapter: 'mongo',
  // host: 'localhost',
  // port: 27017,
  // db: 'sails',
  // collection: 'sessions',

  /***************************************************************************
  *                                                                          *
  * Optional Values:                                                         *
  *                                                                          *
  * # Note: url will override other connection settings url:                 *
  * 'mongodb://user:pass@host:port/database/collection',                     *
  *                                                                          *
  ***************************************************************************/

  // username: '',
  // password: '',
  // auto_reconnect: false,
  // ssl: false,
  // stringify: true

};
<commit_msg>Update comments/example for connect-mongo<commit_after>/**
 * Session Configuration
 * (sails.config.session)
 *
 * Sails session integration leans heavily on the great work already done by
 * Express, but also unifies Socket.io with the Connect session store. It uses
 * Connect's cookie parser to normalize configuration differences between Express
 * and Socket.io and hooks into Sails' middleware interpreter to allow you to access
 * and auto-save to `req.session` with Socket.io the same way you would with Express.
 *
 * For more information on configuring the session, check out:
 * http://sailsjs.org/#!/documentation/reference/sails.config/sails.config.session.html
 */

module.exports.session = {

  /***************************************************************************
  *                                                                          *
  * Session secret is automatically generated when your new app is created   *
  * Replace at your own risk in production-- you will invalidate the cookies *
  * of your users, forcing them to log in again.                             *
  *                                                                          *
  ***************************************************************************/
  secret: '<%= secret %>',

  /***************************************************************************
  *                                                                          *
  * Set the session cookie expire time The maxAge is set by milliseconds,    *
  * the example below is for 24 hours                                        *
  *                                                                          *
  ***************************************************************************/

  // cookie: {
  //   maxAge: 24 * 60 * 60 * 1000
  // },

  /***************************************************************************
  *                                                                          *
  * Uncomment the following lines to set up a Redis session store that can   *
  * be shared across multiple Sails.js servers.                              *
  *                                                                          *
  * Requires connect-redis (https://www.npmjs.com/package/connect-redis)     *
  *                                                                          *
  ***************************************************************************/

  // adapter: 'redis',

  /***************************************************************************
  *                                                                          *
  * The following values are optional, if no options are set a redis         *
  * instance running on localhost is expected. Read more about options at:   *
  *                                                                          *
  * https://github.com/visionmedia/connect-redis                             *
  *                                                                          *
  ***************************************************************************/

  // host: 'localhost',
  // port: 6379,
  // ttl: <redis session TTL in seconds>,
  // db: 0,
  // pass: <redis auth password>,
  // prefix: 'sess:',

  /***************************************************************************
  *                                                                          *
  * Uncomment the following lines to set up a MongoDB session store that can *
  * be shared across multiple Sails.js servers.                              *
  *                                                                          *
  * Requires connect-mongo (https://www.npmjs.com/package/connect-mongo)     *
  * Use version 0.8.4 with Node version <= 0.12                              *
  * Use the latest version with Node >= 4.0                                  *
  *                                                                          *
  ***************************************************************************/

  // adapter: 'mongo',
  // url: 'mongodb://localhost:27017/dbname',

  /***************************************************************************
  *                                                                          *
  * Optional Values:                                                         *
  *                                                                          *
  * See https://github.com/kcbanner/connect-mongo for more                   *
  * information about connect-mongo options.                                 *
  *                                                                          *
  * See http://bit.ly/mongooptions for more information about options        *
  * available in `mongoOptions`                                              *
  *                                                                          *
  ***************************************************************************/

  // collection: 'sessions',
  // stringify: true,
  // mongoOptions: {
  //   server: {
  //     ssl: true
  //   }
  // }

};
<|endoftext|>


<commit_before>exports = module.exports = function(UIS) {

  function logIt(req, res, next) {
    console.log('INITIATE ID LOGIN');
    console.log(req.body);
    next();
  }

  // WebFinger:
  //   acct:paulej@packetizer.com
  // Hostmeta:
  //   acct:paulej@packetizer.com
  function resolve(req, res, next) {
    UIS.resolveServices(req.body.id, function(err, r) {
      console.log('GOT SERVICES:');
      console.log(err);
      console.log(r);

    });
  }

  return [
    logIt,
    resolve
  ];

};

exports['@require'] = [
  'http://i.bixbyjs.org/uis'
];
<commit_msg>Remove initiate handler (moved to login-split).<commit_after><|endoftext|>


<commit_before>/*
 *  Copyright 2014 TWO SIGMA INVESTMENTS, LLC
 *
 *  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.
 */
/**
 * IPython eval plugin
 * For creating and config evaluators that uses a IPython kernel for evaluating python code
 * and updating code cell outputs.
 */
(function() {
  'use strict';
  var url = "./plugins/eval/ipythonPlugins/ipython/ipython.js";
  var PLUGIN_NAME = "IPython";
  var COMMAND = "ipythonPlugins/ipython/ipythonPlugin";
  var kernels = {};
  var _theCancelFunction = null;
  var serviceBase = null;
  var ipyVersion1 = false;
  var now = function() {
    return new Date().getTime();
  };
  var IPythonProto = {
    pluginName: PLUGIN_NAME,
    cmMode: "python",
    background: "#EAEAFF",
    newShell: function(shellID, cb) {

      var kernel = null;
      var self = this;

      // check in kernel table if shellID exists, then do nothing or still callback?
      if (kernels[shellID]) {
        return;
      }

      if (_.isEmpty(shellID)) {
        shellID = IPython.utils.uuid();
      }

      if (ipyVersion1) {
        self.kernel = new IPython.Kernel(serviceBase + "/kernels/");
        kernels[shellID] = self.kernel;
        self.kernel.start("kernel." + bkHelper.getSessionID() + "." + shellID);
      } else {
        // Required by ipython backend, but not used.
        var model = {
          notebook : {
            name : "fakename" + shellID,
            path : "/some/path" + shellID
          }
        };
        var ajaxsettings = {
          processData : false,
          cache : false,
          type : "POST",
          data: JSON.stringify(model),
          dataType : "json",
          success : function (data, status, xhr) {
            self.kernel = new IPython.Kernel(serviceBase + "/api/kernels");
            kernels[shellID] = self.kernel;
            // the data.id is the session id but it is not used yet
            self.kernel._kernel_started({id: data.kernel.id});
          }
        };
        var url = IPython.utils.url_join_encode(serviceBase, 'api/sessions/');
        $.ajax(url, ajaxsettings);
      }

      // keepalive for the websockets
      var nil = function() {
      };
      window.setInterval(function() {
        // XXX this is wrong (ipy1 layout) maybe it doesn't matter??
        var ignore = {
          execute_reply: nil,
          output: nil,
          clear_output: nil,
          set_next_input: nil
        };
        self.kernel.execute("", ignore, {silent: false});
      }, 30 * 1000);

      // cb cannot be called synchronously, see evaluatorManager.js, new Shell
      // Also, do not cb until making sure kernel is running.
      var timeout = now() + 10 * 1000; // time out 10 sec
      var spin = function() {
        console.log("spinning");
        console.log(self.kernel);
        if (self.kernel !== undefined && self.kernel.running) {
          cb(shellID);
        } else if (now() < timeout) {
          setTimeout(spin, 100);
        } else {
          console.error("TIMED OUT - waiting for ipython kernel to start");
        }
      };
      setTimeout(spin, 0);
    },
    evaluate: function(code, modelOutput) {
      if (_theCancelFunction) {
        throw "multiple evaluation at the same time is not supported";
      }

      // utils
      var emptyOutputResult = function() {
        modelOutput.result = "";
      };
      var ensureOutputIsHtml = function() {
        if (!modelOutput.result ||
            modelOutput.result.type !== "BeakerDisplay" ||
            modelOutput.result.innertype !== "Html") {
          modelOutput.result = {
            type: "BeakerDisplay",
            innertype: "Html",
            object: ""
          };
        }
      }
      var setOutputResult = function(result) {
        ensureOutputIsHtml();
        modelOutput.result.object = result;
      };
      var appendToResult = function(txtToAppend) {
        ensureOutputIsHtml();
        modelOutput.result.object += txtToAppend;
      };

      // begin
      var deferred = bkHelper.newDeferred();
      var self = this;
      var startTime = new Date().getTime();
      var kernel = kernels[self.settings.shellID];
      var progressObj = {
        type: "BeakerDisplay",
        innertype: "Progress",
        object: {
          message: "evaluating ...",
          startTime: startTime
        }
      };
      modelOutput.result = progressObj;
      modelOutput.outputArrived = false;
      _theCancelFunction = function() {
        var kernel = kernels[self.settings.shellID];
        kernel.interrupt();
        deferred.reject("cancelled by user");
        modelOutput.result = "canceling ...";
      };
      var execute_reply = function(msg) {
        var result = _(msg.payload).map(function(payload) {
          return IPython.utils.fixCarriageReturn(IPython.utils.fixConsole(payload.text));
        }).join("");
        if (!_.isEmpty(result)) {
          setOutputResult("
" + result + "
");
        } else if (!modelOutput.outputArrived) {
          emptyOutputResult();
        }
        modelOutput.elapsedTime = now() - startTime;
        deferred.resolve();
        bkHelper.refreshRootScope();
      }
      var output = function output(a0, a1) {
        var type;
        var content;
        if (ipyVersion1) {
          type = a0;
          content = a1;
        } else {
          type = a0.msg_type;
          content = a0.content;
        }
        modelOutput.outputArrived = true;
        if (type === "pyerr") {
          var trace = _.reduce(content.traceback, function(memo, line) {
            return  memo + "
" + IPython.utils.fixCarriageReturn(IPython.utils.fixConsole(line));
          }, content.evalue);
          modelOutput.result = {
            type: "BeakerDisplay",
            innertype: "Error",
            object: (content.ename === "KeyboardInterrupt") ? "Interrupted" : [content.evalue, trace]
          };
        } else if (type === "stream") {
          var json = JSON.stringify({evaluator: "ipython",
                                     type: content.name,
                                     line: content.data});
          $.cometd.publish("/service/outputlog/put", json);
          appendToResult("");
        } else {
          var elem = $(document.createElement("div"));
          var oa = new IPython.OutputArea(elem);
          // twiddle the mime types? XXX
          if (ipyVersion1) {
            oa.append_mime_type(oa.convert_mime_types({}, content.data), elem, true);
          } else {
            oa.append_mime_type(content.data, elem);
          }
          var table = bkHelper.findTable(elem[0]);
          if (table) {
            modelOutput.result = table;
          } else {
            appendToResult(elem.html());
          }
        }
        modelOutput.elapsedTime = now() - startTime;
        deferred.resolve();
        bkHelper.refreshRootScope();
      };
      var callbacks = ipyVersion1 ? {
        execute_reply: execute_reply,
        output: output
      } : {
        shell: {reply: execute_reply},
        iopub: {output: output}
      };
      kernel.execute(code, callbacks, {silent: false});
      deferred.promise.finally(function() {
        console.log("reset cancel function");
        _theCancelFunction = null;
      });
      return deferred.promise;
    },
    autocomplete: function(code, cpos, cb) {
      var kernel = kernels[this.settings.shellID];
      kernel.complete(code, cpos, {'complete_reply': function(reply) {
        cb(reply.matches, reply.matched_text);
      }});
    },
    interrupt: function() {
      this.cancelExecution();
    },
    cancelExecution: function() {
      if (_theCancelFunction) {
        _theCancelFunction();
      }
    },
    spec: {
      interrupt: {type: "action", action: "interrupt", name: "Interrupt"}
    }
  };

  var init = function() {

    var onSuccess = function() {
      /* chrome has a bug where websockets don't support authentication so we
       disable it. http://code.google.com/p/chromium/issues/detail?id=123862
       this is safe because the URL has the kernel ID in it, and that's a 128-bit
       random number, only delivered via the secure channel. */
      var nginxRules =
        (ipyVersion1 ? ("location %(base_url)s/kernels/ {" +
                        "  proxy_pass http://127.0.0.1:%(port)s/kernels;" +
                        "}" +
                        "location ~ %(base_url)s/kernels/[0-9a-f-]+/  {") :
         ("location %(base_url)s/api/kernels/ {" +
          "  proxy_pass http://127.0.0.1:%(port)s/api/kernels;" +
          "}" +
          "location %(base_url)s/api/sessions/ {" +
          "  proxy_pass http://127.0.0.1:%(port)s/api/sessions;" +
          "}" +
          "location ~ %(base_url)s/api/kernels/[0-9a-f-]+/  {")) +
        "  rewrite ^%(base_url)s/(.*)$ /$1 break; " +
        "  proxy_pass http://127.0.0.1:%(port)s; " +
        "  proxy_http_version 1.1; " +
        "  proxy_set_header Upgrade $http_upgrade; " +
        "  proxy_set_header Connection \"upgrade\"; " +
        "  proxy_set_header Origin \"$scheme://$host\"; " +
        "  proxy_set_header Host $host;" +
        "}";
      bkHelper.locatePluginService(PLUGIN_NAME, {
          command: COMMAND,
          nginxRules: nginxRules,
          startedIndicator: "[NotebookApp] The IPython Notebook is running at: http://127.0.0.1:",
          startedIndicatorStream: "stderr"
      }).success(function(ret) {
        serviceBase = ret;
        var IPythonShell = function(settings, cb) {
          var self = this;
          var setShellIdCB = function(shellID) {
            settings.shellID = shellID;

            // XXX these are not used by python, they are leftover from groovy
            if (!settings.imports) {
              settings.imports = "";
            }
            if (!settings.supplementalClassPath) {
              settings.supplementalClassPath = "";
            }
            self.settings = settings;
            if (cb) {
              cb();
            }
          };
          if (!settings.shellID) {
            settings.shellID = "";
          }
          this.newShell(settings.shellID, setShellIdCB);
          this.perform = function(what) {
            var action = this.spec[what].action;
            this[action]();
          };
        };
        IPythonShell.prototype = IPythonProto;
        bkHelper.getLoadingPlugin(url).onReady(IPythonShell);
      }).error(function() {
        console.log("failed to locate plugin service", PLUGIN_NAME, arguments);
      });
    };
    var onFail = function() {
      console.log("failed to load ipython libs");
    };

    bkHelper.httpGet("/beaker/rest/plugin-services/getIPythonVersion")
      .success(function(result) {
        var backendVersion = result;
        if (backendVersion[0] == "1") {
          ipyVersion1 = true;
        }
        console.log("Using ipython 1.x compatibility mode: " + ipyVersion1);
        if (ipyVersion1) {
          bkHelper.loadList(["./plugins/eval/ipythonPlugins/vendor/ipython/namespace.js",
                             "./plugins/eval/ipythonPlugins/vendor/ipython/utils.js",
                             "./plugins/eval/ipythonPlugins/vendor/ipython/kernel.js",
                             "./plugins/eval/ipythonPlugins/vendor/ipython/outputarea.js"
                            ], onSuccess, onFail);
        } else {
          bkHelper.loadList(["./plugins/eval/ipythonPlugins/vendor/ipython2/namespace.js",
                             "./plugins/eval/ipythonPlugins/vendor/ipython2/utils.js",
                             "./plugins/eval/ipythonPlugins/vendor/ipython2/kernel.js",
                             "./plugins/eval/ipythonPlugins/vendor/ipython2/session.js",
                             "./plugins/eval/ipythonPlugins/vendor/ipython2/comm.js",
                             "./plugins/eval/ipythonPlugins/vendor/ipython2/outputarea.js"
                            ], onSuccess, onFail);
        }
      });
  };
  init();
})();
<commit_msg>fix Issue #150, ipython2 help<commit_after>/*
 *  Copyright 2014 TWO SIGMA INVESTMENTS, LLC
 *
 *  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.
 */
/**
 * IPython eval plugin
 * For creating and config evaluators that uses a IPython kernel for evaluating python code
 * and updating code cell outputs.
 */
(function() {
  'use strict';
  var url = "./plugins/eval/ipythonPlugins/ipython/ipython.js";
  var PLUGIN_NAME = "IPython";
  var COMMAND = "ipythonPlugins/ipython/ipythonPlugin";
  var kernels = {};
  var _theCancelFunction = null;
  var serviceBase = null;
  var ipyVersion1 = false;
  var now = function() {
    return new Date().getTime();
  };
  var IPythonProto = {
    pluginName: PLUGIN_NAME,
    cmMode: "python",
    background: "#EAEAFF",
    newShell: function(shellID, cb) {

      var kernel = null;
      var self = this;

      // check in kernel table if shellID exists, then do nothing or still callback?
      if (kernels[shellID]) {
        return;
      }

      if (_.isEmpty(shellID)) {
        shellID = IPython.utils.uuid();
      }

      if (ipyVersion1) {
        self.kernel = new IPython.Kernel(serviceBase + "/kernels/");
        kernels[shellID] = self.kernel;
        self.kernel.start("kernel." + bkHelper.getSessionID() + "." + shellID);
      } else {
        // Required by ipython backend, but not used.
        var model = {
          notebook : {
            name : "fakename" + shellID,
            path : "/some/path" + shellID
          }
        };
        var ajaxsettings = {
          processData : false,
          cache : false,
          type : "POST",
          data: JSON.stringify(model),
          dataType : "json",
          success : function (data, status, xhr) {
            self.kernel = new IPython.Kernel(serviceBase + "/api/kernels");
            kernels[shellID] = self.kernel;
            // the data.id is the session id but it is not used yet
            self.kernel._kernel_started({id: data.kernel.id});
          }
        };
        var url = IPython.utils.url_join_encode(serviceBase, 'api/sessions/');
        $.ajax(url, ajaxsettings);
      }

      // keepalive for the websockets
      var nil = function() {
      };
      window.setInterval(function() {
        // XXX this is wrong (ipy1 layout) maybe it doesn't matter??
        var ignore = {
          execute_reply: nil,
          output: nil,
          clear_output: nil,
          set_next_input: nil
        };
        self.kernel.execute("", ignore, {silent: false});
      }, 30 * 1000);

      // cb cannot be called synchronously, see evaluatorManager.js, new Shell
      // Also, do not cb until making sure kernel is running.
      var timeout = now() + 10 * 1000; // time out 10 sec
      var spin = function() {
        if (self.kernel !== undefined && self.kernel.running) {
          cb(shellID);
        } else if (now() < timeout) {
          setTimeout(spin, 100);
        } else {
          console.error("TIMED OUT - waiting for ipython kernel to start");
        }
      };
      setTimeout(spin, 0);
    },
    evaluate: function(code, modelOutput) {
      if (_theCancelFunction) {
        throw "multiple evaluation at the same time is not supported";
      }

      // utils
      var emptyOutputResult = function() {
        modelOutput.result = "";
      };
      var ensureOutputIsHtml = function() {
        if (!modelOutput.result ||
            modelOutput.result.type !== "BeakerDisplay" ||
            modelOutput.result.innertype !== "Html") {
          modelOutput.result = {
            type: "BeakerDisplay",
            innertype: "Html",
            object: ""
          };
        }
      }
      var setOutputResult = function(result) {
        ensureOutputIsHtml();
        modelOutput.result.object = result;
      };
      var appendToResult = function(txtToAppend) {
        ensureOutputIsHtml();
        modelOutput.result.object += txtToAppend;
      };

      // begin
      var deferred = bkHelper.newDeferred();
      var self = this;
      var startTime = new Date().getTime();
      var kernel = kernels[self.settings.shellID];
      var progressObj = {
        type: "BeakerDisplay",
        innertype: "Progress",
        object: {
          message: "evaluating ...",
          startTime: startTime
        }
      };
      modelOutput.result = progressObj;
      modelOutput.outputArrived = false;
      _theCancelFunction = function() {
        var kernel = kernels[self.settings.shellID];
        kernel.interrupt();
        deferred.reject("cancelled by user");
        modelOutput.result = "canceling ...";
      };
      var execute_reply = function(msg) {
        if (!ipyVersion1) {
          msg = msg.content;
        }
        var result = _(msg.payload).map(function(payload) {
          return IPython.utils.fixCarriageReturn(IPython.utils.fixConsole(payload.text));
        }).join("");
        if (!_.isEmpty(result)) {
          setOutputResult("
" + result + "
");
        } else if (!modelOutput.outputArrived) {
          emptyOutputResult();
        }
        modelOutput.elapsedTime = now() - startTime;
        deferred.resolve();
        bkHelper.refreshRootScope();
      }
      var output = function output(a0, a1) {
        var type;
        var content;
        if (ipyVersion1) {
          type = a0;
          content = a1;
        } else {
          type = a0.msg_type;
          content = a0.content;
        }
        modelOutput.outputArrived = true;
        if (type === "pyerr") {
          var trace = _.reduce(content.traceback, function(memo, line) {
            return  memo + "
" + IPython.utils.fixCarriageReturn(IPython.utils.fixConsole(line));
          }, content.evalue);
          modelOutput.result = {
            type: "BeakerDisplay",
            innertype: "Error",
            object: (content.ename === "KeyboardInterrupt") ? "Interrupted" : [content.evalue, trace]
          };
        } else if (type === "stream") {
          var json = JSON.stringify({evaluator: "ipython",
                                     type: content.name,
                                     line: content.data});
          $.cometd.publish("/service/outputlog/put", json);
          appendToResult("");
        } else {
          var elem = $(document.createElement("div"));
          var oa = new IPython.OutputArea(elem);
          // twiddle the mime types? XXX
          if (ipyVersion1) {
            oa.append_mime_type(oa.convert_mime_types({}, content.data), elem, true);
          } else {
            oa.append_mime_type(content.data, elem);
          }
          var table = bkHelper.findTable(elem[0]);
          if (table) {
            modelOutput.result = table;
          } else {
            appendToResult(elem.html());
          }
        }
        modelOutput.elapsedTime = now() - startTime;
        deferred.resolve();
        bkHelper.refreshRootScope();
      };
      var callbacks = ipyVersion1 ? {
        execute_reply: execute_reply,
        output: output
      } : {
        shell: {reply: execute_reply},
        iopub: {output: output}
      };
      kernel.execute(code, callbacks, {silent: false});
      deferred.promise.finally(function() {
        _theCancelFunction = null;
      });
      return deferred.promise;
    },
    autocomplete: function(code, cpos, cb) {
      var kernel = kernels[this.settings.shellID];
      kernel.complete(code, cpos, {'complete_reply': function(reply) {
        cb(reply.matches, reply.matched_text);
      }});
    },
    interrupt: function() {
      this.cancelExecution();
    },
    cancelExecution: function() {
      if (_theCancelFunction) {
        _theCancelFunction();
      }
    },
    spec: {
      interrupt: {type: "action", action: "interrupt", name: "Interrupt"}
    }
  };

  var init = function() {

    var onSuccess = function() {
      /* chrome has a bug where websockets don't support authentication so we
       disable it. http://code.google.com/p/chromium/issues/detail?id=123862
       this is safe because the URL has the kernel ID in it, and that's a 128-bit
       random number, only delivered via the secure channel. */
      var nginxRules =
        (ipyVersion1 ? ("location %(base_url)s/kernels/ {" +
                        "  proxy_pass http://127.0.0.1:%(port)s/kernels;" +
                        "}" +
                        "location ~ %(base_url)s/kernels/[0-9a-f-]+/  {") :
         ("location %(base_url)s/api/kernels/ {" +
          "  proxy_pass http://127.0.0.1:%(port)s/api/kernels;" +
          "}" +
          "location %(base_url)s/api/sessions/ {" +
          "  proxy_pass http://127.0.0.1:%(port)s/api/sessions;" +
          "}" +
          "location ~ %(base_url)s/api/kernels/[0-9a-f-]+/  {")) +
        "  rewrite ^%(base_url)s/(.*)$ /$1 break; " +
        "  proxy_pass http://127.0.0.1:%(port)s; " +
        "  proxy_http_version 1.1; " +
        "  proxy_set_header Upgrade $http_upgrade; " +
        "  proxy_set_header Connection \"upgrade\"; " +
        "  proxy_set_header Origin \"$scheme://$host\"; " +
        "  proxy_set_header Host $host;" +
        "}";
      bkHelper.locatePluginService(PLUGIN_NAME, {
          command: COMMAND,
          nginxRules: nginxRules,
          startedIndicator: "[NotebookApp] The IPython Notebook is running at: http://127.0.0.1:",
          startedIndicatorStream: "stderr"
      }).success(function(ret) {
        serviceBase = ret;
        var IPythonShell = function(settings, cb) {
          var self = this;
          var setShellIdCB = function(shellID) {
            settings.shellID = shellID;

            // XXX these are not used by python, they are leftover from groovy
            if (!settings.imports) {
              settings.imports = "";
            }
            if (!settings.supplementalClassPath) {
              settings.supplementalClassPath = "";
            }
            self.settings = settings;
            if (cb) {
              cb();
            }
          };
          if (!settings.shellID) {
            settings.shellID = "";
          }
          this.newShell(settings.shellID, setShellIdCB);
          this.perform = function(what) {
            var action = this.spec[what].action;
            this[action]();
          };
        };
        IPythonShell.prototype = IPythonProto;
        bkHelper.getLoadingPlugin(url).onReady(IPythonShell);
      }).error(function() {
        console.log("failed to locate plugin service", PLUGIN_NAME, arguments);
      });
    };
    var onFail = function() {
      console.log("failed to load ipython libs");
    };

    bkHelper.httpGet("/beaker/rest/plugin-services/getIPythonVersion")
      .success(function(result) {
        var backendVersion = result;
        if (backendVersion[0] == "1") {
          ipyVersion1 = true;
        }
        console.log("Using ipython 1.x compatibility mode: " + ipyVersion1);
        if (ipyVersion1) {
          bkHelper.loadList(["./plugins/eval/ipythonPlugins/vendor/ipython/namespace.js",
                             "./plugins/eval/ipythonPlugins/vendor/ipython/utils.js",
                             "./plugins/eval/ipythonPlugins/vendor/ipython/kernel.js",
                             "./plugins/eval/ipythonPlugins/vendor/ipython/outputarea.js"
                            ], onSuccess, onFail);
        } else {
          bkHelper.loadList(["./plugins/eval/ipythonPlugins/vendor/ipython2/namespace.js",
                             "./plugins/eval/ipythonPlugins/vendor/ipython2/utils.js",
                             "./plugins/eval/ipythonPlugins/vendor/ipython2/kernel.js",
                             "./plugins/eval/ipythonPlugins/vendor/ipython2/session.js",
                             "./plugins/eval/ipythonPlugins/vendor/ipython2/comm.js",
                             "./plugins/eval/ipythonPlugins/vendor/ipython2/outputarea.js"
                            ], onSuccess, onFail);
        }
      });
  };
  init();
})();
<|endoftext|>


<commit_before>var five = require("johnny-five"),
    board = new five.Board();
var program = require('commander');
var keypress = require('keypress');

program
  .version('1.0.0')

board.on("ready", function() {
  console.log("board ready. left right arrow keys, 'q' to quit.");
  var servo = new five.Servo({
    "pin": 9,
    "startAt":program.startAt,
    "type":"continuous"
    });
  process.stdin.on('keypress', function (ch, key) {
    // console.log('got "keypress"', key);
    if (key && key.name == 'right') {
      servo.cw(1);
    }
    if (key && key.name == 'left') {
      servo.ccw(1);
    }
    if(key && key.name == 'q') {
      process.exit(0);
    }
  });

  process.stdin.setRawMode(true);
  process.stdin.resume();
});<commit_msg>don't use continuous API<commit_after>var five = require("johnny-five"),
    board = new five.Board();
var program = require('commander');
var keypress = require('keypress');

program
  .version('1.0.0')

board.on("ready", function() {
  console.log("board ready. left right arrow keys, 'q' to quit.");
  var servo = new five.Servo({
    "pin": 9,
    "startAt":program.startAt
    });
  process.stdin.on('keypress', function (ch, key) {
    // console.log('got "keypress"', key);
    if (key && key.name == 'right') {
      servo.to(0);
    }
    if (key && key.name == 'left') {
      servo.to(180);
    }
    if(key && key.name == 'q') {
      process.exit(0);
    }
  });

  process.stdin.setRawMode(true);
  process.stdin.resume();
});<|endoftext|>


<commit_before>/**
 * Collection of various utility functions.
 *
 *
 * Copyright (c) 2014 ITSA - https://github.com/itsa
 * New BSD License - http://choosealicense.com/licenses/bsd-3-clause/
 *
 * @module utils
 * @class Utils
 * @static
*/

"use strict";

require('polyfill/polyfill-base.js');

var NAME = '[utils-timers]: ',
    _asynchronizer, _async;

/**
 * Forces a function to be run asynchronously, but as fast as possible. In Node.js
 * this is achieved using `setImmediate` or `process.nextTick`.
 *
 * @method _asynchronizer
 * @param callbackFn {Function} The function to call asynchronously
 * @static
 * @private
**/
_asynchronizer = (typeof setImmediate !== 'undefined') ? function (fn) {setImmediate(fn);} :
                    ((typeof process !== 'undefined') && process.nextTick) ? process.nextTick : function (fn) {setTimeout(fn, 0);};

/**
 * Invokes the callbackFn once in the next turn of the JavaScript event loop. If the function
 * requires a specific execution context or arguments, wrap it with Function.bind.
 *
 * I.async returns an object with a cancel method.  If the cancel method is
 * called before the callback function, the callback function won't be called.
 *
 * @method async
 * @param {Function} callbackFn
 * @param [invokeAfterFn=true] {boolean} set to false to prevent the _afterSyncFn to be invoked
 * @return {Object} An object with a cancel method.  If the cancel method is
 * called before the callback function, the callback function won't be called.
**/
_async = function (callbackFn, invokeAfterFn) {
	console.log(NAME, 'async');
	var canceled;

	invokeAfterFn = (typeof invokeAfterFn === 'boolean') ? invokeAfterFn : true;
	(typeof callbackFn==='function') && _asynchronizer(function () {
		if (!canceled) {
			callbackFn();
		}
	});

	return {
		cancel: function () {
			canceled = true;
		}
	};
};

/**
 * Invokes the callbackFn once in the next turn of the JavaScript event loop. If the function
 * requires a specific execution context or arguments, wrap it with Function.bind.
 *
 * I.async returns an object with a cancel method.  If the cancel method is
 * called before the callback function, the callback function won't be called.
 *
 * @method async
 * @param {Function} callbackFn
 * @param [invokeAfterFn=true] {boolean} set to false to prevent the _afterSyncFn to be invoked
 * @return {Object} An object with a cancel method.  If the cancel method is
 * called before the callback function, the callback function won't be called.
**/
module.exports.async = _async;

/**
 * Invokes the callbackFn after a timeout (asynchronous). If the function
 * requires a specific execution context or arguments, wrap it with Function.bind.
 *
 * To invoke the callback function periodic, set 'periodic' either 'true', or specify a second timeout.
 * If number, then periodic is considered 'true' but with a perdiod defined by 'periodic',
 * which means: the first timer executes after 'timeout' and next timers after 'period'.
 *
 * I.later returns an object with a cancel method.  If the cancel() method is
 * called before the callback function, the callback function won't be called.
 *
 * @method later
 * @param callbackFn {Function} the function to execute.
 * @param [timeout] {Number} the number of milliseconds to wait until the callbackFn is executed.
 * when not set, the callback function is invoked once in the next turn of the JavaScript event loop.
 * @param [periodic] {boolean|Number} if true, executes continuously at supplied, if number, then periodic is considered 'true' but with a perdiod
 * defined by 'periodic', which means: the first timer executes after 'timeout' and next timers after 'period'.
 * The interval executes until canceled.
 * @return {object} a timer object. Call the cancel() method on this object to stop the timer.
*/
module.exports.later = function (callbackFn, timeout, periodic) {
	console.log(NAME, 'later --> timeout: '+timeout+'ms | periodic: '+periodic);
	var canceled = false;
	if (!timeout) {
		return _async(callbackFn);
	}
	var wrapper = function() {
			// nodejs may execute a callback, so in order to preserve
			// the cancel() === no more runny-run, we have to build in an extra conditional
			if (!canceled) {
				callbackFn();
				// we are NOT using setInterval, because that leads to problems when the callback
				// lasts longer than the interval. Instead, we use the interval as inbetween-phase
				// between the separate callbacks.
				id = periodic ? setTimeout(wrapper, (typeof periodic==='number') ? periodic : timeout) : null;
			}
		},
		id;
	(typeof callbackFn==='function') && (id=setTimeout(wrapper, timeout));

	return {
		cancel: function() {
			canceled = true;
			id && clearTimeout(id);
			// break closure:
			id = null;
		}
	};
};<commit_msg>bugfix later work with zero seconds and repeat<commit_after>/**
 * Collection of various utility functions.
 *
 *
 * Copyright (c) 2014 ITSA - https://github.com/itsa
 * New BSD License - http://choosealicense.com/licenses/bsd-3-clause/
 *
 * @module utils
 * @class Utils
 * @static
*/

"use strict";

require('polyfill/polyfill-base.js');

var NAME = '[utils-timers]: ',
    _asynchronizer, _async;

/**
 * Forces a function to be run asynchronously, but as fast as possible. In Node.js
 * this is achieved using `setImmediate` or `process.nextTick`.
 *
 * @method _asynchronizer
 * @param callbackFn {Function} The function to call asynchronously
 * @static
 * @private
**/
_asynchronizer = (typeof setImmediate !== 'undefined') ? function (fn) {setImmediate(fn);} :
                    ((typeof process !== 'undefined') && process.nextTick) ? process.nextTick : function (fn) {setTimeout(fn, 0);};

/**
 * Invokes the callbackFn once in the next turn of the JavaScript event loop. If the function
 * requires a specific execution context or arguments, wrap it with Function.bind.
 *
 * I.async returns an object with a cancel method.  If the cancel method is
 * called before the callback function, the callback function won't be called.
 *
 * @method async
 * @param {Function} callbackFn
 * @param [invokeAfterFn=true] {boolean} set to false to prevent the _afterSyncFn to be invoked
 * @return {Object} An object with a cancel method.  If the cancel method is
 * called before the callback function, the callback function won't be called.
**/
_async = function (callbackFn, invokeAfterFn) {
	console.log(NAME, 'async');
	var canceled;

	invokeAfterFn = (typeof invokeAfterFn === 'boolean') ? invokeAfterFn : true;
	(typeof callbackFn==='function') && _asynchronizer(function () {
		if (!canceled) {
			callbackFn();
		}
	});

	return {
		cancel: function () {
			canceled = true;
		}
	};
};

/**
 * Invokes the callbackFn once in the next turn of the JavaScript event loop. If the function
 * requires a specific execution context or arguments, wrap it with Function.bind.
 *
 * I.async returns an object with a cancel method.  If the cancel method is
 * called before the callback function, the callback function won't be called.
 *
 * @method async
 * @param {Function} callbackFn
 * @param [invokeAfterFn=true] {boolean} set to false to prevent the _afterSyncFn to be invoked
 * @return {Object} An object with a cancel method.  If the cancel method is
 * called before the callback function, the callback function won't be called.
**/
module.exports.async = _async;

/**
 * Invokes the callbackFn after a timeout (asynchronous). If the function
 * requires a specific execution context or arguments, wrap it with Function.bind.
 *
 * To invoke the callback function periodic, set 'periodic' either 'true', or specify a second timeout.
 * If number, then periodic is considered 'true' but with a perdiod defined by 'periodic',
 * which means: the first timer executes after 'timeout' and next timers after 'period'.
 *
 * I.later returns an object with a cancel method.  If the cancel() method is
 * called before the callback function, the callback function won't be called.
 *
 * @method later
 * @param callbackFn {Function} the function to execute.
 * @param [timeout] {Number} the number of milliseconds to wait until the callbackFn is executed.
 * when not set, the callback function is invoked once in the next turn of the JavaScript event loop.
 * @param [periodic] {boolean|Number} if true, executes continuously at supplied, if number, then periodic is considered 'true' but with a perdiod
 * defined by 'periodic', which means: the first timer executes after 'timeout' and next timers after 'period'.
 * The interval executes until canceled.
 * @return {object} a timer object. Call the cancel() method on this object to stop the timer.
*/
module.exports.later = function (callbackFn, timeout, periodic) {
	console.log(NAME, 'later --> timeout: '+timeout+'ms | periodic: '+periodic);
	var canceled = false;
	if (typeof timeout!=='number') {
		return _async(callbackFn);
	}
	var wrapper = function() {
			// nodejs may execute a callback, so in order to preserve
			// the cancel() === no more runny-run, we have to build in an extra conditional
			if (!canceled) {
				callbackFn();
				// we are NOT using setInterval, because that leads to problems when the callback
				// lasts longer than the interval. Instead, we use the interval as inbetween-phase
				// between the separate callbacks.
				id = periodic ? setTimeout(wrapper, (typeof periodic==='number') ? periodic : timeout) : null;
			}
		},
		id;
	(typeof callbackFn==='function') && (id=setTimeout(wrapper, timeout));

	return {
		cancel: function() {
			canceled = true;
			id && clearTimeout(id);
			// break closure:
			id = null;
		}
	};
};<|endoftext|>