<commit_before>const express = require('express');
const path = require('path');

const app = express();
const PORT = process.env.PORT || 5000;

const bodyParser = require('body-parser');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));

/*
  Set up mongo
  */

  const mongoose = require('mongoose');
  mongoose.Promise = Promise;
  mongoose.connect('mongodb://sam:pass@ds145312.mlab.com:45312/heroku_gbvm74zg');

  var Schema = mongoose.Schema;

/**
  Datapoints
  */

  const dataPointSchema = new Schema({
    value: Number,
    created_at: Date,
  });

  const DataPoint = mongoose.model('DataPoint', dataPointSchema);

  const roomSchema = new Schema({
    data_points: [{
      value: Number,
      created_at: Date
    }],
    room_name: String,
    daily_graph: {
      data:[Number],
      updated_at: Date
    }
  });

  const Room = mongoose.model('Room', roomSchema);

app.post('/api/roomdata', (req, res) => {
    res.set('Content-Type', 'application/json');

    const roomName = req.body.room_name;

  // const dp = DataPoint({
  //   value: req.body.value,
  //   created_at: new Date()
  // });

  const dp = {
    value: req.body.value,
    created_at: new Date()
  };

  Room.findOneAndUpdate({room_name: roomName}, {$push:{data_points: dp}}, {safe: true, upsert: true}, (err, model) => {
    if (err) {
      console.log("err");
      res.send({message:"error"});
    }
    Room.findOne({'room_name':roomName}, (err, room) => {
      console.log(room.daily_graph.data.length);
      if(room.daily_graph.data.length == 0){
        const graph = [0.0, 0.2, 0.5, 0.5, 0.6, 0.75, 0.4, 0.2, 0.0, 0.2, 0.5, 0.5, 0.6, 0.75, 0.4, 0.2, 0.0, 0.2, 0.5, 0.5, 0.6, 0.75, 0.4, 0.2];
        room.daily_graph.data = graph;
        room.daily_graph.updated_at = new Date();
        room.save((err) =>{
          if(err){
            console.log("Error updating new data");
          }
        })
      }
      else{
        const current_date = new Date()
        if(((current_date.getTime() - room.daily_graph.updated_at.getTime())/1000.0)>3600){

          const datapoints = room.datapoints;
          const count = 0;
          const total = 0;
          for (var i =0; i < datapoints.length; i++){
            if(datapoints[i].created_at > room.daily_graph.updated_at){
              total+= datapoints[i].value;
              count++;
            }
          }
          const average = count / float(total);
          var new_data = room.daily_graph.slice(1);
          new_data.add(average);
          room.daily_graph.data = new_data;
          room.daily_graph.updated_at = current_date;
          room.save((err)=>{
            console.log("Error updating new data");
          });
        }
      }
      console.log("Success");
      res.send({message: "Success"});
    });
  });
});

// app.post('/api/roomdata', (req, res) => {
//   res.set('Content-Type', 'application/json');
//   console.log('got da dp');
//   console.log(req.body);
//   const dp = DataPoint({
//     value: req.body.value,
//     created_at: new Date()
//   });

//   dp.save(err => {
//     if (err) {
//       throw err;
//       res.send({message: "Error"});
//     }
//     console.log("saved dat bitch");
//     res.send({message: "Success"});
//   });
// });

app.get('/api/roomdata/:room_name', (req, res) => {
  res.set('Content-Type', 'application/json');
  const roomName = req.params.room_name;
  Room.find({room_name: roomName}, (err, room) => {
    if (err) throw err;
    res.send(room);
  });
});

app.get('/api/rooms', (req, res) => {
  res.set('Content-Type', 'application/json');
  Room.find({}, (err, rooms) => {
    if (err) throw err;
    console.log(rooms);
    const roomData = rooms.map(room => {
      return {
        roomName: room.room_name,
        status: Math.random() > .5 ? 1 : 0
      }
    });
    console.log(roomData)
    res.send(roomData);
  })
});

app.get('/api/rooms/:room/currentDayDataPoints', (req, res) => {
  res.set('Content-Type', 'application/json');
  //User.find({ admin: true }).where('updated_at').gt(monthAgo).exec(function(err, users) {
  Room.findOne({"room_name":req.params.room}, (err, doc) =>{
    res.send(doc.daily_graph);
  })
});

app.get('/api/rooms/:room/currentWeekDataPoints', (req,res) => {
  res.set('Content-Type', 'application/json');
  res.send([0.0, 0.2, 0.5, 0.5, 0.6, 0.75, 0.4, 0.2, 0.0, 0.2, 0.5, 0.5, 0.6, 0.75, 0.4, 0.2, 0.0, 0.2, 0.5, 0.5, 0.6, 0.75, 0.4, 0.2]);
})

/**
 End Datapoints
 */

/**

*/

// Priority serve any static files.
app.use(express.static(path.resolve(__dirname, '../react-ui/build')));

// All remaining requests return the React app, so it can handle routing.
app.get('*', function(request, response) {
  response.sendFile(path.resolve(__dirname, '../react-ui/build', 'index.html'));
});

app.listen(PORT, function () {
  console.log(`Listening on port ${PORT}`);
});
<commit_msg>logic for weekly data<commit_after>const express = require('express');
const path = require('path');

const app = express();
const PORT = process.env.PORT || 5000;

const bodyParser = require('body-parser');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));

/*
  Set up mongo
  */

  const mongoose = require('mongoose');
  mongoose.Promise = Promise;
  mongoose.connect('mongodb://sam:pass@ds145312.mlab.com:45312/heroku_gbvm74zg');

  var Schema = mongoose.Schema;

/**
  Datapoints
  */

  const dataPointSchema = new Schema({
    value: Number,
    created_at: Date,
  });

  const DataPoint = mongoose.model('DataPoint', dataPointSchema);

  const roomSchema = new Schema({
    data_points: [{
      value: Number,
      created_at: Date
    }],
    room_name: String,
    daily_graph: {
      data:[Number],
      updated_at: Date
    },
    occupied:Number
  });

  const Room = mongoose.model('Room', roomSchema);

app.post('/api/roomdata', (req, res) => {
    res.set('Content-Type', 'application/json');

    const roomName = req.body.room_name;

  // const dp = DataPoint({
  //   value: req.body.value,
  //   created_at: new Date()
  // });

  const dp = {
    value: req.body.value,
    created_at: new Date()
  };

  Room.findOneAndUpdate({room_name: roomName}, {$push:{data_points: dp}, $set:{occupied:req.body.value}}, {safe: true, upsert: true}, (err, model) => {
    if (err) {
      console.log("err");
      res.send({message:"error"});
    }
    Room.findOne({'room_name':roomName}, (err, room) => {
      console.log(room.daily_graph.data.length);
      if(room.daily_graph.data.length == 0){
        const graph = [0.0, 0.2, 0.5, 0.5, 0.6, 0.75, 0.4, 0.2, 0.0, 0.2, 0.5, 0.5, 0.6, 0.75, 0.4, 0.2, 0.0, 0.2, 0.5, 0.5, 0.6, 0.75, 0.4, 0.2];
        room.daily_graph.data = graph;
        room.daily_graph.updated_at = new Date();
        room.save((err) =>{
          if(err){
            console.log("Error updating new data");
          }
        })
      }
      else{
        const current_date = new Date()
        if(((current_date.getTime() - room.daily_graph.updated_at.getTime())/1000.0)>3600){

          const datapoints = room.datapoints;
          const count = 0;
          const total = 0;
          for (var i =0; i < datapoints.length; i++){
            if(datapoints[i].created_at > room.daily_graph.updated_at){
              total+= datapoints[i].value;
              count++;
            }
          }
          const average = count / float(total);
          var new_data = room.daily_graph.slice(1);
          new_data.add(average);
          room.daily_graph.data = new_data;
          room.daily_graph.updated_at = current_date;
          room.save((err)=>{
            console.log("Error updating new data");
          });
        }
      }
      console.log("Success");
      res.send({message: "Success"});
    });
  });
});

// app.post('/api/roomdata', (req, res) => {
//   res.set('Content-Type', 'application/json');
//   console.log('got da dp');
//   console.log(req.body);
//   const dp = DataPoint({
//     value: req.body.value,
//     created_at: new Date()
//   });

//   dp.save(err => {
//     if (err) {
//       throw err;
//       res.send({message: "Error"});
//     }
//     console.log("saved dat bitch");
//     res.send({message: "Success"});
//   });
// });

app.get('/api/roomdata/:room_name', (req, res) => {
  res.set('Content-Type', 'application/json');
  const roomName = req.params.room_name;
  Room.find({room_name: roomName}, (err, room) => {
    if (err) throw err;
    res.send(room);
  });
});

app.get('/api/rooms', (req, res) => {
  res.set('Content-Type', 'application/json');
  Room.find({}, (err, rooms) => {
    if (err) throw err;
    console.log(rooms);
    const roomData = rooms.map(room => {
      return {
        roomName: room.room_name,
        status: Math.random() > .5 ? 1 : 0
      }
    });
    console.log(roomData)
    res.send(roomData);
  })
});

app.get('/api/rooms/:room/currentDayDataPoints', (req, res) => {
  res.set('Content-Type', 'application/json');
  //User.find({ admin: true }).where('updated_at').gt(monthAgo).exec(function(err, users) {
  Room.findOne({"room_name":req.params.room}, (err, doc) =>{
    res.send(doc.daily_graph);
  })
});

app.get('/api/rooms/:room/currentWeekDataPoints', (req,res) => {
  res.set('Content-Type', 'application/json');
  res.send([0.0, 0.2, 0.5, 0.5, 0.6, 0.75, 0.4, 0.2, 0.0, 0.2, 0.5, 0.5, 0.6, 0.75, 0.4, 0.2, 0.0, 0.2, 0.5, 0.5, 0.6, 0.75, 0.4, 0.2]);
})

/**
 End Datapoints
 */

/**

*/

// Priority serve any static files.
app.use(express.static(path.resolve(__dirname, '../react-ui/build')));

// All remaining requests return the React app, so it can handle routing.
app.get('*', function(request, response) {
  response.sendFile(path.resolve(__dirname, '../react-ui/build', 'index.html'));
});

app.listen(PORT, function () {
  console.log(`Listening on port ${PORT}`);
});
<|endoftext|>


<commit_before>import { isEnabled } from '@ember/canary-features';
import applyMixins from './apply-mixins';
import getAllPropertyNames from './get-all-property-names';
import { all } from 'rsvp';

