<commit_before>
/*
 *
 * poloniex-unofficial
 *
 * Yet another unofficial wrapper for the Poloniex cryptocurrency exchange APIs
 * on Node.js
 *
 */

// Import modules
var autobahn = require("autobahn");

// Autobahn|JS connection object for push API (utilizes the WAMP protocol)
var connection = new autobahn.Connection({
    "url": "wss://api.poloniex.com",
    "realm": "realm1"
});

// Current status of API connection
var connected = false;

// Handler for connection open event
connection.onopen = (session) => {
    // Set connected flag
    connected = true;
};

// Handler for connection close event
connection.onclose = (reason, details) => {
    // Clear connected flag
    connected = false;

};

// Connects to the push API
function connect() {
    // Don't try to connect if already so
    if (connected) {
        return;
    }

    // Open connection to push API
    connection.open();
}

// Disconnects from the push API
function disconnect() {
    // Don't try to disconnect if already so
    if (!connected) {
        return;
    }

    // Close connection to push API
    connection.close();
}

// Representation of the Poloniex push API
var apiPush = {};

// Ticker subscription function
apiPush.ticker = (callback) => {
    // TODO: Stuff goes here
};

// Order book subscription function
apiPush.orderBook = (currencyPair, callback) => {
    // TODO: Stuff goes here
};

// Trollbox subscription function
apiPush.trollbox = (callback) => {
    // TODO: Stuff goes here
};

// Export a function which returns apiPush
module.exports = () => apiPush;

<commit_msg>Yay, something works!<commit_after>
/*
 *
 * poloniex-unofficial
 *
 * Yet another unofficial wrapper for the Poloniex cryptocurrency exchange APIs
 * on Node.js
 *
 */

// Import modules
var autobahn = require("autobahn");

// Autobahn|JS connection object for push API (utilizes the WAMP protocol)
var connection = new autobahn.Connection({
    "url": "wss://api.poloniex.com",
    "realm": "realm1"
});

// Helper function to open connection and retry a function with a callback
function connectAndRetry(retry, callback) {
    // Check if connection is not yet open
    if (!connection.isOpen) {
        // Register a callback to retry this function
        connection.onopen = (session) => {
            // Retry on successful connection
            retry(callback);
        }

        // Attempt to open the connection
        connection.open();
    }
}

// Representation of the Poloniex push API
var apiPush = {};

// Ticker subscription function
apiPush.ticker = (callback) => {
    // Try to connect to push API
    connectAndRetry(apiPush.ticker, callback);

    // Continue if connection is open
    if (connection.isOpen) {
        // Subscribe to the ticker
        connection.session.subscribe("ticker", (args) => {
            // FIXME: Parse the JSON input
            callback(null, args);
        });
    }
};

// Order book subscription function
apiPush.orderBook = (currencyPair, callback) => {
    // Try to connect to push API
    connectAndRetry(apiPush.orderBook, callback);

    // Continue if connection is open
    if (connection.isOpen) {
        // TODO: Stuff goes here
    }
};

// Trollbox subscription function
apiPush.trollbox = (callback) => {
    // Try to connect to push API
    connectAndRetry(apiPush.trollbox, callback);

    // Continue if connection is open
    if (connection.isOpen) {
        // TODO: Stuff goes here
    }
};

// Export a function which returns apiPush
module.exports = () => apiPush;

<|endoftext|>


<commit_before>// ==UserScript==
// @name         Putlocker Navigation Buttons
// @namespace    http://rotar.tk/
// @version      0.1.1
// @description  Add navigation buttons (previous,next) under putlocker tvshow videos.
// @author       Rotar
// @match        http://putlocker.is/watch*
// @grant        none
// @downloadURL  https://github.com/kaneorotar/putlocker-userscript/raw/master/putlocker-navi.user.js
// ==/UserScript==

(function() {
	'use strict';
	var curl = window.location.href;
	var vals = /watch-([a-z0-9\-]*)-tvshow(-season-([0-9]{1,2})-episode-([0-9]{1,2}))?-online/.exec(curl);
	var se = 0, ep = 0;
	var iurl = curl.replace(/-season-([0-9]{1,2})-episode-([0-9]{1,2})/,"");
	var retries = 3;

	var list = {
		seasons: [],
		season: function(){
			return this.seasons.length-1;
		},
		episode: function(season){
			return this.seasons[season];
		},
		next: function(season,episode){
			if((episode+1)>this.episode(season)){
				if((season+1)>this.season()){
					return null;
				}else{
					return [season+1,1];
				}
			}else{
				return [season,episode+1];
			}
		},
		previous: function(season,episode){
			if((episode-1)<1){
				if((season-1)<1){
					return null;
				}else{
					return [season-1,this.episode(season-1)];
				}
			}else{
				return [season,episode-1];
			}
		}
	};

	if(typeof(vals[2])!="undefined"){//on an episode page
		se = parseInt(vals[3]);
		ep = parseInt(vals[4]);

		var contentbox = document.getElementsByClassName("content-box")[0];
		var msgdiv = document.getElementsByClassName("message")[0];

		var navi = document.createElement("div");
		navi.id = "navi_box";
		navi.style.height = "40px";
		navi.style.position = "relative";
		navi.style.textAlign = "center";
		navi.style.fontFamily = "Arial";
		navi.style.fontSize = "22px";
		navi.style.marginTop = "-5px";
		navi.style.display = "None";

		var prev = document.createElement("a");
		prev.id = "prev_btn";
		prev.style.borderRadius = "4px";
		prev.style.position = "absolute";
		prev.style.left = "5px";
		prev.style.padding = "5px";
		prev.style.fontWeight = "bold";
		prev.style.backgroundImage = "-webkit-linear-gradient(top,#18db03 0%,#2a7a54 100%)";
		prev.style.color = "#EEEEEE";
		prev.style.cursor = "pointer";
		prev.innerHTML = "PREVIOUS";
		prev.style.display = "None";
		navi.appendChild(prev);

		var next = document.createElement("a");
		next.id = "next_btn";
		next.style.borderRadius = "4px";
		next.style.position = "absolute";
		next.style.right = "5px";
		next.style.padding = "5px";
		next.style.fontWeight = "bold";
		next.style.backgroundImage = "-webkit-linear-gradient(top,#18db03 0%,#2a7a54 100%)";
		next.style.color = "#EEEEEE";
		next.style.cursor = "pointer";
		next.innerHTML = "NEXT";
		next.style.display = "None";
		navi.appendChild(next);

		contentbox.insertBefore(navi,msgdiv);
		getIndex(iurl);
	}

	function validate(elem){
		var result;
		if(elem.innerHTML.toLowerCase().substr(0,4)=="prev"){
			result = list.previous(se,ep);
		}else{
			result = list.next(se,ep);
		}
		if(result){
			var nurl = window.location.href.replace("-season-"+se+"-episode-"+ep,"-season-"+result[0]+"-episode-"+result[1]);
			elem.href = nurl;
			if(result[0]<se){
				elem.innerHTML = "PREVIOUS SEASON";
			}else if(result[0]>se){
				elem.innerHTML = "NEXT SEASON";
			}
			elem.style.display = "block";
			navi.style.display = "block";
		}
	}

	function getIndex(lurl){
		var responseb;
		var xhr = new XMLHttpRequest();
		xhr.onloadend = function() {
			if (xhr.status == 200 || xhr.status == 304) {
				responseb = xhr.responseText;
				var dp = new DOMParser();
				var rdom = dp.parseFromString(responseb,'text/html');
				console.log("Index Successfully Fetched");

				var icontentbox = rdom.getElementsByClassName("content-box")[0];
				var tbs = icontentbox.getElementsByTagName("table");
				for(var i=0; i<(tbs.length-5); i++){//put number of episodes for each season into list.seasons
					list.seasons[i+1]=tbs[2+i].childNodes[0].childNodes.length;
				}
				validate(prev);
				validate(next);
			}else{
				console.log("[Request Error] Index fetching failed.");
				retries--;
				if(retries>=0){
					console.log("[Request Error] Retrying in 3 seconds");
					setTimeOut(function(){
						console.log("Fetching Index...");
						getIndex(lurl);
					},3000);
				}
			}
		};

		xhr.open('GET', lurl, true);
		xhr.send(null);
	}
})();<commit_msg>Added Chinese @name and @description metadata<commit_after>// ==UserScript==
// @name         Putlocker Navigation Buttons
// @name:zh-CN   Putlocker电视剧上/下集按钮
// @namespace    http://rotar.tk/
// @version      0.1.1
// @description  Add navigation buttons (previous,next) under putlocker tvshow videos.
// @description:zh-CN  在Putlocker电视剧播放页面添加上/下集按钮。
// @author       Rotar
// @match        http://putlocker.is/watch*
// @grant        none
// @downloadURL  https://github.com/kaneorotar/putlocker-userscript/raw/master/putlocker-navi.user.js
// ==/UserScript==

(function() {
	'use strict';
	var curl = window.location.href;
	var vals = /watch-([a-z0-9\-]*)-tvshow(-season-([0-9]{1,2})-episode-([0-9]{1,2}))?-online/.exec(curl);
	var se = 0, ep = 0;
	var iurl = curl.replace(/-season-([0-9]{1,2})-episode-([0-9]{1,2})/,"");
	var retries = 3;

	var list = {
		seasons: [],
		season: function(){
			return this.seasons.length-1;
		},
		episode: function(season){
			return this.seasons[season];
		},
		next: function(season,episode){
			if((episode+1)>this.episode(season)){
				if((season+1)>this.season()){
					return null;
				}else{
					return [season+1,1];
				}
			}else{
				return [season,episode+1];
			}
		},
		previous: function(season,episode){
			if((episode-1)<1){
				if((season-1)<1){
					return null;
				}else{
					return [season-1,this.episode(season-1)];
				}
			}else{
				return [season,episode-1];
			}
		}
	};

	if(typeof(vals[2])!="undefined"){//on an episode page
		se = parseInt(vals[3]);
		ep = parseInt(vals[4]);

		var contentbox = document.getElementsByClassName("content-box")[0];
		var msgdiv = document.getElementsByClassName("message")[0];

		var navi = document.createElement("div");
		navi.id = "navi_box";
		navi.style.height = "40px";
		navi.style.position = "relative";
		navi.style.textAlign = "center";
		navi.style.fontFamily = "Arial";
		navi.style.fontSize = "22px";
		navi.style.marginTop = "-5px";
		navi.style.display = "None";

		var prev = document.createElement("a");
		prev.id = "prev_btn";
		prev.style.borderRadius = "4px";
		prev.style.position = "absolute";
		prev.style.left = "5px";
		prev.style.padding = "5px";
		prev.style.fontWeight = "bold";
		prev.style.backgroundImage = "-webkit-linear-gradient(top,#18db03 0%,#2a7a54 100%)";
		prev.style.color = "#EEEEEE";
		prev.style.cursor = "pointer";
		prev.innerHTML = "PREVIOUS";
		prev.style.display = "None";
		navi.appendChild(prev);

		var next = document.createElement("a");
		next.id = "next_btn";
		next.style.borderRadius = "4px";
		next.style.position = "absolute";
		next.style.right = "5px";
		next.style.padding = "5px";
		next.style.fontWeight = "bold";
		next.style.backgroundImage = "-webkit-linear-gradient(top,#18db03 0%,#2a7a54 100%)";
		next.style.color = "#EEEEEE";
		next.style.cursor = "pointer";
		next.innerHTML = "NEXT";
		next.style.display = "None";
		navi.appendChild(next);

		contentbox.insertBefore(navi,msgdiv);
		getIndex(iurl);
	}

	function validate(elem){
		var result;
		if(elem.innerHTML.toLowerCase().substr(0,4)=="prev"){
			result = list.previous(se,ep);
		}else{
			result = list.next(se,ep);
		}
		if(result){
			var nurl = window.location.href.replace("-season-"+se+"-episode-"+ep,"-season-"+result[0]+"-episode-"+result[1]);
			elem.href = nurl;
			if(result[0]<se){
				elem.innerHTML = "PREVIOUS SEASON";
			}else if(result[0]>se){
				elem.innerHTML = "NEXT SEASON";
			}
			elem.style.display = "block";
			navi.style.display = "block";
		}
	}

	function getIndex(lurl){
		var responseb;
		var xhr = new XMLHttpRequest();
		xhr.onloadend = function() {
			if (xhr.status == 200 || xhr.status == 304) {
				responseb = xhr.responseText;
				var dp = new DOMParser();
				var rdom = dp.parseFromString(responseb,'text/html');
				console.log("Index Successfully Fetched");

				var icontentbox = rdom.getElementsByClassName("content-box")[0];
				var tbs = icontentbox.getElementsByTagName("table");
				for(var i=0; i<(tbs.length-5); i++){//put number of episodes for each season into list.seasons
					list.seasons[i+1]=tbs[2+i].childNodes[0].childNodes.length;
				}
				validate(prev);
				validate(next);
			}else{
				console.log("[Request Error] Index fetching failed.");
				retries--;
				if(retries>=0){
					console.log("[Request Error] Retrying in 3 seconds");
					setTimeOut(function(){
						console.log("Fetching Index...");
						getIndex(lurl);
					},3000);
				}
			}
		};

		xhr.open('GET', lurl, true);
		xhr.send(null);
	}
})();<|endoftext|>


