<commit_before>//Importar middlewares
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 partials = require('express-partials');
var methodOverride = require('method-override');
var session = require('express-session');

//Importar enrutadores
var routes = require('./routes/index');
//var users = require('./routes/users');
//Crear aplicación
var app = express();

//Instalar vistas EJS
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');

app.use(partials());

//Instalar middlewares
// uncomment after placing your favicon in /public
//app.use(favicon(__dirname + '/public/favicon.ico'));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded()); //ahora se parsea bien
app.use(cookieParser('Quiz 2015')); //ahora cifra cookie
app.use(session());
app.use(methodOverride('_method'));
app.use(express.static(path.join(__dirname, 'public')));

//Middleware para autologout
app.use(function(req,res,next) {
    if (req.session.user) {
        var date = new Date();
        var diferenciaMin = date.getMinutes() - req.session.minutes;
        var diferenciaSec = date.getSeconds() - req.session.seconds;
        //Se excede el timempo límite
        if(diferenciaSec >= 10 || diferenciaMin !==0) {
            delete req.session.user;
            res.redirect(req.session.redir.toString());
        }
        else {
            //Reinicio de contadores al hacer nueva transacción HTTP
            req.session.seconds = date.getSeconds();
            req.session.minutes = date.getMinutes();
            next();
        }
    }
    else next();
});

//Autenticación y sesión
app.use(function(req,res,next) {
    //si no existe la redireción, se inicializa a /
    if (!req.session.redir)
        req.session.redir = '/';
    //guardar path en session.redir para despues del login
    if (!req.path.match(/\/login|\/logout|\/user/))
        req.session.redir = req.path;

    //hacer visible req.session en las vistas
    res.locals.session = req.session;
    next();
});

//Instalar enrutadores y asociar rutas a sus gestores
app.use('/', routes);

// Para el resto de rutas, catch 404 y se pasa el error al 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,
            errors: []
        });
    });
}

// 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: {},
        errors: []
    });
});

//Exportar aplicación para que se pueda arrancar desde bin/www
module.exports = app;
<commit_msg>Más arreglos de fallos<commit_after>//Importar middlewares
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 partials = require('express-partials');
var methodOverride = require('method-override');
var session = require('express-session');

//Importar enrutadores
var routes = require('./routes/index');
//var users = require('./routes/users');
//Crear aplicación
var app = express();

//Instalar vistas EJS
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');

app.use(partials());

//Instalar middlewares
// uncomment after placing your favicon in /public
//app.use(favicon(__dirname + '/public/favicon.ico'));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded()); //ahora se parsea bien
app.use(cookieParser('Quiz 2015')); //ahora cifra cookie
app.use(session());
app.use(methodOverride('_method'));
app.use(express.static(path.join(__dirname, 'public')));

//Middleware para autologout
app.use(function(req,res,next) {
    if (req.session.user) {
        var date = new Date();
        var diferenciaMin = date.getMinutes() - req.session.minutes;
        //var diferenciaSec = date.getSeconds() - req.session.seconds;
        //Se excede el timempo límite
        if(diferenciaMin >= 2) {
            delete req.session.user;
            res.redirect(req.session.redir.toString());
        }
        else {
            //Reinicio de contadores al hacer nueva transacción HTTP
            req.session.seconds = date.getSeconds();
            //req.session.minutes = date.getMinutes();
            next();
        }
    }
    else next();
});

//Autenticación y sesión
app.use(function(req,res,next) {
    //si no existe la redireción, se inicializa a /
    if (!req.session.redir)
        req.session.redir = '/';
    //guardar path en session.redir para despues del login
    if (!req.path.match(/\/login|\/logout|\/user/))
        req.session.redir = req.path;

    //hacer visible req.session en las vistas
    res.locals.session = req.session;
    next();
});

//Instalar enrutadores y asociar rutas a sus gestores
app.use('/', routes);

// Para el resto de rutas, catch 404 y se pasa el error al 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,
            errors: []
        });
    });
}

// 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: {},
        errors: []
    });
});

//Exportar aplicación para que se pueda arrancar desde bin/www
module.exports = app;
<|endoftext|>


<commit_before>'use strict';

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

// First and Pike Calculation
var first = {
  storeName: 'First and Pike',
  minCustomers: 23,
  maxCustomers: 65,
  avgSale: 6.3,
  avgCustomersHour: 0,
  avgCookiesHour: 0,
  cookiesArray: [],
  totalCookies: 0,
  getAvgCustomersHour: function (){
    this.avgCustomersHour = Math.ceil(Math.random() * (this.maxCustomers - this.minCustomers + 1) + this.minCustomers);
  },
  getAvgCookiesHour: function () {
    this.avgCookiesHour = Math.ceil(this.avgCustomersHour * this.avgSale);
  },
  render: function () {
    for (var i = 0; i < hours.length; i++) {
      this.getAvgCustomersHour();
      this.getAvgCookiesHour();
      var liEl = document.createElement('li');
<<<<<<< HEAD
      liEl.textContent = hours[i] + ' ' + this.avgCookiesHour + ' cookies sold.';
=======
      liEl.textContent = days[i] + ' ' + this.avgCookiesHour + ' cookies';
>>>>>>> 4fb074186ee618c88702a202f876e6eb17f6d069
      var firstUl = document.getElementById('first');
      firstUl.appendChild(liEl);
      this.cookiesArray.push(this.avgCookiesHour);
    }
  },
  total: function () {
    this.totalCookies = this.cookiesArray.reduce(function (a,b) {
      return a + b;
    }, 0);
    var liEl = document.createElement('li');
<<<<<<< HEAD
    liEl.textContent = 'Total ' + this.totalCookies + ' cookies sold.';
=======
    liEl.textContent = 'Total ' + this.totalCookies + ' cookies';
>>>>>>> 4fb074186ee618c88702a202f876e6eb17f6d069
    var firstUl = document.getElementById('first');
    firstUl.appendChild(liEl);
  }
};

first.getAvgCustomersHour();
first.getAvgCookiesHour();
first.render();
first.total();
console.log('Average Customers per Hour ' + first.avgCustomersHour);
console.log('Average Cookies per Hour ' + first.avgCookiesHour);
console.log(first.cookiesArray);
console.log(first.totalCookies);

// Seatac Airport Calculations
var seatac = {
  storeName: 'SeaTac Airport',
  minCustomers: 3,
  maxCustomers: 24,
  avgSale: 1.2,
  avgCustomersHour: 0,
  avgCookiesHour: 0,
  cookiesArray:[],
  totalCookies: 0,
  getAvgCustomersHour: function (){
    this.avgCustomersHour = Math.ceil(Math.random() * (this.maxCustomers - this.minCustomers + 1) + this.minCustomers);
  },
  getAvgCookiesHour: function () {
    this.avgCookiesHour = Math.ceil(this.avgCustomersHour * this.avgSale);
  },
  render: function () {
    for (var i = 0; i < hours.length; i++) {
      this.getAvgCustomersHour();
      this.getAvgCookiesHour();
      var liEl = document.createElement('li');
<<<<<<< HEAD
      liEl.textContent = hours[i] + ' ' + this.avgCookiesHour + ' cookies sold.';
=======
      liEl.textContent = days[i] + ' ' + this.avgCookiesHour + ' cookies';
>>>>>>> 4fb074186ee618c88702a202f876e6eb17f6d069
      var seatacUl = document.getElementById('seatac');
      seatacUl.appendChild(liEl);
      this.cookiesArray.push(this.avgCookiesHour);
    }
  },
  total: function () {
    this.totalCookies = this.cookiesArray.reduce(function (a,b) {
      return a + b;
    }, 0);
    var liEl = document.createElement('li');
<<<<<<< HEAD
    liEl.textContent = 'Total ' + this.totalCookies + ' cookies sold.';
=======
    liEl.textContent = 'Total ' + this.totalCookies + ' cookies';
>>>>>>> 4fb074186ee618c88702a202f876e6eb17f6d069
    var seatacUl = document.getElementById('seatac');
    seatacUl.appendChild(liEl);
  }
};

seatac.getAvgCustomersHour();
seatac.getAvgCookiesHour();
seatac.render();
seatac.total();
console.log('Average Customers per Hour ' + seatac.avgCustomersHour);
console.log('Average Cookies per Hour ' + seatac.avgCookiesHour);
console.log(seatac.cookiesArray);
console.log(seatac.totalCookies);

//Seattle Center Calculations
var seacenter = {
  storeName: 'Seattle Center',
  minCustomers: 11,
  maxCustomers: 38,
  avgSale: 3.7,
  avgCustomersHour: 0,
  avgCookiesHour: 0,
  cookiesArray: [],
  totalCookies: 0,
  getAvgCustomersHour: function (){
    this.avgCustomersHour = Math.ceil(Math.random() * (this.maxCustomers - this.minCustomers + 1) + this.minCustomers);
  },
  getAvgCookiesHour: function () {
    this.avgCookiesHour = Math.ceil(this.avgCustomersHour * this.avgSale);
  },
  render: function () {
    for (var i = 0; i < hours.length; i++) {
      this.getAvgCustomersHour();
      this.getAvgCookiesHour();
      var liEl = document.createElement('li');
<<<<<<< HEAD
      liEl.textContent = hours[i] + ' ' + this.avgCookiesHour + ' cookies sold.';
=======
      liEl.textContent = days[i] + ' ' + this.avgCookiesHour + ' cookies';
>>>>>>> 4fb074186ee618c88702a202f876e6eb17f6d069
      var seacenterUl = document.getElementById('seacenter');
      seacenterUl.appendChild(liEl);
      this.cookiesArray.push(this.avgCookiesHour);
    }
  },
  total: function () {
    this.totalCookies = this.cookiesArray.reduce(function (a,b) {
      return a + b;
    }, 0);
    var liEl = document.createElement('li');
<<<<<<< HEAD
    liEl.textContent = 'Total ' + this.totalCookies + ' cookies sold.';
=======
    liEl.textContent = 'Total ' + this.totalCookies + ' cookies';
>>>>>>> 4fb074186ee618c88702a202f876e6eb17f6d069
    var seacenterUl = document.getElementById('seacenter');
    seacenterUl.appendChild(liEl);
  }
};

seacenter.getAvgCustomersHour();
seacenter.getAvgCookiesHour();
seacenter.render();
seacenter.total();
console.log('Average Customers per Hour ' + seacenter.avgCustomersHour);
console.log('Average Cookies per Hour ' + seacenter.avgCookiesHour);
console.log(seacenter.cookiesArray);
console.log(seacenter.totalCookies);

//Capitol Hill Calcultions
var caphill = {
  storeName: 'Capitol Hill',
  minCustomers: 20,
  maxCustomers: 38,
  avgSale: 2.3,
  avgCustomersHour: 0,
  avgCookiesHour: 0,
  cookiesArray: [],
  cookiesTotal: 0,
  getAvgCustomersHour: function (){
    this.avgCustomersHour = Math.ceil(Math.random() * (this.maxCustomers - this.minCustomers + 1) + this.minCustomers);
  },
  getAvgCookiesHour: function () {
    this.avgCookiesHour = Math.ceil(this.avgCustomersHour * this.avgSale);
  },
  render: function () {
    for (var i = 0; i < hours.length; i++) {
      this.getAvgCustomersHour();
      this.getAvgCookiesHour();
      var liEl = document.createElement('li');
<<<<<<< HEAD
      liEl.textContent = hours[i] + ' ' + this.avgCookiesHour + ' cookies sold.';
=======
      liEl.textContent = days[i] + ' ' + this.avgCookiesHour + ' cookies';
>>>>>>> 4fb074186ee618c88702a202f876e6eb17f6d069
      var caphillUl = document.getElementById('caphill');
      caphillUl.appendChild(liEl);
      this.cookiesArray.push(this.avgCookiesHour);
    }
  },
  total: function () {
    this.totalCookies = this.cookiesArray.reduce(function (a,b) {
      return a + b;
    }, 0);
    var liEl = document.createElement('li');
<<<<<<< HEAD
    liEl.textContent = 'Total ' + this.totalCookies + ' cookies sold.';
=======
    liEl.textContent = 'Total ' + this.totalCookies + ' cookies';
>>>>>>> 4fb074186ee618c88702a202f876e6eb17f6d069
    var caphillUl = document.getElementById('caphill');
    caphillUl.appendChild(liEl);
  }
};

caphill.getAvgCustomersHour();
caphill.getAvgCookiesHour();
caphill.render();
caphill.total();
console.log('Average Customers per Hour ' + caphill.avgCustomersHour);
console.log('Average Cookies per Hour ' + caphill.avgCookiesHour);
console.log(caphill.cookiesArray);
console.log(caphill.totalCookies);