export default function moduleFor(description, TestClass, ...mixins) {
  QUnit.module(description, {
    beforeEach: function(assert) {
      let instance = new TestClass(assert);
      this.instance = instance;
      if (instance.beforeEach) {
        return instance.beforeEach(assert);
      }
    },

    afterEach: function() {
      let promises = [];
      let instance = this.instance;
      this.instance = null;
      if (instance.teardown) {
        promises.push(instance.teardown());
      }
      if (instance.afterEach) {
        promises.push(instance.afterEach());
      }

      // this seems odd, but actually saves significant time
      // in the test suite
      //
      // returning a promise from a QUnit test always adds a 13ms
      // delay to the test, this filtering prevents returning a
      // promise when it is not needed
      //
      // Remove after we can update to QUnit that includes
      // https://github.com/qunitjs/qunit/pull/1246
      let filteredPromises = promises.filter(Boolean);
      if (filteredPromises.length > 0) {
        return all(filteredPromises);
      }
    },
  });

  if (mixins.length > 0) {
    applyMixins(TestClass, ...mixins);
  }

  let properties = getAllPropertyNames(TestClass);
  properties.forEach(generateTest);

  function shouldTest(features) {
    return features.every(feature => {
      if (feature[0] === '!' && isEnabled(feature.slice(1))) {
        return false;
      } else if (!isEnabled(feature)) {
        return false;
      } else {
        return true;
      }
    });
  }

  function generateTest(name) {
    if (name.indexOf('@test ') === 0) {
      QUnit.test(name.slice(5), function(assert) {
        return this.instance[name](assert);
      });
    } else if (name.indexOf('@only ') === 0) {
      // eslint-disable-next-line qunit/no-only
      QUnit.only(name.slice(5), function(assert) {
        return this.instance[name](assert);
      });
    } else if (name.indexOf('@skip ') === 0) {
      QUnit.skip(name.slice(5), function(assert) {
        return this.instance[name](assert);
      });
    } else {
      let match = /^@feature\(([A-Z_a-z-!]+)\) /.exec(name);

      if (match) {
        let features = match[1].replace(/ /g, '').split(',');

        if (shouldTest(features)) {
          QUnit.test(name.slice(match[0].length), function(assert) {
            return this.instance[name](assert);
          });
        }
      }
    }
  }
}
<commit_msg>internal-test-helpers: Remove obsolete promise filtering<commit_after>import { isEnabled } from '@ember/canary-features';
import applyMixins from './apply-mixins';
import getAllPropertyNames from './get-all-property-names';
import { all } from 'rsvp';

export default function moduleFor(description, TestClass, ...mixins) {
  QUnit.module(description, {
    beforeEach: function(assert) {
      let instance = new TestClass(assert);
      this.instance = instance;
      if (instance.beforeEach) {
        return instance.beforeEach(assert);
      }
    },

    afterEach: function() {
      let promises = [];
      let instance = this.instance;
      this.instance = null;
      if (instance.teardown) {
        promises.push(instance.teardown());
      }
      if (instance.afterEach) {
        promises.push(instance.afterEach());
      }

      return all(promises);
    },
  });

  if (mixins.length > 0) {
    applyMixins(TestClass, ...mixins);
  }

  let properties = getAllPropertyNames(TestClass);
  properties.forEach(generateTest);

  function shouldTest(features) {
    return features.every(feature => {
      if (feature[0] === '!' && isEnabled(feature.slice(1))) {
        return false;
      } else if (!isEnabled(feature)) {
        return false;
      } else {
        return true;
      }
    });
  }

  function generateTest(name) {
    if (name.indexOf('@test ') === 0) {
      QUnit.test(name.slice(5), function(assert) {
        return this.instance[name](assert);
      });
    } else if (name.indexOf('@only ') === 0) {
      // eslint-disable-next-line qunit/no-only
      QUnit.only(name.slice(5), function(assert) {
        return this.instance[name](assert);
      });
    } else if (name.indexOf('@skip ') === 0) {
      QUnit.skip(name.slice(5), function(assert) {
        return this.instance[name](assert);
      });
    } else {
      let match = /^@feature\(([A-Z_a-z-!]+)\) /.exec(name);

      if (match) {
        let features = match[1].replace(/ /g, '').split(',');

        if (shouldTest(features)) {
          QUnit.test(name.slice(match[0].length), function(assert) {
            return this.instance[name](assert);
          });
        }
      }
    }
  }
}
<|endoftext|>


<commit_before>Package.describe({
  name: 'angular2-compilers',
  version: '0.6.6',
  summary: 'Angular 2 Templates, HTML and TypeScript compilers for Meteor',
  git: 'https://github.com/Urigo/angular2-meteor/',
  documentation: 'README.md'
});

Package.registerBuildPlugin({
  name: 'Angular2 Compilers',
  sources: [
    'plugin/register.js'
  ],
  use: [
    // Uses an external packages to get the actual compilers
    'ecmascript@0.4.3',
    'urigo:static-html-compiler@0.1.8',
    'barbatus:css-compiler@0.3.5_1'
  ]
});

Package.onUse(function(api) {
  api.versionsFrom('1.3.1');

  // Required in order to register plugins
  api.use('isobuild:compiler-plugin@1.0.0');

  // These packages are required by Angular2-Meteor NPM.
  // Make sure we have them in this package.
  api.imply([
    'barbatus:typescript@0.5.2',
    'check@1.1.0',
    'tracker@1.0.13'
  ]);
});

Package.onTest(function(api) {
  api.use('tinytest');
  api.use('angular2-compilers');
});
<commit_msg>chore: bump css-compilers<commit_after>Package.describe({
  name: 'angular2-compilers',
  version: '0.6.6',
  summary: 'Angular 2 Templates, HTML and TypeScript compilers for Meteor',
  git: 'https://github.com/Urigo/angular2-meteor/',
  documentation: 'README.md'
});

Package.registerBuildPlugin({
  name: 'Angular2 Compilers',
  sources: [
    'plugin/register.js'
  ],
  use: [
    // Uses an external packages to get the actual compilers
    'ecmascript@0.4.3',
    'urigo:static-html-compiler@0.1.8',
    'barbatus:css-compiler@0.3.6'
  ]
});

Package.onUse(function(api) {
  api.versionsFrom('1.3.1');

  // Required in order to register plugins
  api.use('isobuild:compiler-plugin@1.0.0');

  // These packages are required by Angular2-Meteor NPM.
  // Make sure we have them in this package.
  api.imply([
    'barbatus:typescript@0.5.2',
    'check@1.1.0',
    'tracker@1.0.13'
  ]);
});

Package.onTest(function(api) {
  api.use('tinytest');
  api.use('angular2-compilers');
});
<|endoftext|>


<commit_before>import React from 'react';
import ReactDOM from 'react-dom';
import Index from './components/index'
import { createStore } from 'redux';
import { Provider } from 'react-redux';
import todoApp from './components/Reducers/reducer';

let store = createStore(todoApp);

ReactDOM.render(
    <Provider store={store}>
        <Index />
    </Provider>,
    document.getElementById('content')
);
<commit_msg>增加state更新日志<commit_after>import React from 'react';
import ReactDOM from 'react-dom';
import Index from './components/index'
import { createStore } from 'redux';
import { Provider } from 'react-redux';
import todoApp from './components/Reducers/reducer';

let store = createStore(todoApp);

// 每次state更新时，打印日志
let unSubscribe = store.subscribe(() => {
    console.log(store.getState())
});

ReactDOM.render(
    <Provider store={store}>
        <Index />
    </Provider>,
    document.getElementById('content')
);
<|endoftext|>


<commit_before>import _      from 'lodash';
import Api    from './api';

function proxyUrl(url){
  return `api/canvas?url=${encodeURIComponent(url)}`;
}

function get_next_url(link){
  if(link){
    const url = _.find(link.split(','), (l) => {
      return _.trim(l.split(";")[1]) == 'rel="next"';
    })
    if(url){
      return url.split(';')[0].replace(/[\<\>\s]/g, "");
    }
  }
}

export default class CanvasApi{

  static get(url, key, cb){
    Api.get(key, proxyUrl(url)).then(
    (response) => {
      cb(response);
      if(response.header){
        var next_url = get_next_url(response.headers['link']);
        if(next_url){
          this.get(next_url, key, cb);
        } else {
          return;
        }
      }
    },
    (error) => {
      console.log(error);
    });
  }

  static post(url, body, key){
    return Api.post(key, proxyUrl(url), body);
  }

  static put(url, body, key){
    return Api.put(key, proxyUrl(url), body);
  }

}<commit_msg>Parse text if body is undefined<commit_after>import _      from 'lodash';
import Api    from './api';

function proxyUrl(url){
  return `api/canvas?url=${encodeURIComponent(url)}`;
}

function get_next_url(link){
  if(link){
    const url = _.find(link.split(','), (l) => {
      return _.trim(l.split(";")[1]) == 'rel="next"';
    })
    if(url){
      return url.split(';')[0].replace(/[\<\>\s]/g, "");
    }
  }
}

export default class CanvasApi{

  static get(url, key, cb){
    Api.get(key, proxyUrl(url)).then(
    (response) => {
      cb(response.body || JSON.parse(response.text));
      if(response.header){
        var next_url = get_next_url(response.headers['link']);
        if(next_url){
          this.get(next_url, key, cb);
        } else {
          return;
        }
      }
    },
    (error) => {
      console.log(error);
    });
  }

  static post(url, body, key){
    return Api.post(key, proxyUrl(url), body);
  }

  static put(url, body, key){
    return Api.put(key, proxyUrl(url), body);
  }

}<|endoftext|>


<commit_before>'use strict';

/* eslint-disable prefer-arrow-callback */
/* TODO: Use arrow-functions for tasks once gulp-param fixes bug that causes them not to work */

const gulp = require('gulp-help')(require('gulp-param')(require('gulp'), process.argv));
const async = require('async');
const del = require('del');
const merge = require('merge2');
const path = require('path');

// load gulp plugins
var jeditor = require("gulp-json-editor");
const G$ = require('gulp-load-plugins')({ lazy: true });
const chalk = G$.util.colors;

// constants
const PROJECT_VAR = '{project}';

// load settings
const settings = require('./gulp.json');
const tsconfig = require('./tsconfig.master.json');
const projects = require('./projects.json');
const projectNames = Object.keys(projects);

function expandPaths(globArray) {
    const expandedGlob = [];
    globArray.forEach(item => {
        if (item.indexOf(PROJECT_VAR) > 0) {
            projectNames.forEach(project => {
                expandedGlob.push(item.replace(PROJECT_VAR, project));
            });
        } else {
            expandedGlob.push(item);
        }
    });
    return expandedGlob;
}

function wildcharPaths(globArray) {
    const expandedGlob = [];
    globArray.forEach(item => {
        if (item.indexOf(PROJECT_VAR) > 0) {
            expandedGlob.push(item.replace(PROJECT_VAR, '*'));
        } else {
            expandedGlob.push(item);
        }
    });
    return expandedGlob;
}

function mapPaths(globArray, project) {
    return globArray.map(path =>
        mapPath(path, project));
}

function mapPath(path, project) {
    return path.replace(PROJECT_VAR, project);
}

function plumberErrorHandler(err) {
    console.log(err.stack);
    this.emit('end'); // For gulp watch
}

const exec = require('child_process').exec;
function runCommand(command, options, callback) {
    exec(command, options, function (error, stdout, stderr) {
        console.log(`${path.resolve(options.cwd || '.')} ${command}`);
        console.log(stdout);
        console.log(stderr);
        if (error !== null) {
            console.log('exec error: ', error);
        }
        callback();
    });
}

/*
 * {cmd: "", cwd: ""}
 */
function runCommands(commands, callback) {
    async.eachSeries(commands, function (command, done) {
        runCommand(command.cmd, { cwd: command.cwd }, done);
    }, function () {
        callback();
    });
}

// Setup

gulp.task('setup', 'Install all modules and link projects', function (callback) {
    G$.sequence('install', 'link', callback);
});

gulp.task('teardown', 'Clean all and unlink projects', function (callback) {
    G$.sequence('unlink', 'deepclean', callback);
});

// npm install

