<commit_before>/**
 * Powered by Systango
 * http://www.systango.com
 */

'use strict';

import React from 'react';
import { Platform, Alert } from 'react-native'
import stacktraceParser from 'stacktrace-parser';
var SQLiteManager = require('./SQLiteManager').default
var Configuration = require('./Configuration')
var _keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="
var Buffer = require('buffer').Buffer;
var Database =require('../../../js/Database.js');
var SendReportOnRemote = require('./SendReportOnRemote').default

var RNSystangoBugReporter = require('react-native').NativeModules.RNCrashReporter;
var sqlMngrObj;

// import _ from 'underscore';
/*
  * The instance of our singleton
  * Setting up block level variable to store class state
  * , set's to null by default.
*/
let instance = null;
var defaultHandler;

const parseErrorStack = (error)=>{
  if (!error || !error.stack) {
    return [];
  }
  return Array.isArray(error.stack) ? error.stack :
    stacktraceParser.parse(error.stack);
}

export default class CrashReporter {

  /**
   * ## Constructor
   */
  constructor() {

    //*> Creating singleton
    if(!instance){
      if (Configuration.getIsReportCrash()) {

      //Initializing singleton instance
      instance = this;

      this.initializeDBIncetance();

        if (ErrorUtils._globalHandler) {
            instance.defaultHandler = ErrorUtils.getGlobalHandler && ErrorUtils.getGlobalHandler() || ErrorUtils._globalHandler;
            ErrorUtils.setGlobalHandler(instance.wrapGlobalHandler);  //feed errors directly to our wrapGlobalHandler function
        }
    }
  }
    return instance;
  }

  initializeDBIncetance() {
    instance.sqlMngrObj = new SQLiteManager()
  }

  async wrapGlobalHandler(error, isFatal){

      const stack = parseErrorStack(error);
      instance.sqlMngrObj.addCrashReport(
        {
          errorMsg: error.message,
          errorStack: stack.length > 0 ? JSON.stringify(stack[0]) : ''
        }
      )

      //*> Finish activity
      setTimeout (() => {
        instance.defaultHandler(error, isFatal);  //after you're finished, call the defaultHandler so that react-native also gets the error
        if (Platform.OS == 'android') {
          RNSystangoBugReporter.reload()
        }
      }, 2000);
  }

  /*
  * ReportCrash Manually
  */

  async reportHandledCrashes(superClassName, _methodName, actionON, errorMessage, stackTraceMessage){

    instance.sqlMngrObj.addUserStep(
    {
      className: superClassName,
      methodName: _methodName,
      actionOn: actionON
    });

    instance.sqlMngrObj.addCrashReport(
    {
      errorMsg: errorMessage,
      errorStack: stackTraceMessage
    });

    instance.getUserID()

  }

  getUserID() {

  var db = Database.getDBInstance();

    //Fetch User Details from DB
    var selectUserSql = "SELECT * from User";
    db.transaction((tx) => {

      tx.executeSql(selectUserSql, [], (tx, results) =>
      {

        var len = results.rows.length;
        var user_id = null;
        for (var i = 0; i < len; i++) {
          var row = results.rows.item(i);
          user_id = row.user_id;
        }

        //*> Report crash
        instance.sendCrashReport(user_id);

      }, (error) =>
      {
        instance.sendCrashReport(null);
      });
    });
  }

  sendCrashReport(user_id) {
    //*>Check if have any error
    //*> Get error data

    var objSendReport = new SendReportOnRemote()
    instance.sqlMngrObj.getDeviceInfo((crashReport) => {

      var m = ''+crashReport.length
      if (crashReport.length > 0) {

        var data = crashReport[0];
        objSendReport.sendReport(data, user_id, instance.successCB, instance.errorCB)

      } else {
        //*> Delete all crash report
        instance.sqlMngrObj.deleteAllReportData()
      }
    })
  }

  successCB(msg) {
        //*> Delete all crash report
         instance.sqlMngrObj.deleteAllReportData()
  }

  errorCB(msg){
    console.log("###### error=", errorMsg);
  }

};
<commit_msg>Fix: Removed unwanted imports<commit_after>/**
 * Powered by Systango
 * http://www.systango.com
 */

'use strict';

import React from 'react';
import { Platform, Alert } from 'react-native'
import stacktraceParser from 'stacktrace-parser';
var SQLiteManager = require('./SQLiteManager').default
var Configuration = require('./Configuration')
var _keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="
var Database =require('../../../js/Database.js');
var SendReportOnRemote = require('./SendReportOnRemote').default

var RNSystangoBugReporter = require('react-native').NativeModules.RNCrashReporter;
var sqlMngrObj;

// import _ from 'underscore';
/*
  * The instance of our singleton
  * Setting up block level variable to store class state
  * , set's to null by default.
*/
let instance = null;
var defaultHandler;

const parseErrorStack = (error)=>{
  if (!error || !error.stack) {
    return [];
  }
  return Array.isArray(error.stack) ? error.stack :
    stacktraceParser.parse(error.stack);
}

export default class CrashReporter {

  /**
   * ## Constructor
   */
  constructor() {

    //*> Creating singleton
    if(!instance){
      if (Configuration.getIsReportCrash()) {

      //Initializing singleton instance
      instance = this;

      this.initializeDBIncetance();

        if (ErrorUtils._globalHandler) {
            instance.defaultHandler = ErrorUtils.getGlobalHandler && ErrorUtils.getGlobalHandler() || ErrorUtils._globalHandler;
            ErrorUtils.setGlobalHandler(instance.wrapGlobalHandler);  //feed errors directly to our wrapGlobalHandler function
        }
    }
  }
    return instance;
  }

  initializeDBIncetance() {
    instance.sqlMngrObj = new SQLiteManager()
  }

  async wrapGlobalHandler(error, isFatal){

      const stack = parseErrorStack(error);
      instance.sqlMngrObj.addCrashReport(
        {
          errorMsg: error.message,
          errorStack: stack.length > 0 ? JSON.stringify(stack[0]) : ''
        }
      )

      //*> Finish activity
      setTimeout (() => {
        instance.defaultHandler(error, isFatal);  //after you're finished, call the defaultHandler so that react-native also gets the error
        if (Platform.OS == 'android') {
          RNSystangoBugReporter.reload()
        }
      }, 2000);
  }

  /*
  * ReportCrash Manually
  */

  async reportHandledCrashes(superClassName, _methodName, actionON, errorMessage, stackTraceMessage){

    instance.sqlMngrObj.addUserStep(
    {
      className: superClassName,
      methodName: _methodName,
      actionOn: actionON
    });

    instance.sqlMngrObj.addCrashReport(
    {
      errorMsg: errorMessage,
      errorStack: stackTraceMessage
    });

    instance.getUserID()

  }

  getUserID() {

  var db = Database.getDBInstance();

    //Fetch User Details from DB
    var selectUserSql = "SELECT * from User";
    db.transaction((tx) => {

      tx.executeSql(selectUserSql, [], (tx, results) =>
      {

        var len = results.rows.length;
        var user_id = null;
        for (var i = 0; i < len; i++) {
          var row = results.rows.item(i);
          user_id = row.user_id;
        }

        //*> Report crash
        instance.sendCrashReport(user_id);

      }, (error) =>
      {
        instance.sendCrashReport(null);
      });
    });
  }

  sendCrashReport(user_id) {
    //*>Check if have any error
    //*> Get error data

    var objSendReport = new SendReportOnRemote()
    instance.sqlMngrObj.getDeviceInfo((crashReport) => {

      var m = ''+crashReport.length
      if (crashReport.length > 0) {

        var data = crashReport[0];
        objSendReport.sendReport(data, user_id, instance.successCB, instance.errorCB)

      } else {
        //*> Delete all crash report
        instance.sqlMngrObj.deleteAllReportData()
      }
    })
  }

  successCB(msg) {
        //*> Delete all crash report
         instance.sqlMngrObj.deleteAllReportData()
  }

  errorCB(msg){
    console.log("###### error=", errorMsg);
  }

};
<|endoftext|>


<commit_before><commit_msg>Update ogario.v4.js<commit_after><|endoftext|>


