<commit_before>function createfg(htmlStr) {
    var frag = document.createDocumentFragment(),
        temp = document.createElement('div');
    temp.innerHTML = htmlStr;
    while (temp.firstChild) {
        frag.appendChild(temp.firstChild);
    }
    return frag;
}
function insertHtml(title, content, type) {
    var attention = '<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve"><path id="svgico" fill="none" stroke="#FBB03B" stroke-width="8" stroke-linecap="round" stroke-miterlimit="10" d="M50,83v2 M50,14v54"/></svg>';
    var error = '<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve"><path id="svgico" fill="#FFFFFF" stroke="#C1272D" stroke-width="8" stroke-linecap="round" stroke-miterlimit="10" d="M8.8,90.7L90,9 M90,90.7 L8.8,9"/></svg>';
    var succes = '<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve"><path id="svgico" fill="#FFFFFF" stroke="#8CC63F" stroke-miterlimit="10" d="M46.6,64.3l33.7-40L47.4,75.4L24.7,56L46.6,64.3z" /></svg>';
    var svg = '';
    if (type == 'succes') {
        svg = succes;
    } else if (type == 'error') {
        svg = error;
    } else {
        svg = attention;
    }

    var htmlStr = '

' + svg + '
' + title + '

' + content + '
OK

';
    var fragment = createfg(htmlStr);

    document.body.insertBefore(fragment, document.body.childNodes[0]);
}

function insertCss(){

var cssStr="";
var fragment = createfg(cssStr);

document.body.insertBefore(fragment, document.body.childNodes[0]);
}

function animateSvg(elem ,dir , type) {
    var path = document.getElementById(elem);
    var length = path.getTotalLength();
   if (type=='succes') { path.style.strokeDashoffset = (dir)?0:170;}
   else if (type=='error') { path.style.transform='rotate(720deg)';}
   else if (type=='attention') {}
   	else{};
}

function openModal(type){
   el = document.getElementById("overlay");
     mod = document.getElementById("modalcontainer");
    el.style.visibility = (el.style.visibility == "visible") ? "hidden" : "visible";
    el.style.opacity = 1;
    mod.style.width = '450px';
    mod.style.height = '300px';
    setTimeout('document.getElementById("closeModal").style.opacity = 1; ', 500);
    setTimeout(function() {animateSvg('svgico', true,type) ;} , 400);
   // animateSvg('svgico' , true);
}

function closeModal(type){
  var el = document.getElementById("overlay");
    var  mod = document.getElementById("modalcontainer");
    mod.style.width = '400px';
    mod.style.height = '250px';
    el.style.opacity = 0;
    document.getElementById("closeModal").style.opacity = 0;
    setTimeout('el.style.visibility = (el.style.visibility == "visible") ? "hidden" : "visible";', 500);
     animateSvg('svgico' , false , type);
}

function prettytalert(title, content, type){

insertHtml(title, content, type);
	insertCss();
	setTimeout(function(){	openModal(type);
 	},400);
 	window.onload = function()
{
document.getElementById('closeModal').onclick = function (event) {
	event.preventDefault();
   closeModal(type);
}};

}

function praltimer(title, content, type, time){
insertHtml(title, content, type);
	insertCss();
	setTimeout(function(){	openModal(type);
 	},400);
	setTimeout(function(){	closeModal(type);
 	},time);
}<commit_msg>Add button customization<commit_after>function createfg(htmlStr) {
    var frag = document.createDocumentFragment(),
        temp = document.createElement('div');
    temp.innerHTML = htmlStr;
    while (temp.firstChild) {
        frag.appendChild(temp.firstChild);
    }
    return frag;
}
function insertHtml(title, content, type,btn) {
    var attention = '<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve"><path id="svgico" fill="none" stroke="#FBB03B" stroke-width="8" stroke-linecap="round" stroke-miterlimit="10" d="M50,83v2 M50,14v54"/></svg>';
    var error = '<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve"><path id="svgico" fill="#FFFFFF" stroke="#C1272D" stroke-width="8" stroke-linecap="round" stroke-miterlimit="10" d="M8.8,90.7L90,9 M90,90.7 L8.8,9"/></svg>';
    var succes = '<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 100 100" enable-background="new 0 0 100 100" xml:space="preserve"><path id="svgico" fill="#FFFFFF" stroke="#8CC63F" stroke-miterlimit="10" d="M46.6,64.3l33.7-40L47.4,75.4L24.7,56L46.6,64.3z" /></svg>';
    var svg = '';
    if (type == 'succes') {
        svg = succes;
    } else if (type == 'error') {
        svg = error;
    } else {
        svg = attention;
    }
    var button = ''+btn+'';
    var htmlStr = '

' + svg + '
' + title + '

' + content + '
OK

';
    var fragment = createfg(htmlStr);

    document.body.insertBefore(fragment, document.body.childNodes[0]);
}

function insertCss(){

var cssStr="";
var fragment = createfg(cssStr);

document.body.insertBefore(fragment, document.body.childNodes[0]);
}

function animateSvg(elem ,dir , type) {
    var path = document.getElementById(elem);
    var length = path.getTotalLength();
   if (type=='succes') { path.style.strokeDashoffset = (dir)?0:170;}
   else if (type=='error') { path.style.transform='rotate(720deg)';}
   else if (type=='attention') {}
   	else{};
}

function openModal(type){
   el = document.getElementById("overlay");
     mod = document.getElementById("modalcontainer");
    el.style.visibility = (el.style.visibility == "visible") ? "hidden" : "visible";
    el.style.opacity = 1;
    mod.style.width = '450px';
    mod.style.height = '300px';
    setTimeout('document.getElementById("closeModal").style.opacity = 1; ', 500);
    setTimeout(function() {animateSvg('svgico', true,type) ;} , 400);
   // animateSvg('svgico' , true);
}

function closeModal(type){
  var el = document.getElementById("overlay");
    var  mod = document.getElementById("modalcontainer");
    mod.style.width = '400px';
    mod.style.height = '250px';
    el.style.opacity = 0;
    document.getElementById("closeModal").style.opacity = 0;
    setTimeout('el.style.visibility = (el.style.visibility == "visible") ? "hidden" : "visible";', 500);
     animateSvg('svgico' , false , type);
}

function prettytalert(title, content, type){

insertHtml(title, content, type);
	insertCss();
	setTimeout(function(){	openModal(type);
 	},400);
 	window.onload = function()
{
document.getElementById('closeModal').onclick = function (event) {
	event.preventDefault();
   closeModal(type);
}};

}

function praltimer(title, content, type, time){
insertHtml(title, content, type);
	insertCss();
	setTimeout(function(){	openModal(type);
 	},400);
	setTimeout(function(){	closeModal(type);
 	},time);
}<|endoftext|>


<commit_before>import { WRIAPI } from 'utils/axios';

/**
 * Fetch countries
 */
export const fetchCountries = () =>
  WRIAPI.get('geostore/admin/list')
    .then(array =>
      array.data.data.sort((a, b) => {
        if (a.name < b.name) {
          return -1;
        } else if (a.name > b.name) {
          return 1;
        }
        // eslint-disable-line no-else-return
        return 0;
      }));

/**
 * Get country
 */
export const getCountry = iso =>
  WRIAPI.get(`query/134caa0a-21f7-451d-a7fe-30db31a424aa?sql=SELECT name_engli as label, st_asgeojson(the_geom_simple) as geojson, bbox as bounds from gadm28_countries WHERE iso = '${iso}'`);

/**
 * Get Geostore
 */
export const getGeostore = id => WRIAPI.get(`geostore/${id}`);

export const createGeostore = async (geojson) => {
  const response = await WRIAPI.post('geostore',
    geojson,
    { headers: { 'Content-Type': 'application/json' } })
    .catch(() => { throw new Error("The file couldn't be processed correctly. Try again in a few minutes."); });
  return response.data;
};

/**
 * Get area
 */
export const getArea = (id, token) =>
  WRIAPI.get(
    `area/${id}?application=${process.env.APPLICATIONS}&env=${process.env.API_ENV}`,
    {
      headers: {
        'Content-Type': 'application/json',
        Authorization: token,
        'Upgrade-Insecure-Requests': 1
      }
    }
  );

export default {
  getArea,
  getCountry,
  createGeostore,
  getGeostore,
  fetchCountries
};
<commit_msg>fix createGeostore endpoint<commit_after>import { WRIAPI } from 'utils/axios';

/**
 * Fetch countries
 */
export const fetchCountries = () =>
  WRIAPI.get('geostore/admin/list')
    .then(array =>
      array.data.data.sort((a, b) => {
        if (a.name < b.name) {
          return -1;
        } else if (a.name > b.name) {
          return 1;
        }
        // eslint-disable-line no-else-return
        return 0;
      }));

/**
 * Get country
 */
export const getCountry = iso =>
  WRIAPI.get(`query/134caa0a-21f7-451d-a7fe-30db31a424aa?sql=SELECT name_engli as label, st_asgeojson(the_geom_simple) as geojson, bbox as bounds from gadm28_countries WHERE iso = '${iso}'`);

/**
 * Get Geostore
 */
export const getGeostore = id => WRIAPI.get(`geostore/${id}`);

export const createGeostore = async (geojson) => {
  const response = await WRIAPI.post('geostore',
    geojson,
    { headers: { 'Content-Type': 'application/json' } })
    .catch(() => { throw new Error("The file couldn't be processed correctly. Try again in a few minutes."); });
  return response.data.data;
};

/**
 * Get area
 */
export const getArea = (id, token) =>
  WRIAPI.get(
    `area/${id}?application=${process.env.APPLICATIONS}&env=${process.env.API_ENV}`,
    {
      headers: {
        'Content-Type': 'application/json',
        Authorization: token,
        'Upgrade-Insecure-Requests': 1
      }
    }
  );

export default {
  getArea,
  getCountry,
  createGeostore,
  getGeostore,
  fetchCountries
};
<|endoftext|>


<commit_before>const event = require('../event');
const Allure = require('allure-js-commons');

const defaultConfig = {
  outputDir: global.output_dir,
};

/**
 * Allure reporter
 *
 * ![](https://user-images.githubusercontent.com/220264/45676511-8e052800-bb3a-11e8-8cbb-db5f73de2add.png)
 *
 * Enables Allure reporter.
 *
 * ##### Usage
 *
 * To start please install `allure-commandline` package (which requires Java 8)
 *
 * ```
 * npm install -g allure-commandline --save-dev
 * ```
 *
 * Add this plugin to config file:
 *
 * ```js
 * "plugins": {
 *     "allure": {}
 * }
 * ```
 *
 * Run tests with allure plugin enabled:
 *
 * ```
 * codeceptjs run --plugins allure
 * ```
 *
 * By default, allure reports are saved to `output` directory.
 * Launch Allure server and see the report like on a screenshot above:
 *
 * ```
 * allure serve output
 * ```
 *
 * ##### Configuration
 *
 * * `outputDir` - a directory where allure reports should be stored. Standard output directory is set by default.
 *
 *
 */