//Alki Beach Calculations
var alki = {
  storeName: 'Alki Beach',
  minCustomers: 2,
  maxCustomers: 16,
  avgSale: 4.6,
  avgCustomersHour: 0,
  avgCookiesHourcookiesHour: 0,
  cookiesArray: [],
  cookiesTotal: 0,
  getAvgCustomersHour: function (){
    this.avgCustomersHour = Math.ceil(Math.random() * (this.maxCustomers - this.minCustomers + 1) + this.minCustomers);
  },
  getAvgCookiesHour: function () {
    this.avgCookiesHour = Math.ceil(this.avgCustomersHour * this.avgSale);
  },
  render: function () {
    for (var i = 0; i < hours.length; i++) {
      this.getAvgCustomersHour();
      this.getAvgCookiesHour();
      var liEl = document.createElement('li');
<<<<<<< HEAD
      liEl.textContent = hours[i] + ' ' + this.avgCookiesHour + ' cookies sold.';
=======
      liEl.textContent = days[i] + ' ' + this.avgCookiesHour + ' cookies';
>>>>>>> 4fb074186ee618c88702a202f876e6eb17f6d069
      var alkiUl = document.getElementById('alki');
      alkiUl.appendChild(liEl);
      this.cookiesArray.push(this.avgCookiesHour);
    }
  },
  total: function () {
    this.totalCookies = this.cookiesArray.reduce(function (a,b) {
      return a + b;
    }, 0);
    var liEl = document.createElement('li');
<<<<<<< HEAD
    liEl.textContent = 'Total ' + this.totalCookies + ' cookies sold.';
=======
    liEl.textContent = 'Total ' + this.totalCookies + ' cookies';
>>>>>>> 4fb074186ee618c88702a202f876e6eb17f6d069
    var alkiUl = document.getElementById('alki');
    alkiUl.appendChild(liEl);
  }

};

alki.getAvgCustomersHour();
alki.getAvgCookiesHour();
alki.render();
alki.total();
console.log('Average Customers per Hour ' + alki.avgCustomersHour);
console.log('Average Cookies per Hour ' + alki.avgCookiesHour);
console.log(alki.cookiesArray);
console.log(alki.totalCookies);
<commit_msg>removed wonky error messages<commit_after>'use strict';

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

// First and Pike Calculation
var first = {
  storeName: 'First and Pike',
  minCustomers: 23,
  maxCustomers: 65,
  avgSale: 6.3,
  avgCustomersHour: 0,
  avgCookiesHour: 0,
  cookiesArray: [],
  totalCookies: 0,
  getAvgCustomersHour: function (){
    this.avgCustomersHour = Math.ceil(Math.random() * (this.maxCustomers - this.minCustomers + 1) + this.minCustomers);
  },
  getAvgCookiesHour: function () {
    this.avgCookiesHour = Math.ceil(this.avgCustomersHour * this.avgSale);
  },
  render: function () {
    for (var i = 0; i < hours.length; i++) {
      this.getAvgCustomersHour();
      this.getAvgCookiesHour();
      var liEl = document.createElement('li');
      liEl.textContent = hours[i] + ' ' + this.avgCookiesHour + ' cookies sold.';
      var firstUl = document.getElementById('first');
      firstUl.appendChild(liEl);
      this.cookiesArray.push(this.avgCookiesHour);
    }
  },
  total: function () {
    this.totalCookies = this.cookiesArray.reduce(function (a,b) {
      return a + b;
    }, 0);
    var liEl = document.createElement('li');
    liEl.textContent = 'Total ' + this.totalCookies + ' cookies sold.';
    var firstUl = document.getElementById('first');
    firstUl.appendChild(liEl);
  }
};

first.getAvgCustomersHour();
first.getAvgCookiesHour();
first.render();
first.total();
console.log('Average Customers per Hour ' + first.avgCustomersHour);
console.log('Average Cookies per Hour ' + first.avgCookiesHour);
console.log(first.cookiesArray);
console.log(first.totalCookies);

// Seatac Airport Calculations
var seatac = {
  storeName: 'SeaTac Airport',
  minCustomers: 3,
  maxCustomers: 24,
  avgSale: 1.2,
  avgCustomersHour: 0,
  avgCookiesHour: 0,
  cookiesArray:[],
  totalCookies: 0,
  getAvgCustomersHour: function (){
    this.avgCustomersHour = Math.ceil(Math.random() * (this.maxCustomers - this.minCustomers + 1) + this.minCustomers);
  },
  getAvgCookiesHour: function () {
    this.avgCookiesHour = Math.ceil(this.avgCustomersHour * this.avgSale);
  },
  render: function () {
    for (var i = 0; i < hours.length; i++) {
      this.getAvgCustomersHour();
      this.getAvgCookiesHour();
      var liEl = document.createElement('li');
      liEl.textContent = hours[i] + ' ' + this.avgCookiesHour + ' cookies sold.';
      var seatacUl = document.getElementById('seatac');
      seatacUl.appendChild(liEl);
      this.cookiesArray.push(this.avgCookiesHour);
    }
  },
  total: function () {
    this.totalCookies = this.cookiesArray.reduce(function (a,b) {
      return a + b;
    }, 0);
    var liEl = document.createElement('li');
    liEl.textContent = 'Total ' + this.totalCookies + ' cookies sold.';
    var seatacUl = document.getElementById('seatac');
    seatacUl.appendChild(liEl);
  }
};

seatac.getAvgCustomersHour();
seatac.getAvgCookiesHour();
seatac.render();
seatac.total();
console.log('Average Customers per Hour ' + seatac.avgCustomersHour);
console.log('Average Cookies per Hour ' + seatac.avgCookiesHour);
console.log(seatac.cookiesArray);
console.log(seatac.totalCookies);

//Seattle Center Calculations
var seacenter = {
  storeName: 'Seattle Center',
  minCustomers: 11,
  maxCustomers: 38,
  avgSale: 3.7,
  avgCustomersHour: 0,
  avgCookiesHour: 0,
  cookiesArray: [],
  totalCookies: 0,
  getAvgCustomersHour: function (){
    this.avgCustomersHour = Math.ceil(Math.random() * (this.maxCustomers - this.minCustomers + 1) + this.minCustomers);
  },
  getAvgCookiesHour: function () {
    this.avgCookiesHour = Math.ceil(this.avgCustomersHour * this.avgSale);
  },
  render: function () {
    for (var i = 0; i < hours.length; i++) {
      this.getAvgCustomersHour();
      this.getAvgCookiesHour();
      var liEl = document.createElement('li');
      liEl.textContent = hours[i] + ' ' + this.avgCookiesHour + ' cookies sold.';
      var seacenterUl = document.getElementById('seacenter');
      seacenterUl.appendChild(liEl);
      this.cookiesArray.push(this.avgCookiesHour);
    }
  },
  total: function () {
    this.totalCookies = this.cookiesArray.reduce(function (a,b) {
      return a + b;
    }, 0);
    var liEl = document.createElement('li');
    liEl.textContent = 'Total ' + this.totalCookies + ' cookies sold.';
    var seacenterUl = document.getElementById('seacenter');
    seacenterUl.appendChild(liEl);
  }
};

seacenter.getAvgCustomersHour();
seacenter.getAvgCookiesHour();
seacenter.render();
seacenter.total();
console.log('Average Customers per Hour ' + seacenter.avgCustomersHour);
console.log('Average Cookies per Hour ' + seacenter.avgCookiesHour);
console.log(seacenter.cookiesArray);
console.log(seacenter.totalCookies);

//Capitol Hill Calcultions
var caphill = {
  storeName: 'Capitol Hill',
  minCustomers: 20,
  maxCustomers: 38,
  avgSale: 2.3,
  avgCustomersHour: 0,
  avgCookiesHour: 0,
  cookiesArray: [],
  cookiesTotal: 0,
  getAvgCustomersHour: function (){
    this.avgCustomersHour = Math.ceil(Math.random() * (this.maxCustomers - this.minCustomers + 1) + this.minCustomers);
  },
  getAvgCookiesHour: function () {
    this.avgCookiesHour = Math.ceil(this.avgCustomersHour * this.avgSale);
  },
  render: function () {
    for (var i = 0; i < hours.length; i++) {
      this.getAvgCustomersHour();
      this.getAvgCookiesHour();
      var liEl = document.createElement('li');
      liEl.textContent = hours[i] + ' ' + this.avgCookiesHour + ' cookies sold.';
      var caphillUl = document.getElementById('caphill');
      caphillUl.appendChild(liEl);
      this.cookiesArray.push(this.avgCookiesHour);
    }
  },
  total: function () {
    this.totalCookies = this.cookiesArray.reduce(function (a,b) {
      return a + b;
    }, 0);
    var liEl = document.createElement('li');
    liEl.textContent = 'Total ' + this.totalCookies + ' cookies sold.';
    var caphillUl = document.getElementById('caphill');
    caphillUl.appendChild(liEl);
  }
};

caphill.getAvgCustomersHour();
caphill.getAvgCookiesHour();
caphill.render();
caphill.total();
console.log('Average Customers per Hour ' + caphill.avgCustomersHour);
console.log('Average Cookies per Hour ' + caphill.avgCookiesHour);
console.log(caphill.cookiesArray);
console.log(caphill.totalCookies);

//Alki Beach Calculations
var alki = {
  storeName: 'Alki Beach',
  minCustomers: 2,
  maxCustomers: 16,
  avgSale: 4.6,
  avgCustomersHour: 0,
  avgCookiesHourcookiesHour: 0,
  cookiesArray: [],
  cookiesTotal: 0,
  getAvgCustomersHour: function (){
    this.avgCustomersHour = Math.ceil(Math.random() * (this.maxCustomers - this.minCustomers + 1) + this.minCustomers);
  },
  getAvgCookiesHour: function () {
    this.avgCookiesHour = Math.ceil(this.avgCustomersHour * this.avgSale);
  },
  render: function () {
    for (var i = 0; i < hours.length; i++) {
      this.getAvgCustomersHour();
      this.getAvgCookiesHour();
      var liEl = document.createElement('li');
      liEl.textContent = hours[i] + ' ' + this.avgCookiesHour + ' cookies sold.';
      var alkiUl = document.getElementById('alki');
      alkiUl.appendChild(liEl);
      this.cookiesArray.push(this.avgCookiesHour);
    }
  },
  total: function () {
    this.totalCookies = this.cookiesArray.reduce(function (a,b) {
      return a + b;
    }, 0);
    var liEl = document.createElement('li');
    liEl.textContent = 'Total ' + this.totalCookies + ' cookies sold.';
    var alkiUl = document.getElementById('alki');
    alkiUl.appendChild(liEl);
  }

};

alki.getAvgCustomersHour();
alki.getAvgCookiesHour();
alki.render();
alki.total();
console.log('Average Customers per Hour ' + alki.avgCustomersHour);
console.log('Average Cookies per Hour ' + alki.avgCookiesHour);
console.log(alki.cookiesArray);
console.log(alki.totalCookies);
<|endoftext|>


