<commit_before>'use strict';

var STU_CANTEEN = process.env.STU_CANTEEN || '';
var STU_CANTEEN_NAME = process.env.STU_CANTEEN_NAME || '';
var ZOMATO_CANTEEN = process.env.ZOMATO_CANTEEN || '';
var ZOMATO_CANTEEN_NAME = process.env.ZOMATO_CANTEEN_NAME || '';
var ZOMATO_B_CANTEEN = process.env.ZOMATO_B_CANTEEN || '';
var ZOMATO_B_CANTEEN_NAME = process.env.ZOMATO_B_CANTEEN_NAME || '';
var ZOMATO_C_CANTEEN = process.env.ZOMATO_C_CANTEEN || '';
var ZOMATO_C_CANTEEN_NAME = process.env.ZOMATO_C_CANTEEN_NAME || '';
var HIPCHAT_ROOM = process.env.HIPCHAT_ROOM || '';
var HIPCHAT_API_KEY = process.env.HIPCHAT_API_KEY || '';

var jsdom = require('jsdom');
var HipChatClient = require('hipchat-client');
var hipchat = new HipChatClient(HIPCHAT_API_KEY);

var filterMessage = function(message, from, to) {
    var msgs = [];
    if (from && to) {
        var index = 0;
        var mayPush = false;
        var lines = message.split('\n');
        lines.forEach(function(line){
            line = line.trim();
            if (line && line !== 'AltJedlo') {
                if (index > 0) {
                    if (line.indexOf(from) > -1) {
                        mayPush = true;
                    }

                    if (line.indexOf(to) > -1) {
                        mayPush = false;
                    }

                    if (mayPush) {
                        msgs.push(line);
                    }
                }
                index++;
            }
        });
    }
    else {
        var ms = message.split('\n');
        ms.forEach(function(m){
            if (m.trim() !== '') {
                msgs.push(m.trim());
            }
        });
    }

    return msgs;
};

var sendMessage = function(canteenName, message, from, to){

    var messages = filterMessage(message, from, to);

    var string = '
';
    messages.forEach(function(line){
        string += '
';
        string += line;
        string += '
';
    });
    string += '
';

    console.log(messages);
    hipchat.api.rooms.message({
        room_id: HIPCHAT_ROOM,
        from: canteenName,
        color: 'gray',
        message: string,
        notify: 1
    }, function (err, res) {
        if (err) {
            console.log(err);
        }
        console.log(res, string);
    });
};

var fetchMenu = function(cb){
    var date = new Date();
    var CANTEEN_WEBPAGE = 'https://www.jedalen.stuba.sk/webkredit/Tisk/ObjednavaniJidlenicek.aspx?dateFrom=' + date.toISOString().split('T')[0] + '&dateTo=' + date.toISOString().split('T')[0] + '&canteen=' + STU_CANTEEN;
    console.log(CANTEEN_WEBPAGE);

    jsdom.env(
        CANTEEN_WEBPAGE,
        ['http://code.jquery.com/jquery.js'],
        function (err, window) {
            var text = window.$('center').text();
            console.log(text);
            return cb(err, text);
        }
    );
};

var fetchMenuZomato = function(zomato_id, cb){
    var CANTEEN_WEBPAGE = 'https://www.zomato.com/bratislava/' + zomato_id + '/menu#daily';
    console.log(CANTEEN_WEBPAGE);

    jsdom.env(
        CANTEEN_WEBPAGE,
        ['http://code.jquery.com/jquery.js'],
        function (err, window) {
            var text = window.$('.tmi-group').text();
            console.log(text);
            return cb(err, text);
        }
    );
};

var breakfastNotification = require('cron').CronJob;
new breakfastNotification('0 0 7 * * *', function(){
    fetchMenu(function(err, text){
        sendMessage(STU_CANTEEN_NAME, text, 'Raňajky', 'Obed');
    });
}, null, true, 'Europe/Bratislava');

var lunchNotification = require('cron').CronJob;
new lunchNotification('0 0 11 * * *', function(){
    fetchMenu(function(err, text){
        sendMessage(STU_CANTEEN_NAME, text, 'Obed', 'Večera');
    });

    if (ZOMATO_CANTEEN) {
        fetchMenuZomato(ZOMATO_CANTEEN, function(err, text){
            sendMessage(ZOMATO_CANTEEN_NAME, text);
        });
    }

    if (ZOMATO_B_CANTEEN) {
        fetchMenuZomato(ZOMATO_B_CANTEEN, function(err, text){
            sendMessage(ZOMATO_B_CANTEEN_NAME, text);
        });
    }

    if (ZOMATO_C_CANTEEN) {
        fetchMenuZomato(ZOMATO_C_CANTEEN, function(err, text){
            sendMessage(ZOMATO_C_CANTEEN_NAME, text);
        });
    }
}, null, true, 'Europe/Bratislava');

var dinnerNotification = require('cron').CronJob;
new dinnerNotification('0 0 16 * * *', function(){
    fetchMenu(function(err, text){
        sendMessage(STU_CANTEEN_NAME, text, 'Večera', 'KONIEC');
    });
}, null, true, 'Europe/Bratislava');
<commit_msg>Optional HipChat<commit_after>'use strict';

var STU_CANTEEN = process.env.STU_CANTEEN || '';
var STU_CANTEEN_NAME = process.env.STU_CANTEEN_NAME || '';
var ZOMATO_CANTEEN = process.env.ZOMATO_CANTEEN || '';
var ZOMATO_CANTEEN_NAME = process.env.ZOMATO_CANTEEN_NAME || '';
var ZOMATO_B_CANTEEN = process.env.ZOMATO_B_CANTEEN || '';
var ZOMATO_B_CANTEEN_NAME = process.env.ZOMATO_B_CANTEEN_NAME || '';
var ZOMATO_C_CANTEEN = process.env.ZOMATO_C_CANTEEN || '';
var ZOMATO_C_CANTEEN_NAME = process.env.ZOMATO_C_CANTEEN_NAME || '';
var HIPCHAT_ROOM = process.env.HIPCHAT_ROOM || '';
var HIPCHAT_API_KEY = process.env.HIPCHAT_API_KEY;

var jsdom = require('jsdom');
var HipChatClient = require('hipchat-client');
if (HIPCHAT_API_KEY) {
    var hipchat = new HipChatClient(HIPCHAT_API_KEY);
}

var filterMessage = function(message, from, to) {
    var msgs = [];
    if (from && to) {
        var index = 0;
        var mayPush = false;
        var lines = message.split('\n');
        lines.forEach(function(line){
            line = line.trim();
            if (line && line !== 'AltJedlo') {
                if (index > 0) {
                    if (line.indexOf(from) > -1) {
                        mayPush = true;
                    }

                    if (line.indexOf(to) > -1) {
                        mayPush = false;
                    }

                    if (mayPush) {
                        msgs.push(line);
                    }
                }
                index++;
            }
        });
    }
    else {
        var ms = message.split('\n');
        ms.forEach(function(m){
            if (m.trim() !== '') {
                msgs.push(m.trim());
            }
        });
    }

    return msgs;
};

var sendMessage = function(canteenName, message, from, to){
    var messages = filterMessage(message, from, to);
    console.log(messages);

    if (hipchat) {
        sendMessageHipChat(canteenName, message, from, to)
    }
};

var sendMessageHipChat = function(canteenName, message, from, to){
    var string = '
';
    messages.forEach(function(line){
        string += '
';
        string += line;
        string += '
';
    });
    string += '
';

    hipchat.api.rooms.message({
        room_id: HIPCHAT_ROOM,
        from: canteenName,
        color: 'gray',
        message: string,
        notify: 1
    }, function (err, res) {
        if (err) {
            console.log(err);
        }
        console.log(res, string);
    });
};

var fetchMenu = function(cb){
    var date = new Date();
    var CANTEEN_WEBPAGE = 'https://www.jedalen.stuba.sk/webkredit/Tisk/ObjednavaniJidlenicek.aspx?dateFrom=' + date.toISOString().split('T')[0] + '&dateTo=' + date.toISOString().split('T')[0] + '&canteen=' + STU_CANTEEN;
    console.log(CANTEEN_WEBPAGE);

    jsdom.env(
        CANTEEN_WEBPAGE,
        ['http://code.jquery.com/jquery.js'],
        function (err, window) {
            var text = window.$('center').text();
            console.log(text);
            return cb(err, text);
        }
    );
};

var fetchMenuZomato = function(zomato_id, cb){
    var CANTEEN_WEBPAGE = 'https://www.zomato.com/bratislava/' + zomato_id + '/menu#daily';
    console.log(CANTEEN_WEBPAGE);

    jsdom.env(
        CANTEEN_WEBPAGE,
        ['http://code.jquery.com/jquery.js'],
        function (err, window) {
            var text = window.$('.tmi-group').text();
            console.log(text);
            return cb(err, text);
        }
    );
};

var breakfastNotification = require('cron').CronJob;
new breakfastNotification('0 0 7 * * *', function(){
    fetchMenu(function(err, text){
        sendMessage(STU_CANTEEN_NAME, text, 'Raňajky', 'Obed');
    });
}, null, true, 'Europe/Bratislava');

var lunchNotification = require('cron').CronJob;
new lunchNotification('0 0 11 * * *', function(){
    fetchMenu(function(err, text){
        sendMessage(STU_CANTEEN_NAME, text, 'Obed', 'Večera');
    });

    if (ZOMATO_CANTEEN) {
        fetchMenuZomato(ZOMATO_CANTEEN, function(err, text){
            sendMessage(ZOMATO_CANTEEN_NAME, text);
        });
    }

    if (ZOMATO_B_CANTEEN) {
        fetchMenuZomato(ZOMATO_B_CANTEEN, function(err, text){
            sendMessage(ZOMATO_B_CANTEEN_NAME, text);
        });
    }

    if (ZOMATO_C_CANTEEN) {
        fetchMenuZomato(ZOMATO_C_CANTEEN, function(err, text){
            sendMessage(ZOMATO_C_CANTEEN_NAME, text);
        });
    }
}, null, true, 'Europe/Bratislava');

var dinnerNotification = require('cron').CronJob;
new dinnerNotification('0 0 16 * * *', function(){
    fetchMenu(function(err, text){
        sendMessage(STU_CANTEEN_NAME, text, 'Večera', 'KONIEC');
    });
}, null, true, 'Europe/Bratislava');
<|endoftext|>


<commit_before>/**
 * Create a console logger w/ formatting, timestamp, color, namespace
 *
 * Licensed under MIT.
 * Copyright (c) 2013 David Smith <https://github.com/codeactual/>
 */

/*jshint node:true*/
'use strict';

module.exports = {
  create: create,
  NodeConsole: NodeConsole,
  mixin: mixin,
  requireComponent: require, // For tests and to load other component-land files
  requireNative: null // Normally set by index.js
};

var clc; // cli-color
var sprintf;

var configurable = require('configurable.js');
var extend  = require('extend');
var tea = require('tea-properties');
var getProp = tea.get;
var setProp = tea.set;