<commit_before>;(function($, doc, win) {
  "use strict";

  console.time('umi.js init');
  /* CONFIG */

  function Configuration(){
  	this.config = {
	  	 version : "0.1",
	  	jsprefix : ".json",
	    protocol : {
		  	  upage : "/upage/",
		  	  udata : "/udata/",
		  	uobject : "/uobject/"
	    }
	  };
  }

  Configuration.prototype.setValue = function(name,val) {
  	try {
	  this.config[name] = val;
  	} catch(err) {
	  	throw err;
  	}
 };

  var regedit = new Configuration();

  /* construct */
  function UMI(params){

  	for (var obj in params) {
  		regedit.setValue(obj,params[obj]);
  	}
  	/* start */
  	this.init();
  }
  /*

  MODULE

  name - Module name
  config - configs object
  makeCall(method,argums) - function to call api methods in this module;
  			method - method of the module
  			argums - Array of params

  */

  function Module(moduleName,version){
	  	 this.name = moduleName;
	   this.config = regedit.config;
	  this.version = version;
	 this.makeCall = function(method,argums,success,error){
		  var response = (argums && argums.length) ? UMI.prototype.jsonDecode(this.config.protocol.udata + this.name + "/"+ method + "/" + argums.join("/") + this.config.jsprefix) : UMI.prototype.jsonDecode(this.config.protocol.udata + this.name + "/"+ method + this.config.jsprefix);
		  try {
			  var sf = eval(success);
			  sf(response,argums);
			  return response;
		  } catch(e) {
			   var ef = eval(error);
			   ef(e);
		  }
	  }
  }
  /*

  !SYSTEM FUNCTIONS

  */

  /* INIT */

  UMI.prototype.init = function(){
	//getcurrentpage
  	this.page = this.jsonDecode(regedit.config.protocol.upage+window.location.pathname+regedit.config.jsprefix).page;
  	console.timeEnd('umi.js init');
  };

  /* HTTPRequest */

  UMI.prototype.http = function(url,type){
  	type = type || "GET";
    var xmlHttp = null;
    xmlHttp = new XMLHttpRequest();
    xmlHttp.open( type, url, false );
    xmlHttp.send( null );
    return xmlHttp.responseText;
  };

  /* JSON decode */

  UMI.prototype.jsonDecode = function(url,type){
	 var content = this.http(url,type);
	 return JSON.parse(content);
  };

  /* CurrentVersion of script */
  UMI.prototype.getVersion = function() {
	  console.log(regedit.config.version);
	  return true;
  };

  /*
  !MODULES
  */
  	   UMI.prototype.banners = new Module("banners","0.1");
  	   UMI.prototype.blogs20 = new Module("blogs20","0.1");
	   UMI.prototype.catalog = new Module("catalog","0.1");
	  UMI.prototype.comments = new Module("comments","0.1");
	   UMI.prototype.content = new Module("content","0.1");
	   	  UMI.prototype.core = new Module("core","0.1");
	  	  UMI.prototype.data = new Module("data","0.1");
	   UMI.prototype.emarket = new Module("emarket","0.1");
	       UMI.prototype.faq = new Module("faq","0.1");
         UMI.prototype.forum = new Module("forum","0.1");
		  UMI.prototype.menu = new Module("menu","0.1");
		  UMI.prototype.news = new Module("news","0.1");
	UMI.prototype.photoalbum = new Module("photoalbum","0.1");
		UMI.prototype.search = new Module("search","0.1");
		UMI.prototype.system = new Module("system","0.1");
		 UMI.prototype.users = new Module("users","0.1");
	  UMI.prototype.webforms = new Module("webforms","0.1");
  /*
  !EXPAND MODULES
  */

  UMI.prototype.data.getProperty = function (element_id,prop_name) {
	  var response = UMI.prototype.jsonDecode(regedit.configig.protocol.upage + element_id + "." + prop_name + regedit.configig.jsprefix);
	  return response;
  };

  UMI.prototype.data.getPage = function (page_id) {
	  var response = UMI.prototype.jsonDecode(regedit.config.protocol.upage+page_id+regedit.config.jsprefix).page;
	  return response;
  };

  /* onload */
  $(window).load(function(){
	  window.umi = new UMI({version:"0.2"});
  });
})(jQuery,document, window);<commit_msg>succes/error small<commit_after>;(function($, doc, win) {
  "use strict";

  console.time('umi.js init');
  /* CONFIG */

  function Configuration(){
  	this.config = {
	  	 version : "0.1",
	  	jsprefix : ".json",
	    protocol : {
		  	  upage : "/upage/",
		  	  udata : "/udata/",
		  	uobject : "/uobject/"
	    }
	  };
  }

  Configuration.prototype.setValue = function(name,val) {
  	try {
	  this.config[name] = val;
  	} catch(err) {
	  	throw err;
  	}
 };

  var regedit = new Configuration();

  /* construct */
  function UMI(params){

  	for (var obj in params) {
  		regedit.setValue(obj,params[obj]);
  	}
  	/* start */
  	this.init();
  }
  /*

  MODULE

  name - Module name
  config - configs object
  makeCall(method,argums) - function to call api methods in this module;
  			method - method of the module
  			argums - Array of params

  */

  function Module(moduleName,version){
	  	 this.name = moduleName;
	   this.config = regedit.config;
	  this.version = version;
	 this.makeCall = function(method,argums,success,error){
		  var response = (argums && argums.length) ? UMI.prototype.jsonDecode(this.config.protocol.udata + this.name + "/"+ method + "/" + argums.join("/") + this.config.jsprefix) : UMI.prototype.jsonDecode(this.config.protocol.udata + this.name + "/"+ method + this.config.jsprefix);
		  try {
			  success(response,argums);
			  return response;
		  } catch(e) {
			  error(e);
		  }
	  }
  }
  /*

  !SYSTEM FUNCTIONS

  */

  /* INIT */

  UMI.prototype.init = function(){
	//getcurrentpage
  	this.page = this.jsonDecode(regedit.config.protocol.upage+window.location.pathname+regedit.config.jsprefix).page;
  	console.timeEnd('umi.js init');
  };

  /* HTTPRequest */

  UMI.prototype.http = function(url,type){
  	type = type || "GET";
    var xmlHttp = null;
    xmlHttp = new XMLHttpRequest();
    xmlHttp.open( type, url, false );
    xmlHttp.send( null );
    return xmlHttp.responseText;
  };

  /* JSON decode */

  UMI.prototype.jsonDecode = function(url,type){
	 var content = this.http(url,type);
	 return JSON.parse(content);
  };

  /* CurrentVersion of script */
  UMI.prototype.getVersion = function() {
	  console.log(regedit.config.version);
	  return true;
  };

  /*
  !MODULES
  */
  	   UMI.prototype.banners = new Module("banners","0.1");
  	   UMI.prototype.blogs20 = new Module("blogs20","0.1");
	   UMI.prototype.catalog = new Module("catalog","0.1");
	  UMI.prototype.comments = new Module("comments","0.1");
	   UMI.prototype.content = new Module("content","0.1");
	   	  UMI.prototype.core = new Module("core","0.1");
	  	  UMI.prototype.data = new Module("data","0.1");
	   UMI.prototype.emarket = new Module("emarket","0.1");
	       UMI.prototype.faq = new Module("faq","0.1");
         UMI.prototype.forum = new Module("forum","0.1");
		  UMI.prototype.menu = new Module("menu","0.1");
		  UMI.prototype.news = new Module("news","0.1");
	UMI.prototype.photoalbum = new Module("photoalbum","0.1");
		UMI.prototype.search = new Module("search","0.1");
		UMI.prototype.system = new Module("system","0.1");
		 UMI.prototype.users = new Module("users","0.1");
	  UMI.prototype.webforms = new Module("webforms","0.1");
  /*
  !EXPAND MODULES
  */

  UMI.prototype.data.getProperty = function (element_id,prop_name) {
	  var response = UMI.prototype.jsonDecode(regedit.configig.protocol.upage + element_id + "." + prop_name + regedit.configig.jsprefix);
	  return response;
  };

  UMI.prototype.data.getPage = function (page_id) {
	  var response = UMI.prototype.jsonDecode(regedit.config.protocol.upage+page_id+regedit.config.jsprefix).page;
	  return response;
  };

  /* onload */
  $(window).load(function(){
	  window.umi = new UMI({version:"0.2"});
  });
})(jQuery,document, window);<|endoftext|>


<commit_before>const urlRegex = /^(https?:\/\/)?([\da-z\.-]+\.[a-z\.]{2,6})\/?/; // eslint-disable-line no-useless-escape

const getUrl = (str) => urlRegex.exec(str);
const regex = /^([^\/\s]+)\/?((?:\/?(?:\w+))*)\/([^\/]+?)(?:\.git)?$/; // eslint-disable-line no-useless-escape

/**
* Gitlab repository
* @typedef {Object} GitlabParsedRepository
* @property {String} repo full repository name, including owner & group
* @property {String} repository same as .repo
* @property {String} owner repo owner
* @property {String} group repo group, if any
* @property {String} name repo name
*/

/**
 * Gitlab repository parser
 * @param  {String} str input
 * @return {GitlabParsedRepository}     output
 */
module.exports = (str) => {
  if (!str || typeof str !== 'string' || !str.length) return {};

  const url = getUrl(str);
  const domain = url && url[2];
  const parsed = regex.exec(str.replace(urlRegex, ''));

  return parsed ? {
    host: domain,
    isGitlab: !domain || domain === 'gitlab.com',
    repo: parsed[0],
    repository: parsed[0],
    owner: parsed[1],
    group: parsed[2],
    name: parsed[3],
  } : {};
};
<commit_msg>fix(gitlab): rework parser url to allow urls starting with git@<commit_after>const urlRegex = /^(https?:\/\/|git@)?([\da-z\.-]+\.[a-z\.]{2,6})\/?/; // eslint-disable-line no-useless-escape

const getUrl = (str) => urlRegex.exec(str);
const regex = /^([^\/\s]+)\/?((?:\/?(?:\w+))*)\/([^\/]+?)(?:\.git)?$/; // eslint-disable-line no-useless-escape

/**
* Gitlab repository
* @typedef {Object} GitlabParsedRepository
* @property {String} repo full repository name, including owner & group
* @property {String} repository same as .repo
* @property {String} owner repo owner
* @property {String} group repo group, if any
* @property {String} name repo name
*/

/**
 * Gitlab repository parser
 * @param  {String} str input
 * @return {GitlabParsedRepository}     output
 */
module.exports = (str) => {
  if (!str || typeof str !== 'string' || !str.length) return {};

  const url = getUrl(str);
  const domain = url && url[2];
  const parsed = regex.exec(str.replace(urlRegex, ''));

  return parsed ? {
    host: domain,
    isGitlab: !domain || domain === 'gitlab.com',
    repo: parsed[0],
    repository: parsed[0],
    owner: parsed[1],
    group: parsed[2],
    name: parsed[3],
  } : {};
};
<|endoftext|>


<commit_before>

//==============================
// MultiKeyStore
//==============================

function MultiKeyStore (keyNames) {
	//MUST NOT be destructive of the passed in keyNames array!!
	var numKeyNames = keyNames.length;
	var i;
	var subKeyNames = [];

	this.keyName = keyNames[0];

	for (i = 1; i < numKeyNames; i += 1) {
		subKeyNames[i - 1] = keyNames[i];
	}

	this.subKeyNames = subKeyNames;
	this.height = subKeyNames.length;
	this.terminus = (this.height) ? false : true;

	this.entities = {};

//console.log('MultiKeyStore:', '('+this.keyName+')', 'constructor:', this);
}

MultiKeyStore.prototype.addItem = function (item) {
	var keyValue;
	var entity;

//console.log('MultiKeyStore:',  '('+this.keyName+')'  ,'addItem:', item);

	keyValue = item[this.keyName];
	entity = this.entities[keyValue];

//console.log('\t',  '('+this.keyName+')'  ,'keyValue:', keyValue);

	if (this.terminus) {
		if (!entity) {
			entity = item;
		} else {
			entity = [entity, item];
		}
		this.entities[keyValue] = entity;
	} else {
		if (!entity) {
//console.log('\t',  '('+this.keyName+')'  ,'creating new MultiKeyStore:', this.subKeyNames);
			entity = this.entities[keyValue] = new MultiKeyStore(this.subKeyNames);
		}
		entity.addItem(item);
	}

//console.log('\t', '('+this.keyName+')', 'end of additem...');
//console.log('\t\t', 'subKeyNames:', this.subKeyNames, 'entities:\n', this.entities, '\n');
};

MultiKeyStore.prototype.getItemForKeyValues = function (keyValues) {
	//MUST NOT be destructive of the passed in keyValues array!!

	var entity;
	var keyValue = keyValues[this.keyName];

//console.log('MultiKeyStore:getItemForKeyValues:', keyValues, 'keyValue:', keyValue);
//console.log('\t', 'keys of entities:', Object.keys(this.entities));

	entity = this.entities[keyValue];
//console.log('\t', 'entity:', entity);

	if (!entity) {
		return void 0;
	} else if (this.terminus) {
		return entity || void 0;
	} else {
		// entity is another MultiKeyStore instance
		return entity.getItemForKeyValues(keyValues);
	}
};

MultiKeyStore.prototype.getWalker = function () {
	return new MultiKeyStoreWalker(this);
};

MultiKeyStore.prototype.removeItemWithKeyValues = function (keyValues) {
	var keyValue;
	var entity;

console.log('MultiKeyStore:',  '('+this.keyName+')'  ,'removeItemWithKeyValues:', keyValues);

	keyValue = keyValues[this.keyName];
	entity = this.entities[keyValue];

	if (!entity) {
		return false;
	}

	if (this.terminus) {
		delete this.entities[keyValue];
		return true;
	} else {
		return entity.removeItemWithKeyValues(keyValues);
	}
};

//==============================
// MultiKeyStoreWalker
//==============================

function MultiKeyStoreWalker (multiKey) {
	this.multiKey = multiKey;
	this.keyName = multiKey.keyName;
	this.entities = multiKey.entities;
	this.subWalker = void 0;

	this.reset();
}

MultiKeyStoreWalker.prototype.getNextItem = function () {
	var entity = null;

	if (this.subWalker) {
		entity = this.subWalker.getNextItem();
		if (entity) {
			return entity;
		} else {
			// subWalker has reached its end, so free it, and continue walking this set of entities
			this.subWalker = void 0;
		}
	}

	// advance to next item
	this.index += 1;

	if (this.index < this.numEntities) {
		entityKey = this.entitiesKeys[this.index];
		entity = this.entities[entityKey];
	}

	if (entity instanceof MultiKeyStore) {
		// recursively walk this entity
		this.subWalker = new MultiKeyStoreWalker(entity);
		// start again, now that we have a subWalker
		return this.getNextItem();
	}

	return entity;
};

MultiKeyStoreWalker.prototype.reset = function () {
	this.index = -1;
	this.entitiesKeys = Object.keys(this.entities);
	this.numEntities = this.entitiesKeys.length;
};

//==============================
// exports
//==============================

exports = module.exports = MultiKeyStore;
<commit_msg>remove a console.log<commit_after>

//==============================
// MultiKeyStore
//==============================

