<commit_before>/*
Copyright 2016 First People's Cultural Council

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

import Immutable, {List, Map} from 'immutable';
import StringHelpers from './StringHelpers'

import selectn from 'selectn';

const toJSKeepId = function (js) {
    return typeof js !== 'object' || js === null ? js :
        Array.isArray(js) ?
            Immutable.Seq(js).map(toJSKeepId).toList() :
            (js.hasOwnProperty('id')) ? Immutable.Seq(js).toMap() : Immutable.Seq(js).map(toJSKeepId).toMap();
}

const proxiesKeys = [
    {
        workspace: 'fv-word:categories',
        section: 'fvproxy:proxied_categories'
    },
    {
        workspace: 'fv-phrase:phrase_books',
        section: 'fvproxy:proxied_categories'
    },
    {
        workspace: 'fvm:origin',
        section: 'fvproxy:proxied_origin'
    },
    {
        workspace: 'fv:related_pictures',
        section: 'fvproxy:proxied_pictures'
    },
    {
        workspace: 'fv:related_videos',
        section: 'fvproxy:proxied_videos'
    },
    {
        workspace: 'fv:related_audio',
        section: 'fvproxy:proxied_audio'
    }
];

const getEntryFunc = function (wordResults, path) {
    if (!wordResults || wordResults.isEmpty() || !path) {
        return null;
    }

    let result = wordResults.find(function (entry) {
        return entry.get('id') === path;
    });

    if (result) {
        return result.toJS();
    }

    return null;
};

export default {
    getEntry: getEntryFunc,
    // Will perform action only if the data is not found in store
    // @key - the key to look up (or set) in the store for this action/reducer
    // @action - the action to perform if nothing found in store.
    // @reducer - the reducer to look for
    fetchIfMissing: function (key, action, reducer) {
        if (!selectn('success', getEntryFunc(reducer, key))) {
            action(key);
        }
    },
    toJSKeepId: function (js) {
        return toJSKeepId(js)
    },
    /*hasExtendedGroup: function (extendedGroups, group) {

      if (extendedGroups && extendedGroups.size > 0) {
        if (extendedGroups.findIndex(function(entry) { return (entry.get('name') === group) }) === -1) {
          return false;
        } else {
          return true;
        }
      }

      return false;
    },*/
    isActiveRole: function (roles) {
        if (roles && roles.length > 0) {
            if (roles.indexOf("Record") !== -1 || roles.indexOf("Approve") !== -1 || roles.indexOf("Manage") !== -1 || roles.indexOf("Member") !== -1) {
                return true;
            }
        }

        return false;
    },
    /**
     * A site member is not associated with any specific dialect, but still has access to site for other functionality.
     */
    isSiteMember: function (groups) {
        return groups && groups.length === 1 && groups[0] === "members";
    },
    getDialectPathFromURLArray: function (url) {
        return decodeURI(url.slice(1, 7).join('/'));
    },
    switchWorkspaceSectionKeys: function (workspaceKey, area) {

        let row = proxiesKeys.find(function (mapping) {
            return mapping.workspace === workspaceKey;
        })

        if (row) {
            if (area == 'sections') {
                return row.section;
            } else {
                return row.workspace;
            }
        }

        return workspaceKey;
    },
    getDialectGroups: function (aces = [], currentlyAssignedGroups = []) {

        if (aces.length === 0) {
            return {
                all: null,
                new: null
            };
        }

        // Generate list of groups this user can be added to
        let allAvailableGroups = {};

        // Generate list of all groups related to this dialect
        let newAvailableGroups = {};

        (aces).forEach(function (group, i) {
            let groupArray = group.username.split('_');
            if (group.username.match(/members|recorders|administrators/g) != null) {

                let groupLabel = groupArray.map((group) => StringHelpers.toTitleCase(group)).join(' ');

                allAvailableGroups[group.username] = groupLabel;

                // If user is not already a memeber of this group, add to new available groups
                if (currentlyAssignedGroups.indexOf(group.username) === -1) {
                    newAvailableGroups[group.username] = groupLabel;
                }
            }
        });

        return {
            all: allAvailableGroups,
            new: newAvailableGroups
        };
    },
    replaceAllWorkspaceSectionKeys: function (string, area) {

        let searchKey = (area == 'sections') ? 'workspace' : 'section';
        let replaceKey = (area == 'sections') ? 'section' : 'workspace';

        for (let proxyKey in proxiesKeys) {
            string = string.replace(new RegExp(proxiesKeys[proxyKey][searchKey], 'g'), proxiesKeys[proxyKey][replaceKey]);
        }

        return string;
    },
    filtersToNXQL: function (filterArray) {

        let nxqlFilterString = '';
        let nxqlGroups = {};

        const generateNXQLString = function (nxql, appliedFilter) {
            return nxql.replace(/\$\{value\}/g, appliedFilter);
        }

        for (let appliedFilterKey in filterArray) {
            let ak = Object.assign({}, filterArray[appliedFilterKey]);
            if (ak && ak.hasOwnProperty('filterOptions') && ak.filterOptions && ak.filterOptions.hasOwnProperty('nxql')) {

                if (ak.appliedFilter === true) (ak.appliedFilter = 1);
                if (ak.appliedFilter === false) (ak.appliedFilter = 0);

                if (!ak.filterOptions.hasOwnProperty('nxqlGroup')) {
                    nxqlFilterString += ' ' + (ak.filterOptions.hasOwnProperty('operator') ? ak.filterOptions.operator : 'AND') + ' ' + generateNXQLString(ak.filterOptions.nxql, ak.appliedFilter);
                } else {
                    if (nxqlGroups.hasOwnProperty(ak.filterOptions.nxqlGroup) && nxqlGroups[ak.filterOptions.nxqlGroup].length > 0) {
                        nxqlGroups[ak.filterOptions.nxqlGroup].push(generateNXQLString(ak.filterOptions.nxql, ak.appliedFilter));
                    } else {
                        nxqlGroups[ak.filterOptions.nxqlGroup] = [generateNXQLString(ak.filterOptions.nxql, ak.appliedFilter)];
                    }
                }
            }
        }

        let appendGroupNXQL = '';

        for (var key in nxqlGroups) {
            appendGroupNXQL += ' AND (' + nxqlGroups[key].join(' OR ') + ')'
        }

        return nxqlFilterString + appendGroupNXQL;
    },
    regex: {
        ANYTHING_BUT_SLASH: "([^/]*)",
        ANY_LANGUAGE_CODE: "(en|fr)",
        WORKSPACE_OR_SECTION: "(sections|Workspaces)",
        KIDS_OR_DEFAULT: "(kids|explore)"
    },
    userRegistrationRoles: [
        {value: 'languagerevitilizer', text: 'I am involved in language revitilization'},
        {value: 'teacher', text: 'I am a teacher'},
        {value: 'educator', text: 'I am an educator'},
        {value: 'student', text: 'I am a learner/student'},
        {value: 'learner-1', text: 'I am interested in learning MY language'},
        {value: 'learner-2', text: 'I am interested in learning A language'},
        {value: 'other', text: 'Other (please mention in comments)'}
    ]
}<commit_msg>Fix typo<commit_after>/*
Copyright 2016 First People's Cultural Council

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

import Immutable, {List, Map} from 'immutable';
import StringHelpers from './StringHelpers'

import selectn from 'selectn';

const toJSKeepId = function (js) {
    return typeof js !== 'object' || js === null ? js :
        Array.isArray(js) ?
            Immutable.Seq(js).map(toJSKeepId).toList() :
            (js.hasOwnProperty('id')) ? Immutable.Seq(js).toMap() : Immutable.Seq(js).map(toJSKeepId).toMap();
}

const proxiesKeys = [
    {
        workspace: 'fv-word:categories',
        section: 'fvproxy:proxied_categories'
    },
    {
        workspace: 'fv-phrase:phrase_books',
        section: 'fvproxy:proxied_categories'
    },
    {
        workspace: 'fvm:origin',
        section: 'fvproxy:proxied_origin'
    },
    {
        workspace: 'fv:related_pictures',
        section: 'fvproxy:proxied_pictures'
    },
    {
        workspace: 'fv:related_videos',
        section: 'fvproxy:proxied_videos'
    },
    {
        workspace: 'fv:related_audio',
        section: 'fvproxy:proxied_audio'
    }
];

const getEntryFunc = function (wordResults, path) {
    if (!wordResults || wordResults.isEmpty() || !path) {
        return null;
    }

    let result = wordResults.find(function (entry) {
        return entry.get('id') === path;
    });

    if (result) {
        return result.toJS();
    }

    return null;
};

export default {
    getEntry: getEntryFunc,
    // Will perform action only if the data is not found in store
    // @key - the key to look up (or set) in the store for this action/reducer
    // @action - the action to perform if nothing found in store.
    // @reducer - the reducer to look for
    fetchIfMissing: function (key, action, reducer) {
        if (!selectn('success', getEntryFunc(reducer, key))) {
            action(key);
        }
    },
    toJSKeepId: function (js) {
        return toJSKeepId(js)
    },
    /*hasExtendedGroup: function (extendedGroups, group) {

      if (extendedGroups && extendedGroups.size > 0) {
        if (extendedGroups.findIndex(function(entry) { return (entry.get('name') === group) }) === -1) {
          return false;
        } else {
          return true;
        }
      }

      return false;
    },*/
    isActiveRole: function (roles) {
        if (roles && roles.length > 0) {
            if (roles.indexOf("Record") !== -1 || roles.indexOf("Approve") !== -1 || roles.indexOf("Manage") !== -1 || roles.indexOf("Member") !== -1) {
                return true;
            }
        }

        return false;
    },
    /**
     * A site member is not associated with any specific dialect, but still has access to site for other functionality.
     */
    isSiteMember: function (groups) {
        return groups && groups.length === 1 && groups[0] === "members";
    },
    getDialectPathFromURLArray: function (url) {
        return decodeURI(url.slice(1, 7).join('/'));
    },
    switchWorkspaceSectionKeys: function (workspaceKey, area) {

        let row = proxiesKeys.find(function (mapping) {
            return mapping.workspace === workspaceKey;
        })

        if (row) {
            if (area == 'sections') {
                return row.section;
            } else {
                return row.workspace;
            }
        }

        return workspaceKey;
    },
    getDialectGroups: function (aces = [], currentlyAssignedGroups = []) {

        if (aces.length === 0) {
            return {
                all: null,
                new: null
            };
        }

        // Generate list of groups this user can be added to
        let allAvailableGroups = {};

        // Generate list of all groups related to this dialect
        let newAvailableGroups = {};

        (aces).forEach(function (group, i) {
            let groupArray = group.username.split('_');
            if (group.username.match(/members|recorders|administrators/g) != null) {

                let groupLabel = groupArray.map((group) => StringHelpers.toTitleCase(group)).join(' ');

                allAvailableGroups[group.username] = groupLabel;

                // If user is not already a memeber of this group, add to new available groups
                if (currentlyAssignedGroups.indexOf(group.username) === -1) {
                    newAvailableGroups[group.username] = groupLabel;
                }
            }
        });

        return {
            all: allAvailableGroups,
            new: newAvailableGroups
        };
    },
    replaceAllWorkspaceSectionKeys: function (string, area) {

        let searchKey = (area == 'sections') ? 'workspace' : 'section';
        let replaceKey = (area == 'sections') ? 'section' : 'workspace';

        for (let proxyKey in proxiesKeys) {
            string = string.replace(new RegExp(proxiesKeys[proxyKey][searchKey], 'g'), proxiesKeys[proxyKey][replaceKey]);
        }

        return string;
    },
    filtersToNXQL: function (filterArray) {

        let nxqlFilterString = '';
        let nxqlGroups = {};

        const generateNXQLString = function (nxql, appliedFilter) {
            return nxql.replace(/\$\{value\}/g, appliedFilter);
        }

        for (let appliedFilterKey in filterArray) {
            let ak = Object.assign({}, filterArray[appliedFilterKey]);
            if (ak && ak.hasOwnProperty('filterOptions') && ak.filterOptions && ak.filterOptions.hasOwnProperty('nxql')) {

                if (ak.appliedFilter === true) (ak.appliedFilter = 1);
                if (ak.appliedFilter === false) (ak.appliedFilter = 0);

                if (!ak.filterOptions.hasOwnProperty('nxqlGroup')) {
                    nxqlFilterString += ' ' + (ak.filterOptions.hasOwnProperty('operator') ? ak.filterOptions.operator : 'AND') + ' ' + generateNXQLString(ak.filterOptions.nxql, ak.appliedFilter);
                } else {
                    if (nxqlGroups.hasOwnProperty(ak.filterOptions.nxqlGroup) && nxqlGroups[ak.filterOptions.nxqlGroup].length > 0) {
                        nxqlGroups[ak.filterOptions.nxqlGroup].push(generateNXQLString(ak.filterOptions.nxql, ak.appliedFilter));
                    } else {
                        nxqlGroups[ak.filterOptions.nxqlGroup] = [generateNXQLString(ak.filterOptions.nxql, ak.appliedFilter)];
                    }
                }
            }
        }

        let appendGroupNXQL = '';

        for (var key in nxqlGroups) {
            appendGroupNXQL += ' AND (' + nxqlGroups[key].join(' OR ') + ')'
        }

        return nxqlFilterString + appendGroupNXQL;
    },
    regex: {
        ANYTHING_BUT_SLASH: "([^/]*)",
        ANY_LANGUAGE_CODE: "(en|fr)",
        WORKSPACE_OR_SECTION: "(sections|Workspaces)",
        KIDS_OR_DEFAULT: "(kids|explore)"
    },
    userRegistrationRoles: [
        {value: 'languagerevitalizer', text: 'I am involved in language revitalization'},
        {value: 'teacher', text: 'I am a teacher'},
        {value: 'educator', text: 'I am an educator'},
        {value: 'student', text: 'I am a learner/student'},
        {value: 'learner-1', text: 'I am interested in learning MY language'},
        {value: 'learner-2', text: 'I am interested in learning A language'},
        {value: 'other', text: 'Other (please mention in comments)'}
    ]
}<|endoftext|>


