<commit_before>var config = require('config.json')('./config.json');
var app = require('express')();
var User = require('./models/User.js');
var twilio = require('twilio')('ACd9ca0c5ad3177148707f2be7593fc068', 'd381167bf4cfec68df4166c0e97dd666');

var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/test');

var db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', function (callback) {
  console.log("database opened");
});

var listQueue = new Array();

function findUser(user) {
    for (var index = 0; index < listQueue.length; index++) {
      var currentUser = listQueue[index];
      if (currentUser.phone === user.phone) {
        return index;
      }
    }
   return -1;
}

function sendMessage(to, content) {
  twilio.sendSms({
    to:to,
    from:'+33644600833',
    body:content
  }, function(error, message) {
    if (!error) {
        console.log('Success! The SID for this SMS message is:');
        console.log(message.sid);
        console.log('Message sent on:');
        console.log(message.dateCreated);
    } else {
        console.log('Oops! There was an error.');
    }
  });
}

function interpretCommand(command, user) {
    var content = null;
    console.log("interpret command");

    switch (command) {
    case "hello":
      var currentIndexFind = findUser(user);
      if (currentIndexFind != -1) {
        content = "Vous êtes déjà dans la liste d'attente à la position " + currentIndexFind + ".";
      }
      else {
        listQueue.push(user);
        var currentPosInQueue = listQueue.length;
        content = "Bienvenue sur Fastlne, le service de gestion des files d'attente par SMS.";
        content += " Vous êtes le numéro " + currentPosInQueue + " dans la file d'attente.";
        content += " Vous serez prévenu par sms dés que ce sera à votre tour de passer en caisse.";
      }
      break;

    case "status":
      content = ""
      var positionQueue = findUser(user);
      if (positionQueue == -1) {
        content = "Vous n'êtes actuellement pas dans la liste d'attente. Envoyez << hello >> pour entrer dans la fille d'attente.";
      }
      else {
        content = "Vous êtes en position " + positionQueue + " dans la file d'attente.";
      }
      break;

    case "quit":
      var positionQueue = findUser(user);
      if (positionQueue == -1) {
        content = "Vous n'êtes actuellement pas dans la liste d'attente. Envoyez << hello >> pour entrer dans la fille d'attente.";
      }
      else  {
        listQueue.splice(positionQueue, 1);
        content = "Nous avons bien pris en compte votre retrait de la file d’attente";
      }
      break;

    default:
    case "help":
      console.log("commande help");
      content = "help - envoyer <<help>> pour obtenirde l'aide sur le fonctionnement du service."
      content += "\nhello - envoyer <<hello>> pour entrer dans la fille d'attente.";
      content += "\nstatus - envoyer <<status>> pour connaitre votre position dans la fille d'attente.";
      content += "\nquit - envoyer <<quit>> pour sortir de la file d'attente.";
      break;
  }
  if (content) {
    console.log("content : " + content);
    sendMessage(user.phone, content);
  }
}

function sendWelcomeUser(user) {
  var content = "Bienvenue sur Fastlne, le service de gestion des files d'attente par SMS. Voici le descriptif des principales commandes:";
  content += "\n\nhelp - envoyer <<help>> pour obtenirde l'aide sur le fonctionnement du service.";
  content += "\n\nhello - envoyer <<hello>> pour entrer dans la fille d'attente.";
  content += "\n\nstatus - envoyer <<status>> pour connaitre votre position dans la fille d'attente.";
  content += "\n\nquit - envoyer <<quit>> pour sortir de la file d'attente.";
  sendMessage(user.phone, content);
}

app.get('/sms', function (req, res) {
  console.log("------------ [RECEIVED MESSAGE] -------");
  var phoneNumber = "+131";
  var command = req.querry.body.toUpperCase().toLowerCase();

  console.log(listQueue);

  User.findOne({phone:phoneNumber}, function(err, obj) {
      if (err) {
        console.log("error" + err);
        res.send("error");
        return;
      }
      if (obj) {
        console.log("Get user");
        interpretCommand(command, obj);
      }
      else {
        var newUser = User();
        newUser.phone = phoneNumber;
        newUser.save(function(err) {
          if (!err) {
            console.log("Create new user");
            interpretCommand(command, newUser);
          }
        });
      }
  });
  res.send('Hello World!');
});

var server = app.listen(config.port, function () {
  var host = server.address().address;
  var port = server.address().port;
  console.log('Example app listening at http://%s:%s', host, port);
});
<commit_msg>add debug<commit_after>var config = require('config.json')('./config.json');
var app = require('express')();
var User = require('./models/User.js');
var twilio = require('twilio')('ACd9ca0c5ad3177148707f2be7593fc068', 'd381167bf4cfec68df4166c0e97dd666');

var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/test');

var db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', function (callback) {
  console.log("database opened");
});

var listQueue = new Array();

function findUser(user) {
    for (var index = 0; index < listQueue.length; index++) {
      var currentUser = listQueue[index];
      if (currentUser.phone === user.phone) {
        return index;
      }
    }
   return -1;
}

function sendMessage(to, content) {
  twilio.sendSms({
    to:to,
    from:'+33644600833',
    body:content
  }, function(error, message) {
    if (!error) {
        console.log('Success! The SID for this SMS message is:');
        console.log(message.sid);
        console.log('Message sent on:');
        console.log(message.dateCreated);
    } else {
        console.log('Oops! There was an error.');
    }
  });
}

function interpretCommand(command, user) {
    var content = null;
    console.log("interpret command");

    switch (command) {
    case "hello":
      var currentIndexFind = findUser(user);
      if (currentIndexFind != -1) {
        content = "Vous êtes déjà dans la liste d'attente à la position " + currentIndexFind + ".";
      }
      else {
        listQueue.push(user);
        var currentPosInQueue = listQueue.length;
        content = "Bienvenue sur Fastlne, le service de gestion des files d'attente par SMS.";
        content += " Vous êtes le numéro " + currentPosInQueue + " dans la file d'attente.";
        content += " Vous serez prévenu par sms dés que ce sera à votre tour de passer en caisse.";
      }
      break;

    case "status":
      content = ""
      var positionQueue = findUser(user);
      if (positionQueue == -1) {
        content = "Vous n'êtes actuellement pas dans la liste d'attente. Envoyez << hello >> pour entrer dans la fille d'attente.";
      }
      else {
        content = "Vous êtes en position " + positionQueue + " dans la file d'attente.";
      }
      break;

    case "quit":
      var positionQueue = findUser(user);
      if (positionQueue == -1) {
        content = "Vous n'êtes actuellement pas dans la liste d'attente. Envoyez << hello >> pour entrer dans la fille d'attente.";
      }
      else  {
        listQueue.splice(positionQueue, 1);
        content = "Nous avons bien pris en compte votre retrait de la file d’attente";
      }
      break;

    default:
    case "help":
      console.log("commande help");
      content = "help - envoyer <<help>> pour obtenirde l'aide sur le fonctionnement du service."
      content += "\nhello - envoyer <<hello>> pour entrer dans la fille d'attente.";
      content += "\nstatus - envoyer <<status>> pour connaitre votre position dans la fille d'attente.";
      content += "\nquit - envoyer <<quit>> pour sortir de la file d'attente.";
      break;
  }
  if (content) {
    console.log("content : " + content);
    sendMessage(user.phone, content);
  }
}

function sendWelcomeUser(user) {
  var content = "Bienvenue sur Fastlne, le service de gestion des files d'attente par SMS. Voici le descriptif des principales commandes:";
  content += "\n\nhelp - envoyer <<help>> pour obtenirde l'aide sur le fonctionnement du service.";
  content += "\n\nhello - envoyer <<hello>> pour entrer dans la fille d'attente.";
  content += "\n\nstatus - envoyer <<status>> pour connaitre votre position dans la fille d'attente.";
  content += "\n\nquit - envoyer <<quit>> pour sortir de la file d'attente.";
  sendMessage(user.phone, content);
}

app.get('/sms', function (req, res) {
  console.log("------------ [RECEIVED MESSAGE] -------");
  console.log("req : " + req);
  var phoneNumber = req.querry.from;
  var command = req.querry.body.toUpperCase().toLowerCase();

  console.log(listQueue);

  User.findOne({phone:phoneNumber}, function(err, obj) {
      if (err) {
        console.log("error" + err);
        res.send("error");
        return;
      }
      if (obj) {
        console.log("Get user");
        interpretCommand(command, obj);
      }
      else {
        var newUser = User();
        newUser.phone = phoneNumber;
        newUser.save(function(err) {
          if (!err) {
            console.log("Create new user");
            interpretCommand(command, newUser);
          }
        });
      }
  });
  res.send('Hello World!');
});

var server = app.listen(config.port, function () {
  var host = server.address().address;
  var port = server.address().port;
  console.log('Example app listening at http://%s:%s', host, port);
});
<|endoftext|>


<commit_before>var express = require('express')
var app = express()
var swig = require('swig')

app.use('/public', express.static(__dirname + '/public'))
app.engine('html', swig.renderFile)
app.set('views', './views')
app.set('view engine', 'html')

swig.setDefaults({cache: false})

app.use('/admin', require('./routers/admin'))
app.use('/api', require('./routers/api'))
app.use('/main', require('./routers/main'))

app.listen(8081, () => {
  console.log('server is listening at 8081 ...')
})<commit_msg>feat:配置数据库连接<commit_after>var express = require('express')
var app = express()
var swig = require('swig')
var mongoose = require('mongoose')

app.use('/public', express.static(__dirname + '/public'))
app.engine('html', swig.renderFile)
app.set('views', './views')
app.set('view engine', 'html')

swig.setDefaults({cache: false})

app.use('/admin', require('./routers/admin'))
app.use('/api', require('./routers/api'))
app.use('/main', require('./routers/main'))

mongoose.connect('mongodb://localhost:27018/blog', err => {
  if (err) {
    console.log('数据库连接失败')
  } else {
    console.log('数据库连接成功')
    app.listen(8081, () => {
      console.log('server is listening at 8081 ...')
    })

  }
})
<|endoftext|>


<commit_before>'use strict';

var hours = ['6am', '7am', '8am', '9am', '10am', '11am', '12am', '1pm', '2pm', '3pm', '4pm', '5pm', '6pm', '7pm'];

var firstAndPike = {
  locationName: 'First and Pike',
  minCustPerHour: 23,
  maxCustPerHour: 65,
  avgCookiesperCust: 6.3,
  randomCustPerHour: [],
  totalCookiesSoldEachHour: [],
  totalDailyCookiesSales: 0,
  calcRandomCustPerHour: function() {
    for (var i = 0; i < hours.length ; i++){
      // this.randomCustPerHour[i] = Math.floor(Math.random() * ( this.maxCustPerHour - this.minCustPerHour + 1) + this.minCustPerHour);
      this.randomCustPerHour.push(Math.floor(Math.random() *( this.maxCustPerHour - this.minCustPerHour + 1 )) + this.minCustPerHour );
      // console.log(this.randomCustPerHour);
    }
  },

  calcTotalCookiesSoldEachHour: function() {
    //callcalcrandomcustperhour()
    this.calcRandomCustPerHour();
    for (var i = 0; i < hours.length ; i++){
      this.totalCookiesSoldEachHour.push(Math.ceil(this.randomCustPerHour[i] * this.avgCookiesperCust));
      // this.totalCookies += this.cookiesSoldEachHour[i];
      this.totalDailyCookiesSales += this.totalCookiesSoldEachHour[i];
      // console.log(this.totalDailycookiesales, 'running total of daily cookie sales');
    }
    // console.log(this.cookiesSoldEachHour[i]), ' random numbers of cookies sold each hour';
  },
  render: function(){
    this.calcTotalCookiesSoldEachHour();
    var emptyUl = document.getElementById('firstAndPike');
    for (var i = 0; i < hours.length ; i++){
      var liEl = document.createElement('li');
      liEl.textContent = hours[i] + ': ' + this.totalCookiesSoldEachHour[i] + ' cookies';
      emptyUl.appendChild (liEl);
    }
    liEl = document.createElement('li');
    liEl.textContent = 'total: ' + this.totalDailyCookiesSales + ' cookies ';
    emptyUl.appendChild (liEl);
  }
}