gulp.task('install', 'Install all npm modules', function (callback) {
    const commands = [];
    commands.push({ cmd: 'npm install', cwd: undefined });
    projectNames.forEach(name => {
        commands.push({ cmd: 'npm install', cwd: `projects/${name}` });
    });
    runCommands(commands, callback);
});

// npm link

gulp.task('link', 'Link dependencies on local disk', function (callback) {
    linker(true, callback);
});

gulp.task('unlink', 'Unlink dependencies on local disk', function (callback) {
    linker(false, callback);
});

function linker(mode, callback) {
    const linkedDeps = {};
    const commands = [];
    projectNames.forEach(proj => {
        if (projects[proj].dependencies) {
            projects[proj].dependencies.forEach(dep => {
                if (!linkedDeps[dep]) {
                    commands.push({ cmd: `npm ${mode ? 'link' : 'unlink'} --no-bin-links`, cwd: `projects/${dep}` });
                    linkedDeps[dep] = true;
                }
                if (mode) {
                    const packageName = require(`./projects/${dep}/package.json`).name;
                    commands.push({ cmd: `npm ${mode ? 'link' : 'unlink'} ${packageName} --no-bin-links`, cwd: `projects/${proj}` });
                }
            });
        }
    });
    runCommands(commands, callback);
    // info about "--no-bin-links" : see http://stackoverflow.com/questions/17990647/npm-install-errors-with-error-enoent-chmod
}

// Building

gulp.task('build', 'Compiles all TypeScript source files and updates module references', function (callback) {
    G$.sequence(['tslint', 'clean'], 'ts-all', callback);
});

gulp.task('watch', 'Contiuous build', ['build'], function () {
    projectNames.forEach(project => {
        gulp.watch(mapPaths(Array.prototype.concat(settings.tsfiles, settings.jsFiles), project), [`ts-${project}`]);
    });
});

// see https://www.npmjs.com/package/tslint
gulp.task('tslint', 'Lints all TypeScript source files', function () {
    return gulp.src(wildcharPaths(settings.tsfiles))
        .pipe(G$.tslint({ formatter: 'verbose' }))
        .pipe(G$.tslint.report({ emitError: false }));
});

// Cleaning

gulp.task('clean', 'Cleans the generated files from lib directory', function () {
    return del(expandPaths(settings.clean));
});

gulp.task('deepclean', 'Cleans the generated files from lib directory and all node_modules', function () {
    return del(expandPaths(settings.deepClean));
});

// Transpiling
projectNames.forEach(project => {
    gulp.task(`ts-${project}`, `Transpile ${chalk.green(project)}`, function () {
        const tsResult = gulp.src(mapPaths(settings.tsfiles, project))
            .pipe(G$.sourcemaps.init())
            .pipe(G$.typescript.createProject(tsconfig.compilerOptions)());
        const dest = mapPath(settings.dest, project);
        return merge([
            tsResult.dts.pipe(gulp.dest(dest)),
            tsResult.js
                .pipe(G$.sourcemaps.write('.')) // separate .js.map files
                .pipe(gulp.dest(dest)),
            // JS files
            gulp.src(mapPaths(settings.jsFiles, project)).pipe(G$.babel({
                presets: ['es2015']
            })).pipe(gulp.dest(dest)),
            // all other files
            gulp.src(mapPaths(settings.resources, project)).pipe(gulp.dest(dest))
        ]);
    });
});

gulp.task('ts-all', 'Transpile all projects', function (callback) {
    G$.sequence(projectNames.map(name => `ts-${name}`), callback);
});

// Extras

gulp.task('npm-i', `Install and save a ${chalk.cyan('pack')}age to a ${chalk.cyan('project')}`, function (project, pack, callback) {
    runCommand(`npm install --save ${pack}`, { cwd: mapPath(settings.projectPath, project) }, function () {
        callback();
    });
}, {
        options: {
            pack: 'Package name',
            project: `Project name: ${chalk.green(projectNames.join(chalk.white(', ')))}`
        }
    });

gulp.task('npm-u', `Uninstall and save a ${chalk.cyan('pack')}age to a ${chalk.cyan('project')}`, function (project, pack, callback) {
    runCommand(`npm uninstall --save ${pack}`, { cwd: mapPath(settings.projectPath, project) }, function () {
        callback();
    });
}, {
        options: {
            pack: 'Package name',
            project: `Project name: ${chalk.green(projectNames.join(chalk.white(', ')))}`
        }
    });

gulp.task('stats', 'Get lines of code', function (project) {
    console.log(project);
    if (project) {
        console.log(`Source Lines of Code: ${chalk.green(project)}`);
        gulp.src(mapPaths(settings.sloc_project, project)).pipe(G$.sloc({ tolerant: true }));
    } else {
        console.log(`Source Lines of Code: ${chalk.white('ALL')}`);
        gulp.src(settings.sloc_all).pipe(G$.sloc({ tolerant: true }));
    }
}, {
        options: {
            project: `Project name: ${chalk.green(projectNames.join(chalk.white(', ')))}`
        }
    });

gulp.task('size', 'Get size of code', function (project) {
    console.log(project);
    if (project) {
        console.log(`Source Lines of Code: ${chalk.green(project)}`);
        gulp.src(mapPaths(settings.runtimeFiles, project)).pipe(G$.size({ showFiles: true }));
    } else {
        console.log(`Source Lines of Code: ${chalk.white('ALL')}`);
        gulp.src(expandPaths(settings.runtimeFiles)).pipe(G$.size({ showFiles: true }));
    }
}, {
        options: {
            project: `Project name: ${chalk.green(projectNames.join(chalk.white(', ')))}`
        }
    });

// Deploying

function getPackageName(packagePath) {
    const packageFile = require(path.join(path.resolve(packagePath), 'package.json'));
    return `${packageFile.name}_${packageFile.version}`;
}

gulp.task('package', false, function () {
    const packageFileName = `${getPackageName(settings.edgeDir)}.tar`;
    return gulp.src(settings.packageFiles, { follow: true })
        .pipe(gulp.dest(`dist/droplit-edge`))
        .pipe(G$.debug({ title: 'package:' }))
        .pipe(G$.tar(packageFileName))
        .pipe(G$.gzip())
        .pipe(gulp.dest('dist'));
});

gulp.task('clean-dist', false, function () {
    return del('dist');
});

gulp.task('move-temp', false, function () {
    return gulp.src(settings.edgeFiles, { follow: true })
        .pipe(gulp.dest('temp/droplit-edge'));
});

gulp.task('clean-temp', false, function () {
    return del('temp');
});

gulp.task('setup-package', false, function () {
    return gulp.src('./temp/droplit-edge/package.json')
        .pipe(jeditor(function (json) {
            const localConfig = require('./temp/droplit-edge/localsettings.json');
            if (Array.isArray(localConfig.plugins))
                localConfig.plugins.forEach(plugin => {
                    if (typeof plugin === 'string') {
                        json.dependencies[plugin] = `../../projects/${plugin}`;
                        return;
                    }

                    if (typeof plugin === 'object' && plugin.hasOwnProperty('name') && plugin.enabled !== false)
                        json.dependencies[plugin.name] = `../../projects/${plugin.name}`;
                });
            else
                Object.keys(localConfig.plugins).forEach(plugin => {
                    if (localConfig.plugins[plugin] && localConfig.plugins[plugin].enabled !== false) {
                        json.dependencies[plugin] = `../../projects/${plugin}`;
                    }
                });
            return json;
        }))
        .pipe(gulp.dest('temp/droplit-edge/'));
});

gulp.task('pre-install-dist', false, function () {
    return del('temp/droplit-edge/node_modules');
});

gulp.task('install-dist', false, function (callback) {

    runCommand('npm install', { cwd: 'temp/droplit-edge' }, callback)
});

gulp.task('build-dist', false, function (callback) {
    G$.sequence('clean-dist', 'build', 'unlink', 'move-temp', 'setup-package', 'pre-install-dist', 'install-dist', 'package', 'clean-temp', callback);
});

gulp.task('deploy', 'Glob the Droplit Edge for embedding', function (callback) {
    G$.sequence('setup', 'build-dist', callback);
});

// Testing for improving package
gulp.task('prep', false, function () {
    return del(expandPaths(settings.prep));
});

// Version bump

const bumpOpts = {
    options: {
        major: 'when you make incompatible API changes',
        minor: 'when you add functionality in a backwards-compatible manner',
        patch: 'when you make backwards-compatible bug fixes',
        project: `Project name: ${chalk.green(projectNames.join(chalk.white(', ')))}`
    }
};

gulp.task('bump', 'Version bump a project.', function (major, minor, patch, project) {
    if (!project) return console.log(`${chalk.red('No project specified!')}`);
    let type = '';
    if (major && !minor && !patch) type = 'major';
    if (!major && minor && !patch) type = 'minor';
    if (!major && !minor && patch) type = 'patch';
    if (!type) return console.log(`${chalk.red('Specify one version type to bump!')}`);
    const cwd = 'projects/project/';
    return gulp.src('./package.json', { cwd })
        .pipe(G$.bump({ type }))
        .pipe(gulp.dest('./', { cwd }));
}, bumpOpts);

gulp.task('debug', 'Debug droplit-edge', function () {
    const project = 'droplit-edge';
    G$.nodemon({
        script: `${project}.js`,
        ext: 'js',
        env: {
            DEBUG: 'droplit:*'
        },
        delay: 1, // Sec
        watch: `projects/${project}`,
        ignore: `projects/${project}/src`
    });
});

// .pipe(G$.plumber()) // exit gracefully if something fails after this

// gulp.task('test', 'Runs all tests', [], function () {
//     $.util.log(colors.cyan(`Testing ${settings.testGlob}`));

//     return gulp
//         .src(settings.testGlob, { read: true })
//         .pipe($.plumber()) // exit gracefully if something fails after this
//         .pipe($.mocha({ reporter: 'spec' }));
// });

// Attitional reference: https://github.com/johnpapa/gulp-patterns
// http://www.bennadel.com/blog/2169-where-does-node-js-and-require-look-for-modules.htm<commit_msg>Fix linting<commit_after>'use strict';

/* eslint-disable prefer-arrow-callback */
/* TODO: Use arrow-functions for tasks once gulp-param fixes bug that causes them not to work */

const gulp = require('gulp-help')(require('gulp-param')(require('gulp'), process.argv));
const async = require('async');
const del = require('del');
const merge = require('merge2');
const path = require('path');

// load gulp plugins
const jeditor = require('gulp-json-editor');
const G$ = require('gulp-load-plugins')({ lazy: true });
const chalk = G$.util.colors;

// constants
const PROJECT_VAR = '{project}';

// load settings
const settings = require('./gulp.json');
const tsconfig = require('./tsconfig.master.json');
const projects = require('./projects.json');
const projectNames = Object.keys(projects);

function expandPaths(globArray) {
    const expandedGlob = [];
    globArray.forEach(item => {
        if (item.indexOf(PROJECT_VAR) > 0) {
            projectNames.forEach(project => {
                expandedGlob.push(item.replace(PROJECT_VAR, project));
            });
        } else {
            expandedGlob.push(item);
        }
    });
    return expandedGlob;
}

function wildcharPaths(globArray) {
    const expandedGlob = [];
    globArray.forEach(item => {
        if (item.indexOf(PROJECT_VAR) > 0) {
            expandedGlob.push(item.replace(PROJECT_VAR, '*'));
        } else {
            expandedGlob.push(item);
        }
    });
    return expandedGlob;
}