<commit_before>const Canvas = require('./canvas');

var dx = 5;
var dy = -5;

var Ball = function(game, paddle, bricks){
  var canvas = new Canvas().canvas;
  this.game = game;
  this.paddle = paddle;
  this.startAngle = 0;
  this.x = canvas.width/2;
  this.y = canvas.height-30;
  this.canvasHeightOffset = 8;
  this.radius = 10;
  this.gameSize = {x: this.game.size.x, y: this.game.size.y};
  this.bricks = bricks;
}

Ball.prototype = {

  draw: function(canvas) {
    canvas.beginPath();
    canvas.arc(this.x, this.y, this.radius, this.startAngle, Math.PI*2);
    canvas.fillStyle = "#F00000";
    canvas.fill();
    canvas.closePath();
  },

  reset: function(){
    this.startAngle = 0;
    this.x = canvas.width/2;
    this.y = canvas.height-30;
    dy = -dy
  },

  move: function () {
    this.collisionDetectionBricks();

    if(this.x + dx > this.gameSize.x-this.radius || this.x + dx < this.radius) {
      this.game.wallSound.load();
      this.game.wallSound.play();
      dx = -dx;
    }

    if((this.y - this.canvasHeightOffset) + dy < this.radius) {
      this.game.topSound.load();
      this.game.topSound.play();
      dy = -dy;
    }

    else if(this.y + dy > this.gameSize.y - (this.radius * 2)) {
      if(this.x > this.paddle.position.x && this.x < this.paddle.position.x + this.paddle.size.x) {
        this.game.paddleSound.load();
        this.game.paddleSound.play();
        dy = -dy;
      }
      else {

        this.game.lives -= 1;
        if (this.game.lives > 0){
          this.reset();
        } else {
          alert("You Fell into the Wall - GAME OVER");
          this.game.deathSound.load();
          this.game.deathSound.play();
          document.location.reload();
        }
      }
   }
    this.x += dx;
    this.y += dy;
  },

  collisionDetectionBricks: function() {
    var self = this;
    var brickHeight = self.bricks[0].size.y;
    var brickWidth = self.bricks[0].size.x;

    for (var i = 0; i < self.bricks.length; i++) {
      if((self.x > self.bricks[i].position.x)
        && (self.x < self.bricks[i].position.x + brickWidth)
        && (self.y - self.radius < self.bricks[i].position.y + brickHeight)
        && (self.y + self.radius > self.bricks[i].position.y - brickHeight)) {
        this.game.brickSound.load();
        this.game.brickSound.play();
        dy = -dy;
        self.bricks[i].status = 0;
        self.bricks.splice(i, 1);
        self.game.score += 10;
      }
    }
    return dy;
  }
};

module.exports = Ball;<commit_msg>Extended paddle Now that when you hit the corner you dont fall to your death<commit_after>const Canvas = require('./canvas');

var dx = -5;
var dy = 5;

var Ball = function(game, paddle, bricks){
  var canvas = new Canvas().canvas;
  this.game = game;
  this.paddle = paddle;
  this.startAngle = 0;
  this.x = canvas.width/2;
  this.y = canvas.height-30;
  this.canvasHeightOffset = 8;
  this.radius = 10;
  this.gameSize = {x: this.game.size.x, y: this.game.size.y};
  this.bricks = bricks;
}

Ball.prototype = {

  draw: function(canvas) {
    canvas.beginPath();
    canvas.arc(this.x, this.y, this.radius, this.startAngle, Math.PI*2);
    canvas.fillStyle = "#F00000";
    canvas.fill();
    canvas.closePath();
  },

  reset: function(){
    this.startAngle = 0;
    this.x = canvas.width/2;
    this.y = canvas.height-30;
    dy = -dy
  },

  move: function () {
    this.collisionDetectionBricks();

    if(this.x + dx > this.gameSize.x-this.radius || this.x + dx < this.radius) {
      this.game.wallSound.load();
      this.game.wallSound.play();
      dx = -dx;
    }

    if((this.y - this.canvasHeightOffset) + dy < this.radius) {
      this.game.topSound.load();
      this.game.topSound.play();
      dy = -dy;
    }

    else if(this.y + dy > this.gameSize.y - (this.radius * 2)) {
      if(this.x > this.paddle.position.x - 3 && this.x < this.paddle.position.x - 3 + this.paddle.size.x) {
        this.game.paddleSound.load();
        this.game.paddleSound.play();
        dy = -dy;
      }
      else {

        this.game.lives -= 1;
        if (this.game.lives > 0){
          this.reset();
        } else {
          alert("You Fell into the Wall - GAME OVER");
          this.game.deathSound.load();
          this.game.deathSound.play();
          document.location.reload();
        }
      }
   }
    this.x += dx;
    this.y += dy;
  },

  collisionDetectionBricks: function() {
    var self = this;
    var brickHeight = self.bricks[0].size.y;
    var brickWidth = self.bricks[0].size.x;

    for (var i = 0; i < self.bricks.length; i++) {
      if((self.x > self.bricks[i].position.x)
        && (self.x < self.bricks[i].position.x + brickWidth)
        && (self.y - self.radius < self.bricks[i].position.y + brickHeight)
        && (self.y + self.radius > self.bricks[i].position.y - brickHeight)) {
        this.game.brickSound.load();
        this.game.brickSound.play();
        dy = -dy;
        self.bricks[i].status = 0;
        self.bricks.splice(i, 1);
        self.game.score += 10;
      }
    }
    return dy;
  }
};

module.exports = Ball;<|endoftext|>


<commit_before>var tilelive = require("tilelive");

// A tilelive provider that returns solid colored tiles
var solid = require("tilelive-solid");
var s = new solid(tilelive),
	source;
tilelive.load("solid:#fff", function(err, data){
 	if(err){
 		console.log(err);
 	}else{
 		return data;
 	}
});
<commit_msg>delete test file<commit_after><|endoftext|>


<commit_before>AbstractAction = AbstractClass.extend({
	new: function(){
		var action = {
			controllerName: "",
			actionName: "",
			templateName: "",
			templateContainer: "",
			templateCollection: null,
			data: {className: "frontis"},
			hasInstance: true,
			uniqueInstance: true,
			uniqueID: "",

			partial: function(){
				//returns the rendering content
				var renderer = Renderer.new(this.templateName);
				return renderer.buildHTML(this.data, this.templateCollection);
			},
			render: function(target){
				//console.log("render::this")
				//console.log(this)
				if(target == null){
					target = this.templateContainer;
				}
				if(this.hasInstance){
					if(this.uniqueInstance){
						//no can do
						console.log(this);
						console.log("cant render...")
					}else{
						this.displayInstance(target)
					}
				}else{
					this.displayInstance(target);
				}
			},
			updateTemplate: function(data){
				//update own data
				this.data = data;
				// search template by uniqueID

				// re-render template

			},
			displayInstance: function(target){
				//console.log("displayInstance");
				this.hasInstance = true;
				var renderer = Renderer.new(this.templateName);
				renderer.displayFromJSON(this.data, this.templateCollection, target);
			}
		}
		return action;
	}
})
// each action has its own timestamp id -> Date.now()<commit_msg>update unique id of controller each time it renders<commit_after>AbstractAction = AbstractClass.extend({
	new: function(){
		var action = {
			controllerName: "",
			actionName: "",
			templateName: "",
			templateContainer: "",
			templateCollection: null,
			data: {className: "frontis"},
			hasInstance: true,
			uniqueInstance: true,
			uniqueID: "",

			partial: function(){
				//returns the rendering content
				var renderer = Renderer.new(this.templateName);
				return renderer.buildHTML(this.data, this.templateCollection);
			},
			render: function(target){
				//console.log("render::this")
				//console.log(this)
				if(target == null){
					target = this.templateContainer;
				}
				if(this.hasInstance){
					if(this.uniqueInstance){
						//no can do
						console.log(this);
						console.log("cant render...")
					}else{
						this.displayInstance(target)
					}
				}else{
					this.displayInstance(target);
				}
			},
			updateTemplate: function(data){
				//update own data
				this.data = data;
				// search template by uniqueID

				// re-render template

			},
			displayInstance: function(target){
				//console.log("displayInstance");
				this.hasInstance = true;
				this.getUniqueID(); //should instances have the uniqueID as a class?
				var renderer = Renderer.new(this.templateName);
				renderer.displayFromJSON(this.data, this.templateCollection, target);
			},
			getUniqueID: function(){
				this.uniqueID = AbstractAction.uniqueID(this);
			}
		}
		return action;
	},
	lastUniqueID: null;
	uniqueID: function(action){
		var uniq = Date.now();
		while(lastUniqueID == uniq){
			uniq = Date.now() + action.actionName;
		}
		return uniq;
	})
})
// each action has its own timestamp id -> Date.now()<|endoftext|>