function MultiKeyStore (keyNames) {
	//MUST NOT be destructive of the passed in keyNames array!!
	var numKeyNames = keyNames.length;
	var i;
	var subKeyNames = [];

	this.keyName = keyNames[0];

	for (i = 1; i < numKeyNames; i += 1) {
		subKeyNames[i - 1] = keyNames[i];
	}

	this.subKeyNames = subKeyNames;
	this.height = subKeyNames.length;
	this.terminus = (this.height) ? false : true;

	this.entities = {};

//console.log('MultiKeyStore:', '('+this.keyName+')', 'constructor:', this);
}

MultiKeyStore.prototype.addItem = function (item) {
	var keyValue;
	var entity;

//console.log('MultiKeyStore:',  '('+this.keyName+')'  ,'addItem:', item);

	keyValue = item[this.keyName];
	entity = this.entities[keyValue];

//console.log('\t',  '('+this.keyName+')'  ,'keyValue:', keyValue);

	if (this.terminus) {
		if (!entity) {
			entity = item;
		} else {
			entity = [entity, item];
		}
		this.entities[keyValue] = entity;
	} else {
		if (!entity) {
//console.log('\t',  '('+this.keyName+')'  ,'creating new MultiKeyStore:', this.subKeyNames);
			entity = this.entities[keyValue] = new MultiKeyStore(this.subKeyNames);
		}
		entity.addItem(item);
	}

//console.log('\t', '('+this.keyName+')', 'end of additem...');
//console.log('\t\t', 'subKeyNames:', this.subKeyNames, 'entities:\n', this.entities, '\n');
};

MultiKeyStore.prototype.getItemForKeyValues = function (keyValues) {
	//MUST NOT be destructive of the passed in keyValues array!!

	var entity;
	var keyValue = keyValues[this.keyName];

//console.log('MultiKeyStore:getItemForKeyValues:', keyValues, 'keyValue:', keyValue);
//console.log('\t', 'keys of entities:', Object.keys(this.entities));

	entity = this.entities[keyValue];
//console.log('\t', 'entity:', entity);

	if (!entity) {
		return void 0;
	} else if (this.terminus) {
		return entity || void 0;
	} else {
		// entity is another MultiKeyStore instance
		return entity.getItemForKeyValues(keyValues);
	}
};

MultiKeyStore.prototype.getWalker = function () {
	return new MultiKeyStoreWalker(this);
};

MultiKeyStore.prototype.removeItemWithKeyValues = function (keyValues) {
	var keyValue;
	var entity;

//console.log('MultiKeyStore:',  '('+this.keyName+')'  ,'removeItemWithKeyValues:', keyValues);

	keyValue = keyValues[this.keyName];
	entity = this.entities[keyValue];

	if (!entity) {
		return false;
	}

	if (this.terminus) {
		delete this.entities[keyValue];
		return true;
	} else {
		return entity.removeItemWithKeyValues(keyValues);
	}
};

//==============================
// MultiKeyStoreWalker
//==============================

function MultiKeyStoreWalker (multiKey) {
	this.multiKey = multiKey;
	this.keyName = multiKey.keyName;
	this.entities = multiKey.entities;
	this.subWalker = void 0;

	this.reset();
}

MultiKeyStoreWalker.prototype.getNextItem = function () {
	var entity = null;

	if (this.subWalker) {
		entity = this.subWalker.getNextItem();
		if (entity) {
			return entity;
		} else {
			// subWalker has reached its end, so free it, and continue walking this set of entities
			this.subWalker = void 0;
		}
	}

	// advance to next item
	this.index += 1;

	if (this.index < this.numEntities) {
		entityKey = this.entitiesKeys[this.index];
		entity = this.entities[entityKey];
	}

	if (entity instanceof MultiKeyStore) {
		// recursively walk this entity
		this.subWalker = new MultiKeyStoreWalker(entity);
		// start again, now that we have a subWalker
		return this.getNextItem();
	}

	return entity;
};

MultiKeyStoreWalker.prototype.reset = function () {
	this.index = -1;
	this.entitiesKeys = Object.keys(this.entities);
	this.numEntities = this.entitiesKeys.length;
};

//==============================
// exports
//==============================

exports = module.exports = MultiKeyStore;
<|endoftext|>


