<commit_before>var webpack = require('webpack');
var path = require('path')

// To Reqrite index.html with proper bundle js
var HtmlWebpackPlugin = require('html-webpack-plugin')
var HTMLWebpackPluginConfig = new HtmlWebpackPlugin({
  template: __dirname + '/app/index.html',
  filename: 'index.html',
  inject: 'body'
});

var CopyWebpackPlugin = require('copy-webpack-plugin');
var __DEV__ = process.env.NODE_ENV !== 'production'
console.log("Building for %s", __DEV__ ? "development" : "production")

var entry=[]
if (__DEV__)
  entry=[
    'webpack/hot/only-dev-server',
    'webpack-dev-server/client?http://localhost:3000'
  ]

module.exports = {
    entry: [
      "./app/js/app.js"
    ].concat(entry),
    output: {
        path: path.resolve('dist/'),
        filename: "js/bundle.js"
    },
    resolve: {
      alias:{
        app : path.resolve("./app/js"),
        sass : path.resolve("./app/sass")
      }
    },
    devtool: __DEV__ ? "source-map" : "cheap-module-source-map",
    module: {
        loaders: [
            //{ test: /\.jsx$/, loaders: ['react-hot', 'babel'], exclude: /node_modules/ },
            { test: /\.js$/, exclude: /node_modules/, loaders: ["react-hot", "babel"] },
            { test: /\.css$/, loader: "style!css" },
            { test: /\.sass$/, exclude: /node_modules/, loader: "style!css!sass"},
            { test: /\.(jpe?g|png|gif|svg)$/i,
                    loaders: [
                        'file?hash=sha512&digest=hex&name=[hash].[ext]',
                        'image-webpack?bypassOnDebug&optimizationLevel=7&interlaced=false'
                    ]
                  },
            { test: /\.json$/, loader: "json" },
        ]
    },
    plugins: [
      new webpack.optimize.OccurenceOrderPlugin(),
      new webpack.NoErrorsPlugin(),
      HTMLWebpackPluginConfig,
      new CopyWebpackPlugin([
        {from:'app/css', to:'css'},
        {from:'app/js/jquery-2.2.3.min.js', to:'js'},
        {from:'app/js/semantic.min.js', to:'js'},
        {from:'app/imgs/favicon.png', to:'imgs'},
      ]),
      new webpack.DefinePlugin({
        __DEV__: JSON.stringify(__DEV__),
        SERVERBOARDS_VERSION: JSON.stringify(require("./package.json").version),
        'process.env': {
          'NODE_ENV': __DEV__ ? JSON.stringify("development") : JSON.stringify("production")
        }
      })
    ],
    sassLoader: {
      includePaths: [path.resolve("./sass")]
    },
    imageWebpackLoader: {
      pngquant:{
        quality: "65-90",
        speed: 4
      },
      svgo:{
        plugins: [
          {
            removeViewBox: false
          },
          {
            removeEmptyAttrs: false
          }
        ]
      }
    }
  };
<commit_msg>Save bundle.js with hash, to prevent caching when changes<commit_after>var webpack = require('webpack');
var path = require('path')

// To Reqrite index.html with proper bundle js
var HtmlWebpackPlugin = require('html-webpack-plugin')
var HTMLWebpackPluginConfig = new HtmlWebpackPlugin({
  template: __dirname + '/app/index.html',
  filename: 'index.html',
  inject: 'body'
});

var CopyWebpackPlugin = require('copy-webpack-plugin');
var __DEV__ = process.env.NODE_ENV !== 'production'
console.log("Building for %s", __DEV__ ? "development" : "production")

var entry=[]
if (__DEV__)
  entry=[
    'webpack/hot/only-dev-server',
    'webpack-dev-server/client?http://localhost:3000'
  ]

module.exports = {
    entry: [
      "./app/js/app.js"
    ].concat(entry),
    output: {
        path: path.resolve('dist/'),
        filename: "js/bundle-[hash].js"
    },
    resolve: {
      alias:{
        app : path.resolve("./app/js"),
        sass : path.resolve("./app/sass")
      }
    },
    devtool: __DEV__ ? "source-map" : "cheap-module-source-map",
    module: {
        loaders: [
            //{ test: /\.jsx$/, loaders: ['react-hot', 'babel'], exclude: /node_modules/ },
            { test: /\.js$/, exclude: /node_modules/, loaders: ["react-hot", "babel"] },
            { test: /\.css$/, loader: "style!css" },
            { test: /\.sass$/, exclude: /node_modules/, loader: "style!css!sass"},
            { test: /\.(jpe?g|png|gif|svg)$/i,
                    loaders: [
                        'file?hash=sha512&digest=hex&name=[hash].[ext]',
                        'image-webpack?bypassOnDebug&optimizationLevel=7&interlaced=false'
                    ]
                  },
            { test: /\.json$/, loader: "json" },
        ]
    },
    plugins: [
      new webpack.optimize.OccurenceOrderPlugin(),
      new webpack.NoErrorsPlugin(),
      HTMLWebpackPluginConfig,
      new CopyWebpackPlugin([
        {from:'app/css', to:'css'},
        {from:'app/js/jquery-2.2.3.min.js', to:'js'},
        {from:'app/js/semantic.min.js', to:'js'},
        {from:'app/imgs/favicon.png', to:'imgs'},
      ]),
      new webpack.DefinePlugin({
        __DEV__: JSON.stringify(__DEV__),
        SERVERBOARDS_VERSION: JSON.stringify(require("./package.json").version),
        'process.env': {
          'NODE_ENV': __DEV__ ? JSON.stringify("development") : JSON.stringify("production")
        }
      })
    ],
    sassLoader: {
      includePaths: [path.resolve("./sass")]
    },
    imageWebpackLoader: {
      pngquant:{
        quality: "65-90",
        speed: 4
      },
      svgo:{
        plugins: [
          {
            removeViewBox: false
          },
          {
            removeEmptyAttrs: false
          }
        ]
      }
    }
  };
<|endoftext|>


<commit_before>/*
 * grunt-phantomcss
 * https://github.com/micahgodbolt/grunt-phantomcss
 *
 * Copyright (c) 2013 Chris Gladd
 * Copyright (c) since 2014 Anselm Hannemann
 * Copyright (c) since 2015 Micah Godbolt
 *
 * Licensed under the MIT license.
 */

'use strict';

function findPath(folderName, paths) {
  var goodPath = null;
  for (var i = 0; i < paths.length && !goodPath; i++) {
    var folderPath = path.resolve(paths[i], folderName);
    console.log('testing ' + folderPath);
    try {
      var stats = fs.statSync(folderPath);
      if (stats.isDirectory()) {
        goodPath = folderPath;
        break;
      }
    } catch (e) {
      // if we get an exception, just try the next path
    }
  }
  if (goodPath == null) {
    throw new Error('Unable to locate the root folder for ' + folderName + ' module');
  }
  return goodPath;
}

var path = require('path');
var fs = require('fs');
var tmp = require('temporary');
var phantomBinaryPath = require('phantomjs').path;
var runnerPath = path.resolve(__dirname, '..', 'phantomjs', 'runner.js');
var phantomCSSPath = findPath('phantomcss', [
  path.resolve(__dirname, '..', 'node_modules'),
  path.resolve(__dirname, '..', '..', 'node_modules') // sibling node_module (per npm 3 installation)
]);
var casperJSPath = findPath('casperjs', [
  path.resolve(phantomCSSPath, 'node_modules'),
  path.resolve(phantomCSSPath, '..', '..', 'node_modules'), // sibling node_module of phantomcss (per nmp 3)
  path.resolve(__dirname, '..', '..', 'node_modules') // sibling root node_module (per npm 3)
]);

module.exports = function(grunt) {
  grunt.registerMultiTask('phantomcss', 'CSS Regression Testing', function() {
    var done = this.async();

    // Variable object to set default values for options
    var options = this.options({
      rootUrl: false,
      screenshots: 'screenshots',
      results: 'results',
      viewportSize: [1280, 800],
      mismatchTolerance: 0.05,
      waitTimeout: 5000, // Set timeout to wait before throwing an exception
      logLevel: 'warning' // debug | info | warning | error
    });

    // Timeout ID for message checking loop
    var messageCheckTimeout;

    // The number of tempfile lines already read
    var lastLine = 0;

    // The number of failed tests
    var failureCount = 0;

    // This is effectively the project root (location of Gruntfile)
    // This allows relative paths in tests, i.e. casper.start('someLocalFile.html')
    var cwd = process.cwd();

    // Create a temporary file for message passing between the task and PhantomJS
    var tempFile = new tmp.File();

    var deleteDiffScreenshots = function(folderpath) {
      // Find diff/fail files
      var diffScreenshots = grunt.file.expand([
        path.join(folderpath + '/' + options.screenshots, '*diff.png'),
        path.join(folderpath + '/' + options.screenshots, '*fail.png'),
      ]);

      // Delete all of 'em
      diffScreenshots.forEach(function(filepath) {
        grunt.file.delete(filepath, { force: true });
      });
    };

    var deleteDiffResults = function(folderpath) {
      // Find diff/fail files
      var diffScreenshots = grunt.file.expand([
        path.join(folderpath, options.results),
      ]);

      // Delete all of 'em
      diffScreenshots.forEach(function(filepath) {
        grunt.file.delete(filepath, { force: true });
      });
    };

    var cleanup = function(error) {
      // Remove temporary file
      tempFile.unlink();

      options.testFolder.forEach(function(folderpath) {
        // Create the output directory
        grunt.file.mkdir(folderpath + '/' + options.results);

        // Copy fixtures, diffs, and failure images to the results directory
        var allScreenshots = grunt.file.expand(path.join(folderpath + '/' + options.screenshots, '**.png'));

        allScreenshots.forEach(function(filepath) {
          grunt.file.copy(filepath, path.join(
            folderpath + '/' + options.results,
            path.basename(filepath)
          ));
        });

        deleteDiffScreenshots(folderpath);
      });
      done(error || failureCount === 0);
    };

    var checkForMessages = function checkForMessages(stopChecking) {
      // Disable logging temporarily
      grunt.log.muted = true;

      // Read the file, splitting lines on \n, and removing a trailing line
      var lines = grunt.file.read(tempFile.path).split('\n').slice(0, -1);

      // Re-enable logging
      grunt.log.muted = false;

      // Iterate over all lines that haven't already been processed
      lines.slice(lastLine).some(function(line) {
        // Get args and method
        var args = JSON.parse(line);
        var eventName = args[0];

        // Debugging messages
        grunt.log.debug(JSON.stringify(['phantomjs'].concat(args)).magenta);

        // Call handler
        if (messageHandlers[eventName]) {
          messageHandlers[eventName].apply(null, args.slice(1));
        }
      });

      // Update lastLine so previously processed lines are ignored
      lastLine = lines.length;

      if (stopChecking) {
        clearTimeout(messageCheckTimeout);
      } else {
        // Check back in a little bit
        messageCheckTimeout = setTimeout(checkForMessages, 100);
      }
    };

    var messageHandlers = {
      onFail: function(test) {
        grunt.log.writeln('Visual change found for ' + path.basename(test.filename) + ' (' + test.mismatch + '% mismatch)');
      },
      onPass: function(test) {
        grunt.log.writeln('No changes found for ' + path.basename(test.filename));
      },
      onTimeout: function(test) {
        grunt.log.writeln('Timeout while processing ' + path.basename(test.filename));
      },
      onComplete: function(allTests, noOfFails, noOfErrors) {
        if (allTests.length) {
          var noOfPasses = allTests.length - failureCount;
          failureCount = noOfFails + noOfErrors;

          if (failureCount === 0) {
            grunt.log.ok('All ' + noOfPasses + ' tests passed!');
          } else {
            if (noOfErrors === 0) {
              grunt.log.error(noOfFails + ' tests failed.');
            } else {
              grunt.log.error(noOfFails + ' tests failed, ' + noOfErrors + ' had errors.');
            }
          }
        }
      }
    };

    // Resolve paths for tests
    options.test = [];
    options.testFolder = [];
    this.filesSrc.forEach(function(filepath) {
      options.test.push(path.resolve(filepath));
      options.testFolder.push(path.dirname(filepath));
    });

    // Put failure screenshots in the same place as source screenshots, we'll move/delete them after the test run
    // Note: This duplicate assignment is provided for clarity; PhantomCSS will put failures in the screenshots folder by default
    options.failures = options.screenshots;

    // Pass necessary paths
    options.tempFile = tempFile.path;
    options.phantomCSSPath = phantomCSSPath;
    options.casperJSPath = casperJSPath;

    // Remove old diff screenshots

    options.testFolder.forEach(function(folderpath) {
      deleteDiffScreenshots(folderpath);
      deleteDiffResults(folderpath);
    });

    // Start watching for messages
    checkForMessages();

    grunt.util.spawn({
      cmd: phantomBinaryPath,
      args: [
        runnerPath,
        JSON.stringify(options),
      ],
      opts: {
        cwd: cwd,
        stdio: 'inherit'
      }
    }, function(error, result, code) {
      // When Phantom exits check for remaining messages one last time
      checkForMessages(true);

      cleanup(error);
    });
  });
};
<commit_msg>minor code reshuffle<commit_after>/*
 * grunt-phantomcss
 * https://github.com/micahgodbolt/grunt-phantomcss
 *
 * Copyright (c) 2013 Chris Gladd
 * Copyright (c) since 2014 Anselm Hannemann
 * Copyright (c) since 2015 Micah Godbolt
 *
 * Licensed under the MIT license.
 */