firstAndPike.render();
// seaTac Airport
var seaTacAirport = {
  locationName: 'seaTac',
  minCustPerHour: 3,
  maxCustPerHour: 24,
  avgCookiesperCust: 63.7,
  randomCustPerHour: [],
  totalCookiesSoldEachHour: [],
  totalDailyCookiesSales: 0,
  calcRandomCustPerHour: function() {
    for (var i = 0; i < hours.length ; i++){
      // this.randomCustPerHour[i] = Math.floor(Math.random() * ( this.maxCustPerHour - this.minCustPerHour + 1) + this.minCustPerHour);
      this.randomCustPerHour.push(Math.floor(Math.random() *( this.maxCustPerHour - this.minCustPerHour + 1 )) + this.minCustPerHour );
      // console.log(this.randomCustPerHour);
    }
  },

  calcTotalCookiesSoldEachHour: function() {
    //callcalcrandomcustperhour()
    this.calcRandomCustPerHour();
    for (var i = 0; i < hours.length ; i++){
      this.totalCookiesSoldEachHour.push(Math.ceil(this.randomCustPerHour[i] * this.avgCookiesperCust));
      // this.totalCookies += this.cookiesSoldEachHour[i];
      this.totalDailyCookiesSales += this.totalCookiesSoldEachHour[i];
      // console.log(this.totalDailycookiesales, 'running total of daily cookie sales');
    }
    // console.log(this.cookiesSoldEachHour[i]), ' random numbers of cookies sold each hour';
  },
  render: function(){
    this.calcTotalCookiesSoldEachHour();
    var emptyUl = document.getElementById('seaTac');
    for (var i = 0; i < hours.length ; i++){
      var liEl = document.createElement('li');
      liEl.textContent = hours[i] + ': ' + this.totalCookiesSoldEachHour[i] + ' cookies';
      emptyUl.appendChild (liEl);
    }
    liEl = document.createElement('li');
    liEl.textContent = 'total: ' + this.totalDailyCookiesSales + ' cookies ';
    emptyUl.appendChild (liEl);
  }
}

seaTacAirport.render();

//seattle Center
var seattleCenter = {
  locationName: 'seaCenter',
  minCustPerHour: 3,
  maxCustPerHour: 24,
  avgCookiesperCust: 63.7,
  randomCustPerHour: [],
  totalCookiesSoldEachHour: [],
  totalDailyCookiesSales: 0,
  calcRandomCustPerHour: function() {
    for (var i = 0; i < hours.length ; i++){
      // this.randomCustPerHour[i] = Math.floor(Math.random() * ( this.maxCustPerHour - this.minCustPerHour + 1) + this.minCustPerHour);
      this.randomCustPerHour.push(Math.floor(Math.random() *( this.maxCustPerHour - this.minCustPerHour + 1 )) + this.minCustPerHour );
      // console.log(this.randomCustPerHour);
    }
  },

  calcTotalCookiesSoldEachHour: function() {
    //callcalcrandomcustperhour()
    this.calcRandomCustPerHour();
    for (var i = 0; i < hours.length ; i++){
      this.totalCookiesSoldEachHour.push(Math.ceil(this.randomCustPerHour[i] * this.avgCookiesperCust));
      // this.totalCookies += this.cookiesSoldEachHour[i];
      this.totalDailyCookiesSales += this.totalCookiesSoldEachHour[i];
      // console.log(this.totalDailycookiesales, 'running total of daily cookie sales');
    }
    // console.log(this.cookiesSoldEachHour[i]), ' random numbers of cookies sold each hour';
  },
  render: function(){
    this.calcTotalCookiesSoldEachHour();
    var emptyUl = document.getElementById('seaCenter');
    for (var i = 0; i < hours.length ; i++){
      var liEl = document.createElement('li');
      liEl.textContent = hours[i] + ': ' + this.totalCookiesSoldEachHour[i] + ' cookies';
      emptyUl.appendChild (liEl);
    }
    liEl = document.createElement('li');
    liEl.textContent = 'total: ' + this.totalDailyCookiesSales + ' cookies ';
    emptyUl.appendChild (liEl);
  }
}

seattleCenter.render();

//capitol Hill
var capitolHill = {
  locationName: 'capitolHill',
  minCustPerHour: 3,
  maxCustPerHour: 24,
  avgCookiesperCust: 63.7,
  randomCustPerHour: [],
  totalCookiesSoldEachHour: [],
  totalDailyCookiesSales: 0,
  calcRandomCustPerHour: function() {
    for (var i = 0; i < hours.length ; i++){
      // this.randomCustPerHour[i] = Math.floor(Math.random() * ( this.maxCustPerHour - this.minCustPerHour + 1) + this.minCustPerHour);
      this.randomCustPerHour.push(Math.floor(Math.random() *( this.maxCustPerHour - this.minCustPerHour + 1 )) + this.minCustPerHour );
      // console.log(this.randomCustPerHour);
    }
  },

  calcTotalCookiesSoldEachHour: function() {
    //callcalcrandomcustperhour()
    this.calcRandomCustPerHour();
    for (var i = 0; i < hours.length ; i++){
      this.totalCookiesSoldEachHour.push(Math.ceil(this.randomCustPerHour[i] * this.avgCookiesperCust));
      // this.totalCookies += this.cookiesSoldEachHour[i];
      this.totalDailyCookiesSales += this.totalCookiesSoldEachHour[i];
      // console.log(this.totalDailycookiesales, 'running total of daily cookie sales');
    }
    // console.log(this.cookiesSoldEachHour[i]), ' random numbers of cookies sold each hour';
  },
  render: function(){
    this.calcTotalCookiesSoldEachHour();
    var emptyUl = document.getElementById('capitolHill');
    for (var i = 0; i < hours.length ; i++){
      var liEl = document.createElement('li');
      liEl.textContent = hours[i] + ': ' + this.totalCookiesSoldEachHour[i] + ' cookies';
      emptyUl.appendChild (liEl);
    }
    liEl = document.createElement('li');
    liEl.textContent = 'total: ' + this.totalDailyCookiesSales + ' cookies ';
    emptyUl.appendChild (liEl);
  }
}

capitolHill.render();

//alki
var alki = {
  locationName: 'alki',
  minCustPerHour: 3,
  maxCustPerHour: 24,
  avgCookiesperCust: 63.7,
  randomCustPerHour: [],
  totalCookiesSoldEachHour: [],
  totalDailyCookiesSales: 0,
  calcRandomCustPerHour: function() {
    for (var i = 0; i < hours.length ; i++){
      // this.randomCustPerHour[i] = Math.floor(Math.random() * ( this.maxCustPerHour - this.minCustPerHour + 1) + this.minCustPerHour);
      this.randomCustPerHour.push(Math.floor(Math.random() *( this.maxCustPerHour - this.minCustPerHour + 1 )) + this.minCustPerHour );
      // console.log(this.randomCustPerHour);
    }
  },

  calcTotalCookiesSoldEachHour: function() {
    //callcalcrandomcustperhour()
    this.calcRandomCustPerHour();
    for (var i = 0; i < hours.length ; i++){
      this.totalCookiesSoldEachHour.push(Math.ceil(this.randomCustPerHour[i] * this.avgCookiesperCust));
      // this.totalCookies += this.cookiesSoldEachHour[i];
      this.totalDailyCookiesSales += this.totalCookiesSoldEachHour[i];
      // console.log(this.totalDailycookiesales, 'running total of daily cookie sales');
    }
    // console.log(this.cookiesSoldEachHour[i]), ' random numbers of cookies sold each hour';
  },
  render: function(){
    this.calcTotalCookiesSoldEachHour();
    var emptyUl = document.getElementById('alki');
    for (var i = 0; i < hours.length ; i++){
      var liEl = document.createElement('li');
      liEl.textContent = hours[i] + ': ' + this.totalCookiesSoldEachHour[i] + ' cookies';
      emptyUl.appendChild (liEl);
    }
    liEl = document.createElement('li');
    liEl.textContent = 'total: ' + this.totalDailyCookiesSales + ' cookies ';
    emptyUl.appendChild (liEl);
  }
}

alki.render();
<commit_msg>constructors made<commit_after>'use strict';
// var allStores = ['First and Pike', 'SeaTac Airport', 'SeattleCenter', 'Capitol Hill', 'Alki'];
// var hours = ['6am', '7am', '8am', '9am', '10am', '11am', '12am', '1pm', '2pm', '3pm', '4pm', '5pm', '6pm', '7pm'];

function Store(locationName, minCustPerHour, maxCustPerHour, avgCookiesperCust){
  this.locationName = locationName;
  this.minCustPerHour = minCustPerHour;
  this.maxCustPerHour = maxCustPerHour;
  this.avgCookiesperCust = avgCookiesperCust;
  this.randomCustPerHour = [];
  this.totalCookiesSoldEachHour = [];
  this.totalDailyCookiesSales = 0;
  //
  this.introduction = function(){
  //   console.log('location is ' + locationName + ' and randomCustPerHour is' + randomCustPerHour);
  };
  allStore.push(this);
  console.log(this);
}
var allStore = [];
new Store('First and Pike', 23,65,6.3);
new Store('SeaTac Airpot', 3, 24, 1.2);
new Store('Seattle Center', 11, 38, 3.7);
new Store('Capitol Hill', 20, 38, 2.3);
new Store('Alki', 2, 16, 4.6);