<commit_before>$(document).ready(function(){
  var divClock = document.getElementById('divClock');

  var clockFaceDivs = [];
  clockFaceDivs[0] = [200, 63.5, 10, 10, 1];
  clockFaceDivs[1] = [236.5, 100, 10, 10, 2];
  clockFaceDivs[2] = [250, 150, 10, 10, 3];
  clockFaceDivs[3] = [236.5, 200, 10, 10, 4];
  clockFaceDivs[4] = [200, 236.5, 10, 10, 5];
  clockFaceDivs[5] = [150, 250, 10, 10, 6];
  clockFaceDivs[6] = [100, 236.5, 10, 10, 7];
  clockFaceDivs[7] = [63.5, 200, 10, 10, 8];
  clockFaceDivs[8] = [50, 150, 10, 10, 9];
  clockFaceDivs[9] = [63.5, 100, 10, 10, 10];
  clockFaceDivs[10] = [100, 63.5, 10, 10, 11];
  clockFaceDivs[11] = [150, 50, 10, 10, 12];

  var secondHandArray = [[0], [10], [20], [30], [40], [50], [60], [70], [80], [90], [100], [110]];
  var minuteHandArray = [[0], [10], [20], [30], [40], [50], [60], [70], [80]];
  var hourHandArray = [[0], [10], [20], [30], [40], [50]];

  function drawDivClockFace() {
    for (var i = 0; i < clockFaceDivs.length; i++) {
      var idString = clockFaceDivs[i][4] + 'holder';
      var noHolder = document.createElement('div');
      noHolder.className = 'clockElement';
      noHolder.id = idString;
      noHolder.textContent = clockFaceDivs[i][4];
      divClock.appendChild(noHolder);
      $('#' + idString).css('left', clockFaceDivs[i][0] - (clockFaceDivs[i][2]/2) );
      $('#' + idString).css('top', clockFaceDivs[i][1] - (clockFaceDivs[i][3]/2));
      $('#' + idString).width(clockFaceDivs[i][2] );
      $('#' + idString).height(clockFaceDivs[i][3] );
    }
  }

  function buildDivHand (buildArray, idAppend, handAngle, divClass, halfWidth){
    for (var i = 0; i < buildArray.length; i++){
      idString = secondHandArray[i][0] + idAppend;
      secondHandArray[i].push(idString);
      var thisDiv = document.createElement('div');
      thisDiv.id = idString;
      thisDiv.className = divClass;
      divClock.appendChild(thisDiv);
      $('#' + idString).css('left', 150 - halfWidth + buildArray[i][0] * Math.sin(handAngle));
      $('#' + idString).css('top', 150 - halfWidth - buildArray[i][0] * Math.cos(handAngle));
    }
  }

  function updateDivHand(buildArray, handAngle, halfWidth) {
    for (var i = 0; i < buildArray.length; i++){
      $('#' + buildArray[i][1]).css('left', 150 - halfWidth + buildArray[i][0] * Math.sin(handAngle));
      $('#' + buildArray[i][1]).css('top', 150 - halfWidth - buildArray[i][0] * Math.cos(handAngle));
    }
  }

//CANVAS CLOCK __________________________________________________________________________________________________________________
  var canvas = document.getElementById('canvas');
  var ctx = canvas.getContext('2d');
  ctx.strokeStyle = '#000000';

  var secondHand = {
    angle: 0,
    length: 110,
    increment: 0.10472,
    seconds: 0,

    updateSecondHand: function(){
      secondHand.seconds++;
      secondHand.angle = (secondHand.angle + secondHand.increment);// % 6.2832;
    },
    drawSecondHand: function(){
      ctx.beginPath();
      ctx.lineWidth = 2;
      ctx.moveTo(150, 150);
      ctx.lineTo( 150 + secondHand.length * Math.sin(secondHand.angle), 150 - secondHand.length * Math.cos(secondHand.angle))
      ctx.stroke();
    }
  }

  var minuteHand = {
    angle: 0,
    length: 80,
    increment: 0.010472,
    seconds: 0,

    updateMinuteHand: function(){
      if (secondHand.seconds % 6 === 0){
        minuteHand.angle = (minuteHand.angle + minuteHand.increment);
      }
    },
    drawMinuteHand: function(){
      ctx.beginPath();
      ctx.lineWidth = 4;
      ctx.moveTo(150, 150);
      ctx.lineTo( 150 + minuteHand.length * Math.sin(minuteHand.angle), 150 - minuteHand.length * Math.cos(minuteHand.angle))
      ctx.stroke();
    }
  }

  var hourHand = {
    angle: 0,
    length: 60,
    increment: 0.010472,
    seconds: 0,

    updateHourHand: function(){
      if (secondHand.seconds % 72 === 0){
        hourHand.angle = (hourHand.angle + hourHand.increment);
        if (secondHand.seconds % 86400 === 0){
          initialize();
        }
      }
    },
    drawHourHand: function(){
      ctx.beginPath();
      ctx.lineWidth = 8;
      ctx.moveTo(150, 150);
      ctx.lineTo( 150 + hourHand.length*Math.sin(hourHand.angle), 150 - hourHand.length * Math.cos(hourHand.angle))
      ctx.stroke();
    }
  }

  function initialize(){
    var date = new Date();
    var hrs = date.getHours();
    var mins = date.getMinutes();
    var secs = date.getSeconds();
    secondHand.seconds = 0;
    secondHand.angle = 0;
    minuteHand.angle = 0;
    hourHand.angle = 0;
    secondHand.seconds = ((3600 * hrs) + (60 * mins) + secs);
    secondHand.angle += (secondHand.seconds % 60) * secondHand.increment;
    minuteHand.angle += (((secondHand.seconds % 3600) - (secs % 6))/ 6 ) * minuteHand.increment;
    hourHand.angle += (((secondHand.seconds % 43200) - ( (60 * mins + secs) % 72) ) / 72 ) * hourHand.increment;
    buildDivHand(secondHandArray, 'second', secondHand.angle, 'secondHandDiv',  1);
    buildDivHand(minuteHandArray, 'minute', minuteHand.angle, 'minuteHandDiv',  2);
    buildDivHand(hourHandArray, 'hour', hourHand.angle, 'hourHandDiv', 4);
  }

  function clearCanvas(){
    ctx.clearRect(0,0, canvas.width, canvas.height);
  }

  function drawBox(centerX, centerY, width, height, color){
    ctx.fillStyle = color;
    ctx.fillRect(centerX - width/2, centerY - height/2, width, height);
  }

  function drawClockFace(){
    drawBox(150, 50, 10, 30, '#000000');
    drawBox(150, 250, 10, 30, '#000000');
    drawBox(50, 150, 30, 10, '#000000');
    drawBox(250, 150, 30, 10, '#000000');
    drawBox(150, 150, 4, 4, '#000000');

    drawBox(200, 63.5, 4, 4, '#000000');
    drawBox(236.5, 100, 4, 4, '#000000');
    drawBox(100, 63.5, 4, 4, '#000000');
    drawBox(63.5, 100, 4, 4, '#000000');
    drawBox(63.5, 200, 4, 4, '#000000');
    drawBox(100, 236.5, 4, 4, '#000000');
    drawBox(200, 236.5, 4, 4, '#000000');
    drawBox(236.5, 200, 4, 4, '#000000');
  }

  function updateHands(){
    secondHand.updateSecondHand();
    minuteHand.updateMinuteHand();
    hourHand.updateHourHand();
  }

  function drawHands(){
    secondHand.drawSecondHand();
    minuteHand.drawMinuteHand();
    hourHand.drawHourHand();
    updateDivHand(secondHandArray, secondHand.angle, 1);
    updateDivHand(minuteHandArray, minuteHand.angle, 2);
    updateDivHand(hourHandArray, hourHand.angle, 4);
  }

  // for (var i = 0; i < secondHandArray.length; i++){
  //   idString = secondHandArray[i][0] + 'second';
  //   secondHandArray[i].push(idString);
  //   var secondHandDiv = document.createElement('div');
  //   secondHandDiv.id = idString;
  //   secondHandDiv.className = 'secondHandDiv';
  //   divClock.appendChild(secondHandDiv);
  //   $('#' + idString).css('left', 149 + secondHandArray[i][0] * Math.sin(secondHand.angle));
  //   $('#' + idString).css('top', 149 - secondHandArray[i][0] * Math.cos(secondHand.angle));
  // }
  //
  // for (var i = 0; i < minuteHandArray.length; i++){
  //   idString = minuteHandArray[i][0] + 'minute';
  //   minuteHandArray[i].push(idString);
  //   var minuteHandDiv = document.createElement('div');
  //   minuteHandDiv.id = idString;
  //   minuteHandDiv.className = 'minuteHandDiv';
  //   divClock.appendChild(minuteHandDiv);
  //   $('#' + idString).css('left', 148 + minuteHandArray[i][0] * Math.sin(minuteHand.angle));
  //   $('#' + idString).css('top', 148 - minuteHandArray[i][0] * Math.cos(minuteHand.angle));
  // }
  // for (var i = 0; i < hourHandArray.length; i++){
  //   idString = hourHandArray[i][0] + 'hour';
  //   hourHandArray[i].push(idString);
  //   var hourHandDiv = document.createElement('div');
  //   hourHandDiv.id = idString;
  //   hourHandDiv.className = 'hourHandDiv';
  //   divClock.appendChild(hourHandDiv);
  //   $('#' + idString).css('left', 146 + hourHandArray[i][0] * Math.sin(hourHand.angle));
  //   $('#' + idString).css('top', 146 - hourHandArray[i][0] * Math.cos(hourHand.angle));
  // }

  initialize();
  drawDivClockFace();
  drawClockFace();
  var requestAnimationFrame = window.requestAnimationFrame;
  function timeLoop() {
    updateHands();
    clearCanvas();
    drawClockFace();
    drawHands();
    setTimeout(function(){
      requestAnimationFrame(timeLoop);
    }, 1000);
  }
  requestAnimationFrame(timeLoop);

});
<commit_msg>last commit before switching to version for portfolio<commit_after>$(document).ready(function(){
  // var divClock = document.getElementById('divClock');
  //
  // var clockFaceDivs = [];
  // clockFaceDivs[0] = [200, 63.5, 10, 10, 1];
  // clockFaceDivs[1] = [236.5, 100, 10, 10, 2];
  // clockFaceDivs[2] = [250, 150, 10, 10, 3];
  // clockFaceDivs[3] = [236.5, 200, 10, 10, 4];
  // clockFaceDivs[4] = [200, 236.5, 10, 10, 5];
  // clockFaceDivs[5] = [150, 250, 10, 10, 6];
  // clockFaceDivs[6] = [100, 236.5, 10, 10, 7];
  // clockFaceDivs[7] = [63.5, 200, 10, 10, 8];
  // clockFaceDivs[8] = [50, 150, 10, 10, 9];
  // clockFaceDivs[9] = [63.5, 100, 10, 10, 10];
  // clockFaceDivs[10] = [100, 63.5, 10, 10, 11];
  // clockFaceDivs[11] = [150, 50, 10, 10, 12];
  //
  // var secondHandArray = [[0], [10], [20], [30], [40], [50], [60], [70], [80], [90], [100], [110]];
  // var minuteHandArray = [[0], [10], [20], [30], [40], [50], [60], [70], [80]];
  // var hourHandArray = [[0], [10], [20], [30], [40], [50]];
  //
  // function drawDivClockFace() {
  //   for (var i = 0; i < clockFaceDivs.length; i++) {
  //     var idString = clockFaceDivs[i][4] + 'holder';
  //     var noHolder = document.createElement('div');
  //     noHolder.className = 'clockElement';
  //     noHolder.id = idString;
  //     noHolder.textContent = clockFaceDivs[i][4];
  //     divClock.appendChild(noHolder);
  //     $('#' + idString).css('left', clockFaceDivs[i][0] - (clockFaceDivs[i][2]/2) );
  //     $('#' + idString).css('top', clockFaceDivs[i][1] - (clockFaceDivs[i][3]/2));
  //     $('#' + idString).width(clockFaceDivs[i][2] );
  //     $('#' + idString).height(clockFaceDivs[i][3] );
  //   }
  // }
  //
  // function buildDivHand (buildArray, idAppend, handAngle, divClass, halfWidth){
  //   for (var i = 0; i < buildArray.length; i++){
  //     idString = secondHandArray[i][0] + idAppend;
  //     secondHandArray[i].push(idString);
  //     var thisDiv = document.createElement('div');
  //     thisDiv.id = idString;
  //     thisDiv.className = divClass;
  //     divClock.appendChild(thisDiv);
  //     $('#' + idString).css('left', 150 - halfWidth + buildArray[i][0] * Math.sin(handAngle));
  //     $('#' + idString).css('top', 150 - halfWidth - buildArray[i][0] * Math.cos(handAngle));
  //   }
  // }
  //
  // function updateDivHand(buildArray, handAngle, halfWidth) {
  //   for (var i = 0; i < buildArray.length; i++){
  //     $('#' + buildArray[i][1]).css('left', 150 - halfWidth + buildArray[i][0] * Math.sin(handAngle));
  //     $('#' + buildArray[i][1]).css('top', 150 - halfWidth - buildArray[i][0] * Math.cos(handAngle));
  //   }
  // }

//CANVAS CLOCK __________________________________________________________________________________________________________________
  var canvas = document.getElementById('canvas');
  var ctx = canvas.getContext('2d');
  ctx.strokeStyle = '#000000';

  var secondHand = {
    angle: 0,
    length: 110,
    increment: 0.10472,
    seconds: 0,

    updateSecondHand: function(){
      secondHand.seconds++;
      secondHand.angle = (secondHand.angle + secondHand.increment);// % 6.2832;
    },
    drawSecondHand: function(){
      ctx.beginPath();
      ctx.lineWidth = 2;
      ctx.moveTo(150, 150);
      ctx.lineTo( 150 + secondHand.length * Math.sin(secondHand.angle), 150 - secondHand.length * Math.cos(secondHand.angle))
      ctx.stroke();
    }
  }

  var minuteHand = {
    angle: 0,
    length: 80,
    increment: 0.010472,
    seconds: 0,

    updateMinuteHand: function(){
      if (secondHand.seconds % 6 === 0){
        minuteHand.angle = (minuteHand.angle + minuteHand.increment);
      }
    },
    drawMinuteHand: function(){
      ctx.beginPath();
      ctx.lineWidth = 4;
      ctx.moveTo(150, 150);
      ctx.lineTo( 150 + minuteHand.length * Math.sin(minuteHand.angle), 150 - minuteHand.length * Math.cos(minuteHand.angle))
      ctx.stroke();
    }
  }

  var hourHand = {
    angle: 0,
    length: 60,
    increment: 0.010472,
    seconds: 0,

    updateHourHand: function(){
      if (secondHand.seconds % 72 === 0){
        hourHand.angle = (hourHand.angle + hourHand.increment);
        if (secondHand.seconds % 86400 === 0){
          initialize();
        }
      }
    },
    drawHourHand: function(){
      ctx.beginPath();
      ctx.lineWidth = 8;
      ctx.moveTo(150, 150);
      ctx.lineTo( 150 + hourHand.length*Math.sin(hourHand.angle), 150 - hourHand.length * Math.cos(hourHand.angle))
      ctx.stroke();
    }
  }

  function initialize(){
    var date = new Date();
    var hrs = date.getHours();
    var mins = date.getMinutes();
    var secs = date.getSeconds();
    secondHand.seconds = 0;
    secondHand.angle = 0;
    minuteHand.angle = 0;
    hourHand.angle = 0;
    secondHand.seconds = ((3600 * hrs) + (60 * mins) + secs);
    secondHand.angle += (secondHand.seconds % 60) * secondHand.increment;
    minuteHand.angle += (((secondHand.seconds % 3600) - (secs % 6))/ 6 ) * minuteHand.increment;
    hourHand.angle += (((secondHand.seconds % 43200) - ( (60 * mins + secs) % 72) ) / 72 ) * hourHand.increment;
    // buildDivHand(secondHandArray, 'second', secondHand.angle, 'secondHandDiv',  1);
    // buildDivHand(minuteHandArray, 'minute', minuteHand.angle, 'minuteHandDiv',  2);
    // buildDivHand(hourHandArray, 'hour', hourHand.angle, 'hourHandDiv', 4);
  }

  function clearCanvas(){
    ctx.clearRect(0,0, canvas.width, canvas.height);
  }

  function drawBox(centerX, centerY, width, height, color){
    ctx.fillStyle = color;
    ctx.fillRect(centerX - width/2, centerY - height/2, width, height);
  }

  function drawClockFace(){
    drawBox(150, 50, 10, 30, '#000000');
    drawBox(150, 250, 10, 30, '#000000');
    drawBox(50, 150, 30, 10, '#000000');
    drawBox(250, 150, 30, 10, '#000000');
    drawBox(150, 150, 4, 4, '#000000');

    drawBox(200, 63.5, 4, 4, '#000000');
    drawBox(236.5, 100, 4, 4, '#000000');
    drawBox(100, 63.5, 4, 4, '#000000');
    drawBox(63.5, 100, 4, 4, '#000000');
    drawBox(63.5, 200, 4, 4, '#000000');
    drawBox(100, 236.5, 4, 4, '#000000');
    drawBox(200, 236.5, 4, 4, '#000000');
    drawBox(236.5, 200, 4, 4, '#000000');
  }

  function updateHands(){
    secondHand.updateSecondHand();
    minuteHand.updateMinuteHand();
    hourHand.updateHourHand();
  }

  function drawHands(){
    secondHand.drawSecondHand();
    minuteHand.drawMinuteHand();
    hourHand.drawHourHand();
    // updateDivHand(secondHandArray, secondHand.angle, 1);
    // updateDivHand(minuteHandArray, minuteHand.angle, 2);
    // updateDivHand(hourHandArray, hourHand.angle, 4);
  }

  // for (var i = 0; i < secondHandArray.length; i++){
  //   idString = secondHandArray[i][0] + 'second';
  //   secondHandArray[i].push(idString);
  //   var secondHandDiv = document.createElement('div');
  //   secondHandDiv.id = idString;
  //   secondHandDiv.className = 'secondHandDiv';
  //   divClock.appendChild(secondHandDiv);
  //   $('#' + idString).css('left', 149 + secondHandArray[i][0] * Math.sin(secondHand.angle));
  //   $('#' + idString).css('top', 149 - secondHandArray[i][0] * Math.cos(secondHand.angle));
  // }
  //
  // for (var i = 0; i < minuteHandArray.length; i++){
  //   idString = minuteHandArray[i][0] + 'minute';
  //   minuteHandArray[i].push(idString);
  //   var minuteHandDiv = document.createElement('div');
  //   minuteHandDiv.id = idString;
  //   minuteHandDiv.className = 'minuteHandDiv';
  //   divClock.appendChild(minuteHandDiv);
  //   $('#' + idString).css('left', 148 + minuteHandArray[i][0] * Math.sin(minuteHand.angle));
  //   $('#' + idString).css('top', 148 - minuteHandArray[i][0] * Math.cos(minuteHand.angle));
  // }
  // for (var i = 0; i < hourHandArray.length; i++){
  //   idString = hourHandArray[i][0] + 'hour';
  //   hourHandArray[i].push(idString);
  //   var hourHandDiv = document.createElement('div');
  //   hourHandDiv.id = idString;
  //   hourHandDiv.className = 'hourHandDiv';
  //   divClock.appendChild(hourHandDiv);
  //   $('#' + idString).css('left', 146 + hourHandArray[i][0] * Math.sin(hourHand.angle));
  //   $('#' + idString).css('top', 146 - hourHandArray[i][0] * Math.cos(hourHand.angle));
  // }

  initialize();
  // drawDivClockFace();
  drawClockFace();
  var requestAnimationFrame = window.requestAnimationFrame;
  function timeLoop() {
    updateHands();
    clearCanvas();
    drawClockFace();
    drawHands();
    setTimeout(function(){
      requestAnimationFrame(timeLoop);
    }, 1000);
  }
  requestAnimationFrame(timeLoop);

});
<|endoftext|>