function create() {
  return new NodeConsole();
}

function NodeConsole() {
  this.settings = {
    namespace: '', // Prepend to each message
    quiet: false,
    time: true, // Prepend toUTCString()
    traceIndent: '    ', // Represent a trace level
    traceLanes: true // Prepend each traceIndent with '|'
  };

  this.traceDepth = 0;
  this.firstLine = true;

  var requireNative = module.exports.requireNative;
  clc = clc || requireNative('cli-color');
  sprintf = sprintf || requireNative('util').format;
}

configurable(NodeConsole.prototype);

/**
 * util.format() wrapper with timestamp and injected output function.
 * Respects --quiet. Applies color selection.
 *
 * @param {string} name Source logger's name, ex. 'stderr'
 * @param {function} fn Ex. console.log
 * @param {string} color cli-color selection, ex. 'red.bold' or 'yellow'
 * @param {boolean} colorBody Apply color to log body in addition to name
 * @param {mixed} args* For util.format()
 */
NodeConsole.prototype.log = function(name, fn, color, colorBody) {
  if (this.get('quiet')) { return; }
  var colorFn = color ? getProp(clc, color) : defColorFn;
  var bodyColorFn = colorBody ? colorFn : defColorFn;
  var namespace = this.get('namespace');
  var indent = '';

  // Apply trace levels to indentation if push() and pop() were used.
  var traceIndent = this.get('traceIndent');
  var laneCx = traceIndent.length;
  indent = (new Array(this.traceDepth + 1)).join(traceIndent);
  if (this.get('traceLanes')) { // Prepend '|' to  every traceIndent section
    indent = indent.replace(new RegExp('.{1,' + laneCx + '}', 'g'), '|$&');
  }

  var sections = [
    indent,
    this.get('time') ? '[' + (new Date()).toUTCString() + '] ' : '',
    namespace ? namespace + ' ' : '',
    name ? colorFn(name) + ' ' : '',
    bodyColorFn(sprintf.apply(null, [].slice.call(arguments, 4)))
  ];
  var joined = sections.join('');

  // Ensure 1st line starts at col 0 for lane alignment
  if (this.firstLine) { joined = '\n' + joined; this.firstLine = false; }

  fn(joined);
};

/**
 * Create a log() wrapper with fixed arguments.
 *
 * @param {string} name Source logger's name, ex. 'stderr'
 * @param {function} fn Ex. console.log
 * @param {string} color cli-color selection, ex. 'red.bold' or 'yellow'
 * @param {boolean} colorBody Apply color to log body in addition to name
 * @return {function} Accepts util.format() arguments
 *   {function} push: Accepts same args. Pushes a trace level.
 *   {function} pop: Accepts same args. Pops a trace level.
 */
NodeConsole.prototype.create = function(name, fn, color, colorBody) {
  var self = this;
  function logger() {
    self.log.apply(self, [name, fn, color, colorBody].concat([].slice.call(arguments)));
  }
  logger.push = function() { logger.apply(self, arguments); self.traceDepth++; };
  logger.pop = function() {
    self.traceDepth--;
    if (arguments.length) { logger.apply(self, arguments); }
  };
  return logger;
};

/**
 * Wrap an object's methods to automatically push/pop for (sync) tracing.
 *
 * @param {string} name Uniquely identify the object
 * @param {object} obj
 * @param {function} Logger from create()
 * @param {regexp} filter Include matching key names
 * @param {regexp} omit Exclude matching key names
 */
NodeConsole.prototype.traceMethods = function(name, obj, logger, filter, omit) {
  var self = this;
  filter = filter || /.?/;
  Object.keys(obj).forEach(function(key) {
    if (typeof obj[key] !== 'function') { return; }
    if (!filter.test(key)) { return; }
    if (omit.test(key)) { return; }
    var orig = obj[key];
    obj[key] = function() {
      logger.push(name + '#' + key);
      var res = orig.apply(this, arguments);
      logger.pop();
      return res;
    };
  });
};

/**
 * Mix the given function set into NodeConsole's prototype.
 *
 * @param {object} ext
 */
function mixin(ext) {
  extend(NodeConsole.prototype, ext);
}

function defColorFn(str) { return str; }
<commit_msg>fix(tracing): Add default omit regex<commit_after>/**
 * Create a console logger w/ formatting, timestamp, color, namespace
 *
 * Licensed under MIT.
 * Copyright (c) 2013 David Smith <https://github.com/codeactual/>
 */

/*jshint node:true*/
'use strict';

module.exports = {
  create: create,
  NodeConsole: NodeConsole,
  mixin: mixin,
  requireComponent: require, // For tests and to load other component-land files
  requireNative: null // Normally set by index.js
};

var clc; // cli-color
var sprintf;

var configurable = require('configurable.js');
var extend  = require('extend');
var tea = require('tea-properties');
var getProp = tea.get;
var setProp = tea.set;

function create() {
  return new NodeConsole();
}

function NodeConsole() {
  this.settings = {
    namespace: '', // Prepend to each message
    quiet: false,
    time: true, // Prepend toUTCString()
    traceIndent: '    ', // Represent a trace level
    traceLanes: true // Prepend each traceIndent with '|'
  };

  this.traceDepth = 0;
  this.firstLine = true;

  var requireNative = module.exports.requireNative;
  clc = clc || requireNative('cli-color');
  sprintf = sprintf || requireNative('util').format;
}

configurable(NodeConsole.prototype);

/**
 * util.format() wrapper with timestamp and injected output function.
 * Respects --quiet. Applies color selection.
 *
 * @param {string} name Source logger's name, ex. 'stderr'
 * @param {function} fn Ex. console.log
 * @param {string} color cli-color selection, ex. 'red.bold' or 'yellow'
 * @param {boolean} colorBody Apply color to log body in addition to name
 * @param {mixed} args* For util.format()
 */
NodeConsole.prototype.log = function(name, fn, color, colorBody) {
  if (this.get('quiet')) { return; }
  var colorFn = color ? getProp(clc, color) : defColorFn;
  var bodyColorFn = colorBody ? colorFn : defColorFn;
  var namespace = this.get('namespace');
  var indent = '';

  // Apply trace levels to indentation if push() and pop() were used.
  var traceIndent = this.get('traceIndent');
  var laneCx = traceIndent.length;
  indent = (new Array(this.traceDepth + 1)).join(traceIndent);
  if (this.get('traceLanes')) { // Prepend '|' to  every traceIndent section
    indent = indent.replace(new RegExp('.{1,' + laneCx + '}', 'g'), '|$&');
  }

  var sections = [
    indent,
    this.get('time') ? '[' + (new Date()).toUTCString() + '] ' : '',
    namespace ? namespace + ' ' : '',
    name ? colorFn(name) + ' ' : '',
    bodyColorFn(sprintf.apply(null, [].slice.call(arguments, 4)))
  ];
  var joined = sections.join('');

  // Ensure 1st line starts at col 0 for lane alignment
  if (this.firstLine) { joined = '\n' + joined; this.firstLine = false; }

  fn(joined);
};

/**
 * Create a log() wrapper with fixed arguments.
 *
 * @param {string} name Source logger's name, ex. 'stderr'
 * @param {function} fn Ex. console.log
 * @param {string} color cli-color selection, ex. 'red.bold' or 'yellow'
 * @param {boolean} colorBody Apply color to log body in addition to name
 * @return {function} Accepts util.format() arguments
 *   {function} push: Accepts same args. Pushes a trace level.
 *   {function} pop: Accepts same args. Pops a trace level.
 */
NodeConsole.prototype.create = function(name, fn, color, colorBody) {
  var self = this;
  function logger() {
    self.log.apply(self, [name, fn, color, colorBody].concat([].slice.call(arguments)));
  }
  logger.push = function() { logger.apply(self, arguments); self.traceDepth++; };
  logger.pop = function() {
    self.traceDepth--;
    if (arguments.length) { logger.apply(self, arguments); }
  };
  return logger;
};

/**
 * Wrap an object's methods to automatically push/pop for (sync) tracing.
 *
 * @param {string} name Uniquely identify the object
 * @param {object} obj
 * @param {function} Logger from create()
 * @param {regexp} filter Include matching key names
 * @param {regexp} omit Exclude matching key names
 */
NodeConsole.prototype.traceMethods = function(name, obj, logger, filter, omit) {
  var self = this;
  filter = filter || /.?/;
  omit = omit || /a^/;
  Object.keys(obj).forEach(function(key) {
    if (typeof obj[key] !== 'function') { return; }
    if (!filter.test(key)) { return; }
    if (omit.test(key)) { return; }
    var orig = obj[key];
    obj[key] = function() {
      logger.push(name + '#' + key);
      var res = orig.apply(this, arguments);
      logger.pop();
      return res;
    };
  });
};

/**
 * Mix the given function set into NodeConsole's prototype.
 *
 * @param {object} ext
 */
function mixin(ext) {
  extend(NodeConsole.prototype, ext);
}

function defColorFn(str) { return str; }
<|endoftext|>


<commit_before>/**
 * @file 遍历和编译已有元素的孩子
 * @author errorrik(errorrik@gmail.com)
 */

var createNodeByEl = require('./create-node-by-el');

// #[begin] reverse
/**
 * 元素子节点遍历操作对象
 *
 * @inner
 * @class
 * @param {HTMLElement} el 要遍历的元素
 */
function DOMChildrenWalker(el) {
    this.raw = [];
    this.index = 0;

    var child = el.firstChild;
    while (child) {
        switch (child.nodeType) {
            case 1:
            case 8:
                this.raw.push(child);
        }

        child = child.nextSibling;
    }

    this.current = this.raw[this.index];
    this.next = this.raw[this.index + 1];
}

/**
 * 往下走一个元素
 */
DOMChildrenWalker.prototype.goNext = function () {
    this.current = this.raw[++this.index];
    this.next = this.raw[this.index + 1];
};

/**
 * 遍历和编译已有元素的孩子
 *
 * @param {HTMLElement} element 已有元素
 */
function fromElInitChildren(element) {
    var walker = new DOMChildrenWalker(element.el);
    var current;
    while ((current = walker.current)) {
        var child = createNodeByEl(current, element, walker);
        if (child && !child._static) {
            element.children.push(child);
        }

        walker.goNext();
    }
}
// #[end]

exports = module.exports = fromElInitChildren;
<commit_msg>fix #183<commit_after>/**
 * @file 遍历和编译已有元素的孩子
 * @author errorrik(errorrik@gmail.com)
 */

var createNodeByEl = require('./create-node-by-el');

// #[begin] reverse
/**
 * 元素子节点遍历操作对象
 *
 * @inner
 * @class
 * @param {HTMLElement} el 要遍历的元素
 */
function DOMChildrenWalker(el) {
    this.raw = [];
    this.index = 0;

    var child = el.firstChild;
    var next;
    while (child) {
        next = child.nextSibling;

        switch (child.nodeType) {
            case 3:
                if (/^\s*$/.test(child.data || child.textContent)) {
                    removeEl(child);
                }
                break;

            case 1:
            case 8:
                this.raw.push(child);
        }

        child = next;
    }

    this.current = this.raw[this.index];
    this.next = this.raw[this.index + 1];
}