module.exports = (config) => {
  config = Object.assign(defaultConfig, config);

  const reporter = new Allure();
  reporter.setOptions({ targetDir: config.outputDir });

  let currentMetaStep = [];
  let currentStep;
  let isHookSteps = false;

  this.addAttachment = (name, buffer, type) => {
    reporter.addAttachment(name, buffer, type);
  };

  event.dispatcher.on(event.suite.before, (suite) => {
    reporter.startSuite(suite.fullTitle());
  });

  event.dispatcher.on(event.suite.before, (suite) => {
    for (const test of suite.tests) {
      if (test.pending) {
        reporter.pendingCase(test.title);
      }
    }
  });

  event.dispatcher.on(event.hook.started, (hook) => {
    isHookSteps = true;
  });

  event.dispatcher.on(event.hook.passed, (hook) => {
    isHookSteps = false;
  });

  event.dispatcher.on(event.suite.after, () => {
    reporter.endSuite();
  });

  event.dispatcher.on(event.test.before, (test) => {
    reporter.startCase(test.title);
    currentStep = null;
  });

  event.dispatcher.on(event.test.started, (test) => {
    const currentTest = reporter.getCurrentTest();
    for (const tag of test.tags) {
      currentTest.addLabel('tag', tag);
    }
  });

  event.dispatcher.on(event.test.failed, (test, err) => {
    if (currentStep) reporter.endStep('failed');
    if (currentMetaStep.length) {
      currentMetaStep.forEach(() => reporter.endStep('failed'));
      currentMetaStep = [];
    }
    reporter.endCase('failed', err);
  });

  event.dispatcher.on(event.test.passed, (test) => {
    if (currentStep) reporter.endStep('passed');
    if (currentMetaStep.length) {
      currentMetaStep.forEach(() => reporter.endStep('passed'));
      currentMetaStep = [];
    }
    reporter.endCase('passed');
  });

  event.dispatcher.on(event.step.started, (step) => {
    if (isHookSteps === false) {
      startMetaStep(step.metaStep);
      if (currentStep !== step) {
        // The reason we need to do this cause
        // the step actor contains this and hence
        // the allure reporter could not parse and
        // generate the report
        if (step.actor.includes('\u001b[36m')) {
          step.actor = step.actor.replace('\u001b[36m', '').replace('\u001b[39m', '');
        }
        reporter.startStep(step.toString());
        currentStep = step;
      }
    }
  });

  event.dispatcher.on(event.step.passed, (step) => {
    if (currentStep === step) {
      reporter.endStep('passed');
      currentStep = null;
    }
  });

  event.dispatcher.on(event.step.failed, (step) => {
    if (currentStep === step) {
      reporter.endStep('failed');
      currentStep = null;
    }
  });

  let maxLevel;
  function finishMetastep(level) {
    const metaStepsToFinish = currentMetaStep.splice(maxLevel - level);
    metaStepsToFinish.forEach(() => reporter.endStep('passed'));
  }

  function startMetaStep(metaStep, level = 0) {
    maxLevel = level;
    if (!metaStep) {
      finishMetastep(0);
      maxLevel--;
      return;
    }

    startMetaStep(metaStep.metaStep, level + 1);

    if (metaStep.toString() !== currentMetaStep[maxLevel - level]) {
      finishMetastep(level);
      currentMetaStep.push(metaStep.toString());
      reporter.startStep(metaStep.toString());
    }
  }

  return this;
};
<commit_msg>add method "addLabel" for allure (#1540)<commit_after>const event = require('../event');
const Allure = require('allure-js-commons');
const logger = require('../output');

const defaultConfig = {
  outputDir: global.output_dir,
};

/**
 * Allure reporter
 *
 * ![](https://user-images.githubusercontent.com/220264/45676511-8e052800-bb3a-11e8-8cbb-db5f73de2add.png)
 *
 * Enables Allure reporter.
 *
 * ##### Usage
 *
 * To start please install `allure-commandline` package (which requires Java 8)
 *
 * ```
 * npm install -g allure-commandline --save-dev
 * ```
 *
 * Add this plugin to config file:
 *
 * ```js
 * "plugins": {
 *     "allure": {}
 * }
 * ```
 *
 * Run tests with allure plugin enabled:
 *
 * ```
 * codeceptjs run --plugins allure
 * ```
 *
 * By default, allure reports are saved to `output` directory.
 * Launch Allure server and see the report like on a screenshot above:
 *
 * ```
 * allure serve output
 * ```
 *
 * ##### Configuration
 *
 * * `outputDir` - a directory where allure reports should be stored. Standard output directory is set by default.
 *
 *
 */
module.exports = (config) => {
  config = Object.assign(defaultConfig, config);

  const reporter = new Allure();
  reporter.setOptions({ targetDir: config.outputDir });

  let currentMetaStep = [];
  let currentStep;
  let isHookSteps = false;

  this.addAttachment = (name, buffer, type) => {
    reporter.addAttachment(name, buffer, type);
  };

  this.addLabel = (name, value) => {
    const currentTest = reporter.getCurrentTest();
    if (currentTest) {
      currentTest.addLabel(name, value);
    } else {
      logger.error(`The test is not run. Please use "addLabel" for events:
      "test.start", "test.before", "test.after", "test.passed", "test.failed", "test.finish"`);
    }
  };

  event.dispatcher.on(event.suite.before, (suite) => {
    reporter.startSuite(suite.fullTitle());
  });

  event.dispatcher.on(event.suite.before, (suite) => {
    for (const test of suite.tests) {
      if (test.pending) {
        reporter.pendingCase(test.title);
      }
    }
  });

  event.dispatcher.on(event.hook.started, (hook) => {
    isHookSteps = true;
  });

  event.dispatcher.on(event.hook.passed, (hook) => {
    isHookSteps = false;
  });

  event.dispatcher.on(event.suite.after, () => {
    reporter.endSuite();
  });

  event.dispatcher.on(event.test.before, (test) => {
    reporter.startCase(test.title);
    currentStep = null;
  });

  event.dispatcher.on(event.test.started, (test) => {
    const currentTest = reporter.getCurrentTest();
    for (const tag of test.tags) {
      currentTest.addLabel('tag', tag);
    }
  });

  event.dispatcher.on(event.test.failed, (test, err) => {
    if (currentStep) reporter.endStep('failed');
    if (currentMetaStep.length) {
      currentMetaStep.forEach(() => reporter.endStep('failed'));
      currentMetaStep = [];
    }
    reporter.endCase('failed', err);
  });

  event.dispatcher.on(event.test.passed, (test) => {
    if (currentStep) reporter.endStep('passed');
    if (currentMetaStep.length) {
      currentMetaStep.forEach(() => reporter.endStep('passed'));
      currentMetaStep = [];
    }
    reporter.endCase('passed');
  });

  event.dispatcher.on(event.step.started, (step) => {
    if (isHookSteps === false) {
      startMetaStep(step.metaStep);
      if (currentStep !== step) {
        // The reason we need to do this cause
        // the step actor contains this and hence
        // the allure reporter could not parse and
        // generate the report
        if (step.actor.includes('\u001b[36m')) {
          step.actor = step.actor.replace('\u001b[36m', '').replace('\u001b[39m', '');
        }
        reporter.startStep(step.toString());
        currentStep = step;
      }
    }
  });

  event.dispatcher.on(event.step.passed, (step) => {
    if (currentStep === step) {
      reporter.endStep('passed');
      currentStep = null;
    }
  });

  event.dispatcher.on(event.step.failed, (step) => {
    if (currentStep === step) {
      reporter.endStep('failed');
      currentStep = null;
    }
  });

  let maxLevel;
  function finishMetastep(level) {
    const metaStepsToFinish = currentMetaStep.splice(maxLevel - level);
    metaStepsToFinish.forEach(() => reporter.endStep('passed'));
  }

  function startMetaStep(metaStep, level = 0) {
    maxLevel = level;
    if (!metaStep) {
      finishMetastep(0);
      maxLevel--;
      return;
    }

    startMetaStep(metaStep.metaStep, level + 1);

    if (metaStep.toString() !== currentMetaStep[maxLevel - level]) {
      finishMetastep(level);
      currentMetaStep.push(metaStep.toString());
      reporter.startStep(metaStep.toString());
    }
  }

  return this;
};
<|endoftext|>


<commit_before>'use strict';

var Redis = require('ioredis'),
    nconf = require('nconf');

const prefix = 'status:'

let redis = new Redis.Cluster(nconf.get('cluster'), { redisOptions: nconf.get('options')});

exports.register = function (server, options, next) {

    // WebApi
    server.route({
        method: 'POST',
        path: '/stats',
        handler: (request, reply) => {
            let type = request.payload.type;
            let host = request.payload.host.split(':')[0];
            let port = request.payload.host.split(':')[1];

            console.log('quering: ' + prefix + host + ':' + port  + ':' + type)
            // get all the keys in the set for this server:port:type
            redis.zrangebyscore(prefix + host + ':' + port + ':' + type, '-inf', '+inf', (err, results) => {
                return reply(results.map((a) => JSON.parse(a)));
            });

        }
    });

    next();
}

exports.register.attributes = {
    'name': 'stats'
};<commit_msg>improved stats handling<commit_after>'use strict';

var Redis = require('ioredis'),
    nconf = require('nconf');

const prefix = 'status:'

let redis = new Redis.Cluster(nconf.get('cluster'), { redisOptions: nconf.get('options')});

exports.register = function (server, options, next) {

    // WebApi
    server.route({
        method: 'POST',
        path: '/stats',
        handler: (request, reply) => {
            let type = request.payload.type;
            let host = request.payload.host.split(':')[0];
            let port = request.payload.host.split(':')[1];

            // period will be set to either hourly, daily or raw... if raw, then omit this from the key lookup
            let period = request.payload.period;
            period = period == 'raw' ? period = ':' : period = ':' + period + ':';

            console.log('quering: ' + prefix + host + ':' + port + period + type);
            // get all the keys in the set for this server:port:type
            redis.zrangebyscore(prefix + host + ':' + port + period + type, '-inf', '+inf', (err, results) => {
                return reply(results.map((a) => JSON.parse(a)).map((a) => {delete a.n; return a}));
            });

        }
    });

    next();
}

exports.register.attributes = {
    'name': 'stats'
};<|endoftext|>


<commit_before>/*
 * Convert jpg to svg to gcode.
 *
 * d3000 - hello@3000d.be
 */

var path = require('path'),
  fs = require('fs'),
  root = require('../root'),
  exec = require('child_process').exec,
  osc = new (require(root.communication + '/osc')),
  util = require('util'),

  Communication = require(root.communication + '/communication'),
  GcodeConverter = require(root.process + '/GcodeConverter'),
  Watcher = require(root.common + '/Watcher');
  WebServer = require(root.web + '/web');

var drawbot = new Communication();
var gcodeConverter = new GcodeConverter({feedrate: 2});
var webServer = new WebServer(drawbot);
webServer.startServer();

var gcodeFiles = [];
var processedGcodeFiles = [];
var currentGcodeFile;

var isProcessStarted = false;

var bmpWatcher = new Watcher({
  folder: path.resolve(root.data_bmp),
  extensions: ['bmp', 'BMP']
});

var jsonWatcher = new Watcher({
  folder: path.resolve(root.data_json),
  extensions: ['json']
});

drawbot.getSerialPortList(function(ports) {
  try {
    drawbot.connect(process.argv[2] || ports[0].comName);
  } catch(e) {}

  drawbot.on('connected', function() {
  });

  //processGcodeFile();

  bmpWatcher.on('fileAdded', function(evt) {
    var fileName = evt.path.split('/');
    fileName = fileName[fileName.length-1].split('.');
    fileName = fileName[fileName.length-2];
    var jsonFileName = fileName + '.json';

    // potrace -i -b geojson -k 0.4 -t 60 -o outputXXX.json bitmapXXX.BMP

    var potrace = 'potrace -i -b geojson -k 0.4 -t 60 -o ' + (root.data_json + '/' + jsonFileName) + ' ' + evt.path;
    var compare = 'compare -metric mae ' + root.process + '/background.bmp ' + evt.path + ' ' + root.data_temp + '/diff.bmp';

    drawbot.log(compare);

    exec(compare, function(error, stdout, strerr){
      if((error && error !== 'null'))
      {
        drawbot.Log.error('compare : error : ' + error);
        return;
      }else
      {
        console.log(stdout);
        console.log(strerr);
        console.log(error);
        drawbot.Log.debug('compare says: ' + stdout);
        if(stdout.split(' ')[0] > 1250)
        {
          drawbot.Log.debug('gotit');
          exec(potrace, function(error, stdout, stderr) {
            if((error && error !== 'null') || stderr) {
              drawbot.Log.error('potrace ' + error);
              return;
            }
            //drawbot.log('-- Json file created: ' + jsonFileName);
          });
        }else
        {
          //fs.unlinkSync(evt.path);
          drawbot.Log.debug('compare : discard');
        }
      }
    });
  });

  jsonWatcher.on('fileAdded', function(evt) {
    try {
      var json = require(evt.path);
      var gcode = gcodeConverter.convert(json);

      var fileName = evt.path.split('/');
      fileName = fileName[fileName.length-1].split('.');
      fileName = fileName[fileName.length-2];
      var gcodeFileName = fileName + '.gcode';

      fs.writeFile(root.data_gcode + '/' + gcodeFileName, gcode, function(err) {
        if(err) {
          drawbot.Log.error('Could not save to gcode');
        } else {
          drawbot.Log.error('-- GCode: ' + gcodeFileName);
          gcodeFiles.push(gcodeFileName);

          if(!isProcessStarted) {
            processGcodeFile();
            isProcessStarted = true;
          }
        }
      });
    } catch(e) {
      drawbot.Log.error('could not convert json to gcode');
    }
  });

  drawbot.on('drawStarted', function() {
    drawbot.log('-- DRAW STARTED');
    osc.sendSOD();
  });

  drawbot.on('drawFinished', function() {
    drawbot.log('-- DRAW FINISHED');
    osc.sendEOD();
    processGcodeFile(true);
  });
});

var processGcodeFile = function(removeLast) {
  if(removeLast && currentGcodeFile) {
    for(var i = 0; i < gcodeFiles.length; i++) {
      if(gcodeFiles[i] === currentGcodeFile) {
        gcodeFiles.splice(i, 1);
      }
    }
    moveGcodeFile(currentGcodeFile);
  }
  var gcode, gcodeFile;
  if(gcodeFiles.length) {
    gcodeFile = gcodeFiles[gcodeFiles.length - 1];
    currentGcodeFile = gcodeFile;

    gcode = fs.readFileSync(root.data_gcode + '/' + gcodeFile, 'utf8');
    if(gcode) drawbot.Log.debug('[PROCESS] DRAW NEW : ' + gcodeFile);
  } else {
    var randIndex = Math.floor(Math.random() * processedGcodeFiles.length);
    gcodeFile = processedGcodeFiles[randIndex];
    gcode = fs.readFileSync(root.data_gcode_processed + '/' + processedGcodeFiles[randIndex]);
    currentGcodeFile = null;
    if(gcode) drawbot.Log.debug('[PROCESS] DRAW OLD : ' + gcodeFile);
  }

  if(gcode) {
    // start debug code
    //drawbot.isDrawing = true;
    //drawbot.emit('drawStarted');
    //setTimeout(function() {
    //  drawbot.isDrawing = false;
    //  drawbot.emit('drawFinished');
    //}, 5000);
    // end debug code

    drawbot.batch(gcode);
  }
};

//var getGcodeFile = function() {
//  if(!gcodeFiles.length) {
//    var gcodesInFolder = fs.readdirSync(root.data_gcode);
//    for(var i = 0; i < gcodesInFolder.length; i++) {
//      var fileName = gcodesInFolder[i].split('.');
//
//      if(fileName[fileName.length-1] === 'gcode') {
//        gcodeFiles.push(gcodesInFolder[i]);
//      }
//    }
//  }
//
//  if(gcodeFiles.length) {
//    return gcodeFiles[gcodeFiles.length - 1];
//  } else {
//    return null;
//  }
//};

var moveGcodeFile = function(gcodeFileName) {
  fs.renameSync(root.data_gcode + '/' + gcodeFileName, root.data_gcode_processed + '/' + gcodeFileName);
  processedGcodeFiles.push(gcodeFileName);
};
<commit_msg>tuning compare<commit_after>/*
 * Convert jpg to svg to gcode.
 *
 * d3000 - hello@3000d.be
 */

var path = require('path'),
  fs = require('fs'),
  root = require('../root'),
  exec = require('child_process').exec,
  osc = new (require(root.communication + '/osc')),
  util = require('util'),

  Communication = require(root.communication + '/communication'),
  GcodeConverter = require(root.process + '/GcodeConverter'),
  Watcher = require(root.common + '/Watcher');
  WebServer = require(root.web + '/web');

var drawbot = new Communication();
var gcodeConverter = new GcodeConverter({feedrate: 2});
var webServer = new WebServer(drawbot);
webServer.startServer();

var gcodeFiles = [];
var processedGcodeFiles = [];
var currentGcodeFile;

var isProcessStarted = false;

var bmpWatcher = new Watcher({
  folder: path.resolve(root.data_bmp),
  extensions: ['bmp', 'BMP']
});

var jsonWatcher = new Watcher({
  folder: path.resolve(root.data_json),
  extensions: ['json']
});

drawbot.getSerialPortList(function(ports) {
  try {
    drawbot.connect(process.argv[2] || ports[0].comName);
  } catch(e) {}

  drawbot.on('connected', function() {
  });

  //processGcodeFile();

  bmpWatcher.on('fileAdded', function(evt) {
    var fileName = evt.path.split('/');
    fileName = fileName[fileName.length-1].split('.');
    fileName = fileName[fileName.length-2];
    var jsonFileName = fileName + '.json';

    // potrace -i -b geojson -k 0.4 -t 60 -o outputXXX.json bitmapXXX.BMP

    var potrace = 'potrace -i -b geojson -k 0.4 -t 60 -o ' + (root.data_json + '/' + jsonFileName) + ' ' + evt.path;
    var compare = 'compare -metric mae ' + root.process + '/background.bmp ' + evt.path + ' ' + root.data_temp + '/diff.bmp';

    drawbot.log(compare);

    exec(compare, function(error, stdout, strerr){
      if((error && error !== 'null'))
      {
        drawbot.Log.error('compare : error : ' + error);
        return;
      }else
      {
        console.log('out + ' + stdout);
        console.log('strout + ' strerr);
        console.log('err + ' error);
        drawbot.Log.debug('compare says: ' + stdout);
        if(stdout.split(' ')[0] > 1250)
        {
          drawbot.Log.debug('gotit');
          exec(potrace, function(error, stdout, stderr) {
            if((error && error !== 'null') || stderr) {
              drawbot.Log.error('potrace ' + error);
              return;
            }
            //drawbot.log('-- Json file created: ' + jsonFileName);
          });
        }else
        {
          //fs.unlinkSync(evt.path);
          drawbot.Log.debug('compare : discard');
        }
      }
    });
  });

  jsonWatcher.on('fileAdded', function(evt) {
    try {
      var json = require(evt.path);
      var gcode = gcodeConverter.convert(json);

      var fileName = evt.path.split('/');
      fileName = fileName[fileName.length-1].split('.');
      fileName = fileName[fileName.length-2];
      var gcodeFileName = fileName + '.gcode';

      fs.writeFile(root.data_gcode + '/' + gcodeFileName, gcode, function(err) {
        if(err) {
          drawbot.Log.error('Could not save to gcode');
        } else {
          drawbot.Log.error('-- GCode: ' + gcodeFileName);
          gcodeFiles.push(gcodeFileName);

          if(!isProcessStarted) {
            processGcodeFile();
            isProcessStarted = true;
          }
        }
      });
    } catch(e) {
      drawbot.Log.error('could not convert json to gcode');
    }
  });

  drawbot.on('drawStarted', function() {
    drawbot.log('-- DRAW STARTED');
    osc.sendSOD();
  });

  drawbot.on('drawFinished', function() {
    drawbot.log('-- DRAW FINISHED');
    osc.sendEOD();
    processGcodeFile(true);
  });
});

var processGcodeFile = function(removeLast) {
  if(removeLast && currentGcodeFile) {
    for(var i = 0; i < gcodeFiles.length; i++) {
      if(gcodeFiles[i] === currentGcodeFile) {
        gcodeFiles.splice(i, 1);
      }
    }
    moveGcodeFile(currentGcodeFile);
  }
  var gcode, gcodeFile;
  if(gcodeFiles.length) {
    gcodeFile = gcodeFiles[gcodeFiles.length - 1];
    currentGcodeFile = gcodeFile;

    gcode = fs.readFileSync(root.data_gcode + '/' + gcodeFile, 'utf8');
    if(gcode) drawbot.Log.debug('[PROCESS] DRAW NEW : ' + gcodeFile);
  } else {
    var randIndex = Math.floor(Math.random() * processedGcodeFiles.length);
    gcodeFile = processedGcodeFiles[randIndex];
    gcode = fs.readFileSync(root.data_gcode_processed + '/' + processedGcodeFiles[randIndex]);
    currentGcodeFile = null;
    if(gcode) drawbot.Log.debug('[PROCESS] DRAW OLD : ' + gcodeFile);
  }

  if(gcode) {
    // start debug code
    //drawbot.isDrawing = true;
    //drawbot.emit('drawStarted');
    //setTimeout(function() {
    //  drawbot.isDrawing = false;
    //  drawbot.emit('drawFinished');
    //}, 5000);
    // end debug code

    drawbot.batch(gcode);
  }
};

//var getGcodeFile = function() {
//  if(!gcodeFiles.length) {
//    var gcodesInFolder = fs.readdirSync(root.data_gcode);
//    for(var i = 0; i < gcodesInFolder.length; i++) {
//      var fileName = gcodesInFolder[i].split('.');
//
//      if(fileName[fileName.length-1] === 'gcode') {
//        gcodeFiles.push(gcodesInFolder[i]);
//      }
//    }
//  }
//
//  if(gcodeFiles.length) {
//    return gcodeFiles[gcodeFiles.length - 1];
//  } else {
//    return null;
//  }
//};

var moveGcodeFile = function(gcodeFileName) {
  fs.renameSync(root.data_gcode + '/' + gcodeFileName, root.data_gcode_processed + '/' + gcodeFileName);
  processedGcodeFiles.push(gcodeFileName);
};
<|endoftext|>


<commit_before>//Table commands.
var ot = require('ot-sexpr');
var sym = ot.sym;

/*
var List = ot.List;
List.prototype.indexOfHead = function(head, start) {
	start = start || 0;
	if (typeof head === 'string')
		head = sym(head);
	if (head === this.head())
		return 0;
};
List.prototype.lastIndexOfHead = function(head, start) {
	start = start || this.size;
	if (typeof head === 'string')
		head = sym(head);
	if (head === this.head())
		return 0;
};
*/
var Selection = ot.Selection;
var Region = ot.Region;

function commands(editor) {

	//(doc -> region -> (arg) -> op) -> selection -> ops
	function bySelection(f, selection, arg) {
		var doc = editor.document();
		var ops = [];
		var _selection = selection || editor.selection();
		function _replace(region) {
			var op = f(doc, region, arg);
			ops = ot.compose(ops, ot.transform(op,ops));
		}
		_selection.forEachR(_replace);
		return ops;
	}

	//given a region return the selected table region
	// + point:table start and node
	//assumes the selection start and end are within a table
	function tableSelection(selection) {
		var _selection = selection || editor.selection();
		var doc = editor.document();
		var _table = sym('table');
		var ret = [];
		_selection.forEachR(function(region) {
			var start = region.begin();
			var end = region.end();
			var ns = doc.nodesAt(start);
			var isTable = false;
			var nl;
			//find the table node.
			for (var i = ns.length - 1; i >= 0; i--) {
				nl = ns[i];
				if (nl.type === 'list' && nl.node.head() === _table)
					break;
			};
			if (i <= 0) return; //not a table node
			//check end point is also in node
			if (nl.node.size + nl.point < end) return;
			//find selected cells.
			var table = nl.node;
			var startCell = _table.cellAt(table, start - nl.point);
			var endCell = _table.cellAt(table, end - nl.point);
			var minCol = Math.min(startCell.column, endCell.column);
			var minRow = Math.min(startCell.row, endCell.row);
			var sAttr = startCell.node.attributes || {};
			var eAttr = endCell.node.attributes || {};
			var maxCol = Math.max(startCell.column + (sAttr.colSpan || 1) - 1,
				endCell.column + (eAttr.colSpan || 1) - 1);
			var maxRow = Math.max(startCell.row + (sAttr.rowSpan || 1) - 1,
				endCell.row + (eAttr.rowSpan || 1) - 1);
			//TODO adjust for col/rowspans in other cells.
			ret.push({node:nl.node, point:nl.point,
					start_row:minRow, start_col:minCol,
					end_row:maxRow, end_col:maxCol});
		});
		return ret;
	}

	function _move_cell(region, forward) {
		var r;
		if (forward)
			r = editor.moveTo(editor.move(
				editor.moveTo(region, 'hardeol'), 'characters', 1, true),
				'hardeol',true);
		else
			r = editor.moveTo(editor.moveTo(editor.move(
				editor.moveTo(region, 'hardbol'), 'characters', 1, false),
				'hardbol'),'hardeol',true);
		return r;
		//TODO: check if we are in the last cell or first cell etc.
	}

	function move_cell(args) {
		var forward = args.forward !== false;
		var selection = editor.selection();
		var regions = selection.regions;

		var ns = new Selection(regions.map(function(r) {
			return _move_cell(r, forward);
		}));

		editor.select(ns);
	};
	move_cell.description = function(args) {
		return "Select the contents of the next/previous cell."
	}

	function move(args) {
		console.log("table_move: " + JSON.stringify(args));
	}
	move.description = function(args) {
		return "Move within table";
	};

	function _moveTo(r, position, extend) {
		var doc = editor.document();
		var head = sym('table');
		var na = doc.nodesAt(r.focus);
		for (var i = na.length - 1; i >= 0; i--) {
			var nl = na[i];
			if (nl.type === 'list' && nl.node.head() === head) {
				switch (position) {
					case 'bot':
						return editor.move(
							new Region(nl.point, r.anchor),
							'characters',1,true, extend);
					case 'eot':
						return editor.move(
							new Region(nl.point + nl.node.size, r.anchor),
							'characters',1,false, extend);
					default:
						return r;
				};
			}
		};
		return r; //unmoved
	}

	function moveTo(args) {
		var position = args.position || 'bot';
		var extend = args.extend; //should extend selection
		var selection = editor.selection();
		var regions = selection.regions;

		console.log("table_move_to: " + JSON.stringify(args));

		var ns = new Selection(regions.map(function(r) {
			return _moveTo(r, position, extend);
		}));

		editor.select(ns);
	}
	moveTo.description = function(args) {
		return "Move to within table";
	};

	function _insert_rows(table, index, n) {
		var hr = table.values[1];
		var cols = 0;
		for (var i = hr.values.length - 1; i >= 1; i--) {
			var c = hr.values[i];
			if (c.attributes && c.attributes.colSpan)
				c += parseInt(c.attributes.colSpan);
			else
				c++;

		};

		return [];
	}

	function insert_row(args) {
		//insert whole row
		var ts = tableSelection();
		var before = args.before !== false;
		var ops = [];
		ts.forEach(function(t) {
			var index = (before ? t.start_row : t.end_row + 1);
			var op = [ot.operations.retain(t.point)];
			_insert_rows(t.node, index,
				t.end_row - t.start_row + 1
				).forEach(function(o) {
					ot._push(op, o);
				});
			ops = ot.compose(ops, ot.transform(op,ops));
		});
		editor.apply(ops);
	}
	insert_row.description = function(description) {
		return "Insert row";
	};

	function _insert_cols(table, index, n) {
		var cell = ot.parse('(cell "")')[0];
		var cell_ops = cell.prefix(0,cell.size);
		var cells_ops = [];
		for (var i = 0; i < n; i++)
			cells_ops = cells_ops.concat(cell_ops);
		console.log(cells_ops);
		var ret = [ot.operations.retain(2)];
		for (var i = 1; i < table.values.length; i++) {
			var row = table.values[i];
			console.log(row)
			//retain to first cell
			ot._push(ret, ot.operations.retain(2));
			var retained = 2;
			for (var j = 1; j <= index; j++) {
				var _cell = row.values[j];
				console.log(_cell)
				ot._push(ret, ot.operations.retain(_cell.size));
				retained += _cell.size;
			}
			ret = ret.concat(cells_ops);
			//retain to end of row
			ot._push(ret, ot.operations.retain(row.size - retained));
		}
		return ret;
	}

	function insert_column(args) {
		//insert whole column
		var before = args.before !== false;
		var ts = tableSelection();
		var ops = [];
		ts.forEach(function(t) {
			var index = (before ? t.start_col : t.end_col + 1);
			var op = [ot.operations.retain(t.point)];
			_insert_cols(t.node, index,
				t.end_col - t.start_col + 1
				).forEach(function(o) {
					ot._push(op, o);
				});
			ops = ot.compose(ops, ot.transform(op,ops));
		});
		console.log(ts);
		console.log(JSON.stringify(ops));
		editor.apply(ops);
	}
	insert_column.description = function(args) {
		return "Insert column";
	};

	function _delete(args) {
		//if column selected delete cells
		//if whole row selected delete rows
		//else clear cell content.
	}
	_delete.description = function(args) {
		return "Delete within table";
	};

	function _make_table(rows, columns, attributes) {
		var cell = '(cell "")'
		var _row = [];
		var i;
		for (i=0;i<columns;i++)
			_row.push(cell);
		var row = '(row ' + _row.join(' ') + ')';
		var _rows = [];
		for (i=0;i<rows;i++)
			_rows.push(row);
		var tbl = '(table ' + _rows.join(' ') + ')';
		if (attributes)
			tbl = JSON.stringify(attributes) + tbl;
		return ot.parse(tbl)[0];
	}

	function _insert_table(doc, region, args) {
		//insert table
		var rows = args.rows || 2;
		var cols = args.columns || args.cols || 2;
		var attributes = args.attributes || {headerRows:1};

		var as = doc.attributesAt(region.begin());
		var breaks = [];
		var ops = [];
		var a;
		for (var i = as.length - 1; i >= 0; i--) {
			var x = as[i];
			breaks.push(x);
			ops.push(ot.operations.pop);
			if (x.type === 'list') break;
		};
		//insert table here
		var tbl = _make_table(rows, cols, attributes);
		console.log(tbl.toSexpr());
		var x = tbl.prefix(0,tbl.size);
		console.log(x);
		ops = ops.concat(x);
		//fixup
		while ((a = breaks.pop())) {
			if (a.type === 'list') {
				ops.push(ot.operations.pushA(a.attributes));
				ops.push(ot.operations.insert('p','sym')); //a.node.head().sym
			} else {
				ops.push(ot.operations.pushS());
			}
		}
		return doc.replace(region, ops);
	}
	function insert_table(args) {
		var ops = bySelection(_insert_table, null, args);
		editor.apply(ops);
		//move to first cell
		var selection = editor.selection();
		var regions = selection.regions;

		var ns = new Selection(regions.map(function(r) {
			return _moveTo(editor.move(r,'characters',1,false), 'bot');
		}));

		editor.select(ns);
	}
	insert_table.description = function(args) {
		return "Insert table";
	};

	return {
		table_move: move,
		table_move_to: moveTo,
		table_move_cell: move_cell,
		insert_table: insert_table,
		insert_row: insert_row,
		insert_column: insert_column,
	};
}

var in_table_context = [{key:"head", operator:"equals", operand:"cell", match_all:true}];

var keymap = [
	{keys:["ctrl+k","b"], command:"table_move_to", args:{position:"bot"}},
	{keys:["ctrl+k","e"], command:"table_move_to", args:{position:"eot"}},
	{keys:["ctrl+k","a","b","up","down"], command:"table_move", args:{mode:"yay", forward:true}},
	{keys:["tab"], command:"table_move_cell", args:{forward:true}}, //, context:in_table_context},
	{keys:["shift+tab"], command:"table_move_cell", args:{forward:false}}, //, context:in_table_context},
	//{keys:["up"], command:"table_move", args:{mode:"row", forward:false}, context:in_table_context},
	//{keys:["down"], command:"table_move", args:{mode:"row", forward:true}, context:in_table_context},
	{keys:["alt+home"], command:"table_move_to", args:{mode:"bol"}, context:in_table_context},
	{keys:["cmd+i","c"], command:"insert_column", args:{before:true}, context:in_table_context},
	{keys:["cmd+i","r"], command:"insert_row", args:{before:true}, context:in_table_context},
	{keys:["cmd+i","shift+c"], command:"insert_column", args:{before:false}, context:in_table_context},
	{keys:["cmd+i","s"], command:"insert_row", args:{before:false}, context:in_table_context},
	{keys:["alt+i","t"], command:"insert_table", args:{},
		context:[
			{key:"breakable", operator:"equals", operand:true, match_all:true}
		]},
	{keys:["cmd+i","t"], command:"insert_table", args:{},
		context:[
			{key:"breakable", operator:"equals", operand:true, match_all:true}
		]},
];

var context_menu = [
	//insert table
	//insert col
	//insert row
	//etc.
];

module.exports = {
	commands: commands,
	keymap: keymap,
	menu: [],
	context_menu: context_menu,
};<commit_msg>initial insert rows - with cool selection move code<commit_after>//Table commands.
var ot = require('ot-sexpr');
var sym = ot.sym;

/*
var List = ot.List;
List.prototype.indexOfHead = function(head, start) {
	start = start || 0;
	if (typeof head === 'string')
		head = sym(head);
	if (head === this.head())
		return 0;
};
List.prototype.lastIndexOfHead = function(head, start) {
	start = start || this.size;
	if (typeof head === 'string')
		head = sym(head);
	if (head === this.head())
		return 0;
};
*/
var Selection = ot.Selection;
var Region = ot.Region;

function commands(editor) {

	//(doc -> region -> (arg) -> op) -> selection -> ops
	function bySelection(f, selection, arg) {
		var doc = editor.document();
		var ops = [];
		var _selection = selection || editor.selection();
		function _replace(region) {
			var op = f(doc, region, arg);
			ops = ot.compose(ops, ot.transform(op,ops));
		}
		_selection.forEachR(_replace);
		return ops;
	}

	//given a region return the selected table region
	// + point:table start and node
	//assumes the selection start and end are within a table
	function tableSelection(selection) {
		var _selection = selection || editor.selection();
		var doc = editor.document();
		var _table = sym('table');
		var ret = [];
		_selection.forEachR(function(region) {
			var start = region.begin();
			var end = region.end();
			var ns = doc.nodesAt(start);
			var isTable = false;
			var nl;
			//find the table node.
			for (var i = ns.length - 1; i >= 0; i--) {
				nl = ns[i];
				if (nl.type === 'list' && nl.node.head() === _table)
					break;
			};
			if (i <= 0) return; //not a table node
			//check end point is also in node
			if (nl.node.size + nl.point < end) return;
			//find selected cells.
			var table = nl.node;
			var startCell = _table.cellAt(table, start - nl.point);
			var endCell = _table.cellAt(table, end - nl.point);
			var minCol = Math.min(startCell.column, endCell.column);
			var minRow = Math.min(startCell.row, endCell.row);
			var sAttr = startCell.node.attributes || {};
			var eAttr = endCell.node.attributes || {};
			var maxCol = Math.max(startCell.column + (sAttr.colSpan || 1) - 1,
				endCell.column + (eAttr.colSpan || 1) - 1);
			var maxRow = Math.max(startCell.row + (sAttr.rowSpan || 1) - 1,
				endCell.row + (eAttr.rowSpan || 1) - 1);
			//TODO adjust for col/rowspans in other cells.
			ret.push({node:nl.node, point:nl.point,
					start_row:minRow, start_col:minCol,
					end_row:maxRow, end_col:maxCol});
		});
		return ret;
	}

	function _move_cell(region, forward) {
		var r;
		if (forward)
			r = editor.moveTo(editor.move(
				editor.moveTo(region, 'hardeol'), 'characters', 1, true),
				'hardeol',true);
		else
			r = editor.moveTo(editor.moveTo(editor.move(
				editor.moveTo(region, 'hardbol'), 'characters', 1, false),
				'hardbol'),'hardeol',true);
		return r;
		//TODO: check if we are in the last cell or first cell etc.
	}

	function move_cell(args) {
		var forward = args.forward !== false;
		var selection = editor.selection();
		var regions = selection.regions;

		var ns = new Selection(regions.map(function(r) {
			return _move_cell(r, forward);
		}));

		editor.select(ns);
	};
	move_cell.description = function(args) {
		return "Select the contents of the next/previous cell."
	}

	function move(args) {
		console.log("table_move: " + JSON.stringify(args));
	}
	move.description = function(args) {
		return "Move within table";
	};

	function _moveTo(r, position, extend) {
		var doc = editor.document();
		var head = sym('table');
		var na = doc.nodesAt(r.focus);
		for (var i = na.length - 1; i >= 0; i--) {
			var nl = na[i];
			if (nl.type === 'list' && nl.node.head() === head) {
				switch (position) {
					case 'bot':
						return editor.move(
							new Region(nl.point, r.anchor),
							'characters',1,true, extend);
					case 'eot':
						return editor.move(
							new Region(nl.point + nl.node.size, r.anchor),
							'characters',1,false, extend);
					default:
						return r;
				};
			}
		};
		return r; //unmoved
	}

	function moveTo(args) {
		var position = args.position || 'bot';
		var extend = args.extend; //should extend selection
		var selection = editor.selection();
		var regions = selection.regions;

		console.log("table_move_to: " + JSON.stringify(args));

		var ns = new Selection(regions.map(function(r) {
			return _moveTo(r, position, extend);
		}));

		editor.select(ns);
	}
	moveTo.description = function(args) {
		return "Move to within table";
	};

	function _insert_rows(table, index, n) {
		var hr = table.values[1];
		var cols = 0;
		var cell = '(cell "")';
		for (var i = hr.values.length - 1; i >= 1; i--) {
			var c = hr.values[i];
			if (c.attributes && c.attributes.colSpan)
				cols += parseInt(c.attributes.colSpan);
			else
				cols++;
		};
		var cells = [];
		for (var i=0;i<cols;i++)
			cells.push(cell);
		var row = ot.parse('(row ' + cells.join(' ') + ')')[0];
		var row_ops = row.prefix(0,row.size);

		var retain = 2;
		for (var i=1;i <=index;i++)
			retain += table.values[i].size;
		var ret = [ot.operations.retain(retain)];
		for (var i=0; i<n; i++)
			ret = ret.concat(row_ops);
		return ret;
	}

	function firstString(ops) {
		var n = 0;
		for (var i = 0; i < ops.length; i++) {
			var op = ops[i];
			if (op.op === 'insert' && op.type === 'push' && op.value === 'string') {
				n += 1;
				return n;
			}
			switch (op.op) {
				case 'insert':
				case 'retain':
					n += op.n;
			}
		};
		return;
	}

	function insert_row(args) {
		//insert whole row
		var ts = tableSelection();
		var before = args.before !== false;
		var ops = [];
		var regions = [];
		ts.forEach(function(t) {
			var index = (before ? t.start_row : t.end_row + 1);
			var op = [ot.operations.retain(t.point)];
			_insert_rows(t.node, index,
				t.end_row - t.start_row + 1
				).forEach(function(o) {
					ot._push(op, o);
				});
			var no = ot.transform(op,ops);
			var x = firstString(no);
			if (x)
				regions.push(new Region(x));
			ops = ot.compose(ops, no);
		});
		editor.apply(ops);
		if(args.select)
			editor.select(new Selection(regions));
	}
	insert_row.description = function(description) {
		return "Insert row";
	};

	function _insert_cols(table, index, n) {
		var cell = ot.parse('(cell "")')[0];
		var cell_ops = cell.prefix(0,cell.size);
		var cells_ops = [];
		for (var i = 0; i < n; i++)
			cells_ops = cells_ops.concat(cell_ops);
		var ret = [ot.operations.retain(2)];
		for (var i = 1; i < table.values.length; i++) {
			var row = table.values[i];
			//retain to first cell
			ot._push(ret, ot.operations.retain(2));
			var retained = 2;
			for (var j = 1; j <= index; j++) {
				var _cell = row.values[j];
				ot._push(ret, ot.operations.retain(_cell.size));
				retained += _cell.size;
			}
			ret = ret.concat(cells_ops);
			//retain to end of row
			ot._push(ret, ot.operations.retain(row.size - retained));
		}
		return ret;
	}

	function insert_column(args) {
		//insert whole column
		var before = args.before !== false;
		var ts = tableSelection();
		var ops = [];
		ts.forEach(function(t) {
			var index = (before ? t.start_col : t.end_col + 1);
			var op = [ot.operations.retain(t.point)];
			_insert_cols(t.node, index,
				t.end_col - t.start_col + 1
				).forEach(function(o) {
					ot._push(op, o);
				});
			ops = ot.compose(ops, ot.transform(op,ops));
		});
		editor.apply(ops);
	}
	insert_column.description = function(args) {
		return "Insert column";
	};

	function _delete(args) {
		//if column selected delete cells
		//if whole row selected delete rows
		//else clear cell content.
	}
	_delete.description = function(args) {
		return "Delete within table";
	};

	function _make_table(rows, columns, attributes) {
		var cell = '(cell "")'
		var _row = [];
		var i;
		for (i=0;i<columns;i++)
			_row.push(cell);
		var row = '(row ' + _row.join(' ') + ')';
		var _rows = [];
		for (i=0;i<rows;i++)
			_rows.push(row);
		var tbl = '(table ' + _rows.join(' ') + ')';
		if (attributes)
			tbl = JSON.stringify(attributes) + tbl;
		return ot.parse(tbl)[0];
	}

	function _insert_table(doc, region, args) {
		//insert table
		var rows = args.rows || 2;
		var cols = args.columns || args.cols || 2;
		var attributes = args.attributes || {headerRows:1};

		var as = doc.attributesAt(region.begin());
		var breaks = [];
		var ops = [];
		var a;
		for (var i = as.length - 1; i >= 0; i--) {
			var x = as[i];
			breaks.push(x);
			ops.push(ot.operations.pop);
			if (x.type === 'list') break;
		};
		//insert table here
		var tbl = _make_table(rows, cols, attributes);
		console.log(tbl.toSexpr());
		var x = tbl.prefix(0,tbl.size);
		console.log(x);
		ops = ops.concat(x);
		//fixup
		while ((a = breaks.pop())) {
			if (a.type === 'list') {
				ops.push(ot.operations.pushA(a.attributes));
				ops.push(ot.operations.insert('p','sym')); //a.node.head().sym
			} else {
				ops.push(ot.operations.pushS());
			}
		}
		return doc.replace(region, ops);
	}
	function insert_table(args) {
		var ops = bySelection(_insert_table, null, args);
		editor.apply(ops);
		//move to first cell
		var selection = editor.selection();
		var regions = selection.regions;

		var ns = new Selection(regions.map(function(r) {
			return _moveTo(editor.move(r,'characters',1,false), 'bot');
		}));

		editor.select(ns);
	}
	insert_table.description = function(args) {
		return "Insert table";
	};

	return {
		table_move: move,
		table_move_to: moveTo,
		table_move_cell: move_cell,
		insert_table: insert_table,
		insert_row: insert_row,
		insert_column: insert_column,
	};
}

var in_table_context = [{key:"head", operator:"equals", operand:"cell", match_all:true}];

var keymap = [
	{keys:["ctrl+k","b"], command:"table_move_to", args:{position:"bot"}},
	{keys:["ctrl+k","e"], command:"table_move_to", args:{position:"eot"}},
	{keys:["ctrl+k","a","b","up","down"], command:"table_move", args:{mode:"yay", forward:true}},
	{keys:["tab"], command:"table_move_cell", args:{forward:true}}, //, context:in_table_context},
	{keys:["shift+tab"], command:"table_move_cell", args:{forward:false}}, //, context:in_table_context},
	//{keys:["up"], command:"table_move", args:{mode:"row", forward:false}, context:in_table_context},
	//{keys:["down"], command:"table_move", args:{mode:"row", forward:true}, context:in_table_context},
	{keys:["alt+home"], command:"table_move_to", args:{mode:"bol"}, context:in_table_context},
	{keys:["cmd+i","c"], command:"insert_column", args:{before:true}, context:in_table_context},
	{keys:["cmd+i","r"], command:"insert_row", args:{before:false}, context:in_table_context},
	{keys:["cmd+i","d"], command:"insert_column", args:{before:false}, context:in_table_context},
	{keys:["cmd+i","s"], command:"insert_row", args:{before:true}, context:in_table_context},
	{keys:["enter"], command:"insert_row", args:{before:false,select:true}, context:in_table_context},
	{keys:["alt+i","t"], command:"insert_table", args:{},
		context:[
			{key:"breakable", operator:"equals", operand:true, match_all:true}
		]},
	{keys:["cmd+i","t"], command:"insert_table", args:{},
		context:[
			{key:"breakable", operator:"equals", operand:true, match_all:true}
		]},
];

var context_menu = [
	//insert table
	//insert col
	//insert row
	//etc.
];

module.exports = {
	commands: commands,
	keymap: keymap,
	menu: [],
	context_menu: context_menu,
};<|endoftext|>


<commit_before>/**
 * @license
 * Copyright 2018 Google LLC. All Rights Reserved.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * =============================================================================
 */

import * as tf from '@tensorflow/tfjs';

import {MnistData} from './data';
import * as ui from './ui';

const model = tf.sequential();

model.add(tf.layers.conv2d({
  inputShape: [28, 28, 1],
  kernelSize: 5,
  filters: 8,
  strides: 1,
  activation: 'relu',
  kernelInitializer: 'varianceScaling'
}));
model.add(tf.layers.maxPooling2d({poolSize: [2, 2], strides: [2, 2]}));
model.add(tf.layers.conv2d({
  kernelSize: 5,
  filters: 16,
  strides: 1,
  activation: 'relu',
  kernelInitializer: 'varianceScaling'
}));
model.add(tf.layers.maxPooling2d({poolSize: [2, 2], strides: [2, 2]}));
model.add(tf.layers.flatten());
model.add(tf.layers.dense(
    {units: 10, kernelInitializer: 'varianceScaling', activation: 'softmax'}));

const LEARNING_RATE = 0.15;
const optimizer = tf.train.sgd(LEARNING_RATE);
model.compile({
  optimizer: optimizer,
  loss: 'categoricalCrossentropy',
  metrics: ['accuracy'],
});

const BATCH_SIZE = 64;
const TRAIN_BATCHES = 150;

// Every few batches, test accuracy over many examples. Ideally, we'd compute
// accuracy over the whole test set, but for performance we'll use a subset.
const TEST_BATCH_SIZE = 1000;
const TEST_ITERATION_FREQUENCY = 5;

async function train() {
  ui.isTraining();

  const lossValues = [];
  const accuracyValues = [];

  for (let i = 0; i < TRAIN_BATCHES; i++) {
    const batch = data.nextTrainBatch(BATCH_SIZE);

    let testBatch;
    let validationData;
    // Every few batches test the accuracy of the mode.
    if (i % TEST_ITERATION_FREQUENCY === 0) {
      testBatch = data.nextTestBatch(TEST_BATCH_SIZE);
      validationData = [
        testBatch.xs.reshape([TEST_BATCH_SIZE, 28, 28, 1]), testBatch.labels
      ];
    }

    // The entire dataset doesn't fit into memory so we call fit repeatedly
    // with batches.
    const history = await model.fit(
        batch.xs.reshape([BATCH_SIZE, 28, 28, 1]), batch.labels,
        {batchSize: BATCH_SIZE, validationData, epochs: 1});

    const loss = history.history.loss[0];
    const accuracy = history.history.acc[0];

    // Plot loss / accuracy.
    lossValues.push({'batch': i, 'loss': loss, 'set': 'train'});
    ui.plotLosses(lossValues);

    if (testBatch != null) {
      accuracyValues.push({'batch': i, 'accuracy': accuracy, 'set': 'train'});
      ui.plotAccuracies(accuracyValues);
    }

    batch.xs.dispose();
    batch.labels.dispose();
    if (testBatch != null) {
      testBatch.xs.dispose();
      testBatch.labels.dispose();
    }

    await tf.nextFrame();
  }
}

async function showPredictions() {
  const testExamples = 100;
  const batch = data.nextTestBatch(testExamples);

  tf.tidy(() => {
    const output = model.predict(batch.xs.reshape([-1, 28, 28, 1]));

    const axis = 1;
    const labels = Array.from(batch.labels.argMax(axis).dataSync());
    const predictions = Array.from(output.argMax(axis).dataSync());

    ui.showTestResults(batch, predictions, labels);
  });
}

let data;
async function load() {
  data = new MnistData();
  await data.load();
}

async function mnist() {
  await load();
  await train();
  showPredictions();
}
mnist();
<commit_msg>Add extensive code comments to mnist example (#92)<commit_after>/**
 * @license
 * Copyright 2018 Google LLC. All Rights Reserved.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * =============================================================================
 */

import * as tf from '@tensorflow/tfjs';

// This is a helper class for loading and managing MNIST data specifically.
// It is a useful example of how you could create your own data manager class
// for arbitrary data though. It's worth a look :)
import {MnistData} from './data';

// This is a helper class for drawing loss graphs and MNIST images to the
// window. For the purposes of understanding the machine learning bits, you can
// largely ignore it
import * as ui from './ui';

// Create a sequential neural network model. tf.sequential provides an API for
// creating "stacked" models where the output from one layer is used as the
// input to the next layer.
const model = tf.sequential();

// The first layer of the convolutional neural network plays a dual role:
// it is both the input layer of the neural network and a layer that performs
// the first convolution operation on the input. It receives the 28x28 pixels
// black and white images. This input layer uses 8 filters with a kernel size
// of 5 pixels each. It uses a simple RELU activation function which pretty
// much just looks like this: __/
model.add(tf.layers.conv2d({
  inputShape: [28, 28, 1],
  kernelSize: 5,
  filters: 8,
  strides: 1,
  activation: 'relu',
  kernelInitializer: 'varianceScaling'
}));

// After the first layer we include a MaxPooling layer. This acts as a sort of
// downsampling using max values in a region instead of averaging.
// https://www.quora.com/What-is-max-pooling-in-convolutional-neural-networks
model.add(tf.layers.maxPooling2d({poolSize: [2, 2], strides: [2, 2]}));

// Our third layer is another convolution, this time with 16 filters.
model.add(tf.layers.conv2d({
  kernelSize: 5,
  filters: 16,
  strides: 1,
  activation: 'relu',
  kernelInitializer: 'varianceScaling'
}));

// Max pooling again.
model.add(tf.layers.maxPooling2d({poolSize: [2, 2], strides: [2, 2]}));

// Now we flatten the output from the 2D filters into a 1D vector to prepare
// it for input into our last layer. This is common practice when feeding
// higher dimensional data to a final classification output layer.
model.add(tf.layers.flatten());

// Our last layer is a dense layer which has 10 output units, one for each
// output class (i.e. 0, 1, 2, 3, 4, 5, 6, 7, 8, 9). Here the classes actually
// represent numbers, but it's the same idea if you had classes that represented
// other entities like dogs and cats (two output classes: 0, 1).
// We use the softmax function as the activation for the output layer as it
// creates a probability distribution over our 10 classes so their output values
// sum to 1.
model.add(tf.layers.dense(
    {units: 10, kernelInitializer: 'varianceScaling', activation: 'softmax'}));

// Now that we've defined our model, we will define our optimizer. The optimizer
// will be used to optimize our model's weight values during training so that
// we can decrease our training loss and increase our classification accuracy.

// The learning rate defines the magnitude by which we update our weights each
// training step. The higher the value, the faster our loss values converge,
// but also the more likely we are to overshoot optimal parameters
// when making an update. A learning rate that is too low will take too long to
// find optimal (or good enough) weight parameters while a learning rate that is
// too high may overshoot optimal parameters. Learning rate is one of the most
// important hyperparameters to set correctly. Finding the right value takes
// practice and is often best found empirically by trying many values.
const LEARNING_RATE = 0.15;

// We are using Stochastic Gradient Descent (SGD) as our optimization algorithm.
// This is the most famous modern optimization algorithm in deep learning and
// it is largely to thank for the current machine learning renaissance.
// Most other optimizers you will come across (e.g. ADAM, RMSProp, AdaGrad,
// Momentum) are variants on SGD. SGD is an iterative method for minimizing an
// objective function. It tries to find the minimum of our loss function with
// respect to the model's weight parameters.
const optimizer = tf.train.sgd(LEARNING_RATE);

// We compile our model by specifying an optimizer, a loss function, and a list
// of metrics that we will use for model evaluation. Here we're using a
// categorical crossentropy loss, the standard choice for a multi-class
// classification problem like MNIST digits.
model.compile({
  optimizer: optimizer,
  loss: 'categoricalCrossentropy',
  metrics: ['accuracy'],
});

// Batch size is another important hyperparameter. It defines the number of
// examples we group together, or batch, between updates to the model's weights
// during training. A value that is too low will update weights using too few
// examples and will not generalize well. Larger batch sizes require more memory
// resources and aren't guaranteed to perform better.
const BATCH_SIZE = 64;

// The number of batches to train on before freezing the model and considering
// it trained. This will result in BATCH_SIZE x TRAIN_BATCHES examples being
// fed to the model during training.
const TRAIN_BATCHES = 150;

// Every few batches, test accuracy over many examples. Ideally, we'd compute
// accuracy over the whole test set, but for performance we'll use a subset.

// The number of test examples to predict each time we test. Because we don't
// update model weights during testing this value doesn't affect model training.
const TEST_BATCH_SIZE = 1000;
// The number of training batches we will run between each test batch.
const TEST_ITERATION_FREQUENCY = 5;

async function train() {
  ui.isTraining();

  // We'll keep a buffer of loss and accuracy values over time.
  const lossValues = [];
  const accuracyValues = [];

  // Iteratively train our model on mini-batches of data.
  for (let i = 0; i < TRAIN_BATCHES; i++) {

    const batch = data.nextTrainBatch(BATCH_SIZE);

    let testBatch;
    let validationData;
    // Every few batches test the accuracy of the model.
    if (i % TEST_ITERATION_FREQUENCY === 0) {
      testBatch = data.nextTestBatch(TEST_BATCH_SIZE);
      validationData = [
        // Reshape the training data from [64, 28x28] to [64, 28, 28, 1] so
        // that we can feed it to our convolutional neural net.
        testBatch.xs.reshape([TEST_BATCH_SIZE, 28, 28, 1]), testBatch.labels
      ];
    }

    // The entire dataset doesn't fit into memory so we call train repeatedly
    // with batches using the fit() method.
    const history = await model.fit(
        batch.xs.reshape([BATCH_SIZE, 28, 28, 1]), batch.labels,
        {batchSize: BATCH_SIZE, validationData, epochs: 1});

    const loss = history.history.loss[0];
    const accuracy = history.history.acc[0];

    // Plot loss / accuracy.
    lossValues.push({'batch': i, 'loss': loss, 'set': 'train'});
    ui.plotLosses(lossValues);

    if (testBatch != null) {
      accuracyValues.push({'batch': i, 'accuracy': accuracy, 'set': 'train'});
      ui.plotAccuracies(accuracyValues);
    }

    // Call dispose on the training/test tensors to free their GPU memory.
    batch.xs.dispose();
    batch.labels.dispose();
    if (testBatch != null) {
      testBatch.xs.dispose();
      testBatch.labels.dispose();
    }

    // tf.nextFrame() returns a promise that resolves at the next call to
    // requestAnimationFrame(). By awaiting this promise we keep our model
    // training from blocking the main UI thread and freezing the browser.
    await tf.nextFrame();
  }
}

async function showPredictions() {
  const testExamples = 100;
  const batch = data.nextTestBatch(testExamples);

  // Code wrapped in a tf.tidy() function callback will have their tensors freed
  // from GPU memory after execution without having to call dispose().
  // The tf.tidy callback runs synchronously.
  tf.tidy(() => {
    const output = model.predict(batch.xs.reshape([-1, 28, 28, 1]));

    // tf.argMax() returns the indices of the maximum values in the tensor along
    // a specific axis. Categorical classification tasks like this one often
    // represent classes as one-hot vectors. One-hot vectors are 1D vectors with
    // one element for each output class. All values in the vector are 0
    // except for one, which has a value of 1 (e.g. [0, 0, 0, 1, 0]). The
    // output from model.predict() will be a probability distribution, so we use
    // argMax to get the index of the vector element that has the highest
    // probability. This is our prediction.
    // (e.g. argmax([0.07, 0.1, 0.03, 0.75, 0.05]) == 3)
    // dataSync() synchronously downloads the tf.tensor values from the GPU so
    // that we can use them in our normal CPU JavaScript code
    // (for a non-blocking version of this function, use data()).
    const axis = 1;
    const labels = Array.from(batch.labels.argMax(axis).dataSync());
    const predictions = Array.from(output.argMax(axis).dataSync());

    ui.showTestResults(batch, predictions, labels);
  });
}

let data;
async function load() {
  data = new MnistData();
  await data.load();
}

// This is our main function. It loads the MNIST data, trains the model, and
// then shows what the model predicted on unseen test data.
async function mnist() {
  await load();
  await train();
  showPredictions();
}
mnist();
<|endoftext|>


<commit_before>'use babel'
'use strict'

const request = require('request')
const mockConfigUtil = require('./mockConfigUtil')

const WebSocketClient = require('websocket').client
const WsBridge = require('./wsBridge')
const configurationManager = require('./configurationManager')

const previewRequest = 'http://127.0.0.1:PORT/theraConfig'
const wsAddress = 'http://127.0.0.1:PORT'
const pageQRCode = 'http://127.0.0.1:PORT/ipAddressPort'

const WS_SEND_MSG = 'weex-run:ws-send-msg'
const HTTP_SEND_MSG = 'weex-run:http-send-msg'
const WS_CONNECTED = 'weex-run:ws-connected'

const SERVER_STATUS_STARTING = "starting"
const SERVER_STATUS_RUNNING = "running"
const SERVER_STATUS_SHUTDOWN = "shutdown"

module.exports = class PreviewClient {
  constructor () {
    atom.commands.add(atom.commands.rootNode, WS_SEND_MSG, (content) => this.wsSend(content))
    atom.commands.add(atom.commands.rootNode, HTTP_SEND_MSG, (content) => this.httpSend(content))
  }

  start (fileToRun, protocol) {
    return new Promise((resolve, reject) => {
      // let curEditor = atom.workspace.getActiveTextEditor()
      // let filePath = fileToRun || curEditor.getPath()

      configurationManager.getConfig()
        .then((configObject) => {
          let options = {
            url: previewRequest.replace('PORT', atom.config.get('weex-run.dumplingPort')),
            method: 'POST',
            headers: {
              'Content-Type': 'application/json'
            },
            body: JSON.stringify({
              'message': 'theraConfig',
              'data': configObject
            })
          }

          request(options, (err, response, body) => {
            if (err) reject(err)
            else {
              console.log('start monitor file...')
              console.log(body)
              resolve()
            }
          })
        })
    })
  }

  requestQRCode () {
    return new Promise((resolve, reject) => {
      const imgURL = pageQRCode.replace('PORT', atom.config.get('weex-run.dumplingPort'))
      request(imgURL, (err, response, body) => {
        if (err || response.statusCode !== 200) {
          console.error(`request qr image ${imgURL} error`, err)
          resolve(undefined)
        } else {
          resolve(body)
        }
      })
    })
  }

  httpSend (content) {
    let {url, method, headers, body} = content.detail
    let payload = {
      url: url,
      method: method,
      headers: headers,
      body: JSON.stringify(body)
    }

    console.log(`send request ${url}`)
    if (payload.method === 'POST') console.log(`send request body ${JSON.stringify(body)}`)
    request(payload, (err, response, body) => {
      if (err || response.statusCode !== 200) {
        if (err) console.error(err)
        else console.error(err)
      } else {
        console.log(body)
      }
    })
  }

  wsSend (content) {
    this.wsClient = this.wsClient || new WebSocketClient()
    if (this.wsClient.connection) {
      console.log(`ws send msg ${JSON.stringify(content.detail)}`)
      this.wsClient.connection.sendUTF(JSON.stringify(content.detail))
    } else {
      console.error('not connected yet')
    }
  }

  wsConnect () {
    var self = this
    return new Promise((resolve, reject) => {
      // If connection is valid, needn't do any thing.
      if (this.wsClient && this.wsClient.connection && this.wsClient.connection.state === 'open') {
        console.log('Thera connection to dumpling is alive. Needn\'t reconnection.');
        resolve();
        return;
      }
      // Clear current connection state.
      if (this.wsClient && this.wsClient.connection) {
        this.wsClient.connection.close('Normally closed.')
        this.wsClient = null
      }
      this.wsClient = this.wsClient || new WebSocketClient()
      this.wsClient.on('connectFailed', (error) => {
        reject(error)
        console.log(`Connect error: ${error.toString()}`)
      })
      this.wsClient.on('connect', (connection) => {
        console.log('websocket connected')
        self.wsClient.connection = connection

        connection.on('error', (error) => {
          console.log(`Connection error: ${error.toString()}`)

          // reconnect after delay
          setTimeout(() => {
            console.log('reconnecting websocket after 3 seconds')

            self.wsClient.connect(
              wsAddress.replace('PORT', atom.config.get('weex-run.dumplingPort')),
              undefined,
              undefined,
              {'from': 'thera'}
            )
          }, 1000 * 3)
        })

        connection.on('close', (error) => {
          console.log('Connection closed: ' + error.toString())
          notifyServerStatus.apply(self, [SERVER_STATUS_SHUTDOWN])
        })

        // dispatch message
        connection.on('message', onRecvCallback.bind(self))
        atom.commands.dispatch(atom.views.getView(atom.workspace), WS_CONNECTED)
        mockConfigUtil.init()
        resolve()
      })

      function onRecvCallback (message) {
        // console.log(message)
        this.wsBridge.dispatch(message)
      }

      function onSendCallback (message) {
        // console.log(message)
        this.wsClient.connection.sendUTF(message)
      }

      function notifyServerStatus(status) {
        console.log('Server status: ' + status)
        atom.commands.dispatch(atom.views.getView(atom.workspace), 'thera-live-server:shutdown')
      }

      if (this.wsBridge) {
        this.wsBridge.dispose()
        this.wsBridge = null
      }
      this.wsBridge = new WsBridge(onSendCallback.bind(this))

      // connect with header from:thera
      this.wsClient.connect(
        wsAddress.replace('PORT', atom.config.get('weex-run.dumplingPort')),
        undefined,
        undefined,
        {'from': 'thera'}
      )
    })
  }
}
<commit_msg>move config code to client<commit_after>'use babel'
'use strict'

const request = require('request')
const mockConfigUtil = require('./mockConfigUtil')

const WebSocketClient = require('websocket').client
const WsBridge = require('./wsBridge')
const configurationManager = require('./configurationManager')

const previewRequest = 'http://127.0.0.1:PORT/theraConfig'
const MOCK_DATA_URL = 'http://localhost:PORT/mockConfig'
const wsAddress = 'http://127.0.0.1:PORT'
const pageQRCode = 'http://127.0.0.1:PORT/ipAddressPort'

const WS_SEND_MSG = 'weex-run:ws-send-msg'
const HTTP_SEND_MSG = 'weex-run:http-send-msg'
const WS_CONNECTED = 'weex-run:ws-connected'

const SERVER_STATUS_STARTING = "starting"
const SERVER_STATUS_RUNNING = "running"
const SERVER_STATUS_SHUTDOWN = "shutdown"

const fsp = require('fs-promise')
const path = require('path')
const fs = require('fs')

module.exports = class PreviewClient {
  constructor () {
    atom.commands.add(atom.commands.rootNode, WS_SEND_MSG, (content) => this.wsSend(content))
    atom.commands.add(atom.commands.rootNode, HTTP_SEND_MSG, (content) => this.httpSend(content.detail))

    let projectPath = atom.project.getDirectories()[0].path
    this.mockConfigPath = path.join(projectPath, 'mock', 'config.json')
    this.launchConfigPath = path.join(projectPath, '.thera', 'launch.json')
  }

  start (fileToRun, protocol) {
    return new Promise((resolve, reject) => {
      // let curEditor = atom.workspace.getActiveTextEditor()
      // let filePath = fileToRun || curEditor.getPath()

      this.sendLaunchConfig()
      this.sendMockConfig()
    })
  }

  requestQRCode () {
    return new Promise((resolve, reject) => {
      const imgURL = pageQRCode.replace('PORT', atom.config.get('weex-run.dumplingPort'))
      request(imgURL, (err, response, body) => {
        if (err || response.statusCode !== 200) {
          console.error(`request qr image ${imgURL} error`, err)
          resolve(undefined)
        } else {
          resolve(body)
        }
      })
    })
  }

  httpSend (content) {
    let {url, method, headers, body} = content
    let payload = {
      url: url,
      method: method,
      headers: headers,
      body: JSON.stringify(body)
    }

    console.log(`send request ${url}`)
    if (payload.method === 'POST') console.log(`send request body ${JSON.stringify(body)}`)
    request(payload, (err, response, body) => {
      if (err || response.statusCode !== 200) {
        if (err) console.error(err)
        else console.error(err)
      } else {
        console.log(body)
      }
    })
  }

  wsSend (content) {
    this.wsClient = this.wsClient || new WebSocketClient()
    if (this.wsClient.connection) {
      console.log(`ws send msg ${JSON.stringify(content.detail)}`)
      this.wsClient.connection.sendUTF(JSON.stringify(content.detail))
    } else {
      console.error('not connected yet')
    }
  }

  wsConnect () {
    var self = this
    return new Promise((resolve, reject) => {
      // If connection is valid, needn't do any thing.
      if (this.wsClient && this.wsClient.connection && this.wsClient.connection.state === 'open') {
        console.log('Thera connection to dumpling is alive. Needn\'t reconnection.');
        resolve();
        return;
      }
      // Clear current connection state.
      if (this.wsClient && this.wsClient.connection) {
        this.wsClient.connection.close('Normally closed.')
        this.wsClient = null
      }
      this.wsClient = this.wsClient || new WebSocketClient()
      this.wsClient.on('connectFailed', (error) => {
        reject(error)
        console.log(`Connect error: ${error.toString()}`)
      })
      this.wsClient.on('connect', (connection) => {
        console.log('websocket connected')
        self.wsClient.connection = connection

        connection.on('error', (error) => {
          console.log(`Connection error: ${error.toString()}`)

          // reconnect after delay
          setTimeout(() => {
            console.log('reconnecting websocket after 3 seconds')

            self.wsClient.connect(
              wsAddress.replace('PORT', atom.config.get('weex-run.dumplingPort')),
              undefined,
              undefined,
              {'from': 'thera'}
            )
          }, 1000 * 3)
        })

        connection.on('close', (error) => {
          console.log('Connection closed: ' + error.toString())
          notifyServerStatus.apply(self, [SERVER_STATUS_SHUTDOWN])
        })

        // dispatch message
        connection.on('message', onRecvCallback.bind(self))
        atom.commands.dispatch(atom.views.getView(atom.workspace), WS_CONNECTED)
        this.watchLaunchConfig()
        this.watchMockConfig()
        resolve()
      })

      function onRecvCallback (message) {
        // console.log(message)
        this.wsBridge.dispatch(message)
      }

      function onSendCallback (message) {
        // console.log(message)
        this.wsClient.connection.sendUTF(message)
      }

      function notifyServerStatus(status) {
        console.log('Server status: ' + status)
        atom.commands.dispatch(atom.views.getView(atom.workspace), 'thera-live-server:shutdown')
      }

      if (this.wsBridge) {
        this.wsBridge.dispose()
        this.wsBridge = null
      }
      this.wsBridge = new WsBridge(onSendCallback.bind(this))

      // connect with header from:thera
      this.wsClient.connect(
        wsAddress.replace('PORT', atom.config.get('weex-run.dumplingPort')),
        undefined,
        undefined,
        {'from': 'thera'}
      )
    })
  }

  watchLaunchConfig() {
    let projectPath = atom.project.getDirectories()[0].path
    var launchConfigPath = path.join(projectPath, '.thera', 'launch.json')
    fs.watchFile(launchConfigPath, (curr, prev) => {
      this.sendLaunchConfig()
    })
  }

  sendLaunchConfig() {
    fsp.readJson(this.launchConfigPath)
        .then((configObject) => {
          let options = {
            url: previewRequest.replace('PORT', atom.config.get('weex-run.dumplingPort')),
            method: 'POST',
            headers: {
              'Content-Type': 'application/json'
            },
            body: JSON.stringify({
              'message': 'theraConfig',
              'data': configObject
            })
          }

          request(options, (err, response, body) => {
            if (err) reject(err)
            else {
              console.log('start monitor file...')
              console.log(body)
            }
          })
        })
  }

  watchMockConfig(){
      // watch config changes
      fs.watchFile(this.mockConfigPath, (curr, prev) => {
        this.sendMockConfig()
      })
  }

  sendMockConfig(){
    fsp.readJson(this.mockConfigPath)
        .then((mockJSON) => {
          let msg = this.parseMockConfig(mockJSON)
          this.httpSend(msg)
        })
  }

  parseMockConfig (config) {
    let projectPath = atom.project.getDirectories()[0].path
    var body
    if (config) {
      body = {
        'message': 'mock',
        'data': {
          'mockData': [],
          'mockModules': []
        }
      }
      if(config.hasOwnProperty('mockData')){
        config.mockData.forEach((data) => {
          let mockUnit = {}
          for (var key in data) {
            if (data.hasOwnProperty(key)) {
              mockUnit[key] = data[key].replace('${workspaceRoot}', projectPath)
            }
          }
          body.data.mockData.push(mockUnit)
        })
      }
      if(config.hasOwnProperty('mockModules')) {
        config.mockModules.forEach((module) => {
          body.data.mockModules.push(module)
        })
      }
    }

    let payload = {
      url: MOCK_DATA_URL.replace('PORT', atom.config.get('weex-run.dumplingPort')),
      method: 'POST',
      headers: {'Content-Type': 'application/json'},
      body: body
    }

    return payload
  }

}
<|endoftext|>


<commit_before>'use strict'
const getParent = require('../render/dom/parent')
const append = require('../render/dom/create/append')
const appendStatic = append.static
const appendState = append.state

exports.types = {
  text: {
    class: null,
    subscriptionType: true,
    render: {
      static (target, pnode) {
        appendStatic(target, pnode, document.createTextNode(target.compute()))
      },
      state  (target, state, type, stamp, subs, tree, id, pid) {
        var node = tree._[id]
        var pnode
        if (!node) {
          pnode = getParent(type, stamp, subs, tree, pid)
          // has to be compute make it fast
          node = tree._[id] = document.createTextNode(target.compute(state))
          appendState(target, pnode, node, subs, tree, id)
        } else {
          // node
          if (type === 'remove') {
            // rather call parentNode but crashes in node
            pnode = getParent(type, stamp, subs, tree, pid) || node.parentNode
            pnode.removeChild(node)
          } else {
            // has to be compute make it fast -- its ultra slow now!
            // easpecially creating the operator keys rly need to optmize
            node.nodeValue = target.compute(state)
          }
        }
      }
    }
  }
}

exports.properties = { text: { type: 'text' } }
<commit_msg>fixes<commit_after>'use strict'
const getParent = require('../render/dom/parent')
const append = require('../render/dom/create/append')
const appendStatic = append.static
const appendState = append.state

exports.types = {
  text: {
    class: null,
    subscriptionType: true,
    render: {
      static (target, pnode) {
        appendStatic(target, pnode, document.createTextNode(target.compute()))
      },
      state  (target, state, type, stamp, subs, tree, id, pid) {
        var node = tree._[id]
        var pnode
        if (!node) {
          pnode = getParent(type, stamp, subs, tree, pid)
          // has to be compute make it fast
          node = tree._[id] = document.createTextNode(target.compute(state))
          appendState(target, pnode, node, subs, tree, id)
        } else {
          // node
          if (type === 'remove') {
            // rather call parentNode but crashes in node
            pnode = getParent(type, stamp, subs, tree, pid) || node.parentNode
            if (pnode) { pnode.removeChild(node) }
          } else {
            // has to be compute make it fast -- its ultra slow now!
            // easpecially creating the operator keys rly need to optmize
            node.nodeValue = target.compute(state)
          }
        }
      }
    }
  }
}

exports.properties = { text: { type: 'text' } }
<|endoftext|>


<commit_before>var fs = require('fs');
var util = require('util');
var debug = require('debug')('mocha:multi');
var path = require('path');
var isString = require('is-string');
var mkdirp = require('mkdirp');

// Let mocha decide about tty early
require('mocha/lib/reporters/base');

module.exports = MochaMulti

// Make sure we don't lose these!
var stdout = process.stdout;
var stderr = process.stderr;

function MochaMulti(runner, options) {
  var setup;
  var reporters = (options && options.reporterOptions);
  if (reporters && Object.keys(reporters).length > 0) {
    debug("options %j", options);
    setup = [];
    Object.keys(reporters).forEach(function(reporter) {
      debug("adding reporter %j %j", reporter, reporters[reporter]);

      var stdout;
      var options;
      if (isString(reporters[reporter])) {
        stdout = reporters[reporter];
        options = null;
      } else {
        stdout = reporters[reporter].stdout;
        options = reporters[reporter].options;
      }

      setup.push([ reporter, stdout, options ]);
    });
  } else {
    setup = parseSetup();
  }
  debug("setup %j", setup);
  var streams = initReportersAndStreams(runner, setup);
  // Remove nulls
  streams = streams.filter(identity);

  //we actually need to wait streams only if they are present
  if(streams.length > 0) {
    awaitStreamsOnExit(streams);
  }
}

var msgs = {
  no_definitions: "reporter definitions should be set in \
the `multi` shell variable\n\
eg. `multi='dot=- xunit=file.xml' mocha`",
  invalid_definition: "'%s' is an invalid definition\n\
expected <reporter>=<destination>",
  invalid_reporter: "Unable to find '%s' reporter"
}
function bombOut(id) {
  var args = Array.prototype.slice.call(arguments, 0);
  args[0] = 'ERROR: ' + msgs[id];
  stderr.write(util.format.apply(util, args) + "\n");
  process.exit(1);
}

function parseSetup() {
  var reporterDefinition = process.env.multi || '';
  var reporterDefs = reporterDefinition.trim().split(/\s/).filter(identity);
  if (!reporterDefs.length) {
    bombOut('no_definitions');
  }
  debug("Got reporter defs: %j", reporterDefs);
  return reporterDefs.map(parseReporter);
}

function parseReporter(definition) {
  var pair = definition.split('=');
  if (pair.length != 2) {
    bombOut('invalid_definition', definition);
  }
  return pair;
}

function initReportersAndStreams(runner, setup) {
  return setup.map(function(definition) {
    var reporter=definition[0], outstream=definition[1], options=definition[2]

    debug("Initialising reporter '%s' to '%s' with options %j", reporter, outstream, options);

    var stream = resolveStream(outstream);
    var shim = createRunnerShim(runner, stream);

    debug("Shimming runner into reporter '%s' %j", reporter, options);

    withReplacedStdout(stream, function() {
      var Reporter = resolveReporter(reporter);
      return new Reporter(shim, options || {});
    })

    return stream;
  })
}

function awaitStreamsOnExit(streams) {
  var exit = process.exit;
  var num = streams.length;
  process.exit = function(code) {
    var quit = exit.bind(process, code);
    streams.forEach(function(stream) {
      stream.end(function() {
        num--;
        onClose();
      });
    });
    function onClose() {
      if(num === 0) {
        quit();
      }
    }
  };
}

function resolveReporter(name) {
  // Cribbed from Mocha.prototype.reporter()
  var reporter;
  reporter = safeRequire('mocha/lib/reporters/' + name);
  if (!reporter) {
    reporter = safeRequire(name);
  }
  if (!reporter) {
    bombOut('invalid_reporter', name);
  }
  debug("Resolved reporter '%s' into '%s'", name, util.inspect(reporter));
  return reporter;
}

function safeRequire(module) {
  try {
    return require(module);
  } catch (err) {
    if (!/Cannot find/.exec(err.message)) {
      throw err;
    }
    return null;
  }
}

function resolveStream(destination) {
  if (destination == '-') {
    debug("Resolved stream '-' into stdout and stderr");
    return null;
  }
  debug("Resolved stream '%s' into writeable file stream", destination);
  // Create directory if not existing
  var destinationDir = path.dirname(destination);
  if (!fs.existsSync(destinationDir)){
    mkdirp.sync(destinationDir);
  }

  // Ensure we can write here
  fs.writeFileSync(destination, '');
  return fs.createWriteStream(destination);
}

function createRunnerShim(runner, stream) {
  var shim = new (require('events').EventEmitter)();

  addDelegate('grepTotal');
  addDelegate('suite');
  addDelegate('total');

  function addDelegate(prop) {
    shim.__defineGetter__(prop, function() {
      var property = runner[prop];
      if (typeof property === 'function') {
        property = property.bind(runner);
      }
      return property;
    });
  }

  var delegatedEvents = {};

  shim.on('newListener', function(event) {

    if (event in delegatedEvents) return;

    delegatedEvents[event] = true;
    debug("Shim: Delegating '%s'", event);

    runner.on(event, function() {
      var eventArgs = Array.prototype.slice.call(arguments, 0);
      eventArgs.unshift(event);

      withReplacedStdout(stream, function() {
        shim.emit.apply(shim, eventArgs)
      })

    })

  })

  return shim;
}

function withReplacedStdout(stream, func) {
  if (!stream) {
    return func();
  }

  // The hackiest of hacks
  debug('Replacing stdout');

  var stdoutGetter = Object.getOwnPropertyDescriptor(process, 'stdout').get;
  var stderrGetter = Object.getOwnPropertyDescriptor(process, 'stderr').get;

  console._stdout = stream;
  console._stderr = stream;
  process.__defineGetter__('stdout', function() { return stream });
  process.__defineGetter__('stderr', function() { return stream });

  try {
    func();
  } finally {
    console._stdout = stdout;
    console._stderr = stderr;
    process.__defineGetter__('stdout', stdoutGetter);
    process.__defineGetter__('stderr', stderrGetter);
    debug('stdout restored');
  }
}

function identity(x) {
  return x;
}
<commit_msg>[#23] Invoke done(fn) on reporters that have it on completion<commit_after>var fs = require('fs');
var util = require('util');
var debug = require('debug')('mocha:multi');
var path = require('path');
var isString = require('is-string');
var mkdirp = require('mkdirp');

// Let mocha decide about tty early
require('mocha/lib/reporters/base');

var Base = require('mocha').reporters.Base;

module.exports = MochaMulti

// Make sure we don't lose these!
var stdout = process.stdout;
var stderr = process.stderr;

function MochaMulti(runner, options) {
  var setup;
  // keep track of reporters that have a done method.
  this.reportersWithDone = [];
  var reporters = (options && options.reporterOptions);
  if (reporters && Object.keys(reporters).length > 0) {
    debug("options %j", options);
    setup = [];
    Object.keys(reporters).forEach(function(reporter) {
      debug("adding reporter %j %j", reporter, reporters[reporter]);

      var stdout;
      var options;
      if (isString(reporters[reporter])) {
        stdout = reporters[reporter];
        options = null;
      } else {
        stdout = reporters[reporter].stdout;
        options = reporters[reporter].options;
      }

      setup.push([ reporter, stdout, options ]);
    });
  } else {
    setup = parseSetup();
  }
  debug("setup %j", setup);
  var streams = initReportersAndStreams(runner, setup, this);
  // Remove nulls
  streams = streams.filter(identity);

  //we actually need to wait streams only if they are present
  if(streams.length > 0) {
    awaitStreamsOnExit(streams);
  }
}

util.inherits(MochaMulti, Base);

/**
 * Override done to allow done processing for any reporters that have a done method.
 */
MochaMulti.prototype.done = function (failures, fn) {
  var self = this;

  if(self.reportersWithDone.length !== 0) {
    var count = self.reportersWithDone.length;
    debug('Awaiting on %j reporters to invoke done callback.', count);
    var cb = function() {
      if(--count === 0) {
        debug('All reporters invoked done callback.');
        fn(failures);
      } else {
        debug('Awaiting on %j reporters to invoke done callback.', count);
      }
    };

    self.reportersWithDone.forEach(function(r) {
      r.done(failures, cb);
    });
  } else {
    debug('No reporters have done method, completing.');
    fn(failures);
  }
};

var msgs = {
  no_definitions: "reporter definitions should be set in \
the `multi` shell variable\n\
eg. `multi='dot=- xunit=file.xml' mocha`",
  invalid_definition: "'%s' is an invalid definition\n\
expected <reporter>=<destination>",
  invalid_reporter: "Unable to find '%s' reporter"
}
function bombOut(id) {
  var args = Array.prototype.slice.call(arguments, 0);
  args[0] = 'ERROR: ' + msgs[id];
  stderr.write(util.format.apply(util, args) + "\n");
  process.exit(1);
}

function parseSetup() {
  var reporterDefinition = process.env.multi || '';
  var reporterDefs = reporterDefinition.trim().split(/\s/).filter(identity);
  if (!reporterDefs.length) {
    bombOut('no_definitions');
  }
  debug("Got reporter defs: %j", reporterDefs);
  return reporterDefs.map(parseReporter);
}

function parseReporter(definition) {
  var pair = definition.split('=');
  if (pair.length != 2) {
    bombOut('invalid_definition', definition);
  }
  return pair;
}

function initReportersAndStreams(runner, setup, multi) {
  return setup.map(function(definition) {
    var reporter=definition[0], outstream=definition[1], options=definition[2]

    debug("Initialising reporter '%s' to '%s' with options %j", reporter, outstream, options);

    var stream = resolveStream(outstream);
    var shim = createRunnerShim(runner, stream);

    debug("Shimming runner into reporter '%s' %j", reporter, options);

    withReplacedStdout(stream, function() {
      var Reporter = resolveReporter(reporter);
      var r = new Reporter(shim, options || {});
      // If the reporter possess a done() method register it so we can
      // wait for it to complete when done.
      if(r && r.done) {
        multi.reportersWithDone.push(r);
      }
      return r;
    })

    return stream;
  })
}

function awaitStreamsOnExit(streams) {
  var exit = process.exit;
  var num = streams.length;
  process.exit = function(code) {
    var quit = exit.bind(process, code);
    streams.forEach(function(stream) {
      stream.end(function() {
        num--;
        onClose();
      });
    });
    function onClose() {
      if(num === 0) {
        quit();
      }
    }
  };
}

function resolveReporter(name) {
  // Cribbed from Mocha.prototype.reporter()
  var reporter;
  reporter = safeRequire('mocha/lib/reporters/' + name);
  if (!reporter) {
    reporter = safeRequire(name);
  }
  if (!reporter) {
    bombOut('invalid_reporter', name);
  }
  debug("Resolved reporter '%s' into '%s'", name, util.inspect(reporter));
  return reporter;
}

function safeRequire(module) {
  try {
    return require(module);
  } catch (err) {
    if (!/Cannot find/.exec(err.message)) {
      throw err;
    }
    return null;
  }
}

function resolveStream(destination) {
  if (destination == '-') {
    debug("Resolved stream '-' into stdout and stderr");
    return null;
  }
  debug("Resolved stream '%s' into writeable file stream", destination);
  // Create directory if not existing
  var destinationDir = path.dirname(destination);
  if (!fs.existsSync(destinationDir)){
    mkdirp.sync(destinationDir);
  }

  // Ensure we can write here
  fs.writeFileSync(destination, '');
  return fs.createWriteStream(destination);
}

function createRunnerShim(runner, stream) {
  var shim = new (require('events').EventEmitter)();

  addDelegate('grepTotal');
  addDelegate('suite');
  addDelegate('total');

  function addDelegate(prop) {
    shim.__defineGetter__(prop, function() {
      var property = runner[prop];
      if (typeof property === 'function') {
        property = property.bind(runner);
      }
      return property;
    });
  }

  var delegatedEvents = {};

  shim.on('newListener', function(event) {

    if (event in delegatedEvents) return;

    delegatedEvents[event] = true;
    debug("Shim: Delegating '%s'", event);

    runner.on(event, function() {
      var eventArgs = Array.prototype.slice.call(arguments, 0);
      eventArgs.unshift(event);

      withReplacedStdout(stream, function() {
        shim.emit.apply(shim, eventArgs)
      })

    })

  })

  return shim;
}

function withReplacedStdout(stream, func) {
  if (!stream) {
    return func();
  }

  // The hackiest of hacks
  debug('Replacing stdout');

  var stdoutGetter = Object.getOwnPropertyDescriptor(process, 'stdout').get;
  var stderrGetter = Object.getOwnPropertyDescriptor(process, 'stderr').get;

  console._stdout = stream;
  console._stderr = stream;
  process.__defineGetter__('stdout', function() { return stream });
  process.__defineGetter__('stderr', function() { return stream });

  try {
    func();
  } finally {
    console._stdout = stdout;
    console._stderr = stderr;
    process.__defineGetter__('stdout', stdoutGetter);
    process.__defineGetter__('stderr', stderrGetter);
    debug('stdout restored');
  }
}

function identity(x) {
  return x;
}
<|endoftext|>