<commit_before>var Gesso = require('gesso');
var helpers = require('./helpers');

var game = new Gesso();
var gravity = 0.3;
var seaLevel = 80;
var player = null;
var rocks = [];
var frameCount = 0;
var highScore = 0;
var highScoreTime = 0;
var highScoreMaxTime = 60;
var particles = [];
var endGameParticleCount = 100;
var bottomLeeway = 60;
var bubbles = [];
var splash = [];

function newGame() {
  player = {
    playing: false,
    x: 100,
    y: 200,
    sy: 1,
    velocity: -10,
    jumpVelocity: 8,
    terminalVelocity: 7,
    score: 0
  };
}

function endGame() {
  if (!player) {
    return;
  }

  // Set the new high score, animating it, if the record was broken
  if (player.score > highScore) {
    highScore = player.score;
    highScoreTime = highScoreMaxTime;
  }

  // Explode
  for (var index = 0; index < endGameParticleCount; index++) {
    var angle = helpers.randInt(0, 360);
    var velocity = helpers.randInt(10, 20);
    particles.push({
      x: player.x,
      y: player.y,
      vx: Math.cos(angle * Math.PI / 180) * velocity - 6,
      vy: Math.sin(angle * Math.PI / 180) * velocity
    });
  }

  // Set to not playing
  player = null;
}

function newSplash() {
  for (var s = 0; s < 20; s++) {
    var ax = Math.random() * 4 - 3;
    var ay = -(Math.random() * 2 + 1);
    splash.push({x: player.x + ax, y: seaLevel, vx: ax, vy: ay, r: helpers.randInt(1, 2)});
  }
}

function newBubble(probability) {
  if (player && helpers.randInt(1, probability) === 1) {
    bubbles.push({x: player.x, y: player.y, r: helpers.randInt(2, 4)});
  }
}

Gesso.getCanvas().addEventListener('mousedown', function (e) {
  e.preventDefault();

  // Create new player, if not currently playing
  if (!player) {
    newGame();
    return false;
  }

  // Swim / jump
  if (player.y > seaLevel) {
    player.velocity = -player.jumpVelocity;
    player.sy = 1.6;
    newBubble(10);
  }

  return false;
});

game.update(function () {
  frameCount += 1;

  // Update rocks
  for (var r = 0; r < rocks.length; r++) {
    rocks[r].x -= 5;
    // Delete rock when out of bounds
    if (rocks[r].x + rocks[r].width < 0) {
      rocks.splice(r, 1);
      r--;
    }
  }

  // Create a new rock
  // TODO: Difficulty
  if (frameCount % 100 === 0) {
    rocks.push({
      x: game.width,
      y: helpers.randInt(50, game.height),
      width: helpers.randInt(100, 150),
      height: helpers.randInt(200, 300)
    });
  }

  // Update bubbles
  for (var b = 0; b < bubbles.length; b++) {
    bubbles[b].x -= 3;
    if (helpers.randInt(1, 3) === 1) {
      bubbles[b].x -= 1;
    }
    if (helpers.randInt(1, 5)) {
      bubbles[b].y += helpers.randInt(-3, 1);
    }
    // Delete bubble when out of bounds
    if (bubbles[b].x + bubbles[b].r < 0 || bubbles[b].y <= seaLevel) {
      bubbles.splice(b, 1);
      b--;
    }
  }
  // Randomly add a new bubble
  if (player) {
    newBubble(100);
  }
  // Check for rock / bubble collisions
  for (r = 0; r < rocks.length; r++) {
    for (b = 0; b < bubbles.length; b++) {
      if (helpers.intersected({x: bubbles[b].x, y: bubbles[b].y, width: bubbles[b].r, height: bubbles[b].r}, rocks[r])) {
        bubbles.splice(b, 1);
        b--;
      }
    }
  }

  // Update splash
  for (var s = 0; s < splash.length; s++) {
    splash[s].x += splash[s].vx;
    splash[s].y += splash[s].vy;
    splash[s].vy += gravity;
    // Delete splash
    if (splash[s].y > seaLevel) {
      splash.splice(s, 1);
      s--;
    }
  }

  // Update particles
  for (var p = 0; p < particles.length; p++) {
    particles[p].x -= particles[p].vx;
    particles[p].y -= particles[p].vy;
    // Delete particle when out of bounds
    if (particles[p].x + 3 < 0 || particles[p].y + 3 < 0 ||
        particles[p].x - 3 > game.width || particles[p].y - 3 > game.height + bottomLeeway) {
      particles.splice(p, 1);
      p--;
    }
  }

  if (highScoreTime > 0) {
    highScoreTime -= 1;
  }

  // Skip player logic if not currently playing
  if (!player) {
    return;
  }

  // Check for collisions
  for (r = 0; r < rocks.length; r++) {
    if (helpers.intersected({x: player.x, y: player.y, width: 20, height: 10}, rocks[r])) {
      endGame();
      return;
    }
  }

  // Update player
  if (frameCount % 6 === 0) {
    player.score += 100;
  }
  if (player.sy > 1) {
    player.sy -= 0.1;
  }
  if (player.best && player.score > player.best) {
    player.best = player.score;
  }
  player.velocity += gravity;
  if (player.velocity > player.terminalVelocity) {
    player.velocity = player.terminalVelocity;
  }
  player.y += player.velocity;
  if (player.y >= game.height + bottomLeeway) {
    endGame();
    return;
  }
  if ((player.y - player.velocity >= seaLevel && player.y < seaLevel) ||
      (player.y - player.velocity <= seaLevel && player.y > seaLevel)) {
    newSplash();
  }
});

game.render(function (ctx) {
  // Draw background
  ctx.fillStyle = '#ece';
  ctx.fillRect(0, 0, game.width, game.height);

  // Draw sky
  var grd = ctx.createLinearGradient(game.width / 2, 0.000, game.width / 2, seaLevel);
  grd.addColorStop(0.000, '#80befc');
  grd.addColorStop(1.000, '#cbcfed');
  ctx.fillStyle = grd;
  ctx.fillRect(0, 0, game.width, seaLevel);

  // Draw water
  grd = ctx.createLinearGradient(game.width / 2, seaLevel, game.width / 2, game.height - seaLevel);
  grd.addColorStop(0.000, '#7EBDFC');
  grd.addColorStop(0.100, '#007fff');
  grd.addColorStop(1.000, '#003f7f');
  ctx.fillStyle = grd;
  ctx.fillRect(0, seaLevel, game.width, game.height - seaLevel);

  // Water lighting (note: coordinates are off, but the mistake looks better)
  grd = ctx.createLinearGradient(0, 0, game.width, game.height - seaLevel);
  grd.addColorStop(0.000, 'rgba(0, 127, 255, 0.200)');
  grd.addColorStop(0.100, 'rgba(255, 255, 255, 0.200)');
  grd.addColorStop(0.200, 'rgba(0, 127, 255, 0.200)');
  grd.addColorStop(0.500, 'rgba(255, 255, 255, 0.200)');
  grd.addColorStop(0.600, 'rgba(0, 127, 255, 0.200)');
  grd.addColorStop(0.800, 'rgba(255, 255, 255, 0.200)');
  grd.addColorStop(1.000, 'rgba(0, 127, 255, 0.200)');
  ctx.fillStyle = grd;
  ctx.fillRect(0, seaLevel, game.width, game.height - seaLevel);

  // Draw splash
  for (var s = 0; s < splash.length; s++) {
    helpers.fillCircle(ctx, splash[s].x, splash[s].y, splash[s].r, '#7EBDFC');
  }

  // Draw bubbles
  for (var b = 0; b < bubbles.length; b++) {
    helpers.fillCircle(ctx, bubbles[b].x, bubbles[b].y, bubbles[b].r, 'rgba(255, 255, 255, 0.8)');
  }

  // Draw rocks
  for (var r = 0; r < rocks.length; r++) {
    ctx.fillStyle = '#5d4';
    ctx.fillRect(rocks[r].x, rocks[r].y, rocks[r].width, rocks[r].height);
  }

  // Draw particles
  for (var p = 0; p < particles.length; p++) {
    helpers.fillCircle(ctx, particles[p].x, particles[p].y, 3, '#ff4');
  }

  // Draw score
  if (player || highScore) {
    ctx.font = 'bold 24px sans-serif';
    ctx.textAlign = 'right';
    helpers.outlineText(ctx, 'Score: ' + (player ? player.score : 0), game.width - 30, 32, '#333', '#fff');
  }
  if (highScore) {
    ctx.font = 'bold 24px sans-serif';
    helpers.outlineText(ctx, 'Best: ' + highScore, game.width - 30, 64, '#333', '#fff');
    if (highScoreTime > 0) {
      var offset = (highScoreTime) * 2;
      var fade = (highScoreTime / highScoreMaxTime * 2);
      ctx.font = 'bold ' + (24 + offset) + 'px sans-serif';
      ctx.fillStyle = 'rgba(255, 255, 255, ' + fade + ')';
      ctx.fillText('Best: ' + highScore, game.width - 30 + (offset * 0.25), 64 + (offset * 1.5));
    }
  }

  if (player) {
    // Draw player
    helpers.fillEllipse(ctx, player.x, player.y, 10, 2, player.sy, '#ff4');
    helpers.fillCircle(ctx, player.x + 5, player.y - 2, 3, '#330');
  }

  // Draw water depth gradient
  grd = ctx.createLinearGradient(game.width / 2, seaLevel, game.width / 2, game.height);
  grd.addColorStop(0.000, 'rgba(0, 127, 255, 0.100)');
  grd.addColorStop(0.700, 'rgba(0, 63, 127, 0.100)');
  grd.addColorStop(1.000, 'rgba(0, 63, 127, 0.500)');
  ctx.fillStyle = grd;
  ctx.fillRect(0, seaLevel, game.width, game.height - seaLevel);

  if (!player) {
    // Draw pre-game text
    if ((frameCount % 120 > 5 && frameCount % 120 < 20) || frameCount % 120 > 25) {
      ctx.font = 'bold 64px sans-serif';
      ctx.textAlign = 'center';
      if (highScore) {
        helpers.outlineText(ctx, 'Game over!', (game.width / 2), (game.height / 2) - 30, '#333', '#fff');
        helpers.outlineText(ctx, 'Click again!', (game.width / 2), (game.height / 2) + 40, '#333', '#fff');
      } else {
        helpers.outlineText(ctx, 'Click to start!', (game.width / 2), (game.height / 2), '#333', '#fff');
      }
    }
  }
});

// TODO: Delete this
game.run();

// TODO: Get the runtime to expose this object through a gesso.current global
module.exports = game;
<commit_msg>Add jump out of water leeway.<commit_after>var Gesso = require('gesso');
var helpers = require('./helpers');

var game = new Gesso();
var gravity = 0.3;
var seaLevel = 80;
var player = null;
var rocks = [];
var frameCount = 0;
var highScore = 0;
var highScoreTime = 0;
var highScoreMaxTime = 60;
var particles = [];
var endGameParticleCount = 100;
var bottomLeeway = 60;
var bubbles = [];
var splash = [];

function newGame() {
  player = {
    playing: false,
    x: 100,
    y: 200,
    sy: 1,
    velocity: -10,
    jumpVelocity: 8,
    terminalVelocity: 7,
    score: 0
  };
}

function endGame() {
  if (!player) {
    return;
  }

  // Set the new high score, animating it, if the record was broken
  if (player.score > highScore) {
    highScore = player.score;
    highScoreTime = highScoreMaxTime;
  }

  // Explode
  for (var index = 0; index < endGameParticleCount; index++) {
    var angle = helpers.randInt(0, 360);
    var velocity = helpers.randInt(10, 20);
    particles.push({
      x: player.x,
      y: player.y,
      vx: Math.cos(angle * Math.PI / 180) * velocity - 6,
      vy: Math.sin(angle * Math.PI / 180) * velocity
    });
  }

  // Set to not playing
  player = null;
}