'use strict';

var path = require('path');
var fs = require('fs');

function findPath(folderName, paths) {
  var goodPath = null;
  for (var i = 0; i < paths.length && !goodPath; i++) {
    var folderPath = path.resolve(paths[i], folderName);
    console.log('testing ' + folderPath);
    try {
      var stats = fs.statSync(folderPath);
      if (stats.isDirectory()) {
        goodPath = folderPath;
        break;
      }
    } catch (e) {
      // if we get an exception, just try the next path
    }
  }
  if (goodPath == null) {
    throw new Error('Unable to locate the root folder for ' + folderName + ' module');
  }
  return goodPath;
}

var tmp = require('temporary');
var phantomBinaryPath = require('phantomjs').path;
var runnerPath = path.resolve(__dirname, '..', 'phantomjs', 'runner.js');
var phantomCSSPath = findPath('phantomcss', [
  path.resolve(__dirname, '..', 'node_modules'),
  path.resolve(__dirname, '..', '..', 'node_modules') // sibling node_module (per npm 3 installation)
]);
var casperJSPath = findPath('casperjs', [
  path.resolve(phantomCSSPath, 'node_modules'),
  path.resolve(phantomCSSPath, '..', '..', 'node_modules'), // sibling node_module of phantomcss (per nmp 3)
  path.resolve(__dirname, '..', '..', 'node_modules') // sibling root node_module (per npm 3)
]);

module.exports = function(grunt) {
  grunt.registerMultiTask('phantomcss', 'CSS Regression Testing', function() {
    var done = this.async();

    // Variable object to set default values for options
    var options = this.options({
      rootUrl: false,
      screenshots: 'screenshots',
      results: 'results',
      viewportSize: [1280, 800],
      mismatchTolerance: 0.05,
      waitTimeout: 5000, // Set timeout to wait before throwing an exception
      logLevel: 'warning' // debug | info | warning | error
    });

    // Timeout ID for message checking loop
    var messageCheckTimeout;

    // The number of tempfile lines already read
    var lastLine = 0;

    // The number of failed tests
    var failureCount = 0;

    // This is effectively the project root (location of Gruntfile)
    // This allows relative paths in tests, i.e. casper.start('someLocalFile.html')
    var cwd = process.cwd();

    // Create a temporary file for message passing between the task and PhantomJS
    var tempFile = new tmp.File();

    var deleteDiffScreenshots = function(folderpath) {
      // Find diff/fail files
      var diffScreenshots = grunt.file.expand([
        path.join(folderpath + '/' + options.screenshots, '*diff.png'),
        path.join(folderpath + '/' + options.screenshots, '*fail.png'),
      ]);

      // Delete all of 'em
      diffScreenshots.forEach(function(filepath) {
        grunt.file.delete(filepath, { force: true });
      });
    };

    var deleteDiffResults = function(folderpath) {
      // Find diff/fail files
      var diffScreenshots = grunt.file.expand([
        path.join(folderpath, options.results),
      ]);

      // Delete all of 'em
      diffScreenshots.forEach(function(filepath) {
        grunt.file.delete(filepath, { force: true });
      });
    };

    var cleanup = function(error) {
      // Remove temporary file
      tempFile.unlink();

      options.testFolder.forEach(function(folderpath) {
        // Create the output directory
        grunt.file.mkdir(folderpath + '/' + options.results);

        // Copy fixtures, diffs, and failure images to the results directory
        var allScreenshots = grunt.file.expand(path.join(folderpath + '/' + options.screenshots, '**.png'));

        allScreenshots.forEach(function(filepath) {
          grunt.file.copy(filepath, path.join(
            folderpath + '/' + options.results,
            path.basename(filepath)
          ));
        });

        deleteDiffScreenshots(folderpath);
      });
      done(error || failureCount === 0);
    };

    var checkForMessages = function checkForMessages(stopChecking) {
      // Disable logging temporarily
      grunt.log.muted = true;

      // Read the file, splitting lines on \n, and removing a trailing line
      var lines = grunt.file.read(tempFile.path).split('\n').slice(0, -1);

      // Re-enable logging
      grunt.log.muted = false;

      // Iterate over all lines that haven't already been processed
      lines.slice(lastLine).some(function(line) {
        // Get args and method
        var args = JSON.parse(line);
        var eventName = args[0];

        // Debugging messages
        grunt.log.debug(JSON.stringify(['phantomjs'].concat(args)).magenta);

        // Call handler
        if (messageHandlers[eventName]) {
          messageHandlers[eventName].apply(null, args.slice(1));
        }
      });

      // Update lastLine so previously processed lines are ignored
      lastLine = lines.length;

      if (stopChecking) {
        clearTimeout(messageCheckTimeout);
      } else {
        // Check back in a little bit
        messageCheckTimeout = setTimeout(checkForMessages, 100);
      }
    };

    var messageHandlers = {
      onFail: function(test) {
        grunt.log.writeln('Visual change found for ' + path.basename(test.filename) + ' (' + test.mismatch + '% mismatch)');
      },
      onPass: function(test) {
        grunt.log.writeln('No changes found for ' + path.basename(test.filename));
      },
      onTimeout: function(test) {
        grunt.log.writeln('Timeout while processing ' + path.basename(test.filename));
      },
      onComplete: function(allTests, noOfFails, noOfErrors) {
        if (allTests.length) {
          var noOfPasses = allTests.length - failureCount;
          failureCount = noOfFails + noOfErrors;

          if (failureCount === 0) {
            grunt.log.ok('All ' + noOfPasses + ' tests passed!');
          } else {
            if (noOfErrors === 0) {
              grunt.log.error(noOfFails + ' tests failed.');
            } else {
              grunt.log.error(noOfFails + ' tests failed, ' + noOfErrors + ' had errors.');
            }
          }
        }
      }
    };

    // Resolve paths for tests
    options.test = [];
    options.testFolder = [];
    this.filesSrc.forEach(function(filepath) {
      options.test.push(path.resolve(filepath));
      options.testFolder.push(path.dirname(filepath));
    });

    // Put failure screenshots in the same place as source screenshots, we'll move/delete them after the test run
    // Note: This duplicate assignment is provided for clarity; PhantomCSS will put failures in the screenshots folder by default
    options.failures = options.screenshots;

    // Pass necessary paths
    options.tempFile = tempFile.path;
    options.phantomCSSPath = phantomCSSPath;
    options.casperJSPath = casperJSPath;

    // Remove old diff screenshots

    options.testFolder.forEach(function(folderpath) {
      deleteDiffScreenshots(folderpath);
      deleteDiffResults(folderpath);
    });

    // Start watching for messages
    checkForMessages();

    grunt.util.spawn({
      cmd: phantomBinaryPath,
      args: [
        runnerPath,
        JSON.stringify(options),
      ],
      opts: {
        cwd: cwd,
        stdio: 'inherit'
      }
    }, function(error, result, code) {
      // When Phantom exits check for remaining messages one last time
      checkForMessages(true);

      cleanup(error);
    });
  });
};
<|endoftext|>


<commit_before>/*
* grunt-ssh-deploy
* https://github.com/dcarlson/grunt-ssh-deploy
*
* Copyright (c) 2014 Dustin Carlson
* Licensed under the MIT license.
*/

'use strict';

module.exports = function(grunt) {

	grunt.registerMultiTask('ssh_deploy', 'Begin Deployment', function() {
		this.async();
		var Connection = require('ssh2');
		var moment = require('moment');
		var timestamp = moment().format('YYYYMMDDHHmmssSSS');
		var async = require('async');

		var options = this.options({
			host: '',
			username: '',
			password: '',
			port: '22',
			deploy_path: '',
			local_path: '',
			current_symlink: 'current',
			debug: false
		});

		var c = new Connection();
		c.on('connect', function() {
			grunt.log.subhead('Connecting :: ' + options.host);
		});
		c.on('ready', function() {
			grunt.log.subhead('Connected :: ' + options.host);
			// execution of tasks
			execCommands(options,c);
		});
		c.on('error', function(err) {
			grunt.log.subhead("Error :: " + options.host);
			grunt.log.errorlns(err);
			if (err) {throw err; connection.end(); return false;}
		});
		c.on('close', function(had_error) {
			grunt.log.subhead("Closed :: " + options.host);
		});
		c.connect(options);

		var execCommands = function(options, connection){
			var childProcessExec = require('child_process').exec;

			var execLocal = function(cmd, next) {
				var nextFun = next;
				childProcessExec(cmd, function(err, stdout, stderr){
					grunt.log.debug(cmd);
					grunt.log.debug('stdout: ' + stdout);
					grunt.log.debug('stderr: ' + stderr);
					if (err !== null) {
						grunt.log.errorlns('exec error: ' + err);
						grunt.log.subhead('Error deploying. Closing connection.');

						deleteRelease(closeConnection);
					} else {
						next();
					}
				});
			};

			// executes a remote command via ssh
			var execRemote = function(cmd, showLog, next){
				connection.exec(cmd, function(err, stream) {
					if (err) {
						grunt.log.errorlns(err);
						grunt.log.subhead('ERROR DEPLOYING. CLOSING CONNECTION AND DELETING RELEASE.');

						deleteRelease(closeConnection);
					}
					stream.on('data', function(data, extended) {
						grunt.log.debug((extended === 'stderr' ? 'STDERR: ' : 'STDOUT: ') + data);
					});
					stream.on('end', function() {
						grunt.log.debug('REMOTE: ' + cmd);
						if(!err) {
							next && next()
						}
					});
				});
			};

			var createReleases = function(callback) {
				var command = 'cd ' + options.deploy_path + '/releases && mkdir ' + timestamp;
				grunt.log.subhead('--------------- CREATING NEW RELEASE');
				grunt.log.subhead('--- ' + command);
				execRemote(command, options.debug, callback);
			};

			var scpBuild = function(callback) {
				var remote_string = options.username + '@' + options.host + ':' + options.deploy_path + '/releases/' + timestamp + '/';
				var command = 'scp -p ' + options.port + ' -r ' + options.local_path + '/. ' + remote_string;
				grunt.log.subhead('--------------- UPLOADING NEW BUILD');
				grunt.log.subhead('--- ' + command);
				execLocal(command, callback);
			};

			var updateSymlink = function(callback) {
				var delete_symlink = 'rm -rf ' + options.deploy_path + '/' + options.current_symlink;
				var set_symlink = 'ln -s ' + options.deploy_path + '/releases/' + timestamp + ' ' + options.deploy_path + '/' + options.current_symlink;
				var command = delete_symlink + ' && ' + set_symlink;
				grunt.log.subhead('--------------- UPDATING SYM LINK');
				grunt.log.subhead('--- ' + command);
				execRemote(command, options.debug, callback);
			};

			var deleteRelease = function(callback) {
				var command = 'rm -rf ' + options.deploy_path + '/releases/' + timestamp + '/';
				grunt.log.subhead('--------------- DELETING RELEASE');
				grunt.log.subhead('--- ' + command);
				execRemote(command, options.debug, callback);
			}

			// closing connection to remote server
			var closeConnection = function(callback) {
				connection.end();
			};

			async.series([
				createReleases,
				scpBuild,
				updateSymlink,
				closeConnection
			]);
		};
	});
};<commit_msg>fixing port specification on scp command<commit_after>/*
* grunt-ssh-deploy
* https://github.com/dcarlson/grunt-ssh-deploy
*
* Copyright (c) 2014 Dustin Carlson
* Licensed under the MIT license.
*/