/**
 * 往下走一个元素
 */
DOMChildrenWalker.prototype.goNext = function () {
    this.current = this.raw[++this.index];
    this.next = this.raw[this.index + 1];
};

/**
 * 遍历和编译已有元素的孩子
 *
 * @param {HTMLElement} element 已有元素
 */
function fromElInitChildren(element) {
    var walker = new DOMChildrenWalker(element.el);
    var current;
    while ((current = walker.current)) {
        var child = createNodeByEl(current, element, walker);
        if (child && !child._static) {
            element.children.push(child);
        }

        walker.goNext();
    }
}
// #[end]

exports = module.exports = fromElInitChildren;
<|endoftext|>


<commit_before>const express = require('express');
const path = require('path');
const fs = require('fs');
const pug = require('pug');
const request = require('request');
const cheerio = require('cheerio');

const app = express();

app.set('views', './views')
app.set('view engine', 'pug');
app.use(express.static(path.join(__dirname, '/')));

//
// API: /
// --------------------------------------------------------------------------
app.get('/', function(req, res) {

	// Scrape GO Transit main page
  const url = 'http://www.gotransit.com/publicroot/en/default.aspx';
  var timestamp;
  var trainsArr = [];

  // Supply formatted, scraped data to render of pug
  request(url, function(error, response, html) {
		if (!error) {
			var name, status, smallDelay, bigDelay;
			var names = [];
	    var $ = cheerio.load(html);
	    timestamp = $('.timestamp div span').html();
	    // Returns all train lines
	    var trains = $('#rtab1 .gridStatusTrain tbody tr');
	    // If empty, no trains are delayed
	    var trainsDelayed = trains.has('.delayLink');

	    for (var i = 0; i < trains.length; i++) {
	    	name = $(trains[i.toString()]).find('.gridStatusWidthOne').text();
	    	// console.log(name);

	    	// Set default status to On time
	    	status = "On time";
	    	// Check if
 contains info within one of its children
	    	smallDelay = $(trains[i.toString()]).has('.delayLink');
	    	// Check if
 has link to URL with additional info
	    	bigDelay = $(trains[i.toString()]).has('.moreInfoLink');

	    	// If
 contains an element
	    	// with either .delayLink or
	    	// .moreInfoLink, it's delayed
	    	if (smallDelay.length > 0) {
	    		status = "Delayed";

	    		// If the current retrieved train line is delayed,
	    		// find info about it
	    		var statusText, direction, details;
	    		var statusArr = [];
	    		var statusPopovers = $(trains[i.toString()]).find('.messageDisrp');

		    	for (var j = 0; j < statusPopovers.length; j++) {
		    		if ($(statusPopovers[j.toString()]).find('h3').text() === name) {
		    			// WESTBOUND or EASTBOUND
		    			direction = $(statusPopovers[j.toString()]).find('.subtitle h4').text();
		    			//
		    			details = $(statusPopovers[j.toString()]).find('li > span');

		    			for (var k = 0; k < details.length; k++) {
		    				// Iterate through known delays,
		    				// save their data to statusArr[]
		    				var detail = details[k.toString()];
		    				statusArr.push({
		    					"delayedTrain": detail.children[0].data,
		    					"delayLength": detail.children[2].data,
		    					"delayStatus": detail.children[4].data
		    				});
		    			}

		    			// Data within the . Contains up to 7 children. (As of 12/01/2016)
		    			// Counts text as an Object?
		    			// [0] = Which train time is delayed (e.x., Union Station 22:13 - Aldershot GO 23:31)
		    			// [1] =

		    			// [2] = Length of delay (e.x., Delay of 7m:53s)
		    			// [3] =

		    			// [4] = State of train (e.x., Moving)
		    			// [5] =

		    			// [6] = Additional state of train (e.x., Waiting on a train ahead)
		    		}
		    	}
	    	}
	    	else if (bigDelay.length > 0) {
	    		status = "Delayed";

	    		// If the current retrieved train line is delayed,
	    		// find info about it
	    		var statusText, details;
	    		var statusArr = [];
	    		var moreInfoURL = $(trains[i.toString()]).find('.moreInfoLink').attr('href');

	    		request(moreInfoURL, function(error, response, html) {
	    			if (!error) {
					    var $ = cheerio.load(html);
					    var content = $('.tabs_tab').prop('style');
					    console.log(content);
					    statusArr.push({
					    	"delayMsg": "Errro retrieving message"
					    })
					  }
	    		});
	    	}

	    	// Push retrieved train line info
	    	// to trains array
	    	trainsArr.push({
	    		"name": name,
	    		"status": status,
	    		"direction": direction,
	    		"details": statusArr
	    	})
	    }
    }
    res.render('index', { "retrieveTime": timestamp, "trains": trainsArr });
	});
});

//
// API: /fetch
// --------------------------------------------------------------------------
app.get('/fetch', (req, res) => {
	var url = 'http://www.gotransit.com/publicroot/en/default.aspx';
	var trainsArr = [];
	var timestamp;

	request(url, function(error, response, html) {
		if (!error) {
      var $ = cheerio.load(html);
	    timestamp = $('.timestamp div span').html();
	    // Returns all train lines
	    var trains = $('#rtab1 .gridStatusTrain tbody tr');
	    // If empty, no trains are delayed
	    var trainsDelayed = trains.has('.delayLink');

	    for (var i = 0; i < trains.length; i++) {
	    	var name = $(trains[i.toString()]).find('.gridStatusWidthOne').text();
	    	var status = $(trains[i.toString()]).has('.delayLink').length === 0 ? "On time" : "Delayed";

	    	// Push retrieved train line info
	    	// to trains array
	    	trainsArr.push({
	    		"name": name,
	    		"status": status
	    	})
	    }
    }
    res.json({"timestamp": timestamp, "trains": trainsArr});
	});
});

app.trainsAreDelayed = function() {
	var url = 'http://www.gotransit.com/publicroot/en/default.aspx';

  request(url, function(error, response, html) {
      if (!error) {
          // Next, we'll utilize the cheerio library on the returned html which will essentially give us jQuery functionality
          var $ = cheerio.load(html);
          var trains = $('.gridStatusTrain tbody tr');
          var trainsDelayed = trains.has('.delayLink');

          // If trainsDelayed.length is 0, none are delayed
          if (trainsDelayed.length === 0) {
          	return false;
          }
          else {
          	return true;
          }
      }
  });
}

app.listen(process.env.PORT || 5000);

exports = module.exports = app;<commit_msg>Add delay directional information as part of data sent to the view<commit_after>const express = require('express');
const path = require('path');
const fs = require('fs');
const pug = require('pug');
const request = require('request');
const cheerio = require('cheerio');

const app = express();

app.set('views', './views')
app.set('view engine', 'pug');
app.use(express.static(path.join(__dirname, '/')));

//
// API: /
// --------------------------------------------------------------------------
app.get('/', function(req, res) {

	// Scrape GO Transit main page
  const url = 'http://www.gotransit.com/publicroot/en/default.aspx';
  var timestamp;
  var trainsArr = [];

  // Supply formatted, scraped data to render of pug
  request(url, function(error, response, html) {
		if (!error) {
			var name, status, smallDelay, bigDelay;
			var names = [];
	    var $ = cheerio.load(html);
	    timestamp = $('.timestamp div span').html();
	    // Returns all train lines
	    var trains = $('#rtab1 .gridStatusTrain tbody tr');
	    // If empty, no trains are delayed
	    var trainsDelayed = trains.has('.delayLink');

	    for (var i = 0; i < trains.length; i++) {
	    	name = $(trains[i.toString()]).find('.gridStatusWidthOne').text();
	    	// console.log(name);

	    	// Set default status to On time
	    	status = "On time";
	    	// Check if
 contains info within one of its children
	    	smallDelay = $(trains[i.toString()]).has('.delayLink');
	    	// Check if
 has link to URL with additional info
	    	bigDelay = $(trains[i.toString()]).has('.moreInfoLink');

	    	// If
 contains an element
	    	// with either .delayLink or
	    	// .moreInfoLink, it's delayed
	    	if (smallDelay.length > 0) {
	    		status = "Delayed";

	    		// If the current retrieved train line is delayed,
	    		// find info about it
	    		var statusText, direction, details;
	    		var statusArr = [];
	    		var statusPopovers = $(trains[i.toString()]).find('.messageDisrp');

		    	for (var j = 0; j < statusPopovers.length; j++) {
		    		if ($(statusPopovers[j.toString()]).find('h3').text() === name) {
		    			direction = $(statusPopovers[j.toString()]).find('.subtitle h4').text();
		    			details = $(statusPopovers[j.toString()]).find('li > span');

		    			for (var k = 0; k < details.length; k++) {
		    				// Iterate through known delays,
		    				// save their data to statusArr[]
		    				var detail = details[k.toString()];
		    				// Data within the . Contains up to 7 children. (As of 12/01/2016)
			    			// Counts text as an Object?
			    			// [0] = Which train time is delayed (e.x., Union Station 22:13 - Aldershot GO 23:31)
			    			// [1] =

			    			// [2] = Length of delay (e.x., Delay of 7m:53s)
			    			// [3] =

			    			// [4] = State of train (e.x., Moving)
			    			// [5] =

			    			// [6] = Additional state of train (e.x., Waiting on a train ahead)
		    				statusArr.push({
		    					"delayDirection": direction,
		    					"delayedTrain": detail.children[0].data,
		    					"delayLength": detail.children[2].data,
		    					"delayStatus": detail.children[4].data
		    				});
		    			}

		    			// Data within the . Contains up to 7 children. (As of 12/01/2016)
		    			// Counts text as an Object?
		    			// [0] = Which train time is delayed (e.x., Union Station 22:13 - Aldershot GO 23:31)
		    			// [1] =

		    			// [2] = Length of delay (e.x., Delay of 7m:53s)
		    			// [3] =

		    			// [4] = State of train (e.x., Moving)
		    			// [5] =

		    			// [6] = Additional state of train (e.x., Waiting on a train ahead)
		    		}
		    	}
	    	}
	    	else if (bigDelay.length > 0) {
	    		status = "Delayed";

	    		// If the current retrieved train line is delayed,
	    		// find info about it
	    		var statusText, details;
	    		var statusArr = [];
	    		var moreInfoURL = $(trains[i.toString()]).find('.moreInfoLink').attr('href');

	    		request(moreInfoURL, function(error, response, html) {
	    			if (!error) {
					    var $ = cheerio.load(html);
					    var content = $('.tabs_tab').prop('style');
					    console.log(content);
					    statusArr.push({
					    	"delayMsg": "Errro retrieving message"
					    })
					  }
	    		});
	    	}

	    	// Push retrieved train line info
	    	// to trains array
	    	trainsArr.push({
	    		"name": name,
	    		"status": status,
	    		"direction": direction,
	    		"details": statusArr
	    	})
	    }
    }
    res.render('index', { "retrieveTime": timestamp, "trains": trainsArr });
	});
});