function newSplash() {
  for (var s = 0; s < 20; s++) {
    var ax = Math.random() * 4 - 3;
    var ay = -(Math.random() * 2 + 1);
    splash.push({x: player.x + ax, y: seaLevel, vx: ax, vy: ay, r: helpers.randInt(1, 2)});
  }
}

function newBubble(probability) {
  if (player && helpers.randInt(1, probability) === 1) {
    bubbles.push({x: player.x, y: player.y, r: helpers.randInt(2, 4)});
  }
}

Gesso.getCanvas().addEventListener('mousedown', function (e) {
  e.preventDefault();

  // Create new player, if not currently playing
  if (!player) {
    newGame();
    return false;
  }

  // Swim / jump
  if (player.y + 5 > seaLevel) {
    player.velocity = -player.jumpVelocity;
    player.sy = 1.6;
    newBubble(10);
  }

  return false;
});

game.update(function () {
  frameCount += 1;

  // Update rocks
  for (var r = 0; r < rocks.length; r++) {
    rocks[r].x -= 5;
    // Delete rock when out of bounds
    if (rocks[r].x + rocks[r].width < 0) {
      rocks.splice(r, 1);
      r--;
    }
  }

  // Create a new rock
  // TODO: Difficulty
  if (frameCount % 100 === 0) {
    rocks.push({
      x: game.width,
      y: helpers.randInt(50, game.height),
      width: helpers.randInt(100, 150),
      height: helpers.randInt(200, 300)
    });
  }

  // Update bubbles
  for (var b = 0; b < bubbles.length; b++) {
    bubbles[b].x -= 3;
    if (helpers.randInt(1, 3) === 1) {
      bubbles[b].x -= 1;
    }
    if (helpers.randInt(1, 5)) {
      bubbles[b].y += helpers.randInt(-3, 1);
    }
    // Delete bubble when out of bounds
    if (bubbles[b].x + bubbles[b].r < 0 || bubbles[b].y <= seaLevel) {
      bubbles.splice(b, 1);
      b--;
    }
  }
  // Randomly add a new bubble
  if (player) {
    newBubble(100);
  }
  // Check for rock / bubble collisions
  for (r = 0; r < rocks.length; r++) {
    for (b = 0; b < bubbles.length; b++) {
      if (helpers.intersected({x: bubbles[b].x, y: bubbles[b].y, width: bubbles[b].r, height: bubbles[b].r}, rocks[r])) {
        bubbles.splice(b, 1);
        b--;
      }
    }
  }

  // Update splash
  for (var s = 0; s < splash.length; s++) {
    splash[s].x += splash[s].vx;
    splash[s].y += splash[s].vy;
    splash[s].vy += gravity;
    // Delete splash
    if (splash[s].y > seaLevel) {
      splash.splice(s, 1);
      s--;
    }
  }

  // Update particles
  for (var p = 0; p < particles.length; p++) {
    particles[p].x -= particles[p].vx;
    particles[p].y -= particles[p].vy;
    // Delete particle when out of bounds
    if (particles[p].x + 3 < 0 || particles[p].y + 3 < 0 ||
        particles[p].x - 3 > game.width || particles[p].y - 3 > game.height + bottomLeeway) {
      particles.splice(p, 1);
      p--;
    }
  }

  if (highScoreTime > 0) {
    highScoreTime -= 1;
  }

  // Skip player logic if not currently playing
  if (!player) {
    return;
  }

  // Check for collisions
  for (r = 0; r < rocks.length; r++) {
    if (helpers.intersected({x: player.x, y: player.y, width: 20, height: 10}, rocks[r])) {
      endGame();
      return;
    }
  }

  // Update player
  if (frameCount % 6 === 0) {
    player.score += 100;
  }
  if (player.sy > 1) {
    player.sy -= 0.1;
  }
  if (player.best && player.score > player.best) {
    player.best = player.score;
  }
  player.velocity += gravity;
  if (player.velocity > player.terminalVelocity) {
    player.velocity = player.terminalVelocity;
  }
  player.y += player.velocity;
  if (player.y >= game.height + bottomLeeway) {
    endGame();
    return;
  }
  if ((player.y - player.velocity >= seaLevel && player.y < seaLevel) ||
      (player.y - player.velocity <= seaLevel && player.y > seaLevel)) {
    newSplash();
  }
});

game.render(function (ctx) {
  // Draw background
  ctx.fillStyle = '#ece';
  ctx.fillRect(0, 0, game.width, game.height);

  // Draw sky
  var grd = ctx.createLinearGradient(game.width / 2, 0.000, game.width / 2, seaLevel);
  grd.addColorStop(0.000, '#80befc');
  grd.addColorStop(1.000, '#cbcfed');
  ctx.fillStyle = grd;
  ctx.fillRect(0, 0, game.width, seaLevel);

  // Draw water
  grd = ctx.createLinearGradient(game.width / 2, seaLevel, game.width / 2, game.height - seaLevel);
  grd.addColorStop(0.000, '#7EBDFC');
  grd.addColorStop(0.100, '#007fff');
  grd.addColorStop(1.000, '#003f7f');
  ctx.fillStyle = grd;
  ctx.fillRect(0, seaLevel, game.width, game.height - seaLevel);

  // Water lighting (note: coordinates are off, but the mistake looks better)
  grd = ctx.createLinearGradient(0, 0, game.width, game.height - seaLevel);
  grd.addColorStop(0.000, 'rgba(0, 127, 255, 0.200)');
  grd.addColorStop(0.100, 'rgba(255, 255, 255, 0.200)');
  grd.addColorStop(0.200, 'rgba(0, 127, 255, 0.200)');
  grd.addColorStop(0.500, 'rgba(255, 255, 255, 0.200)');
  grd.addColorStop(0.600, 'rgba(0, 127, 255, 0.200)');
  grd.addColorStop(0.800, 'rgba(255, 255, 255, 0.200)');
  grd.addColorStop(1.000, 'rgba(0, 127, 255, 0.200)');
  ctx.fillStyle = grd;
  ctx.fillRect(0, seaLevel, game.width, game.height - seaLevel);

  // Draw splash
  for (var s = 0; s < splash.length; s++) {
    helpers.fillCircle(ctx, splash[s].x, splash[s].y, splash[s].r, '#7EBDFC');
  }

  // Draw bubbles
  for (var b = 0; b < bubbles.length; b++) {
    helpers.fillCircle(ctx, bubbles[b].x, bubbles[b].y, bubbles[b].r, 'rgba(255, 255, 255, 0.8)');
  }

  // Draw rocks
  for (var r = 0; r < rocks.length; r++) {
    ctx.fillStyle = '#5d4';
    ctx.fillRect(rocks[r].x, rocks[r].y, rocks[r].width, rocks[r].height);
  }

  // Draw particles
  for (var p = 0; p < particles.length; p++) {
    helpers.fillCircle(ctx, particles[p].x, particles[p].y, 3, '#ff4');
  }

  // Draw score
  if (player || highScore) {
    ctx.font = 'bold 24px sans-serif';
    ctx.textAlign = 'right';
    helpers.outlineText(ctx, 'Score: ' + (player ? player.score : 0), game.width - 30, 32, '#333', '#fff');
  }
  if (highScore) {
    ctx.font = 'bold 24px sans-serif';
    helpers.outlineText(ctx, 'Best: ' + highScore, game.width - 30, 64, '#333', '#fff');
    if (highScoreTime > 0) {
      var offset = (highScoreTime) * 2;
      var fade = (highScoreTime / highScoreMaxTime * 2);
      ctx.font = 'bold ' + (24 + offset) + 'px sans-serif';
      ctx.fillStyle = 'rgba(255, 255, 255, ' + fade + ')';
      ctx.fillText('Best: ' + highScore, game.width - 30 + (offset * 0.25), 64 + (offset * 1.5));
    }
  }

  if (player) {
    // Draw player
    helpers.fillEllipse(ctx, player.x, player.y, 10, 2, player.sy, '#ff4');
    helpers.fillCircle(ctx, player.x + 5, player.y - 2, 3, '#330');
  }

  // Draw water depth gradient
  grd = ctx.createLinearGradient(game.width / 2, seaLevel, game.width / 2, game.height);
  grd.addColorStop(0.000, 'rgba(0, 127, 255, 0.100)');
  grd.addColorStop(0.700, 'rgba(0, 63, 127, 0.100)');
  grd.addColorStop(1.000, 'rgba(0, 63, 127, 0.500)');
  ctx.fillStyle = grd;
  ctx.fillRect(0, seaLevel, game.width, game.height - seaLevel);

  if (!player) {
    // Draw pre-game text
    if ((frameCount % 120 > 5 && frameCount % 120 < 20) || frameCount % 120 > 25) {
      ctx.font = 'bold 64px sans-serif';
      ctx.textAlign = 'center';
      if (highScore) {
        helpers.outlineText(ctx, 'Game over!', (game.width / 2), (game.height / 2) - 30, '#333', '#fff');
        helpers.outlineText(ctx, 'Click again!', (game.width / 2), (game.height / 2) + 40, '#333', '#fff');
      } else {
        helpers.outlineText(ctx, 'Click to start!', (game.width / 2), (game.height / 2), '#333', '#fff');
      }
    }
  }
});

// TODO: Delete this
game.run();

// TODO: Get the runtime to expose this object through a gesso.current global
module.exports = game;
<|endoftext|>


<commit_before>"use strict"

const express = require('express');
const request = require('request');
const cheerio = require('cheerio');
const app = express();

app.get('/', function (req, res) {
    res.send('Junkan server is up and running');
});

app.get('/title/:url', function (req, res) {
    var url = decodeURI(req.params.url);

    let result = {
        "title": ""
    };

    request(url, function(error, response, html) {
        // console.log(response);
        if(!error){
            var $ = cheerio.load(html);
            result.title = $('title').text();
        }

        res.send(result);
    });
});

app.get('/html/:url', function (req, res) {
    var url = decodeURI(req.params.url);

    res.send('Hello World!');
});

app.listen(3000, function () {
    console.log('Example app listening on port 3000!');
});
<commit_msg>Implements the get html route<commit_after>"use strict"

const express = require('express');
const request = require('request');
const cheerio = require('cheerio');
const app = express();

app.get('/', function (req, res) {
    res.send('Junkan server is up and running');
});

app.get('/title/:url', function (req, res) {
    var url = decodeURI(req.params.url);

    let result = {
        "title": ""
    };

    request(url, function(error, response, html) {
        if(!error){
            var $ = cheerio.load(html);
            result.title = $('title').text();
        }

        res.send(result);
    });
});

app.get('/html/:url', function (req, res) {
    var url = decodeURI(req.params.url);

    let result = {
        "html": ""
    };

    request(url, function(error, response, html) {
        if(!error){
            result.html = new Buffer(html).toString('base64');
        }

        res.send(result);
    });
});

app.listen(3000, function () {
    console.log('Junkan server is running on port 3000!');
});
<|endoftext|>


<commit_before>'use strict';

var transparency = require('transparency');
var extend = require('extend-shallow');

exports.name = 'transparency';
exports.inputFormats = ['transparency'];
exports.outputFormat = 'html';

exports.render = function (str, options, locals) {
  options = options && typeof options === 'object' ? options : {};
  locals = locals && typeof locals === 'object' ? locals : {};

  var data = extend({}, options, locals);
  return transparency.render(str, data);
};
<commit_msg>Do not check if options and locals are objects<commit_after>'use strict';