'use strict';

module.exports = function(grunt) {

	grunt.registerMultiTask('ssh_deploy', 'Begin Deployment', function() {
		this.async();
		var Connection = require('ssh2');
		var moment = require('moment');
		var timestamp = moment().format('YYYYMMDDHHmmssSSS');
		var async = require('async');

		var options = this.options({
			host: '',
			username: '',
			password: '',
			port: '22',
			deploy_path: '',
			local_path: '',
			current_symlink: 'current',
			debug: false
		});

		var c = new Connection();
		c.on('connect', function() {
			grunt.log.subhead('Connecting :: ' + options.host);
		});
		c.on('ready', function() {
			grunt.log.subhead('Connected :: ' + options.host);
			// execution of tasks
			execCommands(options,c);
		});
		c.on('error', function(err) {
			grunt.log.subhead("Error :: " + options.host);
			grunt.log.errorlns(err);
			if (err) {throw err; connection.end(); return false;}
		});
		c.on('close', function(had_error) {
			grunt.log.subhead("Closed :: " + options.host);
		});
		c.connect(options);

		var execCommands = function(options, connection){
			var childProcessExec = require('child_process').exec;

			var execLocal = function(cmd, next) {
				var nextFun = next;
				childProcessExec(cmd, function(err, stdout, stderr){
					grunt.log.debug(cmd);
					grunt.log.debug('stdout: ' + stdout);
					grunt.log.debug('stderr: ' + stderr);
					if (err !== null) {
						grunt.log.errorlns('exec error: ' + err);
						grunt.log.subhead('Error deploying. Closing connection.');

						deleteRelease(closeConnection);
					} else {
						next();
					}
				});
			};

			// executes a remote command via ssh
			var execRemote = function(cmd, showLog, next){
				connection.exec(cmd, function(err, stream) {
					if (err) {
						grunt.log.errorlns(err);
						grunt.log.subhead('ERROR DEPLOYING. CLOSING CONNECTION AND DELETING RELEASE.');

						deleteRelease(closeConnection);
					}
					stream.on('data', function(data, extended) {
						grunt.log.debug((extended === 'stderr' ? 'STDERR: ' : 'STDOUT: ') + data);
					});
					stream.on('end', function() {
						grunt.log.debug('REMOTE: ' + cmd);
						if(!err) {
							next && next()
						}
					});
				});
			};

			var createReleases = function(callback) {
				var command = 'cd ' + options.deploy_path + '/releases && mkdir ' + timestamp;
				grunt.log.subhead('--------------- CREATING NEW RELEASE');
				grunt.log.subhead('--- ' + command);
				execRemote(command, options.debug, callback);
			};

			var scpBuild = function(callback) {
				var remote_string = options.username + '@' + options.host + ':' + options.deploy_path + '/releases/' + timestamp + '/';
				var command = 'scp -P ' + options.port + ' -r ' + options.local_path + '/. ' + remote_string;
				grunt.log.subhead('--------------- UPLOADING NEW BUILD');
				grunt.log.subhead('--- ' + command);
				execLocal(command, callback);
			};

			var updateSymlink = function(callback) {
				var delete_symlink = 'rm -rf ' + options.deploy_path + '/' + options.current_symlink;
				var set_symlink = 'ln -s ' + options.deploy_path + '/releases/' + timestamp + ' ' + options.deploy_path + '/' + options.current_symlink;
				var command = delete_symlink + ' && ' + set_symlink;
				grunt.log.subhead('--------------- UPDATING SYM LINK');
				grunt.log.subhead('--- ' + command);
				execRemote(command, options.debug, callback);
			};

			var deleteRelease = function(callback) {
				var command = 'rm -rf ' + options.deploy_path + '/releases/' + timestamp + '/';
				grunt.log.subhead('--------------- DELETING RELEASE');
				grunt.log.subhead('--- ' + command);
				execRemote(command, options.debug, callback);
			}

			// closing connection to remote server
			var closeConnection = function(callback) {
				connection.end();
			};

			async.series([
				createReleases,
				scpBuild,
				updateSymlink,
				closeConnection
			]);
		};
	});
};<|endoftext|>


<commit_before>/*
 * grunt-testflight
 * https://github.com/shiwano/grunt-testflight
 *
 * Copyright (c) 2013 Shogo Iwano
 * Licensed under the MIT license.
 */

'use strict';

var FormData = require('form-data');
var fs = require('fs');

module.exports = function(grunt) {
  var _ = grunt.util._;
  var testFlightAPIUrl = 'http://testflightapp.com/api/builds.json';

  grunt.registerMultiTask('testflight', 'Upload the build to TestFlight', function() {
    var done = this.async();
    var options = this.options({
      apiToken: null,
      teamToken: null,
      file: null,
      notes: null,
      dsym: null,
      distributionLists: [],
      notify: false,
      replace: false
    });

    if (!_.isString(options.apiToken) || !_.isString(options.teamToken) ||
        !_.isString(options.file) || _.isNull(options.notes)) {
      grunt.log.error('Missing required parameter!');
      return done(false);
    }

    if (_.isFunction(options.notes)) {
      options.notes = options.notes(function(notes) {
        if (_.isString(options.notes)) { return; }
        options.notes = notes;
        uploadBuildToTestFlight(options, done);
      });
    }

    if (_.isString(options.notes)) {
      uploadBuildToTestFlight(options, done);
    }
  });

  var uploadBuildToTestFlight = function(options, done) {
    var form = new FormData();
    form.append('api_token', options.apiToken);
    form.append('team_token', options.teamToken);
    form.append('file', fs.createReadStream(options.file));
    form.append('notes', options.notes);
    form.append('distribution_lists', options.distributionLists.join(','));
    form.append('notify', options.notify.toString());
    form.append('replace', options.replace.toString());

    if (/\.ipa$/.test(options.file) && _.isString(options.dsym)) {
      form.append('dsym', fs.createReadStream(options.dsym));
    }

    grunt.log.writeln('Now uploading...');
    form.submit(testFlightAPIUrl, function(err, res) {
      if (err) {
        grunt.log.error(err);
        return done(false);
      }
      if (res.statusCode !== 200) {
        grunt.log.error('Uploading failed with status ' + res.statusCode);
        return done(false);
      }
      grunt.log.ok('Uploaded ' + options.file.cyan + ' to TestFlight!');
      done();
    });
  };
};
<commit_msg>Print TestFlight API response on error<commit_after>/*
 * grunt-testflight
 * https://github.com/shiwano/grunt-testflight
 *
 * Copyright (c) 2013 Shogo Iwano
 * Licensed under the MIT license.
 */

'use strict';

var FormData = require('form-data');
var fs = require('fs');

module.exports = function(grunt) {
  var _ = grunt.util._;
  var testFlightAPIUrl = 'http://testflightapp.com/api/builds.json';

  grunt.registerMultiTask('testflight', 'Upload the build to TestFlight', function() {
    var done = this.async();
    var options = this.options({
      apiToken: null,
      teamToken: null,
      file: null,
      notes: null,
      dsym: null,
      distributionLists: [],
      notify: false,
      replace: false
    });

    if (!_.isString(options.apiToken) || !_.isString(options.teamToken) ||
        !_.isString(options.file) || _.isNull(options.notes)) {
      grunt.log.error('Missing required parameter!');
      return done(false);
    }

    if (_.isFunction(options.notes)) {
      options.notes = options.notes(function(notes) {
        if (_.isString(options.notes)) { return; }
        options.notes = notes;
        uploadBuildToTestFlight(options, done);
      });
    }

    if (_.isString(options.notes)) {
      uploadBuildToTestFlight(options, done);
    }
  });

  var uploadBuildToTestFlight = function(options, done) {
    var form = new FormData();
    form.append('api_token', options.apiToken);
    form.append('team_token', options.teamToken);
    form.append('file', fs.createReadStream(options.file));
    form.append('notes', options.notes);
    form.append('distribution_lists', options.distributionLists.join(','));
    form.append('notify', options.notify.toString());
    form.append('replace', options.replace.toString());

    if (/\.ipa$/.test(options.file) && _.isString(options.dsym)) {
      form.append('dsym', fs.createReadStream(options.dsym));
    }

    grunt.log.writeln('Now uploading...');
    form.submit(testFlightAPIUrl, function(err, res) {
      if (err) {
        grunt.log.error(err);
        return done(false);
      }
      if (res.statusCode !== 200) {
        grunt.log.error('Uploading failed with status ' + res.statusCode);
        res.on('data', function (chunk) {
          grunt.log.error(chunk);
        });
        return done(false);
      }
      grunt.log.ok('Uploaded ' + options.file.cyan + ' to TestFlight!');
      done();
    });
  };
};
<|endoftext|>


<commit_before>game.GameTimerManager = Object.extend({
    init: function(x, y, settings) {
        this.now = new Date().getTime();
        this.lastCreep = new Date().getTime();
        this.paused = false;
        this.alwaysUpdate = true;
    },
    update: function() {
        this.now = new Date().getTime();
        this.addGold();
        this.addCreep();
        return true;
    },
    addGold: function() {
        if (Math.round(this.now / 1000) % 20 === 0 && (this.now - this.lastCreep >= 1000)) {
            game.data.gold += (game.data.exp1 + 1);
            console.log("Current gold:" + game.data.gold);
        }
    },
    addCreep: function() {
        if (Math.round(this.now / 1000) % 10 === 0 && (this.now - this.lastCreep >= 1000)) {
            this.lastCreep = this.now;
            var creep = me.pool.pull("EnemyCreep", 1000, 0, {});
            me.game.world.addChild(creep, 5);
        }
    },
});

game.HeroDeathManager = Object.extend({
    init: function(x, y, settings) {
        this.alwaysUpdate = true;
    },
    update: function() {
        if (game.data.player.dead) {
            me.game.world.removeChild(game.data.player);
            me.state.current().resetPlayer(10, 0);
        }
        return true;
    }
});

