<commit_before>/*
 * Copyright 2013 The Polymer Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style
 * license that can be found in the LICENSE file.
 */

var async = require('async');
var cheerio = require('cheerio');
var cleancss = require('clean-css');
var fs = require('fs');
var path = require('path');
var uglify = require('uglify-js');
var url = require('url');

var constants = require('./constants.js');
var optparser = require('./optparser.js');
var pathresolver = require('./pathresolver');

var read = {};
var options = {};

// validate options with boolean return
function setOptions(optHash, callback) {
  optparser.processOptions(optHash, function(err, o) {
    if (err) {
      return callback(err);
    }
    options = o;
    callback();
  });
}

function exclude(regexes, href) {
  return regexes.some(function(r) {
    return r.test(href);
  });
}

function excludeImport(href) {
  return exclude(excludes.imports, href);
}

function excludeScript(href) {
  return exclude(excludes.scripts, href);
}

function excludeStyle(href) {
  return exclude(excludes.styles, href);
}

// directly update the textnode child of <style>
// equivalent to <style>.textContent
function setTextContent(node, text) {
  node[0].children[0].data = text;
}

// inline relative linked stylesheets into <style> tags
function inlineSheets($, inputPath, outputPath) {
  $('link[rel="stylesheet"]').each(function() {
    var href = this.attr('href');
    if (href && !excludeStyle(href)) {
      var filepath = path.resolve(inputPath, href);
      // fix up paths in the stylesheet to be relative to the location of the style
      var content = pathresolver.rewriteURL(path.dirname(filepath), inputPath, fs.readFileSync(filepath, 'utf8'));
      var styleDoc = cheerio.load('<style>' + content + '</style>');
      // clone attributes
      styleDoc('style').attr(this.attr());
      // don't set href or rel on the <style>
      styleDoc('style').attr('href', null);
      styleDoc('style').attr('rel', null);
      this.replaceWith(styleDoc.html());
    }
  });
}

function inlineScripts($, dir) {
  $(constants.JS_SRC).each(function() {
    var src = this.attr('src');
    if (src && !excludeScript(src)) {
      var filepath = path.resolve(dir, src);
      var content = fs.readFileSync(filepath, 'utf8');
      this.replaceWith('<script>' + content + '</script>');
    }
  });
}

function readDocument(filename) {
  return cheerio.load(fs.readFileSync(filename, 'utf8'));
}

function concat(filename) {
  if (!read[filename]) {
    read[filename] = true;
    var $ = readDocument(filename);
    var dir = path.dirname(filename);
    processImports($, dir);
    inlineSheets($, dir, options.outputDir);
    pathresolver.resolvePaths($, dir, options.outputDir);
    return $.html();
  } else {
    if (options.verbose) {
      console.log('Dependency deduplicated');
    }
  }
}

function processImports($, prefix) {
  $(constants.IMPORTS).each(function() {
    var href = this.attr('href');
    if (excludeImport(href)) {
      // rewrite href to be deduplicated later
      this.attr('href', pathresolver.rewriteRelPath(prefix, options.outputDir, href));
    } else {
      this.replaceWith(concat(path.resolve(prefix, href)));
    }
  });
}

function findScriptLocation($) {
  var pos = $('body').last();
  if (!pos.length) {
    pos = $.root();
  }
  return pos;
}

// arguments are (index, node), where index is unnecessary
function isCommentOrEmptyTextNode(_, node) {
  if (node.type === 'comment'){
    return true;
  } else if (node.type === 'text') {
    // return true if the node is only whitespace
    return !((/\S/).test(node.data));
  }
}

function removeCommentsAndWhitespace($) {
  $.root().contents().filter(isCommentOrEmptyTextNode).remove();
  $('head').contents().filter(isCommentOrEmptyTextNode).remove();
  $('body').contents().filter(isCommentOrEmptyTextNode).remove();
  $(constants.JS).each(function() {
    if (!this.attr('src')) {
      var content = this.html();
      var ast = uglify.parse(content);
      this.replaceWith('<script>' + ast.print_to_string() + '</script>');
    }
  });
  $(constants.CSS).each(function() {
    setTextContent(this, new cleancss().minify(this.text()));
  });
}

function handleMainDocument() {
  // reset shared buffers
  imports_before_polymer = [];
  read = {};
  var $ = readDocument(options.input);
  var dir = path.dirname(options.input);
  processImports($, dir);
  if (options.inline) {
    inlineSheets($, dir, options.outputDir);
  }
  pathresolver.resolvePaths($, dir, options.outputDir);

  // strip scripts into a separate file
  if (options.csp) {
    if (options.verbose) {
      console.log('Separating scripts into separate file');
    }
    var scripts = [];
    var scripts_after_polymer = [];

    var fn = function() {
      var src = this.attr('src');
      if (src) {
        // external script
        if (excludeScript(src)) {
          // put an absolute path script after polymer.js in main document
          scripts_after_polymer.push(this.toString());
        } else {
          scripts.push(fs.readFileSync(path.resolve(options.outputDir, src), 'utf8'));
        }
      } else {
        // inline script
        scripts.push(this.text());
      }
    };

    // CSPify main page
    $(constants.JS).each(fn).remove();

    // join scripts with ';' to prevent breakages due to EOF semicolon insertion
    var script_name = path.basename(options.output, '.html') + '.js';
    fs.writeFileSync(path.resolve(options.outputDir, script_name), scripts.join(';' + EOL), 'utf8');
    scripts_after_polymer.push('<script src="' + script_name + '"></script>');
    findScriptLocation($).append(EOL + scripts_after_polymer.join(EOL) + EOL);
  }

  deduplicateImports($);
  if (!options.csp && options.inline) {
    inlineScripts($, options.outputDir);
  }
  if (options.strip) {
    removeCommentsAndWhitespace($);
  }
  var outhtml = $.html();
  fs.writeFileSync(options.output, outhtml, 'utf8');
}

function deduplicateImports($) {
  var imports = {};
  $(constants.IMPORTS).each(function() {
    var href = this.attr('href');
    // TODO(dfreedm): allow a user defined base url?
    var abs = url.resolve('http://', href);
    if (!imports[abs]) {
      imports[abs] = true;
    } else {
      if(options.verbose) {
        console.log('Import Dependency deduplicated');
      }
      this.remove();
    }
  });
}

exports.processDocument = handleMainDocument;
exports.setOptions = setOptions;
<commit_msg>Remove byte order mark<commit_after>/*
 * Copyright 2013 The Polymer Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style
 * license that can be found in the LICENSE file.
 */

var async = require('async');
var cheerio = require('cheerio');
var cleancss = require('clean-css');
var fs = require('fs');
var path = require('path');
var uglify = require('uglify-js');
var url = require('url');

var constants = require('./constants.js');
var optparser = require('./optparser.js');
var pathresolver = require('./pathresolver');

var read = {};
var options = {};

// validate options with boolean return
function setOptions(optHash, callback) {
  optparser.processOptions(optHash, function(err, o) {
    if (err) {
      return callback(err);
    }
    options = o;
    callback();
  });
}

function exclude(regexes, href) {
  return regexes.some(function(r) {
    return r.test(href);
  });
}

function excludeImport(href) {
  return exclude(excludes.imports, href);
}

function excludeScript(href) {
  return exclude(excludes.scripts, href);
}

function excludeStyle(href) {
  return exclude(excludes.styles, href);
}

// directly update the textnode child of <style>
// equivalent to <style>.textContent
function setTextContent(node, text) {
  node[0].children[0].data = text;
}

function readFile(file) {
  var content = readFile(file);
  return content.replace(/^\uFEFF/, '');
}

// inline relative linked stylesheets into <style> tags
function inlineSheets($, inputPath, outputPath) {
  $('link[rel="stylesheet"]').each(function() {
    var href = this.attr('href');
    if (href && !excludeStyle(href)) {
      var filepath = path.resolve(inputPath, href);
      // fix up paths in the stylesheet to be relative to the location of the style
      var content = pathresolver.rewriteURL(path.dirname(filepath), inputPath, readFile(filepath));
      var styleDoc = cheerio.load('<style>' + content + '</style>');
      // clone attributes
      styleDoc('style').attr(this.attr());
      // don't set href or rel on the <style>
      styleDoc('style').attr('href', null);
      styleDoc('style').attr('rel', null);
      this.replaceWith(styleDoc.html());
    }
  });
}

function inlineScripts($, dir) {
  $(constants.JS_SRC).each(function() {
    var src = this.attr('src');
    if (src && !excludeScript(src)) {
      var filepath = path.resolve(dir, src);
      var content = readFile(filepath);
      this.replaceWith('<script>' + content + '</script>');
    }
  });
}

function readDocument(filename) {
  return cheerio.load(readFile(filename));
}

function concat(filename) {
  if (!read[filename]) {
    read[filename] = true;
    var $ = readDocument(filename);
    var dir = path.dirname(filename);
    processImports($, dir);
    inlineSheets($, dir, options.outputDir);
    pathresolver.resolvePaths($, dir, options.outputDir);
    return $.html();
  } else {
    if (options.verbose) {
      console.log('Dependency deduplicated');
    }
  }
}

function processImports($, prefix) {
  $(constants.IMPORTS).each(function() {
    var href = this.attr('href');
    if (excludeImport(href)) {
      // rewrite href to be deduplicated later
      this.attr('href', pathresolver.rewriteRelPath(prefix, options.outputDir, href));
    } else {
      this.replaceWith(concat(path.resolve(prefix, href)));
    }
  });
}

function findScriptLocation($) {
  var pos = $('body').last();
  if (!pos.length) {
    pos = $.root();
  }
  return pos;
}

// arguments are (index, node), where index is unnecessary
function isCommentOrEmptyTextNode(_, node) {
  if (node.type === 'comment'){
    return true;
  } else if (node.type === 'text') {
    // return true if the node is only whitespace
    return !((/\S/).test(node.data));
  }
}

function removeCommentsAndWhitespace($) {
  $.root().contents().filter(isCommentOrEmptyTextNode).remove();
  $('head').contents().filter(isCommentOrEmptyTextNode).remove();
  $('body').contents().filter(isCommentOrEmptyTextNode).remove();
  $(constants.JS).each(function() {
    if (!this.attr('src')) {
      var content = this.html();
      var ast = uglify.parse(content);
      this.replaceWith('<script>' + ast.print_to_string() + '</script>');
    }
  });
  $(constants.CSS).each(function() {
    setTextContent(this, new cleancss().minify(this.text()));
  });
}

function handleMainDocument() {
  // reset shared buffers
  imports_before_polymer = [];
  read = {};
  var $ = readDocument(options.input);
  var dir = path.dirname(options.input);
  processImports($, dir);
  if (options.inline) {
    inlineSheets($, dir, options.outputDir);
  }
  pathresolver.resolvePaths($, dir, options.outputDir);

  // strip scripts into a separate file
  if (options.csp) {
    if (options.verbose) {
      console.log('Separating scripts into separate file');
    }
    var scripts = [];
    var scripts_after_polymer = [];

    var fn = function() {
      var src = this.attr('src');
      if (src) {
        // external script
        if (excludeScript(src)) {
          // put an absolute path script after polymer.js in main document
          scripts_after_polymer.push(this.toString());
        } else {
          scripts.push(readFile(path.resolve(options.outputDir, src)));
        }
      } else {
        // inline script
        scripts.push(this.text());
      }
    };

    // CSPify main page
    $(constants.JS).each(fn).remove();

    // join scripts with ';' to prevent breakages due to EOF semicolon insertion
    var script_name = path.basename(options.output, '.html') + '.js';
    fs.writeFileSync(path.resolve(options.outputDir, script_name), scripts.join(';' + EOL), 'utf8');
    scripts_after_polymer.push('<script src="' + script_name + '"></script>');
    findScriptLocation($).append(EOL + scripts_after_polymer.join(EOL) + EOL);
  }

  deduplicateImports($);
  if (!options.csp && options.inline) {
    inlineScripts($, options.outputDir);
  }
  if (options.strip) {
    removeCommentsAndWhitespace($);
  }
  var outhtml = $.html();
  fs.writeFileSync(options.output, outhtml, 'utf8');
}