// var firstAndPike = {
//   locationName: 'First and Pike',
//   minCustPerHour: 23,
//   maxCustPerHour: 65,
//   avgCookiesperCust: 6.3,
//   randomCustPerHour: [],
//   totalCookiesSoldEachHour: [],
//   totalDailyCookiesSales: 0,
//   calcRandomCustPerHour: function() {
//     for (var i = 0; i < hours.length ; i++){
//       // this.randomCustPerHour[i] = Math.floor(Math.random() * ( this.maxCustPerHour - this.minCustPerHour + 1) + this.minCustPerHour);
//       this.randomCustPerHour.push(Math.floor(Math.random() *( this.maxCustPerHour - this.minCustPerHour + 1 )) + this.minCustPerHour );
//       // console.log(this.randomCustPerHour);
//     }
//   },
//
//
//   calcTotalCookiesSoldEachHour: function() {
//     //callcalcrandomcustperhour()
//     this.calcRandomCustPerHour();
//     for (var i = 0; i < hours.length ; i++){
//       this.totalCookiesSoldEachHour.push(Math.ceil(this.randomCustPerHour[i] * this.avgCookiesperCust));
//       // this.totalCookies += this.cookiesSoldEachHour[i];
//       this.totalDailyCookiesSales += this.totalCookiesSoldEachHour[i];
//       // console.log(this.totalDailycookiesales, 'running total of daily cookie sales');
//     }
//     // console.log(this.cookiesSoldEachHour[i]), ' random numbers of cookies sold each hour';
//   },
//   render: function(){
//     this.calcTotalCookiesSoldEachHour();
//     var emptyUl = document.getElementById('firstAndPike');
//     for (var i = 0; i < hours.length ; i++){
//       var liEl = document.createElement('li');
//       liEl.textContent = hours[i] + ': ' + this.totalCookiesSoldEachHour[i] + ' cookies';
//       emptyUl.appendChild (liEl);
//     }
//     liEl = document.createElement('li');
//     liEl.textContent = 'total: ' + this.totalDailyCookiesSales + ' cookies ';
//     emptyUl.appendChild (liEl);
//   }
// }
//
// firstAndPike.render();
// // seaTac Airport
// var seaTacAirport = {
//   locationName: 'seaTac',
//   minCustPerHour: 3,
//   maxCustPerHour: 24,
//   avgCookiesperCust: 63.7,
//   randomCustPerHour: [],
//   totalCookiesSoldEachHour: [],
//   totalDailyCookiesSales: 0,
//   calcRandomCustPerHour: function() {
//     for (var i = 0; i < hours.length ; i++){
//       // this.randomCustPerHour[i] = Math.floor(Math.random() * ( this.maxCustPerHour - this.minCustPerHour + 1) + this.minCustPerHour);
//       this.randomCustPerHour.push(Math.floor(Math.random() *( this.maxCustPerHour - this.minCustPerHour + 1 )) + this.minCustPerHour );
//       // console.log(this.randomCustPerHour);
//     }
//   },
//
//
//   calcTotalCookiesSoldEachHour: function() {
//     //callcalcrandomcustperhour()
//     this.calcRandomCustPerHour();
//     for (var i = 0; i < hours.length ; i++){
//       this.totalCookiesSoldEachHour.push(Math.ceil(this.randomCustPerHour[i] * this.avgCookiesperCust));
//       // this.totalCookies += this.cookiesSoldEachHour[i];
//       this.totalDailyCookiesSales += this.totalCookiesSoldEachHour[i];
//       // console.log(this.totalDailycookiesales, 'running total of daily cookie sales');
//     }
//     // console.log(this.cookiesSoldEachHour[i]), ' random numbers of cookies sold each hour';
//   },
//   render: function(){
//     this.calcTotalCookiesSoldEachHour();
//     var emptyUl = document.getElementById('seaTac');
//     for (var i = 0; i < hours.length ; i++){
//       var liEl = document.createElement('li');
//       liEl.textContent = hours[i] + ': ' + this.totalCookiesSoldEachHour[i] + ' cookies';
//       emptyUl.appendChild (liEl);
//     }
//     liEl = document.createElement('li');
//     liEl.textContent = 'total: ' + this.totalDailyCookiesSales + ' cookies ';
//     emptyUl.appendChild (liEl);
//   }
// }
//
// seaTacAirport.render();
//
// //seattle Center
// var seattleCenter = {
//   locationName: 'seaCenter',
//   minCustPerHour: 3,
//   maxCustPerHour: 24,
//   avgCookiesperCust: 63.7,
//   randomCustPerHour: [],
//   totalCookiesSoldEachHour: [],
//   totalDailyCookiesSales: 0,
//   calcRandomCustPerHour: function() {
//     for (var i = 0; i < hours.length ; i++){
//       // this.randomCustPerHour[i] = Math.floor(Math.random() * ( this.maxCustPerHour - this.minCustPerHour + 1) + this.minCustPerHour);
//       this.randomCustPerHour.push(Math.floor(Math.random() *( this.maxCustPerHour - this.minCustPerHour + 1 )) + this.minCustPerHour );
//       // console.log(this.randomCustPerHour);
//     }
//   },
//
//
//   calcTotalCookiesSoldEachHour: function() {
//     //callcalcrandomcustperhour()
//     this.calcRandomCustPerHour();
//     for (var i = 0; i < hours.length ; i++){
//       this.totalCookiesSoldEachHour.push(Math.ceil(this.randomCustPerHour[i] * this.avgCookiesperCust));
//       // this.totalCookies += this.cookiesSoldEachHour[i];
//       this.totalDailyCookiesSales += this.totalCookiesSoldEachHour[i];
//       // console.log(this.totalDailycookiesales, 'running total of daily cookie sales');
//     }
//     // console.log(this.cookiesSoldEachHour[i]), ' random numbers of cookies sold each hour';
//   },
//   render: function(){
//     this.calcTotalCookiesSoldEachHour();
//     var emptyUl = document.getElementById('seaCenter');
//     for (var i = 0; i < hours.length ; i++){
//       var liEl = document.createElement('li');
//       liEl.textContent = hours[i] + ': ' + this.totalCookiesSoldEachHour[i] + ' cookies';
//       emptyUl.appendChild (liEl);
//     }
//     liEl = document.createElement('li');
//     liEl.textContent = 'total: ' + this.totalDailyCookiesSales + ' cookies ';
//     emptyUl.appendChild (liEl);
//   }
// }
//
// seattleCenter.render();
//
// //capitol Hill
// var capitolHill = {
//   locationName: 'capitolHill',
//   minCustPerHour: 3,
//   maxCustPerHour: 24,
//   avgCookiesperCust: 63.7,
//   randomCustPerHour: [],
//   totalCookiesSoldEachHour: [],
//   totalDailyCookiesSales: 0,
//   calcRandomCustPerHour: function() {
//     for (var i = 0; i < hours.length ; i++){
//       // this.randomCustPerHour[i] = Math.floor(Math.random() * ( this.maxCustPerHour - this.minCustPerHour + 1) + this.minCustPerHour);
//       this.randomCustPerHour.push(Math.floor(Math.random() *( this.maxCustPerHour - this.minCustPerHour + 1 )) + this.minCustPerHour );
//       // console.log(this.randomCustPerHour);
//     }
//   },
//
//
//   calcTotalCookiesSoldEachHour: function() {
//     //callcalcrandomcustperhour()
//     this.calcRandomCustPerHour();
//     for (var i = 0; i < hours.length ; i++){
//       this.totalCookiesSoldEachHour.push(Math.ceil(this.randomCustPerHour[i] * this.avgCookiesperCust));
//       // this.totalCookies += this.cookiesSoldEachHour[i];
//       this.totalDailyCookiesSales += this.totalCookiesSoldEachHour[i];
//       // console.log(this.totalDailycookiesales, 'running total of daily cookie sales');
//     }
//     // console.log(this.cookiesSoldEachHour[i]), ' random numbers of cookies sold each hour';
//   },
//   render: function(){
//     this.calcTotalCookiesSoldEachHour();
//     var emptyUl = document.getElementById('capitolHill');
//     for (var i = 0; i < hours.length ; i++){
//       var liEl = document.createElement('li');
//       liEl.textContent = hours[i] + ': ' + this.totalCookiesSoldEachHour[i] + ' cookies';
//       emptyUl.appendChild (liEl);
//     }
//     liEl = document.createElement('li');
//     liEl.textContent = 'total: ' + this.totalDailyCookiesSales + ' cookies ';
//     emptyUl.appendChild (liEl);
//   }
// }
//
// capitolHill.render();
//
// //alki
// var alki = {
//   locationName: 'alki',
//   minCustPerHour: 3,
//   maxCustPerHour: 24,
//   avgCookiesperCust: 63.7,
//   randomCustPerHour: [],
//   totalCookiesSoldEachHour: [],
//   totalDailyCookiesSales: 0,
//   calcRandomCustPerHour: function() {
//     for (var i = 0; i < hours.length ; i++){
//       // this.randomCustPerHour[i] = Math.floor(Math.random() * ( this.maxCustPerHour - this.minCustPerHour + 1) + this.minCustPerHour);
//       this.randomCustPerHour.push(Math.floor(Math.random() *( this.maxCustPerHour - this.minCustPerHour + 1 )) + this.minCustPerHour );
//       // console.log(this.randomCustPerHour);
//     }
//   },
//
//
//   calcTotalCookiesSoldEachHour: function() {
//     //callcalcrandomcustperhour()
//     this.calcRandomCustPerHour();
//     for (var i = 0; i < hours.length ; i++){
//       this.totalCookiesSoldEachHour.push(Math.ceil(this.randomCustPerHour[i] * this.avgCookiesperCust));
//       // this.totalCookies += this.cookiesSoldEachHour[i];
//       this.totalDailyCookiesSales += this.totalCookiesSoldEachHour[i];
//       // console.log(this.totalDailycookiesales, 'running total of daily cookie sales');
//     }
//     // console.log(this.cookiesSoldEachHour[i]), ' random numbers of cookies sold each hour';
//   },
//   render: function(){
//     this.calcTotalCookiesSoldEachHour();
//     var emptyUl = document.getElementById('alki');
//     for (var i = 0; i < hours.length ; i++){
//       var liEl = document.createElement('li');
//       liEl.textContent = hours[i] + ': ' + this.totalCookiesSoldEachHour[i] + ' cookies';
//       emptyUl.appendChild (liEl);
//     }
//     liEl = document.createElement('li');
//     liEl.textContent = 'total: ' + this.totalDailyCookiesSales + ' cookies ';
//     emptyUl.appendChild (liEl);
//   }
// }
//
// alki.render();
<|endoftext|>


<commit_before>var connectors = require('./connectors');
var config = require('./config');
var async = require('async');

var debug = false;
var makeAndCancelOffers = true;

async.forever(function(cb) {
    console.log('-----------------------------------');
    console.log(new Date());
    console.log('-----------------------------------');
    console.log();
    async.forEachOfSeries(config.exchanges, function(exchange, exchangeName, cb) {
	async.forEachOfSeries(exchange.currencies, function(settings, currency, cb) {
	    if (settings.active) {
		var handle;
		if (exchangeName === 'bitfinex') {
		    handle = new connectors.bitfinex(config.exchanges.bitfinex.credentials);
		}
		else if (exchangeName === 'poloniex') {
		    handle = new connectors.poloniex(config.exchanges.poloniex.credentials);
		}
		if (handle) {
		    manage(exchangeName, handle, currency, settings, cb);
		}
		else {
		    cb({message: 'exchange '+exchangeName+' not found'});
		}
	    }
	    else {
		cb();
	    }
	},
	function(err) {
	    cb(err);
	});
    },
    function(err) {
	if (err) {
	    console.log(err);
	}
	console.log('done');
	console.log();
	setTimeout(function() {
	    cb();
	}, config.loopDelayInMinutes * 60 * 1000);
    });
}, function(err) {
    console.log(err);
});

function manage(exchangeName, handle, currency, settings, cb) {
    console.log(exchangeName, currency);

    var data = {};
    async.series([function(cb) {
	// 1. get this exchange's usd rate for this currency
	if (currency.toLowerCase() !== 'usd') {
	  handle.lastUSDPrice(currency, function(err, usdPrice) {
	      data.usdPrice = usdPrice;
	      setTimeout(function() {
		  cb(err);
	      }, config.msDelayBetweenAPICalls);
	  });
	}
	else {
	    data.usdPrice = 1;
	    cb();
	}
    },
    function(cb) {
	// 2. get active loans
	handle.activeLoans(currency, function(err, activeLoans) {
	    data.activeLoans = activeLoans;
	    setTimeout(function() {
		cb(err);
	    }, config.msDelayBetweenAPICalls);
	});
    },
    function(cb) {
	// 3. show active loans (with USD value)
	console.log('  active loans');
	data.loanTotal = 0;
	data.rateTotal = 0;
	async.eachSeries(data.activeLoans, function(loan, cb) {
	    console.log('   ', loan.amount.toFixed(8), loan.currency, '($'+(loan.amount * data.usdPrice).toFixed(2)+') at',
			loan.rate.toFixed(2)+'%', loan.createDate, 'for', loan.duration, 'days');
	    data.loanTotal += loan.amount;
	    data.rateTotal += loan.rate * loan.amount;
	    cb();
        },
        function(err) {
	    if (data.loanTotal > 0) {
		console.log();
		console.log('    total:', data.loanTotal.toFixed(8), currency, '($'+(data.loanTotal * data.usdPrice).toFixed(2)+')',
			    'at', (data.rateTotal / data.loanTotal).toFixed(2)+'%');
	    }
	    console.log();
	    cb();
	});
    },
    function(cb) {
	// 4. get order book
	handle.lendbook(currency, function(err, lendbook) {
            data.lendbook = lendbook;
            setTimeout(function() {
                cb(err);
            }, config.msDelayBetweenAPICalls);
        });
    },
    function(cb) {
	// 5. find desired rate
	if (data.lendbook.offers.length > 0) {
	    data.lendbook.offerTotal = 0;
	    for (var x in data.lendbook.offers) {
		var offer = data.lendbook.offers[x];
		data.lendbook.offerTotal += offer.amount;
	    }
	    var target = data.lendbook.offerTotal * (settings.lendbookPositioningPercentage / 100);
	    var runningTotal = 0;
	    for (var x in data.lendbook.offers) {
		var offer = data.lendbook.offers[x];
		runningTotal += offer.amount;
		if (runningTotal < target) {
		    data.targetRate = offer.rate;
		}
	    }
	    console.log('  target rate:', data.targetRate.toFixed(2)+'%');
	    console.log();
	    cb();
	}
	else {
	    cb({message: 'no offers in lendbook'});
	}
    },
    function(cb) {
	// 6. get open (unfilled) loan offers
	handle.openLoanOffers(currency, function(err, loanOffers) {
            data.loanOffers = loanOffers;
            setTimeout(function() {
                cb(err);
            }, config.msDelayBetweenAPICalls);
        });
    },
    function(cb) {
	// 7. show open (unfilled) loan offers
	console.log('  open loan offers');
	for (var x in data.loanOffers) {
	    var offer = data.loanOffers[x];
	    console.log('   ', offer.amount.toFixed(8), offer.currency, '($'+(offer.amount * data.usdPrice).toFixed(2)+') at',
                        offer.rate.toFixed(2)+'%', offer.createDate, 'for', offer.duration, 'days');
	}
	cb();
    },
    function(cb) {
	// 8. cancel open offers outside of desired rate bounds
	var first = true;
	async.eachSeries(data.loanOffers, function(offer, cb) {
	    if (data.targetRate > settings.minimumRate && offer.rate > data.targetRate * (1 + (settings.driftPercent / 100))) {
		if (first) {
		    console.log();
		    first = false;
		}
		console.log('    cancelling', offer.amount.toFixed(8), offer.currency, '($'+(offer.amount * data.usdPrice).toFixed(2)+') at',
                            offer.rate.toFixed(2)+'%', offer.createDate, 'for', offer.duration, 'days');
		if (makeAndCancelOffers) {
		    handle.cancelLoanOffer(offer.id, function(err, res) {
			if (debug) {
			    console.log(res);
			}
			setTimeout(function() {
			    cb(err);
			}, config.msDelayBetweenAPICalls);
		    });
		}
		else {
		    cb();
		}
	    }
	    else {
		cb();
	    }
	},
	function(err) {
	    console.log();
	    cb(err)
	});
    },
    function(cb) {
	// 9. get available balance for this currency
	handle.availableBalance(currency, function(err, availableBalance) {
            data.availableBalance = availableBalance;
	    console.log('  available balance:', data.availableBalance, currency, '($'+(data.availableBalance * data.usdPrice).toFixed(2)+')');
	    console.log();
            setTimeout(function() {
                cb(err);
            }, config.msDelayBetweenAPICalls);
        });
    },
    function(cb) {
	// 10. optionally create offer
	if (data.availableBalance * data.usdPrice > settings.minimumSizeUSD && data.targetRate > settings.minimumRate) {
	    var amount = data.availableBalance;
	    var duration = 2;
	    if (amount * data.usdPrice > settings.maximumSizeUSD) {
		amount = Number((settings.maximumSizeUSD / data.usdPrice).toFixed(4));
	    }
	    if (data.targetRate > 30) {
		duration = 10;
	    }
	    if (data.targetRate > 40) {
		duration = 30;
	    }
	    if (exchangeName === 'poloniex' && data.targetRate > 50) {
		duration = 60;
	    }
	    console.log('  creating offer for', amount, currency, '($'+(amount * data.usdPrice).toFixed(2)+') at',
			data.targetRate.toFixed(2)+'% for', duration, 'days');
	    if (makeAndCancelOffers) {
		handle.createLoanOffer(currency, amount, Number(data.targetRate.toFixed(2)), duration, function(err, res) {
		    if (debug) {
			console.log(res);
		    }
		    setTimeout(function() {
			cb(err);
		    }, config.msDelayBetweenAPICalls);
		});
	    }
	    else {
		cb();
	    }
	}
	else {
	    console.log('  not creating a new offer');
	    cb();
	}
    }],
    function(err) {
	console.log();
	cb(err);
    });
}
<commit_msg>app.js: make sure data.targetRate is never null<commit_after>var connectors = require('./connectors');
var config = require('./config');
var async = require('async');