game.ExperienceManager = Object.extend({
    init: function(x, y, settings) {
        this.alwaysUpdate = true;
        this.gameover = false;
    },
    update: function() {
        if (game.data.win === true && !this.gameover) {
            this.gameOver(true);
        } else if (game.data.win == false && !this.gameover) {
            this.gameOver(false);
        }
        return true;
    },

    gameOver: function(win) {
        if(win){
           game.data.exp += 10;
        }else{
           game.data.exp += 1;
        }

        this.gameOver = true;
        me.save.exp = game.data.exp;
    }
});

game.SpendGold = Object.extend({
    init: function(x, y, settings) {
        this.now = new Date().getTime();
        this.lastBuy = new Date().getTime();
        this.paused = false;
        this.alwaysUpdate = true;
        this.updateWhenPaused = true;
        this.buying = false;
    },

    update: function(){
        this.now = new Date().getTime();
        if(me.input.isKeyPressed("buy") && this.now-this.lastBuy >= 1000){
            this.lastBuy = this.now;
            if(!this.buying){
                this.startBuying();
            }else{
                this.stopBuying();
            }

        }
        return true;
    },

    startBuying: function(){
        this.buying = true;
        me.state.pause(me.state.PLAY);
        game.data.pausePos = me.game.viewport.localToWorld(0, 0);
        game.data.buyscreen = new me.Sprite(game.data.pausePos.x, game.data.pausePos.y, me.loader.getImage("gold-screen"));
        game.data.buyscreen.updateWhenPaused = true;
        game.data.buyscreen.setOpacity(0.8);
        me.game.world.addChild(game.data.buyscreen, 34);
        game.data.player.body.setVelocity(0, 0);
        me.input.bindKey(me.input.KEY. F1, "F1", true);
        me.input.bindKey(me.input.KEY. F2, "F2", true);
        me.input.bindKey(me.input.KEY. F3, "F3", true);
        me.input.bindKey(me.input.KEY. F4, "F4", true);
        me.input.bindKey(me.input.KEY. F5, "F5", true);
        me.input.bindKey(me.input.KEY. F6, "F6", true);
        this.setBuyText();
    },

    setBuyText: function(){
        game.data.buytext = new (me.Renderable.extend({
            init: function() {
                this._super(me.Renderable, 'init', [game.data.pausePos.x, game.data.pausePos.y, 300, 50]);
                this.font = new me.Font("Arial", 26, "white");
                this.updateWhenPaused = true;
                this.alwaysUpdate;
            },
            draw: function(renderer) {
                this.font.draw(renderer.getContext(), "Press F1-F6 to Buy, Press B to Exit.  Current Gold: " + game.data.gold, this.pos.x, this.pos.y);
                this.font.draw(renderer.getContext(), "Skill 1: Increase Health. Current Level: " + game.data.exp1 + "Cost: " + ((game.data.exp1) * 10), this.pos.x, this.pos.y + 40);
                this.font.draw(renderer.getContext(), "Skill 2: Increase Speed. Current Level: " + game.data.exp2 + "Cost: " + ((game.data.exp2) * 10), this.pos.x, this.pos.y + 80);
                this.font.draw(renderer.getContext(), "Skill 3: Increase Damage. Current Level: " + game.data.exp3 + "Cost: " + ((game.data.exp3) * 10), this.pos.x, this.pos.y + 120);
                this.font.draw(renderer.getContext(), "Q Ability: Speed Burst! Current Level: " + game.data.ability2 + "Cost: " + ((game.data.ability1+1) * 10), this.pos.x, this.pos.y + 160);
                this.font.draw(renderer.getContext(), "W Ability: Eat Creep for Health! Current Level:" + game.data.ability2 + "Cost: " + ((game.data.ability2+1) * 10), this.pos.x, this.pos.y + 200);
                this.font.draw(renderer.getContext(), "E Ability: Throw your Spear! Current Level:" + game.data.ability3 + "Cost: " + ((game.data.ability3+1) * 10), this.pos.x, this.pos.y + 240);
            }
        }));
        me.game.world.addChild(game.data.buytext, 35);
    },

    stopBuying: function(){
        this.buying = false;
        me.state.resume(me.state.PLAY);
        game.data.player.body.setVelocity(game.data.playerMoveSpeed, 20);
        me.game.world.removeChild(game.data.buyscreen);
        me.input.unbindKey(me.input.KEY. F1, "F1", true);
        me.input.unbindKey(me.input.KEY. F2, "F2", true);
        me.input.unbindKey(me.input.KEY. F3, "F3", true);
        me.input.unbindKey(me.input.KEY. F4, "F4", true);
        me.input.unbindKey(me.input.KEY. F5, "F5", true);
        me.input.unbindKey(me.input.KEY. F6, "F6", true);
        me.game.world.removeChild(game.data.buytext);
    },

});<commit_msg>Video 50 In Progress<commit_after>game.GameTimerManager = Object.extend({
    init: function(x, y, settings) {
        this.now = new Date().getTime();
        this.lastCreep = new Date().getTime();
        this.paused = false;
        this.alwaysUpdate = true;
    },
    update: function() {
        this.now = new Date().getTime();
        this.addGold();
        this.addCreep();
        return true;
    },
    addGold: function() {
        if (Math.round(this.now / 1000) % 20 === 0 && (this.now - this.lastCreep >= 1000)) {
            game.data.gold += (game.data.exp1 + 1);
            console.log("Current gold:" + game.data.gold);
        }
    },
    addCreep: function() {
        if (Math.round(this.now / 1000) % 10 === 0 && (this.now - this.lastCreep >= 1000)) {
            this.lastCreep = this.now;
            var creep = me.pool.pull("EnemyCreep", 1000, 0, {});
            me.game.world.addChild(creep, 5);
        }
    },
});

game.HeroDeathManager = Object.extend({
    init: function(x, y, settings) {
        this.alwaysUpdate = true;
    },
    update: function() {
        if (game.data.player.dead) {
            me.game.world.removeChild(game.data.player);
            me.state.current().resetPlayer(10, 0);
        }
        return true;
    }
});

game.ExperienceManager = Object.extend({
    init: function(x, y, settings) {
        this.alwaysUpdate = true;
        this.gameover = false;
    },
    update: function() {
        if (game.data.win === true && !this.gameover) {
            this.gameOver(true);
        } else if (game.data.win == false && !this.gameover) {
            this.gameOver(false);
        }
        return true;
    },

    gameOver: function(win) {
        if(win){
           game.data.exp += 10;
        }else{
           game.data.exp += 1;
        }

        this.gameOver = true;
        me.save.exp = game.data.exp;
    }
});

game.SpendGold = Object.extend({
    init: function(x, y, settings) {
        this.now = new Date().getTime();
        this.lastBuy = new Date().getTime();
        this.paused = false;
        this.alwaysUpdate = true;
        this.updateWhenPaused = true;
        this.buying = false;
    },

    update: function(){
        this.now = new Date().getTime();
        if(me.input.isKeyPressed("buy") && this.now-this.lastBuy >= 1000){
            this.lastBuy = this.now;
            if(!this.buying){
                this.startBuying();
            }else{
                this.stopBuying();
            }

        }
        this.checkBuyKeys();

        return true;
    },

    startBuying: function(){
        this.buying = true;
        me.state.pause(me.state.PLAY);
        game.data.pausePos = me.game.viewport.localToWorld(0, 0);
        game.data.buyscreen = new me.Sprite(game.data.pausePos.x, game.data.pausePos.y, me.loader.getImage("gold-screen"));
        game.data.buyscreen.updateWhenPaused = true;
        game.data.buyscreen.setOpacity(0.8);
        me.game.world.addChild(game.data.buyscreen, 34);
        game.data.player.body.setVelocity(0, 0);
        me.input.bindKey(me.input.KEY. F1, "F1", true);
        me.input.bindKey(me.input.KEY. F2, "F2", true);
        me.input.bindKey(me.input.KEY. F3, "F3", true);
        me.input.bindKey(me.input.KEY. F4, "F4", true);
        me.input.bindKey(me.input.KEY. F5, "F5", true);
        me.input.bindKey(me.input.KEY. F6, "F6", true);
        this.setBuyText();
    },

    setBuyText: function(){
        game.data.buytext = new (me.Renderable.extend({
            init: function() {
                this._super(me.Renderable, 'init', [game.data.pausePos.x, game.data.pausePos.y, 300, 50]);
                this.font = new me.Font("Arial", 26, "white");
                this.updateWhenPaused = true;
                this.alwaysUpdate;
            },
            draw: function(renderer) {
                this.font.draw(renderer.getContext(), "Press F1-F6 to Buy, Press B to Exit.  Current Gold: " + game.data.gold, this.pos.x, this.pos.y);
                this.font.draw(renderer.getContext(), "Skill 1: Increase Health. Current Level: " + game.data.skill1 + "Cost: " + ((game.data.skill1+1) * 10), this.pos.x, this.pos.y + 40);
                this.font.draw(renderer.getContext(), "Skill 2: Increase Speed. Current Level: " + game.data.skill2 + "Cost: " + ((game.data.skill2+1) * 10), this.pos.x, this.pos.y + 80);
                this.font.draw(renderer.getContext(), "Skill 3: Increase Damage. Current Level: " + game.data.skill3 + "Cost: " + ((game.data.skill3+1) * 10), this.pos.x, this.pos.y + 120);
                this.font.draw(renderer.getContext(), "Q Ability: Speed Burst! Current Level: " + game.data.ability2 + "Cost: " + ((game.data.ability1+1) * 10), this.pos.x, this.pos.y + 160);
                this.font.draw(renderer.getContext(), "W Ability: Eat Creep for Health! Current Level:" + game.data.ability2 + "Cost: " + ((game.data.ability2+1) * 10), this.pos.x, this.pos.y + 200);
                this.font.draw(renderer.getContext(), "E Ability: Throw your Spear! Current Level:" + game.data.ability3 + "Cost: " + ((game.data.ability3+1) * 10), this.pos.x, this.pos.y + 240);
            }
        }));
        me.game.world.addChild(game.data.buytext, 35);
    },

    stopBuying: function(){
        this.buying = false;
        me.state.resume(me.state.PLAY);
        game.data.player.body.setVelocity(game.data.playerMoveSpeed, 20);
        me.game.world.removeChild(game.data.buyscreen);
        me.input.unbindKey(me.input.KEY. F1, "F1", true);
        me.input.unbindKey(me.input.KEY. F2, "F2", true);
        me.input.unbindKey(me.input.KEY. F3, "F3", true);
        me.input.unbindKey(me.input.KEY. F4, "F4", true);
        me.input.unbindKey(me.input.KEY. F5, "F5", true);
        me.input.unbindKey(me.input.KEY. F6, "F6", true);
        me.game.world.removeChild(game.data.buytext);
    },

    checkBuyKeys: function(){
        if(me.input.isKeyPressed("F1")){
            if(this.checkCost(1)){
                this.makePurchase(1);
            }
        }else if(me.input.isKeyPressed("F2")){
            if(this.checkCost(2)){
                this.makePurchase(2);
            }
        }else if(me.input.isKeyPressed("F2")){
            if(this.checkCost(2)){
                this.makePurchase(2);
            }
        }else if(me.input.isKeyPressed("F3")){
            if(this.checkCost(3)){
                this.makePurchase(3);
            }
        }else if(me.input.isKeyPressed("F4")){
            if(this.checkCost(4)){
                this.makePurchase(4);
            }
        }else if(me.input.isKeyPressed("F5")){
            if(this.checkCost(5)){
                this.makePurchase(5);
            }
        }else if(me.input.isKeyPressed("F6")){
            if(this.checkCost(6)){
                this.makePurchase(6);
            }
        }
    },

    checkCost: function(skill){
        if(skill===1 && (game.data.gold >= ((game.data.skill1+1) * 10))){
            return true;
        }else if(skill===2 && (game.data.gold >= ((game.data.skill2+1) * 10))){
            return true;
        }else if(skill===3 && (game.data.gold >= ((game.data.skill3+1) * 10))){
            return true;
        }else if(skill===4 && (game.data.gold >= ((game.data.skill4+1) * 10))){
            return true;
        }else if(skill===5 && (game.data.gold >= ((game.data.skill5+1) * 10))){
            return true;
        }else if(skill===6 && (game.data.gold >= ((game.data.skill6+1) * 10))){
            return true;
        }else{
            return false;
        }
    },

    makePurchase: function(skill){

    }

});<|endoftext|>