function deduplicateImports($) {
  var imports = {};
  $(constants.IMPORTS).each(function() {
    var href = this.attr('href');
    // TODO(dfreedm): allow a user defined base url?
    var abs = url.resolve('http://', href);
    if (!imports[abs]) {
      imports[abs] = true;
    } else {
      if(options.verbose) {
        console.log('Import Dependency deduplicated');
      }
      this.remove();
    }
  });
}

exports.processDocument = handleMainDocument;
exports.setOptions = setOptions;
<|endoftext|>


<commit_before>/*
 * JBoss, Home of Professional Open Source
 * Copyright Red Hat, Inc., and individual contributors.
 *
 * 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.
 */
'use strict';

angular.module('upsConsole').controller('DetailController',
  function($rootScope, $scope, $routeParams, $location, $modal, pushApplication, variants, Notifications, breadcrumbs, application, counts, ContextProvider) {

  /*
   * INITIALIZATION
   */
  $rootScope.application = application;
  $scope.counts = counts;
  breadcrumbs.generateBreadcrumbs();
  $scope.currentLocation = ContextProvider.contextPath();

  /*
   * PUBLIC METHODS
   */

  $scope.addVariant = function (variant) {
    var modalInstance = show(variant, 'create-variant.html');
    modalInstance.result.then(function (result) {
      var variantData = variantProperties(result.variant);
      var params = $.extend({}, {
        appId: $scope.application.pushApplicationID,
        variantType: result.variant.type
      });

      var createFunction = (variantData instanceof FormData) ? variants.createWithFormData : variants.create;

      createFunction(params, variantData, function (newVariant) {
        var length = application.variants.length;
        for (var i = 0; i < length; i++) {
          if (newVariant.type === application.variants[i].type) {
            break;
          }
        }
        $scope.application.variants.splice(i, 0, newVariant);
        Notifications.success('Successfully created variant');
      }, function () {
        Notifications.error('Something went wrong...');
      });
    });
  };

  $scope.editVariant = function (variant) {
    var modalInstance = show(variant, 'create-variant.html');
    modalInstance.result.then(function (result) {
      var variantDataUpdate = variantProperties(variant);
      var params = $.extend({}, {
        appId: $scope.application.pushApplicationID,
        variantType: result.variant.type,
        variantId: result.variant.variantID
      });

      var successCallback = function () {
        Notifications.success('Successfully modified variant');
      };
      var failureCallback = function () {
        Notifications.error('Something went wrong...');
      };

      if (variantType !== 'ios') {
        variants.update(params, variantDataUpdate, successCallback, failureCallback);
      } else {
        if (variantDataUpdate.certificate) {
          variants.updateWithFormData(params, variantDataUpdate, successCallback, failureCallback);
        } else {
          variants.patch(params, { name: variant.name, description: variant.description}, successCallback, failureCallback);
        }
      }
    });
  };

  $scope.removeVariant = function (variant) {
    var modalInstance = show(variant, 'remove-variant.html');
    modalInstance.result.then(function (result) {
      var params = $.extend({}, {
        appId: $scope.application.pushApplicationID,
        variantType: result.variant.type,
        variantId: result.variant.variantID
      });
      variants.remove(params, function () {
        var osVariants = $scope.application.variants;
        osVariants.splice(osVariants.indexOf(variant), 1);
        Notifications.success('Successfully removed variant');
      }, function () {
        Notifications.error('Something went wrong...');
      });
    });
  };

  $scope.renewMasterSecret = function () {
    var modalInstance = show(null, 'renew-secret.html');
    modalInstance.result.then(function () {
      var app = $scope.application;
      pushApplication.reset({appId: app.pushApplicationID}, function (application) {
        $scope.application.masterSecret = application.masterSecret;
        Notifications.success('Successfully renewed master secret for "' + app.name + '"');
      });
    });
  };

  /*
   * PRIVATE FUNCTIONS
   */

  function modalController($scope, $modalInstance, variant) {
    $scope.variant = variant;

    if (!$scope.variant) {
      $scope.variant = {};
    }
    $scope.variant.certificates = [];

    $scope.ok = function (variant) {
      $modalInstance.close({
        variant: variant
      });
    };

    $scope.cancel = function () {
      $modalInstance.dismiss('cancel');
    };
  }

  function show(variant, template) {
    return $modal.open({
      templateUrl: 'views/dialogs/' + template,
      controller: modalController,
      resolve: {
        variant: function () {
          return variant;
        }
      }
    });
  }

  function variantProperties(variant) {
    var properties = ['name', 'description'], result = {};
    switch (variant.type) {
    case 'android':
      properties = properties.concat(['projectNumber', 'googleKey']);
      break;
    case 'simplePush':
      properties = properties.concat([]);
      break;
    case 'chrome':
      properties = properties.concat(['clientId', 'clientSecret', 'refreshToken']);
      break;
    case 'ios':
      if (variant.certificates && variant.certificates.length) {
        variant.certificate = variant.certificates[0];
      }
      properties = properties.concat(['production', 'passphrase', 'certificate']);
      var formData = new FormData();
      properties.forEach(function (property) {
        formData.append(property, variant[property] || '');
      });
      return formData;
    default:
      Notifications.error('Unknown variant type ' + variantType);
    }

    properties.forEach(function (property) {
      result[property] = variant[property];
    });
    return result;
  }

});
<commit_msg>removed passing of variantType<commit_after>/*
 * JBoss, Home of Professional Open Source
 * Copyright Red Hat, Inc., and individual contributors.
 *
 * 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.
 */
'use strict';

angular.module('upsConsole').controller('DetailController',
  function($rootScope, $scope, $routeParams, $location, $modal, pushApplication, variants, Notifications, breadcrumbs, application, counts, ContextProvider) {

  /*
   * INITIALIZATION
   */
  $rootScope.application = application;
  $scope.counts = counts;
  breadcrumbs.generateBreadcrumbs();
  $scope.currentLocation = ContextProvider.contextPath();

  /*
   * PUBLIC METHODS
   */

  $scope.addVariant = function (variant) {
    var modalInstance = show(variant, 'create-variant.html');
    modalInstance.result.then(function (result) {
      var variantData = variantProperties(result.variant);
      var params = $.extend({}, {
        appId: $scope.application.pushApplicationID,
        variantType: result.variant.type
      });

      var createFunction = (variantData instanceof FormData) ? variants.createWithFormData : variants.create;

      createFunction(params, variantData, function (newVariant) {
        var length = application.variants.length;
        for (var i = 0; i < length; i++) {
          if (newVariant.type === application.variants[i].type) {
            break;
          }
        }
        $scope.application.variants.splice(i, 0, newVariant);
        Notifications.success('Successfully created variant');
      }, function () {
        Notifications.error('Something went wrong...');
      });
    });
  };

  $scope.editVariant = function (variant) {
    var modalInstance = show(variant, 'create-variant.html');
    modalInstance.result.then(function (result) {
      var variantDataUpdate = variantProperties(variant);
      var params = $.extend({}, {
        appId: $scope.application.pushApplicationID,
        variantType: result.variant.type,
        variantId: result.variant.variantID
      });

      var successCallback = function () {
        Notifications.success('Successfully modified variant');
      };
      var failureCallback = function () {
        Notifications.error('Something went wrong...');
      };

      if (variant.type !== 'ios') {
        variants.update(params, variantDataUpdate, successCallback, failureCallback);
      } else {
        if (variantDataUpdate.certificate) {
          variants.updateWithFormData(params, variantDataUpdate, successCallback, failureCallback);
        } else {
          variants.patch(params, { name: variant.name, description: variant.description}, successCallback, failureCallback);
        }
      }
    });
  };

  $scope.removeVariant = function (variant) {
    var modalInstance = show(variant, 'remove-variant.html');
    modalInstance.result.then(function (result) {
      var params = $.extend({}, {
        appId: $scope.application.pushApplicationID,
        variantType: result.variant.type,
        variantId: result.variant.variantID
      });
      variants.remove(params, function () {
        var osVariants = $scope.application.variants;
        osVariants.splice(osVariants.indexOf(variant), 1);
        Notifications.success('Successfully removed variant');
      }, function () {
        Notifications.error('Something went wrong...');
      });
    });
  };

  $scope.renewMasterSecret = function () {
    var modalInstance = show(null, 'renew-secret.html');
    modalInstance.result.then(function () {
      var app = $scope.application;
      pushApplication.reset({appId: app.pushApplicationID}, function (application) {
        $scope.application.masterSecret = application.masterSecret;
        Notifications.success('Successfully renewed master secret for "' + app.name + '"');
      });
    });
  };

  /*
   * PRIVATE FUNCTIONS
   */

  function modalController($scope, $modalInstance, variant) {
    $scope.variant = variant;

    if (!$scope.variant) {
      $scope.variant = {};
    }
    $scope.variant.certificates = [];

    $scope.ok = function (variant) {
      $modalInstance.close({
        variant: variant
      });
    };

    $scope.cancel = function () {
      $modalInstance.dismiss('cancel');
    };
  }

  function show(variant, template) {
    return $modal.open({
      templateUrl: 'views/dialogs/' + template,
      controller: modalController,
      resolve: {
        variant: function () {
          return variant;
        }
      }
    });
  }

  function variantProperties(variant) {
    var properties = ['name', 'description'], result = {};
    switch (variant.type) {
    case 'android':
      properties = properties.concat(['projectNumber', 'googleKey']);
      break;
    case 'simplePush':
      properties = properties.concat([]);
      break;
    case 'chrome':
      properties = properties.concat(['clientId', 'clientSecret', 'refreshToken']);
      break;
    case 'ios':
      if (variant.certificates && variant.certificates.length) {
        variant.certificate = variant.certificates[0];
      }
      properties = properties.concat(['production', 'passphrase', 'certificate']);
      var formData = new FormData();
      properties.forEach(function (property) {
        formData.append(property, variant[property] || '');
      });
      return formData;
    default:
      Notifications.error('Unknown variant type ' + variantType);
    }

    properties.forEach(function (property) {
      result[property] = variant[property];
    });
    return result;
  }

});
<|endoftext|>


<commit_before>/**
 * Created by Leo.H & MC.Gong on 2017/3/6.
 */

// This file is the main script file.
// This file is used to move the block.

/*-----------------------------keypressed Function---------------------------*/
	//keypressed function to move blocks
	function KeyPressed(event)
	{
			var code = event.which || event.keyCode;

			//Move Up
			if( code == 38 || code == 119)
			{
				UpMoving();
			}

			//Move Down
			if(code == 40 || code ==115)
			{
				DownMoving();
			}

			//Move Left
			if(code == 37 || code ==97)
			{
				LeftMoving();
			}

			//Move Right
			if(code == 49 || code ==100)
			{
				RightMoving();
			}
	}