<commit_before>var twitter = require('twitter');
var cylon = require('cylon');
var config = require('./config');

var twit = new twitter({
    consumer_key: config.consumerKey,
    consumer_secret: config.consumerSecret,
    access_token_key: config.accessTokenKey,
    access_token_secret: config.accessTokenSecret
});

cylon.robot({
    connections: { edison: { adaptor: 'intel-iot' } },
    devices: { monkey: { driver: 'direct-pin', pin: 2 } },
    work: function (edison) {
        twit.stream('filter', { track: '#tweetmonkey' }, function (stream) {
            stream.on('data', function (data) {
                edison.monkey.digitalWrite(1);
                setTimeout(function () { edison.monkey.digitalWrite(0); }, 5000);
            });
        });
    }
}).start();

<commit_msg>add comment for monitoring based on twitter user instead of just topic<commit_after>var twitter = require('twitter');
var cylon = require('cylon');
var config = require('./config');

var twit = new twitter({
    consumer_key: config.consumerKey,
    consumer_secret: config.consumerSecret,
    access_token_key: config.accessTokenKey,
    access_token_secret: config.accessTokenSecret
});

cylon.robot({
    name: 'edison',
    connections: { edison: { adaptor: 'intel-iot' } },
    devices: { monkey: { driver: 'direct-pin', pin: 2 } },
    work: function (edison) {
        //monitor by topic
        twit.stream('filter', { track: '#tweetmonkey' }, function (stream) {
            stream.on('data', function (data) {
                edison.monkey.digitalWrite(1);
                setTimeout(function () { edison.monkey.digitalWrite(0); }, 5000);
            });
        });

        ////monitor by user
        //twit.showUser('{SCREENNAME}', function (data) {
        //    userId = data.id;
        //    twit.stream('filter', { follow: userId }, function (stream) {
        //        stream.on('data', function (data) {
        //            edison.monkey.digitalWrite(1);
        //            setTimeout(function () { edison.monkey.digitalWrite(0); }, 5000);
        //        });
        //    });
        //});

    }
}).start();

<|endoftext|>


<commit_before>// Run this before other modules
if (process.env.NEW_RELIC_LICENSE_KEY) {
  require('newrelic')
}

process.title = 'streetmix'

const compression = require('compression')
const cookieParser = require('cookie-parser')
const cookieSession = require('cookie-session')
const express = require('express')
const bodyParser = require('body-parser')
const cors = require('cors')
const helmet = require('helmet')
const config = require('config')
const path = require('path')
const uuid = require('uuid/v4')
const controllers = require('./app/controllers')
const resources = require('./app/resources')
const requestHandlers = require('./lib/request_handlers')
const initRedisClient = require('./lib/redis')
const initMongoDB = require('./lib/db')
const initCloudinary = require('./lib/cloudinary')
const exec = require('child_process').exec

const client = initRedisClient()
initMongoDB()
initCloudinary()

const app = module.exports = express()

// Get the timestamp of this server's start time to use as a cachebusting filename.
const cacheTimestamp = Date.now()
app.locals.cacheTimestamp = cacheTimestamp

process.on('uncaughtException', function (error) {
  console.log(error)
  console.trace()

  if (client.connected) {
    client.on('end', function () {
      process.exit(1)
    })
  } else {
    process.exit(1)
  }
})

// Provide a message after a Ctrl-C
// Note: various sources tell us that this does not work on Windows
process.on('SIGINT', function () {
  if (app.locals.config.env === 'development') {
    console.log('Stopping Streetmix!')
    exec('npm stop')
  }

  if (client.connected) {
    client.on('end', process.exit)
  } else {
    process.exit()
  }
})

app.locals.config = config

// Not all headers from `helmet` are on by default. These turns on specific
// off-by-default headers for better security as recommended by https://securityheaders.io/
const helmetConfig = {
  frameguard: false, // Allow Streetmix to be iframed in 3rd party sites
  hsts: {
    maxAge: 5184000, // 60 days
    includeSubDomains: false // we don't have a wildcard ssl cert
  },
  referrerPolicy: {
    policy: 'no-referrer-when-downgrade'
  }
}

// CSP directives are defined separately so we can generate nonces
const csp = {
  directives: {
    defaultSrc: ["'self'"],
    styleSrc: [
      "'self'",
      "'unsafe-inline'",
      'fonts.googleapis.com',
      '*.typekit.net'
    ],
    scriptSrc: [
      "'self'",
      'platform.twitter.com',
      'https://www.google-analytics.com',
      'cdn.mxpnl.com',
      'streetmix.auth0.com',
      '*.basemaps.cartocdn.com',
      'api.geocode.earth',
      (req, res) => "'nonce-" + res.locals.nonce.google_analytics + "'",
      (req, res) => "'nonce-" + res.locals.nonce.mixpanel + "'"
    ],
    childSrc: ['platform.twitter.com'],
    frameSrc: ["'self'", 'streetmix.github.io'],
    imgSrc: [
      "'self'",
      'data:',
      'pbs.twimg.com',
      'syndication.twitter.com',
      's.gravatar.com',
      'https://www.google-analytics.com',
      '*.basemaps.cartocdn.com',
      'https://res.cloudinary.com/'
    ],
    fontSrc: [
      "'self'",
      'fonts.gstatic.com',
      '*.typekit.net'
    ],
    connectSrc: [
      "'self'",
      'api.mixpanel.com',
      'api.geocode.earth',
      'syndication.twitter.com',
      'https://www.google-analytics.com',
      'app.getsentry.com',
      'streetmix.auth0.com'
    ]
  }
}

// Allow arbitrary injected code (e.g. Redux dispatches from dev tools) in development
if (app.locals.config.env === 'development') {
  csp.directives.scriptSrc.push("'unsafe-eval'")
  // Allows websockets for hot-module reloading (note: ports are assigned randomly by Parcel)
  csp.directives.connectSrc.push('ws:')
}

app.use(helmet(helmetConfig))
app.use(express.json())
app.use(compression())
app.use(cookieParser())
app.use(cookieSession({ secret: config.cookie_session_secret }))

app.use(requestHandlers.login_token_parser)
app.use(requestHandlers.request_log)
app.use(requestHandlers.request_id_echo)

// Generate nonces for inline scripts
app.use((req, res, next) => {
  res.locals.nonce = {
    google_analytics: uuid(),
    mixpanel: uuid()
  }

  res.locals.STREETMIX_IMAGE = {
    image: 'https://streetmix.net/images/thumbnail.png',
    width: 1008,
    height: 522
  }

  res.locals.STREETMIX_TITLE = 'Streetmix'
  res.locals.STREETMIX_URL = config.restapi.protocol + config.app_host_port + '/'

  next()
})

// Set Redis client for when requesting the geoip
app.use('/services/geoip', (req, res, next) => {
  req.redisClient = client
  next()
})

// Set CSP directives
app.use(helmet.contentSecurityPolicy(csp))

// Rewrite requests with timestamp
app.use((req, res, next) => {
  // Matches a filename like styles.2395934243.css
  // Accepts optional `?29090424` query string used by Parcel's hot-module reloader
  req.url = req.url.replace(/\/([^/]+)\.[0-9]+\.(css|js)(\?[0-9]+)?$/, '/$1.$2')
  next()
})

app.set('view engine', 'hbs')
app.set('views', path.join(__dirname, '/app/views'))

app.get('/help/about', (req, res) => res.redirect('https://www.opencollective.com/streetmix/'))
app.get('/map', (req, res) => res.redirect('https://streetmix.github.io/map/'))

app.get('/privacy-policy', (req, res) => res.render('privacy'))
app.get('/terms-of-service', (req, res) => res.render('tos'))

app.get('/twitter-sign-in', controllers.twitter_sign_in.get)
app.get(config.twitter.oauth_callback_uri, controllers.twitter_sign_in_callback.get)
// Auth0
app.get(config.auth0.callback_uri, controllers.auth0_sign_in_callback.get)

// Enable CORS for all OPTIONs "pre-flight" requests
app.options('/api/*', cors())

app.post('/api/v1/users', cors(), resources.v1.users.post)
app.get('/api/v1/users', cors(), resources.v1.users.get)
app.get('/api/v1/users/:user_id', cors(), resources.v1.user.get)
app.put('/api/v1/users/:user_id', cors(), resources.v1.user.put)
app.delete('/api/v1/users/:user_id', cors(), resources.v1.user.delete)
app.delete('/api/v1/users/:user_id/login-token', cors(), resources.v1.user_session.delete)
app.delete('/api/v1/users/:user_id/streets', cors(), resources.v1.users_streets.delete)
app.get('/api/v1/users/:user_id/streets', cors(), resources.v1.users_streets.get)

app.post('/api/v1/streets', resources.v1.streets.post)
app.get('/api/v1/streets', resources.v1.streets.find)
app.head('/api/v1/streets', resources.v1.streets.find)

app.delete('/api/v1/streets/:street_id', resources.v1.streets.delete)
app.head('/api/v1/streets/:street_id', resources.v1.streets.get)
app.get('/api/v1/streets/:street_id', resources.v1.streets.get)
app.put('/api/v1/streets/:street_id', resources.v1.streets.put)

app.post('/api/v1/streets/images/:street_id', bodyParser.text({ limit: '3mb' }), resources.v1.street_images.post)
app.delete('/api/v1/streets/images/:street_id', resources.v1.street_images.delete)
app.get('/api/v1/streets/images/:street_id', resources.v1.street_images.get)

app.get('/api/v1/geo', cors(), resources.v1.geo.get)

app.get('/services/geoip', resources.services.geoip.get)

app.options('/services/images', cors())
app.get('/services/images', cors(), resources.services.images.get)