function mapPaths(globArray, project) {
    return globArray.map(path =>
        mapPath(path, project));
}

function mapPath(path, project) {
    return path.replace(PROJECT_VAR, project);
}

function plumberErrorHandler(err) {
    console.log(err.stack);
    this.emit('end'); // For gulp watch
}

const exec = require('child_process').exec;

function runCommand(command, options, callback) {
    try {
        exec(command, options, function (error, stdout, stderr) {
            console.log(`${path.resolve(options.cwd || '.')} ${command}`);
            console.log(stdout);
            console.log(stderr);
            if (error !== null) {
                console.log('exec error: ', error);
            }
            callback();
        });
    } catch (ex) {
        console.log('rc ex', ex);
    }
}

/*
 * {cmd: "", cwd: ""}
 */
function runCommands(commands, callback) {
    async.eachSeries(commands, function (command, done) {
        runCommand(command.cmd, { cwd: command.cwd }, done);
    }, function () {
        callback();
    });
}

// Setup

gulp.task('setup', 'Install all modules and link projects', function (callback) {
    G$.sequence('install', 'link', callback);
});

gulp.task('teardown', 'Clean all and unlink projects', function (callback) {
    G$.sequence('unlink', 'deepclean', callback);
});

// npm install

gulp.task('install', 'Install all npm modules', function (callback) {
    const commands = [];
    commands.push({ cmd: 'npm install', cwd: undefined });
    projectNames.forEach(name => {
        commands.push({ cmd: 'npm install', cwd: `projects/${name}` });
    });
    runCommands(commands, callback);
});

// npm link

gulp.task('link', 'Link dependencies on local disk', function (callback) {
    linker(true, callback);
});

gulp.task('unlink', 'Unlink dependencies on local disk', function (callback) {
    linker(false, callback);
});

function linker(mode, callback) {
    const linkedDeps = {};
    const commands = [];
    projectNames.forEach(proj => {
        if (projects[proj].dependencies) {
            projects[proj].dependencies.forEach(dep => {
                if (!linkedDeps[dep]) {
                    commands.push({ cmd: `npm ${mode ? 'link' : 'unlink'} --no-bin-links`, cwd: `projects/${dep}` });
                    linkedDeps[dep] = true;
                }
                if (mode) {
                    const packageName = require(`./projects/${dep}/package.json`).name;
                    commands.push({ cmd: `npm ${mode ? 'link' : 'unlink'} ${packageName} --no-bin-links`, cwd: `projects/${proj}` });
                }
            });
        }
    });
    runCommands(commands, callback);
    // info about "--no-bin-links" : see http://stackoverflow.com/questions/17990647/npm-install-errors-with-error-enoent-chmod
}

// Building

gulp.task('build', 'Compiles all TypeScript source files and updates module references', function (callback) {
    G$.sequence(['tslint', 'clean'], 'ts-all', callback);
});

gulp.task('watch', 'Contiuous build', ['build'], function () {
    projectNames.forEach(project => {
        gulp.watch(mapPaths(Array.prototype.concat(settings.tsfiles, settings.jsFiles), project), [`ts-${project}`]);
    });
});

// see https://www.npmjs.com/package/tslint
gulp.task('tslint', 'Lints all TypeScript source files', function () {
    return gulp.src(wildcharPaths(settings.tsfiles))
        .pipe(G$.tslint({ formatter: 'verbose' }))
        .pipe(G$.tslint.report({ emitError: false }));
});

// Cleaning

gulp.task('clean', 'Cleans the generated files from lib directory', function () {
    return del(expandPaths(settings.clean));
});

gulp.task('deepclean', 'Cleans the generated files from lib directory and all node_modules', function () {
    return del(expandPaths(settings.deepClean));
});

// Transpiling
projectNames.forEach(project => {
    gulp.task(`ts-${project}`, `Transpile ${chalk.green(project)}`, function () {
        const tsResult = gulp.src(mapPaths(settings.tsfiles, project))
            .pipe(G$.sourcemaps.init())
            .pipe(G$.typescript.createProject(tsconfig.compilerOptions)());
        const dest = mapPath(settings.dest, project);
        return merge([
            tsResult.dts.pipe(gulp.dest(dest)),
            tsResult.js
                .pipe(G$.sourcemaps.write('.')) // separate .js.map files
                .pipe(gulp.dest(dest)),
            // JS files
            gulp.src(mapPaths(settings.jsFiles, project)).pipe(G$.babel({
                presets: ['es2015']
            })).pipe(gulp.dest(dest)),
            // all other files
            gulp.src(mapPaths(settings.resources, project)).pipe(gulp.dest(dest))
        ]);
    });
});

gulp.task('ts-all', 'Transpile all projects', function (callback) {
    G$.sequence(projectNames.map(name => `ts-${name}`), callback);
});

// Extras

gulp.task('npm-i', `Install and save a ${chalk.cyan('pack')}age to a ${chalk.cyan('project')}`, function (project, pack, callback) {
    runCommand(`npm install --save ${pack}`, { cwd: mapPath(settings.projectPath, project) }, function () {
        callback();
    });
}, {
    options: {
        pack: 'Package name',
        project: `Project name: ${chalk.green(projectNames.join(chalk.white(', ')))}`
    }
});

gulp.task('npm-u', `Uninstall and save a ${chalk.cyan('pack')}age to a ${chalk.cyan('project')}`, function (project, pack, callback) {
    runCommand(`npm uninstall --save ${pack}`, { cwd: mapPath(settings.projectPath, project) }, function () {
        callback();
    });
}, {
    options: {
        pack: 'Package name',
        project: `Project name: ${chalk.green(projectNames.join(chalk.white(', ')))}`
    }
});

gulp.task('stats', 'Get lines of code', function (project) {
    console.log(project);
    if (project) {
        console.log(`Source Lines of Code: ${chalk.green(project)}`);
        gulp.src(mapPaths(settings.sloc_project, project)).pipe(G$.sloc({ tolerant: true }));
    } else {
        console.log(`Source Lines of Code: ${chalk.white('ALL')}`);
        gulp.src(settings.sloc_all).pipe(G$.sloc({ tolerant: true }));
    }
}, {
    options: {
        project: `Project name: ${chalk.green(projectNames.join(chalk.white(', ')))}`
    }
});

gulp.task('size', 'Get size of code', function (project) {
    console.log(project);
    if (project) {
        console.log(`Source Lines of Code: ${chalk.green(project)}`);
        gulp.src(mapPaths(settings.runtimeFiles, project)).pipe(G$.size({ showFiles: true }));
    } else {
        console.log(`Source Lines of Code: ${chalk.white('ALL')}`);
        gulp.src(expandPaths(settings.runtimeFiles)).pipe(G$.size({ showFiles: true }));
    }
}, {
    options: {
        project: `Project name: ${chalk.green(projectNames.join(chalk.white(', ')))}`
    }
});

// Deploying

function getPackageName(packagePath) {
    const packageFile = require(path.join(path.resolve(packagePath), 'package.json'));
    return `${packageFile.name}_${packageFile.version}`;
}

gulp.task('package', false, function () {
    const packageFileName = `${getPackageName(settings.edgeDir)}.tar`;
    return gulp.src(settings.packageFiles, { follow: true })
        .pipe(gulp.dest('dist/droplit-edge'))
        .pipe(G$.debug({ title: 'package:' }))
        .pipe(G$.tar(packageFileName))
        .pipe(G$.gzip())
        .pipe(gulp.dest('dist'));
});

gulp.task('clean-dist', false, function () {
    return del('dist');
});

gulp.task('move-temp', false, function () {
    return gulp.src(settings.edgeFiles, { follow: true })
        .pipe(gulp.dest('temp/droplit-edge'));
});

gulp.task('clean-temp', false, function () {
    return del('temp');
});

gulp.task('setup-package', false, function () {
    return gulp.src('./temp/droplit-edge/package.json')
        .pipe(jeditor(function (json) {
            const localConfig = require('./temp/droplit-edge/localsettings.json');
            if (Array.isArray(localConfig.plugins))
                localConfig.plugins.forEach(plugin => {
                    if (typeof plugin === 'string') {
                        json.dependencies[plugin] = `../../projects/${plugin}`;
                        return;
                    }

                    if (typeof plugin === 'object' && plugin.hasOwnProperty('name') && plugin.enabled !== false)
                        json.dependencies[plugin.name] = `../../projects/${plugin.name}`;
                });
            else
                Object.keys(localConfig.plugins).forEach(plugin => {
                    if (localConfig.plugins[plugin] && localConfig.plugins[plugin].enabled !== false) {
                        json.dependencies[plugin] = `../../projects/${plugin}`;
                    }
                });
            return json;
        }))
        .pipe(gulp.dest('temp/droplit-edge/'));
});

gulp.task('pre-install-dist', false, function () {
    return del('temp/droplit-edge/node_modules');
});

gulp.task('install-dist', false, function (callback) {
    runCommand('npm install', { cwd: 'temp/droplit-edge' }, () => {
        console.log('done');
        callback();
    });
});

gulp.task('build-dist', false, function (callback) {
    G$.sequence('clean-dist', 'build', 'unlink', 'move-temp', 'setup-package', 'pre-install-dist', 'install-dist', 'package', 'clean-temp', callback);
});

gulp.task('deploy', 'Glob the Droplit Edge for embedding', function (callback) {
    G$.sequence('setup', 'build-dist', callback);
});

// Testing for improving package
gulp.task('prep', false, function () {
    return del(expandPaths(settings.prep));
});

// Version bump

const bumpOpts = {
    options: {
        major: 'when you make incompatible API changes',
        minor: 'when you add functionality in a backwards-compatible manner',
        patch: 'when you make backwards-compatible bug fixes',
        project: `Project name: ${chalk.green(projectNames.join(chalk.white(', ')))}`
    }
};

gulp.task('bump', 'Version bump a project.', function (major, minor, patch, project) {
    if (!project) return console.log(`${chalk.red('No project specified!')}`);
    let type = '';
    if (major && !minor && !patch) type = 'major';
    if (!major && minor && !patch) type = 'minor';
    if (!major && !minor && patch) type = 'patch';
    if (!type) return console.log(`${chalk.red('Specify one version type to bump!')}`);
    const cwd = 'projects/project/';
    return gulp.src('./package.json', { cwd })
        .pipe(G$.bump({ type }))
        .pipe(gulp.dest('./', { cwd }));
}, bumpOpts);

gulp.task('debug', 'Debug droplit-edge', function () {
    const project = 'droplit-edge';
    G$.nodemon({
        script: `${project}.js`,
        ext: 'js',
        env: {
            DEBUG: 'droplit:*'
        },
        delay: 1, // Sec
        watch: `projects/${project}`,
        ignore: `projects/${project}/src`
    });
});

// .pipe(G$.plumber()) // exit gracefully if something fails after this

// gulp.task('test', 'Runs all tests', [], function () {
//     $.util.log(colors.cyan(`Testing ${settings.testGlob}`));

//     return gulp
//         .src(settings.testGlob, { read: true })
//         .pipe($.plumber()) // exit gracefully if something fails after this
//         .pipe($.mocha({ reporter: 'spec' }));
// });