//
// API: /fetch
// --------------------------------------------------------------------------
app.get('/fetch', (req, res) => {
	var url = 'http://www.gotransit.com/publicroot/en/default.aspx';
	var trainsArr = [];
	var timestamp;

	request(url, function(error, response, html) {
		if (!error) {
      var $ = cheerio.load(html);
	    timestamp = $('.timestamp div span').html();
	    // Returns all train lines
	    var trains = $('#rtab1 .gridStatusTrain tbody tr');
	    // If empty, no trains are delayed
	    var trainsDelayed = trains.has('.delayLink');

	    for (var i = 0; i < trains.length; i++) {
	    	var name = $(trains[i.toString()]).find('.gridStatusWidthOne').text();
	    	var status = $(trains[i.toString()]).has('.delayLink').length === 0 ? "On time" : "Delayed";

	    	// Push retrieved train line info
	    	// to trains array
	    	trainsArr.push({
	    		"name": name,
	    		"status": status
	    	})
	    }
    }
    res.json({"timestamp": timestamp, "trains": trainsArr});
	});
});

app.trainsAreDelayed = function() {
	var url = 'http://www.gotransit.com/publicroot/en/default.aspx';

  request(url, function(error, response, html) {
      if (!error) {
          // Next, we'll utilize the cheerio library on the returned html which will essentially give us jQuery functionality
          var $ = cheerio.load(html);
          var trains = $('.gridStatusTrain tbody tr');
          var trainsDelayed = trains.has('.delayLink');

          // If trainsDelayed.length is 0, none are delayed
          if (trainsDelayed.length === 0) {
          	return false;
          }
          else {
          	return true;
          }
      }
  });
}

app.listen(process.env.PORT || 5000);

exports = module.exports = app;<|endoftext|>


<commit_before>// ==UserScript==
// @name         Pos general fixes
// @namespace    bobbilljim.com
// @version      0.1
// @description  pos reply font fix
// @author       You
// @match        forums.somethingawful.com/*
// ==/UserScript==
if (document.body.className.indexOf("forum_219") > -1)
{
    //console.log("i ran");
    var messages = document.getElementsByName("message");
    if(messages.length > 0){
        messages[0].setAttribute('style','font-family:consolas, monaco, monospace;font-size: 14px;');
    }
    GM_addStyle ("\
                 #thread dl.userinfo dt.platinum{\
    			 	background-image: url(data:image/png;base64,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);\
				 }");
    //console.log("i ran");
    if(window.location.pathname == "/forumdisplay.php"){
        GM_addStyle("#forum td.snype { background-color:red !important; text-align:center !important}");
        GM_addStyle("#forum td.almostsnype { background-color:yellow !important; text-align:center !important}");

        var repliesCells = document.getElementsByTagName("td");
        for (var i=1; i<repliesCells.length; i++) {
            if(repliesCells[i].className == "replies"){
                var str = repliesCells[i].innerHTML;

                var numReplies =  repliesCells[i].firstChild.innerHTML ;
                //console.log(str + "  " + numReplies);
                if ((numReplies ) % 40 == 39 || (numReplies ) % 40 == 38)
                {
                    //console.log(str);
                    var threadNumber = str.substring(str.indexOf("threadid=") + "threadid=".length, str.indexOf("target=") - 2);
                    //console.log(threadNumber);
                    repliesCells[i].className = ((numReplies ) % 40 == 39) ? "snype" : "almostsnype";
                    repliesCells[i].innerHTML = "" + numReplies + "" + str.substring(str.indexOf("") + 4);
                }
            }
        }
    }
}
             <commit_msg>added vine and twitter<commit_after>// ==UserScript==
// @name         SA forums shit
// @namespace    bobbilljim.com
// @version      0.3
// @description  sa forums shit
// @author       You
// @match        forums.somethingawful.com/*
// ==/UserScript==

//--------------------- functions ---------------------------------

//copied from snackoverflow because I coudln't understand twitter's version
//http://stackoverflow.com/questions/950087/include-a-javascript-file-in-another-javascript-file
function loadScript(url, callback, id)
{
    // Adding the script tag to the head as suggested before
    var head = document.getElementsByTagName('head')[0];
    var script = document.createElement('script');
    script.type = 'text/javascript';
    script.src = url;
    script.id = id;

    // Then bind the event to the callback function.
    // There are several events for cross browser compatibility.
    script.onreadystatechange = callback;
    script.onload = callback;

    // Fire the loading
    head.appendChild(script);
}

//----------------- shite ----------------------------

//if i was bothered i'd sort out all the lonks in one loop and hand them out to these funcs

//twitter integration
var twitLoaded = function() {
 	var links = document.getElementsByTagName("a");
	//find all tweet links
	for (var i=1; i < links.length; i++) {
        var ref = links[i].href;
        //console.log(ref);
        if(ref.indexOf("twitter.com") > -1 && ref.indexOf("status/") > -1){
            //get tweet id
            var id = ref.substring(ref.indexOf("status/") + 7);
            //fuck it, just slam in the link
            twttr.widgets.createTweet(id, links[i]);
        }
	}
};

loadScript("http://platform.twitter.com/widgets.js", twitLoaded, "twitscript");

//vine integration
var links = document.getElementsByTagName("a");
//find all vine links
var haveVine = false;
for (var i=1; i < links.length; i++) {
    if(links[i].href.indexOf("vine.co") > -1){
        haveVine = true;
        var vineFrame = document.createElement("iframe");
        vineFrame.class = "vine-embed";
        vineFrame.src = links[i].href + "/embed/postcard";
        vineFrame.width="320";
        vineFrame.height="400";
        vineFrame.frameborder="0"
        links[i].appendChild(document.createElement("br"));
        links[i].appendChild(vineFrame);
    }
}
if (haveVine){
    loadScript("//platform.vine.co/static/scripts/embed.js");
}

// ------------------ POS only garbage ---------------------------------
if (document.body.className.indexOf("forum_219") > -1)
{
    //console.log("i ran");
    var messages = document.getElementsByName("message");
    if(messages.length > 0){
        messages[0].setAttribute('style','font-family:consolas, monaco, monospace;font-size: 14px;');
    }
    GM_addStyle ("\
                 #thread dl.userinfo dt.platinum{\
    			 	background-image: url(data:image/png;base64,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);\
				 }");
    //console.log("i ran");
    if(window.location.pathname == "/forumdisplay.php"){
        GM_addStyle("#forum td.snype { background-color:red !important; text-align:center !important}");
        GM_addStyle("#forum td.almostsnype { background-color:yellow !important; text-align:center !important}");

        var repliesCells = document.getElementsByTagName("td");
        for (var i=1; i<repliesCells.length; i++) {
            if(repliesCells[i].className == "replies"){
                var str = repliesCells[i].innerHTML;

                var numReplies =  repliesCells[i].firstChild.innerHTML ;
                //console.log(str + "  " + numReplies);
                if ((numReplies ) % 40 == 39 || (numReplies ) % 40 == 38)
                {
                    //console.log(str);
                    var threadNumber = str.substring(str.indexOf("threadid=") + "threadid=".length, str.indexOf("target=") - 2);
                    //console.log(threadNumber);
                    repliesCells[i].className = ((numReplies ) % 40 == 39) ? "snype" : "almostsnype";
                    repliesCells[i].innerHTML = "" + numReplies + "" + str.substring(str.indexOf("") + 4);
                }
            }
        }
    }
    //cosby shit - NICE! overhaul
}
             <|endoftext|>


<commit_before>var express    = require('express');        // call express
var app        = express();                 // define our app using express
var bodyParser = require('body-parser');
var mongoose   = require('mongoose');

//User Models
var User       = require('./models/user');
mongoose.connect('mongodb://10.132.126.169/battle-api');

app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());

var port = '8080';
var private_ip = '10.132.125.55';

// ROUTES FOR OUR API
// =============================================================================
var router = express.Router();              // get an instance of the express Router

router.get('/', function(req, res, next) {
    res.end("Hello, World!!!");
});

router.route('/users')
    .post(function(req, res) {
        var user = new User();
        user.name = req.body.name;

        user.save(function(err) {
            if (err) res.send(err);

            res.json({ message: 'User created!' });
        })
    })
    .get(function(req,res) {
        User.find(function(err,users) {
          if(err) req.send(err);
          res.send(users);
        })
      });

// REGISTER OUR ROUTES -------------------------------
// all of our routes will be prefixed with /api
app.use('/api', router);

// START THE SERVER
// =============================================================================
app.listen(port);
console.log('Server started on port ' + port);
<commit_msg>ip changes for production test<commit_after>var express    = require('express');        // call express
var app        = express();                 // define our app using express
var bodyParser = require('body-parser');
var mongoose   = require('mongoose');

//User Models
var User       = require('./models/user');
mongoose.connect('mongodb://10.132.126.169/battle-api');

app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());

var port = '8080';
var private_ip = '10.132.125.55';

// ROUTES FOR OUR API
// =============================================================================
var router = express.Router();              // get an instance of the express Router

router.get('/', function(req, res, next) {
  console.log('hitting home');
    res.end("Hello, World!!!");
});

router.route('/users')
    .post(function(req, res) {
        var user = new User();
        user.name = req.body.name;

        user.save(function(err) {
            if (err) res.send(err);

            res.json({ message: 'User created!' });
        })
    })
    .get(function(req,res) {
        User.find(function(err,users) {
          if(err) req.send(err);
          res.send(users);
        })
      });

// REGISTER OUR ROUTES -------------------------------
// all of our routes will be prefixed with /api
app.use('/api', router);

// START THE SERVER
// =============================================================================
app.listen(port);
console.log('Server started on port ' + port);
<|endoftext|>


<commit_before>/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

/// <reference path="../../../typings/require.d.ts" />