var debug = false;
var makeAndCancelOffers = true;

async.forever(function(cb) {
    console.log('-----------------------------------');
    console.log(new Date());
    console.log('-----------------------------------');
    console.log();
    async.forEachOfSeries(config.exchanges, function(exchange, exchangeName, cb) {
	async.forEachOfSeries(exchange.currencies, function(settings, currency, cb) {
	    if (settings.active) {
		var handle;
		if (exchangeName === 'bitfinex') {
		    handle = new connectors.bitfinex(config.exchanges.bitfinex.credentials);
		}
		else if (exchangeName === 'poloniex') {
		    handle = new connectors.poloniex(config.exchanges.poloniex.credentials);
		}
		if (handle) {
		    manage(exchangeName, handle, currency, settings, cb);
		}
		else {
		    cb({message: 'exchange '+exchangeName+' not found'});
		}
	    }
	    else {
		cb();
	    }
	},
	function(err) {
	    cb(err);
	});
    },
    function(err) {
	if (err) {
	    console.log(err);
	}
	console.log('done');
	console.log();
	setTimeout(function() {
	    cb();
	}, config.loopDelayInMinutes * 60 * 1000);
    });
}, function(err) {
    console.log(err);
});

function manage(exchangeName, handle, currency, settings, cb) {
    console.log(exchangeName, currency);

    var data = {};
    async.series([function(cb) {
	// 1. get this exchange's usd rate for this currency
	if (currency.toLowerCase() !== 'usd') {
	  handle.lastUSDPrice(currency, function(err, usdPrice) {
	      data.usdPrice = usdPrice;
	      setTimeout(function() {
		  cb(err);
	      }, config.msDelayBetweenAPICalls);
	  });
	}
	else {
	    data.usdPrice = 1;
	    cb();
	}
    },
    function(cb) {
	// 2. get active loans
	handle.activeLoans(currency, function(err, activeLoans) {
	    data.activeLoans = activeLoans;
	    setTimeout(function() {
		cb(err);
	    }, config.msDelayBetweenAPICalls);
	});
    },
    function(cb) {
	// 3. show active loans (with USD value)
	console.log('  active loans');
	data.loanTotal = 0;
	data.rateTotal = 0;
	async.eachSeries(data.activeLoans, function(loan, cb) {
	    console.log('   ', loan.amount.toFixed(8), loan.currency, '($'+(loan.amount * data.usdPrice).toFixed(2)+') at',
			loan.rate.toFixed(2)+'%', loan.createDate, 'for', loan.duration, 'days');
	    data.loanTotal += loan.amount;
	    data.rateTotal += loan.rate * loan.amount;
	    cb();
        },
        function(err) {
	    if (data.loanTotal > 0) {
		console.log();
		console.log('    total:', data.loanTotal.toFixed(8), currency, '($'+(data.loanTotal * data.usdPrice).toFixed(2)+')',
			    'at', (data.rateTotal / data.loanTotal).toFixed(2)+'%');
	    }
	    console.log();
	    cb();
	});
    },
    function(cb) {
	// 4. get order book
	handle.lendbook(currency, function(err, lendbook) {
            data.lendbook = lendbook;
            setTimeout(function() {
                cb(err);
            }, config.msDelayBetweenAPICalls);
        });
    },
    function(cb) {
	// 5. find desired rate
	if (data.lendbook.offers.length > 0) {
	    data.lendbook.offerTotal = 0;
	    for (var x in data.lendbook.offers) {
		data.lendbook.offerTotal += data.lendbook.offers[x].amount;
	    }
	    var target = data.lendbook.offerTotal * (settings.lendbookPositioningPercentage / 100);
	    var runningTotal = 0;
	    data.targetRate = data.lendbook.offers[0].rate;
	    for (var x in data.lendbook.offers) {
		var offer = data.lendbook.offers[x];
		runningTotal += offer.amount;
		if (runningTotal <= target) {
		    data.targetRate = offer.rate;
		}
	    }
	    console.log('  target rate:', data.targetRate.toFixed(2)+'%');
	    console.log();
	    cb();
	}
	else {
	    cb({message: 'no offers in lendbook'});
	}
    },
    function(cb) {
	// 6. get open (unfilled) loan offers
	handle.openLoanOffers(currency, function(err, loanOffers) {
            data.loanOffers = loanOffers;
            setTimeout(function() {
                cb(err);
            }, config.msDelayBetweenAPICalls);
        });
    },
    function(cb) {
	// 7. show open (unfilled) loan offers
	console.log('  open loan offers');
	for (var x in data.loanOffers) {
	    var offer = data.loanOffers[x];
	    console.log('   ', offer.amount.toFixed(8), offer.currency, '($'+(offer.amount * data.usdPrice).toFixed(2)+') at',
                        offer.rate.toFixed(2)+'%', offer.createDate, 'for', offer.duration, 'days');
	}
	cb();
    },
    function(cb) {
	// 8. cancel open offers outside of desired rate bounds
	var first = true;
	async.eachSeries(data.loanOffers, function(offer, cb) {
	    if (data.targetRate > settings.minimumRate && offer.rate > data.targetRate * (1 + (settings.driftPercent / 100))) {
		if (first) {
		    console.log();
		    first = false;
		}
		console.log('    cancelling', offer.amount.toFixed(8), offer.currency, '($'+(offer.amount * data.usdPrice).toFixed(2)+') at',
                            offer.rate.toFixed(2)+'%', offer.createDate, 'for', offer.duration, 'days');
		if (makeAndCancelOffers) {
		    handle.cancelLoanOffer(offer.id, function(err, res) {
			if (debug) {
			    console.log(res);
			}
			setTimeout(function() {
			    cb(err);
			}, config.msDelayBetweenAPICalls);
		    });
		}
		else {
		    cb();
		}
	    }
	    else {
		cb();
	    }
	},
	function(err) {
	    console.log();
	    cb(err)
	});
    },
    function(cb) {
	// 9. get available balance for this currency
	handle.availableBalance(currency, function(err, availableBalance) {
            data.availableBalance = availableBalance;
	    console.log('  available balance:', data.availableBalance, currency, '($'+(data.availableBalance * data.usdPrice).toFixed(2)+')');
	    console.log();
            setTimeout(function() {
                cb(err);
            }, config.msDelayBetweenAPICalls);
        });
    },
    function(cb) {
	// 10. optionally create offer
	if (data.availableBalance * data.usdPrice > settings.minimumSizeUSD && data.targetRate > settings.minimumRate) {
	    var amount = data.availableBalance;
	    var duration = 2;
	    if (amount * data.usdPrice > settings.maximumSizeUSD) {
		amount = Number((settings.maximumSizeUSD / data.usdPrice).toFixed(4));
	    }
	    if (data.targetRate > 25) {
		duration = 10;
	    }
	    if (data.targetRate > 30) {
		duration = 30;
	    }
	    if (exchangeName === 'poloniex' && data.targetRate > 35) {
		duration = 60;
	    }
	    console.log('  creating offer for', amount, currency, '($'+(amount * data.usdPrice).toFixed(2)+') at',
			data.targetRate.toFixed(2)+'% for', duration, 'days');
	    if (makeAndCancelOffers) {
		handle.createLoanOffer(currency, amount, Number(data.targetRate.toFixed(2)), duration, function(err, res) {
		    if (debug) {
			console.log(res);
		    }
		    setTimeout(function() {
			cb(err);
		    }, config.msDelayBetweenAPICalls);
		});
	    }
	    else {
		cb();
	    }
	}
	else {
	    console.log('  not creating a new offer');
	    cb();
	}
    }],
    function(err) {
	console.log();
	cb(err);
    });
}
<|endoftext|>


<commit_before>const path = require('path');
const cpFile = require('cp-file');
const chalk = require('chalk');

const files = [
  '.github/ISSUE_TEMPLATE.md',
  '.github/PULL_REQUEST_TEMPLATE.md',
];

module.exports = () => {
  files.forEach((file) => {
    console.log(chalk.green(`Copy ${file}`)); // eslint-disable-line no-console
    cpFile(path.resolve(__dirname, '..', file), file);
  });
};
<commit_msg>fix(templates): use sync version of cp-file<commit_after>const path = require('path');
const cpFile = require('cp-file');
const chalk = require('chalk');

const files = [
  '.github/ISSUE_TEMPLATE.md',
  '.github/PULL_REQUEST_TEMPLATE.md',
];

module.exports = () => {
  files.forEach((file) => {
    console.log(chalk.green(`Copy ${file}`)); // eslint-disable-line no-console
    cpFile.sync(path.resolve(__dirname, '..', file), file);
  });
};
<|endoftext|>


<commit_before> // deprecating, replacing with serverless mode
var RUNNING_LOCAL = (document.location.host == 'localhost' || document.location.host == '127.0.0.1' || document.location.protocol == 'file:');
var API_URL = RUNNING_LOCAL ? 'http://0.0.0.0:5000/' : 'https://opentaba-server.herokuapp.com/';
var ADDR_DB_API_URL = RUNNING_LOCAL ? 'http://0.0.0.0:5000/' : 'https://opentaba-address-db.herokuapp.com/';

var gushimLayer;
leafletPip.bassackwards = true;

var CITY_NAME = "ירושלים"; //TODO: replace this with something more scalable.

var MAP_CENTER = [31.765, 35.17];
var DEFAULT_ZOOM = 13;

// var API_URL = '/'; // serverless, bitches! just store the JSON in the directory and grab it from there.

var highlit = [];

// Utility endsWith function
String.prototype.endsWith = function(suffix) {
    return this.indexOf(suffix, this.length - suffix.length) !== -1;
};

function show_data(url){
	if (url.indexOf('.pdf', url.length - 4) !== -1) { // endsWith('.pdf')?
		new PDFObject({ url: url }).embed("modal-doc");
	} else {
		$("#modal-doc").html('');
	}

	$("#doc_new_window").attr("href", url);
	$("#docModal").modal().css({ width: '90%', height: '80%', 'margin-left': function () { return -($(this).width() / 2); } });
}