<commit_before>import { configure, addDecorator } from '@storybook/react';
import { withInfo } from '@storybook/addon-info';
import { withOptions } from '@storybook/addon-options';

import './overrides.css';

global.$ = require('jquery');
global.M = require('materialize-css');

// https://www.npmjs.com/package/@storybook/addon-info
addDecorator(withInfo({
  inline: false,
  header: false,
  source: true
}));

// https://www.npmjs.com/package/@storybook/addon-options
addDecorator(
  withOptions({
    name: 'react-materialize',
    url: 'http://react-materialize.github.io',
    sortStoriesByKind: true,
    showAddonPanel: true
  })
);

function loadStories() {
  const req = require.context('../stories', true, /.js$/);
  req.keys().forEach((filename) => req(filename));
}

configure(loadStories, module);
<commit_msg>Remove jQuery from storybook config<commit_after>import { configure, addDecorator } from '@storybook/react';
import { withInfo } from '@storybook/addon-info';
import { withOptions } from '@storybook/addon-options';

import './overrides.css';

global.M = require('materialize-css');

// https://www.npmjs.com/package/@storybook/addon-info
addDecorator(withInfo({
  inline: false,
  header: false,
  source: true
}));

// https://www.npmjs.com/package/@storybook/addon-options
addDecorator(
  withOptions({
    name: 'react-materialize',
    url: 'http://react-materialize.github.io',
    sortStoriesByKind: true,
    showAddonPanel: true
  })
);

function loadStories() {
  const req = require.context('../stories', true, /.js$/);
  req.keys().forEach((filename) => req(filename));
}

configure(loadStories, module);
<|endoftext|>


<commit_before>"use strict";

load('jsecma5.js');
var Narcissus;
load('narcissus/lib/jsdefs.js');
load('narcissus/lib/jslex.js');
load('narcissus/lib/jsparse.js');

var tkn = Narcissus.definitions.tokenIds;

Array.isArray = Array.isArray || function(o) {
    return Object.prototype.toString.call(o) === '[object Array]';
};

function createTraverseData() {
    var o = [];

    o[tkn.FUNCTION] = ["body"];
    o[tkn.IF] = ["condition", "thenPart", "elsePart"];
    o[tkn.SWITCH] = ["discriminant", "cases"];
    o[tkn.CASE] = ["caseLabel", "statements"];
    o[tkn.DEFAULT] = ["statements"];
    o[tkn.FOR] = ["setup", "condition", "update", "body"];
    o[tkn.WHILE] = ["condition", "body"];
    o[tkn.FOR_IN] = ["varDecl", "iterator", "object", "body"];
    o[tkn.DO] = ["body", "condition"];
    o[tkn.TRY] = ["tryBlock", "catchClauses", "finallyBlock"];
    o[tkn.CATCH] = ["guard", "block"];
    o[tkn.THROW] = ["exception"];
    o[tkn.RETURN] = ["value"];
    o[tkn.YIELD] = ["value"];
    o[tkn.GENERATOR] = ["expression", "tail"];
    o[tkn.WITH] = ["object", "body"];
    o[tkn.SEMICOLON] = ["expression"];
    o[tkn.LABEL] = ["statement"];
    o[tkn.IDENTIFIER] = ["initializer"];
    o[tkn.GETTER] = ["body"];
    o[tkn.SETTER] = ["body"];
    o[tkn.LET_BLOCK] = ["variables", "expression", "block"];
    o[tkn.ARRAY_COMP] = ["expression", "tail"];
    o[tkn.COMP_TAIL] = ["children", "guard"]; // children and custom

    var c = [tkn.SCRIPT,
             tkn.BLOCK, tkn.LET, tkn.VAR, tkn.CONST, tkn.COMMA, tkn.ASSIGN,
             tkn.HOOK, tkn.OR, tkn.AND, tkn.BITWISE_OR, tkn.BITWISE_XOR,
             tkn.BITWISE_AND, tkn.EQ, tkn.NE, tkn.STRICT_EQ, tkn.STRICT_NE,
             tkn.LT, tkn.LE, tkn.GE, tkn.GT, tkn.IN, tkn.INSTANCEOF,
             tkn.LSH, tkn.RSH, tkn.URSH, tkn.PLUS, tkn.MINUS, tkn.MUL,
             tkn.DIV, tkn.MOD, tkn.DELETE, tkn.VOID, tkn.TYPEOF,
             tkn.NOT, tkn.BITWISE_NOT, tkn.UNARY_PLUS, tkn.UNARY_MINUS,
             tkn.INCREMENT, tkn.DECREMENT, tkn.DOT, tkn.INDEX,
             tkn.LIST, tkn.CALL, tkn.NEW, tkn.NEW_WITH_ARGS, tkn.ARRAY_INIT,
             tkn.OBJECT_INIT, tkn.PROPERTY_INIT, tkn.GROUP];

    // add "children" to all tokens enumerated in c
    for (var i = 0; i < c.length; i++) {
        if (o[c[i]]) {
            throw new Error("createTraverseData: don't know ordering so "+
                            "can't add 'children' to existing traverseData");
        }
        o[c[i]] = ["children"];
    }

    return o;
}

var traverseData = createTraverseData();

// visitfns: {pre: function, post: function}
// visit function signature: function(node, level, parent, parentProp)
function traverseAstDFS_dynamic(node, visitfns, level, parent, parentProp) {
    if (!node) {
        return;
    }
    if (node instanceof Narcissus.parser.Node !== true) {
        throw new Error("traverseAstDFS expected Node, got "+ typeof node +
                       ". parentProp: "+ parentProp);
    }

    level = level || 0;
    var n;
    visitfns.pre && (n = visitfns.pre(node, level, parent, parentProp));
    if (n !== undefined) {
        node = n;
    }

    for (var prop in node) {
        if (!node.hasOwnProperty(prop)) {
            continue;
        }
        if (prop === "funDecls" || prop === "params" || prop === "varDecls" ||
            prop === "target") {
            continue;
        }
        if (node[prop] instanceof Narcissus.parser.Node) {
            traverseAstDFS(node[prop], visitfns, level + 1, node, prop);
        }
        else if (Array.isArray(node[prop])) {
            for (var j = 0, k = node[prop].length; j < k; j++) {
                traverseAstDFS(node[prop][j], visitfns, level + 1, node, prop + "[" + String(j) + "]");
            }
        }
    }

    visitfns.post && visitfns.post(node, level, parent, parentProp);
}
function traverseAstDFS(node, visitfns, level, parent, parentProp) {
    if (!node) {
        return node;
    }
    if (node instanceof Narcissus.parser.Node !== true) {
        throw new Error("traverseAstDFS expected Node, got "+ typeof node +
                       ". parentProp: "+ parentProp);
    }

    level = level || 0;
    visitfns.pre && (node = visitfns.pre(node, level, parent, parentProp) || node);

    var subprops = traverseData[node.type] || [];
    for (var i = 0; i < subprops.length; i++) {
        var prop = subprops[i];
        if (Array.isArray(node[prop])) {
            for (var j = 0, k = node[prop].length; j < k; j++) {
                traverseAstDFS(node[prop][j], visitfns, level + 1, node, prop + "[" + String(j) + "]");
            }
        }
        else {
            traverseAstDFS(node[prop], visitfns, level + 1, node, prop);
        }
    }

    visitfns.post && (node = visitfns.post(node, level, parent, parentProp) || node);

    return node;
}

function spaces(n, s) {
    var str = "";
    s = s || " ";
    for (var i = 0; i < n; i++) {
        str += s;
    }
    return str;
}
function tokenString(tt) {
    var defs = Narcissus.definitions;
    var t = defs.tokens[tt];
    return /^\W/.test(t) ? defs.opTypeNames[t] : t.toUpperCase();
}

function abbrev(str, max) {
    max = Math.max(Number(max) || 3, 3);
    if (str.length <= max) {
        return str;
    }
    var l = Math.ceil((max - 3) / 2);
    var r = Math.floor((max - 3) / 2);
    return str.slice(0, l) +"..."+ str.slice(str.length - r, str.length);
}

function nodeString(node) {
    function strPos(pos) {
        return pos === undefined ? "?" : String(pos);
    }
    var src = node.tokenizer.source;
    return tokenString(node.type) +
        ("srcs" in node ? " ["+ String(node.srcs) +"]" :
         "start" in node && "end" in node ?
         " '"+ abbrev(src.slice(node.start, node.end), 30) +"'" :
         (node.value !== undefined ? " ("+ node.value +")" : "")) +
        ("start" in node || "end" in node ?
         " ("+ strPos(node.start) +".."+ strPos(node.end) +")" : "") +
        ("parenthesized" in node ? " parenthesized": "");
}

function printTree(root) {
    traverseAstDFS(root, {pre: function(node, level, parent, parentProp) {
        print(spaces(level * 2) + (parentProp || "root") +": "+
              nodeString(node));
    }});
}

function setParent(parent, parentProp, node) {
    if (parentProp[parentProp.length - 1] === "]") {
        var leftBracket = parentProp.indexOf("[");
        var index = parentProp.slice(leftBracket + 1,
                                     parentProp.length - 1);
        var base = parentProp.slice(0, leftBracket);
        parent[base][index] = node;
    }
    else {
        parent[parentProp] = node;
    }
}

function newNode(type, tokenizer, props) {
    var node = Object.create(Narcissus.parser.Node.prototype);
    node.tokenizer = tokenizer;
    node.type = type;
    node.children = [];

    if (props !== undefined) {
        for (var prop in props) {
            node[prop] = props[prop];
        }
    }
    //value, lineno, start, end
    return node;
}

function alterTree(root) {
    function replace(node, var_args) {
        var placeholders = [];
        //collect all # nodes into placeholders array
        traverseAstDFS(node, {pre: function(node, level, parent, parentProp) {
            if (node.type === tkn.PLACEHOLDER) {
                placeholders.push({node: node, parent: parent, parentProp: parentProp});
            }
        }});
        if (arguments.length - 1 !== placeholders.length) {
            throw new Error("replace: placeholders.length mismatch");
        }

        // replace placeholders with new nodes
        for (var i = 0; i < placeholders.length; i++) {
            var o = placeholders[i];
            setParent(o.parent, o.parentProp, arguments[i + 1]);
        }
    }
    traverseAstDFS(root, {pre: function(node, level, parent, parentProp) {
        if (node.type === tkn.PLUS) {
            var replaceNode = parseExpression("__add(#, #)");
            replace(replaceNode, node.children[0], node.children[1]);
            setParent(parent, parentProp, replaceNode);
        }
    }});
}
function adjustStartEnd(root) {
    return traverseAstDFS(root, {post: function(node, level, parent, parentProp) {
        if (parent) {
            if (parent.start === undefined || parent.end === undefined ||
                node.start === undefined || node.end === undefined) {
                throw new Error("adjustStartEnd: undefined start/end");
            }
            parent.start = Math.min(parent.start, node.start);
            parent.end = Math.max(parent.end, node.end);
        }
    }});
}
function srcsify(root) {
    return traverseAstDFS(root, {
        pre: function(node, level, parent, parentProp) {
            node.pos = node.start;
            node.srcs = [];

            if (parent) {
                var src = parent.tokenizer.source;
                parent.srcs.push(src.slice(parent.pos, node.start));
                parent.pos = node.end;
            }
        },
        post: function(node, level, parent, parentProp) {
            var src = node.tokenizer.source;
            node.srcs.push(src.slice(node.pos, node.end));
            delete node.pos;
            delete node.start;
            delete node.end;
            node.tokenizer = {source: ""};
//            delete node.tokenizer;
        }
    });
}

Narcissus.parser.Node.prototype.getSrc = function() {
    var srcs = [];
    traverseAstDFS(this, {
        pre: function(node, level, parent, parentProp) {
            if (parent) {
                srcs.push(parent.srcs[parent.nPushed++]);
            }
            node.nPushed = 0;
        },
        post: function(node, level, parent, parentProp) {
            srcs.push(node.srcs[node.nPushed++]);
            delete node.nPushed;
        }
    });
    return srcs.join("");
};