<commit_before>test
<commit_msg>Delete test.js<commit_after><|endoftext|>


<commit_before>(function (GLOBAL) {
    var JSUnzip = function (fileContents) {
        this.fileContents = new JSUnzip.BigEndianBinaryStream(fileContents);
    }
    GLOBAL.JSUnzip = JSUnzip;
    JSUnzip.MAGIC_NUMBER = 0x04034b50;

    JSUnzip.prototype = {
        readEntries: function () {
            if (!this.isZipFile()) {
                throw new Error("File is not a Zip file.");
            }

            this.entries = [];
            var e = new JSUnzip.ZipEntry(this.fileContents);
            while (typeof(e.data) === "string") {
                this.entries.push(e);
                e = new JSUnzip.ZipEntry(this.fileContents);
            }
        },

        isZipFile: function () {
            return this.fileContents.getByteRangeAsNumber(0, 4) === JSUnzip.MAGIC_NUMBER;
        }
    }

    JSUnzip.ZipEntry = function (binaryStream) {
        this.signature          = binaryStream.getNextBytesAsNumber(4);
        if (this.signature !== JSUnzip.MAGIC_NUMBER) {
            return;
        }

        this.versionNeeded      = binaryStream.getNextBytesAsNumber(2);
        this.bitFlag            = binaryStream.getNextBytesAsNumber(2);
        this.compressionMethod  = binaryStream.getNextBytesAsNumber(2);
        this.timeBlob           = binaryStream.getNextBytesAsNumber(4);

        if (this.isEncrypted() ||
            this.isUsingUtf8() ||
            this.isUsingBit3TrailingDataDescriptor()) {
            return;
        }

        this.crc32              = binaryStream.getNextBytesAsNumber(4);
        this.compressedSize     = binaryStream.getNextBytesAsNumber(4);
        this.uncompressedSize   = binaryStream.getNextBytesAsNumber(4);

        if (this.isUsingZip64()) {
            return;
        }

        this.fileNameLength     = binaryStream.getNextBytesAsNumber(2);
        this.extraFieldLength   = binaryStream.getNextBytesAsNumber(2);

        this.fileName  = binaryStream.getNextBytesAsString(this.fileNameLength);
        this.extra     = binaryStream.getNextBytesAsString(this.extraFieldLength);
        this.data      = binaryStream.getNextBytesAsString(this.compressedSize);
    }

    JSUnzip.ZipEntry.prototype = {
        isEncrypted: function () {
            return (this.bitFlag & 0x01) === 0x01;
        },

        isUsingUtf8: function () {
            return (this.bitFlag & 0x0800) === 0x0800;
        },

        isUsingBit3TrailingDataDescriptor: function () {
            return (this.bitFlag & 0x0008) === 0x0008;
        },

        isUsingZip64: function () {
            this.compressedSize === 0xFFFFFFFF ||
                this.uncompressedSize === 0xFFFFFFFF;
        }
    }

    JSUnzip.BigEndianBinaryStream = function (stream) {
        this.stream = stream;
        this.resetByteIndex();
    }

    JSUnzip.BigEndianBinaryStream.prototype = {
        // The index of the current byte, used when we step through the byte
        // with getNextBytesAs*.
        resetByteIndex: function () {
            this.currentByteIndex = 0;
        },

        // TODO: Other similar JS libs does charCodeAt(index) & 0xff. Grok
        // why, and do that here if neccesary. So far, I've never gotten a
        // char code higher than 255.
        getByteAt: function (index) {
            return this.stream.charCodeAt(index);
        },

        getNextBytesAsNumber: function (steps) {
            var res = this.getByteRangeAsNumber(this.currentByteIndex, steps);
            this.currentByteIndex += steps;
            return res;
        },

        getNextBytesAsString: function (steps) {
            var res = this.getByteRangeAsString(this.currentByteIndex, steps);
            this.currentByteIndex += steps;
            return res;
        },

        // Big endian, so we're going backwards.
        getByteRangeAsNumber: function (index, steps) {
            var result = 0;
            var i = index + steps - 1;
            while (i >= index) {
                result = (result << 8) + this.getByteAt(i);
                i--;
            }
            return result;
        },

        getByteRangeAsString: function (index, steps) {
            var result = "";
            var max = index + steps;
            var i = index;
            while (i < max) {
                result += String.fromCharCode(this.getByteAt(i));
                i++;
            }
            return result;
        }
    }
}(this));<commit_msg>Stricter error handling.<commit_after>(function (GLOBAL) {
    var JSUnzip = function (fileContents) {
        this.fileContents = new JSUnzip.BigEndianBinaryStream(fileContents);
    }
    GLOBAL.JSUnzip = JSUnzip;
    JSUnzip.MAGIC_NUMBER = 0x04034b50;

    JSUnzip.prototype = {
        readEntries: function () {
            if (!this.isZipFile()) {
                throw new Error("File is not a Zip file.");
            }

            this.entries = [];
            var e = new JSUnzip.ZipEntry(this.fileContents);
            while (typeof(e.data) === "string") {
                this.entries.push(e);
                e = new JSUnzip.ZipEntry(this.fileContents);
            }
        },

        isZipFile: function () {
            return this.fileContents.getByteRangeAsNumber(0, 4) === JSUnzip.MAGIC_NUMBER;
        }
    }

    JSUnzip.ZipEntry = function (binaryStream) {
        this.signature          = binaryStream.getNextBytesAsNumber(4);
        if (this.signature !== JSUnzip.MAGIC_NUMBER) {
            return;
        }

        this.versionNeeded      = binaryStream.getNextBytesAsNumber(2);
        this.bitFlag            = binaryStream.getNextBytesAsNumber(2);
        this.compressionMethod  = binaryStream.getNextBytesAsNumber(2);
        this.timeBlob           = binaryStream.getNextBytesAsNumber(4);

        if (this.isEncrypted()) {
            throw "File contains encrypted entry. Not supported.";
        }

        if (this.isUsingUtf8()) {
            throw "File is using UTF8. Not supported.";
        }

        if (this.isUsingBit3TrailingDataDescriptor()) {
            throw "File is using bit 3 trailing data descriptor. Not supported.";
        }

        this.crc32              = binaryStream.getNextBytesAsNumber(4);
        this.compressedSize     = binaryStream.getNextBytesAsNumber(4);
        this.uncompressedSize   = binaryStream.getNextBytesAsNumber(4);

        if (this.isUsingZip64()) {
            throw "File is using Zip64 (4gb+ file size). Not supported";
        }

        this.fileNameLength     = binaryStream.getNextBytesAsNumber(2);
        this.extraFieldLength   = binaryStream.getNextBytesAsNumber(2);

        this.fileName  = binaryStream.getNextBytesAsString(this.fileNameLength);
        this.extra     = binaryStream.getNextBytesAsString(this.extraFieldLength);
        this.data      = binaryStream.getNextBytesAsString(this.compressedSize);
    }

    JSUnzip.ZipEntry.prototype = {
        isEncrypted: function () {
            return (this.bitFlag & 0x01) === 0x01;
        },

        isUsingUtf8: function () {
            return (this.bitFlag & 0x0800) === 0x0800;
        },

        isUsingBit3TrailingDataDescriptor: function () {
            return (this.bitFlag & 0x0008) === 0x0008;
        },

        isUsingZip64: function () {
            this.compressedSize === 0xFFFFFFFF ||
                this.uncompressedSize === 0xFFFFFFFF;
        }
    }

    JSUnzip.BigEndianBinaryStream = function (stream) {
        this.stream = stream;
        this.resetByteIndex();
    }

    JSUnzip.BigEndianBinaryStream.prototype = {
        // The index of the current byte, used when we step through the byte
        // with getNextBytesAs*.
        resetByteIndex: function () {
            this.currentByteIndex = 0;
        },

        // TODO: Other similar JS libs does charCodeAt(index) & 0xff. Grok
        // why, and do that here if neccesary. So far, I've never gotten a
        // char code higher than 255.
        getByteAt: function (index) {
            return this.stream.charCodeAt(index);
        },

        getNextBytesAsNumber: function (steps) {
            var res = this.getByteRangeAsNumber(this.currentByteIndex, steps);
            this.currentByteIndex += steps;
            return res;
        },

        getNextBytesAsString: function (steps) {
            var res = this.getByteRangeAsString(this.currentByteIndex, steps);
            this.currentByteIndex += steps;
            return res;
        },

        // Big endian, so we're going backwards.
        getByteRangeAsNumber: function (index, steps) {
            var result = 0;
            var i = index + steps - 1;
            while (i >= index) {
                result = (result << 8) + this.getByteAt(i);
                i--;
            }
            return result;
        },

        getByteRangeAsString: function (index, steps) {
            var result = "";
            var max = index + steps;
            var i = index;
            while (i < max) {
                result += String.fromCharCode(this.getByteAt(i));
                i++;
            }
            return result;
        }
    }
}(this));<|endoftext|>


<commit_before>var python = require('python').shell;
var web3 = require('web3');
var fs = require('fs');
var mm = require('methodmissing');
var sync = require('sync-me');
var grunt = require('grunt');

py_exec = function(cmd) {
  console.log("python: " + cmd);
  return sync(python, cmd)[1].trim();
}

py_exec("from ethertdd import EvmContract")

web3.setProvider(new web3.providers.HttpProvider('http://localhost:8101'));
web3.eth.defaultAccount = web3.eth.accounts[0];

TestContractWrapper = (function() {
  function TestContractWrapper(contract, className, args) {
    this.contract = contract;
    this.className = className;
    this.args = args;
    this.initializeContract();
  }

  TestContractWrapper.prototype.initializeContract = function() {
    example_abi = JSON.stringify(contract.info.abiDefinition)
    example_binary = contract.code.slice(2)

    py_exec("example_abi = '" + example_abi + "'")
    py_exec("example_abi")
    py_exec("example_binary = '" + example_binary + "'.decode('hex')")
    py_exec("example_binary")

    if (this.args == undefined) {
      py_exec(this.className + "_contract = EvmContract(example_abi, example_binary, '" + this.className + "')")
    }
    else {
      py_exec(this.className + "_contract = EvmContract(example_abi, example_binary, '" + this.className + "', [" + this.args.join(",") + "])")
    }

    this.contractVariable = this.className + "_contract"
  };

  TestContractWrapper.prototype.execCmd = function(method, args) {
    arg_list = [];
    for (key in args) {
      value = args[key];
      arg_list.push(value);
    }

    data = py_exec(this.className + "_contract." + method + "(" + arg_list.join(",") + ")");
    console.log("res: " + data);
    return data;
  };

  return TestContractWrapper;

})();