<commit_before>/*
 UI Operations Global Undo History Manager

 Usage:
   var OH = window['piro.sakura.ne.jp'].operationHistory;

   // window specific history
   OH.addEntry(
     'MyAddonFeature',
     { label  : 'Change tabbar position',
       onUndo : function() { ... },
       onRedo : function() { ... } },
     window
   );
   OH.undo('MyAddonFeature', window);
   OH.redo('MyAddonFeature', window);

   // global history (not associated to window)
   OH.addEntry(
     'MyAddonFeature',
     { ... }
   );
   OH.undo('MyAddonFeature');

   // anonymous, window specific
   OH.addEntry({ ... }, window);
   OH.undo(window);

   // anonymous, global
   OH.addEntry({ ... });
   OH.undo();

   // When you want to use "window" object in the global history,
   // you should use the ID string instead of the "window" object
   // to reduce memory leak. For example...
   OH.addEntry({
     id : OH.getWindowId(targetWindow),
     onUndo : function() {
       var w = OH.getWindowById(this.id);
       w.MyAddonService.undoSomething();
     },
     onRedo : ...
   });

   // enumerate history entries
   var history = OH.getHistory('MyAddonFeature', window); // options are same to undo/redo
   OH.entries.forEach(function(aEntry, aIndex) {
     var item = MyService.appendItem(aEntry.label);
     if (aIndex == history.index)
       item.setAttribute('checked', true);
   });

 lisence: The MIT License, Copyright (c) 2009-2010 SHIMODA "Piro" Hiroshi
   http://www.cozmixng.org/repos/piro/fx3-compatibility-lib/trunk/license.txt
 original:
   http://www.cozmixng.org/repos/piro/fx3-compatibility-lib/trunk/operationHistory.js
*/
(function() {
	const currentRevision = 3;

	if (!('piro.sakura.ne.jp' in window)) window['piro.sakura.ne.jp'] = {};

	var loadedRevision = 'operationHistory' in window['piro.sakura.ne.jp'] ?
			window['piro.sakura.ne.jp'].operationHistory.revision :
			0 ;
	if (loadedRevision && loadedRevision > currentRevision) {
		return;
	}

	var tables = {};
	if (loadedRevision) {
		tables = window['piro.sakura.ne.jp'].operationHistory._tables;
		window['piro.sakura.ne.jp'].destroy();
	}

	var Cc = Components.classes;
	var Ci = Components.interfaces;

	window['piro.sakura.ne.jp'].operationHistory = {
		revision : currentRevision,

		kMAX_ENTRIES : 999,
		kWINDOW_ID : 'ui-operation-global-history-window-id',

		addEntry : function()
		{
			if (this._doingUndo)
				return;

			var options = this._getOptionsFromArguments(arguments);

			var history = options.history;
			var entries = history.entries;

			entries = entries.slice(0, history.index+1);
			entries.push(options.data);
			entries = entries.slice(-this.kMAX_ENTRIES);

			history.entries = entries;
			history.index = entries.length-1;
		},

		getHistory : function()
		{
			var options = this._getOptionsFromArguments(arguments);
			return options.history;
		},

		undo : function()
		{
			var options = this._getOptionsFromArguments(arguments);
			var history = options.history;
			if (history.index < 0)
				return false;

			this._doingUndo = true;
			var processed = false;
			while (processed === false)
			{
				let error;
				let data = history.entries[history.index--];
				let f = this._getAvailableFunction(data.onUndo, data.onundo, data.undo);
				let done = false;
				try {
					if (f) {
						processed = f.call(data);
						done = true;
					}
					else {
						processed = true;
					}
				}
				catch(e) {
					error = e;
				}
				this._dispatchEvent('UIOperationGlobalHistoryUndo', options, data, done);
			}
			this._doingUndo = false;

			if (error) throw error;
			return true;
		},

		redo : function()
		{
			var options = this._getOptionsFromArguments(arguments);
			var history = options.history;
			if (history.index > history.entries.length-1)
				return false;

			this._doingUndo = true;
			var processed = false;
			while (processed === false)
			{
				let error;
				let f = this._getAvailableFunction(data.onRedo, data.onredo, data.redo);
				let done = false;
				try {
					if (f) {
						processed = f.call(data);
						done = true;
					}
					else {
						processed = true;
					}
				}
				catch(e) {
					error = e;
				}
				this._dispatchEvent('UIOperationGlobalHistoryRedo', options, data, done);
			}
			this._doingUndo = false;

			if (error) throw error;
			return true;
		},

		getWindowId : function(aWindow)
		{
			var windowId;
			try {
				windowId = aWindow.document.documentElement.getAttribute(this.kWINDOW_ID) ||
							this.SessionStore.getWindowValue(aWindow, this.kWINDOW_ID);
			}
			catch(e) {
			}
			if (!windowId) {
				windowId = 'window-'+Date.now()+parseInt(Math.random() * 65000);
				aWindow.document.documentElement.setAttribute(this.kWINDOW_ID, windowId);
				try {
					this.SessionStore.setWindowValue(aWindow, this.kWINDOW_ID, windowId);
				}
				catch(e) {
				}
			}
			return windowId;
		},

		getWindowById : function(aId)
		{
			var targets = this.WindowMediator.getZOrderDOMWindowEnumerator('*', true);
			while (targets.hasMoreElements())
			{
				let target = targets.getNext().QueryInterface(Ci.nsIDOMWindowInternal);
				if (aId == this.getWindowId(target))
					return target;
			}
			return null;
		},

		/* PRIVATE METHODS */

		_doingUndo : false,
		_tables : tables,

		initialized : false,

		init : function()
		{
			var targets = this.WindowMediator.getZOrderDOMWindowEnumerator('navigator:browser', true);
			while (targets.hasMoreElements())
			{
				let target = targets.getNext().QueryInterface(Ci.nsIDOMWindowInternal);
				if (
					'piro.sakura.ne.jp' in target &&
					'operationHistory' in target['piro.sakura.ne.jp'] &&
					target['piro.sakura.ne.jp'].operationHistory.initialized
					) {
					this._tables = target['piro.sakura.ne.jp'].operationHistory._tables;
					break;
				}
			}

			window.addEventListener('unload', this, false);

			this.initialized = true;
		},

		destroy : function()
		{
			window.removeEventListener('unload', this, false);
		},

		_dispatchEvent : function(aType, aOptions, aData, aDone)
		{
			var d = aOptions.window ? aOptions.window.document : document ;
			var event = d.createEvent('Events');
			event.initEvent(aType, true, false);
			event.name = aOptions.name;
			event.data = aData;
			event.done = aDone;
			d.dispatchEvent(event);
		},

		_getOptionsFromArguments : function(aArguments)
		{
			var w = null, name, data = null;
			Array.slice(aArguments).some(function(aArg) {
				if (aArg instanceof Ci.nsIDOMWindow)
					w = aArg;
				else if (typeof aArg == 'string')
					name = aArg;
				else if (aArg)
					data = aArg;

				return (w && name && data);
			});

			if (!name)
				name = w ? 'window' : 'global' ;

			var tableName = encodeURIComponent(name);

			var windowId = w ? this.getWindowId(window) : null ;
			if (windowId)
				tableName += '::'+windowId;

			if (!(tableName in this._tables)) {
				this._tables[tableName] = {
					entries  : [],
					index    : -1,
					windowId : windowId
				};
			}

			return {
				name     : name,
				window   : w,
				windowId : windowId,
				data     : data,
				history  : this._tables[tableName]
			};
		},

		_getAvailableFunction : function()
		{
			var functions = Array.slice(arguments);
			for (var i in functions)
			{
				let f = functions[i];
				if (f && typeof f == 'function')
					return f;
			}
			return null;
		},

		_deleteWindowTables : function()
		{
			var id = this.getWindowId(window);
			if (!id) return;

			var removedTables = [];
			for (let i in this._tables)
			{
				if (id == this._tables[i].windowId)
					removedTables.push(i);
			}
			removedTables.forEach(function(aName) {
				delete this._tables[aName];
			}, this);
		},

		get WindowMediator() {
			if (!this._WindowMediator) {
				this._WindowMediator = Cc['@mozilla.org/appshell/window-mediator;1'].getService(Ci.nsIWindowMediator);
			}
			return this._WindowMediator;
		},
		_WindowMediator : null,

		get SessionStore() {
			if (!this._SessionStore) {
				this._SessionStore = Cc['@mozilla.org/browser/sessionstore;1'].getService(Ci.nsISessionStore);
			}
			return this._SessionStore;
		},
		_SessionStore : null,

		handleEvent : function(aEvent)
		{
			switch (aEvent.type)
			{
				case 'unload':
					this._deleteWindowTables();
					this.destroy();
					return;
			}
		}

	};

	window['piro.sakura.ne.jp'].operationHistory.init();
})();
<commit_msg>doUndoableTask<commit_after>/*
 UI Operations Global Undo History Manager

 Usage:
   var OH = window['piro.sakura.ne.jp'].operationHistory;

   // window specific history
   OH.doUndoableTask(
     // the task which is undo-able (optional)
     function() {
       MyService.myProp = newValue;
     },

     // name of history (optional)
     'MyAddonFeature',

     // target window for the history (optional)
     window,

     // history item
     { label  : 'Change tabbar position',
       onUndo : function() { MyService.myProp = oldValue; },
       onRedo : function() { MyService.myProp = newValue; } }
   );
   OH.undo('MyAddonFeature', window);
   OH.redo('MyAddonFeature', window);

   // global history (not associated to window)
   OH.doUndoableTask(
     function() { ... }, // task
     'MyAddonFeature',
     { ... }
   );
   OH.undo('MyAddonFeature');

   // anonymous, window specific
   OH.doUndoableTask(function() { ... }, { ... }, window);
   OH.undo(window);

   // anonymous, global
   OH.doUndoableTask(function() { ... }, { ... });
   OH.undo();

   // When you want to use "window" object in the global history,
   // you should use the ID string instead of the "window" object
   // to reduce memory leak. For example...
   OH.doUndoableTask(
     function() {
       targetWindow.MyAddonService.myProp = newValue;
     },
     {
       id : OH.getWindowId(targetWindow),
       onUndo : function() {
         var w = OH.getWindowById(this.id);
         w.MyAddonService.myProp = oldValue;
       },
       onRedo : ...
     }
   );

   // enumerate history entries
   var history = OH.getHistory('MyAddonFeature', window); // options are same to undo/redo
   OH.entries.forEach(function(aEntry, aIndex) {
     var item = MyService.appendItem(aEntry.label);
     if (aIndex == history.index)
       item.setAttribute('checked', true);
   });

 lisence: The MIT License, Copyright (c) 2009-2010 SHIMODA "Piro" Hiroshi
   http://www.cozmixng.org/repos/piro/fx3-compatibility-lib/trunk/license.txt
 original:
   http://www.cozmixng.org/repos/piro/fx3-compatibility-lib/trunk/operationHistory.js
*/
(function() {
	const currentRevision = 4;

	if (!('piro.sakura.ne.jp' in window)) window['piro.sakura.ne.jp'] = {};

	var loadedRevision = 'operationHistory' in window['piro.sakura.ne.jp'] ?
			window['piro.sakura.ne.jp'].operationHistory.revision :
			0 ;
	if (loadedRevision && loadedRevision > currentRevision) {
		return;
	}

	var tables = {};
	if (loadedRevision) {
		tables = window['piro.sakura.ne.jp'].operationHistory._tables;
		window['piro.sakura.ne.jp'].destroy();
	}

	var Cc = Components.classes;
	var Ci = Components.interfaces;

	window['piro.sakura.ne.jp'].operationHistory = {
		revision : currentRevision,

		kMAX_ENTRIES : 999,
		kWINDOW_ID : 'ui-operation-global-history-window-id',

		doUndoableTask : function()
		{
			this.addEntry.apply(this, arguments);
		},

		addEntry : function()
		{
			var options = this._getOptionsFromArguments(arguments);
			var history = options.history;
			var entries = history.entries;
			var error;
			var wasInUndoableTask = history._inUndoableTask;

			if (!wasInUndoableTask)
				history._inUndoableTask = true;

			try {
				if (options.task)
					options.task.call(this);
			}
			catch(e) {
				error = e;
			}

			if (!wasInUndoableTask && !this._doingUndo) {
				entries = entries.slice(0, history.index+1);
				entries.push(options.data);
				entries = entries.slice(-this.kMAX_ENTRIES);

				history.entries = entries;
				history.index = entries.length-1;
			}

			if (!wasInUndoableTask)
				delete history._inUndoableTask;

			if (error)
				throw e;
		},

		getHistory : function()
		{
			var options = this._getOptionsFromArguments(arguments);
			return options.history;
		},

		undo : function()
		{
			var options = this._getOptionsFromArguments(arguments);
			var history = options.history;
			if (history.index < 0)
				return false;

			this._doingUndo = true;
			var processed = false;
			while (processed === false)
			{
				let error;
				let data = history.entries[history.index--];
				let f = this._getAvailableFunction(data.onUndo, data.onundo, data.undo);
				let done = false;
				try {
					if (f) {
						processed = f.call(data);
						done = true;
					}
					else {
						processed = true;
					}
				}
				catch(e) {
					error = e;
				}
				this._dispatchEvent('UIOperationGlobalHistoryUndo', options, data, done);
			}
			this._doingUndo = false;

			if (error) throw error;
			return true;
		},

		redo : function()
		{
			var options = this._getOptionsFromArguments(arguments);
			var history = options.history;
			if (history.index > history.entries.length-1)
				return false;

			this._doingUndo = true;
			var processed = false;
			while (processed === false)
			{
				let error;
				let f = this._getAvailableFunction(data.onRedo, data.onredo, data.redo);
				let done = false;
				try {
					if (f) {
						processed = f.call(data);
						done = true;
					}
					else {
						processed = true;
					}
				}
				catch(e) {
					error = e;
				}
				this._dispatchEvent('UIOperationGlobalHistoryRedo', options, data, done);
			}
			this._doingUndo = false;

			if (error) throw error;
			return true;
		},

		getWindowId : function(aWindow)
		{
			var windowId;
			try {
				windowId = aWindow.document.documentElement.getAttribute(this.kWINDOW_ID) ||
							this.SessionStore.getWindowValue(aWindow, this.kWINDOW_ID);
			}
			catch(e) {
			}
			if (!windowId) {
				windowId = 'window-'+Date.now()+parseInt(Math.random() * 65000);
				aWindow.document.documentElement.setAttribute(this.kWINDOW_ID, windowId);
				try {
					this.SessionStore.setWindowValue(aWindow, this.kWINDOW_ID, windowId);
				}
				catch(e) {
				}
			}
			return windowId;
		},

		getWindowById : function(aId)
		{
			var targets = this.WindowMediator.getZOrderDOMWindowEnumerator('*', true);
			while (targets.hasMoreElements())
			{
				let target = targets.getNext().QueryInterface(Ci.nsIDOMWindowInternal);
				if (aId == this.getWindowId(target))
					return target;
			}
			return null;
		},

		/* PRIVATE METHODS */

		_doingUndo : false,
		_tables : tables,

		initialized : false,

		init : function()
		{
			var targets = this.WindowMediator.getZOrderDOMWindowEnumerator('navigator:browser', true);
			while (targets.hasMoreElements())
			{
				let target = targets.getNext().QueryInterface(Ci.nsIDOMWindowInternal);
				if (
					'piro.sakura.ne.jp' in target &&
					'operationHistory' in target['piro.sakura.ne.jp'] &&
					target['piro.sakura.ne.jp'].operationHistory.initialized
					) {
					this._tables = target['piro.sakura.ne.jp'].operationHistory._tables;
					break;
				}
			}

			window.addEventListener('unload', this, false);

			this.initialized = true;
		},

		destroy : function()
		{
			window.removeEventListener('unload', this, false);
		},

		_dispatchEvent : function(aType, aOptions, aData, aDone)
		{
			var d = aOptions.window ? aOptions.window.document : document ;
			var event = d.createEvent('Events');
			event.initEvent(aType, true, false);
			event.name = aOptions.name;
			event.data = aData;
			event.done = aDone;
			d.dispatchEvent(event);
		},

		_getOptionsFromArguments : function(aArguments)
		{
			var w = null, name, data = null, task = null;
			Array.slice(aArguments).some(function(aArg) {
				if (aArg instanceof Ci.nsIDOMWindow)
					w = aArg;
				else if (typeof aArg == 'string')
					name = aArg;
				else if (typeof aArg == 'function')
					task = aArg;
				else if (aArg)
					data = aArg;

				return (w && name && data && task);
			});

			if (!name)
				name = w ? 'window' : 'global' ;

			var tableName = encodeURIComponent(name);

			var windowId = w ? this.getWindowId(window) : null ;
			if (windowId)
				tableName += '::'+windowId;

			if (!(tableName in this._tables)) {
				this._tables[tableName] = {
					entries  : [],
					index    : -1,
					windowId : windowId
				};
			}

			return {
				name     : name,
				window   : w,
				windowId : windowId,
				data     : data,
				history  : this._tables[tableName],
				task     : task
			};
		},

		_getAvailableFunction : function()
		{
			var functions = Array.slice(arguments);
			for (var i in functions)
			{
				let f = functions[i];
				if (f && typeof f == 'function')
					return f;
			}
			return null;
		},

		_deleteWindowTables : function()
		{
			var id = this.getWindowId(window);
			if (!id) return;

			var removedTables = [];
			for (let i in this._tables)
			{
				if (id == this._tables[i].windowId)
					removedTables.push(i);
			}
			removedTables.forEach(function(aName) {
				delete this._tables[aName];
			}, this);
		},

		get WindowMediator() {
			if (!this._WindowMediator) {
				this._WindowMediator = Cc['@mozilla.org/appshell/window-mediator;1'].getService(Ci.nsIWindowMediator);
			}
			return this._WindowMediator;
		},
		_WindowMediator : null,

		get SessionStore() {
			if (!this._SessionStore) {
				this._SessionStore = Cc['@mozilla.org/browser/sessionstore;1'].getService(Ci.nsISessionStore);
			}
			return this._SessionStore;
		},
		_SessionStore : null,

		handleEvent : function(aEvent)
		{
			switch (aEvent.type)
			{
				case 'unload':
					this._deleteWindowTables();
					this.destroy();
					return;
			}
		}

	};

	window['piro.sakura.ne.jp'].operationHistory.init();
})();
<|endoftext|>


<commit_before>"use strict";
var ConcatSource = require('webpack-sources/lib/ConcatSource');
var fs = require('fs');

class PrependPlugin {
    constructor(args) {
        if (typeof args !== 'object') {
            throw new TypeError('Argument "args" must be an object.');
        }

        this.filePath = args.hasOwnProperty('filePath') ? args.filePath : null;
    }