function parse(str) {
    return srcsify(adjustStartEnd(Narcissus.parser.parse(str, "test.js", 1)));
}
function parseExpression(expr) {
    // SCRIPT -> [SEMICOLON ->] expr
    var stmnt = parse(expr).children[0];
    return stmnt.type === tkn.SEMICOLON ? stmnt.expression : stmnt;
}

print("checker.js done");
<commit_msg>smarter spaces<commit_after>"use strict";

load('jsecma5.js');
var Narcissus;
load('narcissus/lib/jsdefs.js');
load('narcissus/lib/jslex.js');
load('narcissus/lib/jsparse.js');

var tkn = Narcissus.definitions.tokenIds;

Array.isArray = Array.isArray || function(o) {
    return Object.prototype.toString.call(o) === '[object Array]';
};

function createTraverseData() {
    var o = [];

    o[tkn.FUNCTION] = ["body"];
    o[tkn.IF] = ["condition", "thenPart", "elsePart"];
    o[tkn.SWITCH] = ["discriminant", "cases"];
    o[tkn.CASE] = ["caseLabel", "statements"];
    o[tkn.DEFAULT] = ["statements"];
    o[tkn.FOR] = ["setup", "condition", "update", "body"];
    o[tkn.WHILE] = ["condition", "body"];
    o[tkn.FOR_IN] = ["varDecl", "iterator", "object", "body"];
    o[tkn.DO] = ["body", "condition"];
    o[tkn.TRY] = ["tryBlock", "catchClauses", "finallyBlock"];
    o[tkn.CATCH] = ["guard", "block"];
    o[tkn.THROW] = ["exception"];
    o[tkn.RETURN] = ["value"];
    o[tkn.YIELD] = ["value"];
    o[tkn.GENERATOR] = ["expression", "tail"];
    o[tkn.WITH] = ["object", "body"];
    o[tkn.SEMICOLON] = ["expression"];
    o[tkn.LABEL] = ["statement"];
    o[tkn.IDENTIFIER] = ["initializer"];
    o[tkn.GETTER] = ["body"];
    o[tkn.SETTER] = ["body"];
    o[tkn.LET_BLOCK] = ["variables", "expression", "block"];
    o[tkn.ARRAY_COMP] = ["expression", "tail"];
    o[tkn.COMP_TAIL] = ["children", "guard"]; // children and custom

    var c = [tkn.SCRIPT,
             tkn.BLOCK, tkn.LET, tkn.VAR, tkn.CONST, tkn.COMMA, tkn.ASSIGN,
             tkn.HOOK, tkn.OR, tkn.AND, tkn.BITWISE_OR, tkn.BITWISE_XOR,
             tkn.BITWISE_AND, tkn.EQ, tkn.NE, tkn.STRICT_EQ, tkn.STRICT_NE,
             tkn.LT, tkn.LE, tkn.GE, tkn.GT, tkn.IN, tkn.INSTANCEOF,
             tkn.LSH, tkn.RSH, tkn.URSH, tkn.PLUS, tkn.MINUS, tkn.MUL,
             tkn.DIV, tkn.MOD, tkn.DELETE, tkn.VOID, tkn.TYPEOF,
             tkn.NOT, tkn.BITWISE_NOT, tkn.UNARY_PLUS, tkn.UNARY_MINUS,
             tkn.INCREMENT, tkn.DECREMENT, tkn.DOT, tkn.INDEX,
             tkn.LIST, tkn.CALL, tkn.NEW, tkn.NEW_WITH_ARGS, tkn.ARRAY_INIT,
             tkn.OBJECT_INIT, tkn.PROPERTY_INIT, tkn.GROUP];

    // add "children" to all tokens enumerated in c
    for (var i = 0; i < c.length; i++) {
        if (o[c[i]]) {
            throw new Error("createTraverseData: don't know ordering so "+
                            "can't add 'children' to existing traverseData");
        }
        o[c[i]] = ["children"];
    }

    return o;
}

var traverseData = createTraverseData();

// visitfns: {pre: function, post: function}
// visit function signature: function(node, level, parent, parentProp)
function traverseAstDFS_dynamic(node, visitfns, level, parent, parentProp) {
    if (!node) {
        return;
    }
    if (node instanceof Narcissus.parser.Node !== true) {
        throw new Error("traverseAstDFS expected Node, got "+ typeof node +
                       ". parentProp: "+ parentProp);
    }

    level = level || 0;
    var n;
    visitfns.pre && (n = visitfns.pre(node, level, parent, parentProp));
    if (n !== undefined) {
        node = n;
    }

    for (var prop in node) {
        if (!node.hasOwnProperty(prop)) {
            continue;
        }
        if (prop === "funDecls" || prop === "params" || prop === "varDecls" ||
            prop === "target") {
            continue;
        }
        if (node[prop] instanceof Narcissus.parser.Node) {
            traverseAstDFS(node[prop], visitfns, level + 1, node, prop);
        }
        else if (Array.isArray(node[prop])) {
            for (var j = 0, k = node[prop].length; j < k; j++) {
                traverseAstDFS(node[prop][j], visitfns, level + 1, node, prop + "[" + String(j) + "]");
            }
        }
    }

    visitfns.post && visitfns.post(node, level, parent, parentProp);
}
function traverseAstDFS(node, visitfns, level, parent, parentProp) {
    if (!node) {
        return node;
    }
    if (node instanceof Narcissus.parser.Node !== true) {
        throw new Error("traverseAstDFS expected Node, got "+ typeof node +
                       ". parentProp: "+ parentProp);
    }

    level = level || 0;
    visitfns.pre && (node = visitfns.pre(node, level, parent, parentProp) || node);

    var subprops = traverseData[node.type] || [];
    for (var i = 0; i < subprops.length; i++) {
        var prop = subprops[i];
        if (Array.isArray(node[prop])) {
            for (var j = 0, k = node[prop].length; j < k; j++) {
                traverseAstDFS(node[prop][j], visitfns, level + 1, node, prop + "[" + String(j) + "]");
            }
        }
        else {
            traverseAstDFS(node[prop], visitfns, level + 1, node, prop);
        }
    }

    visitfns.post && (node = visitfns.post(node, level, parent, parentProp) || node);

    return node;
}

function spaces(n, s) {
    return (new Array(n + 1)).join(s || " ");
}
function tokenString(tt) {
    var defs = Narcissus.definitions;
    var t = defs.tokens[tt];
    return /^\W/.test(t) ? defs.opTypeNames[t] : t.toUpperCase();
}

function abbrev(str, max) {
    max = Math.max(Number(max) || 3, 3);
    if (str.length <= max) {
        return str;
    }
    var l = Math.ceil((max - 3) / 2);
    var r = Math.floor((max - 3) / 2);
    return str.slice(0, l) +"..."+ str.slice(str.length - r, str.length);
}

function nodeString(node) {
    function strPos(pos) {
        return pos === undefined ? "?" : String(pos);
    }
    var src = node.tokenizer.source;
    return tokenString(node.type) +
        ("srcs" in node ? " ["+ String(node.srcs) +"]" :
         "start" in node && "end" in node ?
         " '"+ abbrev(src.slice(node.start, node.end), 30) +"'" :
         (node.value !== undefined ? " ("+ node.value +")" : "")) +
        ("start" in node || "end" in node ?
         " ("+ strPos(node.start) +".."+ strPos(node.end) +")" : "") +
        ("parenthesized" in node ? " parenthesized": "");
}

function printTree(root) {
    traverseAstDFS(root, {pre: function(node, level, parent, parentProp) {
        print(spaces(level * 2) + (parentProp || "root") +": "+
              nodeString(node));
    }});
}

function setParent(parent, parentProp, node) {
    if (parentProp[parentProp.length - 1] === "]") {
        var leftBracket = parentProp.indexOf("[");
        var index = parentProp.slice(leftBracket + 1,
                                     parentProp.length - 1);
        var base = parentProp.slice(0, leftBracket);
        parent[base][index] = node;
    }
    else {
        parent[parentProp] = node;
    }
}

function newNode(type, tokenizer, props) {
    var node = Object.create(Narcissus.parser.Node.prototype);
    node.tokenizer = tokenizer;
    node.type = type;
    node.children = [];

    if (props !== undefined) {
        for (var prop in props) {
            node[prop] = props[prop];
        }
    }
    //value, lineno, start, end
    return node;
}

function alterTree(root) {
    function replace(node, var_args) {
        var placeholders = [];
        //collect all # nodes into placeholders array
        traverseAstDFS(node, {pre: function(node, level, parent, parentProp) {
            if (node.type === tkn.PLACEHOLDER) {
                placeholders.push({node: node, parent: parent, parentProp: parentProp});
            }
        }});
        if (arguments.length - 1 !== placeholders.length) {
            throw new Error("replace: placeholders.length mismatch");
        }

        // replace placeholders with new nodes
        for (var i = 0; i < placeholders.length; i++) {
            var o = placeholders[i];
            setParent(o.parent, o.parentProp, arguments[i + 1]);
        }
    }
    traverseAstDFS(root, {pre: function(node, level, parent, parentProp) {
        if (node.type === tkn.PLUS) {
            var replaceNode = parseExpression("__add(#, #)");
            replace(replaceNode, node.children[0], node.children[1]);
            setParent(parent, parentProp, replaceNode);
        }
    }});
}
function adjustStartEnd(root) {
    return traverseAstDFS(root, {post: function(node, level, parent, parentProp) {
        if (parent) {
            if (parent.start === undefined || parent.end === undefined ||
                node.start === undefined || node.end === undefined) {
                throw new Error("adjustStartEnd: undefined start/end");
            }
            parent.start = Math.min(parent.start, node.start);
            parent.end = Math.max(parent.end, node.end);
        }
    }});
}
function srcsify(root) {
    return traverseAstDFS(root, {
        pre: function(node, level, parent, parentProp) {
            node.pos = node.start;
            node.srcs = [];

            if (parent) {
                var src = parent.tokenizer.source;
                parent.srcs.push(src.slice(parent.pos, node.start));
                parent.pos = node.end;
            }
        },
        post: function(node, level, parent, parentProp) {
            var src = node.tokenizer.source;
            node.srcs.push(src.slice(node.pos, node.end));
            delete node.pos;
            delete node.start;
            delete node.end;
            node.tokenizer = {source: ""};
//            delete node.tokenizer;
        }
    });
}

Narcissus.parser.Node.prototype.getSrc = function() {
    var srcs = [];
    traverseAstDFS(this, {
        pre: function(node, level, parent, parentProp) {
            if (parent) {
                srcs.push(parent.srcs[parent.nPushed++]);
            }
            node.nPushed = 0;
        },
        post: function(node, level, parent, parentProp) {
            srcs.push(node.srcs[node.nPushed++]);
            delete node.nPushed;
        }
    });
    return srcs.join("");
};

function parse(str) {
    return srcsify(adjustStartEnd(Narcissus.parser.parse(str, "test.js", 1)));
}
function parseExpression(expr) {
    // SCRIPT -> [SEMICOLON ->] expr
    var stmnt = parse(expr).children[0];
    return stmnt.type === tkn.SEMICOLON ? stmnt.expression : stmnt;
}

print("checker.js done");
<|endoftext|>


<commit_before>/**
 * Handles the import requests
 */

/*
 * 2011 Peter 'Pita' Martischka (Primary Technology Ltd)
 * 2012 Iván Eixarch
 *
 * 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.
 */

var ERR = require("async-stacktrace")
  , padManager = require("../db/PadManager")
  , padMessageHandler = require("./PadMessageHandler")
  , async = require("async")
  , fs = require("fs")
  , path = require("path")
  , settings = require('../utils/Settings')
  , formidable = require('formidable')
  , os = require("os")
  , importHtml = require("../utils/ImportHtml");

//load abiword only if its enabled
if(settings.abiword != null)
  var abiword = require("../utils/Abiword");

//for node 0.6 compatibily, os.tmpDir() only works from 0.8
var tmpDirectory = process.env.TEMP || process.env.TMPDIR || process.env.TMP || '/tmp';

/**
 * do a requested import
 */