/*-------------------------------Moving Function---------------------------*/
	// when up key pressed, run UpMoving
	/*
		move from BOTTOM to TOP
		if the top cell of the current cell is 0
			=> just move up
		if it can merge
			=> merge the cell to top and clean the current cell
				=> after the merge, check the top cell is 0
					=> if it is 0, move the cell the top UNTIL it move to the FINAL cell
	*/
	function UpMoving()
	{
		var show = false;
		for(var i = 0; i < 4; i++ ){
	        for( var j = 3;j > 0; j--){
	            if (BlockTable[j][i]!=0) {
	            	if (BlockTable[j-1][i] == 0){
	            		BlockTable[j-1][i] = BlockTable[j][i];
	            		BlockTable[j][i] = 0;
	            		if (j<3) {
	            			if (BlockTable[j+1][i] !=0){
		            			BlockTable[j][i]=BlockTable[j+1][i];
		            			BlockTable[j+1][i]=0;
	            			}
	            		}

	            		show = true;
	            	}else if (BlockTable[j][i] == BlockTable[j-1][i]){
	            		BlockTable[j-1][i] = 2*BlockTable[j][i];
	            		BlockTable[j][i] = 0;
	            		if (j>1){
		            		while (BlockTable[j-2][i] == 0){
		            			if (j<3){
		            				if (BlockTable[j+1][i] !=0){
		            					BlockTable[j][i]=BlockTable[j+1][i];
		            				}
		            			}

		            			BlockTable[j-2][i] = BlockTable[j-1][i];
		            			BlockTable[j-1][i] = 0;
		            			j--;
		            			if(j-2<0){
		            				break;
		            			}
		            		}
						}
	            		j--;
	            		show = true;
	            	}
	            }
	        }
	    }
	    if (show){
	    	afterMove();
	    }
	    print();
	}

	// when down key pressed, run DownMoving
	function DownMoving()
	{
		var show = false;
		for(var i = 0; i < 4; i++ ){
	        for( var j = 0;j < 3; j++){
	            if (BlockTable[j][i]!=0) {
	            	if (BlockTable[j+1][i] == 0){
	            		BlockTable[j+1][i] = BlockTable[j][i];
	            		BlockTable[j][i] = 0;
	            		if(j>0){
	            			if (BlockTable[j-1][i] !=0){
	            			BlockTable[j][i]=BlockTable[j-1][i];
	            			BlockTable[j-1][i]=0;
	            			}
	            		}

	            		show = true;
	            	}else if (BlockTable[j][i] == BlockTable[j+1][i]){
	            		BlockTable[j+1][i] = 2*BlockTable[j][i];
	            		BlockTable[j][i] = 0;
	            		if(j<3){
		            		while (BlockTable[j+2][i] == 0){
		            			if (j>0){
		            				if (BlockTable[j-1][i] !=0 ){
		            					BlockTable[j][i]=BlockTable[j-1][i];
		            				}
		            			}

		            			BlockTable[j+2][i] = BlockTable[j+1][i];
		            			BlockTable[j+1][i] = 0;
		            			j++;
		            			if(j+2>3){
		            				break;
		            			}
		            		}
	            		}
	            		j++;
	            		show = true;
	            	}
	            }
	        }
	    }
	    if (show){
	    	afterMove();
	    }
	    print();
	}

	// when left key pressed, run LeftMoving
	function LeftMoving()
	{
		var show = false;
		for(var j = 0; j < 4; j++ ){
	        for( var i = 3;i > 0; i--){
	            if (BlockTable[j][i]!=0) {
	            	if (BlockTable[j][i-1] == 0){
	            		BlockTable[j][i-1] = BlockTable[j][i];
	            		BlockTable[j][i] = 0;
	            		if(i<3){
	            			if (BlockTable[j][i+1] !=0){
	            				BlockTable[j][i]=BlockTable[j][i+1];
	            				BlockTable[j][i+1]=0;
	            			}
	            		}

	            		show = true;
	            	}else if (BlockTable[j][i] == BlockTable[j][i-1]){
	            		BlockTable[j][i-1] = 2*BlockTable[j][i];
	            		BlockTable[j][i] = 0;
	            		if (i>1){
		            		while (BlockTable[j][i-2] == 0){
		            			if(i<3){
		            				if (BlockTable[j][i+1] !=0 ){
		            					BlockTable[j][i]=BlockTable[j][i+1];
		            				}
		            			}

		            			BlockTable[j][i-2] = BlockTable[j][i-1];
		            			BlockTable[j][i-1] = 0;
		            			i--;
		            			if(i-2<0){
		            				break;
		            			}
		            		}
	            		}
	            		i--;
	            		show = true;
	            	}
	            }
	        }
	    }
	    if (show){
	    	afterMove();
	    }
	    print();
	}

	// when right key pressed, run RightMoving
	function RightMoving()
	{
		var show = false;
		for(var j = 0; j < 4; j++ ){
	        for( var i = 0;i < 3; i++){
	            if (BlockTable[j][i]!=0) {
	            	if (BlockTable[j][i+1] == 0){
	            		BlockTable[j][i+1] = BlockTable[j][i];
	            		BlockTable[j][i] = 0;
	            		if (i>0){
	            			if (BlockTable[j][i-1] !=0 ){
		            			BlockTable[j][i]=BlockTable[j][i-1];
		            			BlockTable[j][i-1]=0;
	            			}
	            		}

	            		show = true;
	            	}else if (BlockTable[j][i] == BlockTable[j][i+1]){
	            		BlockTable[j][i+1] = 2*BlockTable[j][i];
	            		BlockTable[j][i] = 0;
	            		if (i<3){
		            		while (BlockTable[j][i+2] == 0){
		            			if(i>0){
		            				if (BlockTable[j][i-1] !=0 ){
		            					BlockTable[j][i]=BlockTable[j][i-1];
		            				}
		            			}

		            			BlockTable[j][i+2] = BlockTable[j][i+1];
		            			BlockTable[j][i+1] = 0;
		            			i++;
		            			if(i>2){
		            				break;
		            			}
		            		}
	            		}
	            		i++;
	            		show = true;
	            	}
	            }
	        }
	    }
	    if (show){
	    	afterMove();
	    }
	    print();
	}

	function afterMove()
	{
		show();
		showValue(getRandomFreeCell(),getRandomNumber());
	}
/*-------------------------------Display Function---------------------------*/
	function getRandomNumber () {
		return Math.random() > 0.3 ? 2 : 4;
	};

	//generate a valid to store an random num created from getRandomNumber
	function getRandomFreeCell () {
		do{
			var count = 4;
			var RandColumn = Math.floor(Math.random() * count);
			var RandRow = Math.floor(Math.random() * count);
			if (BlockTable[RandRow][RandColumn] == 0){
				return "block"+RandRow+"-"+RandColumn;
			}
		}while(BlockTable[RandRow][RandColumn]!=0)
	}

	function print (){
		console.log(BlockTable);
	}<commit_msg>fixed issue #3 and #4<commit_after>/**
 * Created by Leo.H & MC.Gong on 2017/3/6.
 */

// This file is the main script file.
// This file is used to move the block.

/*-----------------------------keypressed Function---------------------------*/
	//keypressed function to move blocks
	function KeyPressed(event)
	{
			var code = event.which || event.keyCode;

			//Move Up
			if( code == 38 || code == 119)
			{
				UpMoving();
			}

			//Move Down
			if(code == 40 || code ==115)
			{
				DownMoving();
			}

			//Move Left
			if(code == 37 || code ==97)
			{
				LeftMoving();
			}

			//Move Right
			if(code == 49 || code ==100)
			{
				RightMoving();
			}
	}

/*-------------------------------Moving Function---------------------------*/
	// when up key pressed, run UpMoving
	/*
		move from BOTTOM to TOP
		if the top cell of the current cell is 0
			=> just move up
		if it can merge
			=> merge the cell to top and clean the current cell
				=> after the merge, check the top cell is 0
					=> if it is 0, move the cell the top UNTIL it move to the FINAL cell
	*/
	function UpMoving()
	{
		var show = false;
		for(var i = 0; i < 4; i++ ){
	        for( var j = 0;j <4; j++){
	        	if (BlockTable[j][i]==0){
	        		cancelUpZero(j,i);
	        		if(BlockTable[j][i] != 0){
	        			show = true;
	        		}
	        	}
	            if (BlockTable[j][i]!=0 && j>0) {
	            	if (BlockTable[j][i] == BlockTable[j-1][i]){
	            		BlockTable[j-1][i] = 2*BlockTable[j-1][i];
	            		BlockTable[j][i] = 0;
	            		for (var row=j;row<3;row++) {
	            			cancelUpZero(row,i);
	            		}
	            		j++;
	            		show = true;
	            	}
	            }
	        }
	    }
	    if (show){
	    	afterMove();
	    }
	}

	function cancelUpZero(j,i){
		var tempRow = j;
		while(BlockTable[j][i]==0 && tempRow <3){
		    BlockTable[j][i] = BlockTable[tempRow+1][i];
		    BlockTable[tempRow+1][i] = 0;
		    tempRow++;
		}
	}

	// when down key pressed, run DownMoving
	function DownMoving()
	{
		var show = false;
		for(var i = 0; i < 4; i++ ){
	        for( var j = 3;j >= 0; j--){
	        	if (BlockTable[j][i]==0){
	        		cancelDownZero (j,i);
	        		if(BlockTable[j][i] != 0){
	        			show = true;
	        		}
	        	}
	            if (BlockTable[j][i]!=0 && j<3) {
	            	if (BlockTable[j][i] == BlockTable[j+1][i]){
	            		BlockTable[j+1][i] = 2*BlockTable[j+1][i];
	            		BlockTable[j][i] = 0;
		        		for (var row=j;row>0;row--) {
	            			cancelDownZero(row,i);
	            		}
	            		j--;
	            		show = true;
	            	}
	            }
	        }
	    }
	    if (show){
	    	afterMove();
	    }
	}

	function cancelDownZero (j,i){
		var tempRow = j;
	    while(BlockTable[j][i]==0 && tempRow >0){
	        BlockTable[j][i] = BlockTable[tempRow-1][i];
	        BlockTable[tempRow-1][i] = 0;
	        tempRow--;
	    }
	}

	// when left key pressed, run LeftMoving
	function LeftMoving()
	{
		var show = false;
		for(var j = 0; j < 4; j++ ){
	        for( var i = 0;i <4; i++){
	        	if (BlockTable[j][i]==0){
	        		cancelLeftZero(j,i);
	        		if(BlockTable[j][i] != 0){
	        			show = true;
	        		}
	        	}
	            if (BlockTable[j][i]!=0 && i>0) {
					if (BlockTable[j][i] == BlockTable[j][i-1]){
	            		BlockTable[j][i-1] = 2*BlockTable[j][i-1];
	            		BlockTable[j][i] = 0;
	            		for (var col=i;col<3;col++) {
	            			cancelLeftZero(j,col);
	            		}
	            		i++;
	            		show = true;
	            	}
	            }
	        }
	    }
	    if (show){
	    	afterMove();
	    }
	}

	function cancelLeftZero(j,i){
		var tempcol = i;
	    while(BlockTable[j][i]==0 && tempcol <3){
	        BlockTable[j][i] = BlockTable[j][tempcol+1];
	        BlockTable[j][tempcol+1] = 0;
	        tempcol++;
	    }
	}

	// when right key pressed, run RightMoving
	function RightMoving()
	{
		var show = false;
		for(var j = 0; j < 4; j++ ){
	        for( var i = 3;i >= 0; i--){
	        	if (BlockTable[j][i]==0){
	        		cancelRightZero(j,i);
	        		if(BlockTable[j][i] != 0){
	        			show = true;
	        		}
	        	}
	            if (BlockTable[j][i]!=0 && i<3) {
	            	if (BlockTable[j][i] == BlockTable[j][i+1]){
	            		BlockTable[j][i+1] = 2*BlockTable[j][i+1];
	            		BlockTable[j][i] = 0;
	            		for (var col=i;col>0;col--) {
	            			cancelRightZero(j,col);
	            		}
	            		i--;
	            		show = true;
	            	}
	            }
	        }
	    }
	    if (show){
	    	afterMove();
	    }
	}

	function cancelRightZero(j,i){
		var tempcol = i;
	    while(BlockTable[j][i]==0 && tempcol >0){
	        BlockTable[j][i] = BlockTable[j][tempcol-1];
	        BlockTable[j][tempcol-1] = 0;
	        tempcol--;
	    }
	}

	function afterMove()
	{
		show();
		showValue(getRandomFreeCell(),getRandomNumber());
	}

/*-------------------------------Display Function---------------------------*/
	function getRandomNumber () {
		return Math.random() > 0.3 ? 2 : 4;
	};

	//generate a valid to store an random num created from getRandomNumber
	function getRandomFreeCell () {
		do{
			var count = 4;
			var RandColumn = Math.floor(Math.random() * count);
			var RandRow = Math.floor(Math.random() * count);
			if (BlockTable[RandRow][RandColumn] == 0){
				return "block"+RandRow+"-"+RandColumn;
			}
		}while(BlockTable[RandRow][RandColumn]!=0)
	}<|endoftext|>


<commit_before>var cluster = require("cluster");
var path = require("path");
var Message = require(path.join(__dirname, 'message'));
var Shared = require(path.join(__dirname, 'shared'));

var Worker = function(options){
  // The runtime context, from here, is from within the master process.

  var options = options || {};
  var priv = {
    onMessageHandler: options['onMessage'],
  };

  var attributes = {};
  var env = {
    'swap': options['shared']['swap'],
    'parent': process.pid,
  };
  attributes['process'] = cluster.fork(env);
  attributes['process'].on('message', priv.onMessageHandler);

  return Object.assign(attributes, {

    send: function(msg){
      this.process.send(msg); // send to our worker process
    },

  });

};