TestContract = function(contract, className, args) {
  var wrapper = new TestContractWrapper(contract, className, args);
  var Obj = mm(wrapper, function (key, args) {
    return wrapper.execCmd(key, args);
  });
  return Obj;
}

//TODO: get the files from the config
contractFiles = grunt.file.expand("./app/contracts/**/*.sol")
contractDB = {}

var i;
for (i = 0, len = contractFiles.length; i < len; i++) {
  var contractFile = contractFiles[i];
  var source = fs.readFileSync(contractFile).toString()

  compiled_contracts = web3.eth.compile.solidity(source)
  for (className in compiled_contracts) {
    var contract = compiled_contracts[className];
    contractDB[className] = contract;
  }
}

request = function(className, args) {
  var contract = contractDB[className];
  return TestContract(contract, className, args)
}

Test = {
  request: request
}

module.exports = Test;

<commit_msg>remove log<commit_after>var python = require('python').shell;
var web3 = require('web3');
var fs = require('fs');
var mm = require('methodmissing');
var sync = require('sync-me');
var grunt = require('grunt');

py_exec = function(cmd) {
  return sync(python, cmd)[1].trim();
}

py_exec("from ethertdd import EvmContract")

web3.setProvider(new web3.providers.HttpProvider('http://localhost:8101'));
web3.eth.defaultAccount = web3.eth.accounts[0];

TestContractWrapper = (function() {
  function TestContractWrapper(contract, className, args) {
    this.contract = contract;
    this.className = className;
    this.args = args;
    this.initializeContract();
  }

  TestContractWrapper.prototype.initializeContract = function() {
    example_abi = JSON.stringify(contract.info.abiDefinition)
    example_binary = contract.code.slice(2)

    py_exec("example_abi = '" + example_abi + "'")
    py_exec("example_abi")
    py_exec("example_binary = '" + example_binary + "'.decode('hex')")
    py_exec("example_binary")

    if (this.args == undefined) {
      py_exec(this.className + "_contract = EvmContract(example_abi, example_binary, '" + this.className + "')")
    }
    else {
      py_exec(this.className + "_contract = EvmContract(example_abi, example_binary, '" + this.className + "', [" + this.args.join(",") + "])")
    }

    this.contractVariable = this.className + "_contract"
  };

  TestContractWrapper.prototype.execCmd = function(method, args) {
    arg_list = [];
    for (key in args) {
      value = args[key];
      arg_list.push(value);
    }

    data = py_exec(this.className + "_contract." + method + "(" + arg_list.join(",") + ")");
    return data;
  };

  return TestContractWrapper;

})();

TestContract = function(contract, className, args) {
  var wrapper = new TestContractWrapper(contract, className, args);
  var Obj = mm(wrapper, function (key, args) {
    return wrapper.execCmd(key, args);
  });
  return Obj;
}

//TODO: get the files from the config
contractFiles = grunt.file.expand("./app/contracts/**/*.sol")
contractDB = {}

var i;
for (i = 0, len = contractFiles.length; i < len; i++) {
  var contractFile = contractFiles[i];
  var source = fs.readFileSync(contractFile).toString()

  compiled_contracts = web3.eth.compile.solidity(source)
  for (className in compiled_contracts) {
    var contract = compiled_contracts[className];
    contractDB[className] = contract;
  }
}

request = function(className, args) {
  var contract = contractDB[className];
  return TestContract(contract, className, args)
}

Test = {
  request: request
}

module.exports = Test;

<|endoftext|>


<commit_before>var utils = require('./utils');
var error = require('./error');
var numeral = require('numeral');

//TODO
exports.ASC = function() {
 throw new Error('ASC is not implemented');
};

//TODO
exports.BAHTTEXT = function() {
 throw new Error('BAHTTEXT is not implemented');
};

exports.CHAR = function(number) {
  number = utils.parseNumber(number);
  if (number instanceof Error) {
    return number;
  }
  return String.fromCharCode(number);
};

exports.CLEAN = function(text) {
  text = text || '';
  var re = /[\0-\x1F]/g;
  return text.replace(re, "");
};

exports.CODE = function(text) {
  text = text || '';
  return text.charCodeAt(0);
};

exports.CONCATENATE = function() {
  var args = utils.flatten(arguments);

  var trueFound = 0;
  while ((trueFound = args.indexOf(true)) > -1) {
    args[trueFound] = 'TRUE';
  }

  var falseFound = 0;
  while ((falseFound = args.indexOf(false)) > -1) {
    args[falseFound] = 'FALSE';
  }

  return args.join('');
};

//TODO
exports.DBCS = function() {
 throw new Error('DBCS is not implemented');
};

exports.DOLLAR = function(number, decimals) {
  decimals = (decimals === undefined) ? 2 : decimals;

  number = utils.parseNumber(number);
  decimals = utils.parseNumber(decimals);
  if (utils.anyIsError(number, decimals)) {
    return error.value;
  }
  var format = '';
  if (decimals <= 0) {
    number = Math.round(number * Math.pow(10, decimals)) / Math.pow(10, decimals);
    format = '($0,0)';
  } else if (decimals > 0) {
    format = '($0,0.' + new Array(decimals + 1).join('0') + ')';
  }
  return numeral(number).format(format);
};

exports.EXACT = function(text1, text2) {
  return text1 === text2;
};

exports.FIND = function(find_text, within_text, position) {
  position = (position === undefined) ? 0 : position;
  return within_text ? within_text.indexOf(find_text, position - 1) + 1 : null;
};

exports.FIXED = function(number, decimals, no_commas) {
  decimals = (decimals === undefined) ? 2 : decimals;
  no_commas = (no_commas === undefined) ? false : no_commas;

  number = utils.parseNumber(number);
  decimals = utils.parseNumber(decimals);
  if (utils.anyIsError(number, decimals)) {
    return error.value;
  }

  var format = no_commas ? '0' : '0,0';
  if (decimals <= 0) {
    number = Math.round(number * Math.pow(10, decimals)) / Math.pow(10, decimals);
  } else if (decimals > 0) {
    format += '.' + new Array(decimals + 1).join('0');
  }
  return numeral(number).format(format);
};

exports.HTML2TEXT = function (value) {
  var result = '';

  if (value) {
    if (value instanceof Array) {
      value.forEach(function (line) {
        if (result !== '') {
          result += '\n';
        }
        result += (line.replace(/<(?:.|\n)*?>/gm, ''));
      });
    } else {
      result = value.replace(/<(?:.|\n)*?>/gm, '');
    }
  }

  return result;
};

exports.LEFT = function(text, number) {
  number = (number === undefined) ? 1 : number;
  number = utils.parseNumber(number);
  if (number instanceof Error || typeof text !== 'string') {
    return error.value;
  }
  return text ? text.substring(0, number) : null;
};

exports.LEN = function(text) {
  if (arguments.length === 0) {
    return error.error;
  }

  if (typeof text === 'string') {
    return text ? text.length : 0;
  }

  if (text.length) {
    return text.length;
  }

  return error.value;
};

exports.LOWER = function(text) {
  if (typeof text !== 'string') {
    return error.value;
  }
  return text ? text.toLowerCase() : text;
};

exports.MID = function(text, start, number) {
  start = utils.parseNumber(start);
  number = utils.parseNumber(number);
  if (utils.anyIsError(start, number) || typeof text !== 'string') {
    return number;
  }
  return text.substring(start - 1, number);
};

// TODO
exports.NUMBERVALUE = function (text, decimal_separator, group_separator)  {
  decimal_separator = (typeof decimal_separator === 'undefined') ? '.' : decimal_separator;
  group_separator = (typeof group_separator === 'undefined') ? ',' : group_separator;
  return Number(text.replace(decimal_separator, '.').replace(group_separator, ''));
};

// TODO
exports.PRONETIC = function() {
 throw new Error('PRONETIC is not implemented');
};

exports.PROPER = function(text) {
  if (text === undefined || text.length === 0) {
    return error.value;
  }
  if (text === true) {
    text = 'TRUE';
  }
  if (text === false) {
    text = 'FALSE';
  }
  if (isNaN(text) && typeof text === 'number') {
    return error.value;
  }
  if (typeof text === 'number') {
    text = '' + text;
  }

  return text.replace(/\w\S*/g, function(txt) {
    return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
  });
};

exports.REGEXEXTRACT = function (text, regular_expression) {
  var match = text.match(new RegExp(regular_expression));
  return match ? (match[match.length > 1 ? match.length - 1 : 0]) : null;
};

exports.REGEXMATCH = function (text, regular_expression, full) {
  var match = text.match(new RegExp(regular_expression));
  return full ? match : !!match;
};

exports.REGEXREPLACE = function (text, regular_expression, replacement) {
  return text.replace(new RegExp(regular_expression), replacement);
};

exports.REPLACE = function(text, position, length, new_text) {
  position = utils.parseNumber(position);
  length = utils.parseNumber(length);
  if (utils.anyIsError(position, length) ||
    typeof text !== 'string' ||
    typeof new_text !== 'string') {
    return error.value;
  }
  return text.substr(0, position - 1) + new_text + text.substr(position - 1 + length);
};

exports.REPT = function(text, number) {
  number = utils.parseNumber(number);
  if (number instanceof Error) {
    return number;
  }
  return new Array(number + 1).join(text);
};

exports.RIGHT = function(text, number) {
  number = (number === undefined) ? 1 : number;
  number = utils.parseNumber(number);
  if (number instanceof Error) {
    return number;
  }
  return text ? text.substring(text.length - number) : null;
};

exports.SEARCH = function(find_text, within_text, position) {
  if (typeof find_text !== 'string' || typeof within_text !== 'string') {
    return error.value;
  }
  position = (position === undefined) ? 0 : position;
  return within_text.toLowerCase().indexOf(find_text.toLowerCase(), position - 1) + 1;
};

exports.SPLIT = function (text, separator) {
  return text.split(separator);
};

exports.SUBSTITUTE = function(text, old_text, new_text, occurrence) {
  if (!text || !old_text || !new_text) {
    return text;
  } else if (occurrence === undefined) {
    return text.replace(new RegExp(old_text, 'g'), new_text);
  } else {
    var index = 0;
    var i = 0;
    while (text.indexOf(old_text, index) > 0) {
      index = text.indexOf(old_text, index + 1);
      i++;
      if (i === occurrence) {
        return text.substring(0, index) + new_text + text.substring(index + old_text.length);
      }
    }
  }
};

exports.T = function(value) {
  return (typeof value === "string") ? value : '';
};

// TODO incomplete implementation
exports.TEXT = function(value, format) {
  value = utils.parseNumber(value);
  if (utils.anyIsError(value)) {
    return error.na;
  }

  return numeral(value).format(format);
};

exports.TRIM = function(text) {
  if (typeof text !== 'string') {
    return error.value;
  }
  return text.replace(/ +/g, ' ').trim();
};

exports.UNICHAR = this.CHAR;

exports.UNICODE = this.CODE;

exports.UPPER = function(text) {
  if (typeof text !== 'string') {
    return error.value;
  }
  return text.toUpperCase();
};