//@ts-check
(function () {
	'use strict';

	/**
	 * @param {NodeRequire} nodeRequire
	 * @param {typeof import('path')} path
	 * @param {typeof import('fs')} fs
	 * @param {typeof import('../common/performance')} perf
	 */
	function factory(nodeRequire, path, fs, perf) {

		/**
		 * @param {string} file
		 * @returns {Promise<boolean>}
		 */
		function exists(file) {
			return new Promise(c => fs.exists(file, c));
		}

		/**
		 * @param {string} file
		 * @returns {Promise<void>}
		 */
		function touch(file) {
			return new Promise((c, e) => { const d = new Date(); fs.utimes(file, d, d, err => err ? e(err) : c()); });
		}

		/**
		 * @param {string} dir
		 * @returns {Promise<string>}
		 */
		function mkdirp(dir) {
			return new Promise((c, e) => fs.mkdir(dir, { recursive: true }, err => (err && err.code !== 'EEXIST') ? e(err) : c(dir)));
		}

		/**
		 * @param {string} location
		 * @returns {Promise<void>}
		 */
		function rimraf(location) {
			return new Promise((c, e) => fs.rm(location, { recursive: true, force: true, maxRetries: 3 }, err => err ? e(err) : c()));
		}

		/**
		 * @param {string} file
		 * @returns {Promise<string>}
		 */
		function readFile(file) {
			return new Promise((c, e) => fs.readFile(file, 'utf8', (err, data) => err ? e(err) : c(data)));
		}

		/**
		 * @param {string} file
		 * @param {string} content
		 * @returns {Promise<void>}
		 */
		function writeFile(file, content) {
			return new Promise((c, e) => fs.writeFile(file, content, 'utf8', err => err ? e(err) : c()));
		}

		/**
		 * @param {string} userDataPath
		 * @returns {object}
		 */
		function getLanguagePackConfigurations(userDataPath) {
			const configFile = path.join(userDataPath, 'languagepacks.json');
			try {
				return nodeRequire(configFile);
			} catch (err) {
				// Do nothing. If we can't read the file we have no
				// language pack config.
			}
			return undefined;
		}

		/**
		 * @param {object} config
		 * @param {string} locale
		 */
		function resolveLanguagePackLocale(config, locale) {
			try {
				while (locale) {
					if (config[locale]) {
						return locale;
					} else {
						const index = locale.lastIndexOf('-');
						if (index > 0) {
							locale = locale.substring(0, index);
						} else {
							return undefined;
						}
					}
				}
			} catch (err) {
				console.error('Resolving language pack configuration failed.', err);
			}
			return undefined;
		}

		/**
		 * @param {string} commit
		 * @param {string} userDataPath
		 * @param {string} metaDataFile
		 * @param {string} locale
		 */
		function getNLSConfiguration(commit, userDataPath, metaDataFile, locale) {
			if (locale === 'pseudo') {
				return Promise.resolve({ locale: locale, availableLanguages: {}, pseudo: true });
			}

			if (process.env['VSCODE_DEV']) {
				return Promise.resolve({ locale: locale, availableLanguages: {} });
			}

			// We have a built version so we have extracted nls file. Try to find
			// the right file to use.

			// Check if we have an English or English US locale. If so fall to default since that is our
			// English translation (we don't ship *.nls.en.json files)
			if (locale && (locale === 'en' || locale === 'en-us')) {
				return Promise.resolve({ locale: locale, availableLanguages: {} });
			}

			const initialLocale = locale;

			perf.mark('code/willGenerateNls');

			const defaultResult = function (locale) {
				perf.mark('code/didGenerateNls');
				return Promise.resolve({ locale: locale, availableLanguages: {} });
			};
			try {
				if (!commit) {
					return defaultResult(initialLocale);
				}
				const configs = getLanguagePackConfigurations(userDataPath);
				if (!configs) {
					return defaultResult(initialLocale);
				}
				locale = resolveLanguagePackLocale(configs, locale);
				if (!locale) {
					return defaultResult(initialLocale);
				}
				const packConfig = configs[locale];
				let mainPack;
				if (!packConfig || typeof packConfig.hash !== 'string' || !packConfig.translations || typeof (mainPack = packConfig.translations['vscode']) !== 'string') {
					return defaultResult(initialLocale);
				}
				return exists(mainPack).then(fileExists => {
					if (!fileExists) {
						return defaultResult(initialLocale);
					}
					const packId = packConfig.hash + '.' + locale;
					const cacheRoot = path.join(userDataPath, 'clp', packId);
					const coreLocation = path.join(cacheRoot, commit);
					const translationsConfigFile = path.join(cacheRoot, 'tcf.json');
					const corruptedFile = path.join(cacheRoot, 'corrupted.info');
					const result = {
						locale: initialLocale,
						availableLanguages: { '*': locale },
						_languagePackId: packId,
						_translationsConfigFile: translationsConfigFile,
						_cacheRoot: cacheRoot,
						_resolvedLanguagePackCoreLocation: coreLocation,
						_corruptedFile: corruptedFile
					};
					return exists(corruptedFile).then(corrupted => {
						// The nls cache directory is corrupted.
						let toDelete;
						if (corrupted) {
							toDelete = rimraf(cacheRoot);
						} else {
							toDelete = Promise.resolve(undefined);
						}
						return toDelete.then(() => {
							return exists(coreLocation).then(fileExists => {
								if (fileExists) {
									// We don't wait for this. No big harm if we can't touch
									touch(coreLocation).catch(() => { });
									perf.mark('code/didGenerateNls');
									return result;
								}
								return mkdirp(coreLocation).then(() => {
									return Promise.all([readFile(metaDataFile), readFile(mainPack)]);
								}).then(values => {
									const metadata = JSON.parse(values[0]);
									const packData = JSON.parse(values[1]).contents;
									const bundles = Object.keys(metadata.bundles);
									const writes = [];
									for (const bundle of bundles) {
										const modules = metadata.bundles[bundle];
										const target = Object.create(null);
										for (const module of modules) {
											const keys = metadata.keys[module];
											const defaultMessages = metadata.messages[module];
											const translations = packData[module];
											let targetStrings;
											if (translations) {
												targetStrings = [];
												for (let i = 0; i < keys.length; i++) {
													const elem = keys[i];
													const key = typeof elem === 'string' ? elem : elem.key;
													let translatedMessage = translations[key];
													if (translatedMessage === undefined) {
														translatedMessage = defaultMessages[i];
													}
													targetStrings.push(translatedMessage);
												}
											} else {
												targetStrings = defaultMessages;
											}
											target[module] = targetStrings;
										}
										writes.push(writeFile(path.join(coreLocation, bundle.replace(/\//g, '!') + '.nls.json'), JSON.stringify(target)));
									}
									writes.push(writeFile(translationsConfigFile, JSON.stringify(packConfig.translations)));
									return Promise.all(writes);
								}).then(() => {
									perf.mark('code/didGenerateNls');
									return result;
								}).catch(err => {
									console.error('Generating translation files failed.', err);
									return defaultResult(locale);
								});
							});
						});
					});
				});
			} catch (err) {
				console.error('Generating translation files failed.', err);
				return defaultResult(locale);
			}
		}

		return {
			getNLSConfiguration
		};
	}

	if (typeof define === 'function') {
		// amd
		define(['require', 'path', 'fs', 'vs/base/common/performance'], function (require, /** @type {typeof import('path')} */ path, /** @type {typeof import('fs')} */ fs, /** @type {typeof import('../common/performance')} */ perf) { return factory(require.__$__nodeRequire, path, fs, perf); });
	} else if (typeof module === 'object' && typeof module.exports === 'object') {
		const path = require('path');
		const fs = require('fs');
		const perf = require('../common/performance');
		module.exports = factory(require, path, fs, perf);
	} else {
		throw new Error('Unknown context');
	}
}());
<commit_msg>Avoid sync require for loading NLS configuration (fix #159894) (#159895)<commit_after>/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

/// <reference path="../../../typings/require.d.ts" />

//@ts-check
(function () {
	'use strict';

	/**
	 * @param {NodeRequire} nodeRequire
	 * @param {typeof import('path')} path
	 * @param {typeof import('fs')} fs
	 * @param {typeof import('../common/performance')} perf
	 */
	function factory(nodeRequire, path, fs, perf) {

		/**
		 * @param {string} file
		 * @returns {Promise<boolean>}
		 */
		function exists(file) {
			return new Promise(c => fs.exists(file, c));
		}

		/**
		 * @param {string} file
		 * @returns {Promise<void>}
		 */
		function touch(file) {
			return new Promise((c, e) => { const d = new Date(); fs.utimes(file, d, d, err => err ? e(err) : c()); });
		}

		/**
		 * @param {string} dir
		 * @returns {Promise<string>}
		 */
		function mkdirp(dir) {
			return new Promise((c, e) => fs.mkdir(dir, { recursive: true }, err => (err && err.code !== 'EEXIST') ? e(err) : c(dir)));
		}

		/**
		 * @param {string} location
		 * @returns {Promise<void>}
		 */
		function rimraf(location) {
			return new Promise((c, e) => fs.rm(location, { recursive: true, force: true, maxRetries: 3 }, err => err ? e(err) : c()));
		}

		/**
		 * @param {string} file
		 * @returns {Promise<string>}
		 */
		function readFile(file) {
			return new Promise((c, e) => fs.readFile(file, 'utf8', (err, data) => err ? e(err) : c(data)));
		}

		/**
		 * @param {string} file
		 * @param {string} content
		 * @returns {Promise<void>}
		 */
		function writeFile(file, content) {
			return new Promise((c, e) => fs.writeFile(file, content, 'utf8', err => err ? e(err) : c()));
		}

		/**
		 * @param {string} userDataPath
		 * @returns {Promise<object | undefined>}
		 */
		async function getLanguagePackConfigurations(userDataPath) {
			const configFile = path.join(userDataPath, 'languagepacks.json');
			try {
				return JSON.parse(await readFile(configFile));
			} catch (err) {
				// Do nothing. If we can't read the file we have no
				// language pack config.
			}
			return undefined;
		}

		/**
		 * @param {object} config
		 * @param {string | undefined} locale
		 */
		function resolveLanguagePackLocale(config, locale) {
			try {
				while (locale) {
					if (config[locale]) {
						return locale;
					} else {
						const index = locale.lastIndexOf('-');
						if (index > 0) {
							locale = locale.substring(0, index);
						} else {
							return undefined;
						}
					}
				}
			} catch (err) {
				console.error('Resolving language pack configuration failed.', err);
			}
			return undefined;
		}

		/**
		 * @param {string} commit
		 * @param {string} userDataPath
		 * @param {string} metaDataFile
		 * @param {string | undefined} locale
		 */
		function getNLSConfiguration(commit, userDataPath, metaDataFile, locale) {
			if (locale === 'pseudo') {
				return Promise.resolve({ locale: locale, availableLanguages: {}, pseudo: true });
			}

			if (process.env['VSCODE_DEV']) {
				return Promise.resolve({ locale: locale, availableLanguages: {} });
			}

			// We have a built version so we have extracted nls file. Try to find
			// the right file to use.

			// Check if we have an English or English US locale. If so fall to default since that is our
			// English translation (we don't ship *.nls.en.json files)
			if (locale && (locale === 'en' || locale === 'en-us')) {
				return Promise.resolve({ locale: locale, availableLanguages: {} });
			}

			const initialLocale = locale;

			perf.mark('code/willGenerateNls');

			const defaultResult = function (locale) {
				perf.mark('code/didGenerateNls');
				return Promise.resolve({ locale: locale, availableLanguages: {} });
			};
			try {
				if (!commit) {
					return defaultResult(initialLocale);
				}
				return getLanguagePackConfigurations(userDataPath).then(configs => {
					if (!configs) {
						return defaultResult(initialLocale);
					}
					locale = resolveLanguagePackLocale(configs, locale);
					if (!locale) {
						return defaultResult(initialLocale);
					}
					const packConfig = configs[locale];
					let mainPack;
					if (!packConfig || typeof packConfig.hash !== 'string' || !packConfig.translations || typeof (mainPack = packConfig.translations['vscode']) !== 'string') {
						return defaultResult(initialLocale);
					}
					return exists(mainPack).then(fileExists => {
						if (!fileExists) {
							return defaultResult(initialLocale);
						}
						const packId = packConfig.hash + '.' + locale;
						const cacheRoot = path.join(userDataPath, 'clp', packId);
						const coreLocation = path.join(cacheRoot, commit);
						const translationsConfigFile = path.join(cacheRoot, 'tcf.json');
						const corruptedFile = path.join(cacheRoot, 'corrupted.info');
						const result = {
							locale: initialLocale,
							availableLanguages: { '*': locale },
							_languagePackId: packId,
							_translationsConfigFile: translationsConfigFile,
							_cacheRoot: cacheRoot,
							_resolvedLanguagePackCoreLocation: coreLocation,
							_corruptedFile: corruptedFile
						};
						return exists(corruptedFile).then(corrupted => {
							// The nls cache directory is corrupted.
							let toDelete;
							if (corrupted) {
								toDelete = rimraf(cacheRoot);
							} else {
								toDelete = Promise.resolve(undefined);
							}
							return toDelete.then(() => {
								return exists(coreLocation).then(fileExists => {
									if (fileExists) {
										// We don't wait for this. No big harm if we can't touch
										touch(coreLocation).catch(() => { });
										perf.mark('code/didGenerateNls');
										return result;
									}
									return mkdirp(coreLocation).then(() => {
										return Promise.all([readFile(metaDataFile), readFile(mainPack)]);
									}).then(values => {
										const metadata = JSON.parse(values[0]);
										const packData = JSON.parse(values[1]).contents;
										const bundles = Object.keys(metadata.bundles);
										const writes = [];
										for (const bundle of bundles) {
											const modules = metadata.bundles[bundle];
											const target = Object.create(null);
											for (const module of modules) {
												const keys = metadata.keys[module];
												const defaultMessages = metadata.messages[module];
												const translations = packData[module];
												let targetStrings;
												if (translations) {
													targetStrings = [];
													for (let i = 0; i < keys.length; i++) {
														const elem = keys[i];
														const key = typeof elem === 'string' ? elem : elem.key;
														let translatedMessage = translations[key];
														if (translatedMessage === undefined) {
															translatedMessage = defaultMessages[i];
														}
														targetStrings.push(translatedMessage);
													}
												} else {
													targetStrings = defaultMessages;
												}
												target[module] = targetStrings;
											}
											writes.push(writeFile(path.join(coreLocation, bundle.replace(/\//g, '!') + '.nls.json'), JSON.stringify(target)));
										}
										writes.push(writeFile(translationsConfigFile, JSON.stringify(packConfig.translations)));
										return Promise.all(writes);
									}).then(() => {
										perf.mark('code/didGenerateNls');
										return result;
									}).catch(err => {
										console.error('Generating translation files failed.', err);
										return defaultResult(locale);
									});
								});
							});
						});
					});
				});
			} catch (err) {
				console.error('Generating translation files failed.', err);
				return defaultResult(locale);
			}
		}

		return {
			getNLSConfiguration
		};
	}

	if (typeof define === 'function') {
		// amd
		define(['require', 'path', 'fs', 'vs/base/common/performance'], function (require, /** @type {typeof import('path')} */ path, /** @type {typeof import('fs')} */ fs, /** @type {typeof import('../common/performance')} */ perf) { return factory(require.__$__nodeRequire, path, fs, perf); });
	} else if (typeof module === 'object' && typeof module.exports === 'object') {
		const path = require('path');
		const fs = require('fs');
		const perf = require('../common/performance');
		module.exports = factory(require, path, fs, perf);
	} else {
		throw new Error('Unknown context');
	}
}());
<|endoftext|>


<commit_before>'use strict';

const debug = require('debug')('platziverse:mqtt');
const mosca = require('mosca');
const redis = require('redis');
const chalk = require('chalk');

const backend = {
  type: 'redis',
  redis,
  return_buffers: true
};

const settings = {
  port: 1883,
  backend
};

const server = new mosca.Server(settings);

server.on('ready', () => {
  console.log(`${chalk.green('[platziverse-mqtt]')} server is running`);

});<commit_msg>Añadidos manejadores de eventos<commit_after>'use strict';

const mosca = require('mosca');
const redis = require('redis');
const chalk = require('chalk');

const backend = {
  type: 'redis',
  redis,
  return_buffers: true
};

const settings = {
  port: 1883,
  backend
};

const server = new mosca.Server(settings);

server.on('ready', () => {
  console.log(`${chalk.green('[platziverse-mqtt]')} server is running`);
});

server.on('clientConnected', (client) => {
  console.log(`Client Connected: ${client.id}`);
});

server.on('clientDisconnected', (client) => {
  console.log(`Client Diconnected: ${client.id}`);
});

server.on('published', (packet, client) => {
  console.log(`Received: ${packet.topic}`);
  console.log(`Payload: ${packet.payload}`);
});

const handleFatalError = function(err) {
  console.error(`${chalk.red('[faltal error]')} ${err.message}`);
  console.error(`${err.stack}`);
  process.exit(1);
};

server.on('error', handleFatalError);
process.on('uncaughtException', handleFatalError);
process.on('unhanledRejection', handleFatalError);
<|endoftext|>


<commit_before>//
// # URL Shortener
//

require('dotenv').config()

var mongoose = require('mongoose')
var hash = require('mongoose-hash')
var express = require('express')
var app = express()
var portNum = process.env.PORT
var dbUrl = process.env.MONGOLAB_URI

// connect to the database when app starts
mongoose.connect(dbUrl)
var db = mongoose.connection

// display landing page if no input given
app.get('/', function (req, res) {
  res.sendfile('index.html')
})

// take action based on the type of input
app.get('/*', function (req, res) {
  var myInput = req.params[0]
  res.setHeader('Content-Type', 'application/json')

  // RETRIEVE A SHORTENED URL
  if (/\w{6}$/.test(myInput)) {
    res.send(JSON.stringify('code'))

  // CREATE A NEW URL ENTRY
  } else if (/^https?:\/\/\w+\.?\w+\.\w+/.test(myInput)) {
    var myUrl = new URL({original: myInput})

    myUrl.save(function (err, product) {
      if (err) {
        console.log(err)
      } else {
        console.log('successfully saved:\n' + product)
      }
    }).then(function(product) {
      console.log('at the end of then')
      res.send(JSON.stringify(product))
    })

  // DISPLAY ERROR MESSAGE WITH UNRECOGNIZED INPUT
  } else {
    res.send(JSON.stringify('ERROR - INVALID INPUT'))
  }
})
.listen(portNum)

// Create a schema for URL
var URLSchema = mongoose.Schema({
  code: String,
  original: String,
  short: { type: String, default: 'https://url-shortener-kastentx.c9.io/' }
})

// mongoose-hash plugin generates a 6-digit code for each new url
URLSchema.plugin(hash, {
  field: 'code',
  size: 3
})

// after code is assigned to a new url, add it to the shortened url (output)
URLSchema.pre('save', function(next) {
  console.log('Middleware activated for ' + this.code)
  this.short += this.code
  next()
})

// only show desired fields when JSON is displayed
URLSchema.methods.toJSON = function() {
  var obj = this.toObject()
  delete obj.code
  delete obj._id
  delete obj.__v
  return obj
}

// Model based on the schema defined above
var URL = mongoose.model('URL', URLSchema)<commit_msg>tweaking regex<commit_after>//
// # URL Shortener
//

require('dotenv').config()

var mongoose = require('mongoose')
var hash = require('mongoose-hash')
var express = require('express')
var app = express()
var portNum = process.env.PORT
var dbUrl = process.env.MONGOLAB_URI

// connect to the database when app starts
mongoose.connect(dbUrl)
var db = mongoose.connection

// display landing page if no input given
app.get('/', function (req, res) {
  res.sendfile('index.html')
})

// take action based on the type of input
app.get('/*', function (req, res) {
  var myInput = req.params[0]
  res.setHeader('Content-Type', 'application/json')

  // RETRIEVE A SHORTENED URL
  if (/\w{6}$/.test(myInput)) {
    res.send(JSON.stringify('code'))

  // CREATE A NEW URL ENTRY
  } else if (/^https?:\/\/\w+(?:[\/\-\.]?\w+)*\.\w+$/.test(myInput)) {
    var myUrl = new URL({original: myInput})

    myUrl.save(function (err, product) {
      if (err) {
        console.log(err)
      } else {
        console.log('successfully saved:\n' + product)
      }
    }).then(function(product) {
      console.log('at the end of then')
      res.send(JSON.stringify(product))
    })

  // DISPLAY ERROR MESSAGE WITH UNRECOGNIZED INPUT
  } else {
    res.send(JSON.stringify('ERROR - INVALID INPUT'))
  }
})
.listen(portNum)

// Create a schema for URL
var URLSchema = mongoose.Schema({
  code: String,
  original: String,
  short: { type: String, default: 'https://url-shortener-kastentx.c9.io/' }
})

// mongoose-hash plugin generates a 6-digit code for each new url
URLSchema.plugin(hash, {
  field: 'code',
  size: 3
})

// after code is assigned to a new url, add it to the shortened url (output)
URLSchema.pre('save', function(next) {
  console.log('Middleware activated for ' + this.code)
  this.short += this.code
  next()
})

// only show desired fields when JSON is displayed
URLSchema.methods.toJSON = function() {
  var obj = this.toObject()
  delete obj.code
  delete obj._id
  delete obj.__v
  return obj
}

// Model based on the schema defined above
var URL = mongoose.model('URL', URLSchema)<|endoftext|>


<commit_before><commit_msg>neobot_equal_with_sensor 글자색 변경<commit_after><|endoftext|>


<commit_before>(function(root) {

var _ = root._;
var errors = root.Substance.errors;
var util = root.Substance.util;
var Chronicle = root.Substance.Chronicle;

var NOP = "0";
var DEL = "-";
var INS = "+";
var MOV = ">>";

// ArrayOperations can be used to describe changes to arrays by operations.
// ========
//
// Insertions
// --------
//
// An insertion is specified by
//    {
//      type: '+',
//      val:  <value>,
//      pos:  <position>
//    }
// or shorter:
//    ['+', <value>, <position>]
//
//
// Deletions
// --------
//
// A deletion is in the same way as Insertions but with '-' as type.
//
//    ['-', <value>, <position>]
//
// The value must be specified too as otherwise the operation would not be invertible.
//
// Moves
// --------
//
// A move is specified by
//    {
//      type:    '>>',
//      pos:     <position>,
//      target:  <position>
//    }
// or shorter:
//    ['+', <from>, <to>]

var ArrayOperation = function(options) {

  // if this operation should be created using an array
  if (_.isArray(options)) {
    var tmp = {
      type: options[0]
    };

    if (tmp.type === MOV) {
      tmp.pos = options[1];
      tmp.target = options[2];
    } else {
      tmp.pos = options[1];
      tmp.val = options[2];
    }

    options = tmp;
  }

  if (options.type === undefined) {
    throw new errors.ChronicleError("Illegal argument: insufficient data.");
  }

  // Insert: '+', Delete: '-', Move: '>>'
  this.type = options.type;

  if (this.type === NOP) return;

  if (this.type === MOV) {
    if (options.pos === undefined || options.target === undefined) {
      throw new errors.ChronicleError("Illegal argument: insufficient data.");
    }
  } else {
    if (options.pos === undefined || options.val === undefined) {
      throw new errors.ChronicleError("Illegal argument: insufficient data.");
    }
  }

  // the position where to apply the operation
  this.pos = options.pos;

  // the string to delete or insert
  this.val = options.val;

  // Move operations have a target position
  this.target = options.target;

  // sanity checks
  if(this.type !== NOP && this.type !== INS && this.type !== DEL && this.type !== MOV) throw new errors.ChronicleError("Illegal type.");

  if (!_.isNumber(this.pos) && this.pos < 0) throw new errors.ChronicleError("Illegal argument: expecting positive number as pos.");

  if (this.type === MOV) {
    if (!_.isNumber(this.target) && this.target < 0) throw new errors.ChronicleError("Illegal argument: expecting positive number as target.");
  }
};

ArrayOperation.DEL = DEL;
ArrayOperation.INS = INS;
ArrayOperation.MOV = MOV;

ArrayOperation.fromJSON = function(json) {
  return new ArrayOperation(json);
};

ArrayOperation.__prototype__ = function() {

  this.isNOP = function() {
    return this.type === NOP;
  };

  this.isInsert = function() {
    return this.type === INS;
  };

  this.isDelete = function() {
    return this.type === DEL;
  };

  this.isMove = function() {
    return this.type === MOV;
  };

  this.copy = function() {
    return new ArrayOperation(this);
  };

  this.apply = function(array) {

    if (this.isNOP()) {
      // enjoy
    }

    // Insert
    else if (this.isInsert()) {
      if (array.length < this.pos) throw new errors.ChronicleError("Provided array is too small.");
      array.splice(this.pos, 0, this.val);
    }

    // Delete
    else if (this.isDelete()) {
      if (array.length < this.pos) {
        throw new errors.ChronicleError("Provided array is too small.");
      }
      if (array[this.pos] !== this.val) {
        throw new errors.ChronicleError("Unexpected value at position " + this.pos + ". Expected " + this.val + ", found " + array[this.pos]);
      }
      array.splice(this.pos, 1);
    }

    // Move
    else {
      if (array.length <= this.pos || array.length <= this.target) {
        throw new errors.ChronicleError("Provided array is too small.");
      }

      if (this.pos == this.target) return array;

      var val = array[this.pos];

      array.splice(this.pos, 1);
      array.splice(this.target, 0, val);
    }

    return array;
  };

  this.invert = function() {
    var data = this.toJSON();

    if (this.isInsert()) data.type = DEL;
    else if (this.isDelete()) data.type = INS;
    else if (this.isMove()) {
      data.pos = this.target;
      data.target = this.pos;
    }

    return new ArrayOperation(data);
  };

  this.hasConflict = function(other) {

    if (!(other instanceof ArrayOperation)) {
      throw new errors.ChronicleError("Illegal Argument.");
    }

    // Deletes and Moves of the same element are conflicts
    if ( (this.isDelete()  || this.isMove()) &&
         (other.isDelete() || other.isMove()) ) {
      return (this.pos === other.pos);
    }
    else {
      // TODO: are the others ok, i.e., Insert at same position or Moves with that target position.
      return false;
    }

  };

  this.toJSON = function() {
    var result = {
      type: this.type,
    };

    if (this.isNOP()) return result;

    result.pos = this.pos;

    if (this.isMove()) {
      result.target = this.target;
    } else {
      result.val = this.val;
    }

    return result;
  };

};
ArrayOperation.prototype = new ArrayOperation.__prototype__();

function transform_insert_insert(a, b, first) {

  if (a.pos === b.pos) {
    if (first) {
      b.pos += 1;
    } else {
      a.pos += 1;
    }
  }
  // a before b
  else if (a.pos < b.pos) {
    b.pos += 1;
  }

  // a after b
  else  {
    a.pos += 1;
  }

}

function transform_delete_delete(a, b) {

  // turn the second of two concurrent deletes into a NOP
  if (a.pos === b.pos) {
    b.type = NOP;
    a.type = NOP;
    return;
  }

  if (a.pos < b.pos) {
    b.pos -= 1;
  } else {
    a.pos -= 1;
  }

}

function transform_insert_delete(a, b) {

  // reduce to a normalized case
  if (a.type === DEL) {
    var tmp = a;
    a = b;
    b = tmp;
  }

  if (a.pos <= b.pos) {
    b.pos += 1;
  } else {
    a.pos -= 1;
  }

}

function transform_move_delete(a, b, first) {

  // reduce to a normalized case
  if (a.type === DEL) {
    return transform_move_delete(b, a, !first);
  }

  // after some struggle I decided to implement this completely test-case driven
  // you can find a test case for each case here.
  // TODO: simplify this after the behaviour is exactly as desired.

  // a before b
  if (a.pos < b.pos && a.target < b.pos) {
    // nothing to do;
  }

  // a after b
  else if (a.pos > b.pos && a.target > b.pos) {
    // nothing to transform;
    a.pos -= 1;
    a.target -= 1;
  }

  // a.s < b < a.t
  else if(a.pos < b.pos && b.pos < a.target) {
    a.target -= 1;
    b.pos -= 1;
  }

  // a.t < b < a.s
  else if(a.target < b.pos && b.pos < a.pos) {
    a.pos -= 1;
    b.pos += 1;
  }

  // a.s == b
  else if (a.pos === b.pos) {
    a.type = NOP;
    b.pos = a.target;
  }

  // a.s < b == a.t
  else if (a.pos < b.pos && b.pos === a.target) {
    a.target -= 1;
    b.pos -= 1;
  }

  // a.t == b < a.s
  else if (a.target === b.pos && b.pos < a.pos) {
    a.pos -= 1;
    a.target -= 1;
  }

}

function transform_move_insert(a, b, first) {

  // reduce to a normalized case
  if (a.type === INS) {
    return transform_move_insert(b, a, !first);
  }

  // after some struggle I decided to implement this completely test-case driven
  // you can find a test case for each case here.
  // TODO: simplify this after the behaviour is exactly as desired.

  // a before b
  if (a.pos < b.pos && a.target < b.pos) {
    // nothing to transform;
  }

  // a after b
  else if (a.pos > b.pos && a.target > b.pos) {
    // nothing to transform;
    a.pos += 1;
    a.target += 1;
  }

  // a.s < b < a.t
  else if(a.pos < b.pos && b.pos < a.target) {
    a.target += 1;
    b.pos -= 1;
  }

  // a.t < b < a.s
  else if(a.target < b.pos && b.pos < a.pos) {
    a.pos += 1;
    b.pos += 1;
  }

  // a.s == b < a.t
  else if (a.pos === b.pos && b.pos < a.target) {
    a.pos += 1;
    a.target += 1;
  }

  // a.s < b == a.t
  else if (a.pos < b.pos && b.pos === a.target) {
    a.target += 1;
    b.pos -= 1;
  }

  // a.t < b == a.s
  else if (a.target < b.pos && b.pos === a.pos) {
    a.pos += 1;
    b.pos += 1;
  }

  // a.t == b < a.s
  else if (a.target === b.pos && b.pos < a.pos) {
    a.pos += 1;
    a.target += 1;
  }

}

function transform_move_move(a, b) {

  function diff(pos, ins, del, first) {
    var res = 0;

    if (pos>ins) res++;
    if (pos>del) res--;

    return res;
  }

  var diff_a1, diff_a2, diff_b1, diff_b2;

  // edge cases that are not covered by a generic approach

  // a.s < a.t == b.s < b.t
  if (a.pos < a.target && a.target === b.pos && b.pos < b.target) {
    a.target -= 1;
    b.pos -= 1;
  }
  // symmetric case: b.s < b.t == a.s < a.t
  else if (b.pos < b.target && b.target === a.pos && a.pos < a.target) {
    a.pos -= 1;
    b.target -= 1;
  }

  // conflict case: both operations move the same element
  // if applied, the second operation is takes effect
  else if (a.pos === b.pos) {
    diff_b2 = diff(b.target, a.target, a.pos);
    b.pos = a.target;
    b.target += diff_b2;
    a.type = NOP;
  }

  else {
    diff_a1 = diff(a.pos, b.target, b.pos);
    diff_a2 = diff(a.target, b.target, b.pos);
    diff_b1 = diff(b.pos, a.target, a.pos);
    diff_b2 = diff(b.target, a.target, a.pos);

    a.pos += diff_a1;
    a.target += diff_a2;
    b.pos += diff_b1;
    b.target += diff_b2;
  }
}

var transform0 = function(a, b, options) {

  options = options || {};

  if (options.check && a.hasConflict(b)) {
    throw Chronicle.mergeConflict(a, b);
  }

  if (!options.inplace) {
    a = a.copy();
    b = b.copy();
  }

  if (a.type === NOP || b.type === NOP)  {
    // nothing to transform
  }
  else if (a.type === INS && b.type === INS)  {
    transform_insert_insert(a, b, true);
  }
  else if (a.type === DEL && b.type === DEL) {
    transform_delete_delete(a, b, true);
  }
  else if (a.type === MOV || b.type === MOV) {

    if (a.type === INS || b.type === INS) {
      transform_move_insert(a, b, true);
    }
    else if (a.type === DEL || b.type === DEL) {
      transform_move_delete(a, b, true);
    }
    else {
      transform_move_move(a, b);
    }

    if (a.type === MOV && a.pos === a.target) a.type = NOP;
    if (b.type === MOV && b.pos === b.target) b.type = NOP;

  }
  else {
    transform_insert_delete(a, b, true);
  }

  return [a, b];
};

ArrayOperation.transform = Chronicle.OT.Compound.createTransform(transform0);

// Creates a sequence of ArrayOperations by transforming the given operations
// which are supposed to be parallel (multi-branch merge)
ArrayOperation.chain = function(ops) {
  if (ops.length === 0) return ops;

  var i,j;

  transformed = [];
  for (i = 0; i < ops.length; i++) {
    transformed.push(new ArrayOperation(ops[i]));
  }

  for (j = 1; j < ops.length; j++) {
    for (i = 0; i < j; i++) {
      t = ArrayOperation.transform(transformed[i], transformed[j]);
      transformed[j] = t[1];
    }
  }

  return transformed;
}

Chronicle.OT = Chronicle.OT || {};
Chronicle.OT.ArrayOperation = ArrayOperation;

})(this);
<commit_msg>Try to handle transformations of MOV/MOV (ArrayOp) in a general way.<commit_after>(function(root) {

var _ = root._;
var errors = root.Substance.errors;
var util = root.Substance.util;
var Chronicle = root.Substance.Chronicle;

var NOP = "0";
var DEL = "-";
var INS = "+";
var MOV = ">>";

// ArrayOperations can be used to describe changes to arrays by operations.
// ========
//
// Insertions
// --------
//
// An insertion is specified by
//    {
//      type: '+',
//      val:  <value>,
//      pos:  <position>
//    }
// or shorter:
//    ['+', <value>, <position>]
//
//
// Deletions
// --------
//
// A deletion is in the same way as Insertions but with '-' as type.
//
//    ['-', <value>, <position>]
//
// The value must be specified too as otherwise the operation would not be invertible.
//
// Moves
// --------
//
// A move is specified by
//    {
//      type:    '>>',
//      pos:     <position>,
//      target:  <position>
//    }
// or shorter:
//    ['+', <from>, <to>]

var ArrayOperation = function(options) {

  // if this operation should be created using an array
  if (_.isArray(options)) {
    var tmp = {
      type: options[0]
    };

    if (tmp.type === MOV) {
      tmp.pos = options[1];
      tmp.target = options[2];
    } else {
      tmp.pos = options[1];
      tmp.val = options[2];
    }

    options = tmp;
  }

  if (options.type === undefined) {
    throw new errors.ChronicleError("Illegal argument: insufficient data.");
  }

  // Insert: '+', Delete: '-', Move: '>>'
  this.type = options.type;

  if (this.type === NOP) return;

  if (this.type === MOV) {
    if (options.pos === undefined || options.target === undefined) {
      throw new errors.ChronicleError("Illegal argument: insufficient data.");
    }
  } else {
    if (options.pos === undefined || options.val === undefined) {
      throw new errors.ChronicleError("Illegal argument: insufficient data.");
    }
  }

  // the position where to apply the operation
  this.pos = options.pos;

  // the string to delete or insert
  this.val = options.val;

  // Move operations have a target position
  this.target = options.target;

  // sanity checks
  if(this.type !== NOP && this.type !== INS && this.type !== DEL && this.type !== MOV) throw new errors.ChronicleError("Illegal type.");

  if (!_.isNumber(this.pos) && this.pos < 0) throw new errors.ChronicleError("Illegal argument: expecting positive number as pos.");

  if (this.type === MOV) {
    if (!_.isNumber(this.target) && this.target < 0) throw new errors.ChronicleError("Illegal argument: expecting positive number as target.");
  }
};

ArrayOperation.DEL = DEL;
ArrayOperation.INS = INS;
ArrayOperation.MOV = MOV;

ArrayOperation.fromJSON = function(json) {
  return new ArrayOperation(json);
};

ArrayOperation.__prototype__ = function() {

  this.isNOP = function() {
    return this.type === NOP;
  };

  this.isInsert = function() {
    return this.type === INS;
  };

  this.isDelete = function() {
    return this.type === DEL;
  };

  this.isMove = function() {
    return this.type === MOV;
  };

  this.copy = function() {
    return new ArrayOperation(this);
  };

  this.apply = function(array) {

    if (this.isNOP()) {
      // enjoy
    }

    // Insert
    else if (this.isInsert()) {
      if (array.length < this.pos) throw new errors.ChronicleError("Provided array is too small.");
      array.splice(this.pos, 0, this.val);
    }

    // Delete
    else if (this.isDelete()) {
      if (array.length < this.pos) {
        throw new errors.ChronicleError("Provided array is too small.");
      }
      if (array[this.pos] !== this.val) {
        throw new errors.ChronicleError("Unexpected value at position " + this.pos + ". Expected " + this.val + ", found " + array[this.pos]);
      }
      array.splice(this.pos, 1);
    }

    // Move
    else {
      if (array.length <= this.pos || array.length <= this.target) {
        throw new errors.ChronicleError("Provided array is too small.");
      }

      if (this.pos == this.target) return array;

      var val = array[this.pos];

      array.splice(this.pos, 1);
      array.splice(this.target, 0, val);
    }

    return array;
  };

  this.invert = function() {
    var data = this.toJSON();

    if (this.isInsert()) data.type = DEL;
    else if (this.isDelete()) data.type = INS;
    else if (this.isMove()) {
      data.pos = this.target;
      data.target = this.pos;
    }

    return new ArrayOperation(data);
  };

  this.hasConflict = function(other) {

    if (!(other instanceof ArrayOperation)) {
      throw new errors.ChronicleError("Illegal Argument.");
    }

    // Deletes and Moves of the same element are conflicts
    if ( (this.isDelete()  || this.isMove()) &&
         (other.isDelete() || other.isMove()) ) {
      return (this.pos === other.pos);
    }
    else {
      // TODO: are the others ok, i.e., Insert at same position or Moves with that target position.
      return false;
    }

  };

  this.toJSON = function() {
    var result = {
      type: this.type,
    };

    if (this.isNOP()) return result;

    result.pos = this.pos;

    if (this.isMove()) {
      result.target = this.target;
    } else {
      result.val = this.val;
    }

    return result;
  };

};
ArrayOperation.prototype = new ArrayOperation.__prototype__();

function transform_insert_insert(a, b, first) {

  if (a.pos === b.pos) {
    if (first) {
      b.pos += 1;
    } else {
      a.pos += 1;
    }
  }
  // a before b
  else if (a.pos < b.pos) {
    b.pos += 1;
  }

  // a after b
  else  {
    a.pos += 1;
  }

}

function transform_delete_delete(a, b) {

  // turn the second of two concurrent deletes into a NOP
  if (a.pos === b.pos) {
    b.type = NOP;
    a.type = NOP;
    return;
  }

  if (a.pos < b.pos) {
    b.pos -= 1;
  } else {
    a.pos -= 1;
  }

}

function transform_insert_delete(a, b) {

  // reduce to a normalized case
  if (a.type === DEL) {
    var tmp = a;
    a = b;
    b = tmp;
  }

  if (a.pos <= b.pos) {
    b.pos += 1;
  } else {
    a.pos -= 1;
  }

}

function transform_move_delete(a, b, first) {

  // reduce to a normalized case
  if (a.type === DEL) {
    return transform_move_delete(b, a, !first);
  }

  // after some struggle I decided to implement this completely test-case driven
  // you can find a test case for each case here.
  // TODO: simplify this after the behaviour is exactly as desired.

  // a before b
  if (a.pos < b.pos && a.target < b.pos) {
    // nothing to do;
  }

  // a after b
  else if (a.pos > b.pos && a.target > b.pos) {
    // nothing to transform;
    a.pos -= 1;
    a.target -= 1;
  }

  // a.s < b < a.t
  else if(a.pos < b.pos && b.pos < a.target) {
    a.target -= 1;
    b.pos -= 1;
  }

  // a.t < b < a.s
  else if(a.target < b.pos && b.pos < a.pos) {
    a.pos -= 1;
    b.pos += 1;
  }

  // a.s == b
  else if (a.pos === b.pos) {
    a.type = NOP;
    b.pos = a.target;
  }

  // a.s < b == a.t
  else if (a.pos < b.pos && b.pos === a.target) {
    a.target -= 1;
    b.pos -= 1;
  }

  // a.t == b < a.s
  else if (a.target === b.pos && b.pos < a.pos) {
    a.pos -= 1;
    a.target -= 1;
  }

}

function transform_move_insert(a, b, first) {

  // reduce to a normalized case
  if (a.type === INS) {
    return transform_move_insert(b, a, !first);
  }

  // after some struggle I decided to implement this completely test-case driven
  // you can find a test case for each case here.
  // TODO: simplify this after the behaviour is exactly as desired.

  // a before b
  if (a.pos < b.pos && a.target < b.pos) {
    // nothing to transform;
  }

  // a after b
  else if (a.pos > b.pos && a.target > b.pos) {
    // nothing to transform;
    a.pos += 1;
    a.target += 1;
  }

  // a.s < b < a.t
  else if(a.pos < b.pos && b.pos < a.target) {
    a.target += 1;
    b.pos -= 1;
  }

  // a.t < b < a.s
  else if(a.target < b.pos && b.pos < a.pos) {
    a.pos += 1;
    b.pos += 1;
  }

  // a.s == b < a.t
  else if (a.pos === b.pos && b.pos < a.target) {
    a.pos += 1;
    a.target += 1;
  }

  // a.s < b == a.t
  else if (a.pos < b.pos && b.pos === a.target) {
    a.target += 1;
    b.pos -= 1;
  }

  // a.t < b == a.s
  else if (a.target < b.pos && b.pos === a.pos) {
    a.pos += 1;
    b.pos += 1;
  }

  // a.t == b < a.s
  else if (a.target === b.pos && b.pos < a.pos) {
    a.pos += 1;
    a.target += 1;
  }

}

// This case is reduced by treating the move as composite (deletion+insertion).
function transform_move_move(a, b) {

  var a_c = new Chronicle.OT.Compound([new ArrayOperation([DEL, a.pos, '']), new ArrayOperation([INS, a.target, '']));
  var b_c = new Chronicle.OT.Compound([new ArrayOperation([DEL, b.pos, '']), new ArrayOperation([INS, b.target, '']));
  ArrayOperation.transform(a_c, b_c, {check: false, inplace: true});

  a.pos = a_c.ops[0].pos;
  a.target = a_c.ops[1].pos;
  b.pos = b_c.ops[0].pos;
  b.target = b_c.ops[1].pos;
};

var transform0 = function(a, b, options) {

  options = options || {};

  if (options.check && a.hasConflict(b)) {
    throw Chronicle.mergeConflict(a, b);
  }

  if (!options.inplace) {
    a = a.copy();
    b = b.copy();
  }

  if (a.type === NOP || b.type === NOP)  {
    // nothing to transform
  }
  else if (a.type === INS && b.type === INS)  {
    transform_insert_insert(a, b, true);
  }
  else if (a.type === DEL && b.type === DEL) {
    transform_delete_delete(a, b, true);
  }
  else if (a.type === MOV || b.type === MOV) {

    if (a.type === INS || b.type === INS) {
      transform_move_insert(a, b, true);
    }
    else if (a.type === DEL || b.type === DEL) {
      transform_move_delete(a, b, true);
    }
    else {
      transform_move_move(a, b);
    }

    if (a.type === MOV && a.pos === a.target) a.type = NOP;
    if (b.type === MOV && b.pos === b.target) b.type = NOP;

  }
  else {
    transform_insert_delete(a, b, true);
  }

  return [a, b];
};

ArrayOperation.transform = Chronicle.OT.Compound.createTransform(transform0);

// Creates a sequence of ArrayOperations by transforming the given operations
// which are supposed to be parallel (multi-branch merge)
ArrayOperation.chain = function(ops) {
  if (ops.length === 0) return ops;

  var i,j;

  transformed = [];
  for (i = 0; i < ops.length; i++) {
    transformed.push(new ArrayOperation(ops[i]));
  }

  for (j = 1; j < ops.length; j++) {
    for (i = 0; i < j; i++) {
      t = ArrayOperation.transform(transformed[i], transformed[j]);
      transformed[j] = t[1];
    }
  }

  return transformed;
}

Chronicle.OT = Chronicle.OT || {};
Chronicle.OT.ArrayOperation = ArrayOperation;

})(this);
<|endoftext|>