// The runtime context, from here, is from within a worker process..
if(require.main === module){
  // our file was called directly rather than req'd.
  var shared = new Shared({
    'swap': process.env.swap
  });

  process.on('message', function(msg){
    var message = msg['payload'];

    switch(message['type']){
      case 'action':

        var cxt = shared || message['arguments'] || this;
        ret = shared.get(message['id']).apply(cxt, message['arguments']);
        if (message.options.promise){
          var msg =  JSON.stringify({
            response: ret,
            promise: message.options.promise,
          });

          process.send(msg);
        }

        break;
      case 'ping':
        // do nothing?
        break;

    }
    if(msg['type'] == 'action'){
    }

  });

} else {
  // our file is loaded in a require(...) statement.
  module.exports = Worker;
}
<commit_msg>minor cleanup in worker<commit_after>var cluster = require("cluster");
var path = require("path");
var Message = require(path.join(__dirname, 'message'));
var Shared = require(path.join(__dirname, 'shared'));

var Worker = function(options){
  // The runtime context, from here, is from within the master process.

  var options = options || {};
  var priv = {
    onMessageHandler: options['onMessage'],
  };

  var attributes = {};
  var env = {
    'swap': options['shared']['swap'],
    'parent': process.pid,
  };
  attributes['process'] = cluster.fork(env);
  attributes['process'].on('message', priv.onMessageHandler);

  return Object.assign(attributes, {

    send: function(msg){
      this.process.send(msg); // send to our worker process
    },

  });

};

// The runtime context, from here, is from within a worker process..
if(require.main === module){
  // our file was called directly rather than req'd.
  var shared = new Shared({
    'swap': process.env.swap
  });

  process.on('message', function(msg){
    var message = msg['payload'];

    switch(message['type']){
      case 'action':

        var cxt = shared || message['arguments'] || this;
        func = shared.get(message['id'])

        ret = func.apply(cxt, message['arguments']);

        if (message.options.promise){
          var msg =  JSON.stringify({
            response: ret,
            promise: message.options.promise,
          });

          process.send(msg);
        }

        break;
      case 'ping':
        // do nothing?
        break;

    }
    if(msg['type'] == 'action'){
    }

  });

} else {
  // our file is loaded in a require(...) statement.
  module.exports = Worker;
}
<|endoftext|>


<commit_before>/*
 * Copyright 2013 The Polymer Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style
 * license that can be found in the LICENSE file.
 */

var cheerio = require('cheerio');
var cleancss = require('clean-css');
var fs = require('fs');
var path = require('path');
var uglify = require('uglify-js');
var url = require('url');

var constants = require('./constants.js');
var optparser = require('./optparser.js');
var pathresolver = require('./pathresolver');
var utils = require('./utils');
var setTextContent = utils.setTextContent;
var getTextContent = utils.getTextContent;

// NOTE: remove this when https://github.com/cheeriojs/dom-serializer/pull/11 is accepted
var render = require('dom-serializer');

var read = {};
var options = {};

var CHEERIO_READ = {
  decodeEntities: false
};

// validate options with boolean return
function setOptions(optHash, callback) {
  optparser.processOptions(optHash, function(err, o) {
    if (err) {
      return callback(err);
    }
    options = o;
    callback();
  });
}

function exclude(regexes, href) {
  return regexes.some(function(r) {
    return r.test(href);
  });
}

function excludeImport(href) {
  return exclude(options.excludes.imports, href);
}

function excludeScript(href) {
  return exclude(options.excludes.scripts, href);
}

function excludeStyle(href) {
  return exclude(options.excludes.styles, href);
}

function readFile(file) {
  var content = fs.readFileSync(file, 'utf8');
  return content.replace(/^\uFEFF/, '');
}

// inline relative linked stylesheets into ', CHEERIO_READ);
      // clone attributes
      styleDoc('style').attr(el.attr());
      // don't set href or rel on the ', CHEERIO_OPTIONS);
      // clone attributes
      styleDoc('style').attr(el.attr());
      // don't set href or rel on the


<commit_before>const dial = require("peer-dial");
const http = require('http');
const express = require('express');
const { spawn } = require('child_process');
const ipc = require('node-ipc');
ipc.config.id = 'screenCastDIAL';
ipc.config.retry = 1000;
const app = express();
const server = http.createServer(app);
const PORT = 8569;
// var PORT = 8080;
const MANUFACTURER = "Kevin Townsend";
const MODEL_NAME = "DIAL Server";
var child = null;