exports.doImport = function(req, res, padId)
{
  //pipe to a file
  //convert file to html via abiword
  //set html in the pad

  var srcFile, destFile
    , pad
    , text;

  async.series([
    //save the uploaded file to /tmp
    function(callback) {
      var form = new formidable.IncomingForm();
      form.keepExtensions = true;
      form.uploadDir = tmpDirectory;

      form.parse(req, function(err, fields, files) {
        //the upload failed, stop at this point
        if(err || files.file === undefined) {
          console.warn("Uploading Error: " + err.stack);
          callback("uploadFailed");
        }
        //everything ok, continue
        else {
          //save the path of the uploaded file
          srcFile = files.file.path;
          callback();
        }
      });
    },

    //ensure this is a file ending we know, else we change the file ending to .txt
    //this allows us to accept source code files like .c or .java
    function(callback) {
      var fileEnding = path.extname(srcFile).toLowerCase()
        , knownFileEndings = [".txt", ".doc", ".docx", ".pdf", ".odt", ".html", ".htm"]
        , fileEndingKnown = (knownFileEndings.indexOf(fileEnding) > -1);

      //if the file ending is known, continue as normal
      if(fileEndingKnown) {
        callback();
      }
      //we need to rename this file with a .txt ending
      else {
        var oldSrcFile = srcFile;
        srcFile = path.join(path.dirname(srcFile),path.basename(srcFile, fileEnding)+".txt");

        fs.rename(oldSrcFile, srcFile, callback);
      }
    },

    //convert file to html
    function(callback) {
      var randNum = Math.floor(Math.random()*0xFFFFFFFF);
      destFile = path.join(tmpDirectory, "eplite_import_" + randNum + ".htm");

      if (abiword) {
        abiword.convertFile(srcFile, destFile, "htm", function(err) {
          //catch convert errors
          if(err) {
            console.warn("Converting Error:", err);
            return callback("convertFailed");
          } else {
            callback();
          }
        });
      } else {
        // if no abiword only rename
        fs.rename(srcFile, destFile, callback);
      }
    },

    //get the pad object
    function(callback) {
      padManager.getPad(padId, function(err, _pad){
        if(ERR(err, callback)) return;
        pad = _pad;
        callback();
      });
    },

    //read the text
    function(callback) {
      fs.readFile(destFile, "utf8", function(err, _text){
        if(ERR(err, callback)) return;
        text = _text;

        //node on windows has a delay on releasing of the file lock.
        //We add a 100ms delay to work around this
        if(os.type().indexOf("Windows") > -1){
           setTimeout(function() {callback();}, 100);
        } else {
          callback();
        }
      });
    },

    //change text of the pad and broadcast the changeset
    function(callback) {
      var fileEnding = path.extname(srcFile).toLowerCase();
      if (abiword || fileEnding == ".htm" || fileEnding == ".html") {
        importHtml.setPadHTML(pad, text);
      } else {
        pad.setText(text);
      }
      padMessageHandler.updatePadClients(pad, callback);
    },

    //clean up temporary files
    function(callback) {
      //for node < 0.7 compatible
      var fileExists = fs.exists || path.exists;
      async.parallel([
        function(callback){
          fileExists (srcFile, function(exist) { (exist)? fs.unlink(srcFile, callback): callback(); });
        },
        function(callback){
          fileExists (destFile, function(exist) { (exist)? fs.unlink(destFile, callback): callback(); });
        }
      ], callback);
    }
  ], function(err) {

    var status = "ok";

    //check for known errors and replace the status
    if(err == "uploadFailed" || err == "convertFailed")
    {
      status = err;
      err = null;
    }

    ERR(err);

    //close the connection
    res.send("<script type='text/javascript' src='/static/js/jquery.js'></script><script> if ( (!$.browser.msie) && (!($.browser.mozilla && $.browser.version.indexOf(\"1.8.\") == 0)) ){document.domain = document.domain;}var impexp = window.top.require('/pad_impexp').padimpexp.handleFrameCall('" + status + "');</script>", 200);
  });
}
<commit_msg>use the parent window, not the top<commit_after>/**
 * Handles the import requests
 */

/*
 * 2011 Peter 'Pita' Martischka (Primary Technology Ltd)
 * 2012 Iván Eixarch
 *
 * 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.
 */

var ERR = require("async-stacktrace")
  , padManager = require("../db/PadManager")
  , padMessageHandler = require("./PadMessageHandler")
  , async = require("async")
  , fs = require("fs")
  , path = require("path")
  , settings = require('../utils/Settings')
  , formidable = require('formidable')
  , os = require("os")
  , importHtml = require("../utils/ImportHtml");

//load abiword only if its enabled
if(settings.abiword != null)
  var abiword = require("../utils/Abiword");

//for node 0.6 compatibily, os.tmpDir() only works from 0.8
var tmpDirectory = process.env.TEMP || process.env.TMPDIR || process.env.TMP || '/tmp';

/**
 * do a requested import
 */
exports.doImport = function(req, res, padId)
{
  //pipe to a file
  //convert file to html via abiword
  //set html in the pad

  var srcFile, destFile
    , pad
    , text;

  async.series([
    //save the uploaded file to /tmp
    function(callback) {
      var form = new formidable.IncomingForm();
      form.keepExtensions = true;
      form.uploadDir = tmpDirectory;

      form.parse(req, function(err, fields, files) {
        //the upload failed, stop at this point
        if(err || files.file === undefined) {
          console.warn("Uploading Error: " + err.stack);
          callback("uploadFailed");
        }
        //everything ok, continue
        else {
          //save the path of the uploaded file
          srcFile = files.file.path;
          callback();
        }
      });
    },

    //ensure this is a file ending we know, else we change the file ending to .txt
    //this allows us to accept source code files like .c or .java
    function(callback) {
      var fileEnding = path.extname(srcFile).toLowerCase()
        , knownFileEndings = [".txt", ".doc", ".docx", ".pdf", ".odt", ".html", ".htm"]
        , fileEndingKnown = (knownFileEndings.indexOf(fileEnding) > -1);

      //if the file ending is known, continue as normal
      if(fileEndingKnown) {
        callback();
      }
      //we need to rename this file with a .txt ending
      else {
        var oldSrcFile = srcFile;
        srcFile = path.join(path.dirname(srcFile),path.basename(srcFile, fileEnding)+".txt");

        fs.rename(oldSrcFile, srcFile, callback);
      }
    },

    //convert file to html
    function(callback) {
      var randNum = Math.floor(Math.random()*0xFFFFFFFF);
      destFile = path.join(tmpDirectory, "eplite_import_" + randNum + ".htm");

      if (abiword) {
        abiword.convertFile(srcFile, destFile, "htm", function(err) {
          //catch convert errors
          if(err) {
            console.warn("Converting Error:", err);
            return callback("convertFailed");
          } else {
            callback();
          }
        });
      } else {
        // if no abiword only rename
        fs.rename(srcFile, destFile, callback);
      }
    },

    //get the pad object
    function(callback) {
      padManager.getPad(padId, function(err, _pad){
        if(ERR(err, callback)) return;
        pad = _pad;
        callback();
      });
    },

    //read the text
    function(callback) {
      fs.readFile(destFile, "utf8", function(err, _text){
        if(ERR(err, callback)) return;
        text = _text;

        //node on windows has a delay on releasing of the file lock.
        //We add a 100ms delay to work around this
        if(os.type().indexOf("Windows") > -1){
           setTimeout(function() {callback();}, 100);
        } else {
          callback();
        }
      });
    },

    //change text of the pad and broadcast the changeset
    function(callback) {
      var fileEnding = path.extname(srcFile).toLowerCase();
      if (abiword || fileEnding == ".htm" || fileEnding == ".html") {
        importHtml.setPadHTML(pad, text);
      } else {
        pad.setText(text);
      }
      padMessageHandler.updatePadClients(pad, callback);
    },

    //clean up temporary files
    function(callback) {
      //for node < 0.7 compatible
      var fileExists = fs.exists || path.exists;
      async.parallel([
        function(callback){
          fileExists (srcFile, function(exist) { (exist)? fs.unlink(srcFile, callback): callback(); });
        },
        function(callback){
          fileExists (destFile, function(exist) { (exist)? fs.unlink(destFile, callback): callback(); });
        }
      ], callback);
    }
  ], function(err) {

    var status = "ok";

    //check for known errors and replace the status
    if(err == "uploadFailed" || err == "convertFailed")
    {
      status = err;
      err = null;
    }

    ERR(err);

    //close the connection
    res.send("<script type='text/javascript' src='/static/js/jquery.js'></script><script> if ( (!$.browser.msie) && (!($.browser.mozilla && $.browser.version.indexOf(\"1.8.\") == 0)) ){document.domain = document.domain;}var impexp = window.parent.require('/pad_impexp').padimpexp.handleFrameCall('" + status + "');</script>", 200);
  });
}
<|endoftext|>


<commit_before>// FIXME factor out key precondition (shift et. al)

goog.provide('ol.interaction.Interaction');

goog.require('ol');
goog.require('ol.Object');
goog.require('ol.animation');
goog.require('ol.easing');

/**
 * @classdesc
 * Abstract base class; normally only used for creating subclasses and not
 * instantiated in apps.
 * User actions that change the state of the map. Some are similar to controls,
 * but are not associated with a DOM element.
 * For example, {@link ol.interaction.KeyboardZoom} is functionally the same as
 * {@link ol.control.Zoom}, but triggered by a keyboard event not a button
 * element event.
 * Although interactions do not have a DOM element, some of them do render
 * vectors and so are visible on the screen.
 *
 * @constructor
 * @param {olx.interaction.InteractionOptions} options Options.
 * @extends {ol.Object}
 * @api
 */
ol.interaction.Interaction = function(options) {

  ol.Object.call(this);

  /**
   * @private
   * @type {ol.Map}
   */
  this.map_ = null;

  this.setActive(true);

  /**
   * @type {function(ol.MapBrowserEvent):boolean}
   */
  this.handleEvent = options.handleEvent;

};
ol.inherits(ol.interaction.Interaction, ol.Object);

/**
 * Return whether the interaction is currently active.
 * @return {boolean} `true` if the interaction is active, `false` otherwise.
 * @observable
 * @api
 */
ol.interaction.Interaction.prototype.getActive = function() {
  return /** @type {boolean} */ (
      this.get(ol.interaction.Interaction.Property.ACTIVE));
};

/**
 * Get the map associated with this interaction.
 * @return {ol.Map} Map.
 * @api
 */
ol.interaction.Interaction.prototype.getMap = function() {
  return this.map_;
};

/**
 * Activate or deactivate the interaction.
 * @param {boolean} active Active.
 * @observable
 * @api
 */
ol.interaction.Interaction.prototype.setActive = function(active) {
  this.set(ol.interaction.Interaction.Property.ACTIVE, active);
};

/**
 * Remove the interaction from its current map and attach it to the new map.
 * Subclasses may set up event handlers to get notified about changes to
 * the map here.
 * @param {ol.Map} map Map.
 */
ol.interaction.Interaction.prototype.setMap = function(map) {
  this.map_ = map;
};

/**
 * @param {ol.Map} map Map.
 * @param {ol.View} view View.
 * @param {ol.Coordinate} delta Delta.
 * @param {number=} opt_duration Duration.
 */
ol.interaction.Interaction.pan = function(map, view, delta, opt_duration) {
  var currentCenter = view.getCenter();
  if (currentCenter) {
    if (opt_duration && opt_duration > 0) {
      map.beforeRender(ol.animation.pan({
        source: currentCenter,
        duration: opt_duration,
        easing: ol.easing.linear
      }));
    }
    var center = view.constrainCenter(
        [currentCenter[0] + delta[0], currentCenter[1] + delta[1]]);
    view.setCenter(center);
  }
};

/**
 * @param {ol.Map} map Map.
 * @param {ol.View} view View.
 * @param {number|undefined} rotation Rotation.
 * @param {ol.Coordinate=} opt_anchor Anchor coordinate.
 * @param {number=} opt_duration Duration.
 */
ol.interaction.Interaction.rotate = function(map, view, rotation, opt_anchor, opt_duration) {
  rotation = view.constrainRotation(rotation, 0);
  ol.interaction.Interaction.rotateWithoutConstraints(
      map, view, rotation, opt_anchor, opt_duration);
};

/**
 * @param {ol.Map} map Map.
 * @param {ol.View} view View.
 * @param {number|undefined} rotation Rotation.
 * @param {ol.Coordinate=} opt_anchor Anchor coordinate.
 * @param {number=} opt_duration Duration.
 */
ol.interaction.Interaction.rotateWithoutConstraints = function(map, view, rotation, opt_anchor, opt_duration) {
  if (rotation !== undefined) {
    var currentRotation = view.getRotation();
    var currentCenter = view.getCenter();
    if (currentRotation !== undefined && currentCenter &&
        opt_duration && opt_duration > 0) {
      map.beforeRender(ol.animation.rotate({
        rotation: currentRotation,
        duration: opt_duration,
        easing: ol.easing.easeOut
      }));
      if (opt_anchor) {
        map.beforeRender(ol.animation.pan({
          source: currentCenter,
          duration: opt_duration,
          easing: ol.easing.easeOut
        }));
      }
    }
    view.rotate(rotation, opt_anchor);
  }
};