function render_plans(plans, gid) {
	//TODO: rewrite this DRY
	var out = '
גוש ' + gid + '
';

	// html brought to you courtsey of 1998
	out += "
";
	for (var i = 0 ; i<plans.length ; i++) {
		var p = plans[i];

		//plan_link = 'http://www.mmi.gov.il/IturTabot/taba2.asp?Gush=' + p.gush_id + '&MisTochnit=' + escape(p.number)
		plan_link = 'http://mmi.gov.il/IturTabot/taba4.asp?kod=3000&MsTochnit=' + escape(p.number);

		out+='
' +
			 '	' + [p.day, p.month, p.year].join('/') + '	' +
			 '	' + p.status  + '	'+
			 '	' + p.essence + '	'+
			 '
' +
			 '
' +
			 '	' +
			 '		'+
			 '		תוכנית ' + p.number + '' +
			 '		' +
			 '	';
		var j;
		for (j=0 ; j<p.tasrit_link.length ; j++)
			out += '';

		for (j=0 ; j<p.takanon_link.length ; j++)
			out += '';

		for (j=0 ; j<p.nispahim_link.length ; j++)
			out += '';

		for (j=0 ; j<p.files_link.length ; j++)
			out += '';

		out+='		'  +
			 '
' 	+
			 '

';
	}
	out += '
';

	$("#info").html(out);

	// activate Boostrap tooltips on attachment icons
	$("[rel='tooltip']").tooltip({'placement' : 'bottom'});

	$(".item").hover(
			function () { $(this).css("background","#fff"); $(this).next(".details").css("background","#fff"); }, //#f7f7f9
			function () { $(this).css("background","")	  ; $(this).next(".details").css("background",""); }
	);

	$(".details").hover(
			function () { $(this).css("background","#fff"); $(this).prev(".item").css("background","#fff"); },
			function () { $(this).css("background","")	  ; $(this).prev(".item").css("background",""); }
	);

}

function get_gush(gush_id) {
	// console.log("get_gush: " + API_URL + 'gush/' + gush_id + '/plans')
	clear_all_highlit();
	highlight_gush(gush_id);
	location.hash = "#/gush/" + gush_id;

	$.getJSON(
		API_URL + 'gush/' + gush_id + '/plans',
		function(d) {
			//console.log(d.length);
			render_plans(d, gush_id);
		}
		);

	console.log('waiting for json');

}

// find a rendered gush based on ID
function find_gush(gush_id){
	g = gushim.features.filter(
		function(f){ return (f.properties.Name == gush_id); }
	);
	return g[0];
}

// get a gush by street address
function get_gush_by_addr(addr) {
	if (!addr.endsWith(" " + CITY_NAME)) { //TODO: change to regex with cityname
		addr = addr + " " + CITY_NAME;
	}

	console.log("get_gush_by_addr: " + addr);

	// Use Google api to find a gush by address
	$.getJSON(
		'https://maps.googleapis.com/maps/api/geocode/json?address='+addr+'&sensor=false',
		function (r) {
			$('#scrobber').hide();
			$('#addr-error-p').html('');

			if (r['status'] == 'OK' && r['results'].length > 0) {
				// Here we have a case when Google api returns without an actual place (even a street),
				// so it only has a city. This happens because it didn't find the address, but we
				// did append the name of the current city at the end, and Google apparently thinks
				// 'better something than nothing'. We're trying to ignore this (should test though)
				if (r['results'][0]['types'].length == 2 &&
					$.inArray('locality', r['results'][0]['types']) > -1 &&
					$.inArray('political', r['results'][0]['types']) > -1) {
					$('#addr-error-p').html('כתובת שגויה או שלא נמצאו נתונים');
				}
				else {
					var lat = r['results'][0]['geometry']['location']['lat'];
					var lon = r['results'][0]['geometry']['location']['lng'];
					console.log('got lon: ' + lon + ', lat: ' + lat);

					// Using leafletpip we try to find an object in the gushim layer with the coordinate we got
					var gid = leafletPip.pointInLayer([lat, lon], gushimLayer, true);
					if (gid && gid.length > 0) {
						get_gush(gid[0].gushid);
						var pp = L.popup().setLatLng([lat, lon]).setContent('' + addr + '').openOn(map);
					} else {
						$('#addr-error-p').html('לא נמצא גוש התואם לכתובת'); // TODO: when enabling multiple cities change the message to point users to try a differenct city
					}
				}
			}
			else if (r['status'] == 'ZERO_RESULTS') {
				$('#addr-error-p').html('כתובת שגויה או שלא נמצאו נתונים');
			}
			else {
				$('#addr-error-p').html('חלה שגיאה בחיפוש הכתובת, אנא נסו שנית מאוחר יותר');
			}
		}
	)
   .fail(
   		function(){
   			$('#scrobber').hide();
   			$('#addr-error-p').html('חלה שגיאה בחיפוש הכתובת, אנא נסו שנית מאוחר יותר');
   		}
   	);
}

function highlight_gush(id) {
	gush = 'gush_' + id;
	console.log("highlight_gush ", gush);
	map.fitBounds(map._layers[gush].getBounds());
	map._layers[gush].setStyle({opacity: 0 	, color: "blue"});
	highlit.push(id);
}

function clear_highlight(id) {
	gush = 'gush_' + id;
	map._layers[gush].setStyle({opacity: 0.05 , color: "#777"});
	highlit.splice(highlit.indexOf(id), 1);
}

function clear_all_highlit() {
	while (highlit.length > 0) {
		clear_highlight(highlit[0]);
	}
}

function onEachFeature(feature, layer) {
	// layer.bindPopup(feature.properties.Name + " גוש ");
	layer.on({
				'mouseover'	: function() { if (highlit.indexOf(this["gushid"]) < 0) { this.setStyle({ opacity: 0 	, color: "red" 	}) } } ,
				'mouseout'	: function() { if (highlit.indexOf(this["gushid"]) < 0) { this.setStyle({ opacity: 0.95, color: "#777" }) } },
				'click'		: function() {
					$("#info").html("עוד מעט...");
					location.hash = "#/gush/" + feature.properties.Name;
					get_gush(feature.properties.Name);
				}
			});
	layer["gushid"] = feature.properties.Name;
	layer._leaflet_id = 'gush_' + feature.properties.Name;
}

// jQuery startup funcs
$(document).ready(function(){

	// comment out for serverless
	// wake up possibly-idling heroku dyno to make sure later requests aren't too slow
	$.getJSON( API_URL + "wakeup" , function(){
		// do nothing
	});

	// setup a path.js router to allow distinct URLs for each block
	Path.map("#/gush/:gush_id").to(
		function(){
			$("#docModal").modal('hide');
			get_gush(this.params['gush_id'].split('?')[0]);  // remove '?params' if exists
		}
	);

	Path.map("").to(
		function(){
			$("#docModal").modal('hide');
			$("#info").html("");
			clear_all_highlit();
			map.setView(MAP_CENTER, DEFAULT_ZOOM);
		}
	);

	Path.listen();

	$('#addr-form').submit(
		function() {
			var addr = $('#addr-text').val();
			console.log('Getting gush for address "' + addr + '"');
			$('#scrobber').show();
			get_gush_by_addr(addr);
			return false;
		}
	);
});

var map = L.map('map', { scrollWheelZoom: true }).setView(MAP_CENTER, DEFAULT_ZOOM);

tile_url = 'http://{s}.tile.cloudmade.com/BC9A493B41014CAABB98F0471D759707/997/256/{z}/{x}/{y}.png';
L.tileLayer(tile_url, {
	maxZoom: 16,
	minZoom: 13
}).addTo(map);

gushimLayer = L.geoJson(gushim,
	{
		onEachFeature: onEachFeature,
		style : {
			"color" : "#777",
			"weight": 1,
			"opacity": 0.9
		}
	}
).addTo(map);
<commit_msg>Adding .json suffix to gush plans URL to support new opentaba-server API<commit_after> // deprecating, replacing with serverless mode
var RUNNING_LOCAL = (document.location.host == 'localhost' || document.location.host == '127.0.0.1' || document.location.protocol == 'file:');
var API_URL = RUNNING_LOCAL ? 'http://0.0.0.0:5000/' : 'https://opentaba-server.herokuapp.com/';
var ADDR_DB_API_URL = RUNNING_LOCAL ? 'http://0.0.0.0:5000/' : 'https://opentaba-address-db.herokuapp.com/';

var gushimLayer;
leafletPip.bassackwards = true;

var CITY_NAME = "ירושלים"; //TODO: replace this with something more scalable.

var MAP_CENTER = [31.765, 35.17];
var DEFAULT_ZOOM = 13;

// var API_URL = '/'; // serverless, bitches! just store the JSON in the directory and grab it from there.

var highlit = [];

// Utility endsWith function
String.prototype.endsWith = function(suffix) {
    return this.indexOf(suffix, this.length - suffix.length) !== -1;
};

function show_data(url){
	if (url.indexOf('.pdf', url.length - 4) !== -1) { // endsWith('.pdf')?
		new PDFObject({ url: url }).embed("modal-doc");
	} else {
		$("#modal-doc").html('');
	}

	$("#doc_new_window").attr("href", url);
	$("#docModal").modal().css({ width: '90%', height: '80%', 'margin-left': function () { return -($(this).width() / 2); } });
}

function render_plans(plans, gid) {
	//TODO: rewrite this DRY
	var out = '
גוש ' + gid + '
';

	// html brought to you courtsey of 1998
	out += "
";
	for (var i = 0 ; i<plans.length ; i++) {
		var p = plans[i];

		//plan_link = 'http://www.mmi.gov.il/IturTabot/taba2.asp?Gush=' + p.gush_id + '&MisTochnit=' + escape(p.number)
		plan_link = 'http://mmi.gov.il/IturTabot/taba4.asp?kod=3000&MsTochnit=' + escape(p.number);

		out+='
' +
			 '	' + [p.day, p.month, p.year].join('/') + '	' +
			 '	' + p.status  + '	'+
			 '	' + p.essence + '	'+
			 '
' +
			 '
' +
			 '	' +
			 '		'+
			 '		תוכנית ' + p.number + '' +
			 '		' +
			 '	';
		var j;
		for (j=0 ; j<p.tasrit_link.length ; j++)
			out += '';

		for (j=0 ; j<p.takanon_link.length ; j++)
			out += '';

		for (j=0 ; j<p.nispahim_link.length ; j++)
			out += '';

		for (j=0 ; j<p.files_link.length ; j++)
			out += '';

		out+='		'  +
			 '
' 	+
			 '

';
	}
	out += '
';

	$("#info").html(out);

	// activate Boostrap tooltips on attachment icons
	$("[rel='tooltip']").tooltip({'placement' : 'bottom'});

	$(".item").hover(
			function () { $(this).css("background","#fff"); $(this).next(".details").css("background","#fff"); }, //#f7f7f9
			function () { $(this).css("background","")	  ; $(this).next(".details").css("background",""); }
	);

	$(".details").hover(
			function () { $(this).css("background","#fff"); $(this).prev(".item").css("background","#fff"); },
			function () { $(this).css("background","")	  ; $(this).prev(".item").css("background",""); }
	);

}

function get_gush(gush_id) {
	// console.log("get_gush: " + API_URL + 'gush/' + gush_id + '/plans')
	clear_all_highlit();
	highlight_gush(gush_id);
	location.hash = "#/gush/" + gush_id;

	$.getJSON(
		API_URL + 'gush/' + gush_id + '/plans.json',
		function(d) {
			//console.log(d.length);
			render_plans(d, gush_id);
		}
		);

	console.log('waiting for json');

}

// find a rendered gush based on ID
function find_gush(gush_id){
	g = gushim.features.filter(
		function(f){ return (f.properties.Name == gush_id); }
	);
	return g[0];
}

// get a gush by street address
function get_gush_by_addr(addr) {
	if (!addr.endsWith(" " + CITY_NAME)) { //TODO: change to regex with cityname
		addr = addr + " " + CITY_NAME;
	}

	console.log("get_gush_by_addr: " + addr);

	// Use Google api to find a gush by address
	$.getJSON(
		'https://maps.googleapis.com/maps/api/geocode/json?address='+addr+'&sensor=false',
		function (r) {
			$('#scrobber').hide();
			$('#addr-error-p').html('');

			if (r['status'] == 'OK' && r['results'].length > 0) {
				// Here we have a case when Google api returns without an actual place (even a street),
				// so it only has a city. This happens because it didn't find the address, but we
				// did append the name of the current city at the end, and Google apparently thinks
				// 'better something than nothing'. We're trying to ignore this (should test though)
				if (r['results'][0]['types'].length == 2 &&
					$.inArray('locality', r['results'][0]['types']) > -1 &&
					$.inArray('political', r['results'][0]['types']) > -1) {
					$('#addr-error-p').html('כתובת שגויה או שלא נמצאו נתונים');
				}
				else {
					var lat = r['results'][0]['geometry']['location']['lat'];
					var lon = r['results'][0]['geometry']['location']['lng'];
					console.log('got lon: ' + lon + ', lat: ' + lat);

					// Using leafletpip we try to find an object in the gushim layer with the coordinate we got
					var gid = leafletPip.pointInLayer([lat, lon], gushimLayer, true);
					if (gid && gid.length > 0) {
						get_gush(gid[0].gushid);
						var pp = L.popup().setLatLng([lat, lon]).setContent('' + addr + '').openOn(map);
					} else {
						$('#addr-error-p').html('לא נמצא גוש התואם לכתובת'); // TODO: when enabling multiple cities change the message to point users to try a differenct city
					}
				}
			}
			else if (r['status'] == 'ZERO_RESULTS') {
				$('#addr-error-p').html('כתובת שגויה או שלא נמצאו נתונים');
			}
			else {
				$('#addr-error-p').html('חלה שגיאה בחיפוש הכתובת, אנא נסו שנית מאוחר יותר');
			}
		}
	)
   .fail(
   		function(){
   			$('#scrobber').hide();
   			$('#addr-error-p').html('חלה שגיאה בחיפוש הכתובת, אנא נסו שנית מאוחר יותר');
   		}
   	);
}

