<commit_before>// JSONPathStoredProc (JPSP)

// using JSONpath query syntax
// query a data store JSON object
// name the query for programmatic use
// name a code block against that query resultset

/* Praeter.js 0.1 - Stored Procedures for JSON results via XPath JSON
 *
 * Copyright (c) 2015 Michael Glazer (https://github.com/magnumjs/praetor.js)
 * Licensed under the MIT (MIT-LICENSE.txt) licence.
 */

var p = (function(window, undefined) {
  'use strict';
  // data contruct
  var map={}
  map.stores={}
  map.queries={}
  map.procs={}

  // copy - don't modify!
  var model = function() {
      return JSON.parse(JSON.stringify(map))
  }()

  var defaults={}
  var settings={}

  var OBJECT = "[object Object]"
  var type = {}.toString;
  // initializer , necessary ?
	function p(state, id, options) {
	  // add options with defaults to get settings
	  //  p.settings = options + defaults
	  // attach to id
    p.map(id, state)
	}

  var getMap=function(){
    return p.map(map)
  }

  p.map=function(id, state){
    this.state = this.state || {}
    if(id && type.call(id) !== OBJECT){
      if(!this.state[id])
        this.state[id] = state || JSON.parse(JSON.stringify(model))
      return this.state[id]
    }
    this.state[p.id]  = id || this.state[p.id] || map
    return this.state[p.id]
  }

	p.setDataStore = function (name, data, id) {
	  p.map(id).stores[name] = data
	}

  p.getDataStore = function (name, id) {
    return p.map(id).stores[name]
  }

  p.setJsonQuery= function (name, JsonPathQuery, storeName) {
    getMap().queries[name] = {query : JsonPathQuery, store : storeName}
  }
  p.getJsonQuery= function ( name ) {
    return getMap().queries[name]
  }
  p.getJsonQueryResult = function ( name , options) {
    var jsonQuery = p.getJsonQuery(name)
    var data = p.getDataStore(jsonQuery.store)
    var result = JSONPath(options||{},data, jsonQuery.query)
    return result
  }

  p.setStoredProc = function ( name,  namedQueries , codeBody , parms ) {
    getMap().procs[name] = {namedQueries: namedQueries, codeBody : codeBody, parms : parms}
  }
  p.getStoredProc = function ( name ){
   return getMap().procs[name]
  }
  p.getStoredProcResult = function ( name , parms ) {
    var storedProc = p.getStoredProc(name)
    var queryResults = [];
    // get all results
    queryResults = storedProc.namedQueries.map(function(val, idx){
      var result = {}
      result[val] = p.getJsonQueryResult(val)
      return result
    })
    // create temp function
    var fun = Function(storedProc.codeBody)

    //merge parms with defaults
    for(var attr in storedProc.parms) {
      parms[attr] = parms[attr] === "undefined" ? storedProc.parms[attr]:parms[attr]
    }
    var context = {results : queryResults, params : parms}
    // execute proc and return results
    var ret= fun.apply(context)
    if(ret) return ret
    return context.results
  }

	// api methods
	p.setState = function ( id, state ) {
	  p.map(id, state)
	}
	p.getState=function(id){
	  return JSON.parse(JSON.stringify(p.map(id)));
	}

	return p

})(typeof window != "undefined" ? window : {});

if (typeof module != "undefined" && module !== null && module.exports) module.exports = p;
else if (typeof define === "function" && define.amd) define(function() {return p});

/*global module, exports, require*/
/*jslint vars:true, evil:true*/
/* JSONPath 0.8.0 - XPath for JSON
 *
 * Copyright (c) 2007 Stefan Goessner (goessner.net)
 * Licensed under the MIT (MIT-LICENSE.txt) licence.
 */