// Attitional reference: https://github.com/johnpapa/gulp-patterns
// http://www.bennadel.com/blog/2169-where-does-node-js-and-require-look-for-modules.htm<|endoftext|>


<commit_before>'use strict';

const test = require('supertape');
const getUserMenu = require('./get-user-menu');

test('user-menu: getUserMenu', (t) => {
    const menu = `module.exports = {
        'F2 - Rename file': ({DOM}) => {
            const {element} = DOM.CurrentInfo;
            DOM.renameCurrent(element);
        }
    }`;

    const result = getUserMenu(menu);

    const [key] = Object.keys(result);

    t.equal(key, 'F2 - Rename file', 'should equal');
    t.end();
});

test('user-menu: getUserMenu: no args', (t) => {
    const result = getUserMenu();
    const [key] = Object.keys(result);

    t.equal(key, 'F2 - Rename file', 'should equal');
    t.end();
});

<commit_msg>test(user-menu) getUserMenu: coverage<commit_after>'use strict';

const test = require('supertape');
const stub = require('@cloudcmd/stub');
const getUserMenu = require('./get-user-menu');

test('user-menu: getUserMenu', (t) => {
    const menu = `module.exports = {
        'F2 - Rename file': ({DOM}) => {
            const {element} = DOM.CurrentInfo;
            DOM.renameCurrent(element);
        }
    }`;

    const result = getUserMenu(menu);

    const [key] = Object.keys(result);

    t.equal(key, 'F2 - Rename file', 'should equal');
    t.end();
});

test('user-menu: getUserMenu: no args', (t) => {
    const result = getUserMenu();
    const renameCurrent = stub();
    const DOM = {
        renameCurrent,
    };

    const name = 'F2 - Rename file';

    result[name]({
        DOM,
    });

    t.ok(renameCurrent.called, 'should call renameCurrent');
    t.end();
});

<|endoftext|>


<commit_before>// Copyright (c) 2015 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
'use strict';

var _ = require('underscore');
var numOrDefault = require('../util.js').numOrDefault;
var rawHead = require('./util.js').rawHead;
var strHead = require('./util.js').strHead;
var TypedError = require('error/typed');

var MaxRetriesExceeded = TypedError({
    type: 'ringpop.request-proxy.max-retries-exceeded',
    message: 'Max number of retries exceeded. ({maxRetries}) were attempted',
    maxRetries: null
});

var RetryDivergenceError = TypedError({
    type: 'ringpop.request-proxy.keys-diverged',
    message: 'Destinations for proxied request have diverged. These keys: \n' +
        ' {keys}, were originally intended for {origDestination}, but are\n' +
        ' now meant for {newDestinations}.',
    keys: null,
    origDestination: null,
    newDestinations: null
});

var RETRY_SCHEDULE = [0, 1, 3.5];

function logContext(send, opts) {
    return _.extend({
        local: send.ringpop.whoami(),
        destOrig: send.channelOpts.host,
        destinations: send.destinations,
        errors: send.errors,
        maxRetries: send.maxRetries,
        maxRetryTimeout: send.maxRetryTimeout,
        numRetries: send.numRetries,
        reqMethod: send.request.obj.method,
        reqUrl: send.request.obj.url,
        reqStartTime: send.reqStartTime,
        reqTotalTime: Date.now() - send.reqStartTime,
        retrySchedule: send.retrySchedule,
        retryStartTime: send.retryStartTime,
        retryTotalTime: Date.now() - send.retryStartTime,
    }, opts);
}

function RequestProxySend(opts) {
    this.ringpop = opts.ringpop;
    this.requestProxy = opts.requestProxy;
    this.keys = opts.keys;
    this.channelOpts = opts.channelOpts;
    this.request = opts.request;
    this.retries = opts.retries;

    this.retrySchedule = this.retries.schedule || RETRY_SCHEDULE;
    this.maxRetries = numOrDefault(this.retries.max, this.retrySchedule.length);
    this.maxRetryTimeout = this.retrySchedule[this.retrySchedule.length - 1] * 1000;

    this.destinations = [this.channelOpts.host];
    this.errors = [];
    this.numRetries = 0;
    this.reqStartTime = Date.now();
    this.retryStartTime = null;
    this.timeout = null;
}

RequestProxySend.prototype.abortOnKeyDivergence = function abortOnKeyDivergence(dests, callback) {
    this.ringpop.stat('increment', 'requestProxy.retry.aborted');
    this.ringpop.logger.warn('ringpop request proxy retry aborted after keys destinations diverged', logContext(this, {
        destNew: dests,
    }));

    this.ringpop.emit('requestProxy.retryAborted');

    callback(RetryDivergenceError({
        keys: this.keys,
        origDestination: this.channelOpts.host,
        newDestinations: dests
    }));
};

RequestProxySend.prototype.attemptRetry = function attemptRetry(callback) {
    this.numRetries++;

    // TODO Support this case too
    var dests = this.lookupKeys(this.keys);
    if (dests.length > 1) {
        this.abortOnKeyDivergence(dests, callback);
        return;
    }

    this.ringpop.stat('increment', 'requestProxy.retry.attempted');
    this.ringpop.emit('requestProxy.retryAttempted');

    var newDest = dests[0];

    // Nothing rebalanced.
    if (newDest === this.channelOpts.host) {
        this.send(this.channelOpts, callback);
        return;
    }

    this.rerouteRetry(newDest, callback);
};

RequestProxySend.prototype.destroy = function destroy() {
    clearTimeout(this.timeout);
};

RequestProxySend.prototype.getRawHead = function getRawHead() {
    return rawHead(this.request.obj, {
        checksum: this.ringpop.membership.checksum,
        keys: this.keys
    });
};

RequestProxySend.prototype.getStrHead = function getStrHead() {
    return strHead(this.request.obj, {
        checksum: this.ringpop.membership.checksum,
        keys: this.keys
    });
};

RequestProxySend.prototype.handleMaxRetriesExceeded = function handleMaxRetriesExceeded(callback) {
    this.ringpop.stat('increment', 'requestProxy.retry.failed');
    this.ringpop.logger.warn('ringpop request proxy retry exceeded max retries and failed', logContext(this));

    this.ringpop.emit('requestProxy.retryFailed');

    callback(MaxRetriesExceeded({
        maxRetries: this.maxRetries
    }));
};

RequestProxySend.prototype.handleSuccess = function handleSuccess(res1, res2, callback) {
    if (this.numRetries > 0) {
        this.ringpop.stat('increment', 'requestProxy.retry.succeeded');
        this.ringpop.logger.info('ringpop request proxy retry succeeded', logContext(this));

        this.ringpop.emit('requestProxy.retrySucceeded');
    }

    callback(null, res1, res2);
};

RequestProxySend.prototype.lookupKeys = function lookupKeys(keys) {
    var dests = [];

    for (var i = 0; i < keys.length; i++) {
        dests.push(this.ringpop.lookup(keys[i]));
    }

    return dests;
};

RequestProxySend.prototype.rerouteRetry = function rerouteRetry(newDest, callback) {
    this.destinations.push(newDest);

    this.ringpop.logger.warn('ringpop request proxy retry rerouted', logContext(this, {
        destNew: newDest
    }));

    this.ringpop.emit('requestProxy.retryRerouted', this.channelOpts.host, newDest);

    if (newDest === this.ringpop.whoami()) {
        this.ringpop.stat('increment', 'requestProxy.retry.reroute.local');
        this.requestProxy.handleRequest(
            this.getRawHead(),
            this.request.body,
            callback
        );
        return;
    }

    this.ringpop.stat('increment', 'requestProxy.retry.reroute.remote');

    // NOTE Passes in different channel opts than all other calls to send
    this.send({
        host: newDest,
        timeout: this.channelOpts.timeout,
        endpoint: this.channelOpts.endpoint
    }, callback);
};

RequestProxySend.prototype.scheduleRetry = function scheduleRetry(callback) {
    var self = this;

    if (this.numRetries === 0) {
        this.retryStartTime = Date.now();
    }

    // `scheduleDelay` could result in NaN. If so, default to max.
    var scheduleDelay = this.retrySchedule[this.numRetries] * 1000;
    var delay = numOrDefault(scheduleDelay, this.maxRetryTimeout);

    // TODO Can we make this delay responsive/adaptive to previously
    // recorded cluster converge-times?
    this.timeout = this.ringpop.setTimeout(function onTimeout() {
        self.attemptRetry(callback);
    }, delay);

    this.ringpop.emit('requestProxy.retryScheduled');
};

RequestProxySend.prototype.send = function send(channelOpts, callback) {
    var self = this;

    this.ringpop.channel.send(
        channelOpts,
        channelOpts.endpoint,
        this.getStrHead(),
        this.request.body,
        this.retries.max === 0 ? callback : onSend
    );

    this.ringpop.emit('requestProxy.requestProxied');

    function onSend(err, res1, res2) {
        if (!err) {
            self.handleSuccess(res1, res2, callback);
            return;
        }

        self.errors.push(err);

        if (self.numRetries >= self.retries.max) {
            self.handleMaxRetriesExceeded(callback);
            return;
        }

        self.scheduleRetry(callback);
    }
};

module.exports = function send(opts, callback) {
    // All properties of opts are request invariants
    // besides channelOpts. Therefore, channelOpts is explicitly
    // passed into the send function instead.
    var sender = new RequestProxySend(opts);
    sender.send(opts.channelOpts, callback);
    return sender;
};
<commit_msg>Use maxRetries everywhere<commit_after>// Copyright (c) 2015 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
'use strict';

var _ = require('underscore');
var numOrDefault = require('../util.js').numOrDefault;
var rawHead = require('./util.js').rawHead;
var strHead = require('./util.js').strHead;
var TypedError = require('error/typed');

var MaxRetriesExceeded = TypedError({
    type: 'ringpop.request-proxy.max-retries-exceeded',
    message: 'Max number of retries exceeded. ({maxRetries}) were attempted',
    maxRetries: null
});

var RetryDivergenceError = TypedError({
    type: 'ringpop.request-proxy.keys-diverged',
    message: 'Destinations for proxied request have diverged. These keys: \n' +
        ' {keys}, were originally intended for {origDestination}, but are\n' +
        ' now meant for {newDestinations}.',
    keys: null,
    origDestination: null,
    newDestinations: null
});

var RETRY_SCHEDULE = [0, 1, 3.5];

function logContext(send, opts) {
    return _.extend({
        local: send.ringpop.whoami(),
        destOrig: send.channelOpts.host,
        destinations: send.destinations,
        errors: send.errors,
        maxRetries: send.maxRetries,
        maxRetryTimeout: send.maxRetryTimeout,
        numRetries: send.numRetries,
        reqMethod: send.request.obj.method,
        reqUrl: send.request.obj.url,
        reqStartTime: send.reqStartTime,
        reqTotalTime: Date.now() - send.reqStartTime,
        retrySchedule: send.retrySchedule,
        retryStartTime: send.retryStartTime,
        retryTotalTime: Date.now() - send.retryStartTime,
    }, opts);
}

function RequestProxySend(opts) {
    this.ringpop = opts.ringpop;
    this.requestProxy = opts.requestProxy;
    this.keys = opts.keys;
    this.channelOpts = opts.channelOpts;
    this.request = opts.request;
    this.retries = opts.retries;

    this.retrySchedule = this.retries.schedule || RETRY_SCHEDULE;
    this.maxRetries = numOrDefault(this.retries.max, this.retrySchedule.length);
    this.maxRetryTimeout = this.retrySchedule[this.retrySchedule.length - 1] * 1000;

    this.destinations = [this.channelOpts.host];
    this.errors = [];
    this.numRetries = 0;
    this.reqStartTime = Date.now();
    this.retryStartTime = null;
    this.timeout = null;
}