function highlight_gush(id) {
	gush = 'gush_' + id;
	console.log("highlight_gush ", gush);
	map.fitBounds(map._layers[gush].getBounds());
	map._layers[gush].setStyle({opacity: 0 	, color: "blue"});
	highlit.push(id);
}

function clear_highlight(id) {
	gush = 'gush_' + id;
	map._layers[gush].setStyle({opacity: 0.05 , color: "#777"});
	highlit.splice(highlit.indexOf(id), 1);
}

function clear_all_highlit() {
	while (highlit.length > 0) {
		clear_highlight(highlit[0]);
	}
}

function onEachFeature(feature, layer) {
	// layer.bindPopup(feature.properties.Name + " גוש ");
	layer.on({
				'mouseover'	: function() { if (highlit.indexOf(this["gushid"]) < 0) { this.setStyle({ opacity: 0 	, color: "red" 	}) } } ,
				'mouseout'	: function() { if (highlit.indexOf(this["gushid"]) < 0) { this.setStyle({ opacity: 0.95, color: "#777" }) } },
				'click'		: function() {
					$("#info").html("עוד מעט...");
					location.hash = "#/gush/" + feature.properties.Name;
					get_gush(feature.properties.Name);
				}
			});
	layer["gushid"] = feature.properties.Name;
	layer._leaflet_id = 'gush_' + feature.properties.Name;
}

// jQuery startup funcs
$(document).ready(function(){

	// comment out for serverless
	// wake up possibly-idling heroku dyno to make sure later requests aren't too slow
	$.getJSON( API_URL + "wakeup" , function(){
		// do nothing
	});

	// setup a path.js router to allow distinct URLs for each block
	Path.map("#/gush/:gush_id").to(
		function(){
			$("#docModal").modal('hide');
			get_gush(this.params['gush_id'].split('?')[0]);  // remove '?params' if exists
		}
	);

	Path.map("").to(
		function(){
			$("#docModal").modal('hide');
			$("#info").html("");
			clear_all_highlit();
			map.setView(MAP_CENTER, DEFAULT_ZOOM);
		}
	);

	Path.listen();

	$('#addr-form').submit(
		function() {
			var addr = $('#addr-text').val();
			console.log('Getting gush for address "' + addr + '"');
			$('#scrobber').show();
			get_gush_by_addr(addr);
			return false;
		}
	);
});

var map = L.map('map', { scrollWheelZoom: true }).setView(MAP_CENTER, DEFAULT_ZOOM);

tile_url = 'http://{s}.tile.cloudmade.com/BC9A493B41014CAABB98F0471D759707/997/256/{z}/{x}/{y}.png';
L.tileLayer(tile_url, {
	maxZoom: 16,
	minZoom: 13
}).addTo(map);

gushimLayer = L.geoJson(gushim,
	{
		onEachFeature: onEachFeature,
		style : {
			"color" : "#777",
			"weight": 1,
			"opacity": 0.9
		}
	}
).addTo(map);
<|endoftext|>


<commit_before>'use strict';

var express = require('express');
var routes = require('./routes');
var http = require('http');
var path = require('path');
var sharejs = require('share');
var socketio = require('socket.io');

var app = express();

// all environments
app.set('port', process.env.PORT || 3000);
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.use(express.favicon());

if ('development' === app.get('env')) {
    app.use(express.logger('dev'));
} else {
    app.use(express.logger());
}

app.use(express.compress());
app.use(express.methodOverride());
app.use(express.bodyParser());
app.use(app.router);
app.use(express.static(path.join(__dirname, 'public')));

/* 404 like middleware. Route everything that was not answered yet to the main
 * page, except the 'channel' url used by sharejs. */
app.use(function (req, res, next) {
    var matched = req.path.match(/^\/(\w+).*$/);
    if (matched && matched[1] === 'channel') {
        next();
    } else {
        res.redirect('/');
    }
});

// development only
if ('development' === app.get('env')) {
    app.use(express.errorHandler());
}

app.get('/', routes.index);
app.get('/about', routes.about);

var server = http.createServer(app);

var sio = socketio.listen(server);
sio.enable('browser client etag');
sio.set('log level', 1);
sio.set('transports', ['xhr-polling']);
// sio.set('close timeout', 5);

/* Attach the sharjs REST and Socket.io interfaces to the server. */
var sharejsOptions = {
    db: {
        type: 'none'
    }
};

sharejs.server.attach(app, sharejsOptions);

server.listen(app.get('port'), function () {
    console.log('Express server listening on port ' + app.get('port'));
});

sio.sockets.on('connection', function (socket) {
    console.log('Websocket connection.');

    socket.on('join', function (data) {
        socket.set('documentId', data.documentId, function () {
            socket.set('userId', data.userId, function () {
                socket.join(data.documentId);
            });
        });
    });

    socket.on('selectionChange', function (data) {
        socket.get('documentId', function (err, documentId) {
            if (err) return console.log(err);
            socket.broadcast.to(documentId).emit('selectionChange', data);
        });
    });

    socket.on('requestFilename', function () {
        socket.get('documentId', function (err, documentId) {
            if (err) return console.log(err);
            socket.broadcast.to(documentId).emit('requestFilename');
        });
    });

    socket.on('notifyFilename', function (data) {
        socket.get('documentId', function (err, documentId) {
            if (err) return console.log(err);
            socket.broadcast.to(documentId).emit('notifyFilename', data);
        });
    });

    socket.on('disconnect', function () {
        socket.get('documentId', function (err, documentId) {
            if (err) return console.log(err);
            var room = sio.sockets.manager.rooms['/' + documentId];
            if (!room || (room.length === 1 && room[0] === socket.id)) {
                /* Zombie document, prune it. */
                console.log('Deleting document ' + documentId);
                app.model.delete(documentId, function (err) {
                    if (err) return console.log(err);
                    console.log('document deleted.');
                });
            } else {
                socket.get('userId', function (err, userId) {
                    if (err) return console.log(err);
                    socket.broadcast.to(documentId).emit('collaboratorDisconnect', userId);
                });
            }
        });
    });
});

<commit_msg>Replace regex by substr<commit_after>'use strict';

var express = require('express');
var routes = require('./routes');
var http = require('http');
var path = require('path');
var sharejs = require('share');
var socketio = require('socket.io');

var app = express();

// all environments
app.set('port', process.env.PORT || 3000);
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.use(express.favicon());

if ('development' === app.get('env')) {
    app.use(express.logger('dev'));
} else {
    app.use(express.logger());
}

app.use(express.compress());
app.use(express.methodOverride());
app.use(express.bodyParser());
app.use(app.router);
app.use(express.static(path.join(__dirname, 'public')));

/* 404 like middleware. Route everything that was not answered yet to the main
 * page, except the 'channel' url used by sharejs. */
app.use(function (req, res, next) {
    if (req.path.length > 7 && req.path.substr(1, 7) === 'channel') {
        next();
    } else {
        res.redirect('/');
    }
});

// development only
if ('development' === app.get('env')) {
    app.use(express.errorHandler());
}

app.get('/', routes.index);
app.get('/about', routes.about);

var server = http.createServer(app);

var sio = socketio.listen(server);
sio.enable('browser client etag');
sio.set('log level', 1);
sio.set('transports', ['xhr-polling']);
// sio.set('close timeout', 5);

/* Attach the sharjs REST and Socket.io interfaces to the server. */
var sharejsOptions = {
    db: {
        type: 'none'
    }
};

sharejs.server.attach(app, sharejsOptions);

server.listen(app.get('port'), function () {
    console.log('Express server listening on port ' + app.get('port'));
});

sio.sockets.on('connection', function (socket) {
    console.log('Websocket connection.');

    socket.on('join', function (data) {
        socket.set('documentId', data.documentId, function () {
            socket.set('userId', data.userId, function () {
                socket.join(data.documentId);
            });
        });
    });

    socket.on('selectionChange', function (data) {
        socket.get('documentId', function (err, documentId) {
            if (err) return console.log(err);
            socket.broadcast.to(documentId).emit('selectionChange', data);
        });
    });

    socket.on('requestFilename', function () {
        socket.get('documentId', function (err, documentId) {
            if (err) return console.log(err);
            socket.broadcast.to(documentId).emit('requestFilename');
        });
    });

    socket.on('notifyFilename', function (data) {
        socket.get('documentId', function (err, documentId) {
            if (err) return console.log(err);
            socket.broadcast.to(documentId).emit('notifyFilename', data);
        });
    });

    socket.on('disconnect', function () {
        socket.get('documentId', function (err, documentId) {
            if (err) return console.log(err);
            var room = sio.sockets.manager.rooms['/' + documentId];
            if (!room || (room.length === 1 && room[0] === socket.id)) {
                /* Zombie document, prune it. */
                console.log('Deleting document ' + documentId);
                app.model.delete(documentId, function (err) {
                    if (err) return console.log(err);
                    console.log('document deleted.');
                });
            } else {
                socket.get('userId', function (err, userId) {
                    if (err) return console.log(err);
                    socket.broadcast.to(documentId).emit('collaboratorDisconnect', userId);
                });
            }
        });
    });
});

<|endoftext|>


<commit_before>/*
 * grunt-webdriver
 * https://github.com/christianbromann/grunt-webdriver
 *
 * Copyright (c) 2013 Christian Bromann
 * Licensed under the MIT license.
 */

'use strict';

var buster        = require('buster'),
    webdriverjs   = require('webdriverjs'),
    startSelenium = require('../lib/startSelenium');

module.exports = function(grunt) {

    grunt.registerMultiTask('webdriver', 'Your task description goes here.', function() {

        var that = this,
            done = this.async(),
            base = process.cwd(),
            options = this.options({
                browser: 'chrome',
                logLevel: 'silent',
                capabilities: {
                    chrome: {
                        'browserName': 'chrome',
                        'chrome.binary': '/Applications/Browser/Google Chrome.app/Contents/MacOS/Google Chrome'
                    },
                    firefox: {
                        'browserName': 'firefox',
                        'firefox_binary': '/Applications/Browser/Firefox.app/Contents/MacOS/firefox'
                    },
                    opera: {
                        'browserName': 'opera',
                        'opera.binary': '/Applications/Browser/Opera.app/Contents/MacOS/Opera'
                    },
                    safari: {
                        'browserName': 'safari',
                        'safari.binary': '/Applications/Browser/Safari.app/Contents/MacOS/Safari'
                    }
                }
            }),
            capabilities = [];

        /**
         * display a warning and abort task immediately if test URL is not defined
         */
        if(this.data.url === undefined) {
            grunt.fail.fatal('the test url is not defined');
        }

        /**
         * set capabilities for webdriverjs
         */
        if(options.binary === undefined) {
            capabilities = options.capabilities[options.browser];
        } else {
            var seperator = options.browser === 'firefox' ? '_' : '.';
            capabilities['browserName'] = options.browser,
            capabilities[options.browser+seperator+'binary'] = options.binary;
        }

        /**
         * initialize webdriver
         */
        var driver = webdriverjs.remote({desiredCapabilities:capabilities,logLevel: options.logLevel});

        /**
         * specify special driver commands
         * @param  {Function} testSuite  command function
         * @return {Object}              driver object
         */
        driver.initTest = function(testSuite) {
            for(var test in testSuite) {
                this.addCommand(test, testSuite[test]);
            }
            return this;
        };

        /**
         * starts selenium standalone server if its not running
         * @param  {Function}        callback function on success
         * @param  {Function} done   grunt done function for async callbacks
         * @param  {Object}   grunt  grunt object
         * @return null
         */
        startSelenium(function() {

            /**
             * require given test files and run buster
             */
            var reporter  = buster.reporters.dots.create({ color: true }),
                runner    = buster.testRunner.create(),
                testCases = grunt.file.expand(grunt.file.expand(base + '/' + that.data.tests));

            // get tests context
            var contexts = [];
            testCases.forEach(function(testCase) {
                var context = require(testCase);

                context.setUp = function() {
                    this.timeout = 9999999;
                    driver.init().url(that.data.url);
                };

                context.driver = driver;
                contexts.push(context);
            });

            reporter.listen(runner);
            runner.runSuite(contexts).then(function(res) {
                done();
            });

        },done,grunt);

    });

};
<commit_msg>changed default path of browser binaries<commit_after>/*
 * grunt-webdriver
 * https://github.com/christianbromann/grunt-webdriver
 *
 * Copyright (c) 2013 Christian Bromann
 * Licensed under the MIT license.
 */