<commit_before>"use strict"

var ndarray = require("ndarray")
var createBuffer = require("gl-buffer")
var createVAO = require("gl-vao")
var createAOMesh = require("./mesh.js")
var ops = require("ndarray-ops")
var glm = require("gl-matrix")
var mat4 = glm.mat4

//Creates a mesh from a set of voxels
function createVoxelMesh(gl, voxels, voxelSideTextureIDs, voxelSideTextureSizes, position) {
  //Create mesh
  var vert_data = createAOMesh(voxels, voxelSideTextureIDs, voxelSideTextureSizes)
  if (vert_data === null) return null // no vertices allocated

  //Upload triangle mesh to WebGL
  var triangleVertexCount = Math.floor(vert_data.length/8)
  var vert_buf = createBuffer(gl, vert_data)
  var triangleVAO = createVAO(gl, [
    { "buffer": vert_buf,
      "type": gl.UNSIGNED_BYTE,
      "size": 4,
      "offset": 0,
      "stride": 8,
      "normalized": false
    },
    { "buffer": vert_buf,
      "type": gl.UNSIGNED_BYTE,
      "size": 4,
      "offset": 4,
      "stride": 8,
      "normalized": false
    }
  ])

  //Create wire mesh
  var wireVertexCount = 2 * triangleVertexCount
  var wireVertexArray = ndarray(new Uint8Array(wireVertexCount * 3), [triangleVertexCount, 2, 3])
  var trianglePositions = ndarray(vert_data, [triangleVertexCount, 3], [8, 1], 0)
  ops.assign(wireVertexArray.pick(undefined, 0, undefined), trianglePositions)
  var wires = wireVertexArray.pick(undefined, 1, undefined)
  for(var i=0; i<3; ++i) {
    ops.assign(wires.lo(i).step(3), trianglePositions.lo((i+1)%3).step(3))
  }
  var wireBuf = createBuffer(gl, wireVertexArray.data)
  var wireVAO = createVAO(gl, [
    { "buffer": wireBuf,
      "type": gl.UNSIGNED_BYTE,
      "size": 3,
      "offset": 0,
      "stride": 3,
      "normalized": false
    }
  ])

  var modelMatrix = mat4.create()
  mat4.translate(modelMatrix, modelMatrix, position)

  //Bundle result and return
  var result = {
    triangleVertexCount: triangleVertexCount,
    triangleVAO: triangleVAO,
    wireVertexCount: wireVertexCount,
    wireVAO: wireVAO,
    center: [voxels.shape[0]>>1, voxels.shape[1]>>1, voxels.shape[2]>>1],
    radius: voxels.shape[2],
    modelMatrix: modelMatrix
  }
  return result
}

module.exports = createVoxelMesh
<commit_msg>Scale position by chunk size<commit_after>"use strict"

var ndarray = require("ndarray")
var createBuffer = require("gl-buffer")
var createVAO = require("gl-vao")
var createAOMesh = require("./mesh.js")
var ops = require("ndarray-ops")
var glm = require("gl-matrix")
var mat4 = glm.mat4

//Creates a mesh from a set of voxels
function createVoxelMesh(gl, voxels, voxelSideTextureIDs, voxelSideTextureSizes, position) {
  //Create mesh
  var vert_data = createAOMesh(voxels, voxelSideTextureIDs, voxelSideTextureSizes)
  if (vert_data === null) return null // no vertices allocated

  //Upload triangle mesh to WebGL
  var triangleVertexCount = Math.floor(vert_data.length/8)
  var vert_buf = createBuffer(gl, vert_data)
  var triangleVAO = createVAO(gl, [
    { "buffer": vert_buf,
      "type": gl.UNSIGNED_BYTE,
      "size": 4,
      "offset": 0,
      "stride": 8,
      "normalized": false
    },
    { "buffer": vert_buf,
      "type": gl.UNSIGNED_BYTE,
      "size": 4,
      "offset": 4,
      "stride": 8,
      "normalized": false
    }
  ])

  //Create wire mesh
  var wireVertexCount = 2 * triangleVertexCount
  var wireVertexArray = ndarray(new Uint8Array(wireVertexCount * 3), [triangleVertexCount, 2, 3])
  var trianglePositions = ndarray(vert_data, [triangleVertexCount, 3], [8, 1], 0)
  ops.assign(wireVertexArray.pick(undefined, 0, undefined), trianglePositions)
  var wires = wireVertexArray.pick(undefined, 1, undefined)
  for(var i=0; i<3; ++i) {
    ops.assign(wires.lo(i).step(3), trianglePositions.lo((i+1)%3).step(3))
  }
  var wireBuf = createBuffer(gl, wireVertexArray.data)
  var wireVAO = createVAO(gl, [
    { "buffer": wireBuf,
      "type": gl.UNSIGNED_BYTE,
      "size": 3,
      "offset": 0,
      "stride": 3,
      "normalized": false
    }
  ])

  // move the chunk into place
  var modelMatrix = mat4.create()
  mat4.translate(modelMatrix, modelMatrix, [
      position[0] * (voxels.shape[0] - 1), // TODO: fix
      position[1] * (voxels.shape[1] - 1),
      position[2] * (voxels.shape[2] - 1)])

  //Bundle result and return
  var result = {
    triangleVertexCount: triangleVertexCount,
    triangleVAO: triangleVAO,
    wireVertexCount: wireVertexCount,
    wireVAO: wireVAO,
    center: [voxels.shape[0]>>1, voxels.shape[1]>>1, voxels.shape[2]>>1],
    radius: voxels.shape[2],
    modelMatrix: modelMatrix
  }
  return result
}

module.exports = createVoxelMesh
<|endoftext|>


<commit_before>/* global env */
exports.publish = publish;

var logger = require('jsdoc/util/logger');
var helper = require('jsdoc/util/templateHelper');
var path = require('canonical-path');
var _ = require('lodash');
var deasync = require('deasync');
var fs = require('fs');
var mkdirp = require('mkdirp');
var util = require('./util');
var async = require('async');

var context;

/**
 * @param {TAFFY} taffyData See <http://taffydb.com/>.
 * @param {object} options JSDoc passed options
 * @param {Tutorial} tutorials List of tutorial
 * @return {undefined}
 */