    apply(compiler) {
        const prependFile = (compilation, fileName) =>
            compilation.assets[fileName] = new ConcatSource(
                fs.readFileSync(this.filePath, 'utf8'),
                compilation.assets[fileName]
            );

        const wrapChunks = (compilation, chunks) =>
            chunks.forEach(chunk => {
                if (chunk.hasRuntime() && chunk.name) {
                    chunk.files.forEach(fileName => prependFile(compilation, fileName));
                }
            });

        if (this.filePath) {
            compiler.plugin('compilation', compilation =>
                compilation.plugin('optimize-chunk-assets', (chunks, done) => {
                    wrapChunks(compilation, chunks);
                    done();
                })
            );
        }
    }
}

module.exports = PrependPlugin;
<commit_msg>Check if extension is .js before prepending<commit_after>"use strict";
var ConcatSource = require('webpack-sources/lib/ConcatSource');
var fs = require('fs');

class PrependPlugin {
    constructor(args) {
        if (typeof args !== 'object') {
            throw new TypeError('Argument "args" must be an object.');
        }

        this.filePath = args.hasOwnProperty('filePath') ? args.filePath : null;
    }

    apply(compiler) {
        const prependFile = (compilation, fileName) =>
            compilation.assets[fileName] = new ConcatSource(
                fs.readFileSync(this.filePath, 'utf8'),
                compilation.assets[fileName]
            );

        const wrapChunks = (compilation, chunks) =>
            chunks.forEach(chunk => {
                if (chunk.hasRuntime() && chunk.name) {
                    chunk.files.forEach(fileName => {
                        if (fileName.match(/\.js$/)) {
                            prependFile(compilation, fileName)
                        }
                    });
                }
            });

        if (this.filePath) {
            compiler.plugin('compilation', compilation =>
                compilation.plugin('optimize-chunk-assets', (chunks, done) => {
                    wrapChunks(compilation, chunks);
                    done();
                })
            );
        }
    }
}

module.exports = PrependPlugin;
<|endoftext|>


<commit_before>var Future = Npm.require("fibers/future");

Ctl.Commands.push({
  name: "help",
  func: function (argv) {
    if (!argv._.length || argv.help)
      Ctl.usage();
    var cmd = argv._.splice(0,1)[0];
    argv.help = true;

    Ctl.findCommand(cmd).func(argv);
  }
});

var mergeObjects = function (obj1, obj2) {
  var result = _.clone(obj1);
  _.each(obj2, function (v, k) {
    // If both objects have an object at this key, then merge those objects.
    // Otherwise, choose obj2's value.
    if ((v instanceof Object) && (obj1[k] instanceof Object))
      result[k] = mergeObjects(v, obj1[k]);
    else
      result[k] = v;
  });
  return result;
};

var startFun = function (argv) {
  if (argv.help || argv._.length !== 0) {
    process.stderr.write(
      "Usage: ctl start\n" +
        "\n" +
        "Starts the app. For now, this just means that it runs the 'server'\n" +
        "program.\n"
    );
    process.exit(1);
  }
  Ctl.subscribeToAppJobs(Ctl.myAppName());
  var jobs = Ctl.jobsCollection();
  var thisJob = jobs.findOne(Ctl.myJobId());
  Ctl.updateProxyActiveTags(['', thisJob.star]);
  if (Ctl.hasProgram("console")) {
    console.log("starting console for app", Ctl.myAppName());
    Ctl.startServerlikeProgramIfNotPresent("console", ["admin"], true);
  }
  console.log("starting server for app", Ctl.myAppName());
  Ctl.startServerlikeProgramIfNotPresent("server", ["runner"]);
};

Ctl.Commands.push({
  name: "start",
  help: "Start this app",
  func: startFun
});

Ctl.Commands.push({
  name: "endUpdate",
  help: "Start this app to end an update",
  func: startFun
});

var stopFun =  function (argv) {
  if (argv.help || argv._.length !== 0) {
    process.stderr.write(
      "Usage: ctl stop\n" +
        "\n" +
        "Stops the app. For now, this just means that it kills all jobs\n" +
        "other than itself.\n"
    );
    process.exit(1);
  }

  // Get all jobs (other than this job: don't commit suicide!) that are not
  // already killed.
  var jobs = Ctl.getJobsByApp(
    Ctl.myAppName(), {_id: {$ne: Ctl.myJobId()}, done: false});
  jobs.forEach(function (job) {
    // Don't commit suicide.
    if (job._id === Ctl.myJobId())
      return;
    // It's dead, Jim.
    if (job.done)
      return;
    Ctl.kill(job.program, job._id);
  });
  console.log("Server stopped.");
};

Ctl.Commands.push({
  name: "stop",
  help: "Stop this app",
  func: stopFun
});

var waitForDone = function (jobCollection, jobId) {
  var fut = new Future();
  var found = false;
  try {
    var observation = jobCollection.find(jobId).observe({
      added: function (doc) {
        found = true;
        if (doc.done)
          fut['return']();
      },
      changed: function (doc) {
        if (doc.done)
          fut['return']();
      },
      removed: function (doc) {
        fut['return']();
      }
    });
    // if the document doesn't exist at all, it's certainly done.
    if (!found)
      fut['return']();
    fut.wait();
  } finally {
    observation.stop();
  }
};

Ctl.Commands.push({
  name: "beginUpdate",
  help: "Stop this app to begin an update",
  func: function (argv) {
    Ctl.subscribeToAppJobs(Ctl.myAppName());
    var jobs = Ctl.jobsCollection();
    var thisJob = jobs.findOne(Ctl.myJobId());
    // Look at all the server jobs that are on the old star.
    var oldJobSelector = {
      app: Ctl.myAppName(),
      star: {$ne: thisJob.star},
      program: "server",
      done: false
    };
    var oldServers = jobs.find(oldJobSelector).fetch();
    // Start a new job for each of them.
    _.each(oldServers, function (oldServer) {
      Ctl.startServerlikeProgram("server",
                                 oldServer.tags,
                                 oldServer.env.ADMIN_APP);
    });
    // Wait for them all to come up and bind to the proxy.
    Meteor._sleepForMs(10000); // XXX: Eventually make sure they're proxy-bound.
    Ctl.updateProxyActiveTags(['', thisJob.star]);

    // (eventually) tell the proxy to switch over to using the new star
    // One by one, kill all the old star's server jobs.
    var jobToKill = jobs.findOne(oldJobSelector);
    while (jobToKill) {
      Ctl.kill("server", jobToKill._id);
      // Wait for it to go down
      waitForDone(jobs, jobToKill._id);
      // Spend some time in between to allow any reconnect storm to die down.
      Meteor._sleepForMs(5000);
      jobToKill = jobs.findOne(oldJobSelector);
    }
    // Now kill all old non-server jobs.  They're less important.
    jobs.find({
      app: Ctl.myAppName(),
      star: {$ne: thisJob.star},
      program: {$ne: "server"},
      done: false
    }).forEach(function (job) {
      Ctl.kill(job.program, job._id);
    });
    // fin
    process.exit(0);
  }
});

main = function (argv) {
  return Ctl.main(argv);
};
<commit_msg>Count new servers already started in ctl before starting lots more<commit_after>var Future = Npm.require("fibers/future");

Ctl.Commands.push({
  name: "help",
  func: function (argv) {
    if (!argv._.length || argv.help)
      Ctl.usage();
    var cmd = argv._.splice(0,1)[0];
    argv.help = true;

    Ctl.findCommand(cmd).func(argv);
  }
});

var mergeObjects = function (obj1, obj2) {
  var result = _.clone(obj1);
  _.each(obj2, function (v, k) {
    // If both objects have an object at this key, then merge those objects.
    // Otherwise, choose obj2's value.
    if ((v instanceof Object) && (obj1[k] instanceof Object))
      result[k] = mergeObjects(v, obj1[k]);
    else
      result[k] = v;
  });
  return result;
};

var startFun = function (argv) {
  if (argv.help || argv._.length !== 0) {
    process.stderr.write(
      "Usage: ctl start\n" +
        "\n" +
        "Starts the app. For now, this just means that it runs the 'server'\n" +
        "program.\n"
    );
    process.exit(1);
  }
  Ctl.subscribeToAppJobs(Ctl.myAppName());
  var jobs = Ctl.jobsCollection();
  var thisJob = jobs.findOne(Ctl.myJobId());
  Ctl.updateProxyActiveTags(['', thisJob.star]);
  if (Ctl.hasProgram("console")) {
    console.log("starting console for app", Ctl.myAppName());
    Ctl.startServerlikeProgramIfNotPresent("console", ["admin"], true);
  }
  console.log("starting server for app", Ctl.myAppName());
  Ctl.startServerlikeProgramIfNotPresent("server", ["runner"]);
};

Ctl.Commands.push({
  name: "start",
  help: "Start this app",
  func: startFun
});

Ctl.Commands.push({
  name: "endUpdate",
  help: "Start this app to end an update",
  func: startFun
});

var stopFun =  function (argv) {
  if (argv.help || argv._.length !== 0) {
    process.stderr.write(
      "Usage: ctl stop\n" +
        "\n" +
        "Stops the app. For now, this just means that it kills all jobs\n" +
        "other than itself.\n"
    );
    process.exit(1);
  }

  // Get all jobs (other than this job: don't commit suicide!) that are not
  // already killed.
  var jobs = Ctl.getJobsByApp(
    Ctl.myAppName(), {_id: {$ne: Ctl.myJobId()}, done: false});
  jobs.forEach(function (job) {
    // Don't commit suicide.
    if (job._id === Ctl.myJobId())
      return;
    // It's dead, Jim.
    if (job.done)
      return;
    Ctl.kill(job.program, job._id);
  });
  console.log("Server stopped.");
};

Ctl.Commands.push({
  name: "stop",
  help: "Stop this app",
  func: stopFun
});

var waitForDone = function (jobCollection, jobId) {
  var fut = new Future();
  var found = false;
  try {
    var observation = jobCollection.find(jobId).observe({
      added: function (doc) {
        found = true;
        if (doc.done)
          fut['return']();
      },
      changed: function (doc) {
        if (doc.done)
          fut['return']();
      },
      removed: function (doc) {
        fut['return']();
      }
    });
    // if the document doesn't exist at all, it's certainly done.
    if (!found)
      fut['return']();
    fut.wait();
  } finally {
    observation.stop();
  }
};

Ctl.Commands.push({
  name: "beginUpdate",
  help: "Stop this app to begin an update",
  func: function (argv) {
    Ctl.subscribeToAppJobs(Ctl.myAppName());
    var jobs = Ctl.jobsCollection();
    var thisJob = jobs.findOne(Ctl.myJobId());
    // Look at all the server jobs that are on the old star.
    var oldJobSelector = {
      app: Ctl.myAppName(),
      star: {$ne: thisJob.star},
      program: "server",
      done: false
    };
    var oldServers = jobs.find(oldJobSelector).fetch();
    // Start a new job for each of them.
    var newServersAlreadyPresent = jobs.find({
      app: Ctl.myAppName(),
      star: thisJob.star,
      program: "server",
      done: false
    }).count();
    // discount any new servers we've already started.
    oldServers.splice(0, newServersAlreadyPresent);
    console.log("starting " + oldServers.length + " new servers to match old");
    _.each(oldServers, function (oldServer) {
      Ctl.startServerlikeProgram("server",
                                 oldServer.tags,
                                 oldServer.env.ADMIN_APP);
    });
    // Wait for them all to come up and bind to the proxy.
    Meteor._sleepForMs(10000); // XXX: Eventually make sure they're proxy-bound.
    Ctl.updateProxyActiveTags(['', thisJob.star]);

    // (eventually) tell the proxy to switch over to using the new star
    // One by one, kill all the old star's server jobs.
    var jobToKill = jobs.findOne(oldJobSelector);
    while (jobToKill) {
      Ctl.kill("server", jobToKill._id);
      // Wait for it to go down
      waitForDone(jobs, jobToKill._id);
      // Spend some time in between to allow any reconnect storm to die down.
      Meteor._sleepForMs(5000);
      jobToKill = jobs.findOne(oldJobSelector);
    }
    // Now kill all old non-server jobs.  They're less important.
    jobs.find({
      app: Ctl.myAppName(),
      star: {$ne: thisJob.star},
      program: {$ne: "server"},
      done: false
    }).forEach(function (job) {
      Ctl.kill(job.program, job._id);
    });
    // fin
    process.exit(0);
  }
});