'use strict';

var buster        = require('buster'),
    webdriverjs   = require('webdriverjs'),
    startSelenium = require('../lib/startSelenium');

module.exports = function(grunt) {

    grunt.registerMultiTask('webdriver', 'Your task description goes here.', function() {

        var that = this,
            done = this.async(),
            base = process.cwd(),
            options = this.options({
                browser: 'chrome',
                logLevel: 'silent',
                capabilities: {
                    chrome: {
                        'browserName': 'chrome',
                        'chrome.binary': '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome'
                    },
                    firefox: {
                        'browserName': 'firefox',
                        'firefox_binary': '/Applications/Firefox.app/Contents/MacOS/firefox'
                    },
                    opera: {
                        'browserName': 'opera',
                        'opera.binary': '/Applications/Opera.app/Contents/MacOS/Opera'
                    },
                    safari: {
                        'browserName': 'safari',
                        'safari.binary': '/Applications/Safari.app/Contents/MacOS/Safari'
                    }
                }
            }),
            capabilities = [];

        /**
         * display a warning and abort task immediately if test URL is not defined
         */
        if(this.data.url === undefined) {
            grunt.fail.fatal('the test url is not defined');
        }

        /**
         * set capabilities for webdriverjs
         */
        if(options.binary === undefined) {
            capabilities = options.capabilities[options.browser];
        } else {
            var seperator = options.browser === 'firefox' ? '_' : '.';
            capabilities['browserName'] = options.browser,
            capabilities[options.browser+seperator+'binary'] = options.binary;
        }

        /**
         * initialize webdriver
         */
        var driver = webdriverjs.remote({desiredCapabilities:capabilities,logLevel: options.logLevel});

        /**
         * specify special driver commands
         * @param  {Function} testSuite  command function
         * @return {Object}              driver object
         */
        driver.initTest = function(testSuite) {
            for(var test in testSuite) {
                this.addCommand(test, testSuite[test]);
            }
            return this;
        };

        /**
         * starts selenium standalone server if its not running
         * @param  {Function}        callback function on success
         * @param  {Function} done   grunt done function for async callbacks
         * @param  {Object}   grunt  grunt object
         * @return null
         */
        startSelenium(function() {

            /**
             * require given test files and run buster
             */
            var reporter  = buster.reporters.dots.create({ color: true }),
                runner    = buster.testRunner.create(),
                testCases = grunt.file.expand(grunt.file.expand(base + '/' + that.data.tests));

            // get tests context
            var contexts = [];
            testCases.forEach(function(testCase) {
                var context = require(testCase);

                context.setUp = function() {
                    this.timeout = 9999999;
                    driver.init().url(that.data.url);
                };

                context.driver = driver;
                contexts.push(context);
            });

            reporter.listen(runner);
            runner.runSuite(contexts).then(function(res) {
                done();
            });

        },done,grunt);

    });

};
<|endoftext|>


<commit_before>var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var session = require('express-session');
var adaro = require('adaro');
var passport = require('./passport')(app);
var routes = require('./routes/index')(passport);

var app = express();

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.engine('dust', adaro.dust());
app.set('view engine', 'dust');

// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(session({secret: 'wwmsec'}));
app.use(express.static(path.join(__dirname, 'public')));

app.use('/', routes);

// catch 404 and forward to error handler
app.use(function(req, res, next) {
  var err = new Error('Not Found');
  err.status = 404;
  next(err);
});

// error handlers

// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
  app.use(function(err, req, res, next) {
    res.status(err.status || 500);
    res.render('error', {
      message: err.message,
      error: err
    });
  });
}

// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
  res.status(err.status || 500);
  res.render('error', {
    message: err.message,
    error: {}
  });
});

module.exports = app;<commit_msg>change order of import<commit_after>var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var session = require('express-session');
var adaro = require('adaro');

var app = express();

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.engine('dust', adaro.dust());
app.set('view engine', 'dust');

// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(session({secret: 'wwmsec'}));
app.use(express.static(path.join(__dirname, 'public')));
var passport = require('./passport')(app);
var routes = require('./routes/index')(passport);

app.use('/', routes);

// catch 404 and forward to error handler
app.use(function(req, res, next) {
  var err = new Error('Not Found');
  err.status = 404;
  next(err);
});

// error handlers

// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
  app.use(function(err, req, res, next) {
    res.status(err.status || 500);
    res.render('error', {
      message: err.message,
      error: err
    });
  });
}

// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
  res.status(err.status || 500);
  res.render('error', {
    message: err.message,
    error: {}
  });
});

module.exports = app;<|endoftext|>


<commit_before>'use strict'

const bs58check = require('bs58check')
const { Transaction, script, address } = require('bitcoinjs-lib')
const request = require('request')
const secp256k1 = require('secp256k1')
const { sha2, ripemd160 } = require('./hash.js')
const { BASE_URL, byte, concat } = require('./util.js')

const DEV = process.env.NODE_ENV === 'development'
const EXODUS_ADDRESS = '15ZcBgrLnjXsHGCv7iiVcxhCf9xK9xQu4B'
const MINIMUM_AMOUNT = DEV ? 60000 : 1000000 // min satoshis to send to exodus
const ATOMS_PER_BTC = 2000
const MINIMUM_OUTPUT = 1000
const INSIGHT_URL = `${BASE_URL}/insight-api`

// returns buffer
function getAddress160 (pub) {
  if (pub == null || pub.length !== 33) {
    throw Error('Invalid public key')
  }
  return ripemd160(sha2(pub))
}

// returns b58 string
function getAddress (pub) {
  let pubkeyHash = getAddress160(pub)

  let payload = concat(byte(0x00), pubkeyHash)
  return bs58check.encode(payload)
}

// -------------------
// insight-api/bitcore self-hosted

function insightRequest (method, url, data, cb) {
  return request({
    method,
    url: `${INSIGHT_URL}/${url}`,
    qs: { cors: true },
    form: data
  }, (err, res, body) => {
    if (err) return cb(err)
    if (res.statusCode !== 200) {
      return cb(Error(body || res.statusCode), body)
    }
    try {
      body = JSON.parse(body)
    } catch (err) {}
    cb(null, body)
  })
}

function insightFetchUtxos (address, cb) {
  let url = `addr/${address}/utxo`
  insightRequest('GET', url, null, (err, res) => {
    // when there are no outputs for this address,
    // blockchain API gives error 500 with this message:
    if (err && res === 'No free outputs to spend') {
      return cb(null, { utxos: [], amount: 0 })
    }
    if (err) return cb(err)
    let amount = 0
    for (let utxo of res) {
      utxo.amount = parseInt(utxo.amount * Math.pow(10, 8))
      amount += utxo.amount
    }
    cb(null, { utxos: res, amount })
  })
}

function insightWaitForPayment (address, cb) {
  let cbCalled = false
  const done = (err, res) => {
    if (cbCalled) return
    cbCalled = true
    clearInterval(interval)
    cb(err, res)
  }
  const checkForUnspent = () => {
    insightFetchUtxos(address, (err, res) => {
      if (err) return done(err)
      if (res.amount < MINIMUM_AMOUNT) return
      done(null, res)
    })
  }
  // poll once every 6 seconds
  let interval = setInterval(checkForUnspent, 6000)
  checkForUnspent()
  return interval
}

function insightPushTx (txHex, cb) {
  insightRequest('POST', 'tx/send', { rawtx: txHex }, cb)
}

// ------------------------
// network requests

function pushTx (txHex, cb) {
  insightPushTx(txHex, cb)
}

function fetchUtxos (address, cb) {
  insightFetchUtxos(address, cb)
}

function waitForPayment (address, cb) {
  return insightWaitForPayment(address, cb)
}

// ---------------------
// tx funcs

function createFinalTx (inputs, feeRate) {
  let inputAmount = 0
  for (let input of inputs) inputAmount += input.amount

  if (inputAmount < MINIMUM_AMOUNT) {
    throw Error(`Intermediate tx is smaller than minimum.
      minimum=${MINIMUM_AMOUNT}
      actual=${inputAmount}`)
  }
  if (!feeRate || feeRate < 0) {
    throw Error(`Must specify a transaction fee rate`)
  }

  let tx = new Transaction()

  // add inputs from intermediate tx
  for (let output of inputs) {
    let txhashhex = output.txid.match(/.{2}/g).reverse().join('') // Reverse the hex string
    let txid = Buffer(txhashhex, 'hex')
    tx.addInput(txid, output.vout)
  }

  // pay to exodus address, spendable by Cosmos developers
  let payToExodus = address.toOutputScript(EXODUS_ADDRESS)
  tx.addOutput(payToExodus, inputAmount)

  // OP_RETURN data output to specify user's Cosmos address
  // this output has a value of 0. we set the address
  // when we sign the transaction
  let cosmosAddressScript = script.nullDataOutput(Buffer(20).fill(0))
  tx.addOutput(cosmosAddressScript, 0)

  // deduct fee from exodus output
  let txLength = tx.byteLength() + tx.ins.length * 107 // account for input scripts
  let feeAmount = txLength * feeRate
  if (tx.outs[0].value - feeAmount < 0) {
    throw Error(`Not enough coins given to pay fee.
      tx length=${txLength}
      fee rate=${feeRate} satoshi/byte
      fee amount=${feeAmount} satoshis
      output amount=${tx.outs[0].value} satoshis`)
  }
  tx.outs[0].value -= feeAmount

  let paidAmount = inputAmount
  let atomAmount = ((tx.outs[0].value + MINIMUM_OUTPUT) * ATOMS_PER_BTC) / 1e8
  return { tx, paidAmount, feeAmount, atomAmount }
}

function signFinalTx (wallet, tx) {
  tx = tx.clone()
  let privKey = wallet.privateKeys.bitcoin
  let pubKey = wallet.publicKeys.bitcoin

  // set output script to specify user's Cosmos address
  let cosmosAddress = Buffer(wallet.addresses.cosmos.slice(2), 'hex')
  let cosmosAddressScript = script.nullDataOutput(cosmosAddress)
  tx.outs[1].script = cosmosAddressScript

  // all utxos we spend from should have used this script
  let pubKeyHash = ripemd160(sha2(pubKey))
  let scriptPubKey = script.pubKeyHashOutput(pubKeyHash)

  // sign inputs
  let sigHashType = Transaction.SIGHASH_ALL
  for (let i = 0; i < tx.ins.length; i++) {
    let input = tx.ins[i] // tx input
    let sigHash = tx.hashForSignature(i, scriptPubKey, sigHashType)
    let signature = sign(privKey, sigHash)
    signature = concat(signature, byte(sigHashType)) // append sighash type byte
    input.script = script.pubKeyHashInput(signature, pubKey)
  }

  return tx
}

function sign (privKey, sigHash) {
  let { signature } = secp256k1.sign(sigHash, privKey)
  signature = secp256k1.signatureNormalize(signature) // enforce low-S
  return secp256k1.signatureExport(signature) // convert to DER encoding
}

function fetchFeeRate (cb) {
  request({
    url: 'https://bitcoinfees.21.co/api/v1/fees/recommended',
    json: true
  }, (err, res, body) => {
    if (err || res.statusCode !== 200) {
      return cb(err || Error(res.statusCode), body)
    }
    let feeRate = body.halfHourFee
    if (feeRate < 150 || feeRate > 1000) {
      return cb(Error('Fee rate out of range'))
    }
    cb(null, body.halfHourFee)
  })
}

function fetchFundraiserStats (cb) {
  insightRequest('GET', `addr/${EXODUS_ADDRESS}/totalReceived`, null, (err, amountDonated) => {
    if (err) return cb(err)
    cb(null, {
      amountDonated,
      amountClaimed: amountDonated * ATOMS_PER_BTC / 1e8,
      txCount: 0 // TODO
    })
  })
}

module.exports = {
  getAddress160,
  getAddress,
  fetchUtxos,
  insightFetchUtxos,
  pushTx,
  insightPushTx,
  waitForPayment,
  createFinalTx,
  signFinalTx,
  fetchFeeRate,
  fetchFundraiserStats,
  MINIMUM_AMOUNT,
  MINIMUM_OUTPUT,
  ATOMS_PER_BTC
}
<commit_msg>Ensure output is not dust<commit_after>'use strict'