var apps = {
	"YouTube": {
		name: "YouTube",
		state: "stopped",
		allowStop: true,
		pid: null,
	    launch: function (launchData, config) {
	        var url = "http://www.youtube.com/tv?"+launchData;
	        child = spawn('npm', ['start', url, config.position, config.width, config.height], {
  				cwd: 'modules/MMM-Screencast'
			})
			child.stdout.on('data', function(data) {
			    console.log('screencast stdout: ' + data);
			});
			child.stderr.on('data', function(data) {
			    console.log('screencast stderr: ' + data);
			});
			child.on('close', function(code) {
			    console.log('closing code: ' + code);
			});
    	}
	},
	"Hulu": {
		name: "Hulu",
		state: "stopped",
		allowStop: true,
		pid: null,
	    launch: function (launchData, config) {
	    	console.log(launchData);
	  //       var url = "http://www.youtube.com/tv?"+launchData;
	  //       child = spawn('npm', ['start', url, config.position, config.width, config.height], {
  	// 			cwd: 'modules/MMM-Screencast'
			// })
			// child.stdout.on('data', function(data) {
			//     console.log('screencast stdout: ' + data);
			// });
			// child.stderr.on('data', function(data) {
			//     console.log('screencast stderr: ' + data);
			// });
			// child.on('close', function(code) {
			//     console.log('closing code: ' + code);
			// });
   //  	}
	}
};

var dialServer = new dial.Server({
	corsAllowOrigins: true,
	expressApp: app,
	port: PORT,
	prefix: "/dial",
	manufacturer: MANUFACTURER,
	modelName: MODEL_NAME,
	launchFunction: null,
	electronConfig: {},
	delegate: {
		getApp: function(appName){
			var app = apps[appName];
			return app;
		},

		launchApp: function(appName,lauchData,callback){
			var app = apps[appName];
			var pid = null;
			if (app) {
				app.pid = "run";
				app.state = "starting";
                app.launch(lauchData, dialServer.electronConfig);
                app.state = "running";
			}
			callback(app.pid);
		},

		stopApp: function(appName,pid,callback){
            console.log("Got request to stop", appName," with pid: ", pid);

			var app = apps[appName];
			if (app && app.pid == pid) {
				app.pid = null;
				app.state = "stopped";
				ipc.connectTo('screenCastWindow',() => {
    				ipc.of.screenCastWindow.on('connect',() => {
                		ipc.of.screenCastWindow.emit('quit');
            		});
            		ipc.of.screenCastWindow.on('quit', () => {
            			ipc.disconnect('screenCastWindow');
            		});
    			});
    			child = null;
				callback(true);
			}
			else {
				callback(false);
			}
		}
	}
});

var App = function() {
	this.config = {};
	this.server = http.createServer(app);

	this.start = function(config) {
		dialServer.electronConfig = config;
		this.server.listen(PORT,function(){
			dialServer.start();
			console.log("DIAL Server is running on PORT "+PORT);
		});
	};

};

module.exports = new App();
<commit_msg>Update DialServer.js<commit_after>const dial = require("peer-dial");
const http = require('http');
const express = require('express');
const { spawn } = require('child_process');
const ipc = require('node-ipc');
ipc.config.id = 'screenCastDIAL';
ipc.config.retry = 1000;
const app = express();
const server = http.createServer(app);
const PORT = 8569;
// var PORT = 8080;
const MANUFACTURER = "Kevin Townsend";
const MODEL_NAME = "DIAL Server";
var child = null;

var apps = {
	"YouTube": {
		name: "YouTube",
		state: "stopped",
		allowStop: true,
		pid: null,
	    launch: function (launchData, config) {
	        var url = "http://www.youtube.com/tv?"+launchData;
	        child = spawn('npm', ['start', url, config.position, config.width, config.height], {
  				cwd: 'modules/MMM-Screencast'
			})
			child.stdout.on('data', function(data) {
			    console.log('screencast stdout: ' + data);
			});
			child.stderr.on('data', function(data) {
			    console.log('screencast stderr: ' + data);
			});
			child.on('close', function(code) {
			    console.log('closing code: ' + code);
			});
    	}
	},
	"Hulu": {
		name: "Hulu",
		state: "stopped",
		allowStop: true,
		pid: null,
	    launch: function (launchData, config) {
	    	console.log(launchData);
	  //       var url = "http://www.youtube.com/tv?"+launchData;
	  //       child = spawn('npm', ['start', url, config.position, config.width, config.height], {
  	// 			cwd: 'modules/MMM-Screencast'
			// })
			// child.stdout.on('data', function(data) {
			//     console.log('screencast stdout: ' + data);
			// });
			// child.stderr.on('data', function(data) {
			//     console.log('screencast stderr: ' + data);
			// });
			// child.on('close', function(code) {
			//     console.log('closing code: ' + code);
			// });
     	}
	}
};

var dialServer = new dial.Server({
	corsAllowOrigins: true,
	expressApp: app,
	port: PORT,
	prefix: "/dial",
	manufacturer: MANUFACTURER,
	modelName: MODEL_NAME,
	launchFunction: null,
	electronConfig: {},
	delegate: {
		getApp: function(appName){
			var app = apps[appName];
			return app;
		},

		launchApp: function(appName,lauchData,callback){
			var app = apps[appName];
			var pid = null;
			if (app) {
				app.pid = "run";
				app.state = "starting";
                app.launch(lauchData, dialServer.electronConfig);
                app.state = "running";
			}
			callback(app.pid);
		},

		stopApp: function(appName,pid,callback){
            console.log("Got request to stop", appName," with pid: ", pid);

			var app = apps[appName];
			if (app && app.pid == pid) {
				app.pid = null;
				app.state = "stopped";
				ipc.connectTo('screenCastWindow',() => {
    				ipc.of.screenCastWindow.on('connect',() => {
                		ipc.of.screenCastWindow.emit('quit');
            		});
            		ipc.of.screenCastWindow.on('quit', () => {
            			ipc.disconnect('screenCastWindow');
            		});
    			});
    			child = null;
				callback(true);
			}
			else {
				callback(false);
			}
		}
	}
});

var App = function() {
	this.config = {};
	this.server = http.createServer(app);

	this.start = function(config) {
		dialServer.electronConfig = config;
		this.server.listen(PORT,function(){
			dialServer.start();
			console.log("DIAL Server is running on PORT "+PORT);
		});
	};

};

module.exports = new App();
<|endoftext|>


<commit_before>describe("incremental content builder", function(){

   it('fires path found when root object opens', function() {

      expect(

         aContentBuilder()
            .receivingEvent('onopenobject')

      ).toHaveFired(

         TYPE_PATH
      ,  anAscentContaining(
            {key:ROOT_PATH, node:{}}
         )

      )
   })

   it('fires path found after key is found in root object', function() {
      // above test, plus some extra events from clarinet

      expect(

         aContentBuilder()
            .receivingEvent('onopenobject')
            .receivingEvent('onkey', 'flavour')

      ).toHaveFired(
          TYPE_PATH
       ,  anAscentContaining(
             {key:ROOT_PATH, node:{flavour:undefined}}
          ,  {key:'flavour', node:undefined}
          )
      )

   })

   it('fires path found if key is found at same time as root object', function() {
      // above test, plus some extra events from clarinet

      expect(

         aContentBuilder()
            .receivingEvent('onopenobject', 'flavour')
      ).toHaveFired(
          TYPE_PATH
       ,  anAscentContaining(
             {key:ROOT_PATH, node:{flavour:undefined}}
          ,  {key:'flavour', node:undefined}
          )
      )

   })

   it('fires node found after value is found for that key', function() {

      expect(

         aContentBuilder()
            .receivingEvent('onopenobject')
            .receivingEvent('onkey'    ,  'flavour')
            .receivingEvent('onvalue'  ,  'strawberry')

      ).toHaveFired(
         TYPE_NODE
      ,  anAscentContaining(
            {key:ROOT_PATH, node:{flavour:'strawberry'}}
         ,  {key:'flavour', node:'strawberry'}
         )
      )

   })

   it('fires node found after root object closes', function() {

      expect(

         aContentBuilder()
            .receivingEvent('onopenobject')
            .receivingEvent('onkey', 'flavour')
            .receivingEvent('onvalue', 'strawberry')
            .receivingEvent('oncloseobject')

      ).toHaveFired(
         TYPE_NODE
      ,  anAscentContaining(
            {key:ROOT_PATH, node:{flavour:'strawberry'}}
         )
      )

   })

   it('provides numeric paths for first array element', function() {

      expect(

         aContentBuilder()
            .receivingEvent('onopenobject')
            .receivingEvent('onkey', 'alphabet')
            .receivingEvent('onopenarray')
            .receivingEvent('onvalue', 'a')

      ).toHaveFired(
         TYPE_PATH
         , anAscentContaining(
               {key:ROOT_PATH,  node:{'alphabet':['a']}    }
            ,  {key:'alphabet', node:['a']                 }
            ,  {key:0,          node:'a'                   }
         )
      );

   })

   it('provides numeric paths for second array element', function() {

      expect(

         aContentBuilder()
            .receivingEvent('onopenobject')
            .receivingEvent('onkey', 'alphabet')
            .receivingEvent('onopenarray')
            .receivingEvent('onvalue', 'a')
            .receivingEvent('onvalue', 'b')

      ).toHaveFired(
         TYPE_PATH
         ,  anAscentContaining(
            {key:ROOT_PATH,  node:{'alphabet':['a','b']}   }
            , {key:'alphabet', node:['a','b']                }
            , {key:1,          node:'b'                      }
         )
      )

   })

   it('provides nodes for first array element', function() {

      expect(

         aContentBuilder()
            .receivingEvent('onopenobject')
            .receivingEvent('onkey'    ,  'alphabet')
            .receivingEvent('onopenarray')
            .receivingEvent('onvalue'    ,  'a')

      ).toHaveFired(
         TYPE_NODE
      ,  anAscentContaining(
            {key:ROOT_PATH,      node:{'alphabet':['a']} }
         ,  {key:'alphabet',     node:['a']              }
         ,  {key:0,              node:'a'                }
         )
      )

   })

   function aContentBuilder() {
      return new IncrementalContentBuilderAsserter( {}, sinon.stub() );
   }

   function IncrementalContentBuilderAsserter( clarinetStub, notifyStub ){

      this._clarinetStub = clarinetStub;
      this._notifyStub = notifyStub;
      this._subject = incrementalContentBuilder(clarinetStub, notifyStub);
   }

   IncrementalContentBuilderAsserter.prototype.receivingEvent = function(fnName /* args */){

      var args = Array.prototype.slice.call(arguments, 1);

      this._clarinetStub[fnName].apply( undefined, args );
      return this;
   };

   beforeEach(function(){

      this.addMatchers({
         toHaveFired: function( eventName, expectedAscent ){

            var asserter = this.actual;
            var notifyStub = asserter._notifyStub;

            var ascentMatch = sinon.match(function ( foundAscent ) {

               function matches( expect, found ) {
                  if( !expect && !found ) {
                     return true;
                  }

                  if( !expect || !found ) {
                     // Both not empty, but one is. Inequal length.
                     return false;
                  }

                  if( head(expect).key != head(found).key ) {
                     // keys inequal
                     return false;
                  }

                  if( JSON.stringify( head(expect).node ) != JSON.stringify( head(found).node ) ) {
                     // nodes inequal
                     return false;
                  }

                  return matches(tail(expect), tail(found));
               }

               return matches(expectedAscent, foundAscent);

            }, 'ascent match');

            this.message = function(){
               if( !notifyStub.called ) {
                  return 'no events have been fired at all';
               }

               function reportCall(eventName, ascentList) {

                  var argArray = listAsArray(ascentList);

                  var toJson = JSON.stringify.bind(JSON);

                  return 'type:' + eventName + ', ascent:[' + argArray.map(toJson).join(',    \t') + ']';
               }

               function reportArgs(args){
                  return reportCall(args[0], args[1]);
               }

               return   'expected a call with : \t' + reportCall(eventName, expectedAscent) +
                        '\n' +
                        'latest call had :      \t' + reportArgs(notifyStub.lastCall.args) +
                        '\n' +
                        'all calls were :' +
                        '\n                     \t' +
                        notifyStub.args.map( reportArgs ).join('\n                     \t')
            };

            return notifyStub.calledWithMatch( eventName, ascentMatch );
         }

      });
   });

   IncrementalContentBuilderAsserter.prototype.toHaveFired = function( eventName, expectedAscent ) {

      var ascentMatch = sinon.match(function ( foundAscent ) {

         function matches( expect, found ) {
            if( !expect && !found ) {
               return true;
            }

            if( !expect || !found ) {
               // Both not empty, but one is. Inequal length.
               return false;
            }

            if( head(expect).key != head(found).key ) {
               // keys inequal
               return false;
            }

            if( JSON.stringify( head(expect).node ) != JSON.stringify( head(found).node ) ) {
               // nodes inequal
               return false;
            }

            return matches(tail(expect), tail(found));
         }

         return matches(expectedAscent, foundAscent);

      }, 'ascent match');

      function reportCall(eventName, ascentList) {

         var argArray = listAsArray(ascentList);

         var toJson = JSON.stringify.bind(JSON);

         return 'type:' + eventName + ', ascent:[' + argArray.map(toJson).join(',    \t') + ']';
      }

      function reportArgs(args){
         return reportCall(args[0], args[1]);
      }

      if( !this._notifyStub.called ) {
         fail('notify has not been called');
      }

      if( !this._notifyStub.calledWithMatch( eventName, ascentMatch ) ) {

         fail(
            '\n' +
            'expected a call with : \t' + reportCall(eventName, expectedAscent) +
            '\n' +
            'latest call had :      \t' + reportArgs(this._notifyStub.lastCall.args) +
            '\n' +
            'all calls were :' +
            '\n                     \t' +
            this._notifyStub.args.map( reportArgs ).join('\n                     \t')
         );
      }
      return this;
   };

   function anAscentContaining ( /* descriptors */ ) {

      var ascentArray = Array.prototype.slice.call(arguments),
          ascentList = emptyList;

      ascentArray.forEach( function(ascentNode){
         ascentList = cons(ascentNode, ascentList);
      });

      return ascentList;
   }

});<commit_msg>remove unused code<commit_after>describe("incremental content builder", function(){

   it('fires path found when root object opens', function() {

      expect(

         aContentBuilder()
            .receivingEvent('onopenobject')

      ).toHaveFired(

         TYPE_PATH
      ,  anAscentContaining(
            {key:ROOT_PATH, node:{}}
         )

      )
   })

   it('fires path found after key is found in root object', function() {
      // above test, plus some extra events from clarinet

      expect(

         aContentBuilder()
            .receivingEvent('onopenobject')
            .receivingEvent('onkey', 'flavour')

      ).toHaveFired(
          TYPE_PATH
       ,  anAscentContaining(
             {key:ROOT_PATH, node:{flavour:undefined}}
          ,  {key:'flavour', node:undefined}
          )
      )

   })

   it('fires path found if key is found at same time as root object', function() {
      // above test, plus some extra events from clarinet

      expect(

         aContentBuilder()
            .receivingEvent('onopenobject', 'flavour')
      ).toHaveFired(
          TYPE_PATH
       ,  anAscentContaining(
             {key:ROOT_PATH, node:{flavour:undefined}}
          ,  {key:'flavour', node:undefined}
          )
      )

   })

   it('fires node found after value is found for that key', function() {

      expect(

         aContentBuilder()
            .receivingEvent('onopenobject')
            .receivingEvent('onkey'    ,  'flavour')
            .receivingEvent('onvalue'  ,  'strawberry')

      ).toHaveFired(
         TYPE_NODE
      ,  anAscentContaining(
            {key:ROOT_PATH, node:{flavour:'strawberry'}}
         ,  {key:'flavour', node:'strawberry'}
         )
      )

   })

   it('fires node found after root object closes', function() {

      expect(

         aContentBuilder()
            .receivingEvent('onopenobject')
            .receivingEvent('onkey', 'flavour')
            .receivingEvent('onvalue', 'strawberry')
            .receivingEvent('oncloseobject')

      ).toHaveFired(
         TYPE_NODE
      ,  anAscentContaining(
            {key:ROOT_PATH, node:{flavour:'strawberry'}}
         )
      )

   })

   it('provides numeric paths for first array element', function() {

      expect(

         aContentBuilder()
            .receivingEvent('onopenobject')
            .receivingEvent('onkey', 'alphabet')
            .receivingEvent('onopenarray')
            .receivingEvent('onvalue', 'a')

      ).toHaveFired(
         TYPE_PATH
         , anAscentContaining(
               {key:ROOT_PATH,  node:{'alphabet':['a']}    }
            ,  {key:'alphabet', node:['a']                 }
            ,  {key:0,          node:'a'                   }
         )
      );

   })

   it('provides numeric paths for second array element', function() {

      expect(

         aContentBuilder()
            .receivingEvent('onopenobject')
            .receivingEvent('onkey', 'alphabet')
            .receivingEvent('onopenarray')
            .receivingEvent('onvalue', 'a')
            .receivingEvent('onvalue', 'b')

      ).toHaveFired(
         TYPE_PATH
         ,  anAscentContaining(
            {key:ROOT_PATH,  node:{'alphabet':['a','b']}   }
            , {key:'alphabet', node:['a','b']                }
            , {key:1,          node:'b'                      }
         )
      )

   })

   it('provides nodes for first array element', function() {

      expect(

         aContentBuilder()
            .receivingEvent('onopenobject')
            .receivingEvent('onkey'    ,  'alphabet')
            .receivingEvent('onopenarray')
            .receivingEvent('onvalue'    ,  'a')

      ).toHaveFired(
         TYPE_NODE
      ,  anAscentContaining(
            {key:ROOT_PATH,      node:{'alphabet':['a']} }
         ,  {key:'alphabet',     node:['a']              }
         ,  {key:0,              node:'a'                }
         )
      )

   })

   function aContentBuilder() {
      return new IncrementalContentBuilderAsserter( {}, sinon.stub() );
   }

   function IncrementalContentBuilderAsserter( clarinetStub, notifyStub ){

      this._clarinetStub = clarinetStub;
      this._notifyStub = notifyStub;
      this._subject = incrementalContentBuilder(clarinetStub, notifyStub);
   }

   IncrementalContentBuilderAsserter.prototype.receivingEvent = function(fnName /* args */){

      var args = Array.prototype.slice.call(arguments, 1);

      this._clarinetStub[fnName].apply( undefined, args );
      return this;
   };

   beforeEach(function(){

      this.addMatchers({
         toHaveFired: function( eventName, expectedAscent ){

            var asserter = this.actual;
            var notifyStub = asserter._notifyStub;

            var ascentMatch = sinon.match(function ( foundAscent ) {

               function matches( expect, found ) {
                  if( !expect && !found ) {
                     return true;
                  }

                  if( !expect || !found ) {
                     // Both not empty, but one is. Inequal length.
                     return false;
                  }

                  if( head(expect).key != head(found).key ) {
                     // keys inequal
                     return false;
                  }

                  if( JSON.stringify( head(expect).node ) != JSON.stringify( head(found).node ) ) {
                     // nodes inequal
                     return false;
                  }

                  return matches(tail(expect), tail(found));
               }

               return matches(expectedAscent, foundAscent);

            }, 'ascent match');

            this.message = function(){
               if( !notifyStub.called ) {
                  return 'no events have been fired at all';
               }

               function reportCall(eventName, ascentList) {

                  var argArray = listAsArray(ascentList);

                  var toJson = JSON.stringify.bind(JSON);

                  return 'type:' + eventName + ', ascent:[' + argArray.map(toJson).join(',    \t') + ']';
               }

               function reportArgs(args){
                  return reportCall(args[0], args[1]);
               }

               return   'expected a call with : \t' + reportCall(eventName, expectedAscent) +
                        '\n' +
                        'latest call had :      \t' + reportArgs(notifyStub.lastCall.args) +
                        '\n' +
                        'all calls were :' +
                        '\n                     \t' +
                        notifyStub.args.map( reportArgs ).join('\n                     \t')
            };

            return notifyStub.calledWithMatch( eventName, ascentMatch );
         }

      });
   });

   function anAscentContaining ( /* descriptors */ ) {

      var ascentArray = Array.prototype.slice.call(arguments),
          ascentList = emptyList;

      ascentArray.forEach( function(ascentNode){
         ascentList = cons(ascentNode, ascentList);
      });

      return ascentList;
   }

});<|endoftext|>


<commit_before>(function() {
	'use strict';
	var fluentd = require(__dirname + '/fluentd.js'),
		cluster = require('cluster');

	function Worker(worker, config) {
		this.pid = worker.process.pid;
		this.id = worker.id;
		this.startTime = new Date();

		this.values = {};
		this.counters = {};
		this.stacks = {};
		this.stackConfig = {};
		this.throughputs = {};
		this.throughputsBuffer = {};
		this.eventListeners = {};

		this.startMemory = process.memoryUsage();
		this.fallBehind = 0;

		this.config = config;

		this.measureFallBehind();

		this.workerMessageListener = worker.on('message', (function workerMessageListenerHandler(msg) {
			if (!msg['~kardia']) {
				return;
			}

			if (msg['~kardia'].cmd && msg['~kardia'].args && this[msg['~kardia'].cmd]) {
				this[msg['~kardia'].cmd].apply(this, msg['~kardia'].args);
			}
		}).bind(this));

		return this;
	}

	Worker.prototype.set = function(name, value) {
		this.values[name] = value;
	};

	Worker.prototype.unset = function(name, value) {
		delete this.values[name];
	};

	Worker.prototype.increment = function(name, value) {
		this.counters[name] = (this.counters[name] || 0) + (Number(value) || 1);
	};

	Worker.prototype.decrement = function(name, value) {
		this.increment(name, -(Number(value) || 1));
	};

	Worker.prototype.throughput = function(name) {
		if (cluster.isWorker && process.send) {
			process.send({ '~kardia': { cmd: 'throughput', args: [].slice.call(arguments) } });
			return;
		}

		if (!this.throughputsBuffer[name]) {
			this.throughputsBuffer[name] = 0;
		}

		this.throughputsBuffer[name]++;

		// the throughput calculation interval time in seconds (will likely be configurable in the future):
		if (!this.throughputCalculationStep) {
			this.throughputCalculationStep = 30;
		}

		if (!this.throughputInterval && Object.keys(this.throughputsBuffer).length > 0) {

			// set up the appropriate interval to calculate throughput rates per sec, minute, hour
			this.throughputInterval = setInterval((function() {
				Object.keys(this.throughputsBuffer).forEach((function(key) {
					if (!this.throughputs[key]) {
						this.throughputs[key] = {};
					}
					if (!this.throughputs[key][this.throughputCalculationStep]) {
						this.throughputs[key][this.throughputCalculationStep] = {};
					}
					var x = this.throughputs[key][this.throughputCalculationStep];
					x.sec = parseInt((this.throughputsBuffer[key] / this.throughputCalculationStep).toFixed(2), 10);
					x.min = parseInt((this.throughputsBuffer[key] * (60 / this.throughputCalculationStep)).toFixed(2), 10);
					x.hour = parseInt((this.throughputsBuffer[key] * (3600 / this.throughputCalculationStep)).toFixed(2), 10);
					this.throughputsBuffer[key] = 0;

				}).bind(this));
				this.emit('throughputIntervalRun');

			}).bind(this), 1000 * this.throughputCalculationStep);
		}
	};

	Worker.prototype.clearThroughput = function(name) {
		if (cluster.isWorker && process.send) {
			process.send({ '~kardia': { cmd: 'clearThroughput', args: [].slice.call(arguments) } });
			return;
		}
		delete this.throughputsBuffer[name];
		delete this.throughput[name];

		if (Object.keys(this.throughputInterval).length === 0 && this.throughputInterval) {
			clearInterval(this.throughputInterval);
		}
	};

	Worker.prototype.startStack = function(name, size) {
		this.stacks[name] = [];
		this.stackConfig[name] = { size: Number(size) || 15 };
	};

	Worker.prototype.stack = function(name, value) {
		if (!this.stacks[name]) this.startStack(name);
		this.stacks[name].unshift({ time: new Date().toISOString(), value: value });
		this.stacks[name] = this.stacks[name].splice(0, this.stackConfig[name].size);
	};

	Worker.prototype.stopStack = function(name) {
		delete this.stacks[name];
		delete this.stackConfig[name];
	};

	Worker.prototype.generateStatus = function() {
		var date = new Date();
		return {
			pid: this.pid,
			startTime: this.startTime,
			uptime: Math.floor((date.getTime() - this.startTime.getTime())/1000),
			values: this.values,
			stacks: this.stacks,
			throughput: this.stacks,
			counters: this.counters,
			fallBehind: this.fallBehind
		};
	};

	Worker.prototype.emit = function(eventName, data) {
		if (this.eventListeners[eventName]) {
			this.eventListeners[eventName].forEach(function(listener) {
				listener(data);
			});
		}
	};

	Worker.prototype.on = function(eventName, handler) {
		if (!this.eventListeners[eventName]) {
			this.eventListeners[eventName] = [];
		}

		this.eventListeners[eventName].push(handler);

		return true;
	};

	Worker.prototype.removeListener = function(eventName, handler) {
		if (this.eventListeners[eventName]) {
			this.eventListeners[eventName].splice(this.eventListeners[eventName].indexOf(handler));
		}

		return true;
	};

	Worker.prototype.measureFallBehind = function() {
		var that = this,
			time = process.hrtime();

		setTimeout(function() {
			var diff = process.hrtime(time);

			that.fallBehind = ((diff[0] - 1) * 1e9 + diff[1]) / 1e6;
			that.measureFallBehind();
		}, 1000).unref();
	};

	Worker.prototype.sendCounterToFluentd = function(name, value) {
		fluentd.incrementCounter(this.config, name, value);
	};

	module.exports = Worker;
})();<commit_msg>fix throughputs passing to worker.js status block<commit_after>(function() {
	'use strict';
	var fluentd = require(__dirname + '/fluentd.js'),
		cluster = require('cluster');

	function Worker(worker, config) {
		this.pid = worker.process.pid;
		this.id = worker.id;
		this.startTime = new Date();

		this.values = {};
		this.counters = {};
		this.stacks = {};
		this.stackConfig = {};
		this.throughputs = {};
		this.throughputsBuffer = {};
		this.eventListeners = {};

		this.startMemory = process.memoryUsage();
		this.fallBehind = 0;

		this.config = config;

		this.measureFallBehind();

		this.workerMessageListener = worker.on('message', (function workerMessageListenerHandler(msg) {
			if (!msg['~kardia']) {
				return;
			}

			if (msg['~kardia'].cmd && msg['~kardia'].args && this[msg['~kardia'].cmd]) {
				this[msg['~kardia'].cmd].apply(this, msg['~kardia'].args);
			}
		}).bind(this));

		return this;
	}

	Worker.prototype.set = function(name, value) {
		this.values[name] = value;
	};

	Worker.prototype.unset = function(name, value) {
		delete this.values[name];
	};

	Worker.prototype.increment = function(name, value) {
		this.counters[name] = (this.counters[name] || 0) + (Number(value) || 1);
	};

	Worker.prototype.decrement = function(name, value) {
		this.increment(name, -(Number(value) || 1));
	};

	Worker.prototype.throughput = function(name) {
		if (cluster.isWorker && process.send) {
			process.send({ '~kardia': { cmd: 'throughput', args: [].slice.call(arguments) } });
			return;
		}

		if (!this.throughputsBuffer[name]) {
			this.throughputsBuffer[name] = 0;
		}

		this.throughputsBuffer[name]++;

		// the throughput calculation interval time in seconds (will likely be configurable in the future):
		if (!this.throughputCalculationStep) {
			this.throughputCalculationStep = 30;
		}

		if (!this.throughputInterval && Object.keys(this.throughputsBuffer).length > 0) {

			// set up the appropriate interval to calculate throughput rates per sec, minute, hour
			this.throughputInterval = setInterval((function() {
				Object.keys(this.throughputsBuffer).forEach((function(key) {
					if (!this.throughputs[key]) {
						this.throughputs[key] = {};
					}
					if (!this.throughputs[key][this.throughputCalculationStep]) {
						this.throughputs[key][this.throughputCalculationStep] = {};
					}
					var x = this.throughputs[key][this.throughputCalculationStep];
					x.sec = parseInt((this.throughputsBuffer[key] / this.throughputCalculationStep).toFixed(2), 10);
					x.min = parseInt((this.throughputsBuffer[key] * (60 / this.throughputCalculationStep)).toFixed(2), 10);
					x.hour = parseInt((this.throughputsBuffer[key] * (3600 / this.throughputCalculationStep)).toFixed(2), 10);
					this.throughputsBuffer[key] = 0;

				}).bind(this));
				this.emit('throughputIntervalRun');

			}).bind(this), 1000 * this.throughputCalculationStep);
		}
	};

	Worker.prototype.clearThroughput = function(name) {
		if (cluster.isWorker && process.send) {
			process.send({ '~kardia': { cmd: 'clearThroughput', args: [].slice.call(arguments) } });
			return;
		}
		delete this.throughputsBuffer[name];
		delete this.throughput[name];

		if (Object.keys(this.throughputInterval).length === 0 && this.throughputInterval) {
			clearInterval(this.throughputInterval);
		}
	};

	Worker.prototype.startStack = function(name, size) {
		this.stacks[name] = [];
		this.stackConfig[name] = { size: Number(size) || 15 };
	};

	Worker.prototype.stack = function(name, value) {
		if (!this.stacks[name]) this.startStack(name);
		this.stacks[name].unshift({ time: new Date().toISOString(), value: value });
		this.stacks[name] = this.stacks[name].splice(0, this.stackConfig[name].size);
	};

	Worker.prototype.stopStack = function(name) {
		delete this.stacks[name];
		delete this.stackConfig[name];
	};

	Worker.prototype.generateStatus = function() {
		var date = new Date();
		return {
			pid: this.pid,
			startTime: this.startTime,
			uptime: Math.floor((date.getTime() - this.startTime.getTime())/1000),
			values: this.values,
			stacks: this.stacks,
			throughput: this.throughputs,
			counters: this.counters,
			fallBehind: this.fallBehind
		};
	};

	Worker.prototype.emit = function(eventName, data) {
		if (this.eventListeners[eventName]) {
			this.eventListeners[eventName].forEach(function(listener) {
				listener(data);
			});
		}
	};

	Worker.prototype.on = function(eventName, handler) {
		if (!this.eventListeners[eventName]) {
			this.eventListeners[eventName] = [];
		}

		this.eventListeners[eventName].push(handler);

		return true;
	};

	Worker.prototype.removeListener = function(eventName, handler) {
		if (this.eventListeners[eventName]) {
			this.eventListeners[eventName].splice(this.eventListeners[eventName].indexOf(handler));
		}

		return true;
	};

	Worker.prototype.measureFallBehind = function() {
		var that = this,
			time = process.hrtime();

		setTimeout(function() {
			var diff = process.hrtime(time);

			that.fallBehind = ((diff[0] - 1) * 1e9 + diff[1]) / 1e6;
			that.measureFallBehind();
		}, 1000).unref();
	};

	Worker.prototype.sendCounterToFluentd = function(name, value) {
		fluentd.incrementCounter(this.config, name, value);
	};

	module.exports = Worker;
})();<|endoftext|>


<commit_before>'use strict';

const _ = require('lodash');
const path = require('path');
const ipc = require('node-ipc');
const Managed = require('./managed.js');
const DBWriter = require('./dbwrite.js');

// Config
const appcfg = _.defaultsDeep(
	{},
	require('../cfg/user.json'),
	require('../cfg/config.json')
);

// IPC setup
const mgd = new Managed(
	{waitforgo: true},
	logfn.bind(null, 'log'),
	logfn.bind(null, 'err')
);
_.assign(ipc.config, {
	appspace: 'twarc',
	socketRoot: path.resolve(appcfg.sockpath) + path.sep,
	id: process.env.childname,
	retry: 250,
	silent: true
});

// DB
const dbw = new DBWriter({
	user_id_str: appcfg.user.id_str,
	path: appcfg.dbpath,
	noSync: true
}, mgd.err.bind(mgd));
const dblog = true;

// Signal handlers
process.on('SIGINT', () => {});
process.on('SIGTERM', () => {
	mgd.log('Caught signal, exiting...')
	.then(() => {
		// Close IPC server & open sockets
		ipc.server.stop();
		ipc.server.sockets.forEach(s => s.end());

		// Close DBs
		dbw.close();

		return 0;
	}).catch(e => {
		// First catch in case of close errors
		return mgd.err(e);
	}).catch(e => {
		// Second catch in case of log error
		console.error(e);
		return 1;
	}).then(code => {
		process.exitCode = code;
		process.disconnect();
	});
});

// Start server
ipc.serve(() => {
	ipc.server.on('connect', socket => socket.on('end', () => socket.end()));
	ipc.server.on('queue', (data, socket) => writefn('queue', data));
	ipc.server.on('user', (data, socket) => writefn('user', data));
	ipc.server.on('user_tweet', (data, socket) => writefn('user_tweet', data));
	ipc.server.on('other_tweet', (data, socket) => writefn('other_tweet', data));
	ipc.server.on('delete', (data, socket) => writefn('delete', data));
	ipc.server.on('favorite', (data, socket) => writefn('favorite', data));
	ipc.server.on('unfavorite', (data, socket) => writefn('unfavorite', data));
	mgd.go();
	// mgd.sendmsg('ready');
});
ipc.server.start();

// Misc funcs
function logfn (type, data) {
	if (data) {
		if (_.isError(data)) {
			data = _.toString(data.stack);
		}
		return mgd.sendmsg({type, data}).catch(e => console.log(e));
	}
	return Promise.resolve();
}

function writefn (type, data, nosync, silent) {
	let sync = false;
	let total = 0;

	function writeq (queue) {
		const types = ['user', 'user_tweet', 'other_tweet', 'delete', 'favorite', 'unfavorite'];
		let syncq = false;
		let count;

		if (dblog) {
			mgd.log(`Received queue of ${data.length} items`);
			count = {
				'user': 0,
				'user_tweet': 0,
				'other_tweet': 0,
				'delete': 0,
				'favorite': 0,
				'unfavorite': 0
			};
		}

		// Recursively call
		for (let i = 0; i < queue.length; i++) {
			let item = queue[i];
			if (_.has(item, 'type') && _.has(item, 'data')) {
				// Leave sync to end of queue, but sync if any write succeeds
				if (writefn(item.type, item.data, true, true)) {
					syncq = true;
					if (dblog) {
						count[item.type]++;
					}
				}
			}
		}

		if (dblog && syncq) {
			let counts = [];
			for (let name of types) {
				let num = count[name];
				if (num > 0) {
					total += num;
					counts.push(`${num} ${name}${num > 1 ? 's' : ''}`);
				}
			}
			if (counts.length > 0) {
				mgd.log(`Wrote queue of ${total} items (${counts.join(', ')})`);
			}
		}

		return syncq;
	}

	try {
		switch (type) {
			case 'queue':
				sync = writeq(data);
				break;
			case 'user':
				sync = dbw.writeuser(data);
				break;
			case 'user_tweet':
				sync = dbw.writetweet(data);
				break;
			case 'other_tweet':
				sync = dbw.writetweet(data);
				break;
			case 'delete':
				sync = dbw.deletetweet(data);
				break;
			case 'favorite':
				sync = dbw.writefav(data);
				break;
			case 'unfavorite':
				sync = dbw.deletefav(data);
				break;
		}
		if (dblog && !silent && sync && type !== 'queue') {
			mgd.log(`Wrote ${type}`);
		}
	}
	catch (e) {
		mgd.err(e);
	}

	if (sync && !nosync) {
		dbw.sync(err => {
			if (err) {
				mgd.err(err);
			}
			else if (dblog && !silent && total > 0) {
				mgd.log(`Synced ${total} items`);
			}
		});
	}

	return sync;
}<commit_msg>Instead of nosync in writer.js, share 1 txn for a whole queue of updates<commit_after>'use strict';

const _ = require('lodash');
const path = require('path');
const ipc = require('node-ipc');
const Managed = require('./managed.js');
const DBWriter = require('./dbwrite.js');

// Config
const appcfg = _.defaultsDeep(
	{},
	require('../cfg/user.json'),
	require('../cfg/config.json')
);

// IPC setup
const mgd = new Managed(
	{waitforgo: true},
	logfn.bind(null, 'log'),
	logfn.bind(null, 'err')
);
_.assign(ipc.config, {
	appspace: 'twarc',
	socketRoot: path.resolve(appcfg.sockpath) + path.sep,
	id: process.env.childname,
	retry: 250,
	silent: true
});

// DB
const dbw = new DBWriter({
	user_id_str: appcfg.user.id_str,
	path: appcfg.dbpath,
	// noSync: true
}, mgd.err.bind(mgd));
const dblog = true;

// Signal handlers
process.on('SIGINT', () => {});
process.on('SIGTERM', () => {
	mgd.log('Caught signal, exiting...')
	.then(() => {
		// Close IPC server & open sockets
		ipc.server.stop();
		ipc.server.sockets.forEach(s => s.end());

		// Close DBs
		dbw.close();

		return 0;
	}).catch(e => {
		// First catch in case of close errors
		return mgd.err(e);
	}).catch(e => {
		// Second catch in case of log error
		console.error(e);
		return 1;
	}).then(code => {
		process.exitCode = code;
		process.disconnect();
	});
});

// Start server
ipc.serve(() => {
	ipc.server.on('connect', socket => socket.on('end', () => socket.end()));
	ipc.server.on('queue', (data, socket) => writefn('queue', data));
	ipc.server.on('user', (data, socket) => writefn('user', data));
	ipc.server.on('user_tweet', (data, socket) => writefn('user_tweet', data));
	ipc.server.on('other_tweet', (data, socket) => writefn('other_tweet', data));
	ipc.server.on('delete', (data, socket) => writefn('delete', data));
	ipc.server.on('favorite', (data, socket) => writefn('favorite', data));
	ipc.server.on('unfavorite', (data, socket) => writefn('unfavorite', data));
	mgd.go();
	// mgd.sendmsg('ready');
});
ipc.server.start();

// Misc funcs
function logfn (type, data) {
	if (data) {
		if (_.isError(data)) {
			data = _.toString(data.stack);
		}
		return mgd.sendmsg({type, data}).catch(e => console.log(e));
	}
	return Promise.resolve();
}

function writefn (type, data, txn, silent) {
	let sync = false;
	let total = 0;

	function writeq (queue) {
		const types = ['user', 'user_tweet', 'other_tweet', 'delete', 'favorite', 'unfavorite'];
		let syncq = false;
		let count;

		if (dblog) {
			mgd.log(`Received queue of ${data.length} items`);
			count = {
				'user': 0,
				'user_tweet': 0,
				'other_tweet': 0,
				'delete': 0,
				'favorite': 0,
				'unfavorite': 0
			};
		}

		// Open transaction
		let qtxn = dbw.env.beginTxn();

		try {
			// Recursively call
			for (let i = 0; i < queue.length; i++) {
				let item = queue[i];
				if (_.has(item, 'type') && _.has(item, 'data')) {
					// Leave sync to end of queue, but sync if any write succeeds
					if (writefn(item.type, item.data, qtxn, true)) {
						syncq = true;
						if (dblog) {
							count[item.type]++;
						}
					}
				}
			}

			qtxn.commit();

			if (dblog) {
				if (syncq) {
					let counts = [];
					for (let name of types) {
						let num = count[name];
						if (num > 0) {
							total += num;
							counts.push(`${num} ${name}${num > 1 ? 's' : ''}`);
						}
					}
					mgd.log(`Wrote queue of ${total} items (${counts.join(', ')})`);
				}
				else {
					mgd.log(`All items in queue already processed`);
				}
			}
		}
		catch (e) {
			qtxn.abort();
			mgd.err(e);
			syncq = false;
		}

		return syncq;
	}

	try {
		switch (type) {
			case 'queue':
				sync = writeq(data);
				break;
			case 'user':
				sync = dbw.writeuser(data, txn);
				break;
			case 'user_tweet':
				sync = dbw.writetweet(data, txn);
				break;
			case 'other_tweet':
				sync = dbw.writetweet(data, txn);
				break;
			case 'delete':
				sync = dbw.deletetweet(data, txn);
				break;
			case 'favorite':
				sync = dbw.writefav(data, txn);
				break;
			case 'unfavorite':
				sync = dbw.deletefav(data, txn);
				break;
		}
		if (dblog && !silent && sync && type !== 'queue') {
			mgd.log(`Wrote ${type}`);
		}
	}
	catch (e) {
		mgd.err(e);
	}

	// if (sync && !nosync) {
	// 	dbw.sync(err => {
	// 		if (err) {
	// 			mgd.err(err);
	// 		}
	// 		else if (dblog && !silent && total > 0) {
	// 			mgd.log(`Synced ${total} items`);
	// 		}
	// 	});
	// }

	return sync;
}<|endoftext|>


<commit_before>var fs = require('fs');
var path = require('path');
var events = require('events');
var extend = require('extend');
var moment = require('moment');
var handlebars = require('handlebars');
var eventEmmiter = new events.EventEmitter();

var Document = require('./resource/document');
var Template = require('./resource/template');
var Widget = require('./resource/widget');
var Chunk = require('./resource/chunk');

/**
 * Default configuation
 * @api private
 *
 * @var {Object} defaultConfig
 */
var defaultConfig = {
  buildPath: 'build',
  srcPath: 'src',
  templatesDir: 'layouts',
  widgetsDir: 'widgets',
  pluginsDir: 'plugins',
  chunksDir: 'chunks',
  docsDir: 'docs',
  locale: 'en',
  siteName: 'ZenPad',
  siteUrl: 'http://localhost:8080/'
};

/**
 * Cache.
 * @api private
 *
 * @var {Object} cache
 */
var cache = {
  templates: {},
  widgets: {},
  chunks: {},
  docs: {}
};

/**
 * Create Engine instance.
 * @constructor
 */
function ZenPad(config) {

  this.env = 'default';
  this.config = extend(defaultConfig, config[this.env]);

  /**
   * Load plugins.
   */

  var pluginsPath = path.resolve(this.config.srcPath, this.config.pluginsDir);
  if (fs.existsSync(pluginsPath)) {
    var that = this;
    fs.readdirSync(pluginsPath).forEach(function(file) {
      require(path.resolve(pluginsPath, file))(that);
    });
  }

};

/**
 * Get document.
 * @api public
 *
 * @param {String} filePath
 * @return {Document}
 */
ZenPad.prototype.getDoc = function(filePath) {
  if (cache.docs[filePath]) {
    return cache.docs[filePath];
  }
  var docContent = fs.readFileSync(path.join(
    this.config.srcPath,
    this.config.docsDir,
    filePath
  ), 'utf-8');

  var doc = new Document(this, filePath, docContent);
  return cache.docs[filePath] = doc;
};

/**
 * Get documents.
 * @api public
 *
 * @param {String} dirPath
 * @param {Object} query
 * @return {Array}
 */
ZenPad.prototype.getDocs = function(dirPath, query) {
  var docs = this._readDocsDir(dirPath, query.depth);
  var result = [];

  for (var i=0, j=docs.length; i<j; i++) {
    var doc = this.getDoc(docs[i]);
    result.push(doc);
  }

  if (query.filter) {
    result = result.filter(query.filter);
  }

  return result;
};

/**
 * @api public
 * @param {String} url
 * @param {Object} data
 */
ZenPad.prototype.createDoc = function(url, data) {
  return new Document(this, url, data);
};

/**
 * Get widget.
 * @api public
 *
 * @param {String} filePath
 * @param {Object} params
 * @return {*}
 */
ZenPad.prototype.getWidget = function(filePath, params) {
  if (cache.widgets[filePath]) {
    var widget = this._widgets[filePath];
  } else {
    var requirePath = require.resolve('../../../' + path.join(
      this.config.srcPath,
      this.config.widgetsDir,
      filePath
    ));
    var widget = new Widget(this, require(requirePath));
    cache.widgets[requirePath] = widget;
  }
  return widget.run(params);
};

/**
 * Get chunk.
 * @api public
 *
 * @param {String} filePath
 * @param {Object} data
 * @return {String}
 */
ZenPad.prototype.getChunk = function(filePath, data) {
  if (cache.chunks[filePath]) {
    var chunk = cache.chunks[filePath];
  } else {
    var chunkContent = fs.readFileSync(path.join(
      this.config.srcPath,
      this.config.chunksDir,
      filePath + '.html'
    ), 'utf-8');
    var chunk = new Chunk(this, chunkContent);
    cache.chunks[filePath] = chunk;
  }
  return chunk.render(data);
};

/**
 * Render template.
 * @api public
 *
 * @param {String} filePath
 * @param {Object} data
 * @return {String}
 */
ZenPad.prototype.getTemplate = function(filePath, data) {
  if (cache.templates[filePath]) {
    var template = cache.templates[filePath];
  } else {
    var templateContent = fs.readFileSync(path.join(
      this.config.srcPath,
      this.config.templatesDir,
      filePath + '.html'
    ), 'utf-8');
    var template = new Template(this, templateContent);
    cache.templates[filePath] = template;
  }
  return template.render(data);
};

/**
 * Render string.
 * @public
 *
 * @param {String} source
 * @param {Object} data
 */
ZenPad.prototype.renderString = function(source, data) {
  return handlebars.compile(source)(data);
};

/**
 * Listen event.
 * @api public
 *
 * @param {String} eventName
 * @param {Function} callback
 */
ZenPad.prototype.listenEvent = function() {
  eventEmmiter.on.apply(this, arguments);
};

/**
 * Call event.
 * @api public
 *
 * @param {String} eventName
 * @param {*} arguments
 */
ZenPad.prototype.callEvent = function() {
  return eventEmmiter.emit.apply(this, arguments);
};

/**
 * Set environment.
 * @api public
 *
 * @param {String} env
 */
ZenPad.prototype.setEnv = function(env) {
  if (fs.existsSync('./zenpad.js')) {
    var config = require('../../../zenpad');
    this.config = extend(this.config, config[this.env = env]);
  }
};

/**
 * Read document dir.
 * @api public
 *
 * @param {String} dir
 * @param {Number} depth
 * @return {Array}
 */
ZenPad.prototype._readDocsDir = function(dir, depth) {
  var realDir = path.join(this.config.srcPath, this.config.docsDir, dir);
  var files = fs.readdirSync(realDir);
  var result = [];
  if (typeof depth != 'number') {
    depth = -1;
  }
  if (depth >= 1 || depth == -1) {
    var that = this;
    if (depth != -1) depth--;
    files.forEach(function(file) {
      if (path.basename(file).indexOf('.') !== 0) {
        var filePath = path.join(realDir, file);
        var fileStat = fs.lstatSync(filePath);
        if (fileStat.isFile()) {
          result.push(path.join(dir, file));
        } else if (fileStat.isDirectory()) {
          var innerFiles = that._readDocsDir(path.join(dir, file), depth);
          innerFiles.forEach(function(innerFile) {
            result.push(innerFile);
          });
        }
      }
    });
  }
  return result;
};

/**
 * ZenPad exports.
 */
module.exports = zenpad = new ZenPad(fs.existsSync('./zenpad.js')
  ? require('../../../zenpad')
  : {}
);

/**
 * Helper for call a widget from template.
 * {{widget 'name' tpl='row'}}
 */
handlebars.registerHelper('widget', function(name, params) {
  return zenpad.getWidget(name, params);
});

/**
 * Helper for show a chunk from template.
 * {{chunk 'name' key='val'}}
 */
handlebars.registerHelper('chunk', function(name, params) {
  var data = params.hash;
  data.doc = params.data.root.doc;
  data.config = params.data.root.config;
  return zenpad.getChunk(name, data);
});

/**
 * Date helper for handlebars.
 * {{date new Date() format='LL'}}
 */
handlebars.registerHelper('date', function(date, params) {
  var format = params.hash.format || 'LL';
  if (moment.lang() != zenpad.config.locale) {
    moment.lang(zenpad.config.locale);
  }
  return moment(date).format(format);
});

/**
 * Get cutted content.
 * {{cut 'content' tag='<!-- cut -->'}}
 */
handlebars.registerHelper('cut', function(content, params) {
  var parts = content.split(params.hash.tag || '<!-- cut -->');
  return parts[0];
});
<commit_msg>CutTag in config<commit_after>var fs = require('fs');
var path = require('path');
var events = require('events');
var extend = require('extend');
var moment = require('moment');
var handlebars = require('handlebars');
var eventEmmiter = new events.EventEmitter();

var Document = require('./resource/document');
var Template = require('./resource/template');
var Widget = require('./resource/widget');
var Chunk = require('./resource/chunk');

/**
 * Default configuation
 * @api private
 *
 * @var {Object} defaultConfig
 */
var defaultConfig = {
  buildPath: 'build',
  srcPath: 'src',
  templatesDir: 'layouts',
  widgetsDir: 'widgets',
  pluginsDir: 'plugins',
  chunksDir: 'chunks',
  docsDir: 'docs',
  locale: 'en',
  siteName: 'ZenPad',
  siteUrl: 'http://localhost:8080/',
  cutTag: '<!-- cut -->'
};

/**
 * Cache.
 * @api private
 *
 * @var {Object} cache
 */
var cache = {
  templates: {},
  widgets: {},
  chunks: {},
  docs: {}
};

/**
 * Create Engine instance.
 * @constructor
 */
function ZenPad(config) {

  this.env = 'default';
  this.config = extend(defaultConfig, config[this.env]);

  /**
   * Load plugins.
   */

  var pluginsPath = path.resolve(this.config.srcPath, this.config.pluginsDir);
  if (fs.existsSync(pluginsPath)) {
    var that = this;
    fs.readdirSync(pluginsPath).forEach(function(file) {
      require(path.resolve(pluginsPath, file))(that);
    });
  }

};

/**
 * Get document.
 * @api public
 *
 * @param {String} filePath
 * @return {Document}
 */
ZenPad.prototype.getDoc = function(filePath) {
  if (cache.docs[filePath]) {
    return cache.docs[filePath];
  }
  var docContent = fs.readFileSync(path.join(
    this.config.srcPath,
    this.config.docsDir,
    filePath
  ), 'utf-8');

  var doc = new Document(this, filePath, docContent);
  return cache.docs[filePath] = doc;
};

/**
 * Get documents.
 * @api public
 *
 * @param {String} dirPath
 * @param {Object} query
 * @return {Array}
 */
ZenPad.prototype.getDocs = function(dirPath, query) {
  var docs = this._readDocsDir(dirPath, query.depth);
  var result = [];

  for (var i=0, j=docs.length; i<j; i++) {
    var doc = this.getDoc(docs[i]);
    result.push(doc);
  }

  if (query.filter) {
    result = result.filter(query.filter);
  }

  return result;
};

/**
 * @api public
 * @param {String} url
 * @param {Object} data
 */
ZenPad.prototype.createDoc = function(url, data) {
  return new Document(this, url, data);
};

/**
 * Get widget.
 * @api public
 *
 * @param {String} filePath
 * @param {Object} params
 * @return {*}
 */
ZenPad.prototype.getWidget = function(filePath, params) {
  if (cache.widgets[filePath]) {
    var widget = this._widgets[filePath];
  } else {
    var requirePath = require.resolve('../../../' + path.join(
      this.config.srcPath,
      this.config.widgetsDir,
      filePath
    ));
    var widget = new Widget(this, require(requirePath));
    cache.widgets[requirePath] = widget;
  }
  return widget.run(params);
};

/**
 * Get chunk.
 * @api public
 *
 * @param {String} filePath
 * @param {Object} data
 * @return {String}
 */
ZenPad.prototype.getChunk = function(filePath, data) {
  if (cache.chunks[filePath]) {
    var chunk = cache.chunks[filePath];
  } else {
    var chunkContent = fs.readFileSync(path.join(
      this.config.srcPath,
      this.config.chunksDir,
      filePath + '.html'
    ), 'utf-8');
    var chunk = new Chunk(this, chunkContent);
    cache.chunks[filePath] = chunk;
  }
  return chunk.render(data);
};

/**
 * Render template.
 * @api public
 *
 * @param {String} filePath
 * @param {Object} data
 * @return {String}
 */
ZenPad.prototype.getTemplate = function(filePath, data) {
  if (cache.templates[filePath]) {
    var template = cache.templates[filePath];
  } else {
    var templateContent = fs.readFileSync(path.join(
      this.config.srcPath,
      this.config.templatesDir,
      filePath + '.html'
    ), 'utf-8');
    var template = new Template(this, templateContent);
    cache.templates[filePath] = template;
  }
  return template.render(data);
};

/**
 * Render string.
 * @public
 *
 * @param {String} source
 * @param {Object} data
 */
ZenPad.prototype.renderString = function(source, data) {
  return handlebars.compile(source)(data);
};

/**
 * Listen event.
 * @api public
 *
 * @param {String} eventName
 * @param {Function} callback
 */
ZenPad.prototype.listenEvent = function() {
  eventEmmiter.on.apply(this, arguments);
};

/**
 * Call event.
 * @api public
 *
 * @param {String} eventName
 * @param {*} arguments
 */
ZenPad.prototype.callEvent = function() {
  return eventEmmiter.emit.apply(this, arguments);
};

/**
 * Set environment.
 * @api public
 *
 * @param {String} env
 */
ZenPad.prototype.setEnv = function(env) {
  if (fs.existsSync('./zenpad.js')) {
    var config = require('../../../zenpad');
    this.config = extend(this.config, config[this.env = env]);
  }
};

/**
 * Read document dir.
 * @api public
 *
 * @param {String} dir
 * @param {Number} depth
 * @return {Array}
 */
ZenPad.prototype._readDocsDir = function(dir, depth) {
  var realDir = path.join(this.config.srcPath, this.config.docsDir, dir);
  var files = fs.readdirSync(realDir);
  var result = [];
  if (typeof depth != 'number') {
    depth = -1;
  }
  if (depth >= 1 || depth == -1) {
    var that = this;
    if (depth != -1) depth--;
    files.forEach(function(file) {
      if (path.basename(file).indexOf('.') !== 0) {
        var filePath = path.join(realDir, file);
        var fileStat = fs.lstatSync(filePath);
        if (fileStat.isFile()) {
          result.push(path.join(dir, file));
        } else if (fileStat.isDirectory()) {
          var innerFiles = that._readDocsDir(path.join(dir, file), depth);
          innerFiles.forEach(function(innerFile) {
            result.push(innerFile);
          });
        }
      }
    });
  }
  return result;
};

/**
 * ZenPad exports.
 */
module.exports = zenpad = new ZenPad(fs.existsSync('./zenpad.js')
  ? require('../../../zenpad')
  : {}
);

/**
 * Helper for call a widget from template.
 * {{widget 'name' tpl='row'}}
 */
handlebars.registerHelper('widget', function(name, params) {
  return zenpad.getWidget(name, params);
});

/**
 * Helper for show a chunk from template.
 * {{chunk 'name' key='val'}}
 */
handlebars.registerHelper('chunk', function(name, params) {
  var data = params.hash;
  data.doc = params.data.root.doc;
  data.config = params.data.root.config;
  return zenpad.getChunk(name, data);
});

/**
 * Date helper for handlebars.
 * {{date new Date() format='LL'}}
 */
handlebars.registerHelper('date', function(date, params) {
  var format = params.hash.format || 'LL';
  if (moment.lang() != zenpad.config.locale) {
    moment.lang(zenpad.config.locale);
  }
  return moment(date).format(format);
});

/**
 * Get cutted content.
 * {{cut 'content' tag='<!-- cut -->'}}
 */
handlebars.registerHelper('cut', function(content, params) {
  var parts = content.split(params.hash.tag || zenpad.config.cutTag);
  return parts[0];
});
<|endoftext|>