app.get('/api/v1/translate/:locale_code/:resource_name', resources.v1.translate.get)

app.get('/api/v1/flags', cors(), resources.v1.flags.get)

// Catch all for all broken api paths, direct to 404 response.
app.get('/api/*', (req, res) => {
  res.status(404).json({ status: 404, error: 'Not found. Did you mispell something?' })
})

// SVG bundled images served directly from packages
app.get('/assets/images/icons.svg', (req, res) => {
  res.sendFile(path.join(__dirname, '/node_modules/@streetmix/icons/dist/icons.svg'))
})

app.get('/assets/images/images.svg', (req, res) => {
  res.sendFile(path.join(__dirname, '/node_modules/@streetmix/illustrations/dist/images.svg'))
})

app.use('/assets', express.static(path.join(__dirname, '/build'), { fallthrough: false }))
app.use(express.static(path.join(__dirname, '/public')))

// Allow hot-module reloading (HMR) in non-production environments
if (config.env !== 'production') {
  const runBundle = require('./app/bundle')
  runBundle(app)
}

app.get(['/:user_id/:namespaced_id', '/:user_id/:namespaced_id/:street_name'], requestHandlers.metatags)

// Catch-all
app.use((req, res) => res.render('main', {
  FACEBOOK_APP_ID: config.facebook_app_id
}))
<commit_msg>Put facebook app ID on res.locals instead<commit_after>// Run this before other modules
if (process.env.NEW_RELIC_LICENSE_KEY) {
  require('newrelic')
}

process.title = 'streetmix'

const compression = require('compression')
const cookieParser = require('cookie-parser')
const cookieSession = require('cookie-session')
const express = require('express')
const bodyParser = require('body-parser')
const cors = require('cors')
const helmet = require('helmet')
const config = require('config')
const path = require('path')
const uuid = require('uuid/v4')
const controllers = require('./app/controllers')
const resources = require('./app/resources')
const requestHandlers = require('./lib/request_handlers')
const initRedisClient = require('./lib/redis')
const initMongoDB = require('./lib/db')
const initCloudinary = require('./lib/cloudinary')
const exec = require('child_process').exec

const client = initRedisClient()
initMongoDB()
initCloudinary()

const app = module.exports = express()

// Get the timestamp of this server's start time to use as a cachebusting filename.
const cacheTimestamp = Date.now()
app.locals.cacheTimestamp = cacheTimestamp

process.on('uncaughtException', function (error) {
  console.log(error)
  console.trace()

  if (client.connected) {
    client.on('end', function () {
      process.exit(1)
    })
  } else {
    process.exit(1)
  }
})

// Provide a message after a Ctrl-C
// Note: various sources tell us that this does not work on Windows
process.on('SIGINT', function () {
  if (app.locals.config.env === 'development') {
    console.log('Stopping Streetmix!')
    exec('npm stop')
  }

  if (client.connected) {
    client.on('end', process.exit)
  } else {
    process.exit()
  }
})

app.locals.config = config

// Not all headers from `helmet` are on by default. These turns on specific
// off-by-default headers for better security as recommended by https://securityheaders.io/
const helmetConfig = {
  frameguard: false, // Allow Streetmix to be iframed in 3rd party sites
  hsts: {
    maxAge: 5184000, // 60 days
    includeSubDomains: false // we don't have a wildcard ssl cert
  },
  referrerPolicy: {
    policy: 'no-referrer-when-downgrade'
  }
}

// CSP directives are defined separately so we can generate nonces
const csp = {
  directives: {
    defaultSrc: ["'self'"],
    styleSrc: [
      "'self'",
      "'unsafe-inline'",
      'fonts.googleapis.com',
      '*.typekit.net'
    ],
    scriptSrc: [
      "'self'",
      'platform.twitter.com',
      'https://www.google-analytics.com',
      'cdn.mxpnl.com',
      'streetmix.auth0.com',
      '*.basemaps.cartocdn.com',
      'api.geocode.earth',
      (req, res) => "'nonce-" + res.locals.nonce.google_analytics + "'",
      (req, res) => "'nonce-" + res.locals.nonce.mixpanel + "'"
    ],
    childSrc: ['platform.twitter.com'],
    frameSrc: ["'self'", 'streetmix.github.io'],
    imgSrc: [
      "'self'",
      'data:',
      'pbs.twimg.com',
      'syndication.twitter.com',
      's.gravatar.com',
      'https://www.google-analytics.com',
      '*.basemaps.cartocdn.com',
      'https://res.cloudinary.com/'
    ],
    fontSrc: [
      "'self'",
      'fonts.gstatic.com',
      '*.typekit.net'
    ],
    connectSrc: [
      "'self'",
      'api.mixpanel.com',
      'api.geocode.earth',
      'syndication.twitter.com',
      'https://www.google-analytics.com',
      'app.getsentry.com',
      'streetmix.auth0.com'
    ]
  }
}

// Allow arbitrary injected code (e.g. Redux dispatches from dev tools) in development
if (app.locals.config.env === 'development') {
  csp.directives.scriptSrc.push("'unsafe-eval'")
  // Allows websockets for hot-module reloading (note: ports are assigned randomly by Parcel)
  csp.directives.connectSrc.push('ws:')
}

app.use(helmet(helmetConfig))
app.use(express.json())
app.use(compression())
app.use(cookieParser())
app.use(cookieSession({ secret: config.cookie_session_secret }))

app.use(requestHandlers.login_token_parser)
app.use(requestHandlers.request_log)
app.use(requestHandlers.request_id_echo)

// Set variables for use in view templates
app.use((req, res, next) => {
  // Generate nonces for inline scripts
  res.locals.nonce = {
    google_analytics: uuid(),
    mixpanel: uuid()
  }

  // Set default metatag information for social sharing cards
  res.locals.STREETMIX_IMAGE = {
    image: 'https://streetmix.net/images/thumbnail.png',
    width: 1008,
    height: 522
  }

  res.locals.STREETMIX_TITLE = 'Streetmix'
  res.locals.STREETMIX_URL = config.restapi.protocol + config.app_host_port + '/'

  // Make required Facebook app ID available to metatags
  res.locals.FACEBOOK_APP_ID = config.facebook_app_id

  next()
})

// Set Redis client for when requesting the geoip
app.use('/services/geoip', (req, res, next) => {
  req.redisClient = client
  next()
})

// Set CSP directives
app.use(helmet.contentSecurityPolicy(csp))

// Rewrite requests with timestamp
app.use((req, res, next) => {
  // Matches a filename like styles.2395934243.css
  // Accepts optional `?29090424` query string used by Parcel's hot-module reloader
  req.url = req.url.replace(/\/([^/]+)\.[0-9]+\.(css|js)(\?[0-9]+)?$/, '/$1.$2')
  next()
})

app.set('view engine', 'hbs')
app.set('views', path.join(__dirname, '/app/views'))

app.get('/help/about', (req, res) => res.redirect('https://www.opencollective.com/streetmix/'))
app.get('/map', (req, res) => res.redirect('https://streetmix.github.io/map/'))

app.get('/privacy-policy', (req, res) => res.render('privacy'))
app.get('/terms-of-service', (req, res) => res.render('tos'))

app.get('/twitter-sign-in', controllers.twitter_sign_in.get)
app.get(config.twitter.oauth_callback_uri, controllers.twitter_sign_in_callback.get)
// Auth0
app.get(config.auth0.callback_uri, controllers.auth0_sign_in_callback.get)

// Enable CORS for all OPTIONs "pre-flight" requests
app.options('/api/*', cors())

app.post('/api/v1/users', cors(), resources.v1.users.post)
app.get('/api/v1/users', cors(), resources.v1.users.get)
app.get('/api/v1/users/:user_id', cors(), resources.v1.user.get)
app.put('/api/v1/users/:user_id', cors(), resources.v1.user.put)
app.delete('/api/v1/users/:user_id', cors(), resources.v1.user.delete)
app.delete('/api/v1/users/:user_id/login-token', cors(), resources.v1.user_session.delete)
app.delete('/api/v1/users/:user_id/streets', cors(), resources.v1.users_streets.delete)
app.get('/api/v1/users/:user_id/streets', cors(), resources.v1.users_streets.get)

app.post('/api/v1/streets', resources.v1.streets.post)
app.get('/api/v1/streets', resources.v1.streets.find)
app.head('/api/v1/streets', resources.v1.streets.find)

app.delete('/api/v1/streets/:street_id', resources.v1.streets.delete)
app.head('/api/v1/streets/:street_id', resources.v1.streets.get)
app.get('/api/v1/streets/:street_id', resources.v1.streets.get)
app.put('/api/v1/streets/:street_id', resources.v1.streets.put)

app.post('/api/v1/streets/images/:street_id', bodyParser.text({ limit: '3mb' }), resources.v1.street_images.post)
app.delete('/api/v1/streets/images/:street_id', resources.v1.street_images.delete)
app.get('/api/v1/streets/images/:street_id', resources.v1.street_images.get)

app.get('/api/v1/geo', cors(), resources.v1.geo.get)

app.get('/services/geoip', resources.services.geoip.get)

app.options('/services/images', cors())
app.get('/services/images', cors(), resources.services.images.get)

app.get('/api/v1/translate/:locale_code/:resource_name', resources.v1.translate.get)

app.get('/api/v1/flags', cors(), resources.v1.flags.get)

// Catch all for all broken api paths, direct to 404 response.
app.get('/api/*', (req, res) => {
  res.status(404).json({ status: 404, error: 'Not found. Did you mispell something?' })
})

// SVG bundled images served directly from packages
app.get('/assets/images/icons.svg', (req, res) => {
  res.sendFile(path.join(__dirname, '/node_modules/@streetmix/icons/dist/icons.svg'))
})

app.get('/assets/images/images.svg', (req, res) => {
  res.sendFile(path.join(__dirname, '/node_modules/@streetmix/illustrations/dist/images.svg'))
})

app.use('/assets', express.static(path.join(__dirname, '/build'), { fallthrough: false }))
app.use(express.static(path.join(__dirname, '/public')))

// Allow hot-module reloading (HMR) in non-production environments
if (config.env !== 'production') {
  const runBundle = require('./app/bundle')
  runBundle(app)
}

app.get(['/:user_id/:namespaced_id', '/:user_id/:namespaced_id/:street_name'], requestHandlers.metatags)

// Catch-all
app.use((req, res) => res.render('main'))
<|endoftext|>


<commit_before>'use strict';

// Enable actions client library debugging
process.env.DEBUG = 'actions-on-google:*';

let ApiAiAssistant = require('actions-on-google').ApiAiAssistant;
let express = require('express');
let bodyParser = require('body-parser');

let app = express();
app.set('port', (process.env.PORT || 8080));
app.use(bodyParser.json({ type: 'application/json' }));

/// Prompts
// These prompts are used to greet the player when they start the game
const GREETING_PROMPTS = [
	'Hello, and welcome to Dungeon Adventure! I\'ll be your Game Master tonight! Hopefully you\'re ready for some adventure!',
	'Welcome to Dungeon Adventure! I\'ll be your Game Master, and I hope you\'re ready to go on an adventure, because I sure am!',
	'It\'s good to see you! I\'m your Game Master, and we\'re about to go on a Dungeon Adventure!',
	'Hey there! Welcome to Dungeon Adventure! I\'m your Game Master, and I can\'t wait to find out what adventure we\'re going to have!'
];
// These prompts are used when starting character creation
const CHARACTER_PROMPTS = [
	'Let\'s get started by creating a character. What do you want to be called?'
];
// This is used to verify the Game Master heard the player's name correctly
const VERIFY_PLAYER_NAME = 'Okay, so you want me to call you ';
// This is used when the Game Master didn't recognize a player name
const VERIFY_WEIRD_PLAYER_NAME = 'That\'s a strange name. So you wanted me to call you ';
// Used when a player says the Game Master misheard their name
const PLAYER_NAME_NOT_RIGHT = [
	'I\'m sorry, let\'s try that again. What did you want me to call you?',
	'Okay, let\'s try one more time. What do you want your character to be called?'
];
// Used during stat generation
const START_GENERATE_STATS = 'It\'s now time to generate your stats. These stats range from 0 to 20.';
// Used during stat generation or stat lookup
const STRENGTH_STAT = 'Your strength stat is ';
// Used during stat generation or stat lookup
const DEXTERITY_STAT = 'Your dexterity stat is ';
// Used during stat generation or stat lookup
const INTELLIGENCE_STAT = 'Your intelligence stat is ';
// Used to confirm the player is ready to start their game
const READY_FOR_ADVENTURE = 'Are you ready to begin your adventure?';

const CONFUSED = [
	'I\'m sorry, but I didn\'t catch that. Can you say it again?'
];

/// Actions
// This action is sent when the player first opens the game
const WELCOME_ACTION = 'input.welcome';
const GET_NAME_ACTION = 'get_player_name';
const GET_WEIRD_NAME_ACTION = 'get_weird_player_name';
const GENERATE_ANSWER_ACTION = 'generate_answer';
const CHECK_GUESS_ACTION = 'check_guess';
const VERIFY_NAME_NO_ACTION = 'verify_character_name_no';
const VERIFY_NAME_YES_ACTION = 'verify_character_name_yes';

const CONFUSED_ACTION = 'input.unknown';