/**
 * @param {ol.Map} map Map.
 * @param {ol.View} view View.
 * @param {number|undefined} resolution Resolution to go to.
 * @param {ol.Coordinate=} opt_anchor Anchor coordinate.
 * @param {number=} opt_duration Duration.
 * @param {number=} opt_direction Zooming direction; > 0 indicates
 *     zooming out, in which case the constraints system will select
 *     the largest nearest resolution; < 0 indicates zooming in, in
 *     which case the constraints system will select the smallest
 *     nearest resolution; == 0 indicates that the zooming direction
 *     is unknown/not relevant, in which case the constraints system
 *     will select the nearest resolution. If not defined 0 is
 *     assumed.
 */
ol.interaction.Interaction.zoom = function(map, view, resolution, opt_anchor, opt_duration, opt_direction) {
  resolution = view.constrainResolution(resolution, 0, opt_direction);
  ol.interaction.Interaction.zoomWithoutConstraints(
      map, view, resolution, opt_anchor, opt_duration);
};

/**
 * @param {ol.Map} map Map.
 * @param {ol.View} view View.
 * @param {number} delta Delta from previous zoom level.
 * @param {ol.Coordinate=} opt_anchor Anchor coordinate.
 * @param {number=} opt_duration Duration.
 */
ol.interaction.Interaction.zoomByDelta = function(map, view, delta, opt_anchor, opt_duration) {
  var currentResolution = view.getResolution();
  var resolution = view.constrainResolution(currentResolution, delta, 0);
  ol.interaction.Interaction.zoomWithoutConstraints(
      map, view, resolution, opt_anchor, opt_duration);
};

/**
 * @param {ol.Map} map Map.
 * @param {ol.View} view View.
 * @param {number|undefined} resolution Resolution to go to.
 * @param {ol.Coordinate=} opt_anchor Anchor coordinate.
 * @param {number=} opt_duration Duration.
 */
ol.interaction.Interaction.zoomWithoutConstraints = function(map, view, resolution, opt_anchor, opt_duration) {
  if (resolution) {
    var currentResolution = view.getResolution();
    var currentCenter = view.getCenter();
    if (currentResolution !== undefined && currentCenter &&
        resolution !== currentResolution &&
        opt_duration && opt_duration > 0) {
      map.beforeRender(ol.animation.zoom({
        resolution: currentResolution,
        duration: opt_duration,
        easing: ol.easing.easeOut
      }));
      if (opt_anchor) {
        map.beforeRender(ol.animation.pan({
          source: currentCenter,
          duration: opt_duration,
          easing: ol.easing.easeOut
        }));
      }
    }
    if (opt_anchor) {
      var center = view.calculateCenterZoom(resolution, opt_anchor);
      view.setCenter(center);
    }
    view.setResolution(resolution);
  }
};

/**
 * @enum {string}
 */
ol.interaction.Interaction.Property = {
  ACTIVE: 'active'
};
<commit_msg>Use view.animate() in the pan interaction<commit_after>// FIXME factor out key precondition (shift et. al)

goog.provide('ol.interaction.Interaction');

goog.require('ol');
goog.require('ol.Object');
goog.require('ol.animation');
goog.require('ol.easing');

/**
 * @classdesc
 * Abstract base class; normally only used for creating subclasses and not
 * instantiated in apps.
 * User actions that change the state of the map. Some are similar to controls,
 * but are not associated with a DOM element.
 * For example, {@link ol.interaction.KeyboardZoom} is functionally the same as
 * {@link ol.control.Zoom}, but triggered by a keyboard event not a button
 * element event.
 * Although interactions do not have a DOM element, some of them do render
 * vectors and so are visible on the screen.
 *
 * @constructor
 * @param {olx.interaction.InteractionOptions} options Options.
 * @extends {ol.Object}
 * @api
 */
ol.interaction.Interaction = function(options) {

  ol.Object.call(this);

  /**
   * @private
   * @type {ol.Map}
   */
  this.map_ = null;

  this.setActive(true);

  /**
   * @type {function(ol.MapBrowserEvent):boolean}
   */
  this.handleEvent = options.handleEvent;

};
ol.inherits(ol.interaction.Interaction, ol.Object);

/**
 * Return whether the interaction is currently active.
 * @return {boolean} `true` if the interaction is active, `false` otherwise.
 * @observable
 * @api
 */
ol.interaction.Interaction.prototype.getActive = function() {
  return /** @type {boolean} */ (
      this.get(ol.interaction.Interaction.Property.ACTIVE));
};

/**
 * Get the map associated with this interaction.
 * @return {ol.Map} Map.
 * @api
 */
ol.interaction.Interaction.prototype.getMap = function() {
  return this.map_;
};

/**
 * Activate or deactivate the interaction.
 * @param {boolean} active Active.
 * @observable
 * @api
 */
ol.interaction.Interaction.prototype.setActive = function(active) {
  this.set(ol.interaction.Interaction.Property.ACTIVE, active);
};

/**
 * Remove the interaction from its current map and attach it to the new map.
 * Subclasses may set up event handlers to get notified about changes to
 * the map here.
 * @param {ol.Map} map Map.
 */
ol.interaction.Interaction.prototype.setMap = function(map) {
  this.map_ = map;
};

/**
 * @param {ol.Map} map Map.
 * @param {ol.View} view View.
 * @param {ol.Coordinate} delta Delta.
 * @param {number=} opt_duration Duration.
 */
ol.interaction.Interaction.pan = function(map, view, delta, opt_duration) {
  var currentCenter = view.getCenter();
  if (currentCenter) {
    var center = view.constrainCenter(
        [currentCenter[0] + delta[0], currentCenter[1] + delta[1]]);
    if (opt_duration) {
      view.animate({
        duration: opt_duration,
        easing: ol.easing.linear,
        center: center
      });
    } else {
      view.setCenter(center);
    }
  }
};

/**
 * @param {ol.Map} map Map.
 * @param {ol.View} view View.
 * @param {number|undefined} rotation Rotation.
 * @param {ol.Coordinate=} opt_anchor Anchor coordinate.
 * @param {number=} opt_duration Duration.
 */
ol.interaction.Interaction.rotate = function(map, view, rotation, opt_anchor, opt_duration) {
  rotation = view.constrainRotation(rotation, 0);
  ol.interaction.Interaction.rotateWithoutConstraints(
      map, view, rotation, opt_anchor, opt_duration);
};

/**
 * @param {ol.Map} map Map.
 * @param {ol.View} view View.
 * @param {number|undefined} rotation Rotation.
 * @param {ol.Coordinate=} opt_anchor Anchor coordinate.
 * @param {number=} opt_duration Duration.
 */
ol.interaction.Interaction.rotateWithoutConstraints = function(map, view, rotation, opt_anchor, opt_duration) {
  if (rotation !== undefined) {
    var currentRotation = view.getRotation();
    var currentCenter = view.getCenter();
    if (currentRotation !== undefined && currentCenter &&
        opt_duration && opt_duration > 0) {
      map.beforeRender(ol.animation.rotate({
        rotation: currentRotation,
        duration: opt_duration,
        easing: ol.easing.easeOut
      }));
      if (opt_anchor) {
        map.beforeRender(ol.animation.pan({
          source: currentCenter,
          duration: opt_duration,
          easing: ol.easing.easeOut
        }));
      }
    }
    view.rotate(rotation, opt_anchor);
  }
};

/**
 * @param {ol.Map} map Map.
 * @param {ol.View} view View.
 * @param {number|undefined} resolution Resolution to go to.
 * @param {ol.Coordinate=} opt_anchor Anchor coordinate.
 * @param {number=} opt_duration Duration.
 * @param {number=} opt_direction Zooming direction; > 0 indicates
 *     zooming out, in which case the constraints system will select
 *     the largest nearest resolution; < 0 indicates zooming in, in
 *     which case the constraints system will select the smallest
 *     nearest resolution; == 0 indicates that the zooming direction
 *     is unknown/not relevant, in which case the constraints system
 *     will select the nearest resolution. If not defined 0 is
 *     assumed.
 */
ol.interaction.Interaction.zoom = function(map, view, resolution, opt_anchor, opt_duration, opt_direction) {
  resolution = view.constrainResolution(resolution, 0, opt_direction);
  ol.interaction.Interaction.zoomWithoutConstraints(
      map, view, resolution, opt_anchor, opt_duration);
};

/**
 * @param {ol.Map} map Map.
 * @param {ol.View} view View.
 * @param {number} delta Delta from previous zoom level.
 * @param {ol.Coordinate=} opt_anchor Anchor coordinate.
 * @param {number=} opt_duration Duration.
 */
ol.interaction.Interaction.zoomByDelta = function(map, view, delta, opt_anchor, opt_duration) {
  var currentResolution = view.getResolution();
  var resolution = view.constrainResolution(currentResolution, delta, 0);
  ol.interaction.Interaction.zoomWithoutConstraints(
      map, view, resolution, opt_anchor, opt_duration);
};

/**
 * @param {ol.Map} map Map.
 * @param {ol.View} view View.
 * @param {number|undefined} resolution Resolution to go to.
 * @param {ol.Coordinate=} opt_anchor Anchor coordinate.
 * @param {number=} opt_duration Duration.
 */
ol.interaction.Interaction.zoomWithoutConstraints = function(map, view, resolution, opt_anchor, opt_duration) {
  if (resolution) {
    var currentResolution = view.getResolution();
    var currentCenter = view.getCenter();
    if (currentResolution !== undefined && currentCenter &&
        resolution !== currentResolution &&
        opt_duration && opt_duration > 0) {
      map.beforeRender(ol.animation.zoom({
        resolution: currentResolution,
        duration: opt_duration,
        easing: ol.easing.easeOut
      }));
      if (opt_anchor) {
        map.beforeRender(ol.animation.pan({
          source: currentCenter,
          duration: opt_duration,
          easing: ol.easing.easeOut
        }));
      }
    }
    if (opt_anchor) {
      var center = view.calculateCenterZoom(resolution, opt_anchor);
      view.setCenter(center);
    }
    view.setResolution(resolution);
  }
};

/**
 * @enum {string}
 */
ol.interaction.Interaction.Property = {
  ACTIVE: 'active'
};
<|endoftext|>