function publish(taffyData, options, tutorials) {
  logger.debug('Tutorials', tutorials);
  logger.debug('Options', options);

  // Use .rst as default extension
  helper.fileExtension = '.rst';

  // README.rst must be kept as it is.
  var readme = _.find(env.opts._, /README.rst/);
  if (readme) {
    logger.debug('Load README.rst file:', readme);
    options.readme = fs.readFileSync(readme);
  }

  // define a global context that should be available by all function
  context = _.extend({
    data: taffyData
  }, options);

  // Augment data with needed informations
  context.data().each(registerLink);

  _.each(helper.find(context.data, {kind: 'function'}), improveFunc);
  _.each(helper.find(context.data, {kind: 'member'}), improveFunc);

  function improveFunc(doclet) {
    doclet.signature = doclet.name + '(';
    _.each(doclet.params, function(p, i) {
      if (!(p && p.type && p.type.names)) {
        logger.debug('Bad parameter', p, doclet.longname);
        return;
      }
      p.signature = ':param ' + p.type && p.type.names && p.type.names.join('|');
      p.signature += ' ' + p.name;

      if (p.optional) {
        doclet.signature += '[';
      }
      if (i > 0) {
        doclet.signature += ', ';
      }
      doclet.signature += p.name;
      if (p.optional) {
        doclet.signature += ']';
      }
      return p.name;
    });
    doclet.signature += ')';

    _.each(doclet.returns, function(r) {
      if (!(r && r.type && r.type.names)) {
        logger.debug('Bad return', r, doclet.longname);
        return;
      }
      r.signature = ':return ' + r.type && r.type.names && r.type.names.join('|');
    });

  }

  // build the list of page generation actions.
  var actions = [];
  actions.push(generate(helper.getUniqueFilename('index'), require('./view-models/home')));
  actions.push(generate('conf.py', require('./view-models/sphinx-config')));
  var docletModel = require('./view-models/doclet');
  context.data().each(function(doclet) {
    var url = helper.longnameToUrl[doclet.longname];
    if (url.indexOf('#') > -1) {
        url = helper.longnameToUrl[doclet.longname].split(/#/).pop();
    }
    if (util.mainDocletKinds.indexOf(doclet.kind) !== -1) {
      actions.push(generate(url, docletModel(doclet)));
    }
  });

  // publish must be synchronous as the caller does not care about callbacks.
  deasync(function(cb) {
    async.parallel(actions, cb);
  })();
}

function generate(target, generator) {
  return function(cb) {
    logger.debug('generate', target);
    generator(context, handleErrorCallback(function(err, data) {
      if(err) {
        logger.error('cannot generate ' + target);
        logger.debug(err);
        return;
      }
      write(target, data, cb);
    }));
  };
}

function registerLink(doclet) {
    var url = helper.createLink(doclet);
    helper.registerLink(doclet.longname, url);
    doclet.rstLink = url.substr(0, url.length - helper.fileExtension.length);
}

/**
 * Handle all write operations.
 *
 * @private
 * @param {string}   relPath Relative path in the ouput directory
 * @param {string}   data    File content
 * @param {publish.writeCallback} cb node fs.write compatible callback
 * @return {undefined}
 */
function write(relPath, data, cb) {
  var target = path.join(context.destination, relPath);

  mkdirp(path.dirname(target), handleErrorCallback(function() {
    fs.writeFileSync(target, data);
    handleErrorCallback(cb)(null, target);
    logger.debug('file written: %s', target);
  }));
}

function handleErrorCallback(cb) {
  return function(err) {
    if (err) {
      logger.error(err);
      return cb(err);
    }
    return cb.apply(this, arguments);
  };
}

/**
 * @callback errCallback
 * The callback function receive an error as first argument if any.
 *
 * @param {error} err The error cause
 */

/**
 * @callback publish.writeCallback
 * @param {error} err The error cause
 * @param {string} filePath The written file path
 */
<commit_msg>Specifying directory (e.g. for use with jsdoc --recurse) as input caused error<commit_after>/* global env */
exports.publish = publish;

var logger = require('jsdoc/util/logger');
var helper = require('jsdoc/util/templateHelper');
var path = require('canonical-path');
var _ = require('lodash');
var deasync = require('deasync');
var fs = require('fs');
var mkdirp = require('mkdirp');
var util = require('./util');
var async = require('async');

var context;

/**
 * @param {TAFFY} taffyData See <http://taffydb.com/>.
 * @param {object} options JSDoc passed options
 * @param {Tutorial} tutorials List of tutorial
 * @return {undefined}
 */
function publish(taffyData, options, tutorials) {
  logger.debug('Tutorials', tutorials);
  logger.debug('Options', options);

  // Use .rst as default extension
  helper.fileExtension = '.rst';

  // README.rst must be kept as it is.
  var readme = _.find(env.opts._, /README.rst/);
  if (readme && !fs.lstatSync(readme).isDirectory()) {
    logger.debug('Load README.rst file:', readme);
    options.readme = fs.readFileSync(readme);
  }

  // define a global context that should be available by all function
  context = _.extend({
    data: taffyData
  }, options);

  // Augment data with needed informations
  context.data().each(registerLink);

  _.each(helper.find(context.data, {kind: 'function'}), improveFunc);
  _.each(helper.find(context.data, {kind: 'member'}), improveFunc);

  function improveFunc(doclet) {
    doclet.signature = doclet.name + '(';
    _.each(doclet.params, function(p, i) {
      if (!(p && p.type && p.type.names)) {
        logger.debug('Bad parameter', p, doclet.longname);
        return;
      }
      p.signature = ':param ' + p.type && p.type.names && p.type.names.join('|');
      p.signature += ' ' + p.name;

      if (p.optional) {
        doclet.signature += '[';
      }
      if (i > 0) {
        doclet.signature += ', ';
      }
      doclet.signature += p.name;
      if (p.optional) {
        doclet.signature += ']';
      }
      return p.name;
    });
    doclet.signature += ')';

    _.each(doclet.returns, function(r) {
      if (!(r && r.type && r.type.names)) {
        logger.debug('Bad return', r, doclet.longname);
        return;
      }
      r.signature = ':return ' + r.type && r.type.names && r.type.names.join('|');
    });

  }

  // build the list of page generation actions.
  var actions = [];
  actions.push(generate(helper.getUniqueFilename('index'), require('./view-models/home')));
  actions.push(generate('conf.py', require('./view-models/sphinx-config')));
  var docletModel = require('./view-models/doclet');
  context.data().each(function(doclet) {
    var url = helper.longnameToUrl[doclet.longname];
    if (url.indexOf('#') > -1) {
        url = helper.longnameToUrl[doclet.longname].split(/#/).pop();
    }
    if (util.mainDocletKinds.indexOf(doclet.kind) !== -1) {
      actions.push(generate(url, docletModel(doclet)));
    }
  });

  // publish must be synchronous as the caller does not care about callbacks.
  deasync(function(cb) {
    async.parallel(actions, cb);
  })();
}

function generate(target, generator) {
  return function(cb) {
    logger.debug('generate', target);
    generator(context, handleErrorCallback(function(err, data) {
      if(err) {
        logger.error('cannot generate ' + target);
        logger.debug(err);
        return;
      }
      write(target, data, cb);
    }));
  };
}

function registerLink(doclet) {
    var url = helper.createLink(doclet);
    helper.registerLink(doclet.longname, url);
    doclet.rstLink = url.substr(0, url.length - helper.fileExtension.length);
}

/**
 * Handle all write operations.
 *
 * @private
 * @param {string}   relPath Relative path in the ouput directory
 * @param {string}   data    File content
 * @param {publish.writeCallback} cb node fs.write compatible callback
 * @return {undefined}
 */
function write(relPath, data, cb) {
  var target = path.join(context.destination, relPath);

  mkdirp(path.dirname(target), handleErrorCallback(function() {
    fs.writeFileSync(target, data);
    handleErrorCallback(cb)(null, target);
    logger.debug('file written: %s', target);
  }));
}

function handleErrorCallback(cb) {
  return function(err) {
    if (err) {
      logger.error(err);
      return cb(err);
    }
    return cb.apply(this, arguments);
  };
}

/**
 * @callback errCallback
 * The callback function receive an error as first argument if any.
 *
 * @param {error} err The error cause
 */

/**
 * @callback publish.writeCallback
 * @param {error} err The error cause
 * @param {string} filePath The written file path
 */
<|endoftext|>


<commit_before>define(['stream', 'stream/util'], function (Stream, util) {
    "use strict";

    /**
     * Base class for Readable Streams
     * @constructor
     * @param [opts] {object} Configuration options
     * @param [opts.highWaterMark=50] {number} The maximum number of objects to
     *     store in the internal buffer before ceasing to read from upstream
     */
    function Readable (opts) {
        opts = opts || {};
        // This Readable implementation only supports objectMode
        opts.objectMode = true;
        this._readableState = new ReadableState(opts, this);

        this.readable = true;
        Stream.call(this);
    }
    util.inherits(Readable, Stream);

    /**
     * The Default .highWaterMark for Readables
     * This will be used if none is specified on construction
     */
    var DEFAULT_HIGH_WATER_MARK = 50;

    /**
     * Push a chunk onto the end of the internal buffer
     * The _read() function will not be called again until at least one
     *     push(chunk) call is made.
     * The Readable class works by putting data into a read queue to be pulled
     *     out later by calling the read() method when the 'readable' event fires.
     * @param chunk {object} Chunk of data to push into the read queue.
     *     if chunk === null, that signals the end of data
     * @returns {boolean} Whether or not more pushes should be performed
     */
    Readable.prototype.push = function (chunk) {
        return this._addToBuffer(chunk, false);
    };

    /**
     * Push a chunk onto the front of the internal buffer.
     * This is useful in certain cases where a stream is being consumed by a
     * parser, which needs to "un-consume" some data that it has optimistically pulled out of the source, so that the stream can be passed on to some other party.
     * @param chunk {object} Chunk of data to unshift onto the read queue
     * @returns {boolean} Whether or not more pushes should be performed
     */
    Readable.prototype.unshift = function (chunk) {
        return this._addToBuffer(chunk, true);
    };

    /**
     * @private
     * Common implementation shared between .push and .unshift
     * Both methods mutate to read buffer
     * @param chunk {object} Chunk of data to add to the read queue
     * @param addToFront {boolean} Whether to add to the front or back of the
     *     buffer
     * @returns {boolean} Whether this stream should have more data pushed
     *     to it
     */
    Readable.prototype._addToBuffer = function (chunk, addToFront) {
        var state = this._readableState;
        if (chunk === null || chunk === undefined) {
            // End of file.
            state.reading = false;
            // Start wrapping up if we haven't before
            if ( ! state.ended) {
                this._endReadable();
            }
        } else if (state.objectMode || chunk && chunk.length > 0) {
            if (state.ended && ! addToFront) {
                this.emit('error', new Error("readable.push() called after EOF"));
            } else if (state.endEmitted && addToFront) {
                this.emit('error', new Error("readable.unshift() called after end event"));
            } else {
                if (addToFront) {
                    state.buffer.unshift(chunk);
                } else {
                    state.reading = false;
                    state.buffer.push(chunk);
                }
                // Now that we've pushed data to the buffer,
                // let listeners know we're readable
                if (state.needReadable) {
                    this._emitReadable();
                }
                this._maybeReadMore();
            }
        }

        // Return whether
        return ! state.ended &&
               ( state.needReadable ||
                 state.buffer.length < state.highWaterMark ||
                 state.buffer.length === 0);
    };

    /**
     * @private
     * _read() more data from upstream until the buffer length is greater than
     *     the highWaterMark. It triggers this by calling .read(0);
     * This executes on nextTick, not synchronously
     */
    Readable.prototype._maybeReadMore = function () {
        var self = this,
            state = self._readableState;

        if (state.readingMore) {
            return;
        }
        state.readingMore = true;

        util.nextTick(_readMore);

        function _readMore () {
            var len = state.buffer.length;
            while ( ! state.reading && ! state.ended &&
                    state.buffer.length < state.highWaterMark ) {
                // Trigger ._read()
                self.read(0);
                if (len === state.buffer.length) {
                    // self.read(0) didn't add any data
                    break;
                } else {
                    len = state.buffer.length;
                }
            }
            state.readingMore = false;
        }
    };

    /**
     * Bind an event listener to an event on this stream
     * Readable adds some extra functionality so that binding a listener
     *     to 'readable' marks ._readableState.needReadable=true
     * @param eventName {string} The Event name to listen for
     * @param cb {function} Callback function to call when eventName fires
     */
    Readable.prototype.on = function (eventName, cb) {
        var ret = Stream.prototype.on.call(this, eventName, cb),
            state = this._readableState;

        if (eventName === 'readable' && this.readable) {
            // Start reading on the first readable listener
            if ( ! state.readableListening) {
                state.readableListening = true;
                state.emittedReadable = false;
                state.needReadable = true;
                if ( ! state.reading) {
                    this.read(0);
                } else if (state.buffer.length) {
                    this._emitReadable();
                }
            }
        }
    };

    /**
     * Read data from the read buffer
     * @param [size] {number} The number of items to read from the buffer.
     *     If not provided, all data will be returned.
     *     If 0, There are some cases where you want to trigger a refresh of the
     *     underlying readable stream mechanisms, without actually consuming any
     *     data. In that case, you can call stream.read(0), which will always
     *     return null.
     *     If the internal read buffer is below the highWaterMark, and the
     *     stream is not currently reading, then calling read(0) will trigger a
     *     low-level _read call.
     *     There is almost never a need to do this externally.
     * @returns {object|null} An object from the read buffer, or null
     */
    Readable.prototype.read = function (size) {
        var state = this._readableState,
            originalSize = size,
            doRead,
            ret;

        state.calledRead = true;

        if (typeof size !== 'number' || size > 0) {
            // User wants data. We'll need to emit readable
            state.emittedReadable = false;
        }

        if (size === 0 && state.needReadable &&
           (state.buffer.length >= state.highWaterMark || state.ended)) {
            this._emitReadable();
            return null;
        }

        size = this._getSizeToRead(size);

        // If called with 0 once end has been emitted, return null
        if (size === 0 && state.ended) {
            if (state.buffer.length === 0) {
                this._endReadable();
            }
            return null;
        }

        // Determine whether ._read needs to be called to fill up the buffer
        doRead = state.needReadable;

        // We need to read if this read will lower the buffer size
        // below the highWaterMark
        if (state.buffer.length - size <= state.highWaterMark) {
            doRead = true;
        }

        // Never read if already reading or the stream has ended
        if (state.reading || state.ended) {
            doRead = false;
        }

        if (doRead) {
            state.reading = true;
            state.sync = true;
            if (state.buffer.length === 0) {
                state.needReadable = true;
            }
            // Go get more data!
            this._read(state.highWaterMark);
            state.sync = false;
            // state.reading will be falsy if _read executed synchronously
            // This could change the buffer so we recalc size
            if ( ! state.reading) {
                size = this._getSizeToRead(originalSize);
            }
        }

        if (size > 0) {
            ret = this._readFromBuffer(size);
        } else {
            ret = null;
        }

        if (ret === null) {
            state.needReadable = true;
            size = 0;
        }

        // If we have nothing in the buffer, then we want to know
        // as soon as we *do* get something into the buffer.
        if (state.buffer.length === 0 && !state.ended) {
            state.needReadable = true;
        }

        // If we happened to read() exactly the remaining amount in the
        // buffer, and the EOF has been seen at this point, then make sure
        // that we emit 'end' on the very next tick.
        if (state.ended && !state.endEmitted && state.buffer.length === 0) {
            this._endReadable();
        }

        return ret;
    };

    /**
     * @private
     * Fetch data asynchronously from an upstream source.
     * Implement this function, but do NOT call it directly.
     * When data is available, put it into the read queue by calling
     *     readable.push(chunk). If push returns false, then you should stop
     *     reading. When _read is called again, you should start pushing more.
     */
    Readable.prototype._read = function () {
        this.emit('error', new Error('._read() not implemented'));
    };

    /**
     * @private
     * Get data from the internal read buffer
     * @returns {object|null} An object from the internal read buffer, or null
     *     if there is no more on the buffer
     */
    Readable.prototype._readFromBuffer = function () {
        var state = this._readableState,
            buffer = state.buffer;
        if (buffer.length === 0) {
            return null;
        } else {
            return buffer.shift();
        }
    };

    /**
     * @private
     * Get the appropriate number of objects to read from the buffer.
     * @param sizeAskedFor {number} The Number of items asked for by the user
     * @returns {number} The number of objects that should be returned from
     *     .read()
     */
    Readable.prototype._getSizeToRead = function (sizeAskedFor) {
        var state = this._readableState;
        // Don't read anything if there's nothing to read
        if (state.buffer.length === 0 && state.ended) {
            return 0;
        }
        // Assuming objectMode. Return at most one item
        return sizeAskedFor === 0 ? 0 : 1;
    };

    /**
     * @private
     * Cause the stream to emit 'readable'
     */
    Readable.prototype._emitReadable = function () {
        var self = this,
            state = this._readableState;
        state.needReadable = false;
        state.emittedReadable = true;
        if (state.sync) {
            util.nextTick(emitReadable);
        } else {
            emitReadable();
        }
        function emitReadable () {
            self.emit('readable');
        }
    };

    /**
     * @private
     * Mark the stream as closed and that it should not be readable again.
     * Often this happens after this.push(null);
     */
    Readable.prototype._endReadable = function () {
        var state = this._readableState;
        state.ended = true;
        if (state.buffer.length) {
            this._emitReadable();
        } else {
            this._emitEnd();
        }
    };

    /**
     * @private
     * Emit the end event if it hasn't been emitted yet
     */
    Readable.prototype._emitEnd = function () {
        var self = this,
            state = this._readableState;
        if (state.buffer.length > 0) {
            throw new Error("Tried to emit end event on a non-empty Readable");
        }
        if ( ! state.endEmitted && state.calledRead) {
            state.ended = true;
            util.nextTick(function () {
                // Check that we didn't get one last unshift.
                if (!state.endEmitted && state.buffer.length === 0) {
                    state.endEmitted = true;
                    self.readable = false;
                    self.emit('end');
                }
            });
        }
    };

    /**
     * The state objects contain other useful information for debugging the
     * state of streams in your programs. It is safe to look at them, but beyond
     * setting option flags in the constructor, it is not safe to modify them.
     * Copied from http://bit.ly/16eA5K7
     */
    function ReadableState(opts, stream) {
        opts = opts || {};

        // the point at which it stops calling _read() to fill the buffer
        // Note: 0 is a valid value, means "don't call _read preemptively ever"
        var hwm = opts.highWaterMark;
        this.highWaterMark = (hwm || hwm === 0) ? hwm : DEFAULT_HIGH_WATER_MARK;

        // cast to ints.
        this.highWaterMark = ~~this.highWaterMark;

        this.buffer = [];
        this.pipes = null;
        this.pipesCount = 0;
        this.flowing = false;
        this.ended = false;
        this.endEmitted = false;
        this.reading = false;

        // In streams that never have any data, and do push(null) right away,
        // the consumer can miss the 'end' event if they do some I/O before
        // consuming the stream.  So, we don't emit('end') until some reading
        // happens.
        this.calledRead = false;

        // a flag to be able to tell if the onwrite cb is called immediately,
        // or on a later tick.  We set this to true at first, becuase any
        // actions that shouldn't happen until "later" should generally also
        // not happen before the first write call.
        this.sync = true;

        // whenever we return null, then we set a flag to say
        // that we're awaiting a 'readable' event emission.
        this.needReadable = false;
        this.emittedReadable = false;
        this.readableListening = false;

        // object stream flag. Used to make read(n) ignore n and to
        // make all the buffer merging and length checks go away
        this.objectMode = !!opts.objectMode;

        // Crypto is kind of old and crusty.  Historically, its default string
        // encoding is 'binary' so we have to make this configurable.
        // Everything else in the universe uses 'utf8', though.
        this.defaultEncoding = opts.defaultEncoding || 'utf8';

        // when piping, we only care about 'readable' events that happen
        // after read()ing all the bytes and not getting any pushback.
        this.ranOut = false;

        // the number of writers that are awaiting a drain event in .pipe()s
        this.awaitDrain = 0;

        // if true, a maybeReadMore has been scheduled
        this.readingMore = false;

        this.decoder = null;
        this.encoding = null;
    }

    return Readable;
});<commit_msg>Fix doc in _read<commit_after>define(['stream', 'stream/util'], function (Stream, util) {
    "use strict";

    /**
     * Base class for Readable Streams
     * @constructor
     * @param [opts] {object} Configuration options
     * @param [opts.highWaterMark=50] {number} The maximum number of objects to
     *     store in the internal buffer before ceasing to read from upstream
     */
    function Readable (opts) {
        opts = opts || {};
        // This Readable implementation only supports objectMode
        opts.objectMode = true;
        this._readableState = new ReadableState(opts, this);

        this.readable = true;
        Stream.call(this);
    }
    util.inherits(Readable, Stream);

    /**
     * The Default .highWaterMark for Readables
     * This will be used if none is specified on construction
     */
    var DEFAULT_HIGH_WATER_MARK = 50;

    /**
     * Push a chunk onto the end of the internal buffer
     * The _read() function will not be called again until at least one
     *     push(chunk) call is made.
     * The Readable class works by putting data into a read queue to be pulled
     *     out later by calling the read() method when the 'readable' event fires.
     * @param chunk {object} Chunk of data to push into the read queue.
     *     if chunk === null, that signals the end of data
     * @returns {boolean} Whether or not more pushes should be performed
     */
    Readable.prototype.push = function (chunk) {
        return this._addToBuffer(chunk, false);
    };

    /**
     * Push a chunk onto the front of the internal buffer.
     * This is useful in certain cases where a stream is being consumed by a
     * parser, which needs to "un-consume" some data that it has optimistically pulled out of the source, so that the stream can be passed on to some other party.
     * @param chunk {object} Chunk of data to unshift onto the read queue
     * @returns {boolean} Whether or not more pushes should be performed
     */
    Readable.prototype.unshift = function (chunk) {
        return this._addToBuffer(chunk, true);
    };

    /**
     * @private
     * Common implementation shared between .push and .unshift
     * Both methods mutate to read buffer
     * @param chunk {object} Chunk of data to add to the read queue
     * @param addToFront {boolean} Whether to add to the front or back of the
     *     buffer
     * @returns {boolean} Whether this stream should have more data pushed
     *     to it
     */
    Readable.prototype._addToBuffer = function (chunk, addToFront) {
        var state = this._readableState;
        if (chunk === null || chunk === undefined) {
            // End of file.
            state.reading = false;
            // Start wrapping up if we haven't before
            if ( ! state.ended) {
                this._endReadable();
            }
        } else if (state.objectMode || chunk && chunk.length > 0) {
            if (state.ended && ! addToFront) {
                this.emit('error', new Error("readable.push() called after EOF"));
            } else if (state.endEmitted && addToFront) {
                this.emit('error', new Error("readable.unshift() called after end event"));
            } else {
                if (addToFront) {
                    state.buffer.unshift(chunk);
                } else {
                    state.reading = false;
                    state.buffer.push(chunk);
                }
                // Now that we've pushed data to the buffer,
                // let listeners know we're readable
                if (state.needReadable) {
                    this._emitReadable();
                }
                this._maybeReadMore();
            }
        }

        // Return whether
        return ! state.ended &&
               ( state.needReadable ||
                 state.buffer.length < state.highWaterMark ||
                 state.buffer.length === 0);
    };

    /**
     * @private
     * _read() more data from upstream until the buffer length is greater than
     *     the highWaterMark. It triggers this by calling .read(0);
     * This executes on nextTick, not synchronously
     */
    Readable.prototype._maybeReadMore = function () {
        var self = this,
            state = self._readableState;

        if (state.readingMore) {
            return;
        }
        state.readingMore = true;

        util.nextTick(_readMore);

        function _readMore () {
            var len = state.buffer.length;
            while ( ! state.reading && ! state.ended &&
                    state.buffer.length < state.highWaterMark ) {
                // Trigger ._read()
                self.read(0);
                if (len === state.buffer.length) {
                    // self.read(0) didn't add any data
                    break;
                } else {
                    len = state.buffer.length;
                }
            }
            state.readingMore = false;
        }
    };

    /**
     * Bind an event listener to an event on this stream
     * Readable adds some extra functionality so that binding a listener
     *     to 'readable' marks ._readableState.needReadable=true
     * @param eventName {string} The Event name to listen for
     * @param cb {function} Callback function to call when eventName fires
     */
    Readable.prototype.on = function (eventName, cb) {
        var ret = Stream.prototype.on.call(this, eventName, cb),
            state = this._readableState;

        if (eventName === 'readable' && this.readable) {
            // Start reading on the first readable listener
            if ( ! state.readableListening) {
                state.readableListening = true;
                state.emittedReadable = false;
                state.needReadable = true;
                if ( ! state.reading) {
                    this.read(0);
                } else if (state.buffer.length) {
                    this._emitReadable();
                }
            }
        }
    };

    /**
     * Read data from the read buffer
     * @param [size] {number} The number of items to read from the buffer.
     *     If not provided, all data will be returned.
     *     If 0, There are some cases where you want to trigger a refresh of the
     *     underlying readable stream mechanisms, without actually consuming any
     *     data. In that case, you can call stream.read(0), which will always
     *     return null.
     *     If the internal read buffer is below the highWaterMark, and the
     *     stream is not currently reading, then calling read(0) will trigger a
     *     low-level _read call.
     *     There is almost never a need to do this externally.
     * @returns {object|null} An object from the read buffer, or null
     */
    Readable.prototype.read = function (size) {
        var state = this._readableState,
            originalSize = size,
            doRead,
            ret;

        state.calledRead = true;

        if (typeof size !== 'number' || size > 0) {
            // User wants data. We'll need to emit readable
            state.emittedReadable = false;
        }

        if (size === 0 && state.needReadable &&
           (state.buffer.length >= state.highWaterMark || state.ended)) {
            this._emitReadable();
            return null;
        }

        size = this._getSizeToRead(size);

        // If called with 0 once end has been emitted, return null
        if (size === 0 && state.ended) {
            if (state.buffer.length === 0) {
                this._endReadable();
            }
            return null;
        }

        // Determine whether ._read needs to be called to fill up the buffer
        doRead = state.needReadable;

        // We need to read if this read will lower the buffer size
        // below the highWaterMark
        if (state.buffer.length - size <= state.highWaterMark) {
            doRead = true;
        }

        // Never read if already reading or the stream has ended
        if (state.reading || state.ended) {
            doRead = false;
        }

        if (doRead) {
            state.reading = true;
            state.sync = true;
            if (state.buffer.length === 0) {
                state.needReadable = true;
            }
            // Go get more data!
            this._read(state.highWaterMark);
            state.sync = false;
            // state.reading will be falsy if _read executed synchronously
            // This could change the buffer so we recalc size
            if ( ! state.reading) {
                size = this._getSizeToRead(originalSize);
            }
        }

        if (size > 0) {
            ret = this._readFromBuffer(size);
        } else {
            ret = null;
        }

        if (ret === null) {
            state.needReadable = true;
            size = 0;
        }

        // If we have nothing in the buffer, then we want to know
        // as soon as we *do* get something into the buffer.
        if (state.buffer.length === 0 && !state.ended) {
            state.needReadable = true;
        }

        // If we happened to read() exactly the remaining amount in the
        // buffer, and the EOF has been seen at this point, then make sure
        // that we emit 'end' on the very next tick.
        if (state.ended && !state.endEmitted && state.buffer.length === 0) {
            this._endReadable();
        }

        return ret;
    };

    /**
     * @private
     * Fetch data asynchronously from an upstream source.
     * Implement this function, but do NOT call it directly.
     * When data is available, put it into the read queue by calling
     *     readable.push(chunk). If push returns false, then you should stop
     *     pushing. When _read is called again, you should start pushing more.
     */
    Readable.prototype._read = function () {
        this.emit('error', new Error('._read() not implemented'));
    };

    /**
     * @private
     * Get data from the internal read buffer
     * @returns {object|null} An object from the internal read buffer, or null
     *     if there is no more on the buffer
     */
    Readable.prototype._readFromBuffer = function () {
        var state = this._readableState,
            buffer = state.buffer;
        if (buffer.length === 0) {
            return null;
        } else {
            return buffer.shift();
        }
    };

    /**
     * @private
     * Get the appropriate number of objects to read from the buffer.
     * @param sizeAskedFor {number} The Number of items asked for by the user
     * @returns {number} The number of objects that should be returned from
     *     .read()
     */
    Readable.prototype._getSizeToRead = function (sizeAskedFor) {
        var state = this._readableState;
        // Don't read anything if there's nothing to read
        if (state.buffer.length === 0 && state.ended) {
            return 0;
        }
        // Assuming objectMode. Return at most one item
        return sizeAskedFor === 0 ? 0 : 1;
    };

    /**
     * @private
     * Cause the stream to emit 'readable'
     */
    Readable.prototype._emitReadable = function () {
        var self = this,
            state = this._readableState;
        state.needReadable = false;
        state.emittedReadable = true;
        if (state.sync) {
            util.nextTick(emitReadable);
        } else {
            emitReadable();
        }
        function emitReadable () {
            self.emit('readable');
        }
    };

    /**
     * @private
     * Mark the stream as closed and that it should not be readable again.
     * Often this happens after this.push(null);
     */
    Readable.prototype._endReadable = function () {
        var state = this._readableState;
        state.ended = true;
        if (state.buffer.length) {
            this._emitReadable();
        } else {
            this._emitEnd();
        }
    };

    /**
     * @private
     * Emit the end event if it hasn't been emitted yet
     */
    Readable.prototype._emitEnd = function () {
        var self = this,
            state = this._readableState;
        if (state.buffer.length > 0) {
            throw new Error("Tried to emit end event on a non-empty Readable");
        }
        if ( ! state.endEmitted && state.calledRead) {
            state.ended = true;
            util.nextTick(function () {
                // Check that we didn't get one last unshift.
                if (!state.endEmitted && state.buffer.length === 0) {
                    state.endEmitted = true;
                    self.readable = false;
                    self.emit('end');
                }
            });
        }
    };

    /**
     * The state objects contain other useful information for debugging the
     * state of streams in your programs. It is safe to look at them, but beyond
     * setting option flags in the constructor, it is not safe to modify them.
     * Copied from http://bit.ly/16eA5K7
     */
    function ReadableState(opts, stream) {
        opts = opts || {};

        // the point at which it stops calling _read() to fill the buffer
        // Note: 0 is a valid value, means "don't call _read preemptively ever"
        var hwm = opts.highWaterMark;
        this.highWaterMark = (hwm || hwm === 0) ? hwm : DEFAULT_HIGH_WATER_MARK;

        // cast to ints.
        this.highWaterMark = ~~this.highWaterMark;

        this.buffer = [];
        this.pipes = null;
        this.pipesCount = 0;
        this.flowing = false;
        this.ended = false;
        this.endEmitted = false;
        this.reading = false;

        // In streams that never have any data, and do push(null) right away,
        // the consumer can miss the 'end' event if they do some I/O before
        // consuming the stream.  So, we don't emit('end') until some reading
        // happens.
        this.calledRead = false;

        // a flag to be able to tell if the onwrite cb is called immediately,
        // or on a later tick.  We set this to true at first, becuase any
        // actions that shouldn't happen until "later" should generally also
        // not happen before the first write call.
        this.sync = true;

        // whenever we return null, then we set a flag to say
        // that we're awaiting a 'readable' event emission.
        this.needReadable = false;
        this.emittedReadable = false;
        this.readableListening = false;

        // object stream flag. Used to make read(n) ignore n and to
        // make all the buffer merging and length checks go away
        this.objectMode = !!opts.objectMode;

        // Crypto is kind of old and crusty.  Historically, its default string
        // encoding is 'binary' so we have to make this configurable.
        // Everything else in the universe uses 'utf8', though.
        this.defaultEncoding = opts.defaultEncoding || 'utf8';

        // when piping, we only care about 'readable' events that happen
        // after read()ing all the bytes and not getting any pushback.
        this.ranOut = false;

        // the number of writers that are awaiting a drain event in .pipe()s
        this.awaitDrain = 0;

        // if true, a maybeReadMore has been scheduled
        this.readingMore = false;

        this.decoder = null;
        this.encoding = null;
    }

    return Readable;
});<|endoftext|>


<commit_before>const axios = require('axios');
const Boom = require('boom');
const cacheHeaders = require('./route-helpers/cache-control');

// Article endpoints on each museum website
var endpoints = [
  { label: 'National Science and Media Museum', url: 'https://www.scienceandmediamuseum.org.uk/collection-media/collection-usage/objects' },
  { label: 'Science and Industry Musem', url: 'https://www.scienceandindustrymuseum.org.uk/collection-media/collection-usage/objects' },
  { label: 'Science Museum', url: 'https://www.sciencemuseum.org.uk/collection-media/collection-usage/objects' },
  { label: 'Railway Museum', url: 'https://www.railwaymuseum.org.uk/collection-media/collection-usage/objects' },
  { label: 'Science Museum Blog', url: 'https://blog.sciencemuseum.org.uk/wp-json/collection-media/collection-usage' }
  // { label: 'Learning Resources', url: 'https://learning-resources.sciencemuseum.org.uk/wp-json/collection-media/collection-usage' },
  // { label: 'Railway Museum Blog', url: 'https://blog.railwaymuseum.org.uk/wp-json/collection-media/collection-usage' }
  // { label: 'National Science and Media Museum', url: 'https://www.scienceandmediamuseum.org.uk/collection-media/collection-usage/objects' },
  // { label: 'Science and Industry Musem Blog', url: 'https://blog.scienceandindustrymuseum.org.uk/wp-json/collection-media/collection-usage' }
];

module.exports = (config) => ({
  method: 'GET',
  path: '/articles/{id}',
  config: {
    cache: cacheHeaders(config, 3600 * 12),
    handler: async function (req, h) {
      try {
        const articles = await Promise.all(endpoints.map(e => fetchArticles(e, req.params.id)));
        return h.response({ data: articles.filter(e => e.data.length > 0) });
      } catch (err) {
        return new Boom('Cannot parse related objects feed:', err);
      }
    }
  }
});

async function fetchArticles (endpoint, id) {
  try {
    const aclient = axios.create({
      timeout: 10000,
      headers: { 'User-Agent': 'SMG Collection Site 1.0' }
    });
    const response = await aclient.get(endpoint.url);
    const data = response.data ? response.data.filter(e => e.collection_objects.indexOf(id) > -1) : [];

    return {
      museum: endpoint.label,
      data: data
    };
  } catch (err) {
    console.log(err);
    throw err;
  }
}
<commit_msg>Adds learning resources url back<commit_after>const axios = require('axios');
const Boom = require('boom');
const cacheHeaders = require('./route-helpers/cache-control');

// Article endpoints on each museum website
var endpoints = [
  { label: 'National Science and Media Museum', url: 'https://www.scienceandmediamuseum.org.uk/collection-media/collection-usage/objects' },
  { label: 'Science and Industry Musem', url: 'https://www.scienceandindustrymuseum.org.uk/collection-media/collection-usage/objects' },
  { label: 'Science Museum', url: 'https://www.sciencemuseum.org.uk/collection-media/collection-usage/objects' },
  { label: 'Railway Museum', url: 'https://www.railwaymuseum.org.uk/collection-media/collection-usage/objects' },
  { label: 'Science Museum Blog', url: 'https://blog.sciencemuseum.org.uk/wp-json/collection-media/collection-usage' },
  { label: 'Learning Resources', url: 'https://learning-resources.sciencemuseum.org.uk/wp-json/collection-media/collection-usage' }
  // { label: 'Railway Museum Blog', url: 'https://blog.railwaymuseum.org.uk/wp-json/collection-media/collection-usage' }
  // { label: 'National Science and Media Museum', url: 'https://www.scienceandmediamuseum.org.uk/collection-media/collection-usage/objects' },
  // { label: 'Science and Industry Musem Blog', url: 'https://blog.scienceandindustrymuseum.org.uk/wp-json/collection-media/collection-usage' }
];

module.exports = (config) => ({
  method: 'GET',
  path: '/articles/{id}',
  config: {
    cache: cacheHeaders(config, 3600 * 12),
    handler: async function (req, h) {
      try {
        const articles = await Promise.all(endpoints.map(e => fetchArticles(e, req.params.id)));
        return h.response({ data: articles.filter(e => e.data.length > 0) });
      } catch (err) {
        return new Boom('Cannot parse related objects feed:', err);
      }
    }
  }
});

async function fetchArticles (endpoint, id) {
  try {
    const aclient = axios.create({
      timeout: 10000,
      headers: { 'User-Agent': 'SMG Collection Site 1.0' }
    });
    const response = await aclient.get(endpoint.url);
    const data = response.data ? response.data.filter(e => e.collection_objects.indexOf(id) > -1) : [];

    return {
      museum: endpoint.label,
      data: data
    };
  } catch (err) {
    console.log(err);
    throw err;
  }
}
<|endoftext|>


<commit_before>'use strict';

const express = require('express');
const router = express.Router();
// const note = require('../controllers/note');
const Note = require('../models/note');
const category = require('../controllers/category');
const Category = require('../models/category');

// // // middleware params, gets the id and puts it into req.category
router.param('id', (req, res, next, id) => {
  Category.findById(id, (err, category) => {
    if (err) throw err;
    req.category = category;
    Note.find({category: id}, (err, notes) => {
      if (err) throw err;
      req.category.notes = notes;
      next();
    });
  });
});

// show all categories
router.get('/categories', category.index);

// new category form
router.get('/categories/new', category.newCategory);

// routes with route params need to be below static routes
// show all notes in a category
router.get('/categories/:id', category.show);

// //edit category
// router.get('/categories/:id/edit', category.edit);

// //update category after edit
// router.put('/categories/:id', category.update);

// // delete category
// router.delete('/categories/:id', category.destroy);

// post new category to db and redirect to home
router.post('/categories/', category.create);

module.exports = router;
<commit_msg>middleware comment<commit_after>'use strict';

const express = require('express');
const router = express.Router();
// const note = require('../controllers/note');
const Note = require('../models/note');
const category = require('../controllers/category');
const Category = require('../models/category');

// middleware params, gets the id and puts it into req.category
router.param('id', (req, res, next, id) => {
  Category.findById(id, (err, category) => {
    if (err) throw err;
    req.category = category;
    Note.find({category: id}, (err, notes) => {
      if (err) throw err;
      req.category.notes = notes;
      next();
    });
  });
});

// show all categories
router.get('/categories', category.index);

// new category form
router.get('/categories/new', category.newCategory);

// routes with route params need to be below static routes
// show all notes in a category
router.get('/categories/:id', category.show);

// //edit category
// router.get('/categories/:id/edit', category.edit);

// //update category after edit
// router.put('/categories/:id', category.update);

// // delete category
// router.delete('/categories/:id', category.destroy);

// post new category to db and redirect to home
router.post('/categories/', category.create);

module.exports = router;
<|endoftext|>