const bs58check = require('bs58check')
const { Transaction, script, address } = require('bitcoinjs-lib')
const request = require('request')
const secp256k1 = require('secp256k1')
const { sha2, ripemd160 } = require('./hash.js')
const { BASE_URL, byte, concat } = require('./util.js')

const DEV = process.env.NODE_ENV === 'development'
const EXODUS_ADDRESS = '15ZcBgrLnjXsHGCv7iiVcxhCf9xK9xQu4B'
const MINIMUM_AMOUNT = DEV ? 60000 : 1000000 // min satoshis to send to exodus
const ATOMS_PER_BTC = 2000
const MINIMUM_OUTPUT = 1000
const INSIGHT_URL = `${BASE_URL}/insight-api`

// returns buffer
function getAddress160 (pub) {
  if (pub == null || pub.length !== 33) {
    throw Error('Invalid public key')
  }
  return ripemd160(sha2(pub))
}

// returns b58 string
function getAddress (pub) {
  let pubkeyHash = getAddress160(pub)

  let payload = concat(byte(0x00), pubkeyHash)
  return bs58check.encode(payload)
}

// -------------------
// insight-api/bitcore self-hosted

function insightRequest (method, url, data, cb) {
  return request({
    method,
    url: `${INSIGHT_URL}/${url}`,
    qs: { cors: true },
    form: data
  }, (err, res, body) => {
    if (err) return cb(err)
    if (res.statusCode !== 200) {
      return cb(Error(body || res.statusCode), body)
    }
    try {
      body = JSON.parse(body)
    } catch (err) {}
    cb(null, body)
  })
}

function insightFetchUtxos (address, cb) {
  let url = `addr/${address}/utxo`
  insightRequest('GET', url, null, (err, res) => {
    // when there are no outputs for this address,
    // blockchain API gives error 500 with this message:
    if (err && res === 'No free outputs to spend') {
      return cb(null, { utxos: [], amount: 0 })
    }
    if (err) return cb(err)
    let amount = 0
    for (let utxo of res) {
      utxo.amount = parseInt(utxo.amount * Math.pow(10, 8))
      amount += utxo.amount
    }
    cb(null, { utxos: res, amount })
  })
}

function insightWaitForPayment (address, cb) {
  let cbCalled = false
  const done = (err, res) => {
    if (cbCalled) return
    cbCalled = true
    clearInterval(interval)
    cb(err, res)
  }
  const checkForUnspent = () => {
    insightFetchUtxos(address, (err, res) => {
      if (err) return done(err)
      if (res.amount < MINIMUM_AMOUNT) return
      done(null, res)
    })
  }
  // poll once every 6 seconds
  let interval = setInterval(checkForUnspent, 6000)
  checkForUnspent()
  return interval
}

function insightPushTx (txHex, cb) {
  insightRequest('POST', 'tx/send', { rawtx: txHex }, cb)
}

// ------------------------
// network requests

function pushTx (txHex, cb) {
  insightPushTx(txHex, cb)
}

function fetchUtxos (address, cb) {
  insightFetchUtxos(address, cb)
}

function waitForPayment (address, cb) {
  return insightWaitForPayment(address, cb)
}

// ---------------------
// tx funcs

function createFinalTx (inputs, feeRate) {
  let inputAmount = 0
  for (let input of inputs) inputAmount += input.amount

  if (inputAmount < MINIMUM_AMOUNT) {
    throw Error(`Intermediate tx is smaller than minimum.
      minimum=${MINIMUM_AMOUNT}
      actual=${inputAmount}`)
  }
  if (!feeRate || feeRate < 0) {
    throw Error(`Must specify a transaction fee rate`)
  }

  let tx = new Transaction()

  // add inputs from intermediate tx
  for (let output of inputs) {
    let txhashhex = output.txid.match(/.{2}/g).reverse().join('') // Reverse the hex string
    let txid = Buffer(txhashhex, 'hex')
    tx.addInput(txid, output.vout)
  }

  // pay to exodus address, spendable by Cosmos developers
  let payToExodus = address.toOutputScript(EXODUS_ADDRESS)
  tx.addOutput(payToExodus, inputAmount)

  // OP_RETURN data output to specify user's Cosmos address
  // this output has a value of 0. we set the address
  // when we sign the transaction
  let cosmosAddressScript = script.nullDataOutput(Buffer(20).fill(0))
  tx.addOutput(cosmosAddressScript, 0)

  // deduct fee from exodus output
  let txLength = tx.byteLength() + tx.ins.length * 107 // account for input scripts
  let feeAmount = txLength * feeRate
  if (tx.outs[0].value - feeAmount < MINIMUM_OUTPUT) {
    throw Error(`Not enough coins given to pay fee.
      tx length=${txLength}
      fee rate=${feeRate} satoshi/byte
      fee amount=${feeAmount} satoshis
      output amount=${tx.outs[0].value} satoshis`)
  }
  tx.outs[0].value -= feeAmount

  let paidAmount = inputAmount
  let atomAmount = ((tx.outs[0].value + MINIMUM_OUTPUT) * ATOMS_PER_BTC) / 1e8
  return { tx, paidAmount, feeAmount, atomAmount }
}

function signFinalTx (wallet, tx) {
  tx = tx.clone()
  let privKey = wallet.privateKeys.bitcoin
  let pubKey = wallet.publicKeys.bitcoin

  // set output script to specify user's Cosmos address
  let cosmosAddress = Buffer(wallet.addresses.cosmos.slice(2), 'hex')
  let cosmosAddressScript = script.nullDataOutput(cosmosAddress)
  tx.outs[1].script = cosmosAddressScript

  // all utxos we spend from should have used this script
  let pubKeyHash = ripemd160(sha2(pubKey))
  let scriptPubKey = script.pubKeyHashOutput(pubKeyHash)

  // sign inputs
  let sigHashType = Transaction.SIGHASH_ALL
  for (let i = 0; i < tx.ins.length; i++) {
    let input = tx.ins[i] // tx input
    let sigHash = tx.hashForSignature(i, scriptPubKey, sigHashType)
    let signature = sign(privKey, sigHash)
    signature = concat(signature, byte(sigHashType)) // append sighash type byte
    input.script = script.pubKeyHashInput(signature, pubKey)
  }

  return tx
}

function sign (privKey, sigHash) {
  let { signature } = secp256k1.sign(sigHash, privKey)
  signature = secp256k1.signatureNormalize(signature) // enforce low-S
  return secp256k1.signatureExport(signature) // convert to DER encoding
}

function fetchFeeRate (cb) {
  request({
    url: 'https://bitcoinfees.21.co/api/v1/fees/recommended',
    json: true
  }, (err, res, body) => {
    if (err || res.statusCode !== 200) {
      return cb(err || Error(res.statusCode), body)
    }
    let feeRate = body.halfHourFee
    if (feeRate < 150 || feeRate > 1000) {
      return cb(Error('Fee rate out of range'))
    }
    cb(null, body.halfHourFee)
  })
}

function fetchFundraiserStats (cb) {
  insightRequest('GET', `addr/${EXODUS_ADDRESS}/totalReceived`, null, (err, amountDonated) => {
    if (err) return cb(err)
    cb(null, {
      amountDonated,
      amountClaimed: amountDonated * ATOMS_PER_BTC / 1e8,
      txCount: 0 // TODO
    })
  })
}

module.exports = {
  getAddress160,
  getAddress,
  fetchUtxos,
  insightFetchUtxos,
  pushTx,
  insightPushTx,
  waitForPayment,
  createFinalTx,
  signFinalTx,
  fetchFeeRate,
  fetchFundraiserStats,
  MINIMUM_AMOUNT,
  MINIMUM_OUTPUT,
  ATOMS_PER_BTC
}
<|endoftext|>


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

var mongoUrl = process.env.MONGOURL || 'mongodb://localhost/epic';

mongoose.connect(mongoUrl);

var Stat = require('./Stat');

if(process.env.RUN_WITH_TRACKER)
  require('./tracker');

/**
 * Module dependencies.
 */
var express = require('express')
  , http = require('http')
  , path = require('path')
  , hbs = require('./lib/hbshelpers')
  , path = require('path');

// Express 3.0 App
var app = express();

var oneYear = 31557600000;

app.configure(function(){
  app.set('port', process.env.PORT || 8080);
  app.set('views',path.join(process.cwd(), 'views'));
  app.set('view engine', 'hbs');

  app.use(express.compress());
  app.use(express.static(path.join(process.cwd(), 'public'), { maxAge: oneYear }));
  app.use(express.favicon());
  app.use(express.logger('dev'));
  app.use(express.bodyParser());
  app.use(express.methodOverride());

  app.use(app.router);

  app.use(function(req, res, next){
    res.statusCode = 404;
    res.render('error/404');
  });

});

app.configure('development', function(){
  app.use(express.errorHandler());
});

function navBar(sel){
  var navs = [];
  Stat.Mountains.forEach(function(m){

    var obj = {
      name : m,
      val : m,
      selected : false
    };

    if(sel === m)
      obj.selected = true;

    navs.push(obj);
  });

  return navs;
}

app.get('/',function(req,res){
  res.redirect('/MtBrighton');
});

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

  if(Stat.Mountains.indexOf(req.params.mountain) == -1){
    res.statusCode = 404;
    return res.render('error/404');
  }

  res.render('show',{mountain : req.params.mountain, navBar : navBar(req.params.mountain) });
});

app.get('/:mountain/stats.json',function(req,res){

  var doy = new Date().getDOY();
  Stat.find({mountain : req.params.mountain,DoY : doy})
  .sort({date : 1})
  .exec(function(err,docs){
    if(err)
      return res.send(500);

    function mapStat(k,s){
      if(s[k] < 0)
        return [s.date.getTime(),0];
      return [s.date.getTime(),s[k]];
    }

    var obj = {
      liftStats : docs.map(mapStat.bind(this,'lifts')),
      liftDxStats : docs.map(mapStat.bind(this,'liftsDx'))
    };

    res.send(obj);
  })
});

http.createServer(app).listen(app.get('port'), function(){
  console.log("Server listening on port " + app.get('port'));
});<commit_msg>Updated mongo env name<commit_after>var mongoose  = require('mongoose');

var mongoUrl = process.env.MONGOHQ_URL || 'mongodb://localhost/epic';

mongoose.connect(mongoUrl);

var Stat = require('./Stat');

if(process.env.RUN_WITH_TRACKER)
  require('./tracker');

/**
 * Module dependencies.
 */
var express = require('express')
  , http = require('http')
  , path = require('path')
  , hbs = require('./lib/hbshelpers')
  , path = require('path');

// Express 3.0 App
var app = express();

var oneYear = 31557600000;

app.configure(function(){
  app.set('port', process.env.PORT || 8080);
  app.set('views',path.join(process.cwd(), 'views'));
  app.set('view engine', 'hbs');

  app.use(express.compress());
  app.use(express.static(path.join(process.cwd(), 'public'), { maxAge: oneYear }));
  app.use(express.favicon());
  app.use(express.logger('dev'));
  app.use(express.bodyParser());
  app.use(express.methodOverride());

  app.use(app.router);

  app.use(function(req, res, next){
    res.statusCode = 404;
    res.render('error/404');
  });

});

app.configure('development', function(){
  app.use(express.errorHandler());
});

function navBar(sel){
  var navs = [];
  Stat.Mountains.forEach(function(m){

    var obj = {
      name : m,
      val : m,
      selected : false
    };

    if(sel === m)
      obj.selected = true;

    navs.push(obj);
  });

  return navs;
}

app.get('/',function(req,res){
  res.redirect('/MtBrighton');
});

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

  if(Stat.Mountains.indexOf(req.params.mountain) == -1){
    res.statusCode = 404;
    return res.render('error/404');
  }

  res.render('show',{mountain : req.params.mountain, navBar : navBar(req.params.mountain) });
});

app.get('/:mountain/stats.json',function(req,res){

  var doy = new Date().getDOY();
  Stat.find({mountain : req.params.mountain,DoY : doy})
  .sort({date : 1})
  .exec(function(err,docs){
    if(err)
      return res.send(500);

    function mapStat(k,s){
      if(s[k] < 0)
        return [s.date.getTime(),0];
      return [s.date.getTime(),s[k]];
    }

    var obj = {
      liftStats : docs.map(mapStat.bind(this,'lifts')),
      liftDxStats : docs.map(mapStat.bind(this,'liftsDx'))
    };

    res.send(obj);
  })
});

http.createServer(app).listen(app.get('port'), function(){
  console.log("Server listening on port " + app.get('port'));
});<|endoftext|>