exports.VALUE = function(text) {
  if (typeof text !== 'string') {
    return error.value;
  }
  return numeral().unformat(text);
};
<commit_msg>Fixing SEARCH function to return error.value when text is not found<commit_after>var utils = require('./utils');
var error = require('./error');
var numeral = require('numeral');

//TODO
exports.ASC = function() {
 throw new Error('ASC is not implemented');
};

//TODO
exports.BAHTTEXT = function() {
 throw new Error('BAHTTEXT is not implemented');
};

exports.CHAR = function(number) {
  number = utils.parseNumber(number);
  if (number instanceof Error) {
    return number;
  }
  return String.fromCharCode(number);
};

exports.CLEAN = function(text) {
  text = text || '';
  var re = /[\0-\x1F]/g;
  return text.replace(re, "");
};

exports.CODE = function(text) {
  text = text || '';
  return text.charCodeAt(0);
};

exports.CONCATENATE = function() {
  var args = utils.flatten(arguments);

  var trueFound = 0;
  while ((trueFound = args.indexOf(true)) > -1) {
    args[trueFound] = 'TRUE';
  }

  var falseFound = 0;
  while ((falseFound = args.indexOf(false)) > -1) {
    args[falseFound] = 'FALSE';
  }

  return args.join('');
};

//TODO
exports.DBCS = function() {
 throw new Error('DBCS is not implemented');
};

exports.DOLLAR = function(number, decimals) {
  decimals = (decimals === undefined) ? 2 : decimals;

  number = utils.parseNumber(number);
  decimals = utils.parseNumber(decimals);
  if (utils.anyIsError(number, decimals)) {
    return error.value;
  }
  var format = '';
  if (decimals <= 0) {
    number = Math.round(number * Math.pow(10, decimals)) / Math.pow(10, decimals);
    format = '($0,0)';
  } else if (decimals > 0) {
    format = '($0,0.' + new Array(decimals + 1).join('0') + ')';
  }
  return numeral(number).format(format);
};

exports.EXACT = function(text1, text2) {
  return text1 === text2;
};

exports.FIND = function(find_text, within_text, position) {
  position = (position === undefined) ? 0 : position;
  return within_text ? within_text.indexOf(find_text, position - 1) + 1 : null;
};

exports.FIXED = function(number, decimals, no_commas) {
  decimals = (decimals === undefined) ? 2 : decimals;
  no_commas = (no_commas === undefined) ? false : no_commas;

  number = utils.parseNumber(number);
  decimals = utils.parseNumber(decimals);
  if (utils.anyIsError(number, decimals)) {
    return error.value;
  }

  var format = no_commas ? '0' : '0,0';
  if (decimals <= 0) {
    number = Math.round(number * Math.pow(10, decimals)) / Math.pow(10, decimals);
  } else if (decimals > 0) {
    format += '.' + new Array(decimals + 1).join('0');
  }
  return numeral(number).format(format);
};

exports.HTML2TEXT = function (value) {
  var result = '';

  if (value) {
    if (value instanceof Array) {
      value.forEach(function (line) {
        if (result !== '') {
          result += '\n';
        }
        result += (line.replace(/<(?:.|\n)*?>/gm, ''));
      });
    } else {
      result = value.replace(/<(?:.|\n)*?>/gm, '');
    }
  }

  return result;
};

exports.LEFT = function(text, number) {
  number = (number === undefined) ? 1 : number;
  number = utils.parseNumber(number);
  if (number instanceof Error || typeof text !== 'string') {
    return error.value;
  }
  return text ? text.substring(0, number) : null;
};

exports.LEN = function(text) {
  if (arguments.length === 0) {
    return error.error;
  }

  if (typeof text === 'string') {
    return text ? text.length : 0;
  }

  if (text.length) {
    return text.length;
  }

  return error.value;
};

exports.LOWER = function(text) {
  if (typeof text !== 'string') {
    return error.value;
  }
  return text ? text.toLowerCase() : text;
};

exports.MID = function(text, start, number) {
  start = utils.parseNumber(start);
  number = utils.parseNumber(number);
  if (utils.anyIsError(start, number) || typeof text !== 'string') {
    return number;
  }
  return text.substring(start - 1, number);
};

// TODO
exports.NUMBERVALUE = function (text, decimal_separator, group_separator)  {
  decimal_separator = (typeof decimal_separator === 'undefined') ? '.' : decimal_separator;
  group_separator = (typeof group_separator === 'undefined') ? ',' : group_separator;
  return Number(text.replace(decimal_separator, '.').replace(group_separator, ''));
};

// TODO
exports.PRONETIC = function() {
 throw new Error('PRONETIC is not implemented');
};

exports.PROPER = function(text) {
  if (text === undefined || text.length === 0) {
    return error.value;
  }
  if (text === true) {
    text = 'TRUE';
  }
  if (text === false) {
    text = 'FALSE';
  }
  if (isNaN(text) && typeof text === 'number') {
    return error.value;
  }
  if (typeof text === 'number') {
    text = '' + text;
  }

  return text.replace(/\w\S*/g, function(txt) {
    return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
  });
};

exports.REGEXEXTRACT = function (text, regular_expression) {
  var match = text.match(new RegExp(regular_expression));
  return match ? (match[match.length > 1 ? match.length - 1 : 0]) : null;
};

exports.REGEXMATCH = function (text, regular_expression, full) {
  var match = text.match(new RegExp(regular_expression));
  return full ? match : !!match;
};

exports.REGEXREPLACE = function (text, regular_expression, replacement) {
  return text.replace(new RegExp(regular_expression), replacement);
};

exports.REPLACE = function(text, position, length, new_text) {
  position = utils.parseNumber(position);
  length = utils.parseNumber(length);
  if (utils.anyIsError(position, length) ||
    typeof text !== 'string' ||
    typeof new_text !== 'string') {
    return error.value;
  }
  return text.substr(0, position - 1) + new_text + text.substr(position - 1 + length);
};

exports.REPT = function(text, number) {
  number = utils.parseNumber(number);
  if (number instanceof Error) {
    return number;
  }
  return new Array(number + 1).join(text);
};

exports.RIGHT = function(text, number) {
  number = (number === undefined) ? 1 : number;
  number = utils.parseNumber(number);
  if (number instanceof Error) {
    return number;
  }
  return text ? text.substring(text.length - number) : null;
};

exports.SEARCH = function(find_text, within_text, position) {
  var foundAt;
  if (typeof find_text !== 'string' || typeof within_text !== 'string') {
    return error.value;
  }
  position = (position === undefined) ? 0 : position;
  foundAt = within_text.toLowerCase().indexOf(find_text.toLowerCase(), position - 1);
  return (foundAt === -1)?error.value:foundAt;
};

exports.SPLIT = function (text, separator) {
  return text.split(separator);
};

exports.SUBSTITUTE = function(text, old_text, new_text, occurrence) {
  if (!text || !old_text || !new_text) {
    return text;
  } else if (occurrence === undefined) {
    return text.replace(new RegExp(old_text, 'g'), new_text);
  } else {
    var index = 0;
    var i = 0;
    while (text.indexOf(old_text, index) > 0) {
      index = text.indexOf(old_text, index + 1);
      i++;
      if (i === occurrence) {
        return text.substring(0, index) + new_text + text.substring(index + old_text.length);
      }
    }
  }
};

exports.T = function(value) {
  return (typeof value === "string") ? value : '';
};

// TODO incomplete implementation
exports.TEXT = function(value, format) {
  value = utils.parseNumber(value);
  if (utils.anyIsError(value)) {
    return error.na;
  }

  return numeral(value).format(format);
};

exports.TRIM = function(text) {
  if (typeof text !== 'string') {
    return error.value;
  }
  return text.replace(/ +/g, ' ').trim();
};

exports.UNICHAR = this.CHAR;

exports.UNICODE = this.CODE;

exports.UPPER = function(text) {
  if (typeof text !== 'string') {
    return error.value;
  }
  return text.toUpperCase();
};

exports.VALUE = function(text) {
  if (typeof text !== 'string') {
    return error.value;
  }
  return numeral().unformat(text);
};
<|endoftext|>


<commit_before>// September 2012, Franziska Hinkelmann, Mike Stillman, and Lars Kastner
//
// This is server-side JavaScript, intended to be run with Node.js.
// This file defines a Node.js server for serving 'tryM2'.
//   run
//      node m2server.js
// in a terminal in this directory.
// Then in a browser, use:
//      http://localhost:8000/
// Required Node.js libraries: cookies.  Install via:
//   npm install cookies, or sudo npm install -g cookies
// Required on path: M2
// We are using our own open script to make Graphs.m2 work (generate jpegs for users), please include the current directory in your path:
// export PATH=.:$PATH

// intended to run on (s)chrooted environment, where every user starts M2 in a separate schroot.
//
// A message on / : possibly creates a cookie, and serves back index.html
//   and related js/css/png files
// A POST message on /chat: input should be Macaulay2 commands to perform.
// A message on /chat: start an event emitter, which will return the output of
// the M2 process.

var port = 8002;
var sandboxDir = "/";

var http = require('http')
    , connect = require('connect')
    , Cookies = require('cookies');

var SCHROOT = false; // start with --schroot on server

// The HTML file for the chat client. Used below.
//var clientui = require('fs').readFileSync("index.html");
var totalUsers = 0;

// An array of Client objects.  Each has an M2 process, and a response object
// It is possible that this.m2 is not defined, and/or that this.eventStream is not
// defined.
var clients = {};

function runShellCommand(cmd, callbackFcn) {
    // runs a command, and calls the callbackFnc with the output from stdout

    require('child_process').exec( cmd, function(error, stdout, stderr) {
        console.log("runShellCommand result:" + stdout);
        callbackFcn(stdout);
    });
}

function Client(m2process, resp) {
    this.m2 = m2process;
    this.eventStream = resp;
    this.clientID = null;
}

startUser = function(cookies, callbackFcn) {
    totalUsers = totalUsers + 1;
    var clientID = Math.random()*1000000;
    clientID = Math.floor(clientID);
    clientID = "user" + clientID.toString(10);
    cookies.set( "tryM2", clientID, { httpOnly: false } );
    clients[clientID] = new Client();
    clients[clientID].clientID = clientID;
    if (SCHROOT) {
	console.log("Spawning new schroot process named " + clientID + ".");
	require('child_process').exec('schroot -c clone -n '+ clientID + ' -b', function() {
            var filename = "/var/lib/schroot/mount/" + clientID + "/home/franzi/sName.txt";
            // create a file inside schroot directory to allow schroot know its own name
            require('fs').writeFile(filename, clientID, function(err) {
                if(err) {
                    console.log("failing to write the file " + filename);
                    console.log(err);
                } else {
                    console.log("wrote schroot's name into " + filename);
    		    callbackFcn(clientID);
                }
	    });
	});
    } else {
	callbackFcn(clientID);
    }
    return clientID;
}

m2Start = function(clientID) {
    var spawn = require('child_process').spawn;
    if (SCHROOT) {
        var m2 = spawn( 'schroot', ['-c', clientID, '-u', 'franzi', '-d', '/home/franzi/', '-r', '/M2/bin/M2']);
        console.log("PID of schroot: " + m2.pid);
        runShellCommand('pgrep -P ' + m2.pid, function(m2Pid) {
            console.log("PID of M2 inside schroot: " + m2Pid);
        });
    } else {
        m2 = spawn('M2');
        console.log("Spawning new M2 process...");
    }
    m2.stdout.setEncoding("utf8");
    m2.stderr.setEncoding("utf8");
    return m2;
}