var transparency = require('transparency');
var extend = require('extend-shallow');

exports.name = 'transparency';
exports.inputFormats = ['transparency'];
exports.outputFormat = 'html';

exports.render = function (str, options, locals) {
  var data = extend({}, options, locals);
  return transparency.render(str, data);
};
<|endoftext|>


<commit_before>var util = require('util')
  , fs = require('fs')
  , spawn = require('./spawn')
  , proxy = require('./proxy')
  , errors = require('./errors')
  , cwd = process.cwd();

/**
 * Make some curl opts friendlier.
 */

var curl_map = {
    timeout: 'max-time'
  , redirects: 'max-redirs'
  , method: 'request'
  , useragent: 'user-agent'
};

/**
 * Default user-agents.
 */

var ua_file = __dirname + '/useragents.txt'
  , user_agents = fs.readFileSync(ua_file).toString().split('\n').slice(0, -1)
  , user_agents_len = user_agents.length;

/**
 * Default request headers.
 */

var default_headers = {
    'Accept': '*/*'
  , 'Accept-Charset': 'ISO-8859-1,utf-8;q=0.7,*;q=0.3'
  , 'Accept-Language': 'en-US,en;q=0.8'
};

/**
 * Make a request with cURL.
 *
 * @param {Object|String} options (optional) - see `man curl`
 * @param {Function} callback (optional)
 * @api public
 */

exports.request = function (options, callback) {
    if (arguments.length === 1) {
        var defaults = options;
        return function (options, callback) {
            if (typeof options === 'function') {
                callback = options;
                options = {};
            } else if (typeof options === 'string') {
                options = { url: options };
            }
            for (var key in defaults) {
                if (typeof options[key] === 'undefined') {
                    options[key] = defaults[key];
                }
            }
            exports.request.call(this, options, callback);
        };
    }

    if (options.retries) {
        var remaining = options.retries;
        delete options.retries;
        return (function curl() {
            exports.request(options, function (err) {
                if (!err || !--remaining) {
                    return callback.apply(this, arguments);
                }
                process.nextTick(curl);
            });
        })();
    }

    if (typeof options === 'string') {
        options = { url: options };
    } else {
        options = exports.copy(options);
    }

    for (var key in curl_map) {
        if (typeof options[key] !== 'undefined') {
            options[curl_map[key]] = options[key];
            delete options[key];
        }
    }

    if (options.proxies) {
        if (!proxy.transform) {
            proxy.transform = proxy.unpack(options.key).transform;
        }
        options = proxy.transform(options);
        delete options.key;
    }

    var curl
      , curl_path = 'curl'
      , args = ['--silent', '--show-error', '--no-buffer']
      , start = new Date
      , err
      , stderr = ''
      , stdoutlen
      , stdout = new Buffer(stdoutlen = 0)
      , encoding
      , complete
      , cleanup
      , postprocess
      , require_str
      , require_not_str
      , scope = {}
      , cmd = 'curl'
      , timeout;

    function finish() {
        if (options.fail && stderr) {
            err = String(stderr).replace(/^curl: \(\d+\) /, ''); // "curl: (22) The requested URL returned error..." => "The requested URL returned error..."
        } else if (err in errors) {
            err = errors[err];
        }
        callback.call(scope, err, stdout, {
            cmd: cmd
          , args: args
          , time: (new Date().getTime() - start.getTime())
        });
        complete = true;
    }

    //Allow for a custom curl path
    if (options.curl_path) {
        curl_path = options.curl_path;
        delete options.curl_path;
    }

    //Follow location by default
    if ('max-redirs' in options) {
        options.location = !!options['max-redirs'];
    } else {
        options.location = true;
        options['max-redirs'] = 3;
    }

    //Add an additional setTimeout for max-time
    if (options['max-time']) {
        timeout = setTimeout(function () {
            if (complete) return;
            stderr = 'timeout', stdout = null;
            finish();
            if (curl && curl.kill) curl.kill('SIGKILL');
        }, 1000 * options['max-time']);
    }

    //Default encoding is utf8. Set encoding = null to get a buffer
    if (!options.encoding && options.encoding !== null) {
        options.encoding = 'utf8';
    }
    encoding = options.encoding;
    if (encoding === 'ascii') {
        options['use-ascii'] = true;
    }
    delete options.encoding;

    //Parse POST data
    if (options.data && typeof options.data === 'object') {
        var data = [];
        for (var key in options.data) {
            data.push(encodeURIComponent(key) + '=' + encodeURIComponent(options.data[key]));
        }
        options.data = data.join('&');
    }

    //Check for the occurrence of a string and fail if not found
    if (options.require) {
        require_str = options.require;
        if (!Array.isArray(require_str)) {
            require_str = [require_str];
        }
        delete options.require;
    }

    //Check for the occurrence of a string and fail if found
    if (options.require_not) {
        require_not_str = options.require_not;
        if (!Array.isArray(require_not_str)) {
            require_not_str = [require_not_str];
        }
        delete options.require_not;
    }

    //Call the callback in a custom scope
    if (options.scope) {
        scope = options.scope;
        delete options.scope;
    }

    //Apply a post-processing function?
    if (options.process) {
        postprocess = options.process;
        delete options.process;
    }

    //Setup default headers
    var key, headers = {};
    for (key in default_headers) {
        headers[key] = default_headers[key];
    }
    if (options.headers) {
        for (key in options.headers) {
            key = key.replace(/[_-]/g, ' ').split(' ').map(function (str) {
                if (str.length) {
                    str = str[0].toUpperCase() + str.substr(1);
                }
                return str;
            }).join('-');
            headers[key] = options.headers[key];
        }
        delete options.headers;
    }
    options.header = options.header || [];
    for (key in headers) {
        options.header.push(key + ': ' + headers[key]);
    }

    //Select a random user agent if one wasn't provided
    if (!headers['User-Agent'] && !options['user-agent']) {
        options['user-agent'] = user_agents[Math.random() * user_agents_len | 0];
    }

    //Prepare curl args
    var key, values;
    for (key in options) {
        if (key === 'pretend') {
            continue;
        }
        values = Array.isArray(options[key]) ? options[key] : [options[key]];
        values.forEach(function (value) {
            args.push('--' + key);
            if (true !== value) {
                args.push(value);
            }
        });
    }

    if (options.file) {
        cmd = 'cat';
        args = [options.file];
    }

    //Simulate the spawn?
    if (options.pretend) {
        return finish();
    }

    //Spawn the process
    var child = spawn(cmd, args, { cwd: options.cwd || cwd }, function (curl) {

        //Collect stdout
        curl.stdout.on('data', function (data) {
            if (complete) return;
            var len = data.length, prev = stdout;
            stdout = new Buffer(len + stdoutlen);
            prev.copy(stdout, 0, 0, stdoutlen);
            data.copy(stdout, stdoutlen, 0, len);
            stdoutlen += len;
        });

        //Pipe stderr to the current process?
        if (options.stderr) {
            if (options.stderr === true) {
                curl.stderr.pipe(process.stderr);
                delete options.stderr
            }
        }

        curl.stderr.on('data', function (data) {
          if (complete) return;
          stderr += data;
        });

        //Handle curl exit
        curl.on('exit', function (code) {
            try {
                err = code;
                if (complete) return;
                if (encoding) {
                    stdout = stdout.toString(encoding);
                }
                if (postprocess && stdout) {
                    stdout = postprocess(stdout);
                }
                if (require_str) {
                    var valid = false;
                    if (!encoding) {
                        stdout = stdout.toString();
                    }
                    for (var i = 0, l = require_str.length; i < l; i++) {
                        if ((util.isRegExp(require_str[i]) && require_str[i].test(stdout))
                                || stdout.indexOf(require_str[i]) !== -1) {
                            valid = true;
                            break;
                        }
                    }
                    if (!valid) {
                        err = 'response does not contain required string(s)';
                        stdout = null
                    } else if (!encoding) {
                        stdout = new Buffer(stdout);
                    }
                }
                if (require_not_str) {
                    var valid = true;
                    if (!encoding) {
                        stdout = stdout.toString();
                    }
                    for (var i = 0, l = require_not_str.length; i < l; i++) {
                        if ((util.isRegExp(require_not_str[i]) && require_not_str[i].test(stdout))
                                || stdout.indexOf(require_not_str[i]) !== -1) {
                            valid = false;
                            break;
                        }
                    }
                    if (!valid) {
                        err = 'response contains bad string(s)';
                        stdout = null
                    } else if (!encoding) {
                        stdout = new Buffer(stdout);
                    }
                }
            } catch (e) {
                err = typeof e === 'object' ? e.message || '' : e;
            }
            finish();
            if (timeout) clearTimeout(timeout);
        });
    });
};

/**
 * Expose a helper for scraping urls from a page.
 */