main = function (argv) {
  return Ctl.main(argv);
};
<|endoftext|>


<commit_before>/* eslint max-len: 0 */
import React from 'react';
import { Link } from 'routes';
import classnames from 'classnames';
import { Autobind } from 'es-decorators';
import { Router } from 'routes';

// Redux
import withRedux from 'next-redux-wrapper';
import { initStore } from 'store';
import { getInsights } from 'redactions/insights';

// Layout
import Page from 'components/app/layout/Page';
import Head from 'components/app/layout/head';

// Components

let Map;
let Cesium;
if (typeof window !== 'undefined') {
  /* eslint-disable */
  Map = require('react-cesium').Map;
  /* eslint-enable */
}

const MARKERS = [
  {
    name: 'Tropical deforestation',
    lat: 0.076,
    lon: 101,
    type: 'billboard',
    image: '../../static/images/splash/marker.svg',
    imageSelected: '../../static/images/splash/markerSelected.svg',
    imageNotSelected: '../../static/images/splash/marker.svg'
  },
  {
    name: 'Coral bleaching',
    lat: -21,
    lon: 151,
    type: 'billboard',
    image: '../../static/images/splash/marker.svg',
    imageSelected: '../../static/images/splash/markerSelected.svg',
    imageNotSelected: '../../static/images/splash/marker.svg',
    thumbnail: '../../static/images/splash/bleached.jpg',
    routeId: 'coral'
  }
];

const CAMERA_INITIAL_POSITION = { lat: 35.46, lon: -3.55, height: 90000 };
const CAMERA_NEW_POSITION = { lat: 49.2002, lon: -0.1382, height: 20000000 };

class Splash extends Page {
  constructor(props) {
    super(props);

    this.state = {
      billboardHover: false,
      selectedMarker: null,
      viewer: null
    };
  }

  componentDidMount() {
    super.componentDidMount();

    // Init Cesium var
    Cesium = window.Cesium;
    Cesium.BingMapsApi.defaultKey = process.env.BING_MAPS_API_KEY;

    this.setState({ mounted: true }); // eslint-disable-line react/no-did-mount-set-state
  }

  runInitialAnimation() {
    const { viewer } = this.state;
    const { camera } = viewer;
    // const center = Cesium.Cartesian3.fromDegrees(CAMERA_INITIAL_POSITION.lon, CAMERA_INITIAL_POSITION.lat);
    // camera.lookAt(center, new Cesium.Cartesian3(0.0, 0.0, CAMERA_INITIAL_POSITION.height));
    camera.setView({
      destination: Cesium.Cartesian3.fromDegrees(CAMERA_INITIAL_POSITION.lon, CAMERA_INITIAL_POSITION.lat, CAMERA_INITIAL_POSITION.height),
      orientation: {
        heading: 0.0,
        pitch: -0.3,
        roll: 0.0
      }
    });
    setTimeout(() => camera.flyTo({
      destination: Cesium.Cartesian3.fromDegrees(CAMERA_NEW_POSITION.lon, CAMERA_NEW_POSITION.lat, CAMERA_INITIAL_POSITION.height),
      orientation: {
        heading: 0.0,
        pitch: -0.3,
        roll: 0.0
      },
      duration: 15,
      maximumHeight: CAMERA_INITIAL_POSITION.height
    }), 6000);
    setTimeout(() => camera.flyTo({
      destination: Cesium.Cartesian3.fromDegrees(CAMERA_NEW_POSITION.lon, CAMERA_NEW_POSITION.lat, CAMERA_NEW_POSITION.height),
      orientation: {
        heading: 0.0,
        pitch: -Cesium.Math.PI_OVER_TWO,
        roll: 0.0
      },
      duration: 8,
      maximumHeight: CAMERA_INITIAL_POSITION.height + 9000000
    }), 16000);
  }

  handleMouseMove(e) {

  }

  @Autobind
  handleBillboardClick(e) {
    const name = e.id.name;
    this.setState({ selectedMarker: MARKERS.find(elem => elem.name === name) });
  }

  @Autobind
  handleBillboardHover() {
    this.setState({ billboardHover: true });
  }

  @Autobind
  handleBillboardOut() {
    this.setState({ billboardHover: false });
  }

  @Autobind
  handleVisitButton() {
    const { selectedMarker, viewer } = this.state;
    viewer.camera.flyTo({
      destination: Cesium.Cartesian3.fromDegrees(selectedMarker.lon, selectedMarker.lat, 1000.0),
      duration: 3
    });
    // Router.pushRoute('splash_detail', { id: selectedMarker.routeId });
    setTimeout(() => { window.location = `/splash/${selectedMarker.routeId}`; }, 3000);
  }

  // @Autobind
  // handleMouseClick(e) {
  // }

  @Autobind
  handleOnInit(viewer) {
    this.setState({ viewer }, this.runInitialAnimation);
  }

  render() {
    const { mounted, billboardHover, selectedMarker } = this.state;
    const cesiumClassname = classnames({
      'cesium-map': true,
      '-cursor-pointer': billboardHover
    });

    return (

          <Link route="home">

          </Link>
          <Link route="home">
            GO TO RESOURCE WATCH
          </Link>

        {mounted &&
          <Map
            className={cesiumClassname}
            shapes={MARKERS}
            homeButton={false}
            navigationHelpButton={false}
            selectionIndicator={false}
            showInfoWindow={false}
            onBillboardClick={this.handleBillboardClick}
            onBillboardHover={this.handleBillboardHover}
            onBillboardOut={this.handleBillboardOut}
            onClick={this.handleMouseClick}
            onInit={this.handleOnInit}
          />
        }
        {selectedMarker &&

                {selectedMarker.name}

                  VISIT THIS PLACE

        }

    );
  }
}

const mapStateToProps = state => ({ insights: state.insights.list });

const mapDispatchToProps = dispatch => ({
  getInsights: () => dispatch(getInsights())
});

export default withRedux(initStore, mapStateToProps, mapDispatchToProps)(Splash);
<commit_msg>Parameterize most variables involved in the initial animation<commit_after>/* eslint max-len: 0 */
import React from 'react';
import { Link } from 'routes';
import classnames from 'classnames';
import { Autobind } from 'es-decorators';
import { Router } from 'routes';

// Redux
import withRedux from 'next-redux-wrapper';
import { initStore } from 'store';
import { getInsights } from 'redactions/insights';

// Layout
import Page from 'components/app/layout/Page';
import Head from 'components/app/layout/head';

// Components

let Map;
let Cesium;
if (typeof window !== 'undefined') {
  /* eslint-disable */
  Map = require('react-cesium').Map;
  /* eslint-enable */
}

const MARKERS = [
  {
    name: 'Tropical deforestation',
    lat: 0.076,
    lon: 101,
    type: 'billboard',
    image: '../../static/images/splash/marker.svg',
    imageSelected: '../../static/images/splash/markerSelected.svg',
    imageNotSelected: '../../static/images/splash/marker.svg'
  },
  {
    name: 'Coral bleaching',
    lat: -21,
    lon: 151,
    type: 'billboard',
    image: '../../static/images/splash/marker.svg',
    imageSelected: '../../static/images/splash/markerSelected.svg',
    imageNotSelected: '../../static/images/splash/marker.svg',
    thumbnail: '../../static/images/splash/bleached.jpg',
    routeId: 'coral'
  }
];

const CAMERA_INITIAL_POSITION = { lat: 35.46, lon: -3.55, height: 90000, pitch: -0.3, heading: 0, roll: 0 };
const CAMERA_FINAL_POSITION = { lat: 49.2002, lon: -0.1382, height: 20000000, pitch: -0.3, heading: 0, roll: 0 };
const ANIMATION_DURATION = 15;
const INITIAL_WAIT = 6000;
const FINAL_ANIMATION_DURATION = 8;

class Splash extends Page {
  constructor(props) {
    super(props);

    this.state = {
      billboardHover: false,
      selectedMarker: null,
      viewer: null
    };
  }

  componentDidMount() {
    super.componentDidMount();

    // Init Cesium var
    Cesium = window.Cesium;
    Cesium.BingMapsApi.defaultKey = process.env.BING_MAPS_API_KEY;

    this.setState({ mounted: true }); // eslint-disable-line react/no-did-mount-set-state
  }

  runInitialAnimation() {
    const { viewer } = this.state;
    const { camera } = viewer;
    // ------ INIT VARIABLES -----
    const { query } = this.props.url;
    const duration = query.duration ? query.duration : ANIMATION_DURATION;
    const initialLat = query.initialLat ? query.initialLat : CAMERA_INITIAL_POSITION.lat;
    const initialLon = query.initialLon ? query.initialLon : CAMERA_INITIAL_POSITION.lon;
    const initialHeight = query.initialHeight ? query.initialHeight : CAMERA_INITIAL_POSITION.height;
    const finalLat = query.finalLat ? query.finalLat : CAMERA_FINAL_POSITION.lat;
    const finalLon = query.finalLon ? query.finalLon : CAMERA_FINAL_POSITION.lon;
    const finalHeight = query.finalHeight ? query.finalHeight : CAMERA_FINAL_POSITION.height;
    const finalAnimationDuration = query.finalAnimationDuration ? query.finalAnimationDuration : FINAL_ANIMATION_DURATION;
    const initialHeading = query.initialHeading ? query.initialHeading : CAMERA_INITIAL_POSITION.heading;
    const initialRoll = query.initialRoll ? query.initialRoll : CAMERA_INITIAL_POSITION.roll;
    const initialPitch = query.initialPitch ? query.initialPitch : CAMERA_INITIAL_POSITION.pitch;
    const finalHeading = query.finalHeading ? query.finalHeading : CAMERA_FINAL_POSITION.heading;
    const finalRoll = query.finalRoll ? query.finalRoll : CAMERA_FINAL_POSITION.roll;
    const finalPitch = query.finalPitch ? query.finalPitch : CAMERA_FINAL_POSITION.pitch;
    // --------------------------

    // ------- CAMERA INITIAL POSITION -------
    camera.setView({
      destination: Cesium.Cartesian3.fromDegrees(initialLon, initialLat, initialHeight),
      orientation: {
        heading: initialHeading,
        pitch: initialPitch,
        roll: initialRoll
      }
    });
    // ------- FIRST FLY -------
    setTimeout(() => camera.flyTo({
      destination: Cesium.Cartesian3.fromDegrees(finalLon, finalLat, initialHeight),
      orientation: {
        heading: finalHeading,
        pitch: finalPitch,
        roll: finalRoll
      },
      duration,
      maximumHeight: initialHeight
    }), INITIAL_WAIT);

    const timeoutTime = (Number(duration) + 1) * 1000;

    // ------- SECOND FLY -------
    setTimeout(() => camera.flyTo({
      destination: Cesium.Cartesian3.fromDegrees(finalLon, finalLat, finalHeight),
      orientation: {
        heading: 0.0,
        pitch: -Cesium.Math.PI_OVER_TWO,
        roll: 0.0
      },
      duration: finalAnimationDuration,
      maximumHeight: initialHeight + 9000000
    }), timeoutTime + INITIAL_WAIT);
  }

  // handleMouseMove(e) {
  //
  // }

  @Autobind
  handleBillboardClick(e) {
    const name = e.id.name;
    this.setState({ selectedMarker: MARKERS.find(elem => elem.name === name) });
  }