RequestProxySend.prototype.abortOnKeyDivergence = function abortOnKeyDivergence(dests, callback) {
    this.ringpop.stat('increment', 'requestProxy.retry.aborted');
    this.ringpop.logger.warn('ringpop request proxy retry aborted after keys destinations diverged', logContext(this, {
        destNew: dests,
    }));

    this.ringpop.emit('requestProxy.retryAborted');

    callback(RetryDivergenceError({
        keys: this.keys,
        origDestination: this.channelOpts.host,
        newDestinations: dests
    }));
};

RequestProxySend.prototype.attemptRetry = function attemptRetry(callback) {
    this.numRetries++;

    // TODO Support this case too
    var dests = this.lookupKeys(this.keys);
    if (dests.length > 1) {
        this.abortOnKeyDivergence(dests, callback);
        return;
    }

    this.ringpop.stat('increment', 'requestProxy.retry.attempted');
    this.ringpop.emit('requestProxy.retryAttempted');

    var newDest = dests[0];

    // Nothing rebalanced.
    if (newDest === this.channelOpts.host) {
        this.send(this.channelOpts, callback);
        return;
    }

    this.rerouteRetry(newDest, callback);
};

RequestProxySend.prototype.destroy = function destroy() {
    clearTimeout(this.timeout);
};

RequestProxySend.prototype.getRawHead = function getRawHead() {
    return rawHead(this.request.obj, {
        checksum: this.ringpop.membership.checksum,
        keys: this.keys
    });
};

RequestProxySend.prototype.getStrHead = function getStrHead() {
    return strHead(this.request.obj, {
        checksum: this.ringpop.membership.checksum,
        keys: this.keys
    });
};

RequestProxySend.prototype.handleMaxRetriesExceeded = function handleMaxRetriesExceeded(callback) {
    this.ringpop.stat('increment', 'requestProxy.retry.failed');
    this.ringpop.logger.warn('ringpop request proxy retry exceeded max retries and failed', logContext(this));

    this.ringpop.emit('requestProxy.retryFailed');

    callback(MaxRetriesExceeded({
        maxRetries: this.maxRetries
    }));
};

RequestProxySend.prototype.handleSuccess = function handleSuccess(res1, res2, callback) {
    if (this.numRetries > 0) {
        this.ringpop.stat('increment', 'requestProxy.retry.succeeded');
        this.ringpop.logger.info('ringpop request proxy retry succeeded', logContext(this));

        this.ringpop.emit('requestProxy.retrySucceeded');
    }

    callback(null, res1, res2);
};

RequestProxySend.prototype.lookupKeys = function lookupKeys(keys) {
    var dests = [];

    for (var i = 0; i < keys.length; i++) {
        dests.push(this.ringpop.lookup(keys[i]));
    }

    return dests;
};

RequestProxySend.prototype.rerouteRetry = function rerouteRetry(newDest, callback) {
    this.destinations.push(newDest);

    this.ringpop.logger.warn('ringpop request proxy retry rerouted', logContext(this, {
        destNew: newDest
    }));

    this.ringpop.emit('requestProxy.retryRerouted', this.channelOpts.host, newDest);

    if (newDest === this.ringpop.whoami()) {
        this.ringpop.stat('increment', 'requestProxy.retry.reroute.local');
        this.requestProxy.handleRequest(
            this.getRawHead(),
            this.request.body,
            callback
        );
        return;
    }

    this.ringpop.stat('increment', 'requestProxy.retry.reroute.remote');

    // NOTE Passes in different channel opts than all other calls to send
    this.send({
        host: newDest,
        timeout: this.channelOpts.timeout,
        endpoint: this.channelOpts.endpoint
    }, callback);
};

RequestProxySend.prototype.scheduleRetry = function scheduleRetry(callback) {
    var self = this;

    if (this.numRetries === 0) {
        this.retryStartTime = Date.now();
    }

    // `scheduleDelay` could result in NaN. If so, default to max.
    var scheduleDelay = this.retrySchedule[this.numRetries] * 1000;
    var delay = numOrDefault(scheduleDelay, this.maxRetryTimeout);

    // TODO Can we make this delay responsive/adaptive to previously
    // recorded cluster converge-times?
    this.timeout = this.ringpop.setTimeout(function onTimeout() {
        self.attemptRetry(callback);
    }, delay);

    this.ringpop.emit('requestProxy.retryScheduled');
};

RequestProxySend.prototype.send = function send(channelOpts, callback) {
    var self = this;

    this.ringpop.channel.send(
        channelOpts,
        channelOpts.endpoint,
        this.getStrHead(),
        this.request.body,
        this.maxRetries === 0 ? callback : onSend
    );

    this.ringpop.emit('requestProxy.requestProxied');

    function onSend(err, res1, res2) {
        if (!err) {
            self.handleSuccess(res1, res2, callback);
            return;
        }

        self.errors.push(err);

        if (self.numRetries >= self.maxRetries) {
            self.handleMaxRetriesExceeded(callback);
            return;
        }

        self.scheduleRetry(callback);
    }
};

module.exports = function send(opts, callback) {
    // All properties of opts are request invariants
    // besides channelOpts. Therefore, channelOpts is explicitly
    // passed into the send function instead.
    var sender = new RequestProxySend(opts);
    sender.send(opts.channelOpts, callback);
    return sender;
};
<|endoftext|>


<commit_before>"use strict";

treeherder.controller('JobsCtrl',
    function JobsCtrl($scope, $http, $rootScope, $routeParams, $log, $cookies,
                      localStorageService, thUrl, thRepos, thSocket,
                      thResultSetModelManager) {

        // set the default repo to mozilla-inbound if not specified
        if ($routeParams.hasOwnProperty("repo") &&
            $routeParams.repo !== "") {
            $rootScope.repoName = $routeParams.repo;
        } else {
            $rootScope.repoName = "mozilla-inbound";
        }

        // handle the most recent used repos
        $rootScope.update_mru_repos = function(repo){
            var max_mru_repos_length = 6;
            var curr_repo_index = $scope.mru_repos.indexOf($rootScope.repoName);
            if( curr_repo_index !== -1){
                $scope.mru_repos.splice(curr_repo_index, 1);
            }
            $scope.mru_repos.unshift($rootScope.repoName);
            if($scope.mru_repos.length > max_mru_repos_length){
                var old_branch= $scope.mru_repos.pop();
                thSocket.emit('subscribe', old_branch+'.job_failure');
                $log.debug("subscribing to "+old_branch+'.job_failure');
            }
            localStorageService.set("mru_repos", $scope.mru_repos);
        };

        // the primary data model
        thResultSetModelManager.init(60000, $scope.repoName);
        $scope.result_sets = thResultSetModelManager.getResultSetsArray();

        $rootScope.update_mru_repos($rootScope.repoName);

        // stop receiving new failures for the current branch
        if($rootScope.new_failures.hasOwnProperty($rootScope.repoName)){
            delete $rootScope.new_failures[$rootScope.repoName];
        }

        thRepos.load($scope.repoName);

        $scope.isLoadingRsBatch = thResultSetModelManager.loadingStatus;

        // load our initial set of resultsets
        // scope needs this function so it can be called directly by the user, too.
        $scope.fetchResultSets = function(count) {
            thResultSetModelManager.fetchResultSets(count);
        };
        $scope.fetchResultSets(2);

        $scope.repo_has_failures = function(repo_name){
            if($rootScope.new_failures.hasOwnProperty(repo_name) &&
               $rootScope.new_failures[repo_name].length > 0){
                return true;
            }else{
                return false;
            }
        };

    }
);

treeherder.controller('ResultSetCtrl',
    function ResultSetCtrl($scope, $rootScope, $http, $log,
                           thUrl, thServiceDomain, thResultStatusInfo) {

        // determine the greatest severity this resultset contains
        // so that the UI can depict that
        var getMostSevereResultStatus = function(result_types) {

            var status = "pending",
                rsInfo = thResultStatusInfo(status);

            for (var i = 0; i < result_types.length; i++) {
                var res = thResultStatusInfo(result_types[i]);
                if (res.severity < rsInfo.severity) {
                    status = result_types[i];
                    rsInfo = res;
                }
            }
            return {status: status, isCollapsedResults: rsInfo.isCollapsedResults};
        };

        var severeResultStatus = getMostSevereResultStatus($scope.resultset.result_types);
        $scope.$watch('resultset.result_types', function(newVal) {
            severeResultStatus = getMostSevereResultStatus($scope.resultset.result_types);

            if ($scope.resultSeverity !== severeResultStatus.status) {
                $log.debug("updating resultSeverity from " + $scope.resultSeverity + " to " + severeResultStatus.status);
            }

            $scope.resultSeverity = severeResultStatus.status;
        }, true);
        $scope.resultSeverity = severeResultStatus.status;
        $scope.isCollapsedResults = severeResultStatus.isCollapsedResults;

        // whether or not revision list for a resultset is collapsed
        $scope.isCollapsedRevisions = true;

        $scope.viewJob = function(job) {
            // set the selected job
            $rootScope.selectedJob = job;
        };

        $scope.viewLog = function(job_uri) {
            // open the logviewer for this job in a new window
            // currently, invoked by right-clicking a job.

            $http.get(thServiceDomain + job_uri).
                success(function(data) {
                    if (data.hasOwnProperty("artifacts")) {
                        data.artifacts.forEach(function(artifact) {
                            if (artifact.name === "Structured Log") {
                                window.open(thUrl.getLogViewerUrl(artifact.id));
                            }
                        });
                    } else {
                        $log.warn("Job had no artifacts: " + job_uri);
                    }
                });

        };
    }
);
<commit_msg>change rs count<commit_after>"use strict";

treeherder.controller('JobsCtrl',
    function JobsCtrl($scope, $http, $rootScope, $routeParams, $log, $cookies,
                      localStorageService, thUrl, thRepos, thSocket,
                      thResultSetModelManager) {

        // set the default repo to mozilla-inbound if not specified
        if ($routeParams.hasOwnProperty("repo") &&
            $routeParams.repo !== "") {
            $rootScope.repoName = $routeParams.repo;
        } else {
            $rootScope.repoName = "mozilla-inbound";
        }

        // handle the most recent used repos
        $rootScope.update_mru_repos = function(repo){
            var max_mru_repos_length = 6;
            var curr_repo_index = $scope.mru_repos.indexOf($rootScope.repoName);
            if( curr_repo_index !== -1){
                $scope.mru_repos.splice(curr_repo_index, 1);
            }
            $scope.mru_repos.unshift($rootScope.repoName);
            if($scope.mru_repos.length > max_mru_repos_length){
                var old_branch= $scope.mru_repos.pop();
                thSocket.emit('subscribe', old_branch+'.job_failure');
                $log.debug("subscribing to "+old_branch+'.job_failure');
            }
            localStorageService.set("mru_repos", $scope.mru_repos);
        };

        // the primary data model
        thResultSetModelManager.init(60000, $scope.repoName);
        $scope.result_sets = thResultSetModelManager.getResultSetsArray();

        $rootScope.update_mru_repos($rootScope.repoName);

        // stop receiving new failures for the current branch
        if($rootScope.new_failures.hasOwnProperty($rootScope.repoName)){
            delete $rootScope.new_failures[$rootScope.repoName];
        }

        thRepos.load($scope.repoName);

        $scope.isLoadingRsBatch = thResultSetModelManager.loadingStatus;

        // load our initial set of resultsets
        // scope needs this function so it can be called directly by the user, too.
        $scope.fetchResultSets = function(count) {
            thResultSetModelManager.fetchResultSets(count);
        };
        $scope.fetchResultSets(10);

        $scope.repo_has_failures = function(repo_name){
            if($rootScope.new_failures.hasOwnProperty(repo_name) &&
               $rootScope.new_failures[repo_name].length > 0){
                return true;
            }else{
                return false;
            }
        };

    }
);