/// Contexts
// This context is used when a user is picking a name
const NAME_CONTEXT = 'character_name';
const VERIFY_NAME_CONTEXT = 'verify_character_name';
const READY_FOR_ADVENTURE_CONTEXT = 'ready_for_adventure';

// Utility function to pick prompts
function getRandomPrompt(array) {
	return array[Math.floor(Math.random() * (array.length))];
}

function getRandomNumber(min, max) {
	return Math.floor(Math.random() * (max - min + 1)) + min;
}

app.post('/', function (request, response) {
	console.log('headers: ' + JSON.stringify(request.headers));
	console.log('body: ' + JSON.stringify(request.body));

	const assistant = new ApiAiAssistant({ request: request, response: response });
	let actionMap = new Map();

	// Greet the player
	// After greeting them, ask them to create a character
	function greet(assistant)
	{
		// Greet the player
		let greeting = getRandomPrompt(GREETING_PROMPTS);
		// Ask them to make a character
		greeting += '\n' + getRandomPrompt(CHARACTER_PROMPTS);

		setContext(assistant, NAME_CONTEXT, 5);

		assistant.data.lastAction = WELCOME_ACTION;
		assistant.ask(greeting);
	}
	actionMap.set(WELCOME_ACTION, greet);

	// Get the player's name and store it
	// Then, ask them if the name is correct
	function getPlayerName(assistant)
	{
		let playerName = assistant.getArgument('given-name');
		assistant.data.playerName = playerName;
		let verification = VERIFY_PLAYER_NAME + playerName + "?";

		setContext(assistant, VERIFY_NAME_CONTEXT, 2);
		assistant.data.lastAction = GET_NAME_ACTION;
		assistant.ask(verification);
	}
	actionMap.set(GET_NAME_ACTION, getPlayerName);

	// This is used as a fallback if we don't recognize a player's name
	function getWeirdPlayerName(assistant) {
		let playerName = assistant.getRawInput();
		assistant.data.playerName = playerName;

		let verification = VERIFY_WEIRD_PLAYER_NAME + playerName + "?";

		setContext(assistant, VERIFY_NAME_CONTEXT, 2);
		assistant.data.lastAction = GET_NAME_ACTION;
		assistant.ask(verification);
	}
	actionMap.set(GET_WEIRD_NAME_ACTION, getWeirdPlayerName);

	// Player said we didn't get their name right
	// Try it one more time
	function retryCharacterName(assistant)
	{
		let retryName = getRandomPrompt(PLAYER_NAME_NOT_RIGHT);
		assistant.data.playerName = undefined;

		setContext(assistant, NAME_CONTEXT, 5);

		assistant.data.lastAction = VERIFY_NAME_NO_ACTION;
		assistant.ask(retryName);
	}
	actionMap.set(VERIFY_NAME_NO_ACTION, retryCharacterName);

	// If the player says their name is correct, move on to next stage of character creation
	// Generate each stat and tell the player what the stats are
	// Then ask if they are ready to go
	function generatePlayerStats(assistant)
	{
		let statString = 'Alright, ' + assistant.data.playerName + '!\n';

		assistant.data.strengthStat = getRandomNumber(0, 20);
		assistant.data.dexterityStat = getRandomNumber(0, 20);
		assistant.data.intelligenceStat = getRandomNumber(0, 20);

		statString += STRENGTH_STAT + assistant.data.strengthStat + '. \n';
		statString += DEXTERITY_STAT + assistant.data.dexterityStat + '. \n';
		statString += INTELLIGENCE_STAT + assistant.data.intelligenceStat + '. \n';

		statString += READY_FOR_ADVENTURE;

		setContext(assistant, READY_FOR_ADVENTURE_CONTEXT, 5);

		assistant.data.lastAction = VERIFY_NAME_YES_ACTION;
		assistant.ask(statString);
	}
	actionMap.set(VERIFY_NAME_YES_ACTION, generatePlayerStats);

	// This is used when the Game Master has absolutely no idea what the player just said
	function unknownPlayerInput(assistant)
	{
		// If we were talking about names last, that might be a name
		if (assistant.data.lastContext == NAME_CONTEXT)
		{
			getWeirdPlayerName(assistant);
		}
		else
		{
			// No idea
			assistant.tell(getRandomPrompt(CONFUSED));
		}
	}
	actionMap.set(CONFUSED_ACTION, unknownPlayerInput);

	assistant.handleRequest(actionMap);

	// Helpers
	function setContext(assistant, context, length)
	{
		assistant.setContext(context, length);
		assistant.data.lastContext = context;
	}
});

// Start the server
var server = app.listen(app.get('port'), function () {
	console.log('App listening on port %s', server.address().port);
	console.log('Press Ctrl+C to quit.');
});
<commit_msg>Added actual line about stats to app.js.<commit_after>'use strict';

// Enable actions client library debugging
process.env.DEBUG = 'actions-on-google:*';

let ApiAiAssistant = require('actions-on-google').ApiAiAssistant;
let express = require('express');
let bodyParser = require('body-parser');

let app = express();
app.set('port', (process.env.PORT || 8080));
app.use(bodyParser.json({ type: 'application/json' }));

/// Prompts
// These prompts are used to greet the player when they start the game
const GREETING_PROMPTS = [
	'Hello, and welcome to Dungeon Adventure! I\'ll be your Game Master tonight! Hopefully you\'re ready for some adventure!',
	'Welcome to Dungeon Adventure! I\'ll be your Game Master, and I hope you\'re ready to go on an adventure, because I sure am!',
	'It\'s good to see you! I\'m your Game Master, and we\'re about to go on a Dungeon Adventure!',
	'Hey there! Welcome to Dungeon Adventure! I\'m your Game Master, and I can\'t wait to find out what adventure we\'re going to have!'
];
// These prompts are used when starting character creation
const CHARACTER_PROMPTS = [
	'Let\'s get started by creating a character. What do you want to be called?'
];
// This is used to verify the Game Master heard the player's name correctly
const VERIFY_PLAYER_NAME = 'Okay, so you want me to call you ';
// This is used when the Game Master didn't recognize a player name
const VERIFY_WEIRD_PLAYER_NAME = 'That\'s a strange name. So you wanted me to call you ';
// Used when a player says the Game Master misheard their name
const PLAYER_NAME_NOT_RIGHT = [
	'I\'m sorry, let\'s try that again. What did you want me to call you?',
	'Okay, let\'s try one more time. What do you want your character to be called?'
];
// Used during stat generation
const START_GENERATE_STATS = 'It\'s now time to generate your stats. These stats range from 0 to 20.';
// Used during stat generation or stat lookup
const STRENGTH_STAT = 'Your strength stat is ';
// Used during stat generation or stat lookup
const DEXTERITY_STAT = 'Your dexterity stat is ';
// Used during stat generation or stat lookup
const INTELLIGENCE_STAT = 'Your intelligence stat is ';
// Used to confirm the player is ready to start their game
const READY_FOR_ADVENTURE = 'Are you ready to begin your adventure?';

const CONFUSED = [
	'I\'m sorry, but I didn\'t catch that. Can you say it again?'
];

/// Actions
// This action is sent when the player first opens the game
const WELCOME_ACTION = 'input.welcome';
const GET_NAME_ACTION = 'get_player_name';
const GET_WEIRD_NAME_ACTION = 'get_weird_player_name';
const GENERATE_ANSWER_ACTION = 'generate_answer';
const CHECK_GUESS_ACTION = 'check_guess';
const VERIFY_NAME_NO_ACTION = 'verify_character_name_no';
const VERIFY_NAME_YES_ACTION = 'verify_character_name_yes';

const CONFUSED_ACTION = 'input.unknown';

/// Contexts
// This context is used when a user is picking a name
const NAME_CONTEXT = 'character_name';
const VERIFY_NAME_CONTEXT = 'verify_character_name';
const READY_FOR_ADVENTURE_CONTEXT = 'ready_for_adventure';

// Utility function to pick prompts
function getRandomPrompt(array) {
	return array[Math.floor(Math.random() * (array.length))];
}

function getRandomNumber(min, max) {
	return Math.floor(Math.random() * (max - min + 1)) + min;
}

app.post('/', function (request, response) {
	console.log('headers: ' + JSON.stringify(request.headers));
	console.log('body: ' + JSON.stringify(request.body));

	const assistant = new ApiAiAssistant({ request: request, response: response });
	let actionMap = new Map();

	// Greet the player
	// After greeting them, ask them to create a character
	function greet(assistant)
	{
		// Greet the player
		let greeting = getRandomPrompt(GREETING_PROMPTS);
		// Ask them to make a character
		greeting += '\n' + getRandomPrompt(CHARACTER_PROMPTS);

		setContext(assistant, NAME_CONTEXT, 5);

		assistant.data.lastAction = WELCOME_ACTION;
		assistant.ask(greeting);
	}
	actionMap.set(WELCOME_ACTION, greet);
// Get the player's name and store it
	// Then, ask them if the name is correct
	function getPlayerName(assistant)
	{
		let playerName = assistant.getArgument('given-name');
		assistant.data.playerName = playerName;
		let verification = VERIFY_PLAYER_NAME + playerName + "?";

		setContext(assistant, VERIFY_NAME_CONTEXT, 2);
		assistant.data.lastAction = GET_NAME_ACTION;
		assistant.ask(verification);
	}
	actionMap.set(GET_NAME_ACTION, getPlayerName);

	// This is used as a fallback if we don't recognize a player's name
	function getWeirdPlayerName(assistant) {
		let playerName = assistant.getRawInput();
		assistant.data.playerName = playerName;

		let verification = VERIFY_WEIRD_PLAYER_NAME + playerName + "?";

		setContext(assistant, VERIFY_NAME_CONTEXT, 2);
		assistant.data.lastAction = GET_NAME_ACTION;
		assistant.ask(verification);
	}
	actionMap.set(GET_WEIRD_NAME_ACTION, getWeirdPlayerName);

	// Player said we didn't get their name right
	// Try it one more time
	function retryCharacterName(assistant)
	{
		let retryName = getRandomPrompt(PLAYER_NAME_NOT_RIGHT);
		assistant.data.playerName = undefined;

		setContext(assistant, NAME_CONTEXT, 5);

		assistant.data.lastAction = VERIFY_NAME_NO_ACTION;
		assistant.ask(retryName);
}
	actionMap.set(VERIFY_NAME_NO_ACTION, retryCharacterName);

	// If the player says their name is correct, move on to next stage of character creation
	// Generate each stat and tell the player what the stats are
	// Then ask if they are ready to go
	function generatePlayerStats(assistant)
	{
		let statString = 'Alright, ' + assistant.data.playerName + '! ' + START_GENERATE_STATS + '\n';

		assistant.data.strengthStat = getRandomNumber(0, 20);
		assistant.data.dexterityStat = getRandomNumber(0, 20);
		assistant.data.intelligenceStat = getRandomNumber(0, 20);

		statString += STRENGTH_STAT + assistant.data.strengthStat + '. \n';
		statString += DEXTERITY_STAT + assistant.data.dexterityStat + '. \n';
		statString += INTELLIGENCE_STAT + assistant.data.intelligenceStat + '. \n';

		statString += READY_FOR_ADVENTURE;

		setContext(assistant, READY_FOR_ADVENTURE_CONTEXT, 5);

		assistant.data.lastAction = VERIFY_NAME_YES_ACTION;
		assistant.ask(statString);
	}
	actionMap.set(VERIFY_NAME_YES_ACTION, generatePlayerStats);

	// This is used when the Game Master has absolutely no idea what the player just said
	function unknownPlayerInput(assistant)
	{
		// If we were talking about names last, that might be a name
		if (assistant.data.lastContext == NAME_CONTEXT)
		{
			getWeirdPlayerName(assistant);
		}
		else
		{
			// No idea
			assistant.tell(getRandomPrompt(CONFUSED));
		}
	}
	actionMap.set(CONFUSED_ACTION, unknownPlayerInput);

	assistant.handleRequest(actionMap);

	// Helpers
	function setContext(assistant, context, length)
	{
		assistant.setContext(context, length);
		assistant.data.lastContext = context;
	}
});

// Start the server
var server = app.listen(app.get('port'), function () {
	console.log('App listening on port %s', server.address().port);
	console.log('Press Ctrl+C to quit.');
});
<|endoftext|>


<commit_before>var express = require('express')
  , http = require('http')
  , path = require('path')
  , routes = require('./routes')
  , db = require('./db')
  , auth = require('./auth')
  , util = require('./util')
  , async = require('async')
  , fundmanager = require('./fundmanager')
  , fs = require('fs')
  , resize = require('./resize')

var app = express();

var HTTP_PORT = 8080; // main webserver
var WS_PORT = 8081; // websockets for notifications