m2ConnectStream = function(clientID) {
     var client = clients[clientID];
     var ondata = function(data) {
         console.log('ondata: ' + data);
         message = 'data: ' + data.replace(/\n/g, '\ndata: ') + "\r\n\r\n";
         if (!client.eventStream) { // fatal error, should not happen
             console.log("Error: No event stream in Start M2");
             throw "Error: No client.eventStream in Start M2";
         }
         client.eventStream.write(message);
     };
     console.log("Bind stdout to client's m2");
     client.m2.stdout.removeAllListeners('data');
     client.m2.stderr.removeAllListeners('data');
     client.m2.stdout.on('data', ondata);
     client.m2.stderr.on('data', ondata);
};

m2AssureRunning = function(clientID) {
    // clientID: name of the desired client
    // Caveat: It is possible to kill m2 after being being assured that it is
    //   there, so there is a possibility for a problem here.  We need to consider that? TODO

    var client = clients[clientID];
    if (!client.m2) {
        client.m2 = m2Start(clientID);
	m2ConnectStream(clientID);
    }
};

assureClient = function(request, response, callbackFcn) {
    var cookies = new Cookies(request, response);
    var clientID = cookies.get("tryM2");
    //console.log("Client has cookie value: " + clientID);

    // Start new user for users coming with invalid, i.e., old, cookie
    if (!clients[clientID]) {
        console.log("startUser");
        clientID = startUser(cookies, callbackFcn);
    } else {
	callbackFcn(clientID);
    }
};