!function(require){"use strict";function push(t,e){return t=t.slice(),t.push(e),t}function unshift(t,e){return e=e.slice(),e.unshift(t),e}function JSONPath(t,e,r){if(!(this instanceof JSONPath))try{return new JSONPath(t,e,r)}catch(a){if(!a.avoidNew)throw a;return a.value}t=t||{};var n=t.hasOwnProperty("json")&&t.hasOwnProperty("path");if(this.resultType=t.resultType&&t.resultType.toLowerCase()||"value",this.flatten=t.flatten||!1,this.wrap=t.hasOwnProperty("wrap")?t.wrap:!0,this.sandbox=t.sandbox||{},t.autostart!==!1){var i=this.evaluate(n?t.json:e,n?t.path:r);if(!i||"object"!=typeof reg)throw{avoidNew:!0,value:i,message:"JSONPath should not be called with 'new'"}}}Array.isArray||(Array.isArray=function(t){return"[object Array]"===Object.prototype.toString.call(t)});var isNode="undefined"!=typeof module&&!!module.exports,vm=isNode?require("vm"):{runInNewContext:function(expr,context){return eval(Object.keys(context).reduce(function(t,e){return"var "+e+"="+JSON.stringify(context[e])+";"+t},expr))}},cache={};JSONPath.prototype.evaluate=function(t,e){var r=this;if(this._obj=t,e&&t&&("value"===this.resultType||"path"===this.resultType)){var a=this._normalize(e);"$"===a[0]&&a.length>1&&a.shift();var n=this._trace(a,t,["$"]);return n=n.filter(function(t){return t&&!t.isParentSelector}),n.length?1!==n.length||this.wrap||Array.isArray(n[0].value)?n.reduce(function(t,e){var a=e[r.resultType];return"path"===r.resultType&&(a=r._asPath(a)),r.flatten&&Array.isArray(a)?t=t.concat(a):t.push(a),t},[]):n[0][this.resultType]||!1:this.wrap?[]:!1}},JSONPath.prototype._normalize=function(t){if(cache[t])return cache[t];var e=[],r=t.replace(/[\['](\??\(.*?\))[\]']/g,function(t,r){return"[#"+(e.push(r)-1)+"]"}).replace(/'?\.'?|\['?/g,";").replace(/(?:;)?(\^+)(?:;)?/g,function(t,e){return";"+e.split("").join(";")+";"}).replace(/;;;|;;/g,";..;").replace(/;$|'?\]|'$/g,""),a=r.split(";").map(function(t){var r=t.match(/#([0-9]+)/);return r&&r[1]?e[r[1]]:t});return cache[t]=a,cache[t]},JSONPath.prototype._asPath=function(t){var e,r,a=t,n="$";for(e=1,r=a.length;r>e;e++)n+=/^[0-9*]+$/.test(a[e])?"["+a[e]+"]":"['"+a[e]+"']";return n},JSONPath.prototype._trace=function(t,e,r){function a(t){o=o.concat(t)}var n=this;if(!t.length)return[{path:r,value:e}];var i=t[0],s=t.slice(1);if("^"===i)return r.length?[{path:r.slice(0,-1),expr:s,isParentSelector:!0}]:[];var o=[];if(e&&e.hasOwnProperty(i))a(this._trace(s,e[i],push(r,i)));else if("*"===i)this._walk(i,s,e,r,function(t,e,r,i,s){a(n._trace(unshift(t,r),i,s))});else if(".."===i)a(this._trace(s,e,r)),this._walk(i,s,e,r,function(t,e,r,i,s){"object"==typeof i[t]&&a(n._trace(unshift("..",r),i[t],push(s,t)))});else if("("===i[0])a(this._trace(unshift(this._eval(i,e,r[r.length],r),s),e,r));else if(0===i.indexOf("?("))this._walk(i,s,e,r,function(t,e,i,s,o){n._eval(e.replace(/^\?\((.*?)\)$/,"$1"),s[t],t,r)&&a(n._trace(unshift(t,i),s,o))});else if(i.indexOf(",")>-1){var h,u;for(h=i.split(","),u=0;u<h.length;u++)a(this._trace(unshift(h[u],s),e,r))}else/^(-?[0-9]*):(-?[0-9]*):?([0-9]*)$/.test(i)&&a(this._slice(i,s,e,r));return o.reduce(function(t,r){return t.concat(r.isParentSelector?n._trace(r.expr,e,r.path):[r])},[])},JSONPath.prototype._walk=function(t,e,r,a,n){var i,s,o;if(Array.isArray(r))for(i=0,s=r.length;s>i;i++)n(i,t,e,r,a);else if("object"==typeof r)for(o in r)r.hasOwnProperty(o)&&n(o,t,e,r,a)},JSONPath.prototype._slice=function(t,e,r,a){if(Array.isArray(r)){var n,i=r.length,s=t.split(":"),o=s[0]&&parseInt(s[0],10)||0,h=s[1]&&parseInt(s[1],10)||i,u=s[2]&&parseInt(s[2],10)||1;o=0>o?Math.max(0,o+i):Math.min(i,o),h=0>h?Math.max(0,h+i):Math.min(i,h);var c=[];for(n=o;h>n;n+=u)c=c.concat(this._trace(unshift(n,e),r,a));return c}},JSONPath.prototype._eval=function(t,e,r,a){if(!this._obj||!e)return!1;t.indexOf("@path")>-1&&(this.sandbox._$_path=this._asPath(a.concat([r])),t=t.replace(/@path/g,"_$_path")),t.indexOf("@")>-1&&(this.sandbox._$_v=e,t=t.replace(/@/g,"_$_v"));try{return vm.runInNewContext(t,this.sandbox)}catch(n){throw console.log(n),Error("jsonPath: "+n.message+": "+t)}},JSONPath.eval=function(t,e,r){return JSONPath(r,t,e)},"undefined"==typeof module?(window.jsonPath={eval:JSONPath.eval},window.JSONPath=JSONPath):module.exports=JSONPath}("undefined"==typeof require?null:require);
<commit_msg>Added new core base method p.proc<commit_after>// JSONPathStoredProc (JPSP)

// using JSONpath query syntax
// query a data store JSON object
// name the query for programmatic use
// name a code block against that query resultset

/* Praeter.js 0.1 - Stored Procedures (JS Code blocks) for JSON results via XPath JSON
 *
 * Copyright (c) 2015 Michael Glazer (https://github.com/magnumjs/praetor.js)
 * Licensed under the MIT (MIT-LICENSE.txt) licence.
 */

var p = (function(window, undefined) {
  'use strict';
  // data contruct
  var map = {}
  map.stores = {}
  map.queries = {}
  map.procs = {}

  // copy - don't modify!
  var model = function() {
    return JSON.parse(JSON.stringify(map))
  }()

  var defaults = {}
  var settings = {}

  var OBJECT = "[object Object]"
  var type = {}.toString;
  // initializer , necessary ?
  function p(state, id, options) {
    // add options with defaults to get settings
    //  p.settings = options + defaults
    // attach to id
    p.map(id, state)
  }

  var getMap = function() {
    return p.map(map)
  }

  p.map = function(id, state) {
    this.state = this.state || {}
    if (id && type.call(id) !== OBJECT) {
      if (!this.state[id])
        this.state[id] = state || JSON.parse(JSON.stringify(model))
      return this.state[id]
    }
    this.state[p.id] = id || this.state[p.id] || map
    return this.state[p.id]
  }

  p.proc = function(json, queries, code, parms) {
    // can be raw or by stored names
    var queryResults = queries.map(function(query, idx) {
      return JSONPath(defaults.jsonPathOptions || {}, json, query)
    })
    var storedProc = {
      parms: parms,
      codeBody: code
    };
    //return results;
    return createFunctionExec(queryResults, storedProc, parms);
  }

  p.setDataStore = function(name, data, id) {
    p.map(id).stores[name] = data
  }

  p.getDataStore = function(name, id) {
    return p.map(id).stores[name]
  }

  p.setJsonQuery = function(name, JsonPathQuery, storeName) {
    getMap().queries[name] = {
      query: JsonPathQuery,
      store: storeName
    }
  }
  p.getJsonQuery = function(name) {
    return getMap().queries[name]
  }
  p.getJsonQueryResult = function(name, options) {
    var jsonQuery = p.getJsonQuery(name)
    var data = p.getDataStore(jsonQuery.store)
    var result = JSONPath(options || {}, data, jsonQuery.query)
    return result
  }

  p.setStoredProc = function(name, namedQueries, codeBody, parms) {
    getMap().procs[name] = {
      namedQueries: namedQueries,
      codeBody: codeBody,
      parms: parms
    }
  }
  p.getStoredProc = function(name) {
    return getMap().procs[name]
  }

  p.getStoredProcResult = function(name, parms) {
    var storedProc = p.getStoredProc(name)
    var queryResults = [];
    // get all results
    queryResults = storedProc.namedQueries.map(function(val, idx) {
      var result = {}
      result[val] = p.getJsonQueryResult(val)
      return result
    })
    return createFunctionExec(queryResults, storedProc, parms);
  }

  function createFunctionExec(queryResults, storedProc, parms) {
    // create temp function
    var fun = Function(storedProc.codeBody)

    //merge parms with defaults
    //TODO: parms will override if attr don't exist
    for (var attr in storedProc.parms) {
      parms[attr] = parms[attr] === "undefined" ? storedProc.parms[attr] : parms[attr]
    }
    //TODO: optional context via defaults override options
    var context = {
      results: queryResults,
      params: parms
    }
    // execute proc and return results
    var ret = fun.apply(context)
    if (ret) return ret
    return context.results
  }

  // api methods
  p.setState = function(id, state) {
    p.map(id, state)
  }
  p.getState = function(id) {
    return JSON.parse(JSON.stringify(p.map(id)));
  }

  return p

})(typeof window != "undefined" ? window : {});

if (typeof module != "undefined" && module !== null && module.exports) module.exports = p;
else if (typeof define === "function" && define.amd) define(function() {
  return p
});

/*global module, exports, require*/
/*jslint vars:true, evil:true*/
/* JSONPath 0.8.0 - XPath for JSON
 *
 * Copyright (c) 2007 Stefan Goessner (goessner.net)
 * Licensed under the MIT (MIT-LICENSE.txt) licence.
 */
 !function(require){"use strict";function push(t,e){return t=t.slice(),t.push(e),t}function unshift(t,e){return e=e.slice(),e.unshift(t),e}function JSONPath(t,e,r){if(!(this instanceof JSONPath))try{return new JSONPath(t,e,r)}catch(a){if(!a.avoidNew)throw a;return a.value}t=t||{};var n=t.hasOwnProperty("json")&&t.hasOwnProperty("path");if(this.resultType=t.resultType&&t.resultType.toLowerCase()||"value",this.flatten=t.flatten||!1,this.wrap=t.hasOwnProperty("wrap")?t.wrap:!0,this.sandbox=t.sandbox||{},t.autostart!==!1){var i=this.evaluate(n?t.json:e,n?t.path:r);if(!i||"object"!=typeof reg)throw{avoidNew:!0,value:i,message:"JSONPath should not be called with 'new'"}}}Array.isArray||(Array.isArray=function(t){return"[object Array]"===Object.prototype.toString.call(t)});var isNode="undefined"!=typeof module&&!!module.exports,vm=isNode?require("vm"):{runInNewContext:function(expr,context){return eval(Object.keys(context).reduce(function(t,e){return"var "+e+"="+JSON.stringify(context[e])+";"+t},expr))}},cache={};JSONPath.prototype.evaluate=function(t,e){var r=this;if(this._obj=t,e&&t&&("value"===this.resultType||"path"===this.resultType)){var a=this._normalize(e);"$"===a[0]&&a.length>1&&a.shift();var n=this._trace(a,t,["$"]);return n=n.filter(function(t){return t&&!t.isParentSelector}),n.length?1!==n.length||this.wrap||Array.isArray(n[0].value)?n.reduce(function(t,e){var a=e[r.resultType];return"path"===r.resultType&&(a=r._asPath(a)),r.flatten&&Array.isArray(a)?t=t.concat(a):t.push(a),t},[]):n[0][this.resultType]||!1:this.wrap?[]:!1}},JSONPath.prototype._normalize=function(t){if(cache[t])return cache[t];var e=[],r=t.replace(/[\['](\??\(.*?\))[\]']/g,function(t,r){return"[#"+(e.push(r)-1)+"]"}).replace(/'?\.'?|\['?/g,";").replace(/(?:;)?(\^+)(?:;)?/g,function(t,e){return";"+e.split("").join(";")+";"}).replace(/;;;|;;/g,";..;").replace(/;$|'?\]|'$/g,""),a=r.split(";").map(function(t){var r=t.match(/#([0-9]+)/);return r&&r[1]?e[r[1]]:t});return cache[t]=a,cache[t]},JSONPath.prototype._asPath=function(t){var e,r,a=t,n="$";for(e=1,r=a.length;r>e;e++)n+=/^[0-9*]+$/.test(a[e])?"["+a[e]+"]":"['"+a[e]+"']";return n},JSONPath.prototype._trace=function(t,e,r){function a(t){o=o.concat(t)}var n=this;if(!t.length)return[{path:r,value:e}];var i=t[0],s=t.slice(1);if("^"===i)return r.length?[{path:r.slice(0,-1),expr:s,isParentSelector:!0}]:[];var o=[];if(e&&e.hasOwnProperty(i))a(this._trace(s,e[i],push(r,i)));else if("*"===i)this._walk(i,s,e,r,function(t,e,r,i,s){a(n._trace(unshift(t,r),i,s))});else if(".."===i)a(this._trace(s,e,r)),this._walk(i,s,e,r,function(t,e,r,i,s){"object"==typeof i[t]&&a(n._trace(unshift("..",r),i[t],push(s,t)))});else if("("===i[0])a(this._trace(unshift(this._eval(i,e,r[r.length],r),s),e,r));else if(0===i.indexOf("?("))this._walk(i,s,e,r,function(t,e,i,s,o){n._eval(e.replace(/^\?\((.*?)\)$/,"$1"),s[t],t,r)&&a(n._trace(unshift(t,i),s,o))});else if(i.indexOf(",")>-1){var h,u;for(h=i.split(","),u=0;u<h.length;u++)a(this._trace(unshift(h[u],s),e,r))}else/^(-?[0-9]*):(-?[0-9]*):?([0-9]*)$/.test(i)&&a(this._slice(i,s,e,r));return o.reduce(function(t,r){return t.concat(r.isParentSelector?n._trace(r.expr,e,r.path):[r])},[])},JSONPath.prototype._walk=function(t,e,r,a,n){var i,s,o;if(Array.isArray(r))for(i=0,s=r.length;s>i;i++)n(i,t,e,r,a);else if("object"==typeof r)for(o in r)r.hasOwnProperty(o)&&n(o,t,e,r,a)},JSONPath.prototype._slice=function(t,e,r,a){if(Array.isArray(r)){var n,i=r.length,s=t.split(":"),o=s[0]&&parseInt(s[0],10)||0,h=s[1]&&parseInt(s[1],10)||i,u=s[2]&&parseInt(s[2],10)||1;o=0>o?Math.max(0,o+i):Math.min(i,o),h=0>h?Math.max(0,h+i):Math.min(i,h);var c=[];for(n=o;h>n;n+=u)c=c.concat(this._trace(unshift(n,e),r,a));return c}},JSONPath.prototype._eval=function(t,e,r,a){if(!this._obj||!e)return!1;t.indexOf("@path")>-1&&(this.sandbox._$_path=this._asPath(a.concat([r])),t=t.replace(/@path/g,"_$_path")),t.indexOf("@")>-1&&(this.sandbox._$_v=e,t=t.replace(/@/g,"_$_v"));try{return vm.runInNewContext(t,this.sandbox)}catch(n){throw console.log(n),Error("jsonPath: "+n.message+": "+t)}},JSONPath.eval=function(t,e,r){return JSONPath(r,t,e)},"undefined"==typeof module?(window.jsonPath={eval:JSONPath.eval},window.JSONPath=JSONPath):module.exports=JSONPath}("undefined"==typeof require?null:require);
<|endoftext|>


<commit_before>#!/usr/bin/env node
/*global cat:true cd:true echo:true exec:true exit:true*/

// Usage:
// stable release: node release.js
// pre-release: node release.js --pre-release {version}

"use strict";

var baseDir, repoDir, prevVersion, newVersion, nextVersion, tagTime, preRelease,
	fs = require( "fs" ),
	rnewline = /\r?\n/,
	repo = "git@github.com:jquery/jquery-ui.git",
	branch = "master";

walk([
	bootstrap,

	section( "setting up repo" ),
	cloneRepo,
	checkState,

	section( "calculating versions" ),
	getVersions,
	confirm,

	section( "building release" ),
	buildRelease,

	section( "pushing tag" ),
	confirmReview,
	pushRelease,

	section( "updating branch version" ),
	updateBranchVersion,

	section( "pushing " + branch ),
	confirmReview,
	pushBranch,

	section( "generating changelog" ),
	generateChangelog,

	section( "gathering contributors" ),
	gatherContributors,

	section( "updating trac" ),
	updateTrac,
	confirm
]);

function cloneRepo() {
	echo( "Cloning " + repo.cyan + "..." );
	git( "clone " + repo + " " + repoDir, "Error cloning repo." );
	cd( repoDir );

	echo( "Checking out " + branch.cyan + " branch..." );
	git( "checkout " + branch, "Error checking out branch." );
	echo();

	echo( "Installing dependencies..." );
	if ( exec( "npm install" ).code !== 0 ) {
		abort( "Error installing dependencies." );
	}
	// We need download.jqueryui.com in order to generate themes.
	// We only generate themes for stable releases.
	if ( !preRelease ) {
		if ( exec( "npm install download.jqueryui.com" ).code !== 0 ) {
			abort( "Error installing dependencies." );
		}
	}
	echo();
}

function checkState() {
	echo( "Checking AUTHORS.txt..." );
	var result, lastActualAuthor,
		lastListedAuthor = cat( "AUTHORS.txt" ).trim().split( rnewline ).pop();

	result = exec( "grunt authors", { silent: true });
	if ( result.code !== 0 ) {
		abort( "Error getting list of authors." );
	}
	lastActualAuthor = result.output.split( rnewline ).splice( -4, 1 )[ 0 ];

	if ( lastListedAuthor !== lastActualAuthor ) {
		echo( "Last listed author is " + lastListedAuthor.red + "." );
		echo( "Last actual author is " + lastActualAuthor.green + "." );
		abort( "Please update AUTHORS.txt." );
	}

	echo( "Last listed author (" + lastListedAuthor.cyan + ") is correct." );
}

function getVersions() {
	// prevVersion, newVersion, nextVersion are defined in the parent scope
	var parts, major, minor, patch,
		currentVersion = readPackage().version;

	echo( "Validating current version..." );
	if ( currentVersion.substr( -3, 3 ) !== "pre" ) {
		echo( "The current version is " + currentVersion.red + "." );
		abort( "The version must be a pre version." );
	}

	if ( preRelease ) {
		newVersion = preRelease;
		// Note: prevVersion is not currently used for pre-releases. The TODO
		// below about 1.10.0 applies here as well.
		prevVersion = nextVersion = currentVersion;
	} else {
		newVersion = currentVersion.substr( 0, currentVersion.length - 3 );
		parts = newVersion.split( "." );
		major = parseInt( parts[ 0 ], 10 );
		minor = parseInt( parts[ 1 ], 10 );
		patch = parseInt( parts[ 2 ], 10 );

		// TODO: handle 1.10.0
		// Also see comment above about pre-releases
		if ( minor === 0 ) {
			abort( "This script is not smart enough to handle the 1.10.0 release." );
		}

		prevVersion = patch === 0 ?
			[ major, minor - 1, 0 ].join( "." ) :
			[ major, minor, patch - 1 ].join( "." );
		nextVersion = [ major, minor, patch + 1 ].join( "." ) + "pre";
	}

	echo( "We are going from " + prevVersion.cyan + " to " + newVersion.cyan + "." );
	echo( "After the release, the version will be " + nextVersion.cyan + "." );
}

function buildRelease() {
	var pkg,
		releaseTask = preRelease ? "release" : "release_cdn";

	echo( "Creating " + "release".cyan + " branch..." );
	git( "checkout -b release", "Error creating release branch." );
	echo();

	echo( "Updating package.json..." );
	pkg = readPackage();
	pkg.version = newVersion;
	pkg.author.url = pkg.author.url.replace( "master", newVersion );
	pkg.licenses.forEach(function( license ) {
		license.url = license.url.replace( "master", newVersion );
	});
	writePackage( pkg );

	echo( "Generating manifest files..." );
	if ( exec( "grunt manifest" ).code !== 0 ) {
		abort( "Error generating manifest files." );
	}
	echo();

	echo( "Building release..." );
	if ( exec( "grunt " + releaseTask ).code !== 0 ) {
		abort( "Error building release." );
	}
	echo();

	echo( "Committing release artifacts..." );
	git( "add *.jquery.json", "Error adding manifest files to git." );
	git( "commit -am 'Tagging the " + newVersion + " release.'",
		"Error committing release changes." );
	echo();

	echo( "Tagging release..." );
	git( "tag " + newVersion, "Error tagging " + newVersion + "." );
	tagTime = git( "log -1 --format='%ad'", "Error getting tag timestamp." ).trim();
}

function pushRelease() {
	echo( "Pushing release to GitHub..." );
	git( "push --tags", "Error pushing tags to GitHub." );
}

function updateBranchVersion() {
	// Pre-releases don't change the master version
	if ( preRelease ) {
		return;
	}

	var pkg;

	echo( "Checking out " + branch.cyan + " branch..." );
	git( "checkout " + branch, "Error checking out " + branch + " branch." );

	echo( "Updating package.json..." );
	pkg = readPackage();
	pkg.version = nextVersion;
	writePackage( pkg );

	echo( "Committing version update..." );
	git( "commit -am 'Updating the " + branch + " version to " + nextVersion + ".'",
		"Error committing package.json." );
}

function pushBranch() {
	// Pre-releases don't change the master version
	if ( preRelease ) {
		return;
	}

	echo( "Pushing " + branch.cyan + " to GitHub..." );
	git( "push", "Error pushing to GitHub." );
}

function generateChangelog() {
	if ( preRelease ) {
		return;
	}

	var commits,
		changelogPath = baseDir + "/changelog",
		changelog = cat( "build/release/changelog-shell" ) + "\n",
		fullFormat = "* %s (TICKETREF, [%h](http://github.com/jquery/jquery-ui/commit/%H))";

	changelog = changelog.replace( "{title}", "jQuery UI " + newVersion + " Changelog" );

	echo ( "Adding commits..." );
	commits = gitLog( fullFormat );

	echo( "Adding links to tickets..." );
	changelog += commits
		// Add ticket references
		.map(function( commit ) {
			var tickets = [];
			commit.replace( /Fixe[sd] #(\d+)/g, function( match, ticket ) {
				tickets.push( ticket );
			});
			return tickets.length ?
				commit.replace( "TICKETREF", tickets.map(function( ticket ) {
					return "[#" + ticket + "](http://bugs.jqueryui.com/ticket/" + ticket + ")";
				}).join( ", " ) ) :
				// Leave TICKETREF token in place so it's easy to find commits without tickets
				commit;
		})
		// Sort commits so that they're grouped by component
		.sort()
		.join( "\n" ) + "\n";

	echo( "Adding Trac tickets..." );
	changelog += trac( "/query?milestone=" + newVersion + "&resolution=fixed" +
		"&col=id&col=component&col=summary&order=component" ) + "\n";

	fs.writeFileSync( changelogPath, changelog );
	echo( "Stored changelog in " + changelogPath.cyan + "." );
}

function gatherContributors() {
	if ( preRelease ) {
		return;
	}

	var contributors,
		contributorsPath = baseDir + "/contributors";

	echo( "Adding committers and authors..." );
	contributors = gitLog( "%aN%n%cN" );

	echo( "Adding reporters and commenters from Trac..." );
	contributors = contributors.concat(
		trac( "/report/22?V=" + newVersion + "&max=-1" )
			.split( rnewline )
			// Remove header and trailing newline
			.slice( 1, -1 ) );

	echo( "Sorting contributors..." );
	contributors = unique( contributors ).sort(function( a, b ) {
		return a.toLowerCase() < b.toLowerCase() ? -1 : 1;
	});

	echo ( "Adding people thanked in commits..." );
	contributors = contributors.concat(
		gitLog( "%b%n%s" ).filter(function( line ) {
			return (/thank/i).test( line );
		}));

	fs.writeFileSync( contributorsPath, contributors.join( "\n" ) );
	echo( "Stored contributors in " + contributorsPath.cyan + "." );
}

function updateTrac() {
	echo( newVersion.cyan + " was tagged at " + tagTime.cyan + "." );
	if ( !preRelease ) {
		echo( "Close the " + newVersion.cyan + " Milestone." );
	}
	echo( "Create the " + newVersion.cyan + " Version." );
	echo( "When Trac asks for date and time, match the above. Should only change minutes and seconds." );
	echo( "Create a Milestone for the next minor release." );
}

// ===== HELPER FUNCTIONS ======================================================

function git( command, errorMessage ) {
	var result = exec( "git " + command );
	if ( result.code !== 0 ) {
		abort( errorMessage );
	}

	return result.output;
}

function gitLog( format ) {
	var result = exec( "git log " + prevVersion + ".." + newVersion + " " +
		"--format='" + format + "'",
		{ silent: true });

	if ( result.code !== 0 ) {
		abort( "Error getting git log." );
	}

	result = result.output.split( rnewline );
	if ( result[ result.length - 1 ] === "" ) {
		result.pop();
	}

	return result;
}

function trac( path ) {
	var result = exec( "curl -s 'http://bugs.jqueryui.com" + path + "&format=tab'",
		{ silent: true });

	if ( result.code !== 0 ) {
		abort( "Error getting Trac data." );
	}

	return result.output;
}

function unique( arr ) {
	var obj = {};
	arr.forEach(function( item ) {
		obj[ item ] = 1;
	});
	return Object.keys( obj );
}

function readPackage() {
	return JSON.parse( fs.readFileSync( repoDir + "/package.json" ) );
}

function writePackage( pkg ) {
	fs.writeFileSync( repoDir + "/package.json",
		JSON.stringify( pkg, null, "\t" ) + "\n" );
}

function bootstrap( fn ) {
	console.log( "Determining release type..." );
	preRelease = process.argv.indexOf( "--pre-release" );
	if ( preRelease !== -1 ) {
		preRelease = process.argv[ preRelease + 1 ];
		console.log( "pre-release" );
	} else {
		preRelease = null;
		console.log( "stable release" );
	}

	console.log( "Determining directories..." );
	baseDir = process.cwd() + "/__release";
	repoDir = baseDir + "/repo";

	if ( fs.existsSync( baseDir ) ) {
		console.log( "The directory '" + baseDir + "' already exists." );
		console.log( "Aborting." );
		process.exit( 1 );
	}

	console.log( "Creating directory..." );
	fs.mkdirSync( baseDir );

	console.log( "Installing dependencies..." );
	require( "child_process" ).exec( "npm install shelljs colors", function( error ) {
		if ( error ) {
			console.log( error );
			return process.exit( 1 );
		}

		require( "shelljs/global" );
		require( "colors" );

		fn();
	});
}

function section( name ) {
	return function() {
		echo();
		echo( "##" );
		echo( "## " + name.toUpperCase().magenta );
		echo( "##" );
		echo();
	};
}

function prompt( fn ) {
	process.stdin.once( "data", function( chunk ) {
		process.stdin.pause();
		fn( chunk.toString().trim() );
	});
	process.stdin.resume();
}

function confirm( fn ) {
	echo( "Press enter to continue, or ctrl+c to cancel.".yellow );
	prompt( fn );
}

function confirmReview( fn ) {
	echo( "Please review the output and generated files as a sanity check.".yellow );
	confirm( fn );
}

function abort( msg ) {
	echo( msg.red );
	echo( "Aborting.".red );
	exit( 1 );
}

function walk( methods ) {
	var method = methods.shift();

	function next() {
		if ( methods.length ) {
			walk( methods );
		}
	}

	if ( !method.length ) {
		method();
		next();
	} else {
		method( next );
	}
}
<commit_msg>Build: Check patch instead of minor to detect major releases.<commit_after>#!/usr/bin/env node
/*global cat:true cd:true echo:true exec:true exit:true*/

// Usage:
// stable release: node release.js
// pre-release: node release.js --pre-release {version}

"use strict";

var baseDir, repoDir, prevVersion, newVersion, nextVersion, tagTime, preRelease,
	fs = require( "fs" ),
	rnewline = /\r?\n/,
	repo = "git@github.com:jquery/jquery-ui.git",
	branch = "master";

walk([
	bootstrap,

	section( "setting up repo" ),
	cloneRepo,
	checkState,

	section( "calculating versions" ),
	getVersions,
	confirm,

	section( "building release" ),
	buildRelease,

	section( "pushing tag" ),
	confirmReview,
	pushRelease,

	section( "updating branch version" ),
	updateBranchVersion,

	section( "pushing " + branch ),
	confirmReview,
	pushBranch,

	section( "generating changelog" ),
	generateChangelog,

	section( "gathering contributors" ),
	gatherContributors,

	section( "updating trac" ),
	updateTrac,
	confirm
]);

function cloneRepo() {
	echo( "Cloning " + repo.cyan + "..." );
	git( "clone " + repo + " " + repoDir, "Error cloning repo." );
	cd( repoDir );

	echo( "Checking out " + branch.cyan + " branch..." );
	git( "checkout " + branch, "Error checking out branch." );
	echo();

	echo( "Installing dependencies..." );
	if ( exec( "npm install" ).code !== 0 ) {
		abort( "Error installing dependencies." );
	}
	// We need download.jqueryui.com in order to generate themes.
	// We only generate themes for stable releases.
	if ( !preRelease ) {
		if ( exec( "npm install download.jqueryui.com" ).code !== 0 ) {
			abort( "Error installing dependencies." );
		}
	}
	echo();
}

function checkState() {
	echo( "Checking AUTHORS.txt..." );
	var result, lastActualAuthor,
		lastListedAuthor = cat( "AUTHORS.txt" ).trim().split( rnewline ).pop();

	result = exec( "grunt authors", { silent: true });
	if ( result.code !== 0 ) {
		abort( "Error getting list of authors." );
	}
	lastActualAuthor = result.output.split( rnewline ).splice( -4, 1 )[ 0 ];

	if ( lastListedAuthor !== lastActualAuthor ) {
		echo( "Last listed author is " + lastListedAuthor.red + "." );
		echo( "Last actual author is " + lastActualAuthor.green + "." );
		abort( "Please update AUTHORS.txt." );
	}

	echo( "Last listed author (" + lastListedAuthor.cyan + ") is correct." );
}

function getVersions() {
	// prevVersion, newVersion, nextVersion are defined in the parent scope
	var parts, major, minor, patch,
		currentVersion = readPackage().version;

	echo( "Validating current version..." );
	if ( currentVersion.substr( -3, 3 ) !== "pre" ) {
		echo( "The current version is " + currentVersion.red + "." );
		abort( "The version must be a pre version." );
	}

	if ( preRelease ) {
		newVersion = preRelease;
		// Note: prevVersion is not currently used for pre-releases. The TODO
		// below about 1.10.0 applies here as well.
		prevVersion = nextVersion = currentVersion;
	} else {
		newVersion = currentVersion.substr( 0, currentVersion.length - 3 );
		parts = newVersion.split( "." );
		major = parseInt( parts[ 0 ], 10 );
		minor = parseInt( parts[ 1 ], 10 );
		patch = parseInt( parts[ 2 ], 10 );

		// TODO: handle 1.10.0
		// Also see comment above about pre-releases
		if ( patch === 0 ) {
			abort( "This script is not smart enough to handle the 1.10.0 release." );
		}

		prevVersion = patch === 0 ?
			[ major, minor - 1, 0 ].join( "." ) :
			[ major, minor, patch - 1 ].join( "." );
		nextVersion = [ major, minor, patch + 1 ].join( "." ) + "pre";
	}

	echo( "We are going from " + prevVersion.cyan + " to " + newVersion.cyan + "." );
	echo( "After the release, the version will be " + nextVersion.cyan + "." );
}

function buildRelease() {
	var pkg,
		releaseTask = preRelease ? "release" : "release_cdn";

	echo( "Creating " + "release".cyan + " branch..." );
	git( "checkout -b release", "Error creating release branch." );
	echo();

	echo( "Updating package.json..." );
	pkg = readPackage();
	pkg.version = newVersion;
	pkg.author.url = pkg.author.url.replace( "master", newVersion );
	pkg.licenses.forEach(function( license ) {
		license.url = license.url.replace( "master", newVersion );
	});
	writePackage( pkg );

	echo( "Generating manifest files..." );
	if ( exec( "grunt manifest" ).code !== 0 ) {
		abort( "Error generating manifest files." );
	}
	echo();

	echo( "Building release..." );
	if ( exec( "grunt " + releaseTask ).code !== 0 ) {
		abort( "Error building release." );
	}
	echo();

	echo( "Committing release artifacts..." );
	git( "add *.jquery.json", "Error adding manifest files to git." );
	git( "commit -am 'Tagging the " + newVersion + " release.'",
		"Error committing release changes." );
	echo();

	echo( "Tagging release..." );
	git( "tag " + newVersion, "Error tagging " + newVersion + "." );
	tagTime = git( "log -1 --format='%ad'", "Error getting tag timestamp." ).trim();
}

function pushRelease() {
	echo( "Pushing release to GitHub..." );
	git( "push --tags", "Error pushing tags to GitHub." );
}

function updateBranchVersion() {
	// Pre-releases don't change the master version
	if ( preRelease ) {
		return;
	}

	var pkg;

	echo( "Checking out " + branch.cyan + " branch..." );
	git( "checkout " + branch, "Error checking out " + branch + " branch." );

	echo( "Updating package.json..." );
	pkg = readPackage();
	pkg.version = nextVersion;
	writePackage( pkg );

	echo( "Committing version update..." );
	git( "commit -am 'Updating the " + branch + " version to " + nextVersion + ".'",
		"Error committing package.json." );
}

function pushBranch() {
	// Pre-releases don't change the master version
	if ( preRelease ) {
		return;
	}

	echo( "Pushing " + branch.cyan + " to GitHub..." );
	git( "push", "Error pushing to GitHub." );
}

function generateChangelog() {
	if ( preRelease ) {
		return;
	}

	var commits,
		changelogPath = baseDir + "/changelog",
		changelog = cat( "build/release/changelog-shell" ) + "\n",
		fullFormat = "* %s (TICKETREF, [%h](http://github.com/jquery/jquery-ui/commit/%H))";

	changelog = changelog.replace( "{title}", "jQuery UI " + newVersion + " Changelog" );

	echo ( "Adding commits..." );
	commits = gitLog( fullFormat );

	echo( "Adding links to tickets..." );
	changelog += commits
		// Add ticket references
		.map(function( commit ) {
			var tickets = [];
			commit.replace( /Fixe[sd] #(\d+)/g, function( match, ticket ) {
				tickets.push( ticket );
			});
			return tickets.length ?
				commit.replace( "TICKETREF", tickets.map(function( ticket ) {
					return "[#" + ticket + "](http://bugs.jqueryui.com/ticket/" + ticket + ")";
				}).join( ", " ) ) :
				// Leave TICKETREF token in place so it's easy to find commits without tickets
				commit;
		})
		// Sort commits so that they're grouped by component
		.sort()
		.join( "\n" ) + "\n";

	echo( "Adding Trac tickets..." );
	changelog += trac( "/query?milestone=" + newVersion + "&resolution=fixed" +
		"&col=id&col=component&col=summary&order=component" ) + "\n";

	fs.writeFileSync( changelogPath, changelog );
	echo( "Stored changelog in " + changelogPath.cyan + "." );
}

function gatherContributors() {
	if ( preRelease ) {
		return;
	}

	var contributors,
		contributorsPath = baseDir + "/contributors";

	echo( "Adding committers and authors..." );
	contributors = gitLog( "%aN%n%cN" );

	echo( "Adding reporters and commenters from Trac..." );
	contributors = contributors.concat(
		trac( "/report/22?V=" + newVersion + "&max=-1" )
			.split( rnewline )
			// Remove header and trailing newline
			.slice( 1, -1 ) );

	echo( "Sorting contributors..." );
	contributors = unique( contributors ).sort(function( a, b ) {
		return a.toLowerCase() < b.toLowerCase() ? -1 : 1;
	});

	echo ( "Adding people thanked in commits..." );
	contributors = contributors.concat(
		gitLog( "%b%n%s" ).filter(function( line ) {
			return (/thank/i).test( line );
		}));

	fs.writeFileSync( contributorsPath, contributors.join( "\n" ) );
	echo( "Stored contributors in " + contributorsPath.cyan + "." );
}

function updateTrac() {
	echo( newVersion.cyan + " was tagged at " + tagTime.cyan + "." );
	if ( !preRelease ) {
		echo( "Close the " + newVersion.cyan + " Milestone." );
	}
	echo( "Create the " + newVersion.cyan + " Version." );
	echo( "When Trac asks for date and time, match the above. Should only change minutes and seconds." );
	echo( "Create a Milestone for the next minor release." );
}

// ===== HELPER FUNCTIONS ======================================================

function git( command, errorMessage ) {
	var result = exec( "git " + command );
	if ( result.code !== 0 ) {
		abort( errorMessage );
	}

	return result.output;
}

function gitLog( format ) {
	var result = exec( "git log " + prevVersion + ".." + newVersion + " " +
		"--format='" + format + "'",
		{ silent: true });

	if ( result.code !== 0 ) {
		abort( "Error getting git log." );
	}

	result = result.output.split( rnewline );
	if ( result[ result.length - 1 ] === "" ) {
		result.pop();
	}

	return result;
}

function trac( path ) {
	var result = exec( "curl -s 'http://bugs.jqueryui.com" + path + "&format=tab'",
		{ silent: true });

	if ( result.code !== 0 ) {
		abort( "Error getting Trac data." );
	}

	return result.output;
}

function unique( arr ) {
	var obj = {};
	arr.forEach(function( item ) {
		obj[ item ] = 1;
	});
	return Object.keys( obj );
}

function readPackage() {
	return JSON.parse( fs.readFileSync( repoDir + "/package.json" ) );
}

function writePackage( pkg ) {
	fs.writeFileSync( repoDir + "/package.json",
		JSON.stringify( pkg, null, "\t" ) + "\n" );
}

function bootstrap( fn ) {
	console.log( "Determining release type..." );
	preRelease = process.argv.indexOf( "--pre-release" );
	if ( preRelease !== -1 ) {
		preRelease = process.argv[ preRelease + 1 ];
		console.log( "pre-release" );
	} else {
		preRelease = null;
		console.log( "stable release" );
	}

	console.log( "Determining directories..." );
	baseDir = process.cwd() + "/__release";
	repoDir = baseDir + "/repo";

	if ( fs.existsSync( baseDir ) ) {
		console.log( "The directory '" + baseDir + "' already exists." );
		console.log( "Aborting." );
		process.exit( 1 );
	}

	console.log( "Creating directory..." );
	fs.mkdirSync( baseDir );

	console.log( "Installing dependencies..." );
	require( "child_process" ).exec( "npm install shelljs colors", function( error ) {
		if ( error ) {
			console.log( error );
			return process.exit( 1 );
		}

		require( "shelljs/global" );
		require( "colors" );

		fn();
	});
}

function section( name ) {
	return function() {
		echo();
		echo( "##" );
		echo( "## " + name.toUpperCase().magenta );
		echo( "##" );
		echo();
	};
}

function prompt( fn ) {
	process.stdin.once( "data", function( chunk ) {
		process.stdin.pause();
		fn( chunk.toString().trim() );
	});
	process.stdin.resume();
}

function confirm( fn ) {
	echo( "Press enter to continue, or ctrl+c to cancel.".yellow );
	prompt( fn );
}

function confirmReview( fn ) {
	echo( "Please review the output and generated files as a sanity check.".yellow );
	confirm( fn );
}

function abort( msg ) {
	echo( msg.red );
	echo( "Aborting.".red );
	exit( 1 );
}

function walk( methods ) {
	var method = methods.shift();

	function next() {
		if ( methods.length ) {
			walk( methods );
		}
	}

	if ( !method.length ) {
		method();
		next();
	} else {
		method( next );
	}
}
<|endoftext|>


<commit_before>/* wheatonDice is an opensource project to study the legendary dice curse of Wil Wheaton
 * and get to the bottom of bad juju. At the moment, it's just a dice roller, but later
 * functions will include a rolls database that can track any sinking feeling that the kind of
 * cheetos you're eating is influencing your rolls. Also v.1.0 is aiming at 5th edition D&D rules
 * usage. Later versions will be more system agnostic. This is intended for mobile release, but
 * for now, this is just the engine. Minus the actual engine. Broad strokes to get the system
 * working. Much to be built! -Ian
 */

//todo: un-daisychain physics()=>rollDBizer()=>rollOut().
//Allow the calling function to call each separately.
//remove rework in rollDB.
//make rollTime a public variable, or handle it in a better way.
//actually have a saved rollDB.
//allow the user to opt out of DBizing for test rolls.
//add 1-10 importance DB element.
//add standard juju options.
//add home-spun juju options.
//port to Java, Python, Ruby.
//somehow access accelorometer.
//build propper physics engine.
//have something that mines data for analysis.
//somehow build GUI for rolls and DB analysis.
//when all that's done, start building integrated RPG framework for more tools.

//public variables
var displayNumDc = 0,
    displaySides = 0,
    displayRolls = [],
    displayTotal = 0;

//saved rolls go here so they can be accessed and analyzed (unitl a proper DB is made)
//currnet version forgets after the battery of console.log()s are made. Need a proper DB,
//but this is proof of concept. todo: db that can store previous rolls.
var rollDB = [];

/*the physics engine (to be built: a different abstract function than builtin Math.random().
It will access the device's accelerometer and add physics + chaos to generate the roll.
it'll be totally sweet!*/
function physics(diceNumber, diceSides) {

    var rolls = [];

    displaySides = diceSides;
    displayNumDc = diceNumber;

    //warning! no edge case protection! You gotta use it just right! Todo: handle edge cases

    //rolls each die separately then pushes to "rolls" array.
    for (var i = 0; i < diceNumber; i++) {
	    rolls.push(Math.ceil( Math.random() * diceSides ));
    }

    displayRolls = rolls;

    //folds the array into a neat total
    var rollTotal = rolls.reduce(function(a ,b) {
	return a + b;
    });

    displayTotal = rollTotal;
    return rollDBizer();
}

//function between physics and rollOut that passes roll results to rollDB.
function rollDBizer() {
    var rollTime = new Date(),
	rollEntry = [],

    //rollTime set to Now in ms. Date function, roll stats organized to rollEntry
    rollEntry = [rollTime.getTime(), displayNumDc, displaySides, displayRolls, displayTotal];

    rollDB.push(rollEntry);

    return rollOut(displayNumDc, displaySides, displayRolls, displayTotal);
}

//Separate output function, so that code is easy to delete.
//make it so every lowest possible roll that's rolled displays "Wheaton!"
    //instead of the number
//comment out any portion if you don't want Wil distracting you so much.
//uncomment Percy if you're an optimist.
function rollOut(diceNumber, diceSides, rolls, rollTotal) {
    if (rollTotal === diceNumber) {
	rollTotal = "Wheaton!";
    } else if (rollTotal < (0.33 * (diceSides * diceNumber))){
	rollTotal += " lesser Wheaton.";
    } /*else if (rollTotal === (diceSides * diceNumber)) {
	rollTotal = "Percy!";
    } else if (rollTotal > (0.66 * (diceSides * diceNumber))) {
	rollTotal += " lesser Percy.";
    }*/

    //returns a neat string that shows what you rolled, how each roll went, and the total.
    //This will probably be numberfied and separated out when the actual UI gets built
    if (diceNumber === 1) {
	return ("1 d" + diceSides + ": " + rollTotal);
    } else {
	return (diceNumber + " d" + diceSides + ": " + rolls.join(", ") + " Total: " + rollTotal);}
}

//input functions.
//uses public variables to access physics() function.
function roll(diceNumber, diceSides) {
    return physics(diceNumber, diceSides);
}

/*Mixed dice rolls. There are 6 Standard dice in D&D.
d4, d6, d8, d10, d12, and d20. It would be quite unusual for all these
types of dice to be rolled at the same time, but just in case,
rollMix will be able to handle up to 6 different kinds of dice rolls. */
function rollMix(dNum1, dSid1, dNum2, dSid2, dNum3, dSid3,
		 dNum4, dSid4, dNum5, dSid5, dNum6, dSid6) {
    var diceMix = [],
	mixTotal = 0;
	diceRold = [];

    physics(dNum1, dSid1);
    diceRold.push(dNum1 + " d" + dSid1);
    for (var i = 0; i < displayRolls.length; i++) {
	diceMix.push(displayRolls[i]);
    }

    if (dNum2) {
	physics(dNum2, dSid2);
	diceRold.push(dNum2 + " d" + dSid2);
	for (var i = 0; i < displayRolls.length; i++) {
		diceMix.push(displayRolls[i]);
	}
    }
    if (dNum3) {
	physics(dNum3, dSid3);
	diceRold.push(dNum3 + " d" + dSid3);
	for (var i = 0; i < displayRolls.length; i++) {
		diceMix.push(displayRolls[i]);
	}
    }
    if (dNum4) {
	physics(dNum4, dSid4);
	diceRold.push(dNum4 + " d" + dSid4);
	for (var i = 0; i < displayRolls.length; i++) {
		diceMix.push(displayRolls[i]);
	}
    }
    if (dNum5) {
	physics(dNum5, dSid5);
	diceRold.push(dNum5 + " d" + dSid5);
	for (var i = 0; i < displayRolls.length; i++) {
		diceMix.push(displayRolls[i]);
	}
    }
    if (dNum6) {
	physics(dNum6, dSid6);
	diceRold.push(dNum6 + " d" + dSid6);
	for (var i = 0; i < displayRolls.length; i++) {
		diceMix.push(displayRolls[i]);
	}
    }

    mixTotal = diceMix.reduce(function(a ,b) {
	return a + b;
    });

    var displayString = (diceRold.join(", ") + ": "
	+ diceMix.join(", ") + " Total: " + mixTotal);

    return displayString;
}

//Special kinds of D&D rolls, Advantage, Disadvantage, Percent, Inspiration and mixed rolls
//to make sure rollDB gets the proper push, this inefficiently reworks and rewrites rollDBizer().
function rollAdvantage() {
    var rollTime = new Date();
    physics(2, 20);
    displayNumDc = "A";
    displayTotal = Math.max(displayRolls[0], displayRolls[1]);
    rollDB[rollDB.length -1] = [rollTime.getTime(), displayNumDc, displaySides,
				displayRolls, displayTotal];
    return (displayRolls.join(" & ") + ". Result: " + displayTotal);
}

function rollDisadvantage() {
    var rollTime = new Date();
    physics(2, 20);
    displayNumDc = "D";
    displayTotal = Math.min(displayRolls[0], displayRolls[1]);
    rollDB[rollDB.length -1] = [rollTime.getTime(), displayNumDc, displaySides,
				displayRolls, displayTotal];
    return (displayRolls.join(" & ") + ". Result: " + displayTotal);
}

//todo : make sure rollDB gets the proper displayTotal
//entry[1] needs to change to "%". entry[4] needs to change to the true in-game result.
function rollPercent() {
    var rollTime = new Date();
    physics(2, 10);
    displayNumDc = "%";
    displayTotal = ((displayRolls[0] % 10) * 10) + (displayRolls[1] % 10);
    if (displayTotal === 0) displayTotal = 100;
    rollDB[rollDB.length -1] = [rollTime.getTime(), displayNumDc, displaySides,
				displayRolls, displayTotal];
    return (displayRolls.join(" & ") + " %Score: " + displayTotal);
}

//Accesses the last most recent roll, check if it is a d20 roll,
//then add itself to that roll.
//Handles Advantage, & Disadvantage rolls as well.
function rollInspiration() {
    var lastRoll = 0;
    if (displaySides === 20) {
	lastRoll = displayTotal;
	physics(1, 10);
	return ("+" + displayTotal + " to " + lastRoll + ": "
		+ (lastRoll + displayTotal));
    } else {
	return ("You can only add an inspiration die to a d20 roll.");
    }
}

//input for manual rolls (like if you're using real dice). changes public variables directly.
function rollManual(diceNumber, diceSides, rolls) {
    displayNumDc = diceNumber;
    displaySides = diceSides;
    //todo: create an if statement that checks that rolls is an Array.
    displayRolls = rolls;
    displayTotal = rolls.reduce(function(a ,b) {
	return a + b;
    });
    return rollDBizer();
}

//manual testing, no edge cases yet.
console.log(roll(1,20));
console.log(rollInspiration());
console.log(roll(2,12));
console.log(rollInspiration());
console.log(roll(10,6));
console.log(rollAdvantage());
console.log(rollInspiration());
console.log(rollDisadvantage());
console.log(rollInspiration());
console.log(rollManual(10, 6, [4, 4, 4, 2, 5, 2, 3, 2, 1, 6]));
console.log(rollManual(2, 12, [5, 2]));
console.log(rollInspiration());
console.log(rollManual(1, 20, [20]));
console.log(rollInspiration());
console.log(rollMix(2, 12));
console.log(rollMix(2, 12, 3, 10));
console.log(rollPercent());
console.log(rollPercent());
console.log(rollPercent());
console.log(rollPercent());
console.log(rollPercent());
console.log(rollDB);
<commit_msg>refactor to remove dependencies<commit_after>/* wheatonDice is an opensource project to study the legendary dice curse of Wil Wheaton
 * and get to the bottom of bad juju. At the moment, it's just a dice roller, but later
 * functions will include a rolls database that can track any sinking feeling that the kind of
 * cheetos you're eating is influencing your rolls. Also v.1.0 is aiming at 5th edition D&D rules
 * usage. Later versions will be more system agnostic. This is intended for mobile release, but
 * for now, this is just the engine. Minus the actual engine. Broad strokes to get the system
 * working. Much to be built! -Ian
 */

//todo: un-daisychain physics()=>rollDBizer()=>rollOut().
	//===> !!! *** fix rollDBizer *** !!! <===
//Allow the calling function to call each separately.
//remove rework in rollDB.
//make rollTime a public variable, or handle it in a better way.
//actually have a saved rollDB.
//allow the user to opt out of DBizing for test rolls.
//add 1-10 importance DB element.
//add standard juju options.
//add home-spun juju options.
//port to Java, Python, Ruby.
//somehow access accelorometer.
//build propper physics engine.
//have something that mines data for analysis.
//somehow build GUI for rolls and DB analysis.
//when all that's done, start building integrated RPG framework for more tools.

//public variables
var displayNumDc = 0,
    displaySides = 0,
    displayRolls = [],
    displayTotal = 0;

//saved rolls go here so they can be accessed and analyzed (unitl a proper DB is made)
//currnet version forgets after the battery of console.log()s are made. Need a proper DB,
//but this is proof of concept. todo: db that can store previous rolls.
var rollDB = [];

/*the physics engine (to be built: a different abstract function than builtin Math.random().
It will access the device's accelerometer and add physics + chaos to generate the roll.
it'll be totally sweet!*/
function physics(diceNumber, diceSides) {

    var rolls = [];

    displaySides = diceSides;
    displayNumDc = diceNumber;

    //warning! no edge case protection! You gotta use it just right! Todo: handle edge cases

    //rolls each die separately then pushes to "rolls" array.
    for (var i = 0; i < diceNumber; i++) {
	    rolls.push(Math.ceil( Math.random() * diceSides ));
    }

    displayRolls = rolls;

    //folds the array into a neat total
    var rollTotal = rolls.reduce(function(a ,b) {
	return a + b;
    });

    displayTotal = rollTotal;
}

//function between physics and rollOut that passes roll results to rollDB.
function rollDBizer() {
    var rollTime = new Date(),
	rollEntry = [],

    //rollTime set to Now in ms. Date function, roll stats organized to rollEntry
    rollEntry = [rollTime.getTime(), displayNumDc, displaySides, displayRolls, displayTotal];

    rollDB.push(rollEntry);
}

//Separate output function, so that code is easy to delete.
//make it so every lowest possible roll that's rolled displays "Wheaton!"
    //instead of the number
//comment out any portion if you don't want Wil distracting you so much.
//uncomment Percy if you're an optimist.
function rollOut() {
    if (displayTotal === displayNumDc) {
	displayTotal = "Wheaton!";
    } else if (displayTotal < (0.33 * (displaySides * displayNumDc))){
	displayTotal += " lesser Wheaton.";
    } /*else if (displayTotal === (displaySides * displayNumDc)) {
	displayTotal = "Percy!";
    } else if (displayTotal > (0.66 * (displaySides * displayNumDc))) {
	displayTotal += " lesser Percy.";
    }*/

    //returns a neat string that shows what you rolled, how each roll went, and the total.
    //This will probably be numberfied and separated out when the actual UI gets built
    if (displayNumDc === 1) {
	return ("1 d" + displaySides + ": " + displayTotal);
    } else {
	return (displayNumDc + " d" + displaySides + ": " + displayRolls.join(", ") + " Total: " + displayTotal);}
}

//input functions.
//uses public variables to access physics() function.
function roll(diceNumber, diceSides) {
    physics(diceNumber, diceSides);
    rollDBizer();
    return rollOut();
}

/*Mixed dice rolls. There are 6 Standard dice in D&D.
d4, d6, d8, d10, d12, and d20. It would be quite unusual for all these
types of dice to be rolled at the same time, but just in case,
rollMix will be able to handle up to 6 different kinds of dice rolls. */
function rollMix(dNum1, dSid1, dNum2, dSid2, dNum3, dSid3,
		 dNum4, dSid4, dNum5, dSid5, dNum6, dSid6) {
    var diceMix = [],
	mixTotal = 0;
	diceRold = [];

    physics(dNum1, dSid1);
    diceRold.push(dNum1 + " d" + dSid1);
    for (var i = 0; i < displayRolls.length; i++) {
	diceMix.push(displayRolls[i]);
    }

    if (dNum2) {
	physics(dNum2, dSid2);
	diceRold.push(dNum2 + " d" + dSid2);
	for (var i = 0; i < displayRolls.length; i++) {
		diceMix.push(displayRolls[i]);
	}
    }
    if (dNum3) {
	physics(dNum3, dSid3);
	diceRold.push(dNum3 + " d" + dSid3);
	for (var i = 0; i < displayRolls.length; i++) {
		diceMix.push(displayRolls[i]);
	}
    }
    if (dNum4) {
	physics(dNum4, dSid4);
	diceRold.push(dNum4 + " d" + dSid4);
	for (var i = 0; i < displayRolls.length; i++) {
		diceMix.push(displayRolls[i]);
	}
    }
    if (dNum5) {
	physics(dNum5, dSid5);
	diceRold.push(dNum5 + " d" + dSid5);
	for (var i = 0; i < displayRolls.length; i++) {
		diceMix.push(displayRolls[i]);
	}
    }
    if (dNum6) {
	physics(dNum6, dSid6);
	diceRold.push(dNum6 + " d" + dSid6);
	for (var i = 0; i < displayRolls.length; i++) {
		diceMix.push(displayRolls[i]);
	}
    }

    mixTotal = diceMix.reduce(function(a ,b) {
	return a + b;
    });

    var displayString = (diceRold.join(", ") + ": "
	+ diceMix.join(", ") + " Total: " + mixTotal);

    return displayString;
}

//Special kinds of D&D rolls, Advantage, Disadvantage, Percent, Inspiration and mixed rolls
//to make sure rollDB gets the proper push, this inefficiently reworks and rewrites rollDBizer().
function rollAdvantage() {
    var rollTime = new Date();
    physics(2, 20);
    displayNumDc = "A";
    displayTotal = Math.max(displayRolls[0], displayRolls[1]);
    rollDB[rollDB.length -1] = [rollTime.getTime(), displayNumDc, displaySides,
				displayRolls, displayTotal];
    return (displayRolls.join(" & ") + ". Result: " + displayTotal);
}

function rollDisadvantage() {
    var rollTime = new Date();
    physics(2, 20);
    displayNumDc = "D";
    displayTotal = Math.min(displayRolls[0], displayRolls[1]);
    rollDB[rollDB.length -1] = [rollTime.getTime(), displayNumDc, displaySides,
				displayRolls, displayTotal];
    return (displayRolls.join(" & ") + ". Result: " + displayTotal);
}

//todo : make sure rollDB gets the proper displayTotal
//entry[1] needs to change to "%". entry[4] needs to change to the true in-game result.
function rollPercent() {
    var rollTime = new Date();
    physics(2, 10);
    displayNumDc = "%";
    displayTotal = ((displayRolls[0] % 10) * 10) + (displayRolls[1] % 10);
    if (displayTotal === 0) displayTotal = 100;
    rollDB[rollDB.length -1] = [rollTime.getTime(), displayNumDc, displaySides,
				displayRolls, displayTotal];
    return (displayRolls.join(" & ") + " %Score: " + displayTotal);
}

//Accesses the last most recent roll, check if it is a d20 roll,
//then add itself to that roll.
//Handles Advantage, & Disadvantage rolls as well.
function rollInspiration() {
    var lastRoll = 0;
    if (displaySides === 20) {
	lastRoll = displayTotal;
	physics(1, 10);
	return ("+" + displayTotal + " to " + lastRoll + ": "
		+ (lastRoll + displayTotal));
    } else {
	return ("You can only add an inspiration die to a d20 roll.");
    }
}

//input for manual rolls (like if you're using real dice). changes public variables directly.
function rollManual(diceNumber, diceSides, rolls) {
    displayNumDc = diceNumber;
    displaySides = diceSides;
    //todo: create an if statement that checks that rolls is an Array.
    displayRolls = rolls;
    displayTotal = rolls.reduce(function(a ,b) {
	return a + b;
    });
    rollDBizer();
    return rollOut();
}

//manual testing, no edge cases yet.
console.log(roll(1,20));
console.log(rollInspiration());
console.log(roll(2,12));
console.log(rollInspiration());
console.log(roll(10,6));
console.log(rollAdvantage());
console.log(rollInspiration());
console.log(rollDisadvantage());
console.log(rollInspiration());
console.log(rollManual(10, 6, [4, 4, 4, 2, 5, 2, 3, 2, 1, 6]));
console.log(rollManual(2, 12, [5, 2]));
console.log(rollInspiration());
console.log(rollManual(1, 20, [20]));
console.log(rollInspiration());
console.log(rollMix(2, 12));
console.log(rollMix(2, 12, 3, 10));
console.log(rollPercent());
console.log(rollPercent());
console.log(rollPercent());
console.log(rollPercent());
console.log(rollPercent());
console.log(rollDB);
<|endoftext|>


<commit_before>module("About Scope (topics/about_scope.js)");

thisIsAGlobalVariable = 77;

test("global variables", function() {
    equal(__, thisIsAGlobalVariable, 'is thisIsAGlobalVariable defined in this scope?');
});

test("variables declared inside of a function", function() {
    var outerVariable = "outer";

    // this is a self-invoking function. Notice that it calls itself at the end ().
    (function() {
        var innerVariable = "inner";
        equal(__, outerVariable, 'is outerVariable defined in this scope?');
        equal(__, innerVariable, 'is innerVariable defined in this scope?');
    })();

    equal(__, outerVariable, 'is outerVariable defined in this scope?');
    equal(__, typeof(innerVariable), 'is innerVariable defined in this scope?');
});
<commit_msg>About scope done<commit_after>module("About Scope (topics/about_scope.js)");

thisIsAGlobalVariable = 77;

test("global variables", function() {
    equal(77, thisIsAGlobalVariable, 'is thisIsAGlobalVariable defined in this scope?');
});

test("variables declared inside of a function", function() {
    var outerVariable = "outer";

    // this is a self-invoking function. Notice that it calls itself at the end ().
    (function() {
        var innerVariable = "inner";
        equal('outer', outerVariable, 'is outerVariable defined in this scope?');
        equal('inner', innerVariable, 'is innerVariable defined in this scope?');
    })();

    equal('outer', outerVariable, 'is outerVariable defined in this scope?');
    equal('undefined', typeof(innerVariable), 'is innerVariable defined in this scope?');
});
<|endoftext|>


<commit_before>import {run, Rx} from '@cycle/core';
import {makeDOMDriver, h} from '@cycle/dom';
import CycleTimeTravel from 'cycle-time-travel';
import $ from 'jquery';
import _ from 'lodash';
import rhyme from 'rhyme';

Rx.config.longStackSupport = true;

function log (label) {
  return console.log.bind(console, label);
}

function keyPressed (key, number) {
  return ev => {
    return ev.key === key || ev.keyIdentifier === key || ev.keyCode === number;
  };
}

function addRhyme (rhymingDictionary) {
  return state => {
    const wordToRhyme = lastWord(state.text);
    const availableRhymes = rhymingDictionary.rhyme(wordToRhyme);
    const madeRhyme = _.shuffle(availableRhymes).slice(0, 1)[0];
    let text;

    if (wordToRhyme === state.lastWord) {
      const textArray = state.text.split(' ');
      textArray.splice(textArray.length - 1, textArray.length);
      text = textArray.join(' ') + ' ' + madeRhyme.toLowerCase();
    } else {
      text = state.text + madeRhyme.toLowerCase();
    }

    if (_.isEmpty(availableRhymes)) {
      return Object.assign({}, state, {notification: 'No Rhymes'});
    }

    const stateUpdates = {
      text: text,
      notification: '',
      lastWord: wordToRhyme
    };
    return Object.assign({}, state, stateUpdates);
  };
}

function lastWord (text) {
  return _.chain(text.split('\n'))
    .map(_.trim)
    .select(line => line !== '')
    .map(line => line.split(' '))
    .thru(lines => {
      if (lines.length > 1) {
        return lines[lines.length - 2];
      }

      return _.last(lines);
    })
    .last().value();
}

function updateText (textEnteredByUser) {
  return state => Object.assign({}, state, {text: textEnteredByUser, notification: ''});
}

function main ({DOM}) {
  const textUpdate$ = DOM.select('.text').events('input')
    .map(event => event.target.value);

  const keyPress$ = DOM.select('.container').events('keydown');

  const tabPress$ = keyPress$.filter(keyPressed('Tab', 9));

  const rhymePress$ = Rx.Observable.merge(
    tabPress$,
    DOM.select('.rhyme').events('click')
  );

  const rhymingDictionary$ = Rx.Observable.fromCallback(rhyme)();

  rhymePress$.forEach(ev => ev.preventDefault());

  const action$ = Rx.Observable.merge(
    rhymePress$.withLatestFrom(rhymingDictionary$, (ev, rhymingDictionary) => addRhyme(rhymingDictionary)),
    textUpdate$.map(text => updateText(text))
  );

  const initialState = {
    text: '',
    notification: ''
  };

  const state$ = action$.scan((state, action) => action(state), initialState)
    .startWith(initialState)
    .do(function (state) {
      console.log('state', JSON.stringify(state))
    });

  return {
    DOM: state$.map(({text, notification}) => (
      h('.container', [
        h('h1', 'Ghostwriter'),
        h('.app-inner', [
          h('button.rhyme', 'RHYME'),
          h('textarea.text', {rows: 18, value: text}),
          h('.notification', notification)
        ])
      ])
    ))
  };
}

const drivers = {
  DOM: makeDOMDriver('.app')
};

$(() => run(main, drivers));
<commit_msg>Fix no rhmyes notification<commit_after>import {run, Rx} from '@cycle/core';
import {makeDOMDriver, h} from '@cycle/dom';
import CycleTimeTravel from 'cycle-time-travel';
import $ from 'jquery';
import _ from 'lodash';
import rhyme from 'rhyme';

Rx.config.longStackSupport = true;

function log (label) {
  return console.log.bind(console, label);
}

function keyPressed (key, number) {
  return ev => {
    return ev.key === key || ev.keyIdentifier === key || ev.keyCode === number;
  };
}

function addRhyme (rhymingDictionary) {
  return state => {
    const wordToRhyme = lastWord(state.text);
    const availableRhymes = rhymingDictionary.rhyme(wordToRhyme);
    const madeRhyme = _.shuffle(availableRhymes).slice(0, 1)[0];

    if (_.isEmpty(availableRhymes)) {
      return Object.assign({}, state, {notification: 'No Rhymes'});
    }

    // TODO - refactor to avoid mutability
    let text;

    if (wordToRhyme === state.lastWord) {
      const textArray = state.text.split(' ');
      textArray.splice(textArray.length - 1, textArray.length);
      text = textArray.join(' ') + ' ' + madeRhyme.toLowerCase();
    } else {
      text = state.text + madeRhyme.toLowerCase();
    }

    const stateUpdates = {
      text: text,
      notification: '',
      lastWord: wordToRhyme
    };
    return Object.assign({}, state, stateUpdates);
  };
}

function lastWord (text) {
  return _.chain(text.split('\n'))
    .map(_.trim)
    .select(line => line !== '')
    .map(line => line.split(' '))
    .thru(lines => {
      if (lines.length > 1) {
        return lines[lines.length - 2];
      }

      return _.last(lines);
    })
    .last().value();
}

function updateText (textEnteredByUser) {
  return state => Object.assign({}, state, {text: textEnteredByUser, notification: ''});
}

function main ({DOM}) {
  const textUpdate$ = DOM.select('.text').events('input')
    .map(event => event.target.value);

  const keyPress$ = DOM.select('.container').events('keydown');

  const tabPress$ = keyPress$.filter(keyPressed('Tab', 9));

  const rhymePress$ = Rx.Observable.merge(
    tabPress$,
    DOM.select('.rhyme').events('click')
  );

  const rhymingDictionary$ = Rx.Observable.fromCallback(rhyme)();

  rhymePress$.forEach(ev => ev.preventDefault());

  const action$ = Rx.Observable.merge(
    rhymePress$.withLatestFrom(rhymingDictionary$, (ev, rhymingDictionary) => addRhyme(rhymingDictionary)),
    textUpdate$.map(text => updateText(text))
  );

  const initialState = {
    text: '',
    notification: ''
  };

  const state$ = action$.scan((state, action) => action(state), initialState)
    .startWith(initialState)
    .do(function (state) {
      console.log('state', JSON.stringify(state))
    });

  return {
    DOM: state$.map(({text, notification}) => (
      h('.container', [
        h('h1', 'Ghostwriter'),
        h('.app-inner', [
          h('button.rhyme', 'RHYME'),
          h('textarea.text', {rows: 18, value: text}),
          h('.notification', notification)
        ])
      ])
    ))
  };
}

const drivers = {
  DOM: makeDOMDriver('.app')
};

$(() => run(main, drivers));
<|endoftext|>


<commit_before>const fs = require('fs-extra')
const path = require('path')
const chalk = require('chalk')
const gzipSize = require('gzip-size')
const filesize = require('filesize');
const webpack = require('webpack')

const logger = require('../lib/logger')
const webpackConfig = require('../webpack.config')
const project = require('../../project.config')

const runWebpackCompiler = (webpackConfig) =>
  new Promise((resolve, reject) => {
    webpack(webpackConfig).run((err, stats) => {
      if (err) {
        logger.error('Webpack compiler encountered a fatal error.', err)
        return reject(err)
      }

      const jsonStats = stats.toJson()
      if (jsonStats.errors.length > 0) {
        logger.error('Webpack compiler encountered errors.')
        logger.log(jsonStats.errors.join('\n'))
        return reject(new Error('Webpack compiler encountered errors'))
      } else if (jsonStats.warnings.length > 0) {
        logger.warn('Webpack compiler encountered warnings.')
        logger.log(jsonStats.warnings.join('\n'))
      }
      resolve(stats)
    })
  })

const computeSizeLabel = (current, previous) => {
  const diff = previous ? current - previous : 0

  if (diff > 0) {
    return `${filesize(current)} (${chalk.red(`+ ${filesize(diff)}`)})`
  }
  else if (diff < 0) {
    return `${filesize(current)} (${chalk.green(`- ${filesize(-diff)}`)})`
  }

  return filesize(current)
}

const retrievePreviousAssets = assetsSummaryPath => {
  try {
    return JSON
      .parse(fs.readFileSync(assetsSummaryPath, 'utf-8'))
      .reduce((acc, asset) => {
        acc[asset.genericName] = asset
        return acc
      }, {})
  } catch (Error) {
    logger.warn('Previous bundle stats could not be loaded, bundles will not be compared.')
  }

  return null
}

const displayAssetsSummary = (assets, previousAssets) => {
  const longestPath = Math.max.apply(null, assets.map(a => a.path.length))

  logger.log()
  logger.log('File sizes after gzip:')
  logger.log()
  assets.forEach(asset => {
    const previous = previousAssets ? previousAssets[asset.genericName] : null
    const sizeLabel = computeSizeLabel(asset.gzip, previous ? previous.gzip : null)

    let padding = ''
    if (asset.path.length < longestPath) {
      padding = ' '.repeat(longestPath - asset.path.length)
    }

    logger.log(
      `  ${chalk.dim(asset.folder + path.sep) +
      chalk.cyan(asset.genericName)}` +
      padding +
      `  ${sizeLabel}`
    )
  })
  logger.log()

  const total = assets.reduce((sum, a) => a.gzip + sum, 0)
  let previousTotal = null

  if (previousAssets) {
    previousTotal = Object.values(previousAssets).reduce((sum, a) => a.gzip + sum, 0)
  }

  const sizeLabel = computeSizeLabel(total, previousTotal)

  const totalLabel = 'TOTAL'
  logger.log(
    `  ${chalk.cyan(totalLabel)}` +
    ' '.repeat(longestPath - totalLabel.length) +
    `  ${sizeLabel}`
  )
  logger.log()
}

const saveAssetsSummary = (assets, assetsSummaryPath) => {
  try {
    fs.writeFileSync(assetsSummaryPath, JSON.stringify(assets, null, 2), {
      encoding: 'utf-8'
    })

    logger.success(`Saved JSON bundle stats in ${chalk.bold(assetsSummaryPath)}.`)
  }
  catch (Error) {
    logger.warn(`Could not save JSON bundle stats in ${chalk.bold(assetsSummaryPath)}.`)
  }
}

const compile = () => {
  const assetsSummaryPath = path.join(project.reportDir, 'bundles.json')

  logger.info('Starting compiler…')
  logger.info('Target application environment: ' + chalk.bold(project.env))

  runWebpackCompiler(webpackConfig)
    .then(stats => {
      const assets = stats.toJson().assets
        .filter(asset => !/\.map$/.test(asset.name))
        .map(asset => {
          const contents = fs.readFileSync(path.join(project.outDir, asset.name))
          const gsize = gzipSize.sync(contents)

          const folder = path.join(project.outDir, path.dirname(asset.name))
          const name = path.basename(asset.name)

          // Can’t include a `.` in the webpack entries, or this will break
          const genericName = name.replace(/^(.*?\.)[^.]+\.(.*)$/, '$1$2')

          return {
            folder,
            name,
            genericName,

            path: `${folder}${path.sep}${genericName}`,

            size: asset.size,
            gzip: gsize
          }
        })

      assets.sort((a, b) => b.gzip - a.gzip);

      const previousAssets = retrievePreviousAssets(assetsSummaryPath)

      displayAssetsSummary(assets, previousAssets)
      saveAssetsSummary(assets, assetsSummaryPath)

      logger.info(`Copying static assets from ./public to ./${project.outDir}.`)
      fs.copySync(
        path.resolve(project.basePath, 'public'),
        path.resolve(project.basePath, project.outDir)
      )

      logger.success(`Compiler finished successfully! See ./${project.outDir}.`)
    })
    .catch((err) => logger.error('Compiler encountered errors.', err))
}

compile()
<commit_msg>Resolve asset json summary path<commit_after>const fs = require('fs-extra')
const path = require('path')
const chalk = require('chalk')
const gzipSize = require('gzip-size')
const filesize = require('filesize');
const webpack = require('webpack')

const logger = require('../lib/logger')
const webpackConfig = require('../webpack.config')
const project = require('../../project.config')

const runWebpackCompiler = (webpackConfig) =>
  new Promise((resolve, reject) => {
    webpack(webpackConfig).run((err, stats) => {
      if (err) {
        logger.error('Webpack compiler encountered a fatal error.', err)
        return reject(err)
      }

      const jsonStats = stats.toJson()
      if (jsonStats.errors.length > 0) {
        logger.error('Webpack compiler encountered errors.')
        logger.log(jsonStats.errors.join('\n'))
        return reject(new Error('Webpack compiler encountered errors'))
      } else if (jsonStats.warnings.length > 0) {
        logger.warn('Webpack compiler encountered warnings.')
        logger.log(jsonStats.warnings.join('\n'))
      }
      resolve(stats)
    })
  })

const computeSizeLabel = (current, previous) => {
  const diff = previous ? current - previous : 0

  if (diff > 0) {
    return `${filesize(current)} (${chalk.red(`+ ${filesize(diff)}`)})`
  }
  else if (diff < 0) {
    return `${filesize(current)} (${chalk.green(`- ${filesize(-diff)}`)})`
  }

  return filesize(current)
}

const retrievePreviousAssets = assetsSummaryPath => {
  try {
    return JSON
      .parse(fs.readFileSync(assetsSummaryPath, 'utf-8'))
      .reduce((acc, asset) => {
        acc[asset.genericName] = asset
        return acc
      }, {})
  } catch (Error) {
    logger.warn('Previous bundle stats could not be loaded, bundles will not be compared.')
  }

  return null
}

const displayAssetsSummary = (assets, previousAssets) => {
  const longestPath = Math.max.apply(null, assets.map(a => a.path.length))

  logger.log()
  logger.log('File sizes after gzip:')
  logger.log()
  assets.forEach(asset => {
    const previous = previousAssets ? previousAssets[asset.genericName] : null
    const sizeLabel = computeSizeLabel(asset.gzip, previous ? previous.gzip : null)

    let padding = ''
    if (asset.path.length < longestPath) {
      padding = ' '.repeat(longestPath - asset.path.length)
    }

    logger.log(
      `  ${chalk.dim(asset.folder + path.sep) +
      chalk.cyan(asset.genericName)}` +
      padding +
      `  ${sizeLabel}`
    )
  })
  logger.log()

  const total = assets.reduce((sum, a) => a.gzip + sum, 0)
  let previousTotal = null

  if (previousAssets) {
    previousTotal = Object.values(previousAssets).reduce((sum, a) => a.gzip + sum, 0)
  }

  const sizeLabel = computeSizeLabel(total, previousTotal)

  const totalLabel = 'TOTAL'
  logger.log(
    `  ${chalk.cyan(totalLabel)}` +
    ' '.repeat(longestPath - totalLabel.length) +
    `  ${sizeLabel}`
  )
  logger.log()
}

const saveAssetsSummary = (assets, assetsSummaryPath) => {
  try {
    fs.writeFileSync(assetsSummaryPath, JSON.stringify(assets, null, 2), {
      encoding: 'utf-8'
    })

    logger.success(`Saved JSON bundle stats in ${chalk.bold(assetsSummaryPath)}.`)
  }
  catch (Error) {
    logger.warn(`Could not save JSON bundle stats in ${chalk.bold(assetsSummaryPath)}.`)
  }
}

const compile = () => {
  const assetsSummaryPath = path.resolve(path.join(project.reportDir, 'bundles.json'))

  logger.info('Starting compiler…')
  logger.info('Target application environment: ' + chalk.bold(project.env))

  runWebpackCompiler(webpackConfig)
    .then(stats => {
      const assets = stats.toJson().assets
        .filter(asset => !/\.map$/.test(asset.name))
        .map(asset => {
          const contents = fs.readFileSync(path.join(project.outDir, asset.name))
          const gsize = gzipSize.sync(contents)

          const folder = path.join(project.outDir, path.dirname(asset.name))
          const name = path.basename(asset.name)

          // Can’t include a `.` in the webpack entries, or this will break
          const genericName = name.replace(/^(.*?\.)[^.]+\.(.*)$/, '$1$2')

          return {
            folder,
            name,
            genericName,

            path: `${folder}${path.sep}${genericName}`,

            size: asset.size,
            gzip: gsize
          }
        })

      assets.sort((a, b) => b.gzip - a.gzip);

      const previousAssets = retrievePreviousAssets(assetsSummaryPath)

      displayAssetsSummary(assets, previousAssets)
      saveAssetsSummary(assets, assetsSummaryPath)

      logger.info(`Copying static assets from ./public to ./${project.outDir}.`)
      fs.copySync(
        path.resolve(project.basePath, 'public'),
        path.resolve(project.basePath, project.outDir)
      )

      logger.success(`Compiler finished successfully! See ./${project.outDir}.`)
    })
    .catch((err) => logger.error('Compiler encountered errors.', err))
}

compile()
<|endoftext|>


<commit_before>'use strict';

/* Controllers */

 var profileModule = angular.module('profile', ['firebase'])

 profileModule.controller('ProfileCtr', ['$scope', '$rootScope', '$firebase', '$http', 'Facebook', 'FacebookPromises', function($scope, $rootScope, $firebase, $http, Facebook, FacebookPromises) {
		console.log("is facebook ready?", Facebook.isReady());
 		if ($scope.loggedInToFacebook) {
 			getMyFacebookInfo();
 		} else {
	 		$scope.$watch(function() {
	 			return $scope.loggedInToFacebook;
	 		},
	 		function(loggedIn) {
	 			console.log('newVal:', loggedIn);
	 			if (loggedIn) {
		 			getMyFacebookInfo();
	 			}
	 		});
 		}

 		function getMyFacebookInfo() {
 			console.log('kicking off get my facebook info');
	 		FacebookPromises.query('me', 'get', { fields: 'id,name,about,birthday,education,photos,education' })
	 			.then(function(response) {
	 				console.log(response)
	 				// $scope.profileinfo = response;
	 				var uniqueid = response.id;
	 				$rootScope.facebookId = uniqueid;
	 				var name = response.name;
	 				var birthday = response.birthday;
	 				var education = response.education[response.education.length-1].school.name
	 				var photos = [];
	 				console.log("hi")
	 				for (var i=0; i<response.photos.data.length; i++) {
	 					photos.push(response.photos.data[i].source);
	 				};
	 				// Save into firebase
	 				var profileRef = new Firebase("https://amber-fire-4122.firebaseio.com/users/" + uniqueid);

			 		// angularfire!!!///////////////////////////////////////////////////////
			 		var sync = $firebase(profileRef);
			 		//download the data into a local object
			 		var syncObject = sync.$asObject();
			 		// sync the object with a three way binding, use asObject() to create a synchronized object, then call $bindTo() which binds
			 		// it to a $scope variable
			 		syncObject.$bindTo($scope, 'profile');

	 				var profile = { name: name, birthday: birthday, photos: photos, education: education };
	 				profileRef.set(profile);

	 			}, function(response) {
 					console.log(response);
	 			})
 		}

 		var showProfileRef = new Firebase("https://amber-fire-4122.firebaseio.com/users/")
		showProfileRef.on('value', function(snapshot) {
				console.log("snapshot", snapshot.val());
				var users = snapshot.val();
				console.log("fbidddd", FacebookPromises.userId);
				var fbookid = FacebookPromises.userId;
				console.log(users);
				console.log("ihope this works", users[fbookid]);
				$scope.$apply($scope.me = users[fbookid]);
				console.log($scope.me);
		});

		this.submitAboutMe =function(){
			console.log("ng click happenned");
			console.log("aboutmeis", $scope.aboutmetext);
		};

  }]);

 angular.module('SoraLogin', [])
 .controller('LoginCtr', ['$location', '$scope', 'FacebookPromises', function($location, $scope, FacebookPromises) {

 		this.login = function(){
 			console.log('happening!!!!');
 			FacebookPromises.login()
 				.then(function(response){
	 				// FacebookPromises.userId =  response.authResponse.userID;
	 				$location.path('/home');
	 				console.log('good',response);
	 			},function(response){
 					console.log('error',response);
 				});
 		};

  }]);

 var home = angular.module('home',[]);

 home.controller('homeController',['$scope',function($scope){

 }]);

<commit_msg>updating the firebase about me works<commit_after>'use strict';

/* Controllers */

 var profileModule = angular.module('profile', ['firebase'])

 profileModule.controller('ProfileCtr', ['$scope', '$rootScope', '$firebase', '$http', 'Facebook', 'FacebookPromises', function($scope, $rootScope, $firebase, $http, Facebook, FacebookPromises) {
		console.log("is facebook ready?", Facebook.isReady());
 		if ($scope.loggedInToFacebook) {
 			getMyFacebookInfo();
 		} else {
	 		$scope.$watch(function() {
	 			return $scope.loggedInToFacebook;
	 		},
	 		function(loggedIn) {
	 			console.log('newVal:', loggedIn);
	 			if (loggedIn) {
		 			getMyFacebookInfo();
	 			}
	 		});
 		}

 		function getMyFacebookInfo() {
 			console.log('kicking off get my facebook info');
	 		FacebookPromises.query('me', 'get', { fields: 'id,name,about,birthday,education,photos,education' })
	 			.then(function(response) {
	 				console.log(response)
	 				// $scope.profileinfo = response;
	 				var uniqueid = response.id;
	 				$rootScope.facebookId = uniqueid;
	 				var name = response.name;
	 				var birthday = response.birthday;
	 				var education = response.education[response.education.length-1].school.name
	 				var photos = [];
	 				console.log("hi")
	 				for (var i=0; i<response.photos.data.length; i++) {
	 					photos.push(response.photos.data[i].source);
	 				};
	 				// Save into firebase
	 				var profileRef = new Firebase("https://amber-fire-4122.firebaseio.com/users/" + uniqueid);

			 		// angularfire!!!///////////////////////////////////////////////////////
			 		var sync = $firebase(profileRef);
			 		//download the data into a local object
			 		var syncObject = sync.$asObject();
			 		// sync the object with a three way binding, use asObject() to create a synchronized object, then call $bindTo() which binds
			 		// it to a $scope variable
			 		syncObject.$bindTo($scope, 'profile');

	 				var profile = { name: name, birthday: birthday, photos: photos, education: education };
	 				profileRef.set(profile);

	 			}, function(response) {
 					console.log(response);
	 			})
 		}

 		var showProfileRef = new Firebase("https://amber-fire-4122.firebaseio.com/users/")
		showProfileRef.on('value', function(snapshot) {
				console.log("snapshot", snapshot.val());
				var users = snapshot.val();
				console.log("fbidddd", FacebookPromises.userId);
				var fbookid = FacebookPromises.userId;
				console.log(users);
				console.log("ihope this works", users[fbookid]);
				$scope.$apply($scope.me = users[fbookid]);
				console.log($scope.me);
		});

// when submit button is clicked, save about me text to firebase
		this.submitAboutMe =function(){
			console.log("aboutmeis", $scope.aboutmetext);
			console.log(FacebookPromises.userId);
			var fbid = FacebookPromises.userId;
			var meRef = showProfileRef.child(fbid);
			meRef.update({aboutme: $scope.aboutmetext})
		};

  }]);

 angular.module('SoraLogin', [])
 .controller('LoginCtr', ['$location', '$scope', 'FacebookPromises', function($location, $scope, FacebookPromises) {

 		this.login = function(){
 			console.log('happening!!!!');
 			FacebookPromises.login()
 				.then(function(response){
	 				// FacebookPromises.userId =  response.authResponse.userID;
	 				$location.path('/home');
	 				console.log('good',response);
	 			},function(response){
 					console.log('error',response);
 				});
 		};

  }]);

 var home = angular.module('home',[]);

 home.controller('homeController',['$scope',function($scope){

 }]);

<|endoftext|>


<commit_before>'use strict';

var peerhandler = angular.module('peerhandler', []);

peerhandler.factory('peerFactory', function($rootScope, $ionicPopup, $state, $timeout) {
    // PeerJS object representing the user
    var me                = null;

    // Stream object;
    var localStream       = null;

    // Stream sources
    var remoteVideoSource = null;
    var localVideoSource  = null;

    var currentCall   = null;

    // Private api
    var getLocalStream = function(successCallback) {
        if (localStream && successCallback) {
            successCallback(localStream)
        } else {
            navigator.webkitGetUserMedia(
                {
                    audio: true,
                    video: true
                },
                function (stream) {
                    localStream = stream;
                    setLocalStreamSrc(stream);
                    if (successCallback) {
                        successCallback(stream);
                    }
                },
                function(err){
                    console.log(err);
                }
            )
        }
    };

    var setRemoteStreamSrc = function (stream) {
        console.log('setting remote source!');
      remoteVideoSource = window.URL.createObjectURL(stream);
        console.log(remoteVideoSource);
    };

    var setLocalStreamSrc = function (stream) {
        console.log('setting local source!');
        localVideoSource = window.URL.createObjectURL(stream);
        console.log(localVideoSource);
    };

    var answer = function(call) {
        call.on('stream', setRemoteStreamSrc);
        call.on('close', function() {
            alert('Call ended by other!');

        });
        call.answer(localStream);
    };

    // Public PeerJS api
    return {
        getMe: function() {
            if (!me) {return null;}
            return me;
        },
        getRemoteStreamSrc: function() {
            if (!remoteVideoSource) {console.log('No video remote source!')}
            return remoteVideoSource;
        },
        getLocalStreamSrc: function() {
            if (!localVideoSource) {console.log('No video remote source!')}
            return localVideoSource;
        },
        isConnected: function() {
            if (!me) {return false}
            else {return !me.disconnected}
        },
        connectToPeerJS: function(id)   {
            me = new Peer(id, $rootScope.config.peerjs);

            if (!me) {
              alert('Error creating peer!');
            }
            me.on('open', function(id) {
                console.log('Connection opened: ' + id);
            });

            me.on('call', function(mediaConnection) {
                console.log(mediaConnection);
              console.log('Call initiated by ' + mediaConnection.peer );

                var confirmPopup = $ionicPopup.confirm({
                    title: 'Call from ' + mediaConnection.peer,
                    template: 'Incoming call. Answer?'
                });
                confirmPopup.then(function(res) {
                    if(res) {
                        answer(mediaConnection);
                        $timeout(function() {
                            $state.go('call', {user: { displayName: mediaConnection.peer }});
                        }, 500)
                    } else {
                        return false;
                    }
                });
            });

            me.on('connection', function(dataConnection) {
                console.log('dataconnection formed!');
                console.log(dataConnection);
            });

            me.socket._socket.onopen = function() {
              getLocalStream();
            };

            me.on('error', function(error) {
              var errorMsg = error.toString();
              var errorAlert = $ionicPopup.alert({
                  title: 'Something went wrong!',
                  template: errorMsg
              });
             errorAlert.then(function(res) {
                 if (_.contains(errorMsg, 'Lost connection to server')) {
                     $state.go('login');
                 }
              });
            });
        },
        callPeer: function (userToCall) {
            if (!me) return;

            getLocalStream(function (stream) {
                currentCall = me.call(userToCall.number, stream, { metadata: me.id})
                currentCall.on('error', function (err) {
                    console.log('Call error');
                });

                currentCall.on('stream', function(stream) {
                    setRemoteStreamSrc(stream);
                    $timeout(function() {
                        $state.go('call', {user: userToCall});
                    }, 500)
                });

                currentCall.on('close', function() {
                    alert('call ended by you');
                });
            });

        },
        endCurrentCall: function() {
            if (currentCall) {
                currentCall.close();
                currentCall = null;
            }
        },
        disconnectFromPeerJS: function() {
            me.disconnect();
        }
    }
});
<commit_msg>Don't throw around alerts all the time<commit_after>'use strict';

var peerhandler = angular.module('peerhandler', []);

peerhandler.factory('peerFactory', function($rootScope, $ionicPopup, $ionicHistory, $state, $timeout) {
    // PeerJS object representing the user
    var me                = null;

    // Stream object;
    var localStream       = null;

    // Stream sources
    var remoteVideoSource = null;
    var localVideoSource  = null;

    var currentCall   = null;

    // Private api
    var getLocalStream = function(successCallback) {
        if (localStream && successCallback) {
            successCallback(localStream)
        } else {
            navigator.webkitGetUserMedia(
                {
                    audio: true,
                    video: true
                },
                function (stream) {
                    localStream = stream;
                    setLocalStreamSrc(stream);
                    if (successCallback) {
                        successCallback(stream);
                    }
                },
                function(err){
                    console.log(err);
                }
            )
        }
    };

    var setRemoteStreamSrc = function (stream) {
        console.log('setting remote source!');
      remoteVideoSource = window.URL.createObjectURL(stream);
        console.log(remoteVideoSource);
    };

    var setLocalStreamSrc = function (stream) {
        console.log('setting local source!');
        localVideoSource = window.URL.createObjectURL(stream);
        console.log(localVideoSource);
    };

    var answer = function(call) {
        call.on('stream', setRemoteStreamSrc);
        call.on('close', function() {
            var callEndedAlert = $ionicPopup.alert({
                title: 'Call over!',
                template: 'Call was ended by the other party'
            });
            callEndedAlert.then(function() {
                $ionicHistory.goBack();
            });
        });

        call.answer(localStream);
    };

    // Public PeerJS api
    return {
        getMe: function() {
            if (!me) {return null;}
            return me;
        },
        getRemoteStreamSrc: function() {
            if (!remoteVideoSource) {console.log('No video remote source!')}
            return remoteVideoSource;
        },
        getLocalStreamSrc: function() {
            if (!localVideoSource) {console.log('No video remote source!')}
            return localVideoSource;
        },
        isConnected: function() {
            if (!me) {return false}
            else {return !me.disconnected}
        },
        connectToPeerJS: function(id)   {
            me = new Peer(id, $rootScope.config.peerjs);

            if (!me) {
              alert('Error creating peer!');
            }
            me.on('open', function(id) {
                console.log('Connection opened: ' + id);
            });

            me.on('call', function(mediaConnection) {
                console.log(mediaConnection);
              console.log('Call initiated by ' + mediaConnection.peer );

                var confirmPopup = $ionicPopup.confirm({
                    title: 'Call from ' + mediaConnection.peer,
                    template: 'Incoming call. Answer?'
                });
                confirmPopup.then(function(res) {
                    if(res) {
                        answer(mediaConnection);
                        $timeout(function() {
                            $state.go('call', {user: { displayName: mediaConnection.peer }});
                        }, 500)
                    } else {
                        return false;
                    }
                });
            });

            me.on('connection', function(dataConnection) {
                console.log('dataconnection formed!');
                console.log(dataConnection);
            });

            me.socket._socket.onopen = function() {
              getLocalStream();
            };

            me.on('error', function(error) {
              var errorMsg = error.toString();
              var errorAlert = $ionicPopup.alert({
                  title: 'Something went wrong!',
                  template: errorMsg
              });
             errorAlert.then(function(res) {
                 if (_.contains(errorMsg, 'Lost connection to server')) {
                     $state.go('login');
                 }
              });
            });
        },
        callPeer: function (userToCall) {
            if (!me) return;

            getLocalStream(function (stream) {
                currentCall = me.call(userToCall.number, stream, { metadata: me.id})
                currentCall.on('error', function (err) {
                    console.log('Call error');
                });

                currentCall.on('stream', function(stream) {
                    setRemoteStreamSrc(stream);
                    $timeout(function() {
                        $state.go('call', {user: userToCall});
                    }, 500)
                });

                currentCall.on('close', function() {
                    console.log('call closed');
                });
            });

        },
        endCurrentCall: function() {
            if (currentCall) {
                currentCall.close();
                currentCall = null;
            }
        },
        disconnectFromPeerJS: function() {
            me.disconnect();
        }
    }
});
<|endoftext|>


<commit_before>(function(window){
	var $ = window.jQuery;

	$.fn.Present = function( options ) {
		return this;
	}

})(window);<commit_msg>Instance watcher<commit_after>(function(window){
	var $ = window.jQuery;
	var instance = false;

	var Present = function( options ) {
		return this;
	}

	$.fn.Present = function( options ) {
		if(instance) {
			if (window.console) window.console.warn('Present.js is already instantiated!');
			return instance;
		} else {
			return instance = new Present( options );
		}
	}

})(window);<|endoftext|>


<commit_before>var express = require('express');
var exphbs  = require('express-handlebars');
var app = express();
var BME280 = require('node-bme280');
var barometer = new BME280({address: 0x77});
var latestTemp;
var latestPressure;
var latestHumidity;
var ready = false;

var Datastore = require('nedb')
  , db = new Datastore({ filename: 'data.txt', autoload: true });

barometer.begin(function(err) {
    if (err) {
        console.info('error initializing barometer', err);
        return;
    }
    console.info('barometer running');
	setImmediate(readData);
	setInterval(readData, 60 * 1000);
});

var readData = function () {
	barometer.readPressureAndTemparature(function(err, pressure, temperature, humidity) {
		latestTemp = temperature.toFixed(2);
		latestPressure = (pressure / 100).toFixed(2);
		latestHumidity = humidity.toFixed(2);
		ready = true;
		db.insert({
			time: new Date(),
			ambientTemperature: latestTemp,
			pressure: latestPressure,
			humidity: latestHumidity
		});
	});
};

app.engine('handlebars', exphbs({defaultLayout: false}));
app.set('view engine', 'handlebars');
app.use(express.static('static'));

app.get('/', function (req, res) {
	/*res.write("<meta http-equiv=\"refresh\" content=\"5\"><meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">");
	if (ready) {
		res.write("Temperature: " + latestTemp + " ℃
");
		res.write("Pressure: " + latestPressure + " hPa
");
		res.write("Humidity: " + latestHumidity + "%\n");
	} else {
		res.write("No data is available currently.");
	}
	res.end("");*/
	if (ready) {
		res.render("index", {
			ready: true,
			sensors: [
				{
					value: parseFloat(latestTemp).toFixed(1),
					unit: "°C",
					measurement: "Temperature",
					location: "ICT office"
				},
				{
					value: parseFloat(latestHumidity).toFixed(1),
					unit: "%",
					measurement: "Humidity",
					location: "ICT office"
				},
				{
					value: parseFloat(latestPressure).toFixed(0),
					unit: "hPa",
					small: true,
					measurement: "Pressure",
					location: "ICT office"
				}
			]
		});
	} else {
		res.render("index", {
			ready: false
		});
	}
});

app.get('/output.csv', function (req, res) {
	db.find({}).sort({ time: 1 }).exec(function (err, docs) {
		res.write("Time,Temperature,Pressure,Humidity\n");
		for (var i = 0; i < docs.length; i++) {
			var time = docs[i].time;
			var formattedDate = time.getFullYear() + "-" + (time.getMonth() + 1) + "-" + time.getDate();
			var formattedTime = time.getHours() + ":" + time.getMinutes() + ":" + time.getSeconds();
			var formattedDateTime = formattedDate + " " + formattedTime; // github doesn't like long lines
			res.write(formattedDateTime + ",");
			res.write(docs[i].ambientTemperature + ",");
			res.write(docs[i].pressure + ",");
			res.write(docs[i].humidity + "\n");
		}
		res.end();
	});
});

app.listen(80, function () {
	console.log('Example app listening on port 80!');
});
<commit_msg>test not ready<commit_after>var express = require('express');
var exphbs  = require('express-handlebars');
var app = express();
var BME280 = require('node-bme280');
var barometer = new BME280({address: 0x77});
var latestTemp;
var latestPressure;
var latestHumidity;
var ready = false;

var Datastore = require('nedb')
  , db = new Datastore({ filename: 'data.txt', autoload: true });

barometer.begin(function(err) {
    if (err) {
        console.info('error initializing barometer', err);
        return;
    }
    console.info('barometer running');
	setImmediate(readData);
	setInterval(readData, 60 * 1000);
});

var readData = function () {
	barometer.readPressureAndTemparature(function(err, pressure, temperature, humidity) {
		latestTemp = temperature.toFixed(2);
		latestPressure = (pressure / 100).toFixed(2);
		latestHumidity = humidity.toFixed(2);
		ready = true;
		db.insert({
			time: new Date(),
			ambientTemperature: latestTemp,
			pressure: latestPressure,
			humidity: latestHumidity
		});
	});
};

app.engine('handlebars', exphbs({defaultLayout: false}));
app.set('view engine', 'handlebars');
app.use(express.static('static'));

app.get('/', function (req, res) {
	/*res.write("<meta http-equiv=\"refresh\" content=\"5\"><meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">");
	if (ready) {
		res.write("Temperature: " + latestTemp + " ℃
");
		res.write("Pressure: " + latestPressure + " hPa
");
		res.write("Humidity: " + latestHumidity + "%\n");
	} else {
		res.write("No data is available currently.");
	}
	res.end("");*/
	/*if (ready) {
		res.render("index", {
			ready: true,
			sensors: [
				{
					value: parseFloat(latestTemp).toFixed(1),
					unit: "°C",
					measurement: "Temperature",
					location: "ICT office"
				},
				{
					value: parseFloat(latestHumidity).toFixed(1),
					unit: "%",
					measurement: "Humidity",
					location: "ICT office"
				},
				{
					value: parseFloat(latestPressure).toFixed(0),
					unit: "hPa",
					small: true,
					measurement: "Pressure",
					location: "ICT office"
				}
			]
		});
	} else {*/
		res.render("index", {
			ready: false
		});
	//}
});

app.get('/output.csv', function (req, res) {
	db.find({}).sort({ time: 1 }).exec(function (err, docs) {
		res.write("Time,Temperature,Pressure,Humidity\n");
		for (var i = 0; i < docs.length; i++) {
			var time = docs[i].time;
			var formattedDate = time.getFullYear() + "-" + (time.getMonth() + 1) + "-" + time.getDate();
			var formattedTime = time.getHours() + ":" + time.getMinutes() + ":" + time.getSeconds();
			var formattedDateTime = formattedDate + " " + formattedTime; // github doesn't like long lines
			res.write(formattedDateTime + ",");
			res.write(docs[i].ambientTemperature + ",");
			res.write(docs[i].pressure + ",");
			res.write(docs[i].humidity + "\n");
		}
		res.end();
	});
});

app.listen(80, function () {
	console.log('Example app listening on port 80!');
});
<|endoftext|>