  @Autobind
  handleBillboardHover() {
    this.setState({ billboardHover: true });
  }

  @Autobind
  handleBillboardOut() {
    this.setState({ billboardHover: false });
  }

  @Autobind
  handleVisitButton() {
    const { selectedMarker, viewer } = this.state;
    viewer.camera.flyTo({
      destination: Cesium.Cartesian3.fromDegrees(selectedMarker.lon, selectedMarker.lat, 1000.0),
      duration: 3
    });
    // Router.pushRoute('splash_detail', { id: selectedMarker.routeId });
    setTimeout(() => { window.location = `/splash/${selectedMarker.routeId}`; }, 3000);
  }

  // @Autobind
  // handleMouseClick(e) {
  // }

  @Autobind
  handleOnInit(viewer) {
    this.setState({ viewer }, this.runInitialAnimation);
  }

  render() {
    const { mounted, billboardHover, selectedMarker } = this.state;
    const cesiumClassname = classnames({
      'cesium-map': true,
      '-cursor-pointer': billboardHover
    });

    return (

          <Link route="home">

          </Link>
          <Link route="home">
            GO TO RESOURCE WATCH
          </Link>

        {mounted &&
          <Map
            className={cesiumClassname}
            shapes={MARKERS}
            homeButton={false}
            navigationHelpButton={false}
            selectionIndicator={false}
            showInfoWindow={false}
            onBillboardClick={this.handleBillboardClick}
            onBillboardHover={this.handleBillboardHover}
            onBillboardOut={this.handleBillboardOut}
            onClick={this.handleMouseClick}
            onInit={this.handleOnInit}
          />
        }
        {selectedMarker &&

                {selectedMarker.name}

                  VISIT THIS PLACE

        }

    );
  }
}

const mapStateToProps = state => ({ insights: state.insights.list });

const mapDispatchToProps = dispatch => ({
  getInsights: () => dispatch(getInsights())
});

export default withRedux(initStore, mapStateToProps, mapDispatchToProps)(Splash);
<|endoftext|>


<commit_before>/**
 * # SocketManager
 *
 * Copyright(c) 2012 Stefano Balietti
 * MIT Licensed
 *
 * Game socket manager: registers of all open sockets and
 * connected clients
 *
 * ---
 *
 */

// Global scope

module.exports = SocketManager;

/**
 * ## SocketManager constructor
 *
 * Creates an instance of SocketManager
 *
 * @param {GameServer} server A GameServer instance
 */
function SocketManager(server) {
    this.server = server;

    this.sysLogger = server.sysLogger;
    this.msgLogger = server.msgLogger;

    this.sockets = {};
    this.clients = {};
}

// ## METHODS

/**
 * SocketManager.registerSocket
 *
 * Registers a new type of socket
 *
 * @param {string} name The name of the socket
 * @param {object} socket The connection socket
 *
 */
SocketManager.prototype.registerSocket = function(name, socket) {
    this.sockets[name] = socket;
};

/**
 * SocketManager.registerClient
 *
 * Matches a client to a socket
 *
 * @param client {string} The id of the client
 * @param socket {object} The socket through which the client is connected
 *
 */
SocketManager.prototype.registerClient = function(client, socket) {
    this.clients[client] = socket;
};

/**
 * ### SocketManager.send
 *
 * Low level primitive to send a game message
 *
 * @param {GameMsg} gameMsg The game message to send
 * @param {boolean} FALSE, if an error occurs
 */
SocketManager.prototype.send = function(gameMsg) {
    var to = gameMsg.to;
    var smoothExec = true;
    var socket, res, oneFail;
    var registry = this.server.channel.registry;
    var resolvedTo = registry.lookupClient(to,
            registry.getClientRoom(gameMsg.from));

    // Broadcasting a msg (TODO: remove)
    if (to === 'ALL') {
        for (var i in this.sockets) {
            if (this.sockets.hasOwnProperty(i)) {
                res = this.sockets[i].send(gameMsg);
                if (!res) {
                    this.sysLogger.log('An error occurred while sending a message to ALL. client:' + i, 'ERR');
                    oneFail = false;
                }
            }
        }
        return smoothExec;
    }

    // Sending a msg to a specific client
    else {

        socket = this.clients[resolvedTo];

        if (!socket) {
            this.sysLogger.log('Msg not sent. Unexisting recipient: ' +
                    to + ' (resolved as: ' + resolvedTo + ')', 'ERR');
            return false;
        }

        res = socket.send(gameMsg);
        if (!res) {
            this.sysLogger.log('An error occurred while sending a message to ' +
                    to + ' (resolved as: ' + resolvedTo + ')', 'ERR');
        }
        return res;
    }

};

/**
 * ### SocketManager.broadcast
 *
 * Broadcasts a game message to all connected clients in the sender's room,
 * sender excluded
 *
 * @param {GameMsg} gameMsg The game message to send
 * @return {boolean} FALSE is an error occurs
 */
SocketManager.prototype.broadcast = function(gameMsg, from) {
    var client, originalTo, smoothExec;
    var fromRoomName, fromRoom, toClients;

    smoothExec = true;
    originalTo = gameMsg.to;
    from = from || gameMsg.from;

    fromRoomName = this.server.channel.registry.getClientRoom(from);
    if (!fromRoomName) {
        throw new Error('SocketManager.broadcast: Sender (ID: ' + from + ') is not in any room');
    }
    else {
        fromRoom = this.server.channel.gameRooms[fromRoomName];
        if(!fromRoom) {
            throw new Error('SocketManager.broadcast: Sender (ID: ' + from + ') is not in any room');
        }
        else {
            toClients = fromRoom.playerList.id.getAllKeyElements();
        }
    }

    for (client in toClients) {
        if (toClients.hasOwnProperty(client)) {
            // TODO: resolve aliases for this check:
            if (client != from) {  // TODO: change back to '!==' once 'from' is string again
                gameMsg.to = client;
                smoothExec = smoothExec && this.send(gameMsg);
            }
        }
    }

    // The original _from_ field of the gameMsg must be re-set
    // to avoid that a wrong reuse of the msg in the callee
    gameMsg.to = originalTo;

    return smoothExec;
};

/**
 * ### GameMsgManager.forward
 *
 * Low level primitive to forward messages
 *
 * @param {GameMsg} gameMsg The game message to forward
 */
SocketManager.prototype.forward = function(gameMsg) {

    // <!--
    // Create a copy of the msg and prepare the attributes
    // var gameMsg = new GameMsg(gameMsg);
    // gameMsg.from = this.server.name;
    // --!>

    gameMsg.forward = 1;

    if (gameMsg.to === 'SERVER' || gameMsg === null || gameMsg.to === undefined) {
        gameMsg.to = 'ALL';
    }

    this.server.partner.socket.send(gameMsg);

    this.msgLogger.log('F', gameMsg);
    this.sysLogger.log('Msg ' + gameMsg.toSMS() + ' forwarded to ' + this.server.partner.name);
};

<commit_msg>Added alias lookup to SocketManager.broadcast<commit_after>/**
 * # SocketManager
 *
 * Copyright(c) 2012 Stefano Balietti
 * MIT Licensed
 *
 * Game socket manager: registers of all open sockets and
 * connected clients
 *
 * ---
 *
 */

// Global scope

module.exports = SocketManager;

/**
 * ## SocketManager constructor
 *
 * Creates an instance of SocketManager
 *
 * @param {GameServer} server A GameServer instance
 */
function SocketManager(server) {
    this.server = server;

    this.sysLogger = server.sysLogger;
    this.msgLogger = server.msgLogger;

    this.sockets = {};
    this.clients = {};
}

// ## METHODS

/**
 * SocketManager.registerSocket
 *
 * Registers a new type of socket
 *
 * @param {string} name The name of the socket
 * @param {object} socket The connection socket
 *
 */
SocketManager.prototype.registerSocket = function(name, socket) {
    this.sockets[name] = socket;
};

/**
 * SocketManager.registerClient
 *
 * Matches a client to a socket
 *
 * @param client {string} The id of the client
 * @param socket {object} The socket through which the client is connected
 *
 */
SocketManager.prototype.registerClient = function(client, socket) {
    this.clients[client] = socket;
};

/**
 * ### SocketManager.send
 *
 * Low level primitive to send a game message
 *
 * @param {GameMsg} gameMsg The game message to send
 * @param {boolean} FALSE, if an error occurs
 */
SocketManager.prototype.send = function(gameMsg) {
    var to = gameMsg.to;
    var smoothExec = true;
    var socket, res, oneFail;
    var registry = this.server.channel.registry;
    var resolvedTo = registry.lookupClient(to,
            registry.getClientRoom(gameMsg.from));

    // Broadcasting a msg (TODO: remove)
    if (to === 'ALL') {
        for (var i in this.sockets) {
            if (this.sockets.hasOwnProperty(i)) {
                res = this.sockets[i].send(gameMsg);
                if (!res) {
                    this.sysLogger.log('An error occurred while sending a message to ALL. client:' + i, 'ERR');
                    oneFail = false;
                }
            }
        }
        return smoothExec;
    }

    // Sending a msg to a specific client
    else {

        socket = this.clients[resolvedTo];

        if (!socket) {
            this.sysLogger.log('Msg not sent. Unexisting recipient: ' +
                    to + ' (resolved as: ' + resolvedTo + ')', 'ERR');
            return false;
        }

        res = socket.send(gameMsg);
        if (!res) {
            this.sysLogger.log('An error occurred while sending a message to ' +
                    to + ' (resolved as: ' + resolvedTo + ')', 'ERR');
        }
        return res;
    }

};

/**
 * ### SocketManager.broadcast
 *
 * Broadcasts a game message to all connected clients in the sender's room,
 * sender excluded
 *
 * @param {GameMsg} gameMsg The game message to send
 * @return {boolean} FALSE is an error occurs
 */
SocketManager.prototype.broadcast = function(gameMsg, from) {
    var client, originalTo, smoothExec;
    var registry = this.server.channel.registry;
    var resolvedFrom;
    var fromRoomName, fromRoom, toClients;

    smoothExec = true;
    originalTo = gameMsg.to;
    from = from || gameMsg.from;

    resolvedFrom = registry.lookupClient(from);
    fromRoomName = registry.getClientRoom(resolvedFrom);
    if (!fromRoomName) {
        throw new Error('SocketManager.broadcast: Sender (ID: ' + resolvedFrom + ') is not in any room');
    }
    else {
        fromRoom = this.server.channel.gameRooms[fromRoomName];
        if(!fromRoom) {
            throw new Error('SocketManager.broadcast: Sender (ID: ' + resolvedFrom + ') is not in any room');
        }
        else {
            toClients = fromRoom.playerList.id.getAllKeyElements();
        }
    }

    for (client in toClients) {
        if (toClients.hasOwnProperty(client)) {
            if (client != resolvedFrom) {  // TODO: change back to '!==' once 'from' is string again
                gameMsg.to = client;
                smoothExec = smoothExec && this.send(gameMsg);
            }
        }
    }

    // The original _from_ field of the gameMsg must be re-set
    // to avoid that a wrong reuse of the msg in the callee
    gameMsg.to = originalTo;

    return smoothExec;
};

/**
 * ### GameMsgManager.forward
 *
 * Low level primitive to forward messages
 *
 * @param {GameMsg} gameMsg The game message to forward
 */
SocketManager.prototype.forward = function(gameMsg) {

    // <!--
    // Create a copy of the msg and prepare the attributes
    // var gameMsg = new GameMsg(gameMsg);
    // gameMsg.from = this.server.name;
    // --!>

    gameMsg.forward = 1;

    if (gameMsg.to === 'SERVER' || gameMsg === null || gameMsg.to === undefined) {
        gameMsg.to = 'ALL';
    }

    this.server.partner.socket.send(gameMsg);

    this.msgLogger.log('F', gameMsg);
    this.sysLogger.log('Msg ' + gameMsg.toSMS() + ' forwarded to ' + this.server.partner.name);
};