var stats = function(request, response, next) {
    // to do: authorization
     response.writeHead(200, {"Content-Type": "text/html"});
     var currentUsers = 0;
     for( var c in clients) {
         if(clients.hasOwnProperty(c))
            currentUsers = currentUsers + 1;
     }
     response.write('<link rel="stylesheet" href="m2.css" type="text/css" media="screen">' );
     response.write('
Macaulay2 User Statistics
');
     response.write("There are currently " + currentUsers + " users using M2.
" );
     response.write("In total, there were " + totalUsers + " users since the server started.
");
     response.write("Enjoy M2!");
     response.end();
}

// Send a comment to the clients every 20 seconds so they don't
// close the connection and then reconnect
setInterval(function() {
    for (var prop in clients) {
        if (clients.hasOwnProperty(prop)
            && clients[prop]
            && clients[prop].eventStream) {
            clients[prop].eventStream.write(":ping\n");
        }
    }
}, 20000);

// Client starts eventStream to obtain M2 output and start M2
startSource = function( request, response) {
    assureClient(request, response, function (clientID) {
	response.writeHead(200, {'Content-Type': "text/event-stream" });
	if (!clients[clientID].eventStream) {
            clients[clientID].eventStream = response;
	    m2AssureRunning(clientID);
	    m2ConnectStream(clientID);
	}
	// If the client closes the connection, remove client from the list of active clients
	request.connection.on("end", function() {
            console.log("close connection: clients[" + clientID + "]");
            clients[clientID].eventStream = null;
            response.end();
	});
    });
};

chatAction = function( request, response) {
    assureClient(request, response, function (clientID) {
	if (!checkForEventStream(clientID, response)) {return false};
	request.setEncoding("utf8");
	var body = "";
	// When we get a chunk of data, add it to the body
	request.on("data", function(chunk) { body += chunk; });

	// Send input to M2 when we have received the complete body
	request.on("end", function() {
	    m2ProcessInput(clientID, body, response);
	});
    });
};

m2ProcessInput = function( clientID, body, response ) {
    // this starts m2 if needed, and when it is done, calls callback
    console.log("entered m2ProcessInput");
    m2AssureRunning(clientID);

    try {
	console.log("M2 input: " + body);
	clients[clientID].m2.stdin.write(body);
    }
    catch (err) {
	console.log(err);
	console.log("Internal error: nothing to write to?!");
	throw ("Internal error: nothing to write to?!");
	return;
    }
    response.writeHead(200);
    response.end();
};

restartAction = function(request, response) {
    assureClient(request, response, function(clientID) {
	if (!checkForEventStream(clientID, response)) {return false};
	var client = clients[clientID];
	console.log("received: /restart from " + clientID);
	if (client.m2) {
            client.m2.kill();
            console.log("In restartAction, killed child process with PID " + client.m2.pid);
            client.m2 = null;
	}
	client.m2 = m2Start(clientID);
	m2ConnectStream(clientID);
	response.writeHead(200);
	response.end();
    });
};

interruptAction = function(request, response)  {
    assureClient(request, response, function (clientID) {
	    if (!checkForEventStream(clientID, response)) {return false};
    	console.log("received: /interrupt from " + clientID);
    	if (clients[clientID] && clients[clientID].m2) {
                clients[clientID].m2.kill('SIGINT');
    	}
    	response.writeHead(200);
    	response.end();
    });
};

// returning clientID for a given M2 pid
// This currently does not work when working inside a schroot, because pid is not the schroot's pid
findClientID = function(pid){
    //var pid1 = parseInt(pid,10);
    console.log("Searching for clientID whose M2 has PID " + pid);
    for (var prop in clients) {
        if (clients.hasOwnProperty(prop) && clients[prop] && clients[prop].m2) {
            if (pid == clients[prop].m2.pid) {
                console.log("We found the client! It is " + prop);
                if (clients[prop].eventStream) {
                    console.log("findClientID picked user with clientID " + prop);
                    return prop;
                } else {
                    throw ("Client " + clientID + " does not have an eventstream.");
                }
            }
        }
    }
    throw ("Did not find a client for PID " + pid);
}

// return PID extracted from pathname for image displaying
parseUrlForPid = function(url) {
    console.log(url);
    if (SCHROOT) {
        var pid = url.match(/^\/(user\d+)\//);
    } else {
        pid = url.match(/\/M2-(\d+)-/);
    }
    //console.log( pid );
    if (!pid) {
        console.log("error, didn't get PID in image url");
        throw ("Did not get PID in image url");
    }
    console.log("PID = " + pid[1]);
    return pid[1];
    //return parseInt(pid[1],10);
}

// return path to image
parseUrlForPath = function(url) {
    var imagePath = url.match(/^\/(user)?\d+\/(.*)/);
    console.log(imagePath);

    if (!imagePath) {
        throw("Did not get imagePath in image url");
    }
    console.log("imagePath = " + imagePath[2]);
    return imagePath[2];
}

// we get a /image from our open script
// imageAction finds the matching client by parsing the url, then sends the address of the image to the client's eventStream
imageAction = function(request, response, next) {
    var url = require('url').parse(request.url).pathname;
    response.writeHead(200);
    response.end();

    try {
        var pid = parseUrlForPid(url);
        var path = parseUrlForPath(url); // a string
        if (SCHROOT) {
            var clientID = pid;
        } else {
            clientID = findClientID(pid);
        }

        console.log("ClientID = " + clientID);

        client = clients[clientID];
          if (!client) {
              console.log("oops, no client");
              return;
          }

          if (SCHROOT) {
              path = "/var/lib/schroot/mount/" + clientID + path
          }
          console.log('we got a request for an image: ' + path + ", for clientID " + clientID);
          // parse request for PID and path to image

          message = 'event: image\r\ndata: ' + path + "\r\n\r\n";
          if (!client.eventStream) { // fatal error, should not happen
              console.log("Error: No event stream in Start M2");
          }
          else {
              console.log("Sent image message: " + message);
              client.eventStream.write(message);
          }
    }
    catch (err) {
        console.log("Received invalid /image request: " + err);
    }

};

function checkForEventStream(clientID, response) {
    if (!clients[clientID].eventStream ) {
      console.log("Send notEventSourceError back to user.");
      response.writeHead(200, {'notEventSourceError': 'No socket for client...' });
      response.end();
      return false;
   }
   return true;
}

function unhandled(request, response, next) {
    var url = require('url').parse(request.url).pathname;
    if (url == '/chat' || url == 'interrupt' || url == '/restart') {
        next();
        return;
    }
    console.log("User requested something we don't serve");
    console.log(request.url);
}

// when run in production, work with schroots, see startM2Process()
if( process.argv[2] && process.argv[2]=='--schroot') {
    console.log('Running with schroots.');
    SCHROOT=true;
}

var app = connect()
    .use(connect.logger('dev'))
    .use(connect.favicon())
    .use(connect.static('public'))
    .use('/var', connect.static('/var')) // M2 creates temporary files (like created by Graphs.m2) here on MacOS
    .use('/tmp', connect.static('/tmp')) // and here on Ubuntu
    .use('/admin', stats)
    .use('/image', imageAction)
    .use('/startSourceEvent', startSource)
    .use('/chat', chatAction)
    .use('/interrupt', interruptAction)
    .use('/restart', restartAction)
    .use(unhandled)
    ;
    //.use(connect.errorHandler());
console.log("Listening on port " + port + "...");
http.createServer(app).listen(port);

// Local Variables:                                                                                // indent-tabs-mode: nil                                                                              // End:
<commit_msg>interrupt works in schroots<commit_after>// September 2012, Franziska Hinkelmann, Mike Stillman, and Lars Kastner
//
// This is server-side JavaScript, intended to be run with Node.js.
// This file defines a Node.js server for serving 'tryM2'.
//   run
//      node m2server.js
// in a terminal in this directory.
// Then in a browser, use:
//      http://localhost:8000/
// Required Node.js libraries: cookies.  Install via:
//   npm install cookies, or sudo npm install -g cookies
// Required on path: M2
// We are using our own open script to make Graphs.m2 work (generate jpegs for users), please include the current directory in your path:
// export PATH=.:$PATH

// intended to run on (s)chrooted environment, where every user starts M2 in a separate schroot.
//
// A message on / : possibly creates a cookie, and serves back index.html
//   and related js/css/png files
// A POST message on /chat: input should be Macaulay2 commands to perform.
// A message on /chat: start an event emitter, which will return the output of
// the M2 process.

var port = 8002;
var sandboxDir = "/";

var http = require('http')
    , connect = require('connect')
    , Cookies = require('cookies');

var SCHROOT = false; // start with --schroot on server

// The HTML file for the chat client. Used below.
//var clientui = require('fs').readFileSync("index.html");
var totalUsers = 0;

// An array of Client objects.  Each has an M2 process, and a response object
// It is possible that this.m2 is not defined, and/or that this.eventStream is not
// defined.
var clients = {};

function runShellCommand(cmd, callbackFcn) {
    // runs a command, and calls the callbackFnc with the output from stdout

    require('child_process').exec( cmd, function(error, stdout, stderr) {
        //console.log("runShellCommand result:" + stdout);
        callbackFcn(stdout);
    });
}

function Client(m2process, resp) {
    this.m2 = m2process;
    this.eventStream = resp;
    this.clientID = null;
}

startUser = function(cookies, callbackFcn) {
    totalUsers = totalUsers + 1;
    var clientID = Math.random()*1000000;
    clientID = Math.floor(clientID);
    clientID = "user" + clientID.toString(10);
    cookies.set( "tryM2", clientID, { httpOnly: false } );
    clients[clientID] = new Client();
    clients[clientID].clientID = clientID;
    if (SCHROOT) {
	console.log("Spawning new schroot process named " + clientID + ".");
	require('child_process').exec('schroot -c clone -n '+ clientID + ' -b', function() {
            var filename = "/var/lib/schroot/mount/" + clientID + "/home/franzi/sName.txt";
            // create a file inside schroot directory to allow schroot know its own name
            require('fs').writeFile(filename, clientID, function(err) {
                if(err) {
                    console.log("failing to write the file " + filename);
                    console.log(err);
                } else {
                    console.log("wrote schroot's name into " + filename);
    		    callbackFcn(clientID);
                }
	    });
	});
    } else {
	callbackFcn(clientID);
    }
    return clientID;
}

m2Start = function(clientID) {
    var spawn = require('child_process').spawn;
    if (SCHROOT) {
	    var m2 = require('child_process').spawn( 'schroot', ['-c', clientID, '-u', 'franzi', '-d', '/home/franzi/', '-r', '/M2/bin/M2']);
    } else {
        m2 = spawn('M2');
        console.log("Spawning new M2 process...");
    }
    m2.stdout.setEncoding("utf8");
    m2.stderr.setEncoding("utf8");
    return m2;
}

m2ConnectStream = function(clientID) {
     var client = clients[clientID];
     var ondata = function(data) {
         console.log('ondata: ' + data);
         message = 'data: ' + data.replace(/\n/g, '\ndata: ') + "\r\n\r\n";
         if (!client.eventStream) { // fatal error, should not happen
             console.log("Error: No event stream in Start M2");
             throw "Error: No client.eventStream in Start M2";
         }
         client.eventStream.write(message);
     };
     console.log("Bind stdout to client's m2");
     client.m2.stdout.removeAllListeners('data');
     client.m2.stderr.removeAllListeners('data');
     client.m2.stdout.on('data', ondata);
     client.m2.stderr.on('data', ondata);
};

m2AssureRunning = function(clientID) {
    // clientID: name of the desired client
    // Caveat: It is possible to kill m2 after being being assured that it is
    //   there, so there is a possibility for a problem here.  We need to consider that? TODO

    var client = clients[clientID];
    if (!client.m2) {
        client.m2 = m2Start(clientID);
	m2ConnectStream(clientID);
    }
};

assureClient = function(request, response, callbackFcn) {
    var cookies = new Cookies(request, response);
    var clientID = cookies.get("tryM2");
    //console.log("Client has cookie value: " + clientID);

    // Start new user for users coming with invalid, i.e., old, cookie
    if (!clients[clientID]) {
        console.log("startUser");
        clientID = startUser(cookies, callbackFcn);
    } else {
	callbackFcn(clientID);
    }
};

var stats = function(request, response, next) {
    // to do: authorization
     response.writeHead(200, {"Content-Type": "text/html"});
     var currentUsers = 0;
     for( var c in clients) {
         if(clients.hasOwnProperty(c))
            currentUsers = currentUsers + 1;
     }
     response.write('<link rel="stylesheet" href="m2.css" type="text/css" media="screen">' );
     response.write('
Macaulay2 User Statistics
');
     response.write("There are currently " + currentUsers + " users using M2.
" );
     response.write("In total, there were " + totalUsers + " users since the server started.
");
     response.write("Enjoy M2!");
     response.end();
}

// Send a comment to the clients every 20 seconds so they don't
// close the connection and then reconnect
setInterval(function() {
    for (var prop in clients) {
        if (clients.hasOwnProperty(prop)
            && clients[prop]
            && clients[prop].eventStream) {
            clients[prop].eventStream.write(":ping\n");
        }
    }
}, 20000);

// Client starts eventStream to obtain M2 output and start M2
startSource = function( request, response) {
    assureClient(request, response, function (clientID) {
	response.writeHead(200, {'Content-Type': "text/event-stream" });
	if (!clients[clientID].eventStream) {
            clients[clientID].eventStream = response;
	    m2AssureRunning(clientID);
	    m2ConnectStream(clientID);
	}
	// If the client closes the connection, remove client from the list of active clients
	request.connection.on("end", function() {
            console.log("close connection: clients[" + clientID + "]");
            clients[clientID].eventStream = null;
            response.end();
	});
    });
};

chatAction = function( request, response) {
    assureClient(request, response, function (clientID) {
	if (!checkForEventStream(clientID, response)) {return false};
	request.setEncoding("utf8");
	var body = "";
	// When we get a chunk of data, add it to the body
	request.on("data", function(chunk) { body += chunk; });

	// Send input to M2 when we have received the complete body
	request.on("end", function() {
	    m2ProcessInput(clientID, body, response);
	});
    });
};

m2ProcessInput = function( clientID, body, response ) {
    // this starts m2 if needed, and when it is done, calls callback
    console.log("entered m2ProcessInput");
    m2AssureRunning(clientID);

    try {
	console.log("M2 input: " + body);
	clients[clientID].m2.stdin.write(body);
    }
    catch (err) {
	console.log(err);
	console.log("Internal error: nothing to write to?!");
	throw ("Internal error: nothing to write to?!");
	return;
    }
    response.writeHead(200);
    response.end();
};

restartAction = function(request, response) {
    assureClient(request, response, function(clientID) {
	if (!checkForEventStream(clientID, response)) {return false};
	var client = clients[clientID];
	console.log("received: /restart from " + clientID);
	if (client.m2) {
            client.m2.kill();
            console.log("In restartAction, killed child process with PID " + client.m2.pid);
            client.m2 = null;
	}
	client.m2 = m2Start(clientID);
	m2ConnectStream(clientID);
	response.writeHead(200);
	response.end();
    });
};

interruptAction = function(request, response)  {
    assureClient(request, response, function (clientID) {
	    if (!checkForEventStream(clientID, response)) {return false};
    	console.log("received: /interrupt from " + clientID);
    	if (clients[clientID] && clients[clientID].m2) {
            var m2 = clients[clientID].m2;
	    runShellCommand('pgrep -P ' + m2.pid, function(m2Pid) {
		    	console.log("PID of M2 inside schroot: " + m2Pid);
			var cmd = 'kill -s INT ' + m2Pid;
			console.log( "cmd: " + cmd );
			runShellCommand(cmd, function(res) {
				console.log("SIGINT has been sent to M2 " + m2Pid + ".");
			});
	    });
    	}
    	response.writeHead(200);
    	response.end();
    });
};

// returning clientID for a given M2 pid
// This currently does not work when working inside a schroot, because pid is not the schroot's pid
findClientID = function(pid){
    //var pid1 = parseInt(pid,10);
    console.log("Searching for clientID whose M2 has PID " + pid);
    for (var prop in clients) {
        if (clients.hasOwnProperty(prop) && clients[prop] && clients[prop].m2) {
            if (pid == clients[prop].m2.pid) {
                console.log("We found the client! It is " + prop);
                if (clients[prop].eventStream) {
                    console.log("findClientID picked user with clientID " + prop);
                    return prop;
                } else {
                    throw ("Client " + clientID + " does not have an eventstream.");
                }
            }
        }
    }
    throw ("Did not find a client for PID " + pid);
}

// return PID extracted from pathname for image displaying
parseUrlForPid = function(url) {
    console.log(url);
    if (SCHROOT) {
        var pid = url.match(/^\/(user\d+)\//);
    } else {
        pid = url.match(/\/M2-(\d+)-/);
    }
    //console.log( pid );
    if (!pid) {
        console.log("error, didn't get PID in image url");
        throw ("Did not get PID in image url");
    }
    console.log("PID = " + pid[1]);
    return pid[1];
    //return parseInt(pid[1],10);
}

// return path to image
parseUrlForPath = function(url) {
    var imagePath = url.match(/^\/(user)?\d+\/(.*)/);
    console.log(imagePath);

    if (!imagePath) {
        throw("Did not get imagePath in image url");
    }
    console.log("imagePath = " + imagePath[2]);
    return imagePath[2];
}

// we get a /image from our open script
// imageAction finds the matching client by parsing the url, then sends the address of the image to the client's eventStream
imageAction = function(request, response, next) {
    var url = require('url').parse(request.url).pathname;
    response.writeHead(200);
    response.end();

    try {
        var pid = parseUrlForPid(url);
        var path = parseUrlForPath(url); // a string
        if (SCHROOT) {
            var clientID = pid;
        } else {
            clientID = findClientID(pid);
        }

        console.log("ClientID = " + clientID);

        client = clients[clientID];
          if (!client) {
              console.log("oops, no client");
              return;
          }

          if (SCHROOT) {
              path = "/var/lib/schroot/mount/" + clientID + path
          }
          console.log('we got a request for an image: ' + path + ", for clientID " + clientID);
          // parse request for PID and path to image

          message = 'event: image\r\ndata: ' + path + "\r\n\r\n";
          if (!client.eventStream) { // fatal error, should not happen
              console.log("Error: No event stream in Start M2");
          }
          else {
              console.log("Sent image message: " + message);
              client.eventStream.write(message);
          }
    }
    catch (err) {
        console.log("Received invalid /image request: " + err);
    }

};

function checkForEventStream(clientID, response) {
    if (!clients[clientID].eventStream ) {
      console.log("Send notEventSourceError back to user.");
      response.writeHead(200, {'notEventSourceError': 'No socket for client...' });
      response.end();
      return false;
   }
   return true;
}

function unhandled(request, response, next) {
    var url = require('url').parse(request.url).pathname;
    if (url == '/chat' || url == 'interrupt' || url == '/restart') {
        next();
        return;
    }
    console.log("User requested something we don't serve");
    console.log(request.url);
}

// when run in production, work with schroots, see startM2Process()
if( process.argv[2] && process.argv[2]=='--schroot') {
    console.log('Running with schroots.');
    SCHROOT=true;
}

var app = connect()
    .use(connect.logger('dev'))
    .use(connect.favicon())
    .use(connect.static('public'))
    .use('/var', connect.static('/var')) // M2 creates temporary files (like created by Graphs.m2) here on MacOS
    .use('/tmp', connect.static('/tmp')) // and here on Ubuntu
    .use('/admin', stats)
    .use('/image', imageAction)
    .use('/startSourceEvent', startSource)
    .use('/chat', chatAction)
    .use('/interrupt', interruptAction)
    .use('/restart', restartAction)
    .use(unhandled)
    ;
    //.use(connect.errorHandler());
console.log("Listening on port " + port + "...");
http.createServer(app).listen(port);

// Local Variables:                                                                                // indent-tabs-mode: nil                                                                              // End:
<|endoftext|>


<commit_before>function Chest(game, level, x, y){
    this.game = game;
    this.level = level;
    this.x = x;
    this.y = y;
    this.sprite = null;
    this.opened = false;
    this.isEmpty = false;
    //'art',  'levels', , 'progress', 'scoreboard'
    this.elements = ['actions', 'avatar', 'balance', 'feedback', 'progress', 'luck'];
    this.points = [ '100', '150', '200', '250', '300'];
    this.item = null;
    this.create();

}

Chest.prototype = {

    create: function(){
        this.sprite = this.game.add.sprite(this.x, this.y, 'chests');
        this.sprite.differentiate = false;
        this.game.physics.arcade.enable(this.sprite);
        this.sprite.body.gravity.y = 500;
        var rand = Math.floor((Math.random() * 2) + 1);
        //differentiate chests: echest = element chest, chest = score chest
        this.sprite.animations.add('chest', [0]);
        this.sprite.animations.add('chest_open', [1]);
        this.sprite.animations.add('echest', [2]);
        this.sprite.animations.add('echest_open', [3]);
        if(rand === 1){
            this.item = this.elements[Math.floor(Math.random() * this.elements.length)];
            if(this.sprite.differentiate){
                this.sprite.animations.play('echest');
            } else {
                this.sprite.animations.play('chest');
            }
        } else if(rand === 2){
            this.item = this.points[Math.floor(Math.random() * this.points.length)];
            this.sprite.animations.play('chest');
        }
        console.log(this.item);
        this.sprite.body.immovable = true;
        this.sprite.locked = false;

    },

    update: function(player){
        this.game.physics.arcade.collide(this.sprite, this.level.wall);
        if(this.sprite.opened && !this.sprite.locked){
            this.sprite.body.gravity.y = 0;
            if(this.item.slice(2, 3) === '0' || this.item.slice(0,1) === '0'){
                this.setScore();
                this.sprite.animations.play('chest_open');
            } else {
                this.giveItem(player);
                if(this.sprite.differentiate){
                    this.sprite.animations.play('echest_open');
                } else {
                    this.sprite.animations.play('chest_open');
                }
            }
            this.isEmpty = true;
        }
        /*if(this.sprite.locked){
            if(this.item.slice(2, 3) === '0'){
                this.sprite.animations.play('chest_locked');
            } else {
                if(this.sprite.differentiate){
                    this.sprite.animations.play('echest_locked');
                } else {
                    this.sprite.animation.play('chest_locked');
                }
            }
        } */
        if(!this.sprite.opened && !this.sprite.locked){
            if(this.item.slice(2, 3) === '0' || this.item.slice(0, 1) === '0'){
                this.sprite.animations.play('chest');
            } else {
                if(this.sprite.differentiate){
                    this.sprite.animations.play('echest');
                } else {
                    this.sprite.animations.play('chest');
                }
            }
        }
    },

    setScore: function(){
        SCORE = Number(SCORE) + Number(this.item);
        this.level.scoresprite.setText("Score: " + SCORE);
    },

    giveItem: function(player){
        var element = new Element(player.inventory.length * 35 + 35, 100, this.item, this.game, this.level);
        player.elements.push(element);
        player.inventory.add(element.sprite);
    }

};<commit_msg>commit for commit<commit_after>function Chest(game, level, x, y){
    this.game = game;
    this.level = level;
    this.x = x;
    this.y = y;
    this.sprite = null;
    this.opened = false;
    this.isEmpty = false;
    //'art',  'levels', , 'progress', 'scoreboard'
    this.elements = ['actions', 'avatar', 'balance', 'feedback', 'progress', 'luck', 'art'];
    this.points = [ '100', '150', '200', '250', '300'];
    this.item = null;
    this.create();

}

Chest.prototype = {

    create: function(){
        this.sprite = this.game.add.sprite(this.x, this.y, 'chests');
        this.sprite.differentiate = false;
        this.game.physics.arcade.enable(this.sprite);
        this.sprite.body.gravity.y = 500;
        var rand = Math.floor((Math.random() * 2) + 1);
        //differentiate chests: echest = element chest, chest = score chest
        this.sprite.animations.add('chest', [0]);
        this.sprite.animations.add('chest_open', [1]);
        this.sprite.animations.add('echest', [2]);
        this.sprite.animations.add('echest_open', [3]);
        if(rand === 1){
            this.item = this.elements[Math.floor(Math.random() * this.elements.length)];
            if(this.sprite.differentiate){
                this.sprite.animations.play('echest');
            } else {
                this.sprite.animations.play('chest');
            }
        } else if(rand === 2){
            this.item = this.points[Math.floor(Math.random() * this.points.length)];
            this.sprite.animations.play('chest');
        }
        console.log(this.item);
        this.sprite.body.immovable = true;
        this.sprite.locked = false;

    },

    update: function(player){
        this.game.physics.arcade.collide(this.sprite, this.level.wall);
        if(this.sprite.opened && !this.sprite.locked){
            this.sprite.body.gravity.y = 0;
            if(this.item.slice(2, 3) === '0' || this.item.slice(0,1) === '0'){
                this.setScore();
                this.sprite.animations.play('chest_open');
            } else {
                this.giveItem(player);
                if(this.sprite.differentiate){
                    this.sprite.animations.play('echest_open');
                } else {
                    this.sprite.animations.play('chest_open');
                }
            }
            this.isEmpty = true;
        }
        /*if(this.sprite.locked){
            if(this.item.slice(2, 3) === '0'){
                this.sprite.animations.play('chest_locked');
            } else {
                if(this.sprite.differentiate){
                    this.sprite.animations.play('echest_locked');
                } else {
                    this.sprite.animation.play('chest_locked');
                }
            }
        } */
        if(!this.sprite.opened && !this.sprite.locked){
            if(this.item.slice(2, 3) === '0' || this.item.slice(0, 1) === '0'){
                this.sprite.animations.play('chest');
            } else {
                if(this.sprite.differentiate){
                    this.sprite.animations.play('echest');
                } else {
                    this.sprite.animations.play('chest');
                }
            }
        }
    },

    setScore: function(){
        SCORE = Number(SCORE) + Number(this.item);
        this.level.scoresprite.setText("Score: " + SCORE);
    },

    giveItem: function(player){
        var element = new Element(player.inventory.length * 35 + 35, 100, this.item, this.game, this.level);
        player.elements.push(element);
        player.inventory.add(element.sprite);
    }

};<|endoftext|>


<commit_before>//= require jquery-ui-1.9.2/jquery.ui.widget
//= require jquery-ui-1.9.2/jquery.ui.core
//= require jquery-ui-1.9.2/jquery.ui.menu
//= require jquery-ui-1.9.2/jquery.ui.position
//= require jquery-ui-1.9.2/jquery.ui.autocomplete
//
//= require blacklight/blacklight
//
//= require bootstrap/dropdown
//= require bootstrap/button
//= require bootstrap/collapse
//= require bootstrap/tooltip
//= require bootstrap/popover
//
//= require handlebars
//= require jquery.tokeninput
//= require worthwhile/worthwhile
<commit_msg>Add bootstrap-tab javascript<commit_after>//= require jquery-ui-1.9.2/jquery.ui.widget
//= require jquery-ui-1.9.2/jquery.ui.core
//= require jquery-ui-1.9.2/jquery.ui.menu
//= require jquery-ui-1.9.2/jquery.ui.position
//= require jquery-ui-1.9.2/jquery.ui.autocomplete
//
//= require blacklight/blacklight
//
//= require bootstrap/dropdown
//= require bootstrap/button
//= require bootstrap/collapse
//= require bootstrap/tooltip
//= require bootstrap/popover
//= require bootstrap/tab
//
//= require handlebars
//= require jquery.tokeninput
//= require worthwhile/worthwhile
<|endoftext|>


<commit_before>var gulp = require('gulp');
var usemin = require('gulp-usemin');
var rev = require('gulp-rev');
var minifyHtml = require('gulp-minify-html');
var requireJsOptimize = require('gulp-requirejs-optimize');
var install = require('gulp-install');

var paths = {
	scripts: ['app/**/*.js'],
	dist: 'dist2/'
};

gulp.task('install', function(cb) {
	gulp.src(['./bower.json','./package.json']).pipe(install({production: true}));
	cb();
});

gulp.task('scripts', function() {
	return gulp.src('app/scripts/main.js')
		.pipe(requireJsOptimize({
			mainConfigFile : 'app/scripts/main-data.js'
		}))
		.pipe(gulp.dest(paths.dist));
});

gulp.task('usemin', function() {
	return gulp.src('./app/*.html')
		.pipe(usemin())
		.pipe(gulp.dest(paths.dist));
});

gulp.task('build',[
	'install',
	'usemin',
	'scripts'
]);
<commit_msg>fixed<commit_after>var gulp = require('gulp');
var usemin = require('gulp-usemin');
var rev = require('gulp-rev');
var minifyHtml = require('gulp-minify-html');
var requireJsOptimize = require('gulp-requirejs-optimize');
var install = require('gulp-install');

var paths = {
	scripts: ['app/**/*.js'],
	dist: 'dist2/'
};

gulp.task('install', function() {
	return gulp.src(['./bower.json','./package.json']).pipe(install({production: true}));
});

gulp.task('scripts', function() {
	return gulp.src('app/scripts/main.js')
		.pipe(requireJsOptimize({
			mainConfigFile : 'app/scripts/main-data.js'
		}))
		.pipe(gulp.dest(paths.dist));
});

gulp.task('usemin', function() {
	return gulp.src('./app/*.html')
		.pipe(usemin())
		.pipe(gulp.dest(paths.dist));
});

gulp.task('build',[
	'install',
	'usemin',
	'scripts'
]);
<|endoftext|>


<commit_before>module.exports = [
  'Close panels like find and replace with {body>core:cancel}',
  'Everything Atom can do is in the Command Palette. See it by using {command-palette:toggle}',
  'You can quickly open files with the Fuzzy Finder. Try it by using {fuzzy-finder:toggle-file-finder}',
  'You can toggle the Tree View with {tree-view:toggle}',
  'You can focus the Tree View with {tree-view:toggle-focus}',
  'You can toggle the Git tab with {github:toggle-git-tab}',
  'You can focus the Git tab with {github:toggle-git-tab-focus}',
  'You can toggle the GitHub tab with {github:toggle-github-tab}',
  'You can focus the GitHub tab with {github:toggle-github-tab-focus}',
  'You can split a pane with {pane:split-right}',
  'You can jump to a method in the editor using {symbols-view:toggle-file-symbols}',
  'You can install packages and themes from the Settings View {settings-view:open}'
]
<commit_msg>Use pane:split-right-and-copy-active-item<commit_after>module.exports = [
  'Close panels like find and replace with {body>core:cancel}',
  'Everything Atom can do is in the Command Palette. See it by using {command-palette:toggle}',
  'You can quickly open files with the Fuzzy Finder. Try it by using {fuzzy-finder:toggle-file-finder}',
  'You can toggle the Tree View with {tree-view:toggle}',
  'You can focus the Tree View with {tree-view:toggle-focus}',
  'You can toggle the Git tab with {github:toggle-git-tab}',
  'You can focus the Git tab with {github:toggle-git-tab-focus}',
  'You can toggle the GitHub tab with {github:toggle-github-tab}',
  'You can focus the GitHub tab with {github:toggle-github-tab-focus}',
  'You can split a pane with {pane:split-right-and-copy-active-item}',
  'You can jump to a method in the editor using {symbols-view:toggle-file-symbols}',
  'You can install packages and themes from the Settings View {settings-view:open}'
]
<|endoftext|>