app.configure(function(){
	// all environments
	app.set('views', __dirname + '/views');
	app.set('view engine', 'jade');

	app.disable('x-powered-by');
	app.use(express.cookieParser());
	app.use(express.logger('dev'));
	app.use(express.bodyParser({
		uploadDir: './tmp'
	}));
	app.use(function(req, res, next) {
		var discardOriginalFile = function() {
			if (!req.files) return;

			for (name in req.files) {
				fs.unlinkSync(req.files[name].path);
			}
		}

		if (req.url.match(/^\/uploadimage/)) {
			if (!req.files.file) {
				discardOriginalFile();
				res.statusCode = 500;
				res.send("500 Internal Server Error: No file submitted.");
				return;
			}

			var path = "/" + req.files.file.path;
			var newname = util.token();

			async.parallel({
				orig: function(cb) {
					resize(path, "/public/uploads/" + newname + "_orig", false, false, cb)
				},
				thumb32: function(cb) {
					resize(path, "/public/uploads/" + newname + "_32", 32, 32, cb)
				},
				thumb55: function(cb) {
					resize(path, "/public/uploads/" + newname + "_55", 55, 55, cb)
				},
				thumb64: function(cb) {
					resize(path, "/public/uploads/" + newname + "_64", 64, 64, cb)
				},
				thumb140: function(cb) {
					resize(path, "/public/uploads/" + newname + "_140", 140, 140, cb)
				}
			}, function(err, results) {
				if (err) {
					console.log(err);
					discardOriginalFile();
					res.statusCode = 500;
					res.send("500 Internal Server Error: Invalid file format.");
					return;
				}

				for (name in results) {
					results[name] = results[name].replace("/public", "")
				}

				db.query("INSERT INTO imageuploads (orig, thumb32, thumb55, thumb64, thumb140, ip) values (?, ?, ?, ?, ?, ?)",
					[results.orig, results.thumb32, results.thumb55, results.thumb64, results.thumb140, util.ip(req)],
					function(err, r) {
						if (err) {
							discardOriginalFile();
							res.statusCode = 500;
							res.send("500 Internal Server Error: Couldn't save attachment.");
							return;
						}

						results.id = r.insertId;

						discardOriginalFile();
						res.send(JSON.stringify(results));
					}
				);
			})
		} else {
			discardOriginalFile();
			next();
		}
	})
	app.use(express.methodOverride());
	app.use(function(req, res, next) {
		var method = req.method;

		if (method == "POST") {
			if ((!util.isValidToken(req.body.csrf)) || (req.body.csrf != req.cookies.csrf)) {
				res.statusCode = 403;
				res.send("403 Forbidden: CSRF validation failure.");
			} else {
				next();
			}
		} else {
			next();
		}
	})
	app.use(function(req, res, next) {
		if (!util.isValidToken(req.cookies.csrf)) {
			res.cookie('csrf', util.token(), {maxAge: 94636000000, httpOnly:false})
		}
		next();
	})
	app.use(util.verifyRecaptcha);
	app.use(function(req, res, next) {
		res.locals._nl2br_escape = util.nl2br_escape;
		res.locals._quote = util.quote;
		res.locals._isset = util.isset;
		res.locals._timeSince = util.timeSince;
		res.locals._timeUntil = util.timeUntil;
		res.locals._attachment = util.attachment;
		res.locals._slug = util.slug;
		res.locals._repeat = util.repeat;

		if (req.url.substring(0, 6) == '/ajax/') {
			req.url = req.url.substring(5);
			res.locals.__REQUEST_TYPE = 'ajax';
			res.locals.__REQUEST_URL = req.url;
		} else {
			res.locals.__REQUEST_TYPE = 'normal';
			res.locals.__REQUEST_URL = req.url;
		}

		next();
	});

	app.use(express.static(path.join(__dirname, 'public'), {
		maxAge: 86400000
	}));
	app.use(app.router);

	app.use(function(err, req, res, next) {
		if (!err) next();

		console.log(err);
		res.statusCode = 500;
		res.send("<script>notifybox(\"We're sorry, there was an error with your request. :(\");</script>");
	});
});

/// ROUTEWARE:
// auth.require - require authentication
// auth.build - build authentication
// util.prepareLayout - prepare layout (navbar, footer) if non-ajax request // todo consider placing this on everything
//////////////////////////////////////////////////////////////////////////////////////

app.get('/health', util.prepareLayout, function(req, res) {
	util.redirect(req, res, "http://www.reddit.com/r/gonewild+nsfw+RealGirls+ass+BustyPetite+girlsinyogapants+rule34+dirtysmall+celebnsfw+AsianHotties+asstastic+60fpsporn+datgap+WtSSTaDaMiT+AmateurArchives+IndianBabes+assinthong+buttplug+nsfwCelebArchive+latinas+Exxxtras+KateeOwen+Pegging+Anjelica_Ebbi+tight_shorts+celebsnaked+TheUnderbun+Ohlympics+leggingsgonewild+Sashagrey+tightsqueeze+CelebrityButts+SexyGirlsInBoots+nsfwcelebgifs+nsfwasmr+HighResASS+HungryButts+kpopfap+WoahPoon+twerking+MalenaMorgan+LatinasGW+GirlsInMessyRooms+AssOnTheGlass+asianbabes+StomachDownFeetUp+CarlottaChampagne+Maria_Ozawa+CarolSeleme+wacrover", true);
});

// index
app.get('/', util.prepareLayout, routes.index);

app.get('/admin', auth.require, util.prepareLayout, routes.admin.front);
app.get('/admin/womp', auth.require, util.prepareLayout, routes.admin.womp);
app.post('/admin/womp/delete', auth.require, util.prepareLayout, routes.admin.wompdelete);
app.post('/admin/womp/add', auth.require, util.prepareLayout, routes.admin.wompadd);

// map of teamspeak usage by country
app.get('/map', util.prepareLayout, routes.map);

// church fund
app.get('/fund', util.prepareLayout, routes.fund);

// mail authentication HMAC
app.get('/mail', auth.build, util.prepareLayout, routes.mail);

// testimonials / quotes
app.get('/quotes', auth.build, util.prepareLayout, routes.quotes.show);
app.post('/quotes/delete', auth.require, util.prepareLayout, routes.quotes.delete);

// grants page
app.get('/grants/:type?/:page?', auth.build, util.prepareLayout, routes.grants.show);
app.post('/grants', auth.build, util.prepareLayout, routes.grants.submitgrant);
app.post('/grants/delete', auth.require, routes.grants.delete);
app.post('/grants/approve', auth.require, routes.grants.approve);
app.post('/grants/reject', auth.require, routes.grants.reject);

// club system
app.get('/clubs', util.prepareLayout, routes.clubs.list);
app.get('/club/:id', auth.build, util.prepareLayout, routes.clubs.view)
app.post('/club/:id/join', util.prepareLayout, auth.require, routes.clubs.join)
app.post('/club/:id/edit', util.prepareLayout, auth.require, routes.clubs.edit)
app.get('/club/:id/discussion', util.prepareLayout, auth.require, routes.clubs.discussion)
app.post('/club/:id/ban', util.prepareLayout, auth.require, routes.clubs.ban)

// blog system
app.post('/blog/:id/submitpost', auth.require, routes.blog.submitpost);
app.post('/blog/:id/setimage', auth.require, routes.blog.setimage);
app.get('/blog/:id/newpost', util.prepareLayout, auth.require, routes.blog.newpost);
app.get('/blog/:id/:page?', util.prepareLayout, auth.build, routes.blog.show);
app.get('/post/:id', util.prepareLayout, auth.build, routes.blogpost.show);
app.post('/post/:id/edit', auth.require, routes.blogpost.editpost);
app.post('/post/:id/delete', auth.require, routes.blogpost.deletepost);
app.get('/blogs', util.prepareLayout, routes.blog.list);

// comments system
app.post('/comment/:id/edit', auth.require, routes.comments.edit);
app.post('/comment/submit', auth.require, routes.comments.submit);
app.post('/comment/:id/delete', auth.require, routes.comments.delete);

// gallery system
app.get(/^\/gallery(\/([0-9]+)?)?$/, auth.build, util.prepareLayout, routes.gallery.show);
app.get('/viewimage/:id', auth.build, util.prepareLayout, routes.gallery.viewimage);
app.post('/gallery/upload', auth.require, util.prepareLayout, routes.gallery.upload);

// inbox system
app.get('/inbox/:type', util.prepareLayout, auth.require, routes.notifications.inbox);

// user centric stuff
app.get('/register', util.prepareLayout, routes.user.register);
app.post('/register', util.prepareLayout, auth.build, routes.user.register_submit);
app.get('/logout', util.prepareLayout, routes.user.logout);
app.get('/login', util.prepareLayout, routes.user.login);
app.post('/login', util.prepareLayout, routes.user.login_submit)
app.get('/verify/:code', util.prepareLayout, routes.user.verify)
app.get('/verify', auth.require, util.prepareLayout, routes.user.verify_form)
app.post('/verify', auth.require, util.prepareLayout, routes.user.submit_verify_form)
app.get('/forgotpassword', util.prepareLayout, routes.user.forgot);
app.post('/forgotpassword', util.prepareLayout, routes.user.forgot_submit);
app.get('/reset/:code', util.prepareLayout, routes.user.reset);
app.post('/reset/:code', util.prepareLayout, routes.user.reset_submit);

app.get('/panel', util.prepareLayout, auth.require, routes.user.panel);
app.post('/panel/setavatar', auth.require, routes.user.setavatar);
app.post('/panel/changeemail', auth.require, routes.user.changeemail);
app.post('/panel/changepass', auth.require, routes.user.changepass);

app.get('/link-teamspeak', auth.require, util.prepareLayout, routes.user.link_teamspeak);
app.post('/link-teamspeak', auth.require, util.prepareLayout, routes.user.submit_link_teamspeak);

app.get(/\.(gif|jpg|jpeg|png|css|js)$/, function(req, res) {
	res.statusCode = 404;
	res.send("404 Not Found");
})

app.get("*", util.prepareLayout, function(req, res) {
	res.statusCode = 404;
	res.render("404", {title:"404"});
})

// TODO: refactor so that much of this logic is in separate components
http.createServer(app).listen(HTTP_PORT, "localhost", function(){
  console.log('Express server listening on port ' + HTTP_PORT + '...');

  var io = require('socket.io').listen(http.createServer().listen(WS_PORT, 'localhost'))

  var users = [];

  io.sockets.on('connection', function(socket) {
  	var ip = socket.request.headers['x-real-ip'];
  	var active = true;

  	console.log("WebSocket connection from IP " + ip)

  	var $COOKIE = (socket.handshake.headers.cookie || '').split(/;\s*/).reduce(function(re, c) {
	  var tmp = c.match(/([^=]+)=(.*)/);
	  if (tmp) re[tmp[1]] = unescape(tmp[2]);
	  return re;
	}, {});

	auth.verify(String($COOKIE.email), String($COOKIE.pass), function(err, userdata) {
		if (err) return; // TODO: ?

		if (!userdata) return; // TODO: ?

		function f(repeat) {
			if (!active) return;

			routes.notifications.getNum(userdata.id, function(err, result) {
				if (err) return; // TODO: ?

				db.query("SELECT u.teamspeak_uid,t.uid FROM teamspeak_users t LEFT JOIN users u on 1 WHERE t.ip=? AND u.id=?", [ip, userdata.id], function(err, _results) {
					if (err) return; // TODO: ?

					if (_results.length > 0) {
						match = _results[0];

						if (match.uid != match.teamspeak_uid) {
							result.push({type:"link_teamspeak"});
						}
					}

					socket.emit('newNotifications', result)
				})
			})

			if (repeat)
				setTimeout(function() {f(repeat);}, 10000);
		};
		f(true);

		socket.on('fetch', function() {
			f(false);
		})
	})

  	socket.on('disconnect', function() {
  		active = false;
  	})
  })

  // bitcoin fund manager
  fundmanager(io);
});
<commit_msg>Added subreddit to health.<commit_after>var express = require('express')
  , http = require('http')
  , path = require('path')
  , routes = require('./routes')
  , db = require('./db')
  , auth = require('./auth')
  , util = require('./util')
  , async = require('async')
  , fundmanager = require('./fundmanager')
  , fs = require('fs')
  , resize = require('./resize')

var app = express();

var HTTP_PORT = 8080; // main webserver
var WS_PORT = 8081; // websockets for notifications