<|endoftext|>


<commit_before>var jsdom = require('jsdom');

var extractionRules = {
    bikeshed: {
        generator: "Bikeshed",
        sectionId: {
            normative: "normative",
            informative: "informative"
        },
        listSelector: {
            normative: "#normative + dl",
            informative: "#informative + dl"
        }
    },
    respec: {
        generator: "ReSpec",
        sectionId: {
            normative: "normative-references",
            informative: "informative-references"
        },
        listSelector: {
            normative: "#normative-references > dl",
            informative: "#informative-references > dl"
        }
    },
    anolis: {
        generator: "Anolis",
        sectionId: {
            normative: "anolis-references"
        },
        listSelector: {
            normative: "#anolis-references > dl"
        }
    },
};

function extract(url, cb) {
    jsdom.env({
        url: url,
        features: {
            FetchExternalResources: ['script'],
            ProcessExternalResources: ['script'],
            // only load respec, to avoid jsdom bugs
            SkipExternalResources: /^((?!respec).)*$/
        },
        done: function(err, window) {
            if (err) return cb(err);
            var generator = window.document.querySelector("meta[name='generator']");
            if (generator && generator.content.match(/bikeshed/i)) {
                extractReferences(window.document, extractionRules.bikeshed, cb);
            } else if (window.document.body.id === "respecDocument") {
                extractReferences(window.document, extractionRules.respec, cb);
            } else if (window.respecConfig) {
                if (!window.respecConfig.postProcess) {
                    window.respecConfig.postProcess = [];
                }
                window.respecConfig.postProcess.push(function() {
                    extractReferences(window.document, extractionRules.respec, cb);
                });
            } else if (window.document.getElementById('anolis-references')) {
                extractReferences(window.document, extractionRules.anolis, cb);
            } else {
                extractReferences(window.document, null, cb);
            }
        }
    });
}

function nextTag(node, name) {
    var nextSibling = node.nextSibling;
    while(nextSibling && nextSibling.tagName !== name.toUpperCase()) {
        nextSibling = nextSibling.nextSibling;
    }
    return nextSibling;
}

function parseReferences(referenceList) {
    var defaultRef = [], informativeRef = [];
    [].forEach.call(referenceList.querySelectorAll("dt"), function(dt) {
        var ref = {};
        ref.name = dt.textContent.replace(/[\[\] \n]/g, '');
        var desc = nextTag(dt, "dd");
        ref.url = desc.querySelector("a[href]") ? desc.querySelector("a[href]").href : "";
        if (desc.textContent.match(/non-normative/i)) {
            return informativeRef.push(ref);
        }
        defaultRef.push(ref);
    });
    return [defaultRef, informativeRef];
};

function extractReferencesWithoutRules(doc, cb) {
    var anchors = doc.querySelectorAll("h1, h2, h3");
    var referenceHeadings = [].filter.call(anchors, a => a.textContent.match(/references/i));
    if (!referenceHeadings.length) {
        return cb(new Error("Could not detect a heading called \"references\" in document"));
    }
    if (referenceHeadings.length === 1) {
        var list = nextTag(referenceHeadings[0], "dl");
        if (!list) {
            return cb(new Error("Could not find a reference list formatted with a dl"));
        }
        var refs = parseReferences(list);
        return cb(null, {normative: refs[0], informative: refs[1]});
    } else {
        var normative = referenceHeadings.filter(h => h.textContent.match(/normative/i))[0];
        var references = {};
        if (normative) {
            var nList = nextTag(normative, "dl");
            if (nList) {
                references.normative = parseReferences(nList)[0];
            }
        }
        var informative = referenceHeadings.filter(h => h.textContent.match(/informative/i))[0];
        if (informative) {
            var iList = nextTag(informative, "dl");
            if (iList) {
                references.informative = parseReferences(iList)[0];
            }
        }
        if (!informative && !normative) {
            return cb(new Error("Could not detect references in document"));
        }
        cb(null, references);
    }
}

function extractReferences(doc, rules, cb) {
    if (!rules) {
        return extractReferencesWithoutRules(doc, cb);
    }
    if (!rules.sectionId ||
        !rules.sectionId.normative) {
        return cb(new Error("Extraction rules for references section are incorrect"));
    }
    if (!rules.listSelector ||
        !rules.listSelector.normative) {
        return cb(new Error("Extraction rules for the list of references are incorrect"));
    }
    var generator = rules.generator || "an unknown generator";

    var error = null;
    var references = {};
    ['normative', 'informative'].forEach(function(referenceType) {
        if (error) return;
        var refHeading = doc.getElementById(rules.sectionId[referenceType]);
        if (!refHeading) {
            if (referenceType === 'informative') {
                return;
            }
            error = new Error("Spec " + url + " is generated with " + generator + " but does not have a '" + rules.sectionId[referenceType]  + "' id");
            return;
        }
        var referenceList = doc.querySelector(rules.listSelector[referenceType]);
        if (!referenceList) {
            error = new Error("Spec " + url + " is generated with " + generator + " but does not have a definition list following the heading with id '" + rules.id[referenceType] + "'");
            return;
        }
        var refs = parseReferences(referenceList);
        references[referenceType] = refs[0];
        if (referenceType === "normative") {
            references.informative = refs[1];
        }
    });

    if (error) {
        return cb(error);
    }
    else {
        cb(null, references);
    }
}

module.exports.extract = extract;

if (require.main === module) {
    var url = process.argv[2];
    if (!url) {
        console.error("Required URL parameter missing");
        process.exit(2);
    }
    extract(url, function(err, references) {
        if (err) {
            console.error(err);
            process.exit(64);
        }
        console.log(JSON.stringify(references, null, 2));
    });
}
<commit_msg>Added defensive filtering option to references parsing (#10)<commit_after>var jsdom = require('jsdom');

var extractionRules = {
    bikeshed: {
        generator: "Bikeshed",
        sectionId: {
            normative: "normative",
            informative: "informative"
        },
        listSelector: {
            normative: "#normative + dl",
            informative: "#informative + dl"
        }
    },
    respec: {
        generator: "ReSpec",
        sectionId: {
            normative: "normative-references",
            informative: "informative-references"
        },
        listSelector: {
            normative: "#normative-references > dl",
            informative: "#informative-references > dl"
        }
    },
    anolis: {
        generator: "Anolis",
        sectionId: {
            normative: "anolis-references"
        },
        listSelector: {
            normative: "#anolis-references > dl"
        }
    },
};

function extract(url, cb) {
    jsdom.env({
        url: url,
        features: {
            FetchExternalResources: ['script'],
            ProcessExternalResources: ['script'],
            // only load respec, to avoid jsdom bugs
            SkipExternalResources: /^((?!respec).)*$/
        },
        done: function(err, window) {
            if (err) return cb(err);
            var generator = window.document.querySelector("meta[name='generator']");
            if (generator && generator.content.match(/bikeshed/i)) {
                extractReferences(window.document, extractionRules.bikeshed, cb);
            } else if (window.document.body.id === "respecDocument") {
                extractReferences(window.document, extractionRules.respec, cb);
            } else if (window.respecConfig) {
                if (!window.respecConfig.postProcess) {
                    window.respecConfig.postProcess = [];
                }
                window.respecConfig.postProcess.push(function() {
                    extractReferences(window.document, extractionRules.respec, cb);
                });
            } else if (window.document.getElementById('anolis-references')) {
                extractReferences(window.document, extractionRules.anolis, cb);
            } else {
                extractReferences(window.document, null, cb);
            }
        }
    });
}

function nextTag(node, name) {
    var nextSibling = node.nextSibling;
    while(nextSibling && nextSibling.tagName !== name.toUpperCase()) {
        nextSibling = nextSibling.nextSibling;
    }
    return nextSibling;
}

function parseReferences(referenceList, options) {
    var defaultRef = [], informativeRef = [];
    options = options || {};
    [].forEach.call(referenceList.querySelectorAll("dt"), function(dt) {
        var ref = {};
        ref.name = dt.textContent.replace(/[\[\] \n]/g, '');
        var desc = nextTag(dt, "dd");
        ref.url = desc.querySelector("a[href]") ? desc.querySelector("a[href]").href : "";
        if (options.filterInformative &&
            desc.textContent.match(/non-normative/i)) {
            return informativeRef.push(ref);
        }
        defaultRef.push(ref);
    });
    return [defaultRef, informativeRef];
};

function extractReferencesWithoutRules(doc, cb) {
    var anchors = doc.querySelectorAll("h1, h2, h3");
    var referenceHeadings = [].filter.call(anchors, a => a.textContent.match(/references/i));
    if (!referenceHeadings.length) {
        return cb(new Error("Could not detect a heading called \"references\" in document"));
    }
    if (referenceHeadings.length === 1) {
        var list = nextTag(referenceHeadings[0], "dl");
        if (!list) {
            return cb(new Error("Could not find a reference list formatted with a dl"));
        }
        var refs = parseReferences(list, { filterInformative: true });
        return cb(null, {normative: refs[0], informative: refs[1]});
    } else {
        var normative = referenceHeadings.filter(h => h.textContent.match(/normative/i))[0];
        var references = {};
        if (normative) {
            var nList = nextTag(normative, "dl");
            if (nList) {
                references.normative = parseReferences(nList)[0];
            }
        }
        var informative = referenceHeadings.filter(h => h.textContent.match(/informative/i))[0];
        if (informative) {
            var iList = nextTag(informative, "dl");
            if (iList) {
                references.informative = parseReferences(iList)[0];
            }
        }
        if (!informative && !normative) {
            return cb(new Error("Could not detect references in document"));
        }
        cb(null, references);
    }
}

function extractReferences(doc, rules, cb) {
    if (!rules) {
        return extractReferencesWithoutRules(doc, cb);
    }
    if (!rules.sectionId ||
        !rules.sectionId.normative) {
        return cb(new Error("Extraction rules for references section are incorrect"));
    }
    if (!rules.listSelector ||
        !rules.listSelector.normative) {
        return cb(new Error("Extraction rules for the list of references are incorrect"));
    }
    var generator = rules.generator || "an unknown generator";

    var error = null;
    var references = {};
    ['normative', 'informative'].forEach(function(referenceType) {
        if (error) return;
        var refHeading = doc.getElementById(rules.sectionId[referenceType]);
        if (!refHeading) {
            if (referenceType === 'informative') {
                return;
            }
            error = new Error("Spec " + url + " is generated with " + generator + " but does not have a '" + rules.sectionId[referenceType]  + "' id");
            return;
        }
        var referenceList = doc.querySelector(rules.listSelector[referenceType]);
        if (!referenceList) {
            error = new Error("Spec " + url + " is generated with " + generator + " but does not have a definition list following the heading with id '" + rules.id[referenceType] + "'");
            return;
        }
        var refs = parseReferences(referenceList, {
            filterInformative: (referenceType === 'normative')
        });
        references[referenceType] = refs[0];
        if (referenceType === "normative") {
            references.informative = refs[1];
        }
    });

    if (error) {
        return cb(error);
    }
    else {
        cb(null, references);
    }
}

module.exports.extract = extract;

if (require.main === module) {
    var url = process.argv[2];
    if (!url) {
        console.error("Required URL parameter missing");
        process.exit(2);
    }
    extract(url, function(err, references) {
        if (err) {
            console.error(err);
            process.exit(64);
        }
        console.log(JSON.stringify(references, null, 2));
    });
}
<|endoftext|>