treeherder.controller('ResultSetCtrl',
    function ResultSetCtrl($scope, $rootScope, $http, $log,
                           thUrl, thServiceDomain, thResultStatusInfo) {

        // determine the greatest severity this resultset contains
        // so that the UI can depict that
        var getMostSevereResultStatus = function(result_types) {

            var status = "pending",
                rsInfo = thResultStatusInfo(status);

            for (var i = 0; i < result_types.length; i++) {
                var res = thResultStatusInfo(result_types[i]);
                if (res.severity < rsInfo.severity) {
                    status = result_types[i];
                    rsInfo = res;
                }
            }
            return {status: status, isCollapsedResults: rsInfo.isCollapsedResults};
        };

        var severeResultStatus = getMostSevereResultStatus($scope.resultset.result_types);
        $scope.$watch('resultset.result_types', function(newVal) {
            severeResultStatus = getMostSevereResultStatus($scope.resultset.result_types);

            if ($scope.resultSeverity !== severeResultStatus.status) {
                $log.debug("updating resultSeverity from " + $scope.resultSeverity + " to " + severeResultStatus.status);
            }

            $scope.resultSeverity = severeResultStatus.status;
        }, true);
        $scope.resultSeverity = severeResultStatus.status;
        $scope.isCollapsedResults = severeResultStatus.isCollapsedResults;

        // whether or not revision list for a resultset is collapsed
        $scope.isCollapsedRevisions = true;

        $scope.viewJob = function(job) {
            // set the selected job
            $rootScope.selectedJob = job;
        };

        $scope.viewLog = function(job_uri) {
            // open the logviewer for this job in a new window
            // currently, invoked by right-clicking a job.

            $http.get(thServiceDomain + job_uri).
                success(function(data) {
                    if (data.hasOwnProperty("artifacts")) {
                        data.artifacts.forEach(function(artifact) {
                            if (artifact.name === "Structured Log") {
                                window.open(thUrl.getLogViewerUrl(artifact.id));
                            }
                        });
                    } else {
                        $log.warn("Job had no artifacts: " + job_uri);
                    }
                });

        };
    }
);
<|endoftext|>


<commit_before>var Backbone = require('backbone');
var _ = require('underscore');
var ColumnRowData = require('../../../data/column-row-data');

var FIELDTYPE_TO_FORMTYPE = {
  string: 'Text',
  boolean: 'Radio',
  number: 'Number',
  date: 'DateTime',
  geometry: 'Text'
};

var BLACKLISTED_COLUMNS = ['created_at', 'the_geom', 'the_geom_webmercator', 'updated_at'];

module.exports = Backbone.Model.extend({

  initialize: function (attrs, opts) {
    if (!opts.featureModel) throw new Error('featureModel is required');
    if (!opts.columnsCollection) throw new Error('columnsCollection is required');
    if (!opts.configModel) throw new Error('configModel is required');
    if (!opts.nodeDefModel) throw new Error('nodeDefModel is required');

    this._featureModel = opts.featureModel;
    this._columnsCollection = opts.columnsCollection;
    this._configModel = opts.configModel;
    this._nodeDefModel = opts.nodeDefModel;

    this._generateSchema();
    this._initBinds();
  },

  _initBinds: function () {
    this.bind('change', this._onChange, this);
  },

  _onChange: function () {
    _.each(this.changed, function (val, key) {
      this._featureModel.set(key, val);
    }, this);
  },

  _getInputType: function (columnRowData) {
    var rows = columnRowData.getRows();
    return rows && rows.length ? 'Suggest' : 'Text';
  },

  _getSupportedColumnType: function (columnType) {
    var supportedColumnType = _.find(_.keys(FIELDTYPE_TO_FORMTYPE), function (fieldType) {
      return fieldType === columnType;
    });

    return supportedColumnType || 'string'
  },

  _generateSchema: function () {
    var self = this;

    this.schema = {};

    this._columnsCollection.each(function (mdl) {
      var columnName = mdl.get('name');
      var columnType = this._getSupportedColumnType(mdl.get('type'));

      if (!_.contains(BLACKLISTED_COLUMNS, columnName)) {
        // default field type
        this.schema[columnName] = {
          type: FIELDTYPE_TO_FORMTYPE[columnType]
        };

        if (columnType === 'string') {
          var columnRowData = new ColumnRowData({
            column: columnName
          }, {
            nodeDefModel: this._nodeDefModel,
            configModel: this._configModel
          });
          columnRowData.bind('columnsFetched', function (rows) {
            if (self.schema[columnName].type !== self._getInputType(this)) {
              self.schema[columnName].type = self._getInputType(this);
              self.schema[columnName].editorAttrs = {
                showSearch: true,
                allowFreeTextInput: true,
                collectionData: rows
              };

              self._onChangeSchema();
            }
          });
          columnRowData.fetch();
        }

        if (columnType === 'number') {
          this.schema[columnName].isFormatted = true;
          this.schema[columnName].showSlider = false;
        }

        if (columnType === 'boolean') {
          this.schema[columnName].options = [
            {
              label: _t('form-components.editors.radio.true'),
              val: true
            }, {
              label: _t('form-components.editors.radio.false'),
              val: false
            }, {
              label: _t('form-components.editors.radio.null'),
              val: null
            }
          ];
        }

        if (columnName === 'cartodb_id') {
          this.schema[columnName].isFormatted = false;
          this.schema[columnName].editorAttrs = {
            disabled: true
          };
        }
      }
    }, this);
  },

  _onChangeSchema: function () {
    this.trigger('changeSchema');
  }

});
<commit_msg>linter<commit_after>var Backbone = require('backbone');
var _ = require('underscore');
var ColumnRowData = require('../../../data/column-row-data');

var FIELDTYPE_TO_FORMTYPE = {
  string: 'Text',
  boolean: 'Radio',
  number: 'Number',
  date: 'DateTime',
  geometry: 'Text'
};

var BLACKLISTED_COLUMNS = ['created_at', 'the_geom', 'the_geom_webmercator', 'updated_at'];

module.exports = Backbone.Model.extend({

  initialize: function (attrs, opts) {
    if (!opts.featureModel) throw new Error('featureModel is required');
    if (!opts.columnsCollection) throw new Error('columnsCollection is required');
    if (!opts.configModel) throw new Error('configModel is required');
    if (!opts.nodeDefModel) throw new Error('nodeDefModel is required');

    this._featureModel = opts.featureModel;
    this._columnsCollection = opts.columnsCollection;
    this._configModel = opts.configModel;
    this._nodeDefModel = opts.nodeDefModel;

    this._generateSchema();
    this._initBinds();
  },

  _initBinds: function () {
    this.bind('change', this._onChange, this);
  },

  _onChange: function () {
    _.each(this.changed, function (val, key) {
      this._featureModel.set(key, val);
    }, this);
  },

  _getInputType: function (columnRowData) {
    var rows = columnRowData.getRows();
    return rows && rows.length ? 'Suggest' : 'Text';
  },

  _getSupportedColumnType: function (columnType) {
    var supportedColumnType = _.find(_.keys(FIELDTYPE_TO_FORMTYPE), function (fieldType) {
      return fieldType === columnType;
    });

    return supportedColumnType || 'string';
  },

  _generateSchema: function () {
    var self = this;

    this.schema = {};

    this._columnsCollection.each(function (mdl) {
      var columnName = mdl.get('name');
      var columnType = this._getSupportedColumnType(mdl.get('type'));

      if (!_.contains(BLACKLISTED_COLUMNS, columnName)) {
        // default field type
        this.schema[columnName] = {
          type: FIELDTYPE_TO_FORMTYPE[columnType]
        };

        if (columnType === 'string') {
          var columnRowData = new ColumnRowData({
            column: columnName
          }, {
            nodeDefModel: this._nodeDefModel,
            configModel: this._configModel
          });
          columnRowData.bind('columnsFetched', function (rows) {
            if (self.schema[columnName].type !== self._getInputType(this)) {
              self.schema[columnName].type = self._getInputType(this);
              self.schema[columnName].editorAttrs = {
                showSearch: true,
                allowFreeTextInput: true,
                collectionData: rows
              };

              self._onChangeSchema();
            }
          });
          columnRowData.fetch();
        }

        if (columnType === 'number') {
          this.schema[columnName].isFormatted = true;
          this.schema[columnName].showSlider = false;
        }

        if (columnType === 'boolean') {
          this.schema[columnName].options = [
            {
              label: _t('form-components.editors.radio.true'),
              val: true
            }, {
              label: _t('form-components.editors.radio.false'),
              val: false
            }, {
              label: _t('form-components.editors.radio.null'),
              val: null
            }
          ];
        }

        if (columnName === 'cartodb_id') {
          this.schema[columnName].isFormatted = false;
          this.schema[columnName].editorAttrs = {
            disabled: true
          };
        }
      }
    }, this);
  },

  _onChangeSchema: function () {
    this.trigger('changeSchema');
  }

});
<|endoftext|>


<commit_before>import React from 'react'
import PropTypes from 'prop-types'
import 'react-vis/dist/style.css'
import { FlexibleWidthXYPlot, HorizontalBarSeries, HorizontalGridLines, VerticalGridLines, XAxis, YAxis } from 'react-vis'

import * as v from '../../styles/variables'

class FrequenResults extends React.Component {
  constructor (props) {
    super(props)
    this.onMouseOver = this.onMouseOver.bind(this)
    this.onMouseOut = this.onMouseOut.bind(this)
    this.state = {
      index: null
    }

    let rawResults = this.props.results
    this.results = []

    if (rawResults) {
      // Find allophones and combine their counts
      for (let seg in rawResults) {
        if (rawResults.hasOwnProperty(seg)) {
          if (rawResults[seg].hasOwnProperty('allophoneOf')) {
            rawResults[rawResults[seg].allophoneOf].count += rawResults[seg].count
            delete rawResults[seg]
          }
        }
      }

      // Add the results to the results array
      for (let seg in rawResults) {
        this.results.push({ segment: seg, count: rawResults[seg].count, type: rawResults[seg].type })
      }
    }

    this.results.sort((a, b) => {
      return b['count'] - a['count']
    })

    this.fullCount = 0

    this.results.forEach((elObj) => {
      this.fullCount += elObj.count
    })
  }

  onMouseOver (datapoint) {
    this.setState({ index: datapoint.i })
  }

  onMouseOut () {
    this.setState({ index: null })
  }