app.configure(function(){
	// all environments
	app.set('views', __dirname + '/views');
	app.set('view engine', 'jade');

	app.disable('x-powered-by');
	app.use(express.cookieParser());
	app.use(express.logger('dev'));
	app.use(express.bodyParser({
		uploadDir: './tmp'
	}));
	app.use(function(req, res, next) {
		var discardOriginalFile = function() {
			if (!req.files) return;

			for (name in req.files) {
				fs.unlinkSync(req.files[name].path);
			}
		}

		if (req.url.match(/^\/uploadimage/)) {
			if (!req.files.file) {
				discardOriginalFile();
				res.statusCode = 500;
				res.send("500 Internal Server Error: No file submitted.");
				return;
			}

			var path = "/" + req.files.file.path;
			var newname = util.token();

			async.parallel({
				orig: function(cb) {
					resize(path, "/public/uploads/" + newname + "_orig", false, false, cb)
				},
				thumb32: function(cb) {
					resize(path, "/public/uploads/" + newname + "_32", 32, 32, cb)
				},
				thumb55: function(cb) {
					resize(path, "/public/uploads/" + newname + "_55", 55, 55, cb)
				},
				thumb64: function(cb) {
					resize(path, "/public/uploads/" + newname + "_64", 64, 64, cb)
				},
				thumb140: function(cb) {
					resize(path, "/public/uploads/" + newname + "_140", 140, 140, cb)
				}
			}, function(err, results) {
				if (err) {
					console.log(err);
					discardOriginalFile();
					res.statusCode = 500;
					res.send("500 Internal Server Error: Invalid file format.");
					return;
				}

				for (name in results) {
					results[name] = results[name].replace("/public", "")
				}

				db.query("INSERT INTO imageuploads (orig, thumb32, thumb55, thumb64, thumb140, ip) values (?, ?, ?, ?, ?, ?)",
					[results.orig, results.thumb32, results.thumb55, results.thumb64, results.thumb140, util.ip(req)],
					function(err, r) {
						if (err) {
							discardOriginalFile();
							res.statusCode = 500;
							res.send("500 Internal Server Error: Couldn't save attachment.");
							return;
						}

						results.id = r.insertId;

						discardOriginalFile();
						res.send(JSON.stringify(results));
					}
				);
			})
		} else {
			discardOriginalFile();
			next();
		}
	})
	app.use(express.methodOverride());
	app.use(function(req, res, next) {
		var method = req.method;

		if (method == "POST") {
			if ((!util.isValidToken(req.body.csrf)) || (req.body.csrf != req.cookies.csrf)) {
				res.statusCode = 403;
				res.send("403 Forbidden: CSRF validation failure.");
			} else {
				next();
			}
		} else {
			next();
		}
	})
	app.use(function(req, res, next) {
		if (!util.isValidToken(req.cookies.csrf)) {
			res.cookie('csrf', util.token(), {maxAge: 94636000000, httpOnly:false})
		}
		next();
	})
	app.use(util.verifyRecaptcha);
	app.use(function(req, res, next) {
		res.locals._nl2br_escape = util.nl2br_escape;
		res.locals._quote = util.quote;
		res.locals._isset = util.isset;
		res.locals._timeSince = util.timeSince;
		res.locals._timeUntil = util.timeUntil;
		res.locals._attachment = util.attachment;
		res.locals._slug = util.slug;
		res.locals._repeat = util.repeat;

		if (req.url.substring(0, 6) == '/ajax/') {
			req.url = req.url.substring(5);
			res.locals.__REQUEST_TYPE = 'ajax';
			res.locals.__REQUEST_URL = req.url;
		} else {
			res.locals.__REQUEST_TYPE = 'normal';
			res.locals.__REQUEST_URL = req.url;
		}

		next();
	});

	app.use(express.static(path.join(__dirname, 'public'), {
		maxAge: 86400000
	}));
	app.use(app.router);

	app.use(function(err, req, res, next) {
		if (!err) next();

		console.log(err);
		res.statusCode = 500;
		res.send("<script>notifybox(\"We're sorry, there was an error with your request. :(\");</script>");
	});
});

/// ROUTEWARE:
// auth.require - require authentication
// auth.build - build authentication
// util.prepareLayout - prepare layout (navbar, footer) if non-ajax request // todo consider placing this on everything
//////////////////////////////////////////////////////////////////////////////////////

app.get('/health', util.prepareLayout, function(req, res) {
	util.redirect(req, res, "http://www.reddit.com/r/gonewild+nsfw+RealGirls+ass+BustyPetite+girlsinyogapants+rule34+dirtysmall+celebnsfw+AsianHotties+asstastic+60fpsporn+datgap+WtSSTaDaMiT+AmateurArchives+IndianBabes+assinthong+buttplug+nsfwCelebArchive+latinas+Exxxtras+KateeOwen+Pegging+Anjelica_Ebbi+tight_shorts+celebsnaked+TheUnderbun+Ohlympics+leggingsgonewild+Sashagrey+tightsqueeze+CelebrityButts+SexyGirlsInBoots+nsfwcelebgifs+nsfwasmr+HighResASS+HungryButts+kpopfap+WoahPoon+twerking+MalenaMorgan+LatinasGW+GirlsInMessyRooms+AssOnTheGlass+asianbabes+StomachDownFeetUp+CarlottaChampagne+Maria_Ozawa+CarolSeleme+wacrover+girlsfinishingthejob", true);
});

// index
app.get('/', util.prepareLayout, routes.index);

app.get('/admin', auth.require, util.prepareLayout, routes.admin.front);
app.get('/admin/womp', auth.require, util.prepareLayout, routes.admin.womp);
app.post('/admin/womp/delete', auth.require, util.prepareLayout, routes.admin.wompdelete);
app.post('/admin/womp/add', auth.require, util.prepareLayout, routes.admin.wompadd);

// map of teamspeak usage by country
app.get('/map', util.prepareLayout, routes.map);

// church fund
app.get('/fund', util.prepareLayout, routes.fund);

// mail authentication HMAC
app.get('/mail', auth.build, util.prepareLayout, routes.mail);

// testimonials / quotes
app.get('/quotes', auth.build, util.prepareLayout, routes.quotes.show);
app.post('/quotes/delete', auth.require, util.prepareLayout, routes.quotes.delete);

// grants page
app.get('/grants/:type?/:page?', auth.build, util.prepareLayout, routes.grants.show);
app.post('/grants', auth.build, util.prepareLayout, routes.grants.submitgrant);
app.post('/grants/delete', auth.require, routes.grants.delete);
app.post('/grants/approve', auth.require, routes.grants.approve);
app.post('/grants/reject', auth.require, routes.grants.reject);

// club system
app.get('/clubs', util.prepareLayout, routes.clubs.list);
app.get('/club/:id', auth.build, util.prepareLayout, routes.clubs.view)
app.post('/club/:id/join', util.prepareLayout, auth.require, routes.clubs.join)
app.post('/club/:id/edit', util.prepareLayout, auth.require, routes.clubs.edit)
app.get('/club/:id/discussion', util.prepareLayout, auth.require, routes.clubs.discussion)
app.post('/club/:id/ban', util.prepareLayout, auth.require, routes.clubs.ban)

// blog system
app.post('/blog/:id/submitpost', auth.require, routes.blog.submitpost);
app.post('/blog/:id/setimage', auth.require, routes.blog.setimage);
app.get('/blog/:id/newpost', util.prepareLayout, auth.require, routes.blog.newpost);
app.get('/blog/:id/:page?', util.prepareLayout, auth.build, routes.blog.show);
app.get('/post/:id', util.prepareLayout, auth.build, routes.blogpost.show);
app.post('/post/:id/edit', auth.require, routes.blogpost.editpost);
app.post('/post/:id/delete', auth.require, routes.blogpost.deletepost);
app.get('/blogs', util.prepareLayout, routes.blog.list);

// comments system
app.post('/comment/:id/edit', auth.require, routes.comments.edit);
app.post('/comment/submit', auth.require, routes.comments.submit);
app.post('/comment/:id/delete', auth.require, routes.comments.delete);

// gallery system
app.get(/^\/gallery(\/([0-9]+)?)?$/, auth.build, util.prepareLayout, routes.gallery.show);
app.get('/viewimage/:id', auth.build, util.prepareLayout, routes.gallery.viewimage);
app.post('/gallery/upload', auth.require, util.prepareLayout, routes.gallery.upload);

// inbox system
app.get('/inbox/:type', util.prepareLayout, auth.require, routes.notifications.inbox);

// user centric stuff
app.get('/register', util.prepareLayout, routes.user.register);
app.post('/register', util.prepareLayout, auth.build, routes.user.register_submit);
app.get('/logout', util.prepareLayout, routes.user.logout);
app.get('/login', util.prepareLayout, routes.user.login);
app.post('/login', util.prepareLayout, routes.user.login_submit)
app.get('/verify/:code', util.prepareLayout, routes.user.verify)
app.get('/verify', auth.require, util.prepareLayout, routes.user.verify_form)
app.post('/verify', auth.require, util.prepareLayout, routes.user.submit_verify_form)
app.get('/forgotpassword', util.prepareLayout, routes.user.forgot);
app.post('/forgotpassword', util.prepareLayout, routes.user.forgot_submit);
app.get('/reset/:code', util.prepareLayout, routes.user.reset);
app.post('/reset/:code', util.prepareLayout, routes.user.reset_submit);

app.get('/panel', util.prepareLayout, auth.require, routes.user.panel);
app.post('/panel/setavatar', auth.require, routes.user.setavatar);
app.post('/panel/changeemail', auth.require, routes.user.changeemail);
app.post('/panel/changepass', auth.require, routes.user.changepass);

app.get('/link-teamspeak', auth.require, util.prepareLayout, routes.user.link_teamspeak);
app.post('/link-teamspeak', auth.require, util.prepareLayout, routes.user.submit_link_teamspeak);

app.get(/\.(gif|jpg|jpeg|png|css|js)$/, function(req, res) {
	res.statusCode = 404;
	res.send("404 Not Found");
})

app.get("*", util.prepareLayout, function(req, res) {
	res.statusCode = 404;
	res.render("404", {title:"404"});
})

// TODO: refactor so that much of this logic is in separate components
http.createServer(app).listen(HTTP_PORT, "localhost", function(){
  console.log('Express server listening on port ' + HTTP_PORT + '...');

  var io = require('socket.io').listen(http.createServer().listen(WS_PORT, 'localhost'))

  var users = [];

  io.sockets.on('connection', function(socket) {
  	var ip = socket.request.headers['x-real-ip'];
  	var active = true;

  	console.log("WebSocket connection from IP " + ip)

  	var $COOKIE = (socket.handshake.headers.cookie || '').split(/;\s*/).reduce(function(re, c) {
	  var tmp = c.match(/([^=]+)=(.*)/);
	  if (tmp) re[tmp[1]] = unescape(tmp[2]);
	  return re;
	}, {});

	auth.verify(String($COOKIE.email), String($COOKIE.pass), function(err, userdata) {
		if (err) return; // TODO: ?

		if (!userdata) return; // TODO: ?

		function f(repeat) {
			if (!active) return;

			routes.notifications.getNum(userdata.id, function(err, result) {
				if (err) return; // TODO: ?

				db.query("SELECT u.teamspeak_uid,t.uid FROM teamspeak_users t LEFT JOIN users u on 1 WHERE t.ip=? AND u.id=?", [ip, userdata.id], function(err, _results) {
					if (err) return; // TODO: ?

					if (_results.length > 0) {
						match = _results[0];

						if (match.uid != match.teamspeak_uid) {
							result.push({type:"link_teamspeak"});
						}
					}

					socket.emit('newNotifications', result)
				})
			})

			if (repeat)
				setTimeout(function() {f(repeat);}, 10000);
		};
		f(true);

		socket.on('fetch', function() {
			f(false);
		})
	})

  	socket.on('disconnect', function() {
  		active = false;
  	})
  })

  // bitcoin fund manager
  fundmanager(io);
});
<|endoftext|>


<commit_before>const channel_name = 'dl.channel.votes';
const redis = require('redis');
var port = process.env.PORT || 3000;
const io = require('socket.io').listen(port);

// Heroku Cedar stack does not support Websockets yet, force long poll
if(process.env.HEROKU_DEPLOY) {
    io.configure(function () {
        io.set("transports", ["xhr-polling"]);
        io.set("polling duration", 10);
    });
}

io.sockets.on('connection', function(client) {

    const sub = redis.createClient(); //create a new subscriber connection

    //Heroku production authentication
    if (process.env.REDISTOGO_URL) {
        var rtg = require("url").parse(process.env.REDISTOGO_URL);
        sub = redis.createClient(rtg.port, rtg.hostname);
        sub.auth(rtg.auth.split(":")[1]);
    }

    sub.subscribe(channel_name);  //listen for messages published on this channel

    client.on('join', function(session_id) {
        client.set('vote_session', session_id);
        client.join(session_id);
        //console.log("user joined /"+session_id);
    });

    sub.on("message", function(channel, session) {
        var session_id = JSON.parse(session).uuid; //this is a waste, there's probably a way to avoid it
        client.get('vote_session',function(err,vote_session) { //we only want to send updates to clients in this vote session
            if(vote_session == session_id) {
              client.emit('vote', session);
            }
        });
    });

    client.on('disconnect', function() {
        client.get('vote_session',function(err,vote_session) {
            client.leave("/"+vote_session);
            sub.quit();
            //console.log("user left /"+vote_session);
        });
    });

});
<commit_msg>var not const<commit_after>const channel_name = 'dl.channel.votes';
const redis = require('redis');
var port = process.env.PORT || 3000;
const io = require('socket.io').listen(port);

// Heroku Cedar stack does not support Websockets yet, force long poll
if(process.env.HEROKU_DEPLOY) {
    io.configure(function () {
        io.set("transports", ["xhr-polling"]);
        io.set("polling duration", 10);
    });
}

io.sockets.on('connection', function(client) {

    var sub = redis.createClient(); //create a new subscriber connection

    //Heroku production authentication
    if (process.env.REDISTOGO_URL) {
        var rtg = require("url").parse(process.env.REDISTOGO_URL);
        sub = redis.createClient(rtg.port, rtg.hostname);
        sub.auth(rtg.auth.split(":")[1]);
    }

    sub.subscribe(channel_name);  //listen for messages published on this channel

    client.on('join', function(session_id) {
        client.set('vote_session', session_id);
        client.join(session_id);
        //console.log("user joined /"+session_id);
    });

    sub.on("message", function(channel, session) {
        var session_id = JSON.parse(session).uuid; //this is a waste, there's probably a way to avoid it
        client.get('vote_session',function(err,vote_session) { //we only want to send updates to clients in this vote session
            if(vote_session == session_id) {
              client.emit('vote', session);
            }
        });
    });

    client.on('disconnect', function() {
        client.get('vote_session',function(err,vote_session) {
            client.leave("/"+vote_session);
            sub.quit();
            //console.log("user left /"+vote_session);
        });
    });

});
<|endoftext|>