<commit_before>'use strict';

angular.module('PPnet')
  .factory('ppnetPostHelper', function($q, ppnetGeolocation) {

    var defaultPost = {
      msg: '',
      created: false,
      user: false,
      coords: false,
      tags: [],
      type: 'POST'
    };

    var defaultImage = {
      msg: '',
      created: false,
      user: false,
      coords: false,
      tags: [],
      type: 'IMAGE'
    };
    var defaultLike = {
      created: false,
      user: false,
      coords: false,
      type: 'LIKE',
      posting: false
    };
    var defaultComment = {
      msg: '',
      created: false,
      user: false,
      coords: false,
      tags: [],
      type: 'COMMENT',
      posting: false
    };

    var getTags = function(content) {
      var tempTags = content.match(/(#[a-z\d-]+)/ig);
      if (tempTags !== null) {
        for (var i = 0; i < tempTags.length; i++) {
          tempTags[i] = tempTags[i].split("#").join('');
        }
      }
      return tempTags;
    };

    return {
      loadComment: function(comments, newEntry) {
        var postId = newEntry.doc.posting;
        // Checks if there are already comments for the postId
        if (!(postId in comments)) {
          // Initialize an empty array
          comments[postId] = [];
        }
        comments[postId].push(newEntry);
      },
      loadLike: function(likes, newEntry) {
        var postId = newEntry.doc.posting;
        if (!(postId in likes)) {
          likes[postId] = [];
        }
        likes[postId].push(newEntry);
      },
      createPostObject: function(content, user) {
        var tempPost = defaultPost;
        tempPost.created = new Date().getTime();
        tempPost.coords = ppnetGeolocation.getCurrentCoords();
        tempPost.user = {
          id: user.id,
          name: user.name
        };
        tempPost.msg = content;
        tempPost.tags = getTags(content);
        return tempPost;
      },
      createImageObject: function(content, user) {
        var tempImage = defaultImage;
        tempImage.created = new Date().getTime();
        tempImage.coords = ppnetGeolocation.getCurrentCoords();
        tempImage.user = {
          id: user.id,
          name: user.name
        };
        tempPost.tags = getTags(content);
        tempImage.msg = angular.isUndefined(content) ? '' : content;
        return tempImage;
      },
      createLikeObject: function(user, posting) {
        var tempLike = defaultLike;
        tempLike.created = new Date().getTime();
        tempLike.coords = ppnetGeolocation.getCurrentCoords();
        tempLike.user = {
          id: user.id,
          name: user.name
        };
        tempLike.posting = posting;
        return tempLike;
      },
      createCommentObject: function(content, user, posting) {
        var tempComment = defaultComment;
        tempComment.msg = content;
        tempComment.created = new Date().getTime();
        tempComment.coords = ppnetGeolocation.getCurrentCoords();
        tempComment.user = {
          id: user.id,
          name: user.name
        };
        tempPost.tags = getTags(content);
        tempComment.posting = posting;
        return tempComment;
      },
      deleteLikeLocal: function(likes, postId, userId) {
        var deferred = $q.defer();
        var result = false;
        if (!angular.isUndefined(likes[postId])) {
          for (var i = 0; i < likes[postId].length; i++) {
            if (likes[postId][i].doc.user.id === userId) {
              result = likes[postId][i].doc;
              break;
            }
          }
        }
        if (result) {
          deferred.resolve(result);
        } else {
          deferred.reject('No ID found');
        }
        return deferred.promise;
      },
      deleteLike: function(likes, deleted) {
        for (var key in likes) {
          for (var i = 0; i < likes[key].length; i++) {
            if (likes[key][i].id === deleted.id) {
              likes[key].splice(i, 1);
            }
          }
        }
      },
      deleteComment: function(comments, deleted) {
        for (var key in comments) {
          for (var i = 0; i < comments[key].length; i++) {
            if (comments[key][i].id === deleted.id) {
              comments[key].splice(i, 1);
            }
          }
        }
      },
      deletePost: function(posts, deleted) {
        for (var i = 0; i < posts.length; i++) {
          if (posts[i].id === deleted.id) {
            posts.splice(i, 1);
            break;
          }
        }
      },
      findPostInArray: function(posts, id) {
        var deferred = $q.defer();
        var result = false;

        for (var i = 0; i < posts.length; i++) {
          if (posts[i].id === id) {
            result = i;
            break;
          }
        }

        if (result) {
          deferred.resolve(result);
        } else {
          deferred.reject('No ID found');
        }
        return deferred.promise;
      }
    };
  });<commit_msg>PostHelper Fix<commit_after>'use strict';

angular.module('PPnet')
  .factory('ppnetPostHelper', function($q, ppnetGeolocation) {

    var defaultPost = {
      msg: '',
      created: false,
      user: false,
      coords: false,
      tags: [],
      type: 'POST'
    };

    var defaultImage = {
      msg: '',
      created: false,
      user: false,
      coords: false,
      tags: [],
      type: 'IMAGE'
    };
    var defaultLike = {
      created: false,
      user: false,
      coords: false,
      type: 'LIKE',
      posting: false
    };
    var defaultComment = {
      msg: '',
      created: false,
      user: false,
      coords: false,
      tags: [],
      type: 'COMMENT',
      posting: false
    };

    var getTags = function(content) {
      var tempTags = content.match(/(#[a-z\d-]+)/ig);
      if (tempTags !== null) {
        for (var i = 0; i < tempTags.length; i++) {
          tempTags[i] = tempTags[i].split("#").join('');
        }
      }
      return tempTags;
    };

    return {
      loadComment: function(comments, newEntry) {
        var postId = newEntry.doc.posting;
        // Checks if there are already comments for the postId
        if (!(postId in comments)) {
          // Initialize an empty array
          comments[postId] = [];
        }
        comments[postId].push(newEntry);
      },
      loadLike: function(likes, newEntry) {
        var postId = newEntry.doc.posting;
        if (!(postId in likes)) {
          likes[postId] = [];
        }
        likes[postId].push(newEntry);
      },
      createPostObject: function(content, user) {
        var tempPost = defaultPost;
        tempPost.created = new Date().getTime();
        tempPost.coords = ppnetGeolocation.getCurrentCoords();
        tempPost.user = {
          id: user.id,
          name: user.name
        };
        tempPost.msg = content;
        tempPost.tags = getTags(content);
        return tempPost;
      },
      createImageObject: function(content, user) {
        var tempImage = defaultImage;
        tempImage.created = new Date().getTime();
        tempImage.coords = ppnetGeolocation.getCurrentCoords();
        tempImage.user = {
          id: user.id,
          name: user.name
        };
        tempImage.tags = getTags(content);
        tempImage.msg = angular.isUndefined(content) ? '' : content;
        return tempImage;
      },
      createLikeObject: function(user, posting) {
        var tempLike = defaultLike;
        tempLike.created = new Date().getTime();
        tempLike.coords = ppnetGeolocation.getCurrentCoords();
        tempLike.user = {
          id: user.id,
          name: user.name
        };
        tempLike.posting = posting;
        return tempLike;
      },
      createCommentObject: function(content, user, posting) {
        var tempComment = defaultComment;
        tempComment.msg = content;
        tempComment.created = new Date().getTime();
        tempComment.coords = ppnetGeolocation.getCurrentCoords();
        tempComment.user = {
          id: user.id,
          name: user.name
        };
        tempComment.tags = getTags(content);
        tempComment.posting = posting;
        return tempComment;
      },
      deleteLikeLocal: function(likes, postId, userId) {
        var deferred = $q.defer();
        var result = false;
        if (!angular.isUndefined(likes[postId])) {
          for (var i = 0; i < likes[postId].length; i++) {
            if (likes[postId][i].doc.user.id === userId) {
              result = likes[postId][i].doc;
              break;
            }
          }
        }
        if (result) {
          deferred.resolve(result);
        } else {
          deferred.reject('No ID found');
        }
        return deferred.promise;
      },
      deleteLike: function(likes, deleted) {
        for (var key in likes) {
          for (var i = 0; i < likes[key].length; i++) {
            if (likes[key][i].id === deleted.id) {
              likes[key].splice(i, 1);
            }
          }
        }
      },
      deleteComment: function(comments, deleted) {
        for (var key in comments) {
          for (var i = 0; i < comments[key].length; i++) {
            if (comments[key][i].id === deleted.id) {
              comments[key].splice(i, 1);
            }
          }
        }
      },
      deletePost: function(posts, deleted) {
        for (var i = 0; i < posts.length; i++) {
          if (posts[i].id === deleted.id) {
            posts.splice(i, 1);
            break;
          }
        }
      },
      findPostInArray: function(posts, id) {
        var deferred = $q.defer();
        var result = false;

        for (var i = 0; i < posts.length; i++) {
          if (posts[i].id === id) {
            result = i;
            break;
          }
        }

        if (result) {
          deferred.resolve(result);
        } else {
          deferred.reject('No ID found');
        }
        return deferred.promise;
      }
    };
  });<|endoftext|>


<commit_before>// Dependencies
var CaptchaPng = require("captchapng");

// Sessions
var sessions = {};

// Captcha configuration
var serverConfig = {
    width: 100,
    height: 30
};

// Get configuration
M.emit("captcha.getConfig", function (c) {
    serverConfig = c;
});

// Verify captcha
M.on("captcha.verify", function (link, answer, callback) {
    var sid = link.session && link.session._sid;
    callback(answer === sessions[sid]);
});

/**
 * captcha
 * Serves the captcha image
 *
 * @name captcha
 * @function
 * @param {Object} link Mono link object
 * @return
 */
exports.captcha = function (link) {

    var res = link.res;

    // Generate number and store it in sessions cache
    var number = parseInt(Math.random() * 9000 + 1000);
    if (!link.session || !link.session._sid) {
        sessions[link.session._sid] = number;
    }

    var cap = new CaptchaPng(serverConfig.width, serverConfig.height, number);
    cap.color(0, 100, 0, 0);
    cap.color(80, 80, 80, 255);

    var img = cap.getBase64();
    var imgBase64 = new Buffer(img, "base64");
    res.writeHead(200, {
        "Content-Type": "image/png"
    });

    res.end(imgBase64);
};
<commit_msg>Set the number in sessions and correclty compare the values<commit_after>// Dependencies
var CaptchaPng = require("captchapng");

// Sessions
var sessions = {};

// Captcha configuration
var serverConfig = {
    width: 100,
    height: 30
};

// Get configuration
M.emit("captcha.getConfig", function (c) {
    serverConfig = c;
});

// Verify captcha
M.on("captcha.verify", function (link, answer, callback) {
    var sid = link.session && link.session._sid;
    callback(answer.toString() === sessions[sid].toString());
});

/**
 * captcha
 * Serves the captcha image
 *
 * @name captcha
 * @function
 * @param {Object} link Mono link object
 * @return
 */
exports.captcha = function (link) {

    var res = link.res;

    // Generate number and store it in sessions cache
    var number = parseInt(Math.random() * 9000 + 1000);
    var sid = link.session && link.session._sid;
    sessions[sid] = number;

    var cap = new CaptchaPng(serverConfig.width, serverConfig.height, number);
    cap.color(0, 100, 0, 0);
    cap.color(80, 80, 80, 255);

    var img = cap.getBase64();
    var imgBase64 = new Buffer(img, "base64");
    res.writeHead(200, {
        "Content-Type": "image/png"
    });

    res.end(imgBase64);
};
<|endoftext|>


<commit_before>define([
    'angular',
    'require',
    './controllers/list',
    './controllers/upload',
    './archive-widget/archive',
    './directives'
], function(angular, require) {
    'use strict';

    SpikeService.$inject = ['$location', 'api', 'notify', 'gettext'];
    function SpikeService($location, api, notify, gettext) {
        var SPIKE_RESOURCE = 'archive_spike',
            UNSPIKE_RESOURCE = 'archive_unspike';

        /**
         * Spike given item.
         *
         * @param {Object} item
         */
        this.spike = function spike(item) {
            return api.update(SPIKE_RESOURCE, item, {state: 'spiked'})
                .then(function() {
                    if ($location.search()._id === item._id) {
                        $location.search('_id', null);
                    }
                    notify.success(gettext('Item was spiked.'));
                }, function(response) {
                    notify.error(gettext('I\'m sorry but can\'t delete the archive item right now.'));
                });
        };

        /**
         * Unspike given item.
         *
         * @param {Object} item
         */
        this.unspike = function unspike(item) {
            return api.update(UNSPIKE_RESOURCE, item, {})
                .then(function() {
                    notify.success(gettext('Item was unspiked.'));
                });
        };
    }

    return angular.module('superdesk.archive', [
        'superdesk.search',
        require('./directives').name,
        'superdesk.dashboard',
        'superdesk.widgets.archive'
    ])

        .service('spike', SpikeService)

        .config(['superdeskProvider', function(superdesk) {
            superdesk
                .activity('/workspace/content', {
                    label: gettext('Workspace'),
                    priority: 100,
                    controller: require('./controllers/list'),
                    templateUrl: require.toUrl('./views/list.html'),
                    topTemplateUrl: require.toUrl('../superdesk-dashboard/views/workspace-topnav.html'),
                    filters: [
                        {action: 'view', type: 'content'}
                    ],
                    privileges: {archive: 1}
                })
                .activity('upload.media', {
                    label: gettext('Upload media'),
                    modal: true,
                    cssClass: 'upload-media responsive-popup',
                    controller: require('./controllers/upload'),
                    templateUrl: require.toUrl('./views/upload.html'),
                    filters: [
                        {action: 'upload', type: 'media'}
                    ],
                    privileges: {archive: 1}
                })
                .activity('spike', {
                    label: gettext('Spike Item'),
                    icon: 'remove',
                    controller: ['spike', 'data', function spikeActivity(spike, data) {
                        return spike.spike(data.item);
                    }],
                    filters: [{action: 'list', type: 'archive'}],
                    action: 'spike'
                })
                .activity('unspike', {
                    label: gettext('Unspike Item'),
                    icon: 'revert',
                    controller: ['spike', 'data', function unspikeActivity(spike, data) {
                        return spike.unspike(data.item);
                    }],
                    filters: [{action: 'list', type: 'spike'}],
                    action: 'unspike'
                });
        }])

        .config(['apiProvider', function(apiProvider) {
            apiProvider.api('notification', {
                type: 'http',
                backend: {
                    rel: 'notification'
                }
            });
            apiProvider.api('archive', {
                type: 'http',
                backend: {
                    rel: 'archive'
                }
            });
            apiProvider.api('archiveMedia', {
                type: 'http',
                backend: {
                    rel: 'archive_media'
                }
            });
        }]);
});
<commit_msg>feat(archive): Added fetch action to content list and search results.<commit_after>define([
    'angular',
    'require',
    './controllers/list',
    './controllers/upload',
    './archive-widget/archive',
    './directives'
], function(angular, require) {
    'use strict';

    SpikeService.$inject = ['$location', 'api', 'notify', 'gettext'];
    function SpikeService($location, api, notify, gettext) {
        var SPIKE_RESOURCE = 'archive_spike',
            UNSPIKE_RESOURCE = 'archive_unspike';

        /**
         * Spike given item.
         *
         * @param {Object} item
         */
        this.spike = function spike(item) {
            return api.update(SPIKE_RESOURCE, item, {state: 'spiked'})
                .then(function() {
                    if ($location.search()._id === item._id) {
                        $location.search('_id', null);
                    }
                    notify.success(gettext('Item was spiked.'));
                }, function(response) {
                    notify.error(gettext('I\'m sorry but can\'t delete the archive item right now.'));
                });
        };

        /**
         * Unspike given item.
         *
         * @param {Object} item
         */
        this.unspike = function unspike(item) {
            return api.update(UNSPIKE_RESOURCE, item, {})
                .then(function() {
                    notify.success(gettext('Item was unspiked.'));
                });
        };
    }

    return angular.module('superdesk.archive', [
        'superdesk.search',
        require('./directives').name,
        'superdesk.dashboard',
        'superdesk.widgets.archive'
    ])

        .service('spike', SpikeService)

        .config(['superdeskProvider', function(superdesk) {
            superdesk
                .activity('/workspace/content', {
                    label: gettext('Workspace'),
                    priority: 100,
                    controller: require('./controllers/list'),
                    templateUrl: require.toUrl('./views/list.html'),
                    topTemplateUrl: require.toUrl('../superdesk-dashboard/views/workspace-topnav.html'),
                    filters: [
                        {action: 'view', type: 'content'}
                    ],
                    privileges: {archive: 1}
                })
                .activity('upload.media', {
                    label: gettext('Upload media'),
                    modal: true,
                    cssClass: 'upload-media responsive-popup',
                    controller: require('./controllers/upload'),
                    templateUrl: require.toUrl('./views/upload.html'),
                    filters: [
                        {action: 'upload', type: 'media'}
                    ],
                    privileges: {archive: 1}
                })
                .activity('spike', {
                    label: gettext('Spike Item'),
                    icon: 'remove',
                    controller: ['spike', 'data', function spikeActivity(spike, data) {
                        return spike.spike(data.item);
                    }],
                    filters: [{action: 'list', type: 'archive'}],
                    action: 'spike'
                })
                .activity('unspike', {
                    label: gettext('Unspike Item'),
                    icon: 'revert',
                    controller: ['spike', 'data', function unspikeActivity(spike, data) {
                        return spike.unspike(data.item);
                    }],
                    filters: [{action: 'list', type: 'spike'}],
                    action: 'unspike'
                })
                .activity('archiveContent', {
                    label: gettext('Fetch'),
                    icon: 'archive',
                    controller: ['api', 'data', 'desks', function(api, data, desks) {
                        api.archiveIngest.create({
                            guid: data.item.guid,
                            desk: desks.getCurrentDeskId()
                        })
                        .then(function(archiveItem) {
                            data.item.task_id = archiveItem.task_id;
                            data.item.created = archiveItem.created;
                        });
                    }],
                    filters: [{action: 'list', type: 'archive'}],
                    action: 'fetch_as_from_content'
                });
        }])

        .config(['apiProvider', function(apiProvider) {
            apiProvider.api('notification', {
                type: 'http',
                backend: {
                    rel: 'notification'
                }
            });
            apiProvider.api('archive', {
                type: 'http',
                backend: {
                    rel: 'archive'
                }
            });
            apiProvider.api('archiveMedia', {
                type: 'http',
                backend: {
                    rel: 'archive_media'
                }
            });
        }]);
});
<|endoftext|>


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

const saveBid = async ({ vehicle_id, bid, pickup, dropoff }, requestId) => {
  // get new unique id for bid
  const bidId = await redis.incrAsync('next_bid_id');

  // Save bid id in request_bids
  redis.rpushAsync(`request_bids:${requestId}`, bidId);

  // Add bid to bids
  redis.hmsetAsync(`bids:${bidId}`,
    'id', bidId,
    'vehicle_id', vehicle_id,
    'bid', bid,
    'pickup', pickup,
    'dropoff', dropoff,
  );

  return bidId;
};

const getBidsForRequest = async (requestId) => {
  // get request details
  //    note: `hgetall` is only used because we want to get the pickup coordinates so we can
  //    make up some bids. Once we don't need to make them up here we can start using `hexists`
  const request = await redis.hgetallAsync(`requests:${requestId}`);
  if (!request) return [];

  // get bids for request
  const bidIds = await redis.lrangeAsync(`request_bids:${requestId}`, 0, -1);
  const bids = await Promise.all(
    bidIds.map(bidId => redis.hgetallAsync(`bids:${bidId}`))
  );

  // If not enough bids, make some up
  if (bidIds.length < 10) {
    const { pickup_long, pickup_lat } = request;
    const vehicleIds = await redis.georadiusAsync('vehicle_positions', pickup_long, pickup_lat, 2000, 'm');
    if (vehicleIds.length > bidIds.length) {
      // Just a hacky way to get more bids from different vehicles.
      // Not guaranteed to not have duplicate bids from same vehicle
      const vehicleId = vehicleIds[bidIds.length];
      let newBid = {
        vehicle_id: vehicleId,
        bid: 0.8,
        pickup: Date.now()+(1000*60*2),
        dropoff: Date.now()+(1000*60*10),
      };
      const newBidId = await saveBid(newBid, requestId);
      newBid.id = newBidId;
      bids.push(newBid);
    }
  }

  return bids;
};

module.exports = {
  getBidsForRequest
};
<commit_msg>When generating bids use new randomBid function and pass it coordinates<commit_after>const redis = require('./redis');
const { randomBid } = require('../simulation/vehicles');
const { getVehicle } = require('../store/vehicles');

const saveBid = async ({ vehicle_id, bid, pickup, dropoff }, requestId) => {
  // get new unique id for bid
  const bidId = await redis.incrAsync('next_bid_id');

  // Save bid id in request_bids
  redis.rpushAsync(`request_bids:${requestId}`, bidId);

  // Add bid to bids
  redis.hmsetAsync(`bids:${bidId}`,
    'id', bidId,
    'vehicle_id', vehicle_id,
    'bid', bid,
    'pickup', pickup,
    'dropoff', dropoff,
  );

  return bidId;
};

const getBidsForRequest = async (requestId) => {
  // get request details
  //    note: `hgetall` is only used because we want to get the pickup coordinates so we can
  //    make up some bids. Once we don't need to make them up here we can start using `hexists`
  const request = await redis.hgetallAsync(`requests:${requestId}`);
  if (!request) return [];

  // get bids for request
  const bidIds = await redis.lrangeAsync(`request_bids:${requestId}`, 0, -1);
  const bids = await Promise.all(
    bidIds.map(bidId => redis.hgetallAsync(`bids:${bidId}`))
  );

  // If not enough bids, make some up
  if (bidIds.length < 10) {
    const { pickup_long, pickup_lat, dropoff_lat, dropoff_long } = request;
    const pickup =  {lat: pickup_lat,  long: pickup_long};
    const dropoff = {lat: dropoff_lat, long: dropoff_long};
    const vehicleIds = await redis.georadiusAsync('vehicle_positions', pickup_long, pickup_lat, 2000, 'm');
    if (vehicleIds.length > bidIds.length) {
      // Just a hacky way to get more bids from different vehicles.
      // Not guaranteed to not have duplicate bids from same vehicle
      const vehicleId = vehicleIds[bidIds.length];
      const vehicle = await getVehicle(vehicleId);
      const origin = {lat: vehicle.lat, long: vehicle.long};
      let newBid = randomBid(origin, pickup, dropoff);
      newBid.vehicle_id = vehicleId;
      const newBidId = await saveBid(newBid, requestId);
      newBid.id = newBidId;
      bids.push(newBid);
    }
  }

  return bids;
};

module.exports = {
  getBidsForRequest
};
<|endoftext|>


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

var Logger = {
    className: 'Logger',

    /**
     * Syntax:
     * [Time]: [Message]
     */
    log: function(){
        fs.appendFileSync(this.logFile, this.createText(arguments) + "\r\n");
        //console.log.apply(console, arr);
    },

    logArray: function(className, arr){
        fs.appendFileSync(this.logFile, this.createText([className, ':'], arr) + "\r\n");
    },

    createText: function(params, params2){
        params2 = params2 || [];

        var result = ['[', this.getTime(), '] :'];
        for(var i=0; i<params.length; i++){
            result.push(params[i]);
        }
        for(i=0; i<params2.length; i++){
            result.push(params2[i]);
        }
        return result.join(' ');
    },

    sysLog: function(){
        var arr = ['[', this.getTime(), '] :'];
        for(var i =0; i < arguments.length; i++){
            arr.push(arguments[i]);
        }
        console.log.apply(console, arr);
    },

    init: function(){
        var file = this.getFile();
        this.sysLog('Init log file :', file);

        this.logFile = file;

        console.log('/app', fs.existsSync('/app'));
        console.log('/tmp', fs.existsSync('/tmp'));
        console.log('/log', fs.existsSync('/log'));

        if(!fs.existsSync(file)){
            var fd = fs.openSync("/tmp/file.log", "a+");
            fs.closeSync(fd);
        }
    },

    getFile: function(index){
        var logName = this.getLogName();
        index = index || 0;
        var fileName = this.getFormattedLogName(logName, index);

        if(!fs.existsSync(fileName)){
            return fileName;
        }

        var stat = fs.statSync(fileName);
        if(stat.size < 1024 * 1024 * 10){
            return fileName;
        }

        return this.getFile(index + 1);
    },

    /**
     * Syntax: dd/mm/YYYY hh:mm:ss
     * @returns {string}
     */
    getTime: function(){
        var d = new Date();
        return d.getDate() + '/' + d.getMonth() + '/' + d.getFullYear() + ' '
            + d.getHours() + ':' + d.getMinutes() + ':' + d.getSeconds();
    },

    getFormattedLogName: function(logName, index){
        if(index < 1){
            return 'log/' + logName + '.log';
        }
        return 'log/' + logName + '-' + index + '.log';
    },

    getLogName: function(){
        var d = new Date();

        return d.getDate() + '-' + d.getMonth() + '-' + d.getFullYear();
    }
};

var compile = require('./compile.js');
module.exports = compile.singleton(Logger, null, true);
<commit_msg>fix crashing<commit_after>var fs = require('fs');

var Logger = {
    className: 'Logger',

    /**
     * Syntax:
     * [Time]: [Message]
     */
    log: function(){
        fs.appendFileSync(this.logFile, this.createText(arguments) + "\r\n");
        //console.log.apply(console, arr);
    },

    logArray: function(className, arr){
        fs.appendFileSync(this.logFile, this.createText([className, ':'], arr) + "\r\n");
    },

    createText: function(params, params2){
        params2 = params2 || [];

        var result = ['[', this.getTime(), '] :'];
        for(var i=0; i<params.length; i++){
            result.push(params[i]);
        }
        for(i=0; i<params2.length; i++){
            result.push(params2[i]);
        }
        return result.join(' ');
    },

    sysLog: function(){
        var arr = ['[', this.getTime(), '] :'];
        for(var i =0; i < arguments.length; i++){
            arr.push(arguments[i]);
        }
        console.log.apply(console, arr);
    },

    init: function(){
        var file = this.getFile();
        this.sysLog('Init log file :', file);

        this.logFile = file;
        if(!fs.existsSync("log")){ //heroku
            this.logFile = file.replace('log/', '/tmp/');
        }

        if(!fs.existsSync(file)){
            var fd = fs.openSync(file, "a+");
            fs.closeSync(fd);
        }
    },

    getFile: function(index){
        var logName = this.getLogName();
        index = index || 0;
        var fileName = this.getFormattedLogName(logName, index);

        if(!fs.existsSync(fileName)){
            return fileName;
        }

        var stat = fs.statSync(fileName);
        if(stat.size < 1024 * 1024 * 10){
            return fileName;
        }

        return this.getFile(index + 1);
    },

    /**
     * Syntax: dd/mm/YYYY hh:mm:ss
     * @returns {string}
     */
    getTime: function(){
        var d = new Date();
        return d.getDate() + '/' + d.getMonth() + '/' + d.getFullYear() + ' '
            + d.getHours() + ':' + d.getMinutes() + ':' + d.getSeconds();
    },

    getFormattedLogName: function(logName, index){
        if(index < 1){
            return 'log/' + logName + '.log';
        }
        return 'log/' + logName + '-' + index + '.log';
    },

    getLogName: function(){
        var d = new Date();

        return d.getDate() + '-' + d.getMonth() + '-' + d.getFullYear();
    }
};

var compile = require('./compile.js');
module.exports = compile.singleton(Logger, null, true);
<|endoftext|>


<commit_before>/* eslint-disable no-multi-spaces */
import elo from 'elo-rank'

import {roundDecimal} from 'src/common/util'
import {avg, toPercent} from './index'

export const LIKERT_SCORE_NA = 0
export const LIKERT_SCORE_MIN = 1
export const LIKERT_SCORE_MAX = 7

export function aggregateBuildCycles(numPlayers, numBuildCycles = 1) {
  if (numPlayers === null || numBuildCycles === null || isNaN(numPlayers) || isNaN(numBuildCycles)) {
    return null
  }
  return numPlayers * numBuildCycles
}

export function relativeContribution(rcScores) {
  return Math.round(avg(rcScores))
}

export function expectedContribution(playerHours, teamHours) {
  if (playerHours === null || isNaN(playerHours) || isNaN(teamHours)) {
    return null
  }
  if (teamHours === 0) {
    return 0
  }
  return Math.round(toPercent(playerHours / teamHours))
}

export function expectedContributionDelta(ec, rc) {
  if (ec === null || rc === null || isNaN(ec) || isNaN(rc)) {
    return null
  }
  return rc - ec
}

export function effectiveContributionCycles(abc, rc) {
  if (abc === null || rc === null || isNaN(abc) || isNaN(rc)) {
    return null
  }
  return abc * rc
}

export const technicalHealth    = likert7Average
export const cultureContribution = likert7Average
export const cultureContributionStructure = likert7Average
export const cultureContributionSafety = likert7Average
export const cultureContributionTruth = likert7Average
export const cultureContributionChallenge = likert7Average
export const cultureContributionSupport = likert7Average
export const cultureContributionEngagement = likert7Average
export const cultureContributionEnjoyment = likert7Average
export const teamPlay           = likert7Average
export const receptiveness      = likert7Average
export const flexibleLeadership = likert7Average
export const resultsFocus       = likert7Average
export const frictionReduction  = likert7Average

export function likert7Average(scores) {
  return averageScoreInRange(LIKERT_SCORE_MIN, LIKERT_SCORE_MAX, scores)
}

export function averageScoreInRange(minScore, maxScore, scores) {
  if (isNaN(minScore)) {
    throw new Error('Invalid score range min')
  }
  if (isNaN(maxScore)) {
    throw new Error('Invalid score range max')
  }
  if (minScore > maxScore) {
    throw new Error('Min score must be less than or equal to max score')
  }
  if (!Array.isArray(scores)) {
    return null
  }
  // exclude scores outside of valid range
  // shift score values down by min to produce range 0...n
  const adjusted = scores
                    .filter(n => (n >= minScore && n <= maxScore))
                    .map(n => n - minScore)
  const adjustedAvg = avg(adjusted)
  const range = maxScore - minScore
  return Math.round(toPercent(adjustedAvg / range))
}

export function experiencePoints(teamHours, rc) {
  return roundDecimal(teamHours * (rc / 100))
}

/**
 * params:
 *   players (obj array) -> [playerA, playerB]
 *     - rating
 *     - score (game score)
 *     - kFactor
 *
 * returns:
 *   result (int array) -> [newRatingA, newRatingB]
 */
export function eloRatings([playerA, playerB]) {
  _validatePlayer(playerA)
  _validatePlayer(playerB)

  const {rating: ratingA, score: scoreA, kFactor: kFactorA} = playerA
  const {rating: ratingB, score: scoreB, kFactor: kFactorB} = playerB

  const eloA = elo(kFactorA)
  const eloB = elo(kFactorB)

  const expectedMarginA = eloA.getExpected(ratingA, ratingB)
  const expectedMarginB = eloB.getExpected(ratingB, ratingA)

  const [actualMarginA, actualMarginB] = scoreMargins([scoreA, scoreB])

  const newRatingA = eloA.updateRating(expectedMarginA, actualMarginA, ratingA)
  const newRatingB = eloB.updateRating(expectedMarginB, actualMarginB, ratingB)

  return [newRatingA, newRatingB]
}

export function scoreMargins([scoreA, scoreB]) {
  if (scoreA === 0 && scoreB === 0) {
    return [0, 0]
  }

  return [
    roundDecimal(scoreA / (scoreA + scoreB)),
    roundDecimal(scoreB / (scoreB + scoreA)),
  ]
}

/* eslint-disable key-spacing */
// see: https://playbook.learnersguild.org/Game_Manual/Levels_and_Roles.html#level-requirements
// FIXME: missing -- XP/week, estimation accuracy, # of reviews
export const LEVELS = [
  {level: 0, xp:    0, elo:    0, cc:  0, tp:  0, th:  0},
  {level: 1, xp:    0, elo:  900, cc: 65, tp: 65, th:  0},
  {level: 2, xp:  150, elo: 1000, cc: 80, tp: 80, th:  0},
  {level: 3, xp:  500, elo: 1050, cc: 85, tp: 85, th: 80},
  {level: 4, xp:  750, elo: 1100, cc: 90, tp: 90, th: 90},
  {level: 5, xp: 1000, elo: 1150, cc: 90, tp: 90, th: 95},
]
/* eslint-enable key-spacing */

export function computePlayerLevel(player) {
  const {
    elo,
    xp,
    // FIXME: pull these in once we have roll-up stats for cc, tp, and th
    // cc,
    // tp,
    // th,
  } = _playerLevelStats(player)

  const levelsDescending = LEVELS.slice().reverse()
  for (const levelInfo of levelsDescending) {
    const {
      level,
      elo: lvlElo,
      xp: lvlXp,
      // FIXME: pull these in once we have roll-up stats for cc, tp, and th
      // cc: lvlCc,
      // tp: lvlTp,
      // th: lvlTh,
    } = levelInfo

    // FIXME: this should be as below once we have roll-up stats for cc, tp, and th
    // if (xp >= lvlXp && elo >= lvlElo && cc >= lvlCc && tp >= lvlTp && th >= lvlTh) {
    if (xp >= lvlXp && elo >= lvlElo) {
      return level
    }
  }

  throw new Error(`Could not place this player in ANY level! ${player.id}`)
}

function _playerLevelStats(player) {
  const _playerStat = (player, stat) => parseInt((player.stats || {})[stat], 10) || 0

  return {
    elo: parseInt(((player.stats || {}).elo || {}).rating, 10) || 0,
    xp: _playerStat(player, 'xp'),
    // FIXME: pull these in once we have roll-up stats for cc, tp, and th
    // cc: _playerStat(player, 'cc'),
    // tp: _playerStat(player, 'tp'),
    // th: _playerStat(player, 'th'),
  }
}

function _validatePlayer(player) {
  if (!player) {
    throw new Error('Invalid player object')
  }
  if (isNaN(player.rating)) {
    throw new Error('Invalid player rating')
  }
  if (isNaN(player.score)) {
    throw new Error('Invalid player score')
  }
  if (isNaN(player.kFactor)) {
    throw new Error('Invalid player kFactor')
  }
}

export function findValueForReponseQuestionStat(responseArr, statDescriptor) {
  if (!Array.isArray(responseArr) || !statDescriptor) {
    return
  }
  return (responseArr.find(response => (
    ((response.question || {}).stat || {}).descriptor === statDescriptor
  )) || {}).value
}
<commit_msg>Updates ELO thresholds for level 2 and 3<commit_after>/* eslint-disable no-multi-spaces */
import elo from 'elo-rank'

import {roundDecimal} from 'src/common/util'
import {avg, toPercent} from './index'

export const LIKERT_SCORE_NA = 0
export const LIKERT_SCORE_MIN = 1
export const LIKERT_SCORE_MAX = 7

export function aggregateBuildCycles(numPlayers, numBuildCycles = 1) {
  if (numPlayers === null || numBuildCycles === null || isNaN(numPlayers) || isNaN(numBuildCycles)) {
    return null
  }
  return numPlayers * numBuildCycles
}

export function relativeContribution(rcScores) {
  return Math.round(avg(rcScores))
}

export function expectedContribution(playerHours, teamHours) {
  if (playerHours === null || isNaN(playerHours) || isNaN(teamHours)) {
    return null
  }
  if (teamHours === 0) {
    return 0
  }
  return Math.round(toPercent(playerHours / teamHours))
}

export function expectedContributionDelta(ec, rc) {
  if (ec === null || rc === null || isNaN(ec) || isNaN(rc)) {
    return null
  }
  return rc - ec
}

export function effectiveContributionCycles(abc, rc) {
  if (abc === null || rc === null || isNaN(abc) || isNaN(rc)) {
    return null
  }
  return abc * rc
}

export const technicalHealth    = likert7Average
export const cultureContribution = likert7Average
export const cultureContributionStructure = likert7Average
export const cultureContributionSafety = likert7Average
export const cultureContributionTruth = likert7Average
export const cultureContributionChallenge = likert7Average
export const cultureContributionSupport = likert7Average
export const cultureContributionEngagement = likert7Average
export const cultureContributionEnjoyment = likert7Average
export const teamPlay           = likert7Average
export const receptiveness      = likert7Average
export const flexibleLeadership = likert7Average
export const resultsFocus       = likert7Average
export const frictionReduction  = likert7Average

export function likert7Average(scores) {
  return averageScoreInRange(LIKERT_SCORE_MIN, LIKERT_SCORE_MAX, scores)
}

export function averageScoreInRange(minScore, maxScore, scores) {
  if (isNaN(minScore)) {
    throw new Error('Invalid score range min')
  }
  if (isNaN(maxScore)) {
    throw new Error('Invalid score range max')
  }
  if (minScore > maxScore) {
    throw new Error('Min score must be less than or equal to max score')
  }
  if (!Array.isArray(scores)) {
    return null
  }
  // exclude scores outside of valid range
  // shift score values down by min to produce range 0...n
  const adjusted = scores
                    .filter(n => (n >= minScore && n <= maxScore))
                    .map(n => n - minScore)
  const adjustedAvg = avg(adjusted)
  const range = maxScore - minScore
  return Math.round(toPercent(adjustedAvg / range))
}

export function experiencePoints(teamHours, rc) {
  return roundDecimal(teamHours * (rc / 100))
}

/**
 * params:
 *   players (obj array) -> [playerA, playerB]
 *     - rating
 *     - score (game score)
 *     - kFactor
 *
 * returns:
 *   result (int array) -> [newRatingA, newRatingB]
 */
export function eloRatings([playerA, playerB]) {
  _validatePlayer(playerA)
  _validatePlayer(playerB)

  const {rating: ratingA, score: scoreA, kFactor: kFactorA} = playerA
  const {rating: ratingB, score: scoreB, kFactor: kFactorB} = playerB

  const eloA = elo(kFactorA)
  const eloB = elo(kFactorB)

  const expectedMarginA = eloA.getExpected(ratingA, ratingB)
  const expectedMarginB = eloB.getExpected(ratingB, ratingA)

  const [actualMarginA, actualMarginB] = scoreMargins([scoreA, scoreB])

  const newRatingA = eloA.updateRating(expectedMarginA, actualMarginA, ratingA)
  const newRatingB = eloB.updateRating(expectedMarginB, actualMarginB, ratingB)

  return [newRatingA, newRatingB]
}

export function scoreMargins([scoreA, scoreB]) {
  if (scoreA === 0 && scoreB === 0) {
    return [0, 0]
  }

  return [
    roundDecimal(scoreA / (scoreA + scoreB)),
    roundDecimal(scoreB / (scoreB + scoreA)),
  ]
}

/* eslint-disable key-spacing */
// see: https://playbook.learnersguild.org/Game_Manual/Levels_and_Roles.html#level-requirements
// FIXME: missing -- XP/week, estimation accuracy, # of reviews
export const LEVELS = [
  {level: 0, xp:    0, elo:    0, cc:  0, tp:  0, th:  0},
  {level: 1, xp:    0, elo:  900, cc: 65, tp: 65, th:  0},
  {level: 2, xp:  150, elo: 990, cc: 80, tp: 80, th:  0},
  {level: 3, xp:  500, elo: 1020, cc: 85, tp: 85, th: 80},
  {level: 4, xp:  750, elo: 1100, cc: 90, tp: 90, th: 90},
  {level: 5, xp: 1000, elo: 1150, cc: 90, tp: 90, th: 95},
]
/* eslint-enable key-spacing */

export function computePlayerLevel(player) {
  const {
    elo,
    xp,
    // FIXME: pull these in once we have roll-up stats for cc, tp, and th
    // cc,
    // tp,
    // th,
  } = _playerLevelStats(player)

  const levelsDescending = LEVELS.slice().reverse()
  for (const levelInfo of levelsDescending) {
    const {
      level,
      elo: lvlElo,
      xp: lvlXp,
      // FIXME: pull these in once we have roll-up stats for cc, tp, and th
      // cc: lvlCc,
      // tp: lvlTp,
      // th: lvlTh,
    } = levelInfo

    // FIXME: this should be as below once we have roll-up stats for cc, tp, and th
    // if (xp >= lvlXp && elo >= lvlElo && cc >= lvlCc && tp >= lvlTp && th >= lvlTh) {
    if (xp >= lvlXp && elo >= lvlElo) {
      return level
    }
  }

  throw new Error(`Could not place this player in ANY level! ${player.id}`)
}

function _playerLevelStats(player) {
  const _playerStat = (player, stat) => parseInt((player.stats || {})[stat], 10) || 0

  return {
    elo: parseInt(((player.stats || {}).elo || {}).rating, 10) || 0,
    xp: _playerStat(player, 'xp'),
    // FIXME: pull these in once we have roll-up stats for cc, tp, and th
    // cc: _playerStat(player, 'cc'),
    // tp: _playerStat(player, 'tp'),
    // th: _playerStat(player, 'th'),
  }
}

function _validatePlayer(player) {
  if (!player) {
    throw new Error('Invalid player object')
  }
  if (isNaN(player.rating)) {
    throw new Error('Invalid player rating')
  }
  if (isNaN(player.score)) {
    throw new Error('Invalid player score')
  }
  if (isNaN(player.kFactor)) {
    throw new Error('Invalid player kFactor')
  }
}

export function findValueForReponseQuestionStat(responseArr, statDescriptor) {
  if (!Array.isArray(responseArr) || !statDescriptor) {
    return
  }
  return (responseArr.find(response => (
    ((response.question || {}).stat || {}).descriptor === statDescriptor
  )) || {}).value
}
<|endoftext|>


<commit_before>'use strict';
// 3rd party
// ...
// 1st party
var bbcode = require('./bbcode');

// Markup and HTML for the welcome/introductory PM
var welcomeMarkup = `
[center][h1]Welcome to the Roleplayer Guild![/h1][/center]

We are an ever-growing community of enthusiastic and dedicated play-by-post roleplayers that cater to all genres and playstyles - fantasy, sci-fi, romance and even tabletop & nation roleplays. First founded in 2007, the Guild has been the go-to forum for thousands of members since its inception. We sport an easy-to-navigate forum layout and a plethora of nifty features implemented specifically to improve the roleplaying experience.

[list]
[*]Feeling a little overwhelmed? It is [b]highly[/b] recommended that you read the [url=http://www.roleplayerguild.com/topics/150081-a-new-users-guide-to-the-guild/ooc]New User's Guide[/url], which explains the various purposes of our different subforums and is full of useful links & information.
[*]Please familiarize yourself with the [url=http://www.roleplayerguild.com/topics/531/posts/ooc]Fundamental Rules of the Guild[/url]. Don't worry, there aren't many.
[*]The Guild is currently undergoing development. Features that are missing will be implemented in the future and existing functionality will keep improving. Keep an eye on [url=http://www.roleplayerguild.com/topics/75056/posts/ooc]Mahz's Dev Journal[/url] to stay up to date with the changes.
[*]Last but not least, the [url=http://www.roleplayerguild.com/forums/2]Introduce Yourself[/url] subforum is a great way to introduce yourself to our community and make a good first impression. Also be sure to check out the [url=http://www.roleplayerguild.com/chat]Guild's Chat[/url] where our members frequently hang out.[/list]

We hope you enjoy your stay at the Roleplayer Guild. :sun

Yours sincerely,
The Roleplayer Guild Staff
`;

var welcomeHtml = bbcode(welcomeMarkup);

module.exports = {
  markup: welcomeMarkup,
  html: welcomeHtml
};
<commit_msg>Update rules link in welcome pm<commit_after>'use strict';
// 3rd party
// ...
// 1st party
var bbcode = require('./bbcode');

// Markup and HTML for the welcome/introductory PM
var welcomeMarkup = `
[center][h1]Welcome to the Roleplayer Guild![/h1][/center]

We are an ever-growing community of enthusiastic and dedicated play-by-post roleplayers that cater to all genres and playstyles - fantasy, sci-fi, romance and even tabletop & nation roleplays. First founded in 2007, the Guild has been the go-to forum for thousands of members since its inception. We sport an easy-to-navigate forum layout and a plethora of nifty features implemented specifically to improve the roleplaying experience.

[list]
[*]Feeling a little overwhelmed? It is [b]highly[/b] recommended that you read the [url=http://www.roleplayerguild.com/topics/150081-a-new-users-guide-to-the-guild/ooc]New User's Guide[/url], which explains the various purposes of our different subforums and is full of useful links & information.
[*]Please familiarize yourself with the [url=http://www.roleplayerguild.com/topics/150080-fundamental-rules-of-the-guild/ooc]Fundamental Rules of the Guild[/url]. Don't worry, there aren't many.
[*]The Guild is currently undergoing development. Features that are missing will be implemented in the future and existing functionality will keep improving. Keep an eye on [url=http://www.roleplayerguild.com/topics/75056/posts/ooc]Mahz's Dev Journal[/url] to stay up to date with the changes.
[*]Last but not least, the [url=http://www.roleplayerguild.com/forums/2]Introduce Yourself[/url] subforum is a great way to introduce yourself to our community and make a good first impression. Also be sure to check out the [url=http://www.roleplayerguild.com/chat]Guild's Chat[/url] where our members frequently hang out.[/list]

We hope you enjoy your stay at the Roleplayer Guild. :sun

Yours sincerely,
The Roleplayer Guild Staff
`;

var welcomeHtml = bbcode(welcomeMarkup);

module.exports = {
  markup: welcomeMarkup,
  html: welcomeHtml
};
<|endoftext|>


<commit_before><commit_msg>Update toastr_rails.js<commit_after><|endoftext|>


<commit_before><commit_msg>Adding error from state when login fail<commit_after><|endoftext|>


<commit_before><commit_msg>Update myCtrl1<commit_after><|endoftext|>


<commit_before><commit_msg>SWIK-1676 create indexes<commit_after><|endoftext|>


<commit_before>var SourceMapConsumer = require('source-map').SourceMapConsumer;
var path = require('path');
var fs = require('fs');

// Only install once if called multiple times
var errorFormatterInstalled = false;
var uncaughtShimInstalled = false;

// If true, the caches are reset before a stack trace formatting operation
var emptyCacheBetweenOperations = false;

// Supports {browser, node, auto}
var environment = "auto";

// Maps a file path to a string containing the file contents
var fileContentsCache = {};

// Maps a file path to a source map for that file
var sourceMapCache = {};

// Regex for detecting source maps
var reSourceMap = /^data:application\/json[^,]+base64,/;

// Priority list of retrieve handlers
var retrieveFileHandlers = [];
var retrieveMapHandlers = [];

function isInBrowser() {
  if (environment === "browser")
    return true;
  if (environment === "node")
    return false;
  return ((typeof window !== 'undefined') && (typeof XMLHttpRequest === 'function'));
}

function hasGlobalProcessEventEmitter() {
  return ((typeof process === 'object') && (process !== null) && (typeof process.on === 'function'));
}

function handlerExec(list) {
  return function(arg) {
    for (var i = 0; i < list.length; i++) {
      var ret = list[i](arg);
      if (ret) {
        return ret;
      }
    }
    return null;
  };
}

var retrieveFile = handlerExec(retrieveFileHandlers);

retrieveFileHandlers.push(function(path) {
  // Trim the path to make sure there is no extra whitespace.
  path = path.trim();
  if (path in fileContentsCache) {
    return fileContentsCache[path];
  }

  try {
    // Use SJAX if we are in the browser
    if (isInBrowser()) {
      var xhr = new XMLHttpRequest();
      xhr.open('GET', path, false);
      xhr.send(null);
      var contents = null
      if (xhr.readyState === 4 && xhr.status === 200) {
        contents = xhr.responseText
      }
    }

    // Otherwise, use the filesystem
    else {
      var contents = fs.readFileSync(path, 'utf8');
    }
  } catch (e) {
    var contents = null;
  }

  return fileContentsCache[path] = contents;
});

// Support URLs relative to a directory, but be careful about a protocol prefix
// in case we are in the browser (i.e. directories may start with "http://")
function supportRelativeURL(file, url) {
  if (!file) return url;
  var dir = path.dirname(file);
  var match = /^\w+:\/\/[^\/]*/.exec(dir);
  var protocol = match ? match[0] : '';
  return protocol + path.resolve(dir.slice(protocol.length), url);
}

function retrieveSourceMapURL(source) {
  var fileData;

  if (isInBrowser()) {
    var xhr = new XMLHttpRequest();
    xhr.open('GET', source, false);
    xhr.send(null);
    fileData = xhr.readyState === 4 ? xhr.responseText : null;

    // Support providing a sourceMappingURL via the SourceMap header
    var sourceMapHeader = xhr.getResponseHeader("SourceMap") ||
                          xhr.getResponseHeader("X-SourceMap");
    if (sourceMapHeader) {
      return sourceMapHeader;
    }
  }

  // Get the URL of the source map
  fileData = retrieveFile(source);
  //        //# sourceMappingURL=foo.js.map                       /*# sourceMappingURL=foo.js.map */
  var re = /(?:\/\/[@#][ \t]+sourceMappingURL=([^\s'"]+?)[ \t]*$)|(?:\/\*[@#][ \t]+sourceMappingURL=([^\*]+?)[ \t]*(?:\*\/)[ \t]*$)/mg;
  // Keep executing the search to find the *last* sourceMappingURL to avoid
  // picking up sourceMappingURLs from comments, strings, etc.
  var lastMatch, match;
  while (match = re.exec(fileData)) lastMatch = match;
  if (!lastMatch) return null;
  return lastMatch[1];
};

// Can be overridden by the retrieveSourceMap option to install. Takes a
// generated source filename; returns a {map, optional url} object, or null if
// there is no source map.  The map field may be either a string or the parsed
// JSON object (ie, it must be a valid argument to the SourceMapConsumer
// constructor).
var retrieveSourceMap = handlerExec(retrieveMapHandlers);
retrieveMapHandlers.push(function(source) {
  var sourceMappingURL = retrieveSourceMapURL(source);
  if (!sourceMappingURL) return null;

  // Read the contents of the source map
  var sourceMapData;
  if (reSourceMap.test(sourceMappingURL)) {
    // Support source map URL as a data url
    var rawData = sourceMappingURL.slice(sourceMappingURL.indexOf(',') + 1);
    sourceMapData = new Buffer(rawData, "base64").toString();
    sourceMappingURL = null;
  } else {
    // Support source map URLs relative to the source URL
    sourceMappingURL = supportRelativeURL(source, sourceMappingURL);
    sourceMapData = retrieveFile(sourceMappingURL);
  }

  if (!sourceMapData) {
    return null;
  }

  return {
    url: sourceMappingURL,
    map: sourceMapData
  };
});

function mapSourcePosition(position) {
  var sourceMap = sourceMapCache[position.source];
  if (!sourceMap) {
    // Call the (overrideable) retrieveSourceMap function to get the source map.
    var urlAndMap = retrieveSourceMap(position.source);
    if (urlAndMap) {
      sourceMap = sourceMapCache[position.source] = {
        url: urlAndMap.url,
        map: new SourceMapConsumer(urlAndMap.map)
      };

      // Load all sources stored inline with the source map into the file cache
      // to pretend like they are already loaded. They may not exist on disk.
      if (sourceMap.map.sourcesContent) {
        sourceMap.map.sources.forEach(function(source, i) {
          var contents = sourceMap.map.sourcesContent[i];
          if (contents) {
            var url = supportRelativeURL(sourceMap.url, source);
            fileContentsCache[url] = contents;
          }
        });
      }
    } else {
      sourceMap = sourceMapCache[position.source] = {
        url: null,
        map: null
      };
    }
  }

  // Resolve the source URL relative to the URL of the source map
  if (sourceMap && sourceMap.map) {
    var originalPosition = sourceMap.map.originalPositionFor(position);

    // Only return the original position if a matching line was found. If no
    // matching line is found then we return position instead, which will cause
    // the stack trace to print the path and line for the compiled file. It is
    // better to give a precise location in the compiled file than a vague
    // location in the original file.
    if (originalPosition.source !== null) {
      originalPosition.source = supportRelativeURL(
        sourceMap.url, originalPosition.source);
      return originalPosition;
    }
  }

  return position;
}

// Parses code generated by FormatEvalOrigin(), a function inside V8:
// https://code.google.com/p/v8/source/browse/trunk/src/messages.js
function mapEvalOrigin(origin) {
  // Most eval() calls are in this format
  var match = /^eval at ([^(]+) \((.+):(\d+):(\d+)\)$/.exec(origin);
  if (match) {
    var position = mapSourcePosition({
      source: match[2],
      line: match[3],
      column: match[4] - 1
    });
    return 'eval at ' + match[1] + ' (' + position.source + ':' +
      position.line + ':' + (position.column + 1) + ')';
  }

  // Parse nested eval() calls using recursion
  match = /^eval at ([^(]+) \((.+)\)$/.exec(origin);
  if (match) {
    return 'eval at ' + match[1] + ' (' + mapEvalOrigin(match[2]) + ')';
  }

  // Make sure we still return useful information if we didn't find anything
  return origin;
}

// This is copied almost verbatim from the V8 source code at
// https://code.google.com/p/v8/source/browse/trunk/src/messages.js. The
// implementation of wrapCallSite() used to just forward to the actual source
// code of CallSite.prototype.toString but unfortunately a new release of V8
// did something to the prototype chain and broke the shim. The only fix I
// could find was copy/paste.
function CallSiteToString() {
  var fileName;
  var fileLocation = "";
  if (this.isNative()) {
    fileLocation = "native";
  } else {
    fileName = this.getScriptNameOrSourceURL();
    if (!fileName && this.isEval()) {
      fileLocation = this.getEvalOrigin();
      fileLocation += ", ";  // Expecting source position to follow.
    }

    if (fileName) {
      fileLocation += fileName;
    } else {
      // Source code does not originate from a file and is not native, but we
      // can still get the source position inside the source string, e.g. in
      // an eval string.
      fileLocation += "<anonymous>";
    }
    var lineNumber = this.getLineNumber();
    if (lineNumber != null) {
      fileLocation += ":" + lineNumber;
      var columnNumber = this.getColumnNumber();
      if (columnNumber) {
        fileLocation += ":" + columnNumber;
      }
    }
  }

  var line = "";
  var functionName = this.getFunctionName();
  var addSuffix = true;
  var isConstructor = this.isConstructor();
  var isMethodCall = !(this.isToplevel() || isConstructor);
  if (isMethodCall) {
    var typeName = this.getTypeName();
    var methodName = this.getMethodName();
    if (functionName) {
      if (typeName && functionName.indexOf(typeName) != 0) {
        line += typeName + ".";
      }
      line += functionName;
      if (methodName && functionName.indexOf("." + methodName) != functionName.length - methodName.length - 1) {
        line += " [as " + methodName + "]";
      }
    } else {
      line += typeName + "." + (methodName || "<anonymous>");
    }
  } else if (isConstructor) {
    line += "new " + (functionName || "<anonymous>");
  } else if (functionName) {
    line += functionName;
  } else {
    line += fileLocation;
    addSuffix = false;
  }
  if (addSuffix) {
    line += " (" + fileLocation + ")";
  }
  return line;
}

function cloneCallSite(frame) {
  var object = {};
  Object.getOwnPropertyNames(Object.getPrototypeOf(frame)).forEach(function(name) {
    object[name] = /^(?:is|get)/.test(name) ? function() { return frame[name].call(frame); } : frame[name];
  });
  object.toString = CallSiteToString;
  return object;
}

function wrapCallSite(frame) {
  // Most call sites will return the source file from getFileName(), but code
  // passed to eval() ending in "//# sourceURL=..." will return the source file
  // from getScriptNameOrSourceURL() instead
  var source = frame.getFileName() || frame.getScriptNameOrSourceURL();
  if (source) {
    var line = frame.getLineNumber();
    var column = frame.getColumnNumber() - 1;

    // Fix position in Node where some (internal) code is prepended.
    // See https://github.com/evanw/node-source-map-support/issues/36
    if (line === 1 && !isInBrowser() && !frame.isEval()) {
      column -= 62;
    }

    var position = mapSourcePosition({
      source: source,
      line: line,
      column: column
    });
    frame = cloneCallSite(frame);
    frame.getFileName = function() { return position.source; };
    frame.getLineNumber = function() { return position.line; };
    frame.getColumnNumber = function() { return position.column + 1; };
    frame.getScriptNameOrSourceURL = function() { return position.source; };
    return frame;
  }

  // Code called using eval() needs special handling
  var origin = frame.isEval() && frame.getEvalOrigin();
  if (origin) {
    origin = mapEvalOrigin(origin);
    frame = cloneCallSite(frame);
    frame.getEvalOrigin = function() { return origin; };
    return frame;
  }

  // If we get here then we were unable to change the source position
  return frame;
}

// This function is part of the V8 stack trace API, for more info see:
// http://code.google.com/p/v8/wiki/JavaScriptStackTraceApi
function prepareStackTrace(error, stack) {
  if (emptyCacheBetweenOperations) {
    fileContentsCache = {};
    sourceMapCache = {};
  }

  return error + stack.map(function(frame) {
    return '\n    at ' + wrapCallSite(frame);
  }).join('');
}

// Generate position and snippet of original source with pointer
function getErrorSource(error) {
  var match = /\n    at [^(]+ \((.*):(\d+):(\d+)\)/.exec(error.stack);
  if (match) {
    var source = match[1];
    var line = +match[2];
    var column = +match[3];

    // Support the inline sourceContents inside the source map
    var contents = fileContentsCache[source];

    // Support files on disk
    if (!contents && fs.existsSync(source)) {
      contents = fs.readFileSync(source, 'utf8');
    }

    // Format the line from the original source code like node does
    if (contents) {
      var code = contents.split(/(?:\r\n|\r|\n)/)[line - 1];
      if (code) {
        return source + ':' + line + '\n' + code + '\n' +
          new Array(column).join(' ') + '^';
      }
    }
  }
  return null;
}

function printErrorAndExit (error) {
  var source = getErrorSource(error);

  if (source) {
    console.error();
    console.error(source);
  }

  console.error(error.stack);
  process.exit(1);
}

function shimEmitUncaughtException () {
  var origEmit = process.emit;

  process.emit = function (type) {
    if (type === 'uncaughtException') {
      var hasStack = (arguments[1] && arguments[1].stack);
      var hasListeners = (this.listeners(type).length > 0);

      if (hasStack && !hasListeners) {
        return printErrorAndExit(arguments[1]);
      }
    }

    return origEmit.apply(this, arguments);
  };
}

exports.wrapCallSite = wrapCallSite;
exports.getErrorSource = getErrorSource;
exports.mapSourcePosition = mapSourcePosition;
exports.retrieveSourceMap = retrieveSourceMap;

exports.install = function(options) {
  options = options || {};

  if (options.environment) {
    environment = options.environment;
    if (["node", "browser", "auto"].indexOf(environment) === -1) {
      throw new Error("environment " + environment + " was unknown. Available options are {auto, browser, node}")
    }
  }

  // Allow sources to be found by methods other than reading the files
  // directly from disk.
  if (options.retrieveFile) {
    if (options.overrideRetrieveFile) {
      retrieveFileHandlers.length = 0;
    }

    retrieveFileHandlers.unshift(options.retrieveFile);
  }

  // Allow source maps to be found by methods other than reading the files
  // directly from disk.
  if (options.retrieveSourceMap) {
    if (options.overrideRetrieveSourceMap) {
      retrieveMapHandlers.length = 0;
    }

    retrieveMapHandlers.unshift(options.retrieveSourceMap);
  }

  // Configure options
  if (!emptyCacheBetweenOperations) {
    emptyCacheBetweenOperations = 'emptyCacheBetweenOperations' in options ?
      options.emptyCacheBetweenOperations : false;
  }

  // Install the error reformatter
  if (!errorFormatterInstalled) {
    errorFormatterInstalled = true;
    Error.prepareStackTrace = prepareStackTrace;
  }

  if (!uncaughtShimInstalled) {
    var installHandler = 'handleUncaughtExceptions' in options ?
      options.handleUncaughtExceptions : true;

    // Provide the option to not install the uncaught exception handler. This is
    // to support other uncaught exception handlers (in test frameworks, for
    // example). If this handler is not installed and there are no other uncaught
    // exception handlers, uncaught exceptions will be caught by node's built-in
    // exception handler and the process will still be terminated. However, the
    // generated JavaScript code will be shown above the stack trace instead of
    // the original source code.
    if (installHandler && hasGlobalProcessEventEmitter()) {
      uncaughtShimInstalled = true;
      shimEmitUncaughtException();
    }
  }
};
<commit_msg>Defensive coding to prevent out-of-range column<commit_after>var SourceMapConsumer = require('source-map').SourceMapConsumer;
var path = require('path');
var fs = require('fs');

// Only install once if called multiple times
var errorFormatterInstalled = false;
var uncaughtShimInstalled = false;

// If true, the caches are reset before a stack trace formatting operation
var emptyCacheBetweenOperations = false;

// Supports {browser, node, auto}
var environment = "auto";

// Maps a file path to a string containing the file contents
var fileContentsCache = {};

// Maps a file path to a source map for that file
var sourceMapCache = {};

// Regex for detecting source maps
var reSourceMap = /^data:application\/json[^,]+base64,/;

// Priority list of retrieve handlers
var retrieveFileHandlers = [];
var retrieveMapHandlers = [];

function isInBrowser() {
  if (environment === "browser")
    return true;
  if (environment === "node")
    return false;
  return ((typeof window !== 'undefined') && (typeof XMLHttpRequest === 'function'));
}

function hasGlobalProcessEventEmitter() {
  return ((typeof process === 'object') && (process !== null) && (typeof process.on === 'function'));
}

function handlerExec(list) {
  return function(arg) {
    for (var i = 0; i < list.length; i++) {
      var ret = list[i](arg);
      if (ret) {
        return ret;
      }
    }
    return null;
  };
}

var retrieveFile = handlerExec(retrieveFileHandlers);

retrieveFileHandlers.push(function(path) {
  // Trim the path to make sure there is no extra whitespace.
  path = path.trim();
  if (path in fileContentsCache) {
    return fileContentsCache[path];
  }

  try {
    // Use SJAX if we are in the browser
    if (isInBrowser()) {
      var xhr = new XMLHttpRequest();
      xhr.open('GET', path, false);
      xhr.send(null);
      var contents = null
      if (xhr.readyState === 4 && xhr.status === 200) {
        contents = xhr.responseText
      }
    }

    // Otherwise, use the filesystem
    else {
      var contents = fs.readFileSync(path, 'utf8');
    }
  } catch (e) {
    var contents = null;
  }

  return fileContentsCache[path] = contents;
});

// Support URLs relative to a directory, but be careful about a protocol prefix
// in case we are in the browser (i.e. directories may start with "http://")
function supportRelativeURL(file, url) {
  if (!file) return url;
  var dir = path.dirname(file);
  var match = /^\w+:\/\/[^\/]*/.exec(dir);
  var protocol = match ? match[0] : '';
  return protocol + path.resolve(dir.slice(protocol.length), url);
}

function retrieveSourceMapURL(source) {
  var fileData;

  if (isInBrowser()) {
    var xhr = new XMLHttpRequest();
    xhr.open('GET', source, false);
    xhr.send(null);
    fileData = xhr.readyState === 4 ? xhr.responseText : null;

    // Support providing a sourceMappingURL via the SourceMap header
    var sourceMapHeader = xhr.getResponseHeader("SourceMap") ||
                          xhr.getResponseHeader("X-SourceMap");
    if (sourceMapHeader) {
      return sourceMapHeader;
    }
  }

  // Get the URL of the source map
  fileData = retrieveFile(source);
  //        //# sourceMappingURL=foo.js.map                       /*# sourceMappingURL=foo.js.map */
  var re = /(?:\/\/[@#][ \t]+sourceMappingURL=([^\s'"]+?)[ \t]*$)|(?:\/\*[@#][ \t]+sourceMappingURL=([^\*]+?)[ \t]*(?:\*\/)[ \t]*$)/mg;
  // Keep executing the search to find the *last* sourceMappingURL to avoid
  // picking up sourceMappingURLs from comments, strings, etc.
  var lastMatch, match;
  while (match = re.exec(fileData)) lastMatch = match;
  if (!lastMatch) return null;
  return lastMatch[1];
};

// Can be overridden by the retrieveSourceMap option to install. Takes a
// generated source filename; returns a {map, optional url} object, or null if
// there is no source map.  The map field may be either a string or the parsed
// JSON object (ie, it must be a valid argument to the SourceMapConsumer
// constructor).
var retrieveSourceMap = handlerExec(retrieveMapHandlers);
retrieveMapHandlers.push(function(source) {
  var sourceMappingURL = retrieveSourceMapURL(source);
  if (!sourceMappingURL) return null;

  // Read the contents of the source map
  var sourceMapData;
  if (reSourceMap.test(sourceMappingURL)) {
    // Support source map URL as a data url
    var rawData = sourceMappingURL.slice(sourceMappingURL.indexOf(',') + 1);
    sourceMapData = new Buffer(rawData, "base64").toString();
    sourceMappingURL = null;
  } else {
    // Support source map URLs relative to the source URL
    sourceMappingURL = supportRelativeURL(source, sourceMappingURL);
    sourceMapData = retrieveFile(sourceMappingURL);
  }

  if (!sourceMapData) {
    return null;
  }

  return {
    url: sourceMappingURL,
    map: sourceMapData
  };
});

function mapSourcePosition(position) {
  var sourceMap = sourceMapCache[position.source];
  if (!sourceMap) {
    // Call the (overrideable) retrieveSourceMap function to get the source map.
    var urlAndMap = retrieveSourceMap(position.source);
    if (urlAndMap) {
      sourceMap = sourceMapCache[position.source] = {
        url: urlAndMap.url,
        map: new SourceMapConsumer(urlAndMap.map)
      };

      // Load all sources stored inline with the source map into the file cache
      // to pretend like they are already loaded. They may not exist on disk.
      if (sourceMap.map.sourcesContent) {
        sourceMap.map.sources.forEach(function(source, i) {
          var contents = sourceMap.map.sourcesContent[i];
          if (contents) {
            var url = supportRelativeURL(sourceMap.url, source);
            fileContentsCache[url] = contents;
          }
        });
      }
    } else {
      sourceMap = sourceMapCache[position.source] = {
        url: null,
        map: null
      };
    }
  }

  // Resolve the source URL relative to the URL of the source map
  if (sourceMap && sourceMap.map) {
    var originalPosition = sourceMap.map.originalPositionFor(position);

    // Only return the original position if a matching line was found. If no
    // matching line is found then we return position instead, which will cause
    // the stack trace to print the path and line for the compiled file. It is
    // better to give a precise location in the compiled file than a vague
    // location in the original file.
    if (originalPosition.source !== null) {
      originalPosition.source = supportRelativeURL(
        sourceMap.url, originalPosition.source);
      return originalPosition;
    }
  }

  return position;
}

// Parses code generated by FormatEvalOrigin(), a function inside V8:
// https://code.google.com/p/v8/source/browse/trunk/src/messages.js
function mapEvalOrigin(origin) {
  // Most eval() calls are in this format
  var match = /^eval at ([^(]+) \((.+):(\d+):(\d+)\)$/.exec(origin);
  if (match) {
    var position = mapSourcePosition({
      source: match[2],
      line: match[3],
      column: match[4] - 1
    });
    return 'eval at ' + match[1] + ' (' + position.source + ':' +
      position.line + ':' + (position.column + 1) + ')';
  }

  // Parse nested eval() calls using recursion
  match = /^eval at ([^(]+) \((.+)\)$/.exec(origin);
  if (match) {
    return 'eval at ' + match[1] + ' (' + mapEvalOrigin(match[2]) + ')';
  }

  // Make sure we still return useful information if we didn't find anything
  return origin;
}

// This is copied almost verbatim from the V8 source code at
// https://code.google.com/p/v8/source/browse/trunk/src/messages.js. The
// implementation of wrapCallSite() used to just forward to the actual source
// code of CallSite.prototype.toString but unfortunately a new release of V8
// did something to the prototype chain and broke the shim. The only fix I
// could find was copy/paste.
function CallSiteToString() {
  var fileName;
  var fileLocation = "";
  if (this.isNative()) {
    fileLocation = "native";
  } else {
    fileName = this.getScriptNameOrSourceURL();
    if (!fileName && this.isEval()) {
      fileLocation = this.getEvalOrigin();
      fileLocation += ", ";  // Expecting source position to follow.
    }

    if (fileName) {
      fileLocation += fileName;
    } else {
      // Source code does not originate from a file and is not native, but we
      // can still get the source position inside the source string, e.g. in
      // an eval string.
      fileLocation += "<anonymous>";
    }
    var lineNumber = this.getLineNumber();
    if (lineNumber != null) {
      fileLocation += ":" + lineNumber;
      var columnNumber = this.getColumnNumber();
      if (columnNumber) {
        fileLocation += ":" + columnNumber;
      }
    }
  }

  var line = "";
  var functionName = this.getFunctionName();
  var addSuffix = true;
  var isConstructor = this.isConstructor();
  var isMethodCall = !(this.isToplevel() || isConstructor);
  if (isMethodCall) {
    var typeName = this.getTypeName();
    var methodName = this.getMethodName();
    if (functionName) {
      if (typeName && functionName.indexOf(typeName) != 0) {
        line += typeName + ".";
      }
      line += functionName;
      if (methodName && functionName.indexOf("." + methodName) != functionName.length - methodName.length - 1) {
        line += " [as " + methodName + "]";
      }
    } else {
      line += typeName + "." + (methodName || "<anonymous>");
    }
  } else if (isConstructor) {
    line += "new " + (functionName || "<anonymous>");
  } else if (functionName) {
    line += functionName;
  } else {
    line += fileLocation;
    addSuffix = false;
  }
  if (addSuffix) {
    line += " (" + fileLocation + ")";
  }
  return line;
}

function cloneCallSite(frame) {
  var object = {};
  Object.getOwnPropertyNames(Object.getPrototypeOf(frame)).forEach(function(name) {
    object[name] = /^(?:is|get)/.test(name) ? function() { return frame[name].call(frame); } : frame[name];
  });
  object.toString = CallSiteToString;
  return object;
}

function wrapCallSite(frame) {
  // Most call sites will return the source file from getFileName(), but code
  // passed to eval() ending in "//# sourceURL=..." will return the source file
  // from getScriptNameOrSourceURL() instead
  var source = frame.getFileName() || frame.getScriptNameOrSourceURL();
  if (source) {
    var line = frame.getLineNumber();
    var column = frame.getColumnNumber() - 1;

    // Fix position in Node where some (internal) code is prepended.
    // See https://github.com/evanw/node-source-map-support/issues/36
    var headerLength = 62;
    if (line === 1 && column > headerLength && !isInBrowser() && !frame.isEval()) {
      column -= headerLength;
    }

    var position = mapSourcePosition({
      source: source,
      line: line,
      column: column
    });
    frame = cloneCallSite(frame);
    frame.getFileName = function() { return position.source; };
    frame.getLineNumber = function() { return position.line; };
    frame.getColumnNumber = function() { return position.column + 1; };
    frame.getScriptNameOrSourceURL = function() { return position.source; };
    return frame;
  }

  // Code called using eval() needs special handling
  var origin = frame.isEval() && frame.getEvalOrigin();
  if (origin) {
    origin = mapEvalOrigin(origin);
    frame = cloneCallSite(frame);
    frame.getEvalOrigin = function() { return origin; };
    return frame;
  }

  // If we get here then we were unable to change the source position
  return frame;
}

// This function is part of the V8 stack trace API, for more info see:
// http://code.google.com/p/v8/wiki/JavaScriptStackTraceApi
function prepareStackTrace(error, stack) {
  if (emptyCacheBetweenOperations) {
    fileContentsCache = {};
    sourceMapCache = {};
  }

  return error + stack.map(function(frame) {
    return '\n    at ' + wrapCallSite(frame);
  }).join('');
}

// Generate position and snippet of original source with pointer
function getErrorSource(error) {
  var match = /\n    at [^(]+ \((.*):(\d+):(\d+)\)/.exec(error.stack);
  if (match) {
    var source = match[1];
    var line = +match[2];
    var column = +match[3];

    // Support the inline sourceContents inside the source map
    var contents = fileContentsCache[source];

    // Support files on disk
    if (!contents && fs.existsSync(source)) {
      contents = fs.readFileSync(source, 'utf8');
    }

    // Format the line from the original source code like node does
    if (contents) {
      var code = contents.split(/(?:\r\n|\r|\n)/)[line - 1];
      if (code) {
        return source + ':' + line + '\n' + code + '\n' +
          new Array(column).join(' ') + '^';
      }
    }
  }
  return null;
}

function printErrorAndExit (error) {
  var source = getErrorSource(error);

  if (source) {
    console.error();
    console.error(source);
  }

  console.error(error.stack);
  process.exit(1);
}

function shimEmitUncaughtException () {
  var origEmit = process.emit;

  process.emit = function (type) {
    if (type === 'uncaughtException') {
      var hasStack = (arguments[1] && arguments[1].stack);
      var hasListeners = (this.listeners(type).length > 0);

      if (hasStack && !hasListeners) {
        return printErrorAndExit(arguments[1]);
      }
    }

    return origEmit.apply(this, arguments);
  };
}

exports.wrapCallSite = wrapCallSite;
exports.getErrorSource = getErrorSource;
exports.mapSourcePosition = mapSourcePosition;
exports.retrieveSourceMap = retrieveSourceMap;

exports.install = function(options) {
  options = options || {};

  if (options.environment) {
    environment = options.environment;
    if (["node", "browser", "auto"].indexOf(environment) === -1) {
      throw new Error("environment " + environment + " was unknown. Available options are {auto, browser, node}")
    }
  }

  // Allow sources to be found by methods other than reading the files
  // directly from disk.
  if (options.retrieveFile) {
    if (options.overrideRetrieveFile) {
      retrieveFileHandlers.length = 0;
    }

    retrieveFileHandlers.unshift(options.retrieveFile);
  }

  // Allow source maps to be found by methods other than reading the files
  // directly from disk.
  if (options.retrieveSourceMap) {
    if (options.overrideRetrieveSourceMap) {
      retrieveMapHandlers.length = 0;
    }

    retrieveMapHandlers.unshift(options.retrieveSourceMap);
  }

  // Configure options
  if (!emptyCacheBetweenOperations) {
    emptyCacheBetweenOperations = 'emptyCacheBetweenOperations' in options ?
      options.emptyCacheBetweenOperations : false;
  }

  // Install the error reformatter
  if (!errorFormatterInstalled) {
    errorFormatterInstalled = true;
    Error.prepareStackTrace = prepareStackTrace;
  }

  if (!uncaughtShimInstalled) {
    var installHandler = 'handleUncaughtExceptions' in options ?
      options.handleUncaughtExceptions : true;

    // Provide the option to not install the uncaught exception handler. This is
    // to support other uncaught exception handlers (in test frameworks, for
    // example). If this handler is not installed and there are no other uncaught
    // exception handlers, uncaught exceptions will be caught by node's built-in
    // exception handler and the process will still be terminated. However, the
    // generated JavaScript code will be shown above the stack trace instead of
    // the original source code.
    if (installHandler && hasGlobalProcessEventEmitter()) {
      uncaughtShimInstalled = true;
      shimEmitUncaughtException();
    }
  }
};
<|endoftext|>


<commit_before>var canvas = document.getElementById("canvas"),
	context = canvas.getContext("2d");

// Lets draw the circle
context.beginPath();  // start the path
context.arc(230,90,50,0,Math.PI*2,false); // Draw the circle
context.closePath();
context.fill(); // fill the path

// Circle parameters
// context.arc(x, y, radius, startAngle, endAngle, anticlockwise);
// NOTE: the angles are in radians and not degrees
<commit_msg>Added arcTo function<commit_after>var canvas = document.getElementById("canvas"),
	context = canvas.getContext("2d");

// Lets draw the circle
context.beginPath();  // start the path
context.arc(230,90,50,0,Math.PI*2,false); // Draw the circle
context.closePath();
context.fill(); // fill the path

// Circle parameters
// context.arc(x, y, radius, startAngle, endAngle, anticlockwise);
// NOTE: the angles are in radians and not degrees

// Lets draw some arc

context.moveTo(300,20);		// create a starting point
context.lineTo(400,20);		// create a horizontal line
context.arcTo(450,20,450,90,20); // create an arc to the right of the line
context.lineTo(450,120);	// continue a vertical line
context.stroke();

<|endoftext|>


<commit_before>var page = browser.extension.getBackgroundPage();

//Show an alert and then fade out
function toggleAlert(alert) {
    alert.style.display = "block";
    setTimeout(function() {
        alert.classList.add("fadeOut");
    }, 800);
    setTimeout(function() {
        alert.style.display = "none";
        alert.classList.remove("fadeOut");
    }, 1700);

}

/*
    Sidebar Logic
*/
//Switchs the sidebar
function sideBarSwitch(event) {
    var element = event.target;
    if(element.tagName == "SPAN") {
        element = element.parentElement;
    }
    //console.log(element);
    if(sideBarTabToContentMap.has(element)) {
        sideBarTabToContentMap.forEach(function(value, key, map) {
            if(element == key) {
                key.classList.add("pure-menu-selected");
                value.style.display = 'block';
            } else {
                key.classList.remove("pure-menu-selected");
                value.style.display = 'none';
            }
        });
    }
}

//Map that stores the tab to the corresponding content
var sideBarTabToContentMap = new Map();
sideBarTabToContentMap.set(document.getElementById("tabWelcome"), document.getElementById("welcomeContent"));
sideBarTabToContentMap.set(document.getElementById("tabSettings"), document.getElementById("historySettingsContent"));
sideBarTabToContentMap.set(document.getElementById("tabURLList"), document.getElementById("listOfURLSContent"));
sideBarTabToContentMap.set(document.getElementById("tabAbout"), document.getElementById("aboutContent"));

//Set a click event for each tab in the Map
sideBarTabToContentMap.forEach(function(value, key, map) {
    key.addEventListener("click", sideBarSwitch);
});
document.getElementById("tabWelcome").click();

/*
    Welcome Logic
*/

page.storeCounterToLocal();
document.getElementById("sessionDeleted").textContent = page.historyDeletedCounter;
document.getElementById("totalDeleted").textContent = page.historyDeletedCounterTotal;

/*
    History Settings Logic
*/
//Setting the values from local storage
function restoreSettingValues() {
    browser.storage.local.get()
    .then(function(items) {
        document.getElementById("dayInput").value = items.daysToKeep;
        document.getElementById("keepHistorySwitch").checked = items.keepHistorySetting;
		document.getElementById("statLoggingSwitch").checked = items.statLoggingSetting;
    });
}
//Saving the values to local storage
function saveSettingsValues() {
    browser.storage.local.set({daysToKeep: document.getElementById("dayInput").value});

    if(document.getElementById("keepHistorySwitch").checked) {
        browser.storage.local.set({keepHistorySetting: true});
        page.createOldHistoryAlarm();
    } else {
        browser.storage.local.set({keepHistorySetting: false});
        page.deleteOldHistoryAlarm();
    }

    browser.storage.local.set({statLoggingSetting: document.getElementById("statLoggingSwitch").checked});

}

restoreSettingValues();

//Event handlers for the buttons
document.getElementById("saveSettings").addEventListener("click", function() {
    saveSettingsValues();
    toggleAlert(document.getElementById("saveConfirm"));
});

document.getElementById("cancelSettings").addEventListener("click", function() {
    restoreSettingValues();
    toggleAlert(document.getElementById("cancelConfirm"));
});

document.getElementById("manualCleanup").addEventListener("click", function() {
    page.deleteOldHistory();
    toggleAlert(document.getElementById("cleanupConfirm"));
});

document.getElementById("resetCounter").addEventListener("click", function() {
    page.resetCounter();
    toggleAlert(document.getElementById("resetCounterConfirm"));
});

/*
    List of URLS Logic
*/
//Remove the url where the user clicked
function clickRemoved(event) {
    if(event.target.classList.contains("removeIcon")) {
        //console.log(event.target.parentElement.textContent);
        page.removeURL(event.target.parentElement.textContent);
		generateTableOfURLS();
    }
}

//Add URL by keyboard input
function addURLFromInput() {
    var input = document.getElementById("URLForm").value;
    if(input) {
        var URL = "http://www." + input;
        page.addURL(page.getHostname(URL));
        document.getElementById("URLForm").value = "";
        document.getElementById("URLForm").focus();
        generateTableOfURLS();
    }
}

//Export the list of URLS as a text file
function downloadTextFile(arr) {
    var txt = "";
    arr.forEach(function(row) {
        txt += row;
        txt += "\n";
    });

    //console.log(csv);
    var hiddenElement = document.createElement('a');
    hiddenElement.href = 'data:text/plain;charset=utf-8,' + encodeURIComponent(txt);
    hiddenElement.target = '_blank';
    hiddenElement.download = 'urls.txt';
    document.body.appendChild(hiddenElement);
    hiddenElement.click();
    document.body.removeChild(hiddenElement);
}

//Generate the url table
function generateTableOfURLS() {
    var tableContainerNode = document.getElementById('tableContainer');
    while (tableContainerNode.firstChild) {
        tableContainerNode.removeChild(tableContainerNode.firstChild);
    }
    browser.storage.local.get("URLS")
	.then(function (result) {
        var array = result.URLS;
        var arrayLength = array.length;
        var theTable = document.createElement('table');

        for (var i = 0, tr, td; i < arrayLength; i++) {
            tr = document.createElement('tr');
            td = document.createElement('td');
            var removeButton =  new Image();
            removeButton.classList.add("removeIcon");
            removeButton.src = '../icons/close-circle.png';
            removeButton.addEventListener("click", clickRemoved);
            td.appendChild(removeButton);
            td.appendChild(document.createTextNode(array[i]));
            tr.appendChild(td);
            theTable.appendChild(tr);
        }

        document.getElementById('tableContainer').appendChild(theTable);
    });
}

generateTableOfURLS();

//Event handler for the Remove All button
document.getElementById("clear").addEventListener("click", function() {
    page.clearURL();
    generateTableOfURLS();
});

//Event handler for the user entering a URL through a form
document.getElementById("add").addEventListener("click", addURLFromInput);

//Event handler when the user press "Enter" on a keyboard on the URL Form
document.getElementById("URLForm").addEventListener("keypress", function (e) {
    var key = e.which || e.keyCode;
    if (key === 13) {
      addURLFromInput();
    }
});

//Exports urls to a text file
document.getElementById("exportURLS").addEventListener("click", function() {
    browser.storage.local.get("URLS")
	.then(function(items) {
        downloadTextFile(items.URLS);
    });
});

//Import URLS by text
document.getElementById("importURLS").onchange = function() {
	var file = this.files[0];

	var reader = new FileReader();
	reader.onload = function(progressEvent){
	// Entire file
	//console.log(this.result);

	// By lines
	var lines = this.result.split('\n');
	for(var line = 0; line < lines.length; line++){
	  //console.log(lines[line]);
	  if(lines[line] != "") {
	  	page.addURL(lines[line]);
	  }
	}
	generateTableOfURLS();
	};
	reader.readAsText(file);
};

<commit_msg>Settings URL Table Improvements<commit_after>var page = browser.extension.getBackgroundPage();

//Show an alert and then fade out
function toggleAlert(alert) {
    alert.style.display = "block";
    setTimeout(function() {
        alert.classList.add("fadeOut");
    }, 800);
    setTimeout(function() {
        alert.style.display = "none";
        alert.classList.remove("fadeOut");
    }, 1700);

}

/*
    Sidebar Logic
*/
//Switchs the sidebar
function sideBarSwitch(event) {
    var element = event.target;
    if(element.tagName == "SPAN") {
        element = element.parentElement;
    }
    //console.log(element);
    if(sideBarTabToContentMap.has(element)) {
        sideBarTabToContentMap.forEach(function(value, key, map) {
            if(element == key) {
                key.classList.add("pure-menu-selected");
                value.style.display = 'block';
            } else {
                key.classList.remove("pure-menu-selected");
                value.style.display = 'none';
            }
        });
    }
}

//Map that stores the tab to the corresponding content
var sideBarTabToContentMap = new Map();
sideBarTabToContentMap.set(document.getElementById("tabWelcome"), document.getElementById("welcomeContent"));
sideBarTabToContentMap.set(document.getElementById("tabSettings"), document.getElementById("historySettingsContent"));
sideBarTabToContentMap.set(document.getElementById("tabURLList"), document.getElementById("listOfURLSContent"));
sideBarTabToContentMap.set(document.getElementById("tabAbout"), document.getElementById("aboutContent"));

//Set a click event for each tab in the Map
sideBarTabToContentMap.forEach(function(value, key, map) {
    key.addEventListener("click", sideBarSwitch);
});
document.getElementById("tabWelcome").click();

/*
    Welcome Logic
*/

page.storeCounterToLocal();
document.getElementById("sessionDeleted").textContent = page.historyDeletedCounter;
document.getElementById("totalDeleted").textContent = page.historyDeletedCounterTotal;

/*
    History Settings Logic
*/
//Setting the values from local storage
function restoreSettingValues() {
    browser.storage.local.get()
    .then(function(items) {
        document.getElementById("dayInput").value = items.daysToKeep;
        document.getElementById("keepHistorySwitch").checked = items.keepHistorySetting;
		document.getElementById("statLoggingSwitch").checked = items.statLoggingSetting;
    });
}
//Saving the values to local storage
function saveSettingsValues() {
    browser.storage.local.set({daysToKeep: document.getElementById("dayInput").value});

    if(document.getElementById("keepHistorySwitch").checked) {
        browser.storage.local.set({keepHistorySetting: true});
        page.createOldHistoryAlarm();
    } else {
        browser.storage.local.set({keepHistorySetting: false});
        page.deleteOldHistoryAlarm();
    }

    browser.storage.local.set({statLoggingSetting: document.getElementById("statLoggingSwitch").checked});

}

restoreSettingValues();

//Event handlers for the buttons
document.getElementById("saveSettings").addEventListener("click", function() {
    saveSettingsValues();
    toggleAlert(document.getElementById("saveConfirm"));
});

document.getElementById("cancelSettings").addEventListener("click", function() {
    restoreSettingValues();
    toggleAlert(document.getElementById("cancelConfirm"));
});

document.getElementById("manualCleanup").addEventListener("click", function() {
    page.deleteOldHistory();
    toggleAlert(document.getElementById("cleanupConfirm"));
});

document.getElementById("resetCounter").addEventListener("click", function() {
    page.resetCounter();
    toggleAlert(document.getElementById("resetCounterConfirm"));
});

/*
    List of URLS Logic
*/
//Remove the url where the user clicked
function clickRemoved(event) {
    if(event.target.classList.contains("removeIcon")) {
        //console.log(event.target.parentElement.textContent);
        page.removeURL(event.target.parentElement.textContent);
		generateTableOfURLS();
    }
}

//Add URL by keyboard input
function addURLFromInput() {
    var input = document.getElementById("URLForm").value;
    if(input) {
        var URL = "http://www." + input;
        page.addURL(page.getHostname(URL));
        document.getElementById("URLForm").value = "";
        document.getElementById("URLForm").focus();
        generateTableOfURLS();
    }
}

//Export the list of URLS as a text file
function downloadTextFile(arr) {
    var txt = "";
    arr.forEach(function(row) {
        txt += row;
        txt += "\n";
    });

    //console.log(csv);
    var hiddenElement = document.createElement('a');
    hiddenElement.href = 'data:text/plain;charset=utf-8,' + encodeURIComponent(txt);
    hiddenElement.target = '_blank';
    hiddenElement.download = 'urls.txt';
    document.body.appendChild(hiddenElement);
    hiddenElement.click();
    document.body.removeChild(hiddenElement);
}

//Generate the url table
function generateTableOfURLS() {
    var tableContainerNode = document.getElementById('tableContainer');
	/*
    while (tableContainerNode.firstChild) {
        tableContainerNode.removeChild(tableContainerNode.firstChild);
    }
	*/
    browser.storage.local.get("URLS")
	.then(function (result) {
        var array = result.URLS;
        var arrayLength = array.length;
        var theTable = document.createElement('table');

        for (var i = 0, tr, td; i < arrayLength; i++) {
            tr = document.createElement('tr');
            td = document.createElement('td');
            var removeButton =  new Image();
            removeButton.classList.add("removeIcon");
            removeButton.src = '../icons/close-circle.png';
            removeButton.addEventListener("click", clickRemoved);
            td.appendChild(removeButton);
            td.appendChild(document.createTextNode(array[i]));
            tr.appendChild(td);
            theTable.appendChild(tr);
        }
		if(document.getElementById('tableContainer').hasChildNodes()) {
			document.getElementById('tableContainer').firstChild.replaceWith(theTable);
		} else {
			document.getElementById('tableContainer').appendChild(theTable);
		}

    });
}

generateTableOfURLS();

//Event handler for the Remove All button
document.getElementById("clear").addEventListener("click", function() {
    page.clearURL();
    generateTableOfURLS();
});

//Event handler for the user entering a URL through a form
document.getElementById("add").addEventListener("click", addURLFromInput);

//Event handler when the user press "Enter" on a keyboard on the URL Form
document.getElementById("URLForm").addEventListener("keypress", function (e) {
    var key = e.which || e.keyCode;
    if (key === 13) {
      addURLFromInput();
    }
});

//Exports urls to a text file
document.getElementById("exportURLS").addEventListener("click", function() {
    browser.storage.local.get("URLS")
	.then(function(items) {
        downloadTextFile(items.URLS);
    });
});

//Import URLS by text
document.getElementById("importURLS").onchange = function() {
	var file = this.files[0];

	var reader = new FileReader();
	reader.onload = function(progressEvent){
	// Entire file
	//console.log(this.result);

	// By lines
	var lines = this.result.split('\n');
	for(var line = 0; line < lines.length; line++){
	  //console.log(lines[line]);
	  if(lines[line] != "") {
	  	page.addURL(lines[line]);
	  }
	}
	generateTableOfURLS();
	};
	reader.readAsText(file);
};

<|endoftext|>


<commit_before>/**
 * Created by kawika on 5/4/17.
 */
angular.module('kApp').controller('ContactCtrl',
    function ($scope, $http) {

        $scope.user = {};

        //TODO: better alert
        $scope.sendMessage = function () {
            var response;
            var notEnoughData = false;

            if ($scope.user.name == null) {
                response = "Please enter a name!";
                notEnoughData = true;
            } else if ($scope.user.email == null) {
                response = "Please enter an email so that we can respond back to you!";
                notEnoughData = true;
            } else if ($scope.user.message == null) {
                response = "Please enter a message!";
                notEnoughData = true;
            } else {
                $http({
                    method  : 'POST',
                    url     : 'https://script.google.com/macros/s/AKfycbwkeLccwlvni45Wfmb3qGBvSf94imDeqF68E7qpGduX-glZV25d/exec',
                    data    : $scope.user,
                    headers : {'Content-Type': 'application/x-www-form-urlencoded'}
                }).success(
                    function(data) {
                        $scope.user = {};
                        response = data.message;
                        alert(response);
                    }
                );
            }

            if (notEnoughData) {
                alert(response);
            }

        }
    }
);<commit_msg>need to clean up script related stuff; like emaisl<commit_after>/**
 * Created by kawika on 5/4/17.
 */
angular.module('kApp').controller('ContactCtrl',
    function ($scope, $http) {

        $scope.user = {};

        //TODO: format google script in kawika.kasper increment version for reference:
        //TODO: https://github.com/dwyl/html-form-send-email-via-google-script-without-server
        //TODO: better alert
        $scope.sendMessage = function () {
            var response;
            var notEnoughData = false;

            if ($scope.user.name == null) {
                response = "Please enter a name!";
                notEnoughData = true;
            } else if ($scope.user.email == null) {
                response = "Please enter an email so that we can respond back to you!";
                notEnoughData = true;
            } else if ($scope.user.message == null) {
                response = "Please enter a message!";
                notEnoughData = true;
            } else {
                $http({
                    method  : 'POST',
                    url     : 'https://script.google.com/macros/s/AKfycbwkeLccwlvni45Wfmb3qGBvSf94imDeqF68E7qpGduX-glZV25d/exec',
                    data    : $scope.user,
                    headers : {'Content-Type': 'application/x-www-form-urlencoded'}
                }).success(
                    function() {
                        response = "Message sent! We will respond to " + $scope.user.email + " as soon as possible!";
                        $scope.user = {};
                        alert(response);
                    }
                );
            }

            if (notEnoughData) {
                alert(response);
            }

        }
    }
);<|endoftext|>