  render () {
    const data = this.results.map((d, i) => (
      {
        x: (d.count / this.fullCount) * 100,
        y: d.segment,
        i: i,
        color: i === this.state.index ? v.ong.string() : v.blu.string()
      }
    ))

    const axisStyle = {
      fontSize: `${v.ms0}rem`,
      text: {
        fill: `${v.black.lighten(9).string()}`
      },
      line: {
        stroke: `${v.black.lighten(20).string()}`
      }
    }

    const gridStyle = { stroke: `${v.black.lighten(20).string()}` }

    if (this.props.analyzed) {
      return (

            <FlexibleWidthXYPlot
              yType='ordinal'
              height={v.ms2 * 16 * data.length}
              onMouseLeave={this.onMouseOut}
            >
              <VerticalGridLines style={gridStyle} />
              <HorizontalGridLines style={gridStyle} />
              <XAxis
                tickFormat={(t) => `${t}%`}
                style={axisStyle}
              />
              <YAxis style={axisStyle} />
              <HorizontalBarSeries
                data={data}
                animation
                colorType='literal'
                onValueMouseOver={this.onMouseOver}
                onMouseOut={this.onMouseOut}
              />
            </FlexibleWidthXYPlot>

      )
    } else {
      return

    }
  }
}

FrequenResults.propTypes = {
  classes: PropTypes.object,
  results: PropTypes.object.isRequired,
  analyzed: PropTypes.bool.isRequired
}

export default FrequenResults
<commit_msg>Add tooltip to chart<commit_after>import React from 'react'
import PropTypes from 'prop-types'
import 'react-vis/dist/style.css'
import { FlexibleWidthXYPlot, HorizontalBarSeries, HorizontalGridLines, VerticalGridLines, XAxis, YAxis, Hint } from 'react-vis'

import * as v from '../../styles/variables'

class FrequenResults extends React.Component {
  constructor (props) {
    super(props)
    this.onMouseOver = this.onMouseOver.bind(this)
    this.onMouseOut = this.onMouseOut.bind(this)
    this.state = {
      index: null,
      x: null,
      y: null,
      filter: null
    }

    let rawResults = this.props.results
    this.results = []

    if (rawResults) {
      // Find allophones and combine their counts
      for (let seg in rawResults) {
        if (rawResults.hasOwnProperty(seg)) {
          if (rawResults[seg].hasOwnProperty('allophoneOf')) {
            rawResults[rawResults[seg].allophoneOf].count += rawResults[seg].count
            delete rawResults[seg]
          }
        }
      }

      // Add the results to the results array
      for (let seg in rawResults) {
        this.results.push({ segment: seg, count: rawResults[seg].count, type: rawResults[seg].type })
      }
    }

    this.results.sort((a, b) => {
      return b['count'] - a['count']
    })

    this.fullCount = 0

    this.results.forEach((elObj) => {
      this.fullCount += elObj.count
    })
  }

  onMouseOver (datapoint) {
    this.setState({
      index: datapoint.i,
      x: datapoint.x,
      y: datapoint.y
    })
  }

  onMouseOut () {
    this.setState({
      index: null,
      x: null,
      y: null
    })
  }

  render () {
    const data = this.results.map((d, i) => (
      {
        x: (d.count / this.fullCount) * 100,
        y: d.segment,
        i: i,
        color: i === this.state.index ? v.ong.string() : v.blu.string()
      }
    ))

    const axisStyle = {
      fontSize: `${v.ms0}rem`,
      text: {
        fill: `${v.black.lighten(9).string()}`
      },
      line: {
        stroke: `${v.black.lighten(20).string()}`
      }
    }

    const gridStyle = { stroke: `${v.black.lighten(20).string()}` }

    if (this.props.analyzed) {
      return (

            <FlexibleWidthXYPlot
              yType='ordinal'
              height={v.ms2 * 16 * (data.length)}
              onMouseLeave={this.onMouseOut}
            >
              <VerticalGridLines style={gridStyle} />
              <HorizontalGridLines style={gridStyle} />
              <XAxis
                tickFormat={(t) => `${t}%`}
                style={axisStyle}
              />
              <YAxis style={axisStyle} />
              <HorizontalBarSeries
                data={data}
                animation
                colorType='literal'
                onValueMouseOver={this.onMouseOver}
                onMouseOut={this.onMouseOut}
              />
              {this.state.x ? (
                <Hint
                  value={{ Frequency: `${this.state.x.toFixed(2)}%` }}
                  align={{
                    horizontal: 'left',
                    vertical: 'auto'
                  }}
                />
              ) : null}
            </FlexibleWidthXYPlot>

      )
    } else {
      return

    }
  }
}

FrequenResults.propTypes = {
  classes: PropTypes.object,
  results: PropTypes.object.isRequired,
  analyzed: PropTypes.bool.isRequired
}

export default FrequenResults
<|endoftext|>


<commit_before>define([ 'jquery',
         'jquery-ui',
         'underscore',
         'amcharts.serial',
         'backbone',
         'hbs!templates/remotesim' ],
    function($, JUI, _, amRef, Backbone, RemoteSimTemplate) {

  var RemoteSimulation = Backbone.View.extend({

    defaultParams : {
      consumptionPerKm : 1,
      efficiency : 0.99
    },

    initialize : function(options) {
      _.bindAll(this, [ 'runSimulation' ]);
    },

    runSimulation : function() {
      var self = this;
      this.$('.runbutton button').addClass('disabled');

      $.get('/api/simulate', self.defaultParams).done(function(data) {
        self.$('.runbutton button').removeClass('disabled');
        var timeseries = _.map(data.timeseries, function(value, key) {
          return {
            power: value,
            time: key.substring(0, 2) + ':' + key.substring(2, 4)
          };
        });
        $('.energy-total').text(data.totalEnergy);
        timeseries = _.sortBy(timeseries, 'time');

        var chart = amRef.makeChart('chartdiv', {
          'theme' : 'none',
          'type' : 'serial',
          'autoMargins' : false,
          'marginLeft' : 100,
          'marginRight' : 8,
          'marginTop' : 10,
          'marginBottom' : 70,
          'pathToImages' : 'http://www.amcharts.com/lib/3/images/',
          'dataProvider' : timeseries,
          'valueAxes' : [ {
            'id' : 'v1',
            'axisAlpha' : 0,
            'inside' : false,
            'min' : 0,
            'minimum' : 0,
            'max' : 10000,
            'maximum' : 10000,
            'gridAlpha' : 0.1,
            'title' : 'Power use (kW)'
          } ],
          'graphs' : [ {
            'useNegativeColorIfDown' : false,
            'balloonText' : '[[category]]
value: [[value]]',
            'bullet' : 'round',
            'bulletBorderAlpha' : 1,
            'bulletBorderColor' : '#FFFFFF',
            'hideBulletsCount' : 50,
            'lineThickness' : 1,
            'lineColor' : '#0088cc',
            'valueField' : 'power'
          } ],
          'chartCursor' : {
            'valueLineEnabled' : true,
            'valueLineBalloonEnabled' : true
          },
          'categoryField' : 'time',
          'categoryAxis' : {
            'parseDates' : false,
            'axisAlpha' : 0,
            'gridAlpha' : 0,
            'title' : 'Time'
          }
        });
      });
    },

    render : function() {
      var self = this;
      this.$el.html(RemoteSimTemplate());
      this.$('#efficiency').text(this.defaultParams.efficiency);
      this.$('#consumption').text(this.defaultParams.consumptionPerKm);

      this.$('#efficiency-slider').slider({
        value : 1,
        min : 0.5,
        max : 1.0,
        step : 0.01,
        slide : function(event, ui) {
          $('#efficiency').text(ui.value);
          self.defaultParams.efficiency = ui.value;
        }
      });

      this.$('#consumption-slider').slider({
        value : 1,
        min : 0,
        max : 3.1,
        step : 0.1,
        slide : function(event, ui) {
          self.$('#consumption').text(ui.value);
          self.defaultParams.consumptionPerKm = ui.value;
        }
      });

      this.$('.runbutton button').click(this.runSimulation);
      this.runSimulation();
    }
  });

  return RemoteSimulation;
});<commit_msg>First version<commit_after>define([ 'jquery',
         'jquery-ui',
         'underscore',
         'amcharts.serial',
         'backbone',
         'hbs!templates/remotesim' ],
    function($, JUI, _, amRef, Backbone, RemoteSimTemplate) {

  var RemoteSimulation = Backbone.View.extend({

    defaultParams : {
      consumptionPerKm : 1,
      efficiency : 0.99
    },

    initialize : function(options) {
      _.bindAll(this, [ 'runSimulation' ]);
    },

    runSimulation : function() {
      var self = this;
      this.$('.runbutton button').addClass('disabled');

      $.get('/api/simulate', self.defaultParams).done(function(data) {
        self.$('.runbutton button').removeClass('disabled');
        var timeseries = _.map(data.timeseries, function(value, key) {
          return {
            power: value,
            time: key.substring(0, 2) + ':' + key.substring(2, 4)
          };
        });
        $('.energy-total').text(data.totalEnergy);
        timeseries = _.sortBy(timeseries, 'time');

        var chart = amRef.makeChart('chartdiv', {
          'theme' : 'none',
          'type' : 'serial',
          'autoMargins' : false,
          'marginLeft' : 100,
          'marginRight' : 8,
          'marginTop' : 10,
          'marginBottom' : 70,
          'pathToImages' : 'http://www.amcharts.com/lib/3/images/',
          'dataProvider' : timeseries,
          'valueAxes' : [ {
            'id' : 'v1',
            'axisAlpha' : 0,
            'inside' : false,
            'min' : 0,
            'minimum' : 0,
            'max' : 11000,
            'maximum' : 11000,
            'gridAlpha' : 0.1,
            'title' : 'Power use (kW)'
          } ],
          'graphs' : [ {
            'useNegativeColorIfDown' : false,
            'balloonText' : '[[category]]
value: [[value]]',
            'bullet' : 'round',
            'bulletBorderAlpha' : 1,
            'bulletBorderColor' : '#FFFFFF',
            'hideBulletsCount' : 50,
            'lineThickness' : 1,
            'lineColor' : '#0088cc',
            'valueField' : 'power'
          } ],
          'chartCursor' : {
            'valueLineEnabled' : true,
            'valueLineBalloonEnabled' : true
          },
          'categoryField' : 'time',
          'categoryAxis' : {
            'parseDates' : false,
            'axisAlpha' : 0,
            'gridAlpha' : 0,
            'title' : 'Time'
          }
        });
      });
    },

    render : function() {
      var self = this;
      this.$el.html(RemoteSimTemplate());
      this.$('#efficiency').text(this.defaultParams.efficiency);
      this.$('#consumption').text(this.defaultParams.consumptionPerKm);

      this.$('#efficiency-slider').slider({
        value : 1,
        min : 0.5,
        max : 1.0,
        step : 0.01,
        slide : function(event, ui) {
          $('#efficiency').text(ui.value);
          self.defaultParams.efficiency = ui.value;
        }
      });

      this.$('#consumption-slider').slider({
        value : 1,
        min : 0,
        max : 3.1,
        step : 0.1,
        slide : function(event, ui) {
          self.$('#consumption').text(ui.value);
          self.defaultParams.consumptionPerKm = ui.value;
        }
      });

      this.$('.runbutton button').click(this.runSimulation);
      this.runSimulation();
    }
  });

  return RemoteSimulation;
});<|endoftext|>