var urls = /(?:href|src|HREF|SRC)=["']?([^"' >]+)/g;

exports.urls = function (data, regex) {
    var match, matches = [];
    while (match = urls.exec(data)) {
        if (regex && !regex.test(match[1])) {
            continue;
        }
        matches.push(match[1].replace(/[\r\n\t\s]/g, ''));
    }
    return matches;
};

/**
 * A helper for handling async concurrency.
 */

exports.concurrent = function (input, concurrency, fn) {
    if (arguments.length === 3) {
        var len = input.length, pos = 0, remaining = concurrency;
        for (var i = 0; i < concurrency; i++) {
            (function exec() {
                if (pos >= len) {
                    if (!--remaining) {
                        fn(null, function () {});
                    }
                } else {
                    fn(input[pos++], function () {
                        process.nextTick(exec);
                    });
                }
            })();
        }
    } else {
        fn = concurrency;
        concurrency = input;
        for (var i = 0; i < concurrency; i++) {
            (function exec() {
                fn(function () {
                    process.nextTick(exec);
                });
            })();
        }
    }
};

/**
 * A helper for copying an object.
 */

exports.copy = function (obj) {
    var copy = {};
    for (var i in obj) {
        if (typeof obj[i] === 'object') {
            copy[i] = obj[i] ? exports.copy(obj[i]) : null;
        } else {
            copy[i] = obj[i];
        }
    }
    return copy;
};

<commit_msg>Fix undefined headers, closes #17<commit_after>var util = require('util')
  , fs = require('fs')
  , spawn = require('./spawn')
  , proxy = require('./proxy')
  , errors = require('./errors')
  , cwd = process.cwd();

/**
 * Make some curl opts friendlier.
 */

var curl_map = {
    timeout: 'max-time'
  , redirects: 'max-redirs'
  , method: 'request'
  , useragent: 'user-agent'
};

/**
 * Default user-agents.
 */

var ua_file = __dirname + '/useragents.txt'
  , user_agents = fs.readFileSync(ua_file).toString().split('\n').slice(0, -1)
  , user_agents_len = user_agents.length;

/**
 * Default request headers.
 */

var default_headers = {
    'Accept': '*/*'
  , 'Accept-Charset': 'ISO-8859-1,utf-8;q=0.7,*;q=0.3'
  , 'Accept-Language': 'en-US,en;q=0.8'
};

/**
 * Make a request with cURL.
 *
 * @param {Object|String} options (optional) - see `man curl`
 * @param {Function} callback (optional)
 * @api public
 */

exports.request = function (options, callback) {
    if (arguments.length === 1) {
        var defaults = options;
        return function (options, callback) {
            if (typeof options === 'function') {
                callback = options;
                options = {};
            } else if (typeof options === 'string') {
                options = { url: options };
            }
            for (var key in defaults) {
                if (typeof options[key] === 'undefined') {
                    options[key] = defaults[key];
                }
            }
            exports.request.call(this, options, callback);
        };
    }

    if (options.retries) {
        var remaining = options.retries;
        delete options.retries;
        return (function curl() {
            exports.request(options, function (err) {
                if (!err || !--remaining) {
                    return callback.apply(this, arguments);
                }
                process.nextTick(curl);
            });
        })();
    }

    if (typeof options === 'string') {
        options = { url: options };
    } else {
        options = exports.copy(options);
    }

    for (var key in curl_map) {
        if (typeof options[key] !== 'undefined') {
            options[curl_map[key]] = options[key];
            delete options[key];
        }
    }

    if (options.proxies) {
        if (!proxy.transform) {
            proxy.transform = proxy.unpack(options.key).transform;
        }
        options = proxy.transform(options);
        delete options.key;
    }

    var curl
      , curl_path = 'curl'
      , args = ['--silent', '--show-error', '--no-buffer']
      , start = new Date
      , err
      , stderr = ''
      , stdoutlen
      , stdout = new Buffer(stdoutlen = 0)
      , encoding
      , complete
      , cleanup
      , postprocess
      , require_str
      , require_not_str
      , scope = {}
      , cmd = 'curl'
      , timeout;

    function finish() {
        if (options.fail && stderr) {
            err = String(stderr).replace(/^curl: \(\d+\) /, ''); // "curl: (22) The requested URL returned error..." => "The requested URL returned error..."
        } else if (err in errors) {
            err = errors[err];
        }
        callback.call(scope, err, stdout, {
            cmd: cmd
          , args: args
          , time: (new Date().getTime() - start.getTime())
        });
        complete = true;
    }

    //Allow for a custom curl path
    if (options.curl_path) {
        curl_path = options.curl_path;
        delete options.curl_path;
    }

    //Follow location by default
    if ('max-redirs' in options) {
        options.location = !!options['max-redirs'];
    } else {
        options.location = true;
        options['max-redirs'] = 3;
    }

    //Add an additional setTimeout for max-time
    if (options['max-time']) {
        timeout = setTimeout(function () {
            if (complete) return;
            stderr = 'timeout', stdout = null;
            finish();
            if (curl && curl.kill) curl.kill('SIGKILL');
        }, 1000 * options['max-time']);
    }

    //Default encoding is utf8. Set encoding = null to get a buffer
    if (!options.encoding && options.encoding !== null) {
        options.encoding = 'utf8';
    }
    encoding = options.encoding;
    if (encoding === 'ascii') {
        options['use-ascii'] = true;
    }
    delete options.encoding;

    //Parse POST data
    if (options.data && typeof options.data === 'object') {
        var data = [];
        for (var key in options.data) {
            data.push(encodeURIComponent(key) + '=' + encodeURIComponent(options.data[key]));
        }
        options.data = data.join('&');
    }

    //Check for the occurrence of a string and fail if not found
    if (options.require) {
        require_str = options.require;
        if (!Array.isArray(require_str)) {
            require_str = [require_str];
        }
        delete options.require;
    }

    //Check for the occurrence of a string and fail if found
    if (options.require_not) {
        require_not_str = options.require_not;
        if (!Array.isArray(require_not_str)) {
            require_not_str = [require_not_str];
        }
        delete options.require_not;
    }

    //Call the callback in a custom scope
    if (options.scope) {
        scope = options.scope;
        delete options.scope;
    }

    //Apply a post-processing function?
    if (options.process) {
        postprocess = options.process;
        delete options.process;
    }

    //Setup default headers
    var key, headers = {};
    for (key in default_headers) {
        headers[key] = default_headers[key];
    }
    if (options.headers) {
        var normalised_key;
        for (key in options.headers) {
            normalised_key = key.replace(/[_-]/g, ' ').split(' ').map(function (str) {
                if (str.length) {
                    str = str[0].toUpperCase() + str.substr(1);
                }
                return str;
            }).join('-');
            headers[normalised_key] = options.headers[key];
        }
        delete options.headers;
    }
    options.header = options.header || [];
    for (key in headers) {
        options.header.push(key + ': ' + headers[key]);
    }

    //Select a random user agent if one wasn't provided
    if (!headers['User-Agent'] && !options['user-agent']) {
        options['user-agent'] = user_agents[Math.random() * user_agents_len | 0];
    }

    //Prepare curl args
    var key, values;
    for (key in options) {
        if (key === 'pretend') {
            continue;
        }
        values = Array.isArray(options[key]) ? options[key] : [options[key]];
        values.forEach(function (value) {
            args.push('--' + key);
            if (true !== value) {
                args.push(value);
            }
        });
    }

    if (options.file) {
        cmd = 'cat';
        args = [options.file];
    }

    //Simulate the spawn?
    if (options.pretend) {
        return finish();
    }

    //Spawn the process
    var child = spawn(cmd, args, { cwd: options.cwd || cwd }, function (curl) {

        //Collect stdout
        curl.stdout.on('data', function (data) {
            if (complete) return;
            var len = data.length, prev = stdout;
            stdout = new Buffer(len + stdoutlen);
            prev.copy(stdout, 0, 0, stdoutlen);
            data.copy(stdout, stdoutlen, 0, len);
            stdoutlen += len;
        });

        //Pipe stderr to the current process?
        if (options.stderr) {
            if (options.stderr === true) {
                curl.stderr.pipe(process.stderr);
                delete options.stderr
            }
        }

        curl.stderr.on('data', function (data) {
          if (complete) return;
          stderr += data;
        });

        //Handle curl exit
        curl.on('exit', function (code) {
            try {
                err = code;
                if (complete) return;
                if (encoding) {
                    stdout = stdout.toString(encoding);
                }
                if (postprocess && stdout) {
                    stdout = postprocess(stdout);
                }
                if (require_str) {
                    var valid = false;
                    if (!encoding) {
                        stdout = stdout.toString();
                    }
                    for (var i = 0, l = require_str.length; i < l; i++) {
                        if ((util.isRegExp(require_str[i]) && require_str[i].test(stdout))
                                || stdout.indexOf(require_str[i]) !== -1) {
                            valid = true;
                            break;
                        }
                    }
                    if (!valid) {
                        err = 'response does not contain required string(s)';
                        stdout = null
                    } else if (!encoding) {
                        stdout = new Buffer(stdout);
                    }
                }
                if (require_not_str) {
                    var valid = true;
                    if (!encoding) {
                        stdout = stdout.toString();
                    }
                    for (var i = 0, l = require_not_str.length; i < l; i++) {
                        if ((util.isRegExp(require_not_str[i]) && require_not_str[i].test(stdout))
                                || stdout.indexOf(require_not_str[i]) !== -1) {
                            valid = false;
                            break;
                        }
                    }
                    if (!valid) {
                        err = 'response contains bad string(s)';
                        stdout = null
                    } else if (!encoding) {
                        stdout = new Buffer(stdout);
                    }
                }
            } catch (e) {
                err = typeof e === 'object' ? e.message || '' : e;
            }
            finish();
            if (timeout) clearTimeout(timeout);
        });
    });
};

/**
 * Expose a helper for scraping urls from a page.
 */

var urls = /(?:href|src|HREF|SRC)=["']?([^"' >]+)/g;

exports.urls = function (data, regex) {
    var match, matches = [];
    while (match = urls.exec(data)) {
        if (regex && !regex.test(match[1])) {
            continue;
        }
        matches.push(match[1].replace(/[\r\n\t\s]/g, ''));
    }
    return matches;
};

/**
 * A helper for handling async concurrency.
 */

exports.concurrent = function (input, concurrency, fn) {
    if (arguments.length === 3) {
        var len = input.length, pos = 0, remaining = concurrency;
        for (var i = 0; i < concurrency; i++) {
            (function exec() {
                if (pos >= len) {
                    if (!--remaining) {
                        fn(null, function () {});
                    }
                } else {
                    fn(input[pos++], function () {
                        process.nextTick(exec);
                    });
                }
            })();
        }
    } else {
        fn = concurrency;
        concurrency = input;
        for (var i = 0; i < concurrency; i++) {
            (function exec() {
                fn(function () {
                    process.nextTick(exec);
                });
            })();
        }
    }
};

/**
 * A helper for copying an object.
 */

exports.copy = function (obj) {
    var copy = {};
    for (var i in obj) {
        if (typeof obj[i] === 'object') {
            copy[i] = obj[i] ? exports.copy(obj[i]) : null;
        } else {
            copy[i] = obj[i];
        }
    }
    return copy;
};

<|endoftext|>


<commit_before>require('dotenv').config();
require('./util/checkEnv');

const os = require('os');
const fs = require('fs');
const https = require('https');

const express = require('express');
const morgan = require('morgan');
const bodyParser = require('body-parser');
const chalk = require('chalk');
const helmet = require('helmet');
const rfs = require('rotating-file-stream');

const {
  checkAuthToken,
  setupRedis,
  injectRedis,
  getLogsPath,
  logger,
  getAppStatus
} = require('./util');
const {
  getLightsRootAsync,
  getLightsIdAsync,
  postLightsIdStateAsync
} = require('./endpoints/lights');
const {
  getGroupsRootAsync,
  getGroupsIdAsync,
  postGroupIdActionAsync
} = require('./endpoints/groups');
const {
  getScenesAsync,
  getOneSceneAsync,
  deleteOneSceneAsync,
  runSceneAsync
} = require('./endpoints/scenes');
const {
  getProtocols,
  getOneProtocol,
  createProtocol,
  deleteProtocol,
  updateProtocol,
  runProtocolAsync
} = require('./endpoints/protocols');

const wrap = fn => (...args) => fn(...args).catch(args[2]);

if (process.argv.filter(a => a === '--letsencrypt-verify').length > 0) {
  const httpApp = express();
  httpApp.use(morgan('dev'));

  console.log(
    [
      `\n${chalk.yellow('WARNING!')}`,
      "The server running in Let's Encrypt verification mode.",
      `It is serving any files under ${chalk.magenta(
        './static'
      )} without any authentication over HTTP.`,
      `A restart without the ${chalk.cyan(
        '--letsencrypt-verify'
      )} switch is suggested`,
      'after verification is complete.\n'
    ].join(os.EOL)
  );

  httpApp.get('/', (req, res) => res.json({ foo: 'bar' }));

  httpApp.use(express.static('static'));
  httpApp.listen(8080, () =>
    console.log(
      `Let's Encrypt verify server running at ${chalk.green('8080')}...`
    )
  );
} else {
  const app = express();
  app.locals.logger = logger;
  const apiRouter = express.Router(); // eslint-disable-line new-cap
  const apiv2Router = express.Router(); // eslint-disable-line new-cap
  const client = setupRedis(process.env.REDIS_URL);

  const requestLogStream = rfs.createStream('request.log', {
    interval: '6h',
    path: getLogsPath(),
    size: '10M',
    compress: 'gzip'
  });

  const appPort = process.env.PORT || process.argv[2] || 8080;
  const cert = {
    key: fs.readFileSync('./sslcert/key.pem'),
    cert: fs.readFileSync('./sslcert/cert.pem')
  };
  logger.info('Read TLS cert');

  const appStatus = getAppStatus(process.env);
  logger.info(JSON.stringify(appStatus));

  app.use(bodyParser.json());
  app.use(morgan('common'));
  app.use(morgan('common', { stream: requestLogStream }));
  app.use(helmet());
  logger.info('Set up request logging');

  app.get('/', (req, res) => {
    res.json(appStatus);
  });

  apiRouter.use((req, res) => {
    res.location(req.originalUrl.replace(/\/api\//, '/api/v2/'));
    res.sendStatus(301);
  });

  apiv2Router.use(checkAuthToken);

  apiv2Router.get('/lights', wrap(getLightsRootAsync));
  apiv2Router.get('/lights/:id', wrap(getLightsIdAsync));
  apiv2Router.post('/lights/:id/state', wrap(postLightsIdStateAsync));

  apiv2Router.get('/groups', wrap(getGroupsRootAsync));
  apiv2Router.get('/groups/:id', wrap(getGroupsIdAsync));
  apiv2Router.post('/groups/:id/action', wrap(postGroupIdActionAsync));

  apiv2Router.get('/scenes', wrap(getScenesAsync));
  apiv2Router.get('/scenes/:id', wrap(getOneSceneAsync));
  apiv2Router.delete('/scenes/:id', wrap(deleteOneSceneAsync));
  apiv2Router.post('/scenes/:id', wrap(runSceneAsync));

  apiv2Router.get('/protocols', injectRedis(client), wrap(getProtocols));
  apiv2Router.post('/protocols', injectRedis(client), wrap(createProtocol));
  apiv2Router.get(
    '/protocols/:name',
    injectRedis(client),
    wrap(getOneProtocol)
  );
  apiv2Router.delete(
    '/protocols/:name',
    injectRedis(client),
    wrap(deleteProtocol)
  );
  apiv2Router.put(
    '/protocols/:name',
    injectRedis(client),
    wrap(updateProtocol)
  );
  apiv2Router.post(
    '/protocols/:name',
    injectRedis(client),
    wrap(runProtocolAsync)
  );

  app.use('/api', apiRouter);
  app.use('/api/v2', apiv2Router);

  https
    .createServer(cert, app)
    .listen(appPort, () =>
      logger.info(`Hue remote now listening at ${chalk.green(appPort)}...`)
    );
}
<commit_msg>temporarily removed redirect from the index<commit_after>require('dotenv').config();
require('./util/checkEnv');

const os = require('os');
const fs = require('fs');
const https = require('https');

const express = require('express');
const morgan = require('morgan');
const bodyParser = require('body-parser');
const chalk = require('chalk');
const helmet = require('helmet');
const rfs = require('rotating-file-stream');

const {
  checkAuthToken,
  setupRedis,
  injectRedis,
  getLogsPath,
  logger,
  getAppStatus
} = require('./util');
const {
  getLightsRootAsync,
  getLightsIdAsync,
  postLightsIdStateAsync
} = require('./endpoints/lights');
const {
  getGroupsRootAsync,
  getGroupsIdAsync,
  postGroupIdActionAsync
} = require('./endpoints/groups');
const {
  getScenesAsync,
  getOneSceneAsync,
  deleteOneSceneAsync,
  runSceneAsync
} = require('./endpoints/scenes');
const {
  getProtocols,
  getOneProtocol,
  createProtocol,
  deleteProtocol,
  updateProtocol,
  runProtocolAsync
} = require('./endpoints/protocols');

const wrap = fn => (...args) => fn(...args).catch(args[2]);

if (process.argv.filter(a => a === '--letsencrypt-verify').length > 0) {
  const httpApp = express();
  httpApp.use(morgan('dev'));

  console.log(
    [
      `\n${chalk.yellow('WARNING!')}`,
      "The server running in Let's Encrypt verification mode.",
      `It is serving any files under ${chalk.magenta(
        './static'
      )} without any authentication over HTTP.`,
      `A restart without the ${chalk.cyan(
        '--letsencrypt-verify'
      )} switch is suggested`,
      'after verification is complete.\n'
    ].join(os.EOL)
  );

  httpApp.get('/', (req, res) => res.json({ foo: 'bar' }));

  httpApp.use(express.static('static'));
  httpApp.listen(8080, () =>
    console.log(
      `Let's Encrypt verify server running at ${chalk.green('8080')}...`
    )
  );
} else {
  const app = express();
  app.locals.logger = logger;
  const apiRouter = express.Router(); // eslint-disable-line new-cap
  const apiv2Router = express.Router(); // eslint-disable-line new-cap
  const client = setupRedis(process.env.REDIS_URL);

  const requestLogStream = rfs.createStream('request.log', {
    interval: '6h',
    path: getLogsPath(),
    size: '10M',
    compress: 'gzip'
  });

  const appPort = process.env.PORT || process.argv[2] || 8080;
  const cert = {
    key: fs.readFileSync('./sslcert/key.pem'),
    cert: fs.readFileSync('./sslcert/cert.pem')
  };
  logger.info('Read TLS cert');

  const appStatus = getAppStatus(process.env);
  logger.info(JSON.stringify(appStatus));

  app.use(bodyParser.json());
  app.use(morgan('common'));
  app.use(morgan('common', { stream: requestLogStream }));
  app.use(helmet());
  logger.info('Set up request logging');

  app.get('/', (req, res) => {
    res.json(appStatus);
  });

  apiv2Router.use(checkAuthToken);

  apiv2Router.get('/lights', wrap(getLightsRootAsync));
  apiv2Router.get('/lights/:id', wrap(getLightsIdAsync));
  apiv2Router.post('/lights/:id/state', wrap(postLightsIdStateAsync));

  apiv2Router.get('/groups', wrap(getGroupsRootAsync));
  apiv2Router.get('/groups/:id', wrap(getGroupsIdAsync));
  apiv2Router.post('/groups/:id/action', wrap(postGroupIdActionAsync));

  apiv2Router.get('/scenes', wrap(getScenesAsync));
  apiv2Router.get('/scenes/:id', wrap(getOneSceneAsync));
  apiv2Router.delete('/scenes/:id', wrap(deleteOneSceneAsync));
  apiv2Router.post('/scenes/:id', wrap(runSceneAsync));

  apiv2Router.get('/protocols', injectRedis(client), wrap(getProtocols));
  apiv2Router.post('/protocols', injectRedis(client), wrap(createProtocol));
  apiv2Router.get(
    '/protocols/:name',
    injectRedis(client),
    wrap(getOneProtocol)
  );
  apiv2Router.delete(
    '/protocols/:name',
    injectRedis(client),
    wrap(deleteProtocol)
  );
  apiv2Router.put(
    '/protocols/:name',
    injectRedis(client),
    wrap(updateProtocol)
  );
  apiv2Router.post(
    '/protocols/:name',
    injectRedis(client),
    wrap(runProtocolAsync)
  );

  app.use('/api', apiRouter);
  app.use('/api/v2', apiv2Router);

  https
    .createServer(cert, app)
    .listen(appPort, () =>
      logger.info(`Hue remote now listening at ${chalk.green(appPort)}...`)
    );
}
<|endoftext|>


<commit_before>var isolines = require('turf-isolines'),
    grid = require('turf-grid'),
    destination = require('turf-destination'),
    point = require('turf-point'),
    distance = require('turf-distance'),
    extent = require('turf-extent'),
    featureCollection = require('turf-featurecollection'),
    polylineDecode = require('polyline').decode,
    OSRM = require('osrm');

module.exports = function (center, time, options, done) {
    if (!options) throw 'options is mandatory';
    if (!options.resolution) throw 'resolution is mandatory in options';
    if (!options.network) throw 'network is mandatory in options';
    if (!options.maxspeed) throw 'maxspeed is mandatory in options';
    var unit = options.unit || 'miles';
    if (options && options.draw) {
        this.draw = options.draw;
    } else {
        this.draw = function(destinations) {
            console.log(destinations);
            return isolines(destinations, 'eta', options.resolution, [time]);
        };
    }
    this.getIsochrone = function() {
        var osrm = options.network instanceof OSRM ? options.network : new OSRM(options.network);
        // compute bbox
        // bbox should go out 1.4 miles in each direction for each minute
        // this will account for a driver going a bit above the max safe speed
        var centerPt = point(center[0], center[1]);
        var spokes = featureCollection([]);
        var length = (time/3600) * options.maxspeed;
        spokes.features.push(destination(centerPt, length, 180, unit));
        spokes.features.push(destination(centerPt, length, 0, unit));
        spokes.features.push(destination(centerPt, length, 90, unit));
        spokes.features.push(destination(centerPt, length, -90, unit));
        var bbox = this.bbox = extent(spokes);
        var sizeCellGrid = this.sizeCellGrid = distance(point(bbox[0], bbox[1]), point(bbox[0], bbox[3]), unit) / options.resolution;

        //compute destination grid
        var targets = grid(bbox, options.resolution);
        targets.features = targets.features.filter(function(feat) {
            return distance(point(feat.geometry.coordinates[0], feat.geometry.coordinates[1]), centerPt, unit) <= length;
        });
        var destinations = featureCollection([]);

        var coord = targets.features.map(function(feat) {
            return [feat.geometry.coordinates[0], feat.geometry.coordinates[1]]
        });
        coord.push([center[0], center[1]]);
        console.log(coord);
        var sources = coord.length - 1;
        console.log(sources);
        osrm.table({
                coordinates: coord,
                sources: [sources]
            }, function(err, res) {
                if (err) {
                    console.log(err);
                    return done(err);
                }
                if (res.distance_table &&
                    res.distance_table[0] && res.destination_coordinates &&
                    res.distance_table[0].length == res.destination_coordinates.length) {

                    res.distance_table[0].forEach(function(time, idx) {
                        var distanceMapped = distance(
                            point(coord[idx][1], coord[idx][0]),
                            point(res.destination_coordinates[idx][1], res.destination_coordinates[idx][0]),
                            unit
                        );
                        if (distanceMapped < sizeCellGrid) {
                            destinations.features.push({
                                type: 'Feature',
                                properties: {
                                    eta: time / 10
                                },
                                geometry: {
                                    type: 'Point',
                                    coordinates: [res.destination_coordinates[idx][1], res.destination_coordinates[idx][0]]
                                }
                            });
                        }
                        // specific for isoline algorithm: exclude some points from grid
                        else {
                            destinations.features.push({
                                type: 'Feature',
                                properties: {
                                    // this point cannot be routed => a penality 2 is applied to maxspeed
                                    eta: time + (distanceMapped - sizeCellGrid) / (options.maxspeed / 3600) * 2
                                },
                                geometry: {
                                    type: 'Point',
                                    coordinates: [coord[idx][1], coord[idx][0]]
                                }
                            });
                        }
                    });
                }
                var result = self.draw(destinations);
                return done(null, result);
            }
        );
    };
    var self = this;

    // in case module is called directly
    if (this.process && this.process.title == 'node')
        return getIsochrone();
}
<commit_msg>update response property names<commit_after>var isolines = require('turf-isolines'),
    grid = require('turf-grid'),
    destination = require('turf-destination'),
    point = require('turf-point'),
    distance = require('turf-distance'),
    extent = require('turf-extent'),
    featureCollection = require('turf-featurecollection'),
    polylineDecode = require('polyline').decode,
    OSRM = require('osrm');

module.exports = function (center, time, options, done) {
    if (!options) throw 'options is mandatory';
    if (!options.resolution) throw 'resolution is mandatory in options';
    if (!options.network) throw 'network is mandatory in options';
    if (!options.maxspeed) throw 'maxspeed is mandatory in options';
    var unit = options.unit || 'miles';
    if (options && options.draw) {
        this.draw = options.draw;
    } else {
        this.draw = function(destinations) {
            console.log(destinations);
            return isolines(destinations, 'eta', options.resolution, [time]);
        };
    }
    this.getIsochrone = function() {
        var osrm = options.network instanceof OSRM ? options.network : new OSRM(options.network);
        // compute bbox
        // bbox should go out 1.4 miles in each direction for each minute
        // this will account for a driver going a bit above the max safe speed
        var centerPt = point(center[0], center[1]);
        var spokes = featureCollection([]);
        var length = (time/3600) * options.maxspeed;
        spokes.features.push(destination(centerPt, length, 180, unit));
        spokes.features.push(destination(centerPt, length, 0, unit));
        spokes.features.push(destination(centerPt, length, 90, unit));
        spokes.features.push(destination(centerPt, length, -90, unit));
        var bbox = this.bbox = extent(spokes);
        var sizeCellGrid = this.sizeCellGrid = distance(point(bbox[0], bbox[1]), point(bbox[0], bbox[3]), unit) / options.resolution;

        //compute destination grid
        var targets = grid(bbox, options.resolution);
        targets.features = targets.features.filter(function(feat) {
            return distance(point(feat.geometry.coordinates[0], feat.geometry.coordinates[1]), centerPt, unit) <= length;
        });
        var destinations = featureCollection([]);

        var coord = targets.features.map(function(feat) {
            return [feat.geometry.coordinates[0], feat.geometry.coordinates[1]]
        });
        coord.push([center[0], center[1]]);
        console.log(coord);
        var sources = coord.length - 1;
        console.log(sources);
        osrm.table({
                coordinates: coord,
                sources: [sources]
            }, function(err, res) {
                if (err) {
                    console.log(err);
                    return done(err);
                }
                console.log(res.durations);
                if (res.durations &&
                    res.durations[0] && res.destinations &&
                    res.durations[0].length == res.destinations.length) {

                    res.durations[0].forEach(function(time, idx) {
                        var distanceMapped = distance(
                            point(coord[idx][1], coord[idx][0]),
                            point(res.destinations[idx][1], res.destinations[idx][0]),
                            unit
                        );
                        if (distanceMapped < sizeCellGrid) {
                            destinations.features.push({
                                type: 'Feature',
                                properties: {
                                    eta: time / 10
                                },
                                geometry: {
                                    type: 'Point',
                                    coordinates: [res.destinations[idx][1], res.destinations[idx][0]]
                                }
                            });
                        }
                        // specific for isoline algorithm: exclude some points from grid
                        else {
                            destinations.features.push({
                                type: 'Feature',
                                properties: {
                                    // this point cannot be routed => a penality 2 is applied to maxspeed
                                    eta: time + (distanceMapped - sizeCellGrid) / (options.maxspeed / 3600) * 2
                                },
                                geometry: {
                                    type: 'Point',
                                    coordinates: [coord[idx][1], coord[idx][0]]
                                }
                            });
                        }
                    });
                }
                var result = self.draw(destinations);
                return done(null, result);
            }
        );
    };
    var self = this;

    // in case module is called directly
    if (this.process && this.process.title == 'node')
        return getIsochrone();
}
<|endoftext|>


<commit_before>var drjoint = (function(){
'use strict';

  var destinationDB;
  var sourceDB;

  var store = function(what){
    window.localStorage.setItem('drjoint', JSON.stringify(generate()));
  };

  var isContentForLoading = function(){
    var content = window.localStorage.getItem('drjoint');
    if (content && content.length > 0) {
      return true;
    } else {
      return false;
    }
  };

  var loadDialog = $( "#dialog-confirm" ).dialog({
    resizable: false,
    autoOpen: false,
    modal: true,
    buttons: {
      "Load'em ALL!": function() {
        $( this ).dialog( "close" );
      },
      Cancel: function() {
        $( this ).dialog( "close" );
      }
    }
  });

  var createDBSchema = function(data){

    var dbSchema = $('

');
    dbSchema.addClass('db-container');
    var fieldElement;

    // render table names
    for (var table in data) {
      dbSchema.append('
' + table + '
');
      dbSchema.attr('data-table-acc', table);
      fieldElement = $('

');
      fieldElement.appendTo(dbSchema);
      $.each(data[table], function(index, field){
        var fieldLabel = $('

').attr({
          'data-table': table,
          'data-field': field
        }).addClass('db-field').on('click', function(){
          var that = $(this);
          if (that.hasClass('added')) {
            return;
          }
          that.closest('.db-container').find('.selected').removeClass('selected');
          that.toggleClass('selected');
          checkSelected();
          store();
        });

        fieldLabel.append($('

').addClass('remove-button').on('click', function(){
          var that = $(this);
          var field = that.closest('.db-field');

          field.removeClass('added', 'selected');
          field.find('.field-label').text(field.attr('data-field'));
          var linkedField = $('[data-linked-to="' + field.attr('data-table') + '.' + field.attr('data-field') + '"]');
          linkedField.removeClass('added', 'selected');
          linkedField.find('.field-label').text(linkedField.attr('data-field'));
          store();
        }));

        fieldLabel.append($('

').addClass('field-label').text(field));

        fieldElement.append(
          fieldLabel
        );
      });
    }

    dbSchema.accordion({
      active: false,
      collapsible: true,
      heightStyle: 'content'
    });
    return dbSchema;
  };

  $.get('sql/prestashop.json', function (data) {
    destinationDB = createDBSchema(data);
    destinationDB.css({
      float: 'right'
    });
    destinationDB.appendTo($('#content'));
    $('#destination-search').on('keyup', searchAction(destinationDB));

  });

  $.get('sql/opencart.json', function (data) {
    sourceDB = createDBSchema(data);
    sourceDB.appendTo($('#content'));
    $('#source-search').on('keyup', searchAction(sourceDB));
  });

  var checkSelected = function(){
    var selected = $('.selected');
    if (selected.length === 2) {
      selected.addClass('added');

      var first = $(selected[0]);
      var second = $(selected[1]);
      var firstText = first.find('.field-label').text();
      var secondText = second.find('.field-label').text();
      var firstLinkedTo = second.attr('data-table')+'.' + second.attr('data-field');
      var secondLinkedTo = first.attr('data-table')+'.' + first.attr('data-field');
      first.find('.field-label').html(firstText + ' linked to ' + firstLinkedTo + '');
      first.attr('data-linked-to', firstLinkedTo);
      second.attr('data-linked-to', secondLinkedTo);
      second.find('.field-label').html(secondText + ' linked to ' + secondLinkedTo + '');
      selected.removeClass('selected');
    }
  };

  // search elements
  var searchAction = function(db) {
    return function() {
      var searchterm = $(this).val();
      db.find('.hidden').removeClass('hidden');
      var tables = db.children();
      $.each(tables, function(ind, el){
        if ($(el).text().indexOf(searchterm) === -1) {
          $(el).addClass('hidden');
        }
      });
    };
  };

  var generate = function(){
    var output = {};
    var nodes = sourceDB.find('.added');
    $.each(nodes, function(index, node){
      node = $(node);
      output['`' + node.attr('data-table')+'`.`' + node.attr('data-field') + '`'] = node.attr('data-linked-to');
    });

    return output;
  };

  $('#generate-button').on('click', function(){
    var output = generate();
      var element = $('')
        .attr('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(JSON.stringify(output)))
        .attr('download', 'output.json')
        .css('display', 'none')
        .appendTo(document.body);

        console.log(element);
      element[0].click();
      //element.remove();
  });

  if (isContentForLoading()) {
    loadDialog.dialog("open");
  }

})();
<commit_msg>:curry: load button<commit_after>var drjoint = (function(){
'use strict';

  var destinationDB;
  var sourceDB;

  var store = function(what){
    window.localStorage.setItem('drjoint', JSON.stringify(generate()));
  };

  var isContentForLoading = function(){
    var content = window.localStorage.getItem('drjoint');
    if (content && content.length > 0) {
      return true;
    } else {
      return false;
    }
  };

  var loadDialog = $( "#dialog-confirm" ).dialog({
    resizable: false,
    autoOpen: false,
    modal: true,
    buttons: {
      "Load'em ALL!": function() {
        $( this ).dialog( "close" );
      },
      Cancel: function() {
        $( this ).dialog( "close" );
      }
    }
  });

  var createDBSchema = function(data){

    var dbSchema = $('

');
    dbSchema.addClass('db-container');
    var fieldElement;

    // render table names
    for (var table in data) {
      dbSchema.append('
' + table + '
');
      dbSchema.attr('data-table-acc', table);
      fieldElement = $('

');
      fieldElement.appendTo(dbSchema);
      $.each(data[table], function(index, field){
        var fieldLabel = $('

').attr({
          'data-table': table,
          'data-field': field
        }).addClass('db-field').on('click', function(){
          var that = $(this);
          if (that.hasClass('added')) {
            return;
          }
          that.closest('.db-container').find('.selected').removeClass('selected');
          that.toggleClass('selected');
          checkSelected();
          store();
        });

        fieldLabel.append($('

').addClass('remove-button').on('click', function(){
          var that = $(this);
          var field = that.closest('.db-field');

          field.removeClass('added', 'selected');
          field.find('.field-label').text(field.attr('data-field'));
          var linkedField = $('[data-linked-to="' + field.attr('data-table') + '.' + field.attr('data-field') + '"]');
          linkedField.removeClass('added', 'selected');
          linkedField.find('.field-label').text(linkedField.attr('data-field'));
          store();
        }));

        fieldLabel.append($('

').addClass('field-label').text(field));

        fieldElement.append(
          fieldLabel
        );
      });
    }

    dbSchema.accordion({
      active: false,
      collapsible: true,
      heightStyle: 'content'
    });
    return dbSchema;
  };

  $.get('sql/prestashop.json', function (data) {
    destinationDB = createDBSchema(data);
    destinationDB.css({
      float: 'right'
    });
    destinationDB.appendTo($('#content'));
    $('#destination-search').on('keyup', searchAction(destinationDB));

  });

  $.get('sql/opencart.json', function (data) {
    sourceDB = createDBSchema(data);
    sourceDB.appendTo($('#content'));
    $('#source-search').on('keyup', searchAction(sourceDB));
  });

  var checkSelected = function(){
    var selected = $('.selected');
    if (selected.length === 2) {
      selected.addClass('added');

      var first = $(selected[0]);
      var second = $(selected[1]);
      var firstText = first.find('.field-label').text();
      var secondText = second.find('.field-label').text();
      var firstLinkedTo = second.attr('data-table')+'.' + second.attr('data-field');
      var secondLinkedTo = first.attr('data-table')+'.' + first.attr('data-field');
      first.find('.field-label').html(firstText + ' linked to ' + firstLinkedTo + '');
      first.attr('data-linked-to', firstLinkedTo);
      second.attr('data-linked-to', secondLinkedTo);
      second.find('.field-label').html(secondText + ' linked to ' + secondLinkedTo + '');
      selected.removeClass('selected');
    }
  };

  // search elements
  var searchAction = function(db) {
    return function() {
      var searchterm = $(this).val();
      db.find('.hidden').removeClass('hidden');
      var tables = db.children();
      $.each(tables, function(ind, el){
        if ($(el).text().indexOf(searchterm) === -1) {
          $(el).addClass('hidden');
        }
      });
    };
  };

  var generate = function(){
    var output = {};
    var nodes = sourceDB.find('.added');
    $.each(nodes, function(index, node){
      node = $(node);
      output['`' + node.attr('data-table')+'`.`' + node.attr('data-field') + '`'] = node.attr('data-linked-to');
    });

    return output;
  };

  $('#generate-button').on('click', function(){
    var output = generate();
      var element = $('')
        .attr('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(JSON.stringify(output)))
        .attr('download', 'output.json')
        .css('display', 'none')
        .appendTo(document.body);

        console.log(element);
      element[0].click();
      //element.remove();
  });

  $('#load-button').on('click', function(){
    loadDialog.dialog('open');
  });

  if (isContentForLoading()) {
    loadDialog.dialog("open");
  }

})();
<|endoftext|>


<commit_before>import React, { Component, PropTypes } from 'react';
import {
  ListView,
  Platform,
  StyleSheet,
  Text,
  TextInput,
  View
} from 'react-native';

class AutoComplete extends Component {
  static propTypes = {
    ...TextInput.propTypes,
    /**
     * These styles will be applied to the container which
     * surrounds the autocomplete component.
     */
    containerStyle: View.propTypes.style,
    /**
     * Assign an array of data objects which should be
     * rendered in respect to the entered text.
     */
    data: PropTypes.array,
    /*
     * These styles will be applied to the container which surrounds
     * the textInput component.
     */
    inputContainerStyle: View.propTypes.style,
    /**
     * These style will be applied to the result list view.
     */
    listStyle: ListView.propTypes.style,
    /**
     * `renderItem` will be called to render the data objects
     * which will be displayed in the result view below the
     * text input.
     */
    renderItem: PropTypes.func,
    /**
     * `renderSeparator` will be called to render the list separators
     * which will be displayed between the list elements in the result view
     * below the text input.
     */
    renderSeparator: PropTypes.func,
    /**
     * `onShowResults` will be called when list is going to
     * show/hide results.
     */
    onShowResults: PropTypes.func,
    /**
     * renders custom TextInput. All props passed to this function.
     */
    renderTextInput: PropTypes.func
  };

  static defaultProps = {
    data: [],
    defaultValue: '',
    renderItem: rowData => <Text>{rowData}</Text>,
    renderSeparator: null
  };

  constructor(props) {
    super(props);
    const ds = new ListView.DataSource({ rowHasChanged: (r1, r2) => r1 !== r2 });
    this.state = {
      dataSource: ds.cloneWithRows(props.data),
      showResults: props.data && props.data.length > 0
    };
  }

  componentWillReceiveProps(nextProps) {
    const dataSource = this.state.dataSource.cloneWithRows(nextProps.data);
    this._showResults(dataSource.getRowCount() > 0);
    this.setState({ dataSource });
  }

  /**
   * Proxy `blur()` to autocomplete's text input.
   */
  blur() {
    const { textInput } = this;
    textInput && textInput.blur();
  }

  /**
   * Proxy `focus()` to autocomplete's text input.
   */
  focus() {
    const { textInput } = this;
    textInput && textInput.focus();
  }

  _renderItems() {
    const { listStyle, renderItem, renderSeparator } = this.props;
    const { dataSource } = this.state;
    return (
      <ListView
        dataSource={dataSource}
        keyboardShouldPersistTaps="always"
        renderRow={renderItem}
        renderSeparator={renderSeparator}
        style={[styles.list, listStyle]}
      />
    );
  }

  _showResults(show) {
    const { showResults } = this.state;
    const { onShowResults } = this.props;

    if (!showResults && show) {
      this.setState({ showResults: true });
      onShowResults && onShowResults(true);
    } else if (showResults && !show) {
      this.setState({ showResults: false });
      onShowResults && onShowResults(false);
    }
  }

  _renderTextInput() {
    const { onEndEditing, renderTextInput, style } = this.props;
    const props = {
      style: [styles.input, style],
      ref: ref => (this.textInput = ref),
      onEndEditing: e =>
        this._showResults(false) || (onEndEditing && onEndEditing(e)),
      ...this.props
    };

    return renderTextInput
      ? renderTextInput(props)
      : (<TextInput {...props} />);
  }

  render() {
    const { showResults } = this.state;
    const { containerStyle, inputContainerStyle } = this.props;

    return (
      <View style={[styles.container, containerStyle]}>
        <View style={[styles.inputContainer, inputContainerStyle]}>
          {this._renderTextInput()}
        </View>
        <View>
          {showResults && this._renderItems()}
        </View>
      </View>
    );
  }
}

const border = {
  borderColor: '#b9b9b9',
  borderRadius: 1,
  borderWidth: 1
};

const androidStyles = {
  container: {
    flex: 1
  },
  inputContainer: {
    ...border,
    marginBottom: 0
  },
  list: {
    ...border,
    backgroundColor: 'white',
    borderTopWidth: 0,
    margin: 10,
    marginTop: 0
  }
};

const iosStyles = {
  container: {
    zIndex: 1
  },
  inputContainer: {
    ...border
  },
  input: {
    backgroundColor: 'white',
    height: 40,
    paddingLeft: 3
  },
  list: {
    ...border,
    backgroundColor: 'white',
    borderTopWidth: 0,
    left: 0,
    position: 'absolute',
    right: 0
  }
};

const styles = StyleSheet.create({
  input: {
    backgroundColor: 'white',
    height: 40,
    paddingLeft: 3
  },
  ...Platform.select({
    android: { ...androidStyles },
    ios: { ...iosStyles }
  })
});

export default AutoComplete;
<commit_msg>Simplify show results logic<commit_after>import React, { Component, PropTypes } from 'react';
import {
  ListView,
  Platform,
  StyleSheet,
  Text,
  TextInput,
  View
} from 'react-native';

class AutoComplete extends Component {
  static propTypes = {
    ...TextInput.propTypes,
    /**
     * These styles will be applied to the container which
     * surrounds the autocomplete component.
     */
    containerStyle: View.propTypes.style,
    /**
     * Assign an array of data objects which should be
     * rendered in respect to the entered text.
     */
    data: PropTypes.array,
    /*
     * These styles will be applied to the container which surrounds
     * the textInput component.
     */
    inputContainerStyle: View.propTypes.style,
    /**
     * These style will be applied to the result list view.
     */
    listStyle: ListView.propTypes.style,
    /**
     * `renderItem` will be called to render the data objects
     * which will be displayed in the result view below the
     * text input.
     */
    renderItem: PropTypes.func,
    /**
     * `renderSeparator` will be called to render the list separators
     * which will be displayed between the list elements in the result view
     * below the text input.
     */
    renderSeparator: PropTypes.func,
    /**
     * `onShowResults` will be called when list is going to
     * show/hide results.
     */
    onShowResults: PropTypes.func,
    /**
     * renders custom TextInput. All props passed to this function.
     */
    renderTextInput: PropTypes.func
  };

  static defaultProps = {
    data: [],
    defaultValue: '',
    renderItem: rowData => <Text>{rowData}</Text>,
    renderSeparator: null,
    renderTextInput: props => <TextInput {...props} />
  };

  constructor(props) {
    super(props);
    const ds = new ListView.DataSource({ rowHasChanged: (r1, r2) => r1 !== r2 });
    this.state = {
      dataSource: ds.cloneWithRows(props.data),
      showResults: props.data && props.data.length > 0
    };
  }

  componentWillReceiveProps(nextProps) {
    const dataSource = this.state.dataSource.cloneWithRows(nextProps.data);
    this.setState({
      dataSource,
      showResults: dataSource.getRowCount() > 0
    });
  }

  /**
   * Proxy `blur()` to autocomplete's text input.
   */
  blur() {
    const { textInput } = this;
    textInput && textInput.blur();
  }

  /**
   * Proxy `focus()` to autocomplete's text input.
   */
  focus() {
    const { textInput } = this;
    textInput && textInput.focus();
  }

  renderResultList() {
    const { dataSource } = this.state;
    const { listStyle, renderItem, renderSeparator } = this.props;

    return (
      <ListView
        dataSource={dataSource}
        keyboardShouldPersistTaps="always"
        renderRow={renderItem}
        renderSeparator={renderSeparator}
        style={[styles.list, listStyle]}
      />
    );
  }

  renderTextInput() {
    const { onEndEditing, renderTextInput, style } = this.props;
    const props = {
      style: [styles.input, style],
      ref: ref => (this.textInput = ref),
      onEndEditing: e => onEndEditing && onEndEditing(e),
      ...this.props
    };

    return renderTextInput(props);
  }

  render() {
    const { showResults } = this.state;
    const { containerStyle, inputContainerStyle, onShowResults } = this.props;

    // Notify listener if the suggestion will be shown.
    onShowResults && onShowResults(showResults);

    return (
      <View style={[styles.container, containerStyle]}>
        <View style={[styles.inputContainer, inputContainerStyle]}>
          {this.renderTextInput()}
        </View>
        <View>
          {showResults && this.renderResultList()}
        </View>
      </View>
    );
  }
}

const border = {
  borderColor: '#b9b9b9',
  borderRadius: 1,
  borderWidth: 1
};

const androidStyles = {
  container: {
    flex: 1
  },
  inputContainer: {
    ...border,
    marginBottom: 0
  },
  list: {
    ...border,
    backgroundColor: 'white',
    borderTopWidth: 0,
    margin: 10,
    marginTop: 0
  }
};

const iosStyles = {
  container: {
    zIndex: 1
  },
  inputContainer: {
    ...border
  },
  input: {
    backgroundColor: 'white',
    height: 40,
    paddingLeft: 3
  },
  list: {
    ...border,
    backgroundColor: 'white',
    borderTopWidth: 0,
    left: 0,
    position: 'absolute',
    right: 0
  }
};

const styles = StyleSheet.create({
  input: {
    backgroundColor: 'white',
    height: 40,
    paddingLeft: 3
  },
  ...Platform.select({
    android: { ...androidStyles },
    ios: { ...iosStyles }
  })
});

export default AutoComplete;
<|endoftext|>


<commit_before>/**
 * @author James Baicoianu / http://www.baicoianu.com/
 * Source: https://github.com/mrdoob/three.js/blob/master/examples/js/controls/FlyControls.js
 *
 * Adopted to common js by Andrei Kashcha
 */

var eventify = require('ngraph.events');
var createKeyMap = require('./keymap.js');

module.exports = fly;

function fly(camera, domElement, THREE) {
  domElement = domElement || document;
  domElement.setAttribute('tabindex', -1);

  var moveState = {
    up: 0,
    down: 0,
    left: 0,
    right: 0,
    forward: 0,
    back: 0,
    pitchUp: 0,
    pitchDown: 0,
    yawLeft: 0,
    yawRight: 0,
    rollLeft: 0,
    rollRight: 0
  };

  var api = {
    rollSpeed: 0.005,
    movementSpeed: 1,
    dragToLook: true,
    autoForward: false,
    /**
     * Requests to update camera position according to the currently pressed
     * keys/mouse
     */
    update: update,

    /**
     * Releases all event handlers
     */
    destroy: destroy,

    /**
     * This allows external developers to better control our internal state
     * Super flexible, yet a bit dangerous
     */
    moveState: moveState,

    updateMovementVector: updateMovementVector,
    updateRotationVector: updateRotationVector,

    /**
     * Toggles dragToLook setting. When dragToLook is set to false, then
     * camera always attempts to focus on current mouse position. The only
     * stable point in the visualization is middle of the screen.
     */
    toggleDragToLook: toggleDragToLook
  };

  eventify(api);

  var tmpQuaternion = new THREE.Quaternion();
  var isMouseDown = 0;
  var keyMap = createKeyMap();
  // we will remember what keys should be releaed in global keyup handler:
  var pendingKeyUp = Object.create(null);

  var moveVector = new THREE.Vector3(0, 0, 0);
  var rotationVector = new THREE.Vector3(0, 0, 0);

  var moveArgs = {
    move: moveVector,
    rotate: rotationVector
  };

  // these are local to the scene container. We want to initiate actions only
  // when we have focus
  domElement.addEventListener('mousedown', mousedown, false);
  domElement.addEventListener('keydown', keydown, false);

  // These are global since we can loose control otherwise and miss keyup/move
  // events.
  document.addEventListener('mousemove', mousemove, false);
  document.addEventListener('keyup', keyup, false);

  updateMovementVector();
  updateRotationVector();

  return api;

  function toggleDragToLook() {
    api.dragToLook = !api.dragToLook;
    api.moveState.yawLeft = 0;
    api.moveState.pitchDown = 0;

    updateRotationVector();

    return api.dragToLook;
  }

  function update(delta) {
    var moveMult = delta * api.movementSpeed;
    var rotMult = delta * api.rollSpeed;

    camera.translateX(moveVector.x * moveMult);
    camera.translateY(moveVector.y * moveMult);
    camera.translateZ(moveVector.z * moveMult);

    tmpQuaternion.set(rotationVector.x * rotMult, rotationVector.y * rotMult, rotationVector.z * rotMult, 1).normalize();
    camera.quaternion.multiply(tmpQuaternion);

    // expose the rotation vector for convenience
    camera.rotation.setFromQuaternion(camera.quaternion, camera.rotation.order);
  }

  function keydown(event) {
    if (isModifierKey(event)) return;

    var motion = keyMap[event.keyCode];
    if (motion) {
      moveState[motion.name] = 1;
      // we need to make sure that global key up event clears this motion:
      pendingKeyUp[event.keyCode] = true;

      updateMovementVector();
      updateRotationVector();
      api.fire('move', moveArgs);
    }
  }

  function isModifierKey(e) {
    return e.altKey || e.ctrlKey || e.metaKey;
  }

  function keyup(event) {
    if (!pendingKeyUp[event.keyCode]) return;
    pendingKeyUp[event.keyCode] = false;
    var motion = keyMap[event.keyCode];
    moveState[motion.name] = 0;

    updateMovementVector();
    updateRotationVector();
    api.fire('move', moveArgs);
  }

  function mousedown(event) {
    if (domElement !== document) {
      domElement.focus();
    }

    document.addEventListener('mouseup', mouseup, false);

    event.preventDefault();
    event.stopPropagation();

    if (api.dragToLook) {
      isMouseDown = true;
    } else {
      switch (event.button) {
        case 0:
          moveState.forward = 1;
          break;
        case 2:
          moveState.back = 1;
          break;
      }

      updateMovementVector();
    }

    api.fire('move', moveArgs);
  }

  function mousemove(event) {
    if (!api.dragToLook || isMouseDown) {
      var container = getContainerDimensions();
      var halfWidth = container.size[0] / 2;
      var halfHeight = container.size[1] / 2;

      moveState.yawLeft = -((event.pageX - container.offset[0]) - halfWidth) / halfWidth;
      moveState.pitchDown = ((event.pageY - container.offset[1]) - halfHeight) / halfHeight;

      updateRotationVector();
      api.fire('move', moveArgs);
    }
  }

  function mouseup(event) {
    event.preventDefault();
    event.stopPropagation();
    if (isMouseDown) {
      document.removeEventListener('mouseup', mouseup);
      isMouseDown = false;
    }

    if (api.dragToLook) {
      moveState.yawLeft = moveState.pitchDown = 0;
    } else {
      switch (event.button) {
        case 0:
          moveState.forward = 0;
          break;
        case 2:
          moveState.back = 0;
          break;
      }
      updateMovementVector();
    }

    updateRotationVector();
    api.fire('move', moveArgs);
  }

  function updateMovementVector() {
    var forward = (moveState.forward || (api.autoForward && !moveState.back)) ? 1 : 0;

    moveVector.x = (-moveState.left + moveState.right);
    moveVector.y = (-moveState.down + moveState.up);
    moveVector.z = (-forward + moveState.back);
  }

  function updateRotationVector() {
    rotationVector.x = (-moveState.pitchDown + moveState.pitchUp);
    rotationVector.y = (-moveState.yawRight + moveState.yawLeft);
    rotationVector.z = (-moveState.rollRight + moveState.rollLeft);
  }

  function getContainerDimensions() {
    if (domElement !== document) {
      return {
        size: [domElement.offsetWidth, domElement.offsetHeight],
        offset: [domElement.offsetLeft, domElement.offsetTop]
      };
    } else {
      return {
        size: [window.innerWidth, window.innerHeight],
        offset: [0, 0]
      };
    }
  }

  function destroy() {
    document.removeEventListener('mouseup', mouseup);
    document.removeEventListener('mousemove', mousemove, false);
    document.removeEventListener('keyup', keyup, false);
    domElement.removeEventListener('mousedown', mousedown, false);
    domElement.removeEventListener('keydown', keydown, false);
  }
}
<commit_msg>Let clients to query moving state<commit_after>/**
 * @author James Baicoianu / http://www.baicoianu.com/
 * Source: https://github.com/mrdoob/three.js/blob/master/examples/js/controls/FlyControls.js
 *
 * Adopted to common js by Andrei Kashcha
 */

var eventify = require('ngraph.events');
var createKeyMap = require('./keymap.js');

module.exports = fly;

function fly(camera, domElement, THREE) {
  domElement = domElement || document;
  domElement.setAttribute('tabindex', -1);

  var moveState = {
    up: 0,
    down: 0,
    left: 0,
    right: 0,
    forward: 0,
    back: 0,
    pitchUp: 0,
    pitchDown: 0,
    yawLeft: 0,
    yawRight: 0,
    rollLeft: 0,
    rollRight: 0
  };

  var api = {
    rollSpeed: 0.005,
    movementSpeed: 1,
    dragToLook: true,
    autoForward: false,
    /**
     * Requests to update camera position according to the currently pressed
     * keys/mouse
     */
    update: update,

    /**
     * Returns true if we are moving camera at the moment
     */
    isMoving: isMoving,

    /**
     * Releases all event handlers
     */
    destroy: destroy,

    /**
     * This allows external developers to better control our internal state
     * Super flexible, yet a bit dangerous
     */
    moveState: moveState,

    updateMovementVector: updateMovementVector,
    updateRotationVector: updateRotationVector,

    /**
     * Toggles dragToLook setting. When dragToLook is set to false, then
     * camera always attempts to focus on current mouse position. The only
     * stable point in the visualization is middle of the screen.
     */
    toggleDragToLook: toggleDragToLook
  };

  eventify(api);

  var tmpQuaternion = new THREE.Quaternion();
  var isMouseDown = 0;
  var keyMap = createKeyMap();
  // we will remember what keys should be releaed in global keyup handler:
  var pendingKeyUp = Object.create(null);

  var moveVector = new THREE.Vector3(0, 0, 0);
  var rotationVector = new THREE.Vector3(0, 0, 0);

  var moveArgs = {
    move: moveVector,
    rotate: rotationVector
  };

  // these are local to the scene container. We want to initiate actions only
  // when we have focus
  domElement.addEventListener('mousedown', mousedown, false);
  domElement.addEventListener('keydown', keydown, false);

  // These are global since we can loose control otherwise and miss keyup/move
  // events.
  document.addEventListener('mousemove', mousemove, false);
  document.addEventListener('keyup', keyup, false);

  updateMovementVector();
  updateRotationVector();

  return api;

  function isMoving() {
    return moveState.up
            || moveState.down
            || moveState.left
            || moveState.right
            || moveState.forward
            || moveState.back
            || moveState.pitchUp
            || moveState.pitchDown
            || moveState.yawLeft
            || moveState.yawRight
            || moveState.rollLeft
            || moveState.rollRight;
  }

  function toggleDragToLook() {
    api.dragToLook = !api.dragToLook;
    api.moveState.yawLeft = 0;
    api.moveState.pitchDown = 0;

    updateRotationVector();

    return api.dragToLook;
  }

  function update(delta) {
    var moveMult = delta * api.movementSpeed;
    var rotMult = delta * api.rollSpeed;

    camera.translateX(moveVector.x * moveMult);
    camera.translateY(moveVector.y * moveMult);
    camera.translateZ(moveVector.z * moveMult);

    tmpQuaternion.set(rotationVector.x * rotMult, rotationVector.y * rotMult, rotationVector.z * rotMult, 1).normalize();
    camera.quaternion.multiply(tmpQuaternion);

    // expose the rotation vector for convenience
    camera.rotation.setFromQuaternion(camera.quaternion, camera.rotation.order);
  }

  function keydown(event) {
    if (isModifierKey(event)) return;

    var motion = keyMap[event.keyCode];
    if (motion) {
      moveState[motion.name] = 1;
      // we need to make sure that global key up event clears this motion:
      pendingKeyUp[event.keyCode] = true;

      updateMovementVector();
      updateRotationVector();
      api.fire('move', moveArgs);
    }
  }

  function isModifierKey(e) {
    return e.altKey || e.ctrlKey || e.metaKey;
  }

  function keyup(event) {
    if (!pendingKeyUp[event.keyCode]) return;
    pendingKeyUp[event.keyCode] = false;
    var motion = keyMap[event.keyCode];
    moveState[motion.name] = 0;

    updateMovementVector();
    updateRotationVector();
    api.fire('move', moveArgs);
  }

  function mousedown(event) {
    if (domElement !== document) {
      domElement.focus();
    }

    document.addEventListener('mouseup', mouseup, false);

    event.preventDefault();
    //event.stopPropagation();

    if (api.dragToLook) {
      isMouseDown = true;
    } else {
      switch (event.button) {
        case 0:
          moveState.forward = 1;
          break;
        case 2:
          moveState.back = 1;
          break;
      }

      updateMovementVector();
    }

    api.fire('move', moveArgs);
  }

  function mousemove(event) {
    if (!api.dragToLook || isMouseDown) {
      var container = getContainerDimensions();
      var halfWidth = container.size[0] / 2;
      var halfHeight = container.size[1] / 2;

      moveState.yawLeft = -((event.pageX - container.offset[0]) - halfWidth) / halfWidth;
      moveState.pitchDown = ((event.pageY - container.offset[1]) - halfHeight) / halfHeight;

      updateRotationVector();
      api.fire('move', moveArgs);
    }
  }

  function mouseup(event) {
    event.preventDefault();

    if (isMouseDown) {
      document.removeEventListener('mouseup', mouseup);
      isMouseDown = false;
    }

    if (api.dragToLook) {
      moveState.yawLeft = moveState.pitchDown = 0;
    } else {
      switch (event.button) {
        case 0:
          moveState.forward = 0;
          break;
        case 2:
          moveState.back = 0;
          break;
      }
      updateMovementVector();
    }

    updateRotationVector();
    api.fire('move', moveArgs);
  }

  function updateMovementVector() {
    var forward = (moveState.forward || (api.autoForward && !moveState.back)) ? 1 : 0;

    moveVector.x = (-moveState.left + moveState.right);
    moveVector.y = (-moveState.down + moveState.up);
    moveVector.z = (-forward + moveState.back);
  }

  function updateRotationVector() {
    rotationVector.x = (-moveState.pitchDown + moveState.pitchUp);
    rotationVector.y = (-moveState.yawRight + moveState.yawLeft);
    rotationVector.z = (-moveState.rollRight + moveState.rollLeft);
  }

  function getContainerDimensions() {
    if (domElement !== document) {
      return {
        size: [domElement.offsetWidth, domElement.offsetHeight],
        offset: [domElement.offsetLeft, domElement.offsetTop]
      };
    } else {
      return {
        size: [window.innerWidth, window.innerHeight],
        offset: [0, 0]
      };
    }
  }

  function destroy() {
    document.removeEventListener('mouseup', mouseup);
    document.removeEventListener('mousemove', mousemove, false);
    document.removeEventListener('keyup', keyup, false);
    domElement.removeEventListener('mousedown', mousedown, false);
    domElement.removeEventListener('keydown', keydown, false);
  }
}
<|endoftext|>