<commit_before>class Garumu extends Chara{
	static getText(){
		//キャラ説明
		return "アタッカータイプ：
素早く動いて手数で相手を攻める";
	}
	constructor(aX,aY,aTeam,aOperationNum){
		let tData=Garumu.getCharaData();
		super(aX,aY,aTeam,tData,aOperationNum);
		this.data=tData;

		this.doubleTurnFlag=false;
		this.additionalDelayTemp=0;
	}
	static getCharaNatureSkill(){
		//特性の説明
		return "1ターンに2回行動できる";
	}
	static getCharaData(){
		return {NAME:"ガルム",
						HP:80,
						MP:5,
						ATK:23,
						DEF:21,
						SPD:26,
						MOV:2,
						TYPE:"diamond",
						IMAGE:1264010001,
						DECK:Garumu.getDeck()
		}
	}
	static getDeck(){
		return [
			{NUMBER:101,
				TEXT:"隣のマスに威力3のダメージ",
				RANGE:[["distance",1]],
				POWER:3,
				DELAY:0,
				MAGIC:0,
				SUPPORT_Be_Myself:[],
				SUPPORT_Af_Myself:[],
				SUPPORT_Be_Enemy:[],
				SUPPORT_Af_Enemy:[],
				SUPPORT_Otherwise:[],
				M_ATTACK:0,
				F_ATTACK:false,
		    E_ATTACK:true,
				ANIMATION:[0]
			},
			{NUMBER:102,
				TEXT:"隣のマスに威力3のダメージ",
				RANGE:[["distance",1]],
				POWER:3,
				DELAY:0,
				MAGIC:0,
				SUPPORT_Be_Myself:[],
				SUPPORT_Af_Myself:[],
				SUPPORT_Be_Enemy:[],
				SUPPORT_Af_Enemy:[],
				SUPPORT_Otherwise:[],
				M_ATTACK:0,
				F_ATTACK:false,
		    E_ATTACK:true,
				ANIMATION:[0]
			},
			{NUMBER:103,
				TEXT:"隣のマスに威力3のダメージ",
				RANGE:[["distance",1]],
				POWER:3,
				DELAY:0,
				MAGIC:0,
				SUPPORT_Be_Myself:[],
				SUPPORT_Af_Myself:[],
				SUPPORT_Be_Enemy:[],
				SUPPORT_Af_Enemy:[],
				SUPPORT_Otherwise:[],
				M_ATTACK:0,
				F_ATTACK:false,
		    E_ATTACK:true,
				ANIMATION:[0]
			},
			{NUMBER:104,
				TEXT:"2マス隣に威力2ダメージ",
				RANGE:[["distance",2]],
				POWER:2,
				DELAY:0,
				MAGIC:0,
				SUPPORT_Be_Myself:[],
				SUPPORT_Af_Myself:[],
				SUPPORT_Be_Enemy:[],
				SUPPORT_Af_Enemy:[],
				SUPPORT_Otherwise:[],
				M_ATTACK:0,
				F_ATTACK:false,
		    E_ATTACK:true,
				ANIMATION:[0]
			},
			{NUMBER:105,
				TEXT:"2マス隣に威力2のダメージ",
				RANGE:[["distance",2]],
				POWER:2,
				DELAY:0,
				MAGIC:0,
				SUPPORT_Be_Myself:[],
				SUPPORT_Af_Myself:[],
				SUPPORT_Be_Enemy:[],
				SUPPORT_Af_Enemy:[],
				SUPPORT_Otherwise:[],
				M_ATTACK:0,
				F_ATTACK:false,
		    E_ATTACK:true,
				ANIMATION:[0]
			},
			{NUMBER:105,
				TEXT:"2マス隣に威力2のダメージ",
				RANGE:[["distance",2]],
				POWER:2,
				DELAY:0,
				MAGIC:0,
				SUPPORT_Be_Myself:[],
				SUPPORT_Af_Myself:[],
				SUPPORT_Be_Enemy:[],
				SUPPORT_Af_Enemy:[],
				SUPPORT_Otherwise:[],
				M_ATTACK:0,
				F_ATTACK:false,
		    E_ATTACK:true,
				ANIMATION:[0]
			},
			{NUMBER:7,
				TEXT:"シャッフルしてもう一度行動",
				RANGE:[],
				POWER:0,
				DELAY:0,
				MAGIC:0,
				SUPPORT_Be_Myself:[],
				SUPPORT_Af_Myself:[{effect:"getTurn"}],
				SUPPORT_Be_Enemy:[],
				SUPPORT_Af_Enemy:[],
				SUPPORT_Otherwise:[{effect:"shuffle"}],
				M_ATTACK:0,
				F_ATTACK:false,
				E_ATTACK:true,
				ANIMATION:[0]
			},
			{NUMBER:108,
				TEXT:"相手全体に威力1のダメージ",
				RANGE:[["enemy"]],
				POWER:1,
				DELAY:5,
				MAGIC:0,
				SUPPORT_Be_Myself:[],
				SUPPORT_Af_Myself:[],
				SUPPORT_Be_Enemy:[],
				SUPPORT_Af_Enemy:[],
				SUPPORT_Otherwise:[],
				M_ATTACK:0,
				F_ATTACK:false,
		    E_ATTACK:true,
				ANIMATION:[5]
			},
			{NUMBER:106,
				TEXT:"十字に威力２ダメージ",
				RANGE:[["vertical",1],["horizontal",1]],
				POWER:2,
				DELAY:0,
				MAGIC:0,
				SUPPORT_Be_Myself:[],
				SUPPORT_Af_Myself:[],
				SUPPORT_Be_Enemy:[],
				SUPPORT_Af_Enemy:[],
				SUPPORT_Otherwise:[],
				M_ATTACK:0,
				F_ATTACK:false,
		    E_ATTACK:true,
				ANIMATION:[0]
			},
			{NUMBER:106,
				TEXT:"十字に威力２ダメージ",
				RANGE:[["vertical",1],["horizontal",1]],
				POWER:2,
				DELAY:0,
				MAGIC:0,
				SUPPORT_Be_Myself:[],
				SUPPORT_Af_Myself:[],
				SUPPORT_Be_Enemy:[],
				SUPPORT_Af_Enemy:[],
				SUPPORT_Otherwise:[],
				M_ATTACK:0,
				F_ATTACK:false,
		    E_ATTACK:true,
				ANIMATION:[0]
			},
			{NUMBER:111,
				TEXT:"周囲１２マスに敵味方無視の威力4のダメージ",
				RANGE:[["circumference",2]],
				POWER:4,
				DELAY:0,
				MAGIC:1,
				SUPPORT_Be_Myself:[],
				SUPPORT_Af_Myself:[],
				SUPPORT_Be_Enemy:[],
				SUPPORT_Af_Enemy:[],
				SUPPORT_Otherwise:[],
				M_ATTACK:2,
				F_ATTACK:true,
		    E_ATTACK:true,
				ANIMATION:[0,3]
			},
			{NUMBER:112,
				TEXT:"周囲１２マスに敵味方無視の威力4のダメージ",
				RANGE:[["circumference",2]],
				POWER:4,
				DELAY:0,
				MAGIC:1,
				SUPPORT_Be_Myself:[],
				SUPPORT_Af_Myself:[],
				SUPPORT_Be_Enemy:[],
				SUPPORT_Af_Enemy:[],
				SUPPORT_Otherwise:[],
				M_ATTACK:2,
				F_ATTACK:true,
		    E_ATTACK:true,
				ANIMATION:[0,3]
			},
			{NUMBER:612,
				TEXT:"スピード6アップ　その後DELAYを50下げる（タイプ一致時8アップ）",
				RANGE:[],
				POWER:0,
				DELAY:0,
				MAGIC:2,
				SUPPORT_Be_Myself:[],
				SUPPORT_Af_Myself:[{effect:"spd",value:6,additionOfMatchingType:2},{effect:"delay",value:-50}],
				SUPPORT_Be_Enemy:[],
				SUPPORT_Af_Enemy:[],
				SUPPORT_Otherwise:[],
				M_ATTACK:0,
				F_ATTACK:false,
		    E_ATTACK:true,
				ANIMATION:[0]
			},
			{NUMBER:114,
				TEXT:"相手全体に威力3のダメージ その後シャッフルしもう一度行動（消費MP３）",
				RANGE:[["enemy"]],
				POWER:3,
				DELAY:0,
				MAGIC:3,
				SUPPORT_Be_Myself:[],
				SUPPORT_Af_Myself:[{effect:"getTurn"}],
				SUPPORT_Be_Enemy:[],
				SUPPORT_Af_Enemy:[],
				SUPPORT_Otherwise:[{effect:"revers"},{effect:"shuffle"}],
				M_ATTACK:0,
				F_ATTACK:false,
		    E_ATTACK:true,
				ANIMATION:[0]
			},
			{NUMBER:0,
					TEXT:"スカ　何も起こらない",
					RANGE:[],
					POWER:0,
					DELAY:0,
					MAGIC:0,
					SUPPORT_Be_Myself:[],
					SUPPORT_Af_Myself:[],
					SUPPORT_Be_Enemy:[],
					SUPPORT_Af_Enemy:[],
					SUPPORT_Otherwise:[{effect:"revers"}],
					M_ATTACK:0,
					F_ATTACK:false,
			    E_ATTACK:true,
					ANIMATION:[0]
				},]
	}
	startTurn(){
		if(this.doubleTurnFlag){
			this.getTurnFlag=true;
		}
		return super.startTurn();
	}
	endTurn(aDelay){
		if(this.getTurnFlag){
			return super.endTurn(0);
		}
		else{
			if(this.doubleTurnFlag){
				let tDelay=this.additionalDelayTemp;
				this.additionalDelayTemp=0;
				this.doubleTurnFlag=false;
				return super.endTurn(tDelay);
			}
			else{
				this.additionalDelayTemp+=aDelay;
				this.doubleTurnFlag=true;
				newLog([mTurnChara,"は特性によって連続で行動"])
				return new Promise((res,rej)=>{res();});
			}
		}
	}
}
<commit_msg>ガルムのjokerスキル効果をgetTurnからdelayに変更<commit_after>class Garumu extends Chara{
	static getText(){
		//キャラ説明
		return "アタッカータイプ：
素早く動いて手数で相手を攻める";
	}
	constructor(aX,aY,aTeam,aOperationNum){
		let tData=Garumu.getCharaData();
		super(aX,aY,aTeam,tData,aOperationNum);
		this.data=tData;

		this.doubleTurnFlag=false;
		this.additionalDelayTemp=0;
	}
	static getCharaNatureSkill(){
		//特性の説明
		return "1ターンに2回行動できる";
	}
	static getCharaData(){
		return {NAME:"ガルム",
						HP:80,
						MP:5,
						ATK:23,
						DEF:21,
						SPD:26,
						MOV:2,
						TYPE:"diamond",
						IMAGE:1264010001,
						DECK:Garumu.getDeck()
		}
	}
	static getDeck(){
		return [
			{NUMBER:101,
				TEXT:"隣のマスに威力3のダメージ",
				RANGE:[["distance",1]],
				POWER:3,
				DELAY:0,
				MAGIC:0,
				SUPPORT_Be_Myself:[],
				SUPPORT_Af_Myself:[],
				SUPPORT_Be_Enemy:[],
				SUPPORT_Af_Enemy:[],
				SUPPORT_Otherwise:[],
				M_ATTACK:0,
				F_ATTACK:false,
		    E_ATTACK:true,
				ANIMATION:[0]
			},
			{NUMBER:102,
				TEXT:"隣のマスに威力3のダメージ",
				RANGE:[["distance",1]],
				POWER:3,
				DELAY:0,
				MAGIC:0,
				SUPPORT_Be_Myself:[],
				SUPPORT_Af_Myself:[],
				SUPPORT_Be_Enemy:[],
				SUPPORT_Af_Enemy:[],
				SUPPORT_Otherwise:[],
				M_ATTACK:0,
				F_ATTACK:false,
		    E_ATTACK:true,
				ANIMATION:[0]
			},
			{NUMBER:103,
				TEXT:"隣のマスに威力3のダメージ",
				RANGE:[["distance",1]],
				POWER:3,
				DELAY:0,
				MAGIC:0,
				SUPPORT_Be_Myself:[],
				SUPPORT_Af_Myself:[],
				SUPPORT_Be_Enemy:[],
				SUPPORT_Af_Enemy:[],
				SUPPORT_Otherwise:[],
				M_ATTACK:0,
				F_ATTACK:false,
		    E_ATTACK:true,
				ANIMATION:[0]
			},
			{NUMBER:104,
				TEXT:"2マス隣に威力2ダメージ",
				RANGE:[["distance",2]],
				POWER:2,
				DELAY:0,
				MAGIC:0,
				SUPPORT_Be_Myself:[],
				SUPPORT_Af_Myself:[],
				SUPPORT_Be_Enemy:[],
				SUPPORT_Af_Enemy:[],
				SUPPORT_Otherwise:[],
				M_ATTACK:0,
				F_ATTACK:false,
		    E_ATTACK:true,
				ANIMATION:[0]
			},
			{NUMBER:105,
				TEXT:"2マス隣に威力2のダメージ",
				RANGE:[["distance",2]],
				POWER:2,
				DELAY:0,
				MAGIC:0,
				SUPPORT_Be_Myself:[],
				SUPPORT_Af_Myself:[],
				SUPPORT_Be_Enemy:[],
				SUPPORT_Af_Enemy:[],
				SUPPORT_Otherwise:[],
				M_ATTACK:0,
				F_ATTACK:false,
		    E_ATTACK:true,
				ANIMATION:[0]
			},
			{NUMBER:105,
				TEXT:"2マス隣に威力2のダメージ",
				RANGE:[["distance",2]],
				POWER:2,
				DELAY:0,
				MAGIC:0,
				SUPPORT_Be_Myself:[],
				SUPPORT_Af_Myself:[],
				SUPPORT_Be_Enemy:[],
				SUPPORT_Af_Enemy:[],
				SUPPORT_Otherwise:[],
				M_ATTACK:0,
				F_ATTACK:false,
		    E_ATTACK:true,
				ANIMATION:[0]
			},
			{NUMBER:7,
				TEXT:"シャッフルしてもう一度行動",
				RANGE:[],
				POWER:0,
				DELAY:0,
				MAGIC:0,
				SUPPORT_Be_Myself:[],
				SUPPORT_Af_Myself:[{effect:"getTurn"}],
				SUPPORT_Be_Enemy:[],
				SUPPORT_Af_Enemy:[],
				SUPPORT_Otherwise:[{effect:"shuffle"}],
				M_ATTACK:0,
				F_ATTACK:false,
				E_ATTACK:true,
				ANIMATION:[0]
			},
			{NUMBER:108,
				TEXT:"相手全体に威力1のダメージ",
				RANGE:[["enemy"]],
				POWER:1,
				DELAY:5,
				MAGIC:0,
				SUPPORT_Be_Myself:[],
				SUPPORT_Af_Myself:[],
				SUPPORT_Be_Enemy:[],
				SUPPORT_Af_Enemy:[],
				SUPPORT_Otherwise:[],
				M_ATTACK:0,
				F_ATTACK:false,
		    E_ATTACK:true,
				ANIMATION:[5]
			},
			{NUMBER:106,
				TEXT:"十字に威力２ダメージ",
				RANGE:[["vertical",1],["horizontal",1]],
				POWER:2,
				DELAY:0,
				MAGIC:0,
				SUPPORT_Be_Myself:[],
				SUPPORT_Af_Myself:[],
				SUPPORT_Be_Enemy:[],
				SUPPORT_Af_Enemy:[],
				SUPPORT_Otherwise:[],
				M_ATTACK:0,
				F_ATTACK:false,
		    E_ATTACK:true,
				ANIMATION:[0]
			},
			{NUMBER:106,
				TEXT:"十字に威力２ダメージ",
				RANGE:[["vertical",1],["horizontal",1]],
				POWER:2,
				DELAY:0,
				MAGIC:0,
				SUPPORT_Be_Myself:[],
				SUPPORT_Af_Myself:[],
				SUPPORT_Be_Enemy:[],
				SUPPORT_Af_Enemy:[],
				SUPPORT_Otherwise:[],
				M_ATTACK:0,
				F_ATTACK:false,
		    E_ATTACK:true,
				ANIMATION:[0]
			},
			{NUMBER:111,
				TEXT:"周囲１２マスに敵味方無視の威力4のダメージ",
				RANGE:[["circumference",2]],
				POWER:4,
				DELAY:0,
				MAGIC:1,
				SUPPORT_Be_Myself:[],
				SUPPORT_Af_Myself:[],
				SUPPORT_Be_Enemy:[],
				SUPPORT_Af_Enemy:[],
				SUPPORT_Otherwise:[],
				M_ATTACK:2,
				F_ATTACK:true,
		    E_ATTACK:true,
				ANIMATION:[0,3]
			},
			{NUMBER:112,
				TEXT:"周囲１２マスに敵味方無視の威力4のダメージ",
				RANGE:[["circumference",2]],
				POWER:4,
				DELAY:0,
				MAGIC:1,
				SUPPORT_Be_Myself:[],
				SUPPORT_Af_Myself:[],
				SUPPORT_Be_Enemy:[],
				SUPPORT_Af_Enemy:[],
				SUPPORT_Otherwise:[],
				M_ATTACK:2,
				F_ATTACK:true,
		    E_ATTACK:true,
				ANIMATION:[0,3]
			},
			{NUMBER:612,
				TEXT:"スピード6アップ　その後DELAYを50下げる（タイプ一致時8アップ）",
				RANGE:[],
				POWER:0,
				DELAY:0,
				MAGIC:2,
				SUPPORT_Be_Myself:[],
				SUPPORT_Af_Myself:[{effect:"spd",value:6,additionOfMatchingType:2},{effect:"delay",value:-50}],
				SUPPORT_Be_Enemy:[],
				SUPPORT_Af_Enemy:[],
				SUPPORT_Otherwise:[],
				M_ATTACK:0,
				F_ATTACK:false,
		    E_ATTACK:true,
				ANIMATION:[0]
			},
			{NUMBER:114,
				TEXT:"相手全体に威力3のダメージ その後シャッフルしもう一度行動（消費MP３）",
				RANGE:[["enemy"]],
				POWER:3,
				DELAY:0,
				MAGIC:3,
				SUPPORT_Be_Myself:[],
				SUPPORT_Af_Myself:[{effect:"delay",value:-100}],
				SUPPORT_Be_Enemy:[],
				SUPPORT_Af_Enemy:[],
				SUPPORT_Otherwise:[{effect:"revers"},{effect:"shuffle"}],
				M_ATTACK:0,
				F_ATTACK:false,
		    E_ATTACK:true,
				ANIMATION:[0]
			},
			{NUMBER:0,
					TEXT:"スカ　何も起こらない",
					RANGE:[],
					POWER:0,
					DELAY:0,
					MAGIC:0,
					SUPPORT_Be_Myself:[],
					SUPPORT_Af_Myself:[],
					SUPPORT_Be_Enemy:[],
					SUPPORT_Af_Enemy:[],
					SUPPORT_Otherwise:[{effect:"revers"}],
					M_ATTACK:0,
					F_ATTACK:false,
			    E_ATTACK:true,
					ANIMATION:[0]
				},]
	}
	startTurn(){
		if(this.doubleTurnFlag){
			this.getTurnFlag=true;
		}
		return super.startTurn();
	}
	endTurn(aDelay){
		if(this.getTurnFlag){
			return super.endTurn(0);
		}
		else{
			if(this.doubleTurnFlag){
				let tDelay=this.additionalDelayTemp;
				this.additionalDelayTemp=0;
				this.doubleTurnFlag=false;
				return super.endTurn(tDelay);
			}
			else{
				this.additionalDelayTemp+=aDelay;
				this.doubleTurnFlag=true;
				newLog([mTurnChara,"は特性によって連続で行動"])
				return new Promise((res,rej)=>{res();});
			}
		}
	}
}
<|endoftext|>


<commit_before>var current_mode;

function chatsUpdate(first) {
    $('#under-page').empty();

    if ($('body').class()) {
        mode = $('body').class();
    } else {
        mode = 'none';
    }

    if (current_mode == mode || first) {
        if ($('body.mobile').length>0)
            $('
').class('section').prop('id', 'column-1').appendTo('#under-page');
            for(chat in chats) {
                $('
').addClass('card chat').prop('chat-'+chat.url).appendTo('#column-1');
                $('').addClass('title').prop('href','/'+chat.url).text(chat.url+(chat.unread ? ' '+chat.url : '')).append('#column-1');
                if (chat.type == 'group') {
                    $('
').addClass('topic').text(chat.topic).appendTo('#column-1');
                }
            }
        } else if ($('body.nobile').length>0) {
            $('
').class('section').prop('id', 'column-1').appendTo('#under-page');
            $('
').class('section').prop('id', 'column-2').appendTo('#under-page');
            for (var i=0; i<chats.length; i+=2) {
                chat = chats[i];
                $('
').addClass('card chat').prop('chat-'+chat.url).appendTo('#column-1');
                $('').addClass('title').prop('href','/'+chat.url).text(chat.url+(chat.unread ? ' '+chat.url : '')).append('#column-1');
                if (chat.type == 'group') {
                    $('
').addClass('topic').text(chat.topic).appendTo('#column-1');
                }
            }
            for (var i=1; i<chats.length; i+=2) {
                chat = chats[i];
                $('
').addClass('card chat').prop('chat-'+chat.url).appendTo('#column-2');
                $('').addClass('title').prop('href','/'+chat.url).text(chat.url+(chat.unread ? ' '+chat.url : '')).append('#column-2');
                if (chat.type == 'group') {
                    $('
').addClass('topic').text(chat.topic).appendTo('#column-2');
                }
            }
        } else {
            $('
').class('section').prop('id', 'column-1').appendTo('#under-page');
            $('
').class('section').prop('id', 'column-2').appendTo('#under-page');
            $('
').class('section').prop('id', 'column-3').appendTo('#under-page');
            for (var i=0; i<chats.length; i+=3) {
                chat = chats[i];
                $('
').addClass('card chat').prop('chat-'+chat.url).appendTo('#column-1');
                $('').addClass('title').prop('href','/'+chat.url).text(chat.url+(chat.unread ? ' '+chat.url : '')).append('#column-1');
                if (chat.type == 'group') {
                    $('
').addClass('topic').text(chat.topic).appendTo('#column-1');
                }
            }
            for (var i=1; i<chats.length; i+=3) {
                chat = chats[i];
                $('
').addClass('card chat').prop('chat-'+chat.url).appendTo('#column-2');
                $('').addClass('title').prop('href','/'+chat.url).text(chat.url+(chat.unread ? ' '+chat.url : '')).append('#column-2');
                if (chat.type == 'group') {
                    $('
').addClass('topic').text(chat.topic).appendTo('#column-2');
                }
            }
            for (var i=2; i<chats.length; i+=3) {
                chat = chats[i];
                $('
').addClass('card chat').prop('chat-'+chat.url).appendTo('#column-3');
                $('').addClass('title').prop('href','/'+chat.url).text(chat.url+(chat.unread ? ' '+chat.url : '')).append('#column-3');
                if (chat.type == 'group') {
                    $('
').addClass('topic').text(chat.topic).appendTo('#column-3');
                }
            }
        }
    }
    current_mode = mode;
}

$(function(){
    if ($('body').class()) {
        current_mode = $('body').class();
    } else {
        current_mode = 'none';
    }

    chatsUpdate(true);
});<commit_msg>chats.js<commit_after>var current_mode;

function chatsUpdate(first) {
    $('#under-page').empty();

    if ($('body').class()) {
        mode = $('body').class();
    } else {
        mode = 'none';
    }

    if (current_mode == mode || first) {
        if ($('body.mobile').length>0) {
            $('
').class('section').prop('id', 'column-1').appendTo('#under-page');
            for(chat in chats) {
                $('
').addClass('card chat').prop('chat-'+chat.url).appendTo('#column-1');
                $('').addClass('title').prop('href','/'+chat.url).text(chat.url+(chat.unread ? ' '+chat.url : '')).append('#column-1');
                if (chat.type == 'group') {
                    $('
').addClass('topic').text(chat.topic).appendTo('#column-1');
                }
            }
        } else if ($('body.nobile').length>0) {
            $('
').class('section').prop('id', 'column-1').appendTo('#under-page');
            $('
').class('section').prop('id', 'column-2').appendTo('#under-page');
            for (var i=0; i<chats.length; i+=2) {
                chat = chats[i];
                $('
').addClass('card chat').prop('chat-'+chat.url).appendTo('#column-1');
                $('').addClass('title').prop('href','/'+chat.url).text(chat.url+(chat.unread ? ' '+chat.url : '')).append('#column-1');
                if (chat.type == 'group') {
                    $('
').addClass('topic').text(chat.topic).appendTo('#column-1');
                }
            }
            for (var i=1; i<chats.length; i+=2) {
                chat = chats[i];
                $('
').addClass('card chat').prop('chat-'+chat.url).appendTo('#column-2');
                $('').addClass('title').prop('href','/'+chat.url).text(chat.url+(chat.unread ? ' '+chat.url : '')).append('#column-2');
                if (chat.type == 'group') {
                    $('
').addClass('topic').text(chat.topic).appendTo('#column-2');
                }
            }
        } else {
            $('
').class('section').prop('id', 'column-1').appendTo('#under-page');
            $('
').class('section').prop('id', 'column-2').appendTo('#under-page');
            $('
').class('section').prop('id', 'column-3').appendTo('#under-page');
            for (var i=0; i<chats.length; i+=3) {
                chat = chats[i];
                $('
').addClass('card chat').prop('chat-'+chat.url).appendTo('#column-1');
                $('').addClass('title').prop('href','/'+chat.url).text(chat.url+(chat.unread ? ' '+chat.url : '')).append('#column-1');
                if (chat.type == 'group') {
                    $('
').addClass('topic').text(chat.topic).appendTo('#column-1');
                }
            }
            for (var i=1; i<chats.length; i+=3) {
                chat = chats[i];
                $('
').addClass('card chat').prop('chat-'+chat.url).appendTo('#column-2');
                $('').addClass('title').prop('href','/'+chat.url).text(chat.url+(chat.unread ? ' '+chat.url : '')).append('#column-2');
                if (chat.type == 'group') {
                    $('
').addClass('topic').text(chat.topic).appendTo('#column-2');
                }
            }
            for (var i=2; i<chats.length; i+=3) {
                chat = chats[i];
                $('
').addClass('card chat').prop('chat-'+chat.url).appendTo('#column-3');
                $('').addClass('title').prop('href','/'+chat.url).text(chat.url+(chat.unread ? ' '+chat.url : '')).append('#column-3');
                if (chat.type == 'group') {
                    $('
').addClass('topic').text(chat.topic).appendTo('#column-3');
                }
            }
        }
    }
    current_mode = mode;
}

$(function(){
    if ($('body').class()) {
        current_mode = $('body').class();
    } else {
        current_mode = 'none';
    }

    chatsUpdate(true);
});<|endoftext|>


<commit_before>// Copyright (c) 2013, Web Notes Technologies Pvt. Ltd.
// License: GNU General Public License v3. See license.txt

wn.query_reports["Item-wise Purchase Register"] = {
	"filters": [
		{
			"fieldname":"from_date",
			"label": "From Date",
			"fieldtype": "Date",
			"default": wn.defaults.get_user_default("year_start_date"),
			"width": "80"
		},
		{
			"fieldname":"to_date",
			"label": "To Date",
			"fieldtype": "Date",
			"default": get_today()
		},
		{
			"fieldname": "item_code",
			"label": "Item",
			"fieldtype": "Link",
			"options": "Item",
		},
		{
			"fieldname":"account",
			"label": "Account",
			"fieldtype": "Link",
			"options": "Account",
			"get_query": function() {
				var company = wn.query_report.filters_by_name.company.get_value();
				return {
					"query": "accounts.utils.get_account_list",
					"filters": {
						"is_pl_account": "No",
						"debit_or_credit": "Credit",
						"company": company,
						"master_type": "Supplier"
					}
				}
			}
		},
		{
			"fieldname":"company",
			"label": "Company",
			"fieldtype": "Link",
			"options": "Company",
			"default": wn.defaults.get_default("company")
		}
	]
}<commit_msg>Fix translate item_wise_purchase_register.js<commit_after>// Copyright (c) 2013, Web Notes Technologies Pvt. Ltd.
// License: GNU General Public License v3. See license.txt

wn.query_reports["Item-wise Purchase Register"] = {
	"filters": [
		{
			"fieldname":"from_date",
			"label": wn._("From Date"),
			"fieldtype": "Date",
			"default": wn.defaults.get_user_default("year_start_date"),
			"width": "80"
		},
		{
			"fieldname":"to_date",
			"label": wn._("To Date"),
			"fieldtype": "Date",
			"default": get_today()
		},
		{
			"fieldname": "item_code",
			"label": wn._("Item"),
			"fieldtype": "Link",
			"options": "Item",
		},
		{
			"fieldname":"account",
			"label": wn._("Account"),
			"fieldtype": "Link",
			"options": "Account",
			"get_query": function() {
				var company = wn.query_report.filters_by_name.company.get_value();
				return {
					"query": "accounts.utils.get_account_list",
					"filters": {
						"is_pl_account": "No",
						"debit_or_credit": "Credit",
						"company": company,
						"master_type": "Supplier"
					}
				}
			}
		},
		{
			"fieldname":"company",
			"label": wn._("Company"),
			"fieldtype": "Link",
			"options": "Company",
			"default": wn.defaults.get_default("company")
		}
	]
}<|endoftext|>


<commit_before>var EXPORTED_SYMBOLS = ["sendlater3DateParse", "sendlater3DateToSugarDate", "sendlater3SugarLocale"];

// Using mozIJSSubScriptLoader instead of Cu.import because I want to
// preserve sugar.min.js unmodified from the official
// distribution, and it doesn't define EXPORTED_SYMBOLS, which is
// required by CU.import.
var loader = Components.classes["@mozilla.org/moz/jssubscript-loader;1"]
                       .getService(Components.interfaces.mozIJSSubScriptLoader);
loader.loadSubScript("resource://sendlater3/sugar.min.js");

var didLocale = false;
var locale;

function getLocale() {
    if (! didLocale) {
	var localeService = Components.classes["@mozilla.org/intl/nslocaleservice;1"]
            .getService(Components.interfaces.nsILocaleService);
	var localeObj = localeService.getApplicationLocale();
	locale = localeObj.getCategory("NSILOCALE_TIME");
	// Sugar may not recognize the locale. It throws an error when
	// an unrecognized locale is passed in and the locale is
	// needed.

	try {
	    Date.create().format(null, locale);
	}
	catch (ex) {
	    locale = null;
	}
	didLocale = true;
    }
    return locale;
}

function sendlater3DateParse(date) {
    var locale = getLocale();
    var obj = Date.future(date, locale);
    if (! (obj.isValid() || locale.substr(0, 2) == "en")) {
	// Fall back on English date rules
	obj = Date.future(date);
    }
    return obj;
}

function sendlater3DateToSugarDate(date) {
    try {
	return Date.create(date);
    }
    catch (e) {
	var d = new Date();
	d.setTime(date.getTime());
	return d;
    }
}

function sendlater3SugarLocale() {
    return getLocale();
}
<commit_msg>nsILocaleService -> mozILocaleService<commit_after>var EXPORTED_SYMBOLS = ["sendlater3DateParse", "sendlater3DateToSugarDate", "sendlater3SugarLocale"];

// Using mozIJSSubScriptLoader instead of Cu.import because I want to
// preserve sugar.min.js unmodified from the official
// distribution, and it doesn't define EXPORTED_SYMBOLS, which is
// required by CU.import.
var loader = Components.classes["@mozilla.org/moz/jssubscript-loader;1"]
                       .getService(Components.interfaces.mozIJSSubScriptLoader);
loader.loadSubScript("resource://sendlater3/sugar.min.js");

var didLocale = false;
var locale;

function getLocale() {
    if (! didLocale) {
	didLocale = true;
        var locales;
        try {
	    var localeService = Components.classes[
                "@mozilla.org/intl/nslocaleservice;1"]
                .getService(Components.interfaces.nsILocaleService);
	    var localeObj = localeService.getApplicationLocale();
	    locales = [localeObj.getCategory("NSILOCALE_TIME")];
        }
        catch (ex) {
            try {
                locales = Components.classes[
                    "@mozilla.org/intl/localeservice;1"]
                    .getService(Components.interfaces.mozILocaleService)
                    .getRegionalPrefsLocales();
            }
            catch (ex) {
                locales = [];
            }
        }
        for (var l of locales) {
	    // Sugar may not recognize the locale. It throws an error when
	    // an unrecognized locale is passed in and the locale is
	    // needed.
	    try {
	        Date.create().format(null, l);
                locale = l;
                return locale;
	    }
	    catch (ex) {}
        }
    }
    return locale;
}

function sendlater3DateParse(date) {
    var locale = getLocale();
    var obj = Date.future(date, locale);
    if (! (obj.isValid() || locale.substr(0, 2) == "en")) {
	// Fall back on English date rules
	obj = Date.future(date);
    }
    return obj;
}

function sendlater3DateToSugarDate(date) {
    try {
	return Date.create(date);
    }
    catch (e) {
	var d = new Date();
	d.setTime(date.getTime());
	return d;
    }
}

function sendlater3SugarLocale() {
    return getLocale();
}
<|endoftext|>


<commit_before>// dependencies
var CRUD = require ("./crud")
  , ObjectId = require ("mongodb").ObjectID
  , templates = [
        {
            name: "map"
          , id: "534ffc85f607d65614ad00e4"
        }
      , {
            name: "marker"
          , id:   "534ffe16f607d65614ad00e5"
        }
      , {
            name: "infowin"
          , id: "534ffe16f607d65614ad00e6"
        }
      , {
            name: "icon"
          , id: "534fffd7f607d65614ad00f7"
        }
    ]
  ;

/*
 *  Function generator for APIS
 *
 * */
function generateApiSet (templateId) {
    return {
        create: function (options, callback) {
            CRUD.create ({
                _tp: [ ObjectId (templateId) ]
              , templateId: templateId
              , data: options.data
              , options: options.options
              , callback: callback
            });
        }
      , read: function (options, callback) {
            CRUD.read ({
                templateId: templateId
              , query: options.query
              , options: options.options
              , callback: callback
            });
        }
      , update: function (options, callback) {
            CRUD.update ({
                templateId: templateId
              , query: options.query
              , data: data
              , options: options.options
              , callback: callback
            });
        }
      , delete: function (options, callback) {
            CRUD.delete ({
                templateId: templateId
              , query: options.query
              , options: options.options
              , callback: callback
            });
        }
    };
};

// this object will be exported
var Api = {};

// each template
for (var i = 0; i < templates.length; ++i) {

    // get the current template
    var cTemplate = templates[i];

    // generate methods for this template
    Api[cTemplate.name] = generateApiSet (cTemplate.id);
}

// exports the module
module.exports = Api;
<commit_msg>Attach _tp field correctly<commit_after>// dependencies
var CRUD = require ("./crud")
  , ObjectId = require ("mongodb").ObjectID
  , templates = [
        {
            name: "map"
          , id: "534ffc85f607d65614ad00e4"
        }
      , {
            name: "marker"
          , id:   "534ffe16f607d65614ad00e5"
        }
      , {
            name: "infowin"
          , id: "534ffe16f607d65614ad00e6"
        }
      , {
            name: "icon"
          , id: "534fffd7f607d65614ad00f7"
        }
    ]
  ;

/*
 *  Function generator for APIS
 *
 * */
function generateApiSet (templateId) {
    return {
        create: function (options, callback) {

            // force data to be an object and attach _tp field
            options.data = Object (options.data);
            options.data._tp = [ ObjectId (templateId) ];

            CRUD.create ({
                templateId: templateId
              , data: options.data
              , options: options.options
              , callback: callback
            });
        }
      , read: function (options, callback) {
            CRUD.read ({
                templateId: templateId
              , query: options.query
              , options: options.options
              , callback: callback
            });
        }
      , update: function (options, callback) {
            CRUD.update ({
                templateId: templateId
              , query: options.query
              , data: data
              , options: options.options
              , callback: callback
            });
        }
      , delete: function (options, callback) {
            CRUD.delete ({
                templateId: templateId
              , query: options.query
              , options: options.options
              , callback: callback
            });
        }
    };
};

// this object will be exported
var Api = {};

// each template
for (var i = 0; i < templates.length; ++i) {

    // get the current template
    var cTemplate = templates[i];

    // generate methods for this template
    Api[cTemplate.name] = generateApiSet (cTemplate.id);
}

// exports the module
module.exports = Api;
<|endoftext|>


<commit_before>/**

   SAMPLE APP

   This app will do nothing but to output "Hello world" into the stream until it reaches the max count.

**/

var util            = require('util');
var EventEmitter    = require('events').EventEmitter;

var Echo = function(c)
{
   var self = this;

   self.config = c;

   self.echoed = 0;

   self.init = function()
   {
      self.id     = self.config.id;

      self.max    = Math.floor((Math.random()*10)+1);;

      self.process = false;
      self.status  = 'ready';

      self.emit('status','ready');
   }

   self.run = function()
   {
      if(self.status == 'running')
      {
         // already running
         self.emit('status','already running');
      }
      else
      {
         self.running = setInterval(self.echo_console, 1000);

         self.status = 'running';

         self.emit('status','running');
      }
   }

   self.echo_console = function()
   {
      if(self.status == 'running')
      {
         self.echoed++

         // console.log(self.echoed, 'Hello world');

         self.emit('status','Sent ' + self.echoed + " of " + self.max);

         // is this the last one?
         if(self.echoed == self.max)
         {
             self.done();
         }
      }
      else
      {
         self.emit('status','Not running');
      }
   }

   self.done = function()
   {
      clearInterval(self.running);
      self.emit('status','Job completed.');

      process.exit(0);
   }

   self.stop = function()
   {
      clearInterval(self.running);

      self.status  = 'stopped';

      self.emit('status','stopped');
   }

   self.resume = function()
   {
      self.run();
   }
}

util.inherits(Echo, EventEmitter);

module.exports = Echo;<commit_msg>FIXED tests<commit_after>/**

   SAMPLE APP

   This app will do nothing but to output "Hello world" into the stream until it reaches the max count.

**/

var util            = require('util');
var EventEmitter    = require('events').EventEmitter;

var Echo = function(c)
{
   var self = this;

   self.config = c;

   self.echoed = 0;

   self.init = function()
   {
      self.id     = self.config.id;

      // use the ID as the max count
      self.max    = self.id;

      self.process = false;
      self.status  = 'ready';

      self.emit('status','ready');
   }

   self.run = function()
   {
      if(self.status == 'running')
      {
         // already running
         self.emit('status','already running');
      }
      else
      {
         self.running = setInterval(self.echo_console, 1000);

         self.status = 'running';

         self.emit('status','running');
      }
   }

   self.echo_console = function()
   {
      if(self.status == 'running')
      {
         self.echoed++

         // console.log(self.echoed, 'Hello world');

         self.emit('status','Sent ' + self.echoed + " of " + self.max);

         // is this the last one?
         if(self.echoed == self.max)
         {
             self.done();
         }
      }
      else
      {
         self.emit('status','Not running');
      }
   }

   self.done = function()
   {
      clearInterval(self.running);
      self.emit('status','Job completed.');

      process.exit(0);
   }

   self.stop = function()
   {
      clearInterval(self.running);

      self.status  = 'stopped';

      self.emit('status','stopped');
   }

   self.resume = function()
   {
      self.run();
   }
}

util.inherits(Echo, EventEmitter);

module.exports = Echo;<|endoftext|>