<commit_before>'use strict';

const util = require('util');
const rethinkDB = require('rethinkdb');
const log = require('./log');

const WebAPI = require('./WebAPI');

export class UserDB{
  constructor (conn, dbName, dumpPeriod, port, locationSize) {
    this.conn = conn;
    this.dbName = dbName;
    this.port = port;
    this.dumpPeriod = dumpPeriod;

    this.conn.use(this.dbName);

    // dictionary for variant of offset
    this.offsets = {
      'up': {'x': 0, 'y': -1},
      'down': {'x': 0, 'y': 1},
      'left': {'x': -1, 'y': 0},
      'right': {'x': 1, 'y': 0}
    };

    this.locationSize = locationSize;
    this.coordTransMutator = {
      'up': {'y': this.locationSize - 1},
      'down': {'y': 0},
      'left': {'x': this.locationSize - 1},
      'right': {'x': 0}
    };

    this.locationCache = {};
    this.userPositionCache = {};
    this.worldMapCache = {};

    // for broadcast response on location
    // {'location': position.location, 'client': client};
    this.clients = {};
    this.clientId = {};
  }

  run () {
    this.startLocalMode();
  }

  startLocalMode() {
    log.info(`Start local mode, period of dump is ${this.dumpPeriod} sec`);

    rethinkDB
      .table('userPosition', {readMode: 'outdated'})
      .run(this.conn, (err, cursor) => {
        if (err) throw  err;

        cursor.toArray( (err, res) => {
          if (err) throw  err;

          for (let i = 0; i < res.length; i++) {
            let e = res[i];
            this.userPositionCache[e.login] = e;
          }

          log.info(`User position cache is ready.`);

          // 1. We will be get worldMap table too.
          rethinkDB
            .table('worldMap', {readMode: 'outdated'})
            .run(this.conn, (err, cursor) => {
              if (err) throw err;

              cursor.toArray( (err, res) => {
                if (err) throw err;

                for (let i = 0; i < res.length; i++) {
                  let e = res[i];
                  this.worldMapCache[e.location] = e;
                }

                log.info(`World map cache is ready.`);

                this.startPeriodicalDumper();
                this.startWebSocketServer();
              });
            });
        });
      });
  }

  startPeriodicalDumper() {
    setInterval( () => {
      log.info(`Let's start the dump`);

      for (let login in this.userPositionCache) {
        let pos = {
          login: login,
          x: this.userPositionCache[login].x,
          y: this.userPositionCache[login].y,
          direction: this.userPositionCache[login].direction,
          location: this.userPositionCache[login].location
        };

        rethinkDB
          .table('userPosition', {readMode: 'outdated'})
          .get(this.userPositionCache[login].id)
          .update(pos)
          .run(this.conn, function (err) {
            if (err) throw  err;
          });
      }
    }, this.dumpPeriod * 1000);
  }

  startWebSocketServer () {
    this.webAPI = new WebAPI.WebAPI(this, this.port);
  }

  getNeighborLocation (location, direction) {
    return this.worldMapCache[location][direction];
  }

  /**
  *
  * @param curPosition {y, x} current user position
  * @param direction 'up', or 'down', or 'left', or 'right'
  * @returns {{y: *, x: *, direction: *}} new position and direction
  *          or undefined if block ahead
  * @constructor
  */
  getNewPosition(curPosition, direction) {
    const offset = this.offsets[direction];

    let newY = curPosition.y + offset.y;
    let newX = curPosition.x + offset.x;

    const curLocation = this.locationCache[curPosition.location];

    if (curLocation
      && newX >= 0
      && newX < this.locationSize
      && newY >= 0
      && newY < this.locationSize) {
        if (curLocation[newY] && curLocation[newX] && curLocation[newY][newX] >= 1) {
          const locationElem = curLocation[newY][newX];

          if (locationElem >= 1 && locationElem < 2) {
            return {
              'y': newY,
              'x': newX,
              'direction': direction
            };
          } else if (locationElem >= 2) {
            if (locationElem === 2.1) {
              // entrance to the dungeon's level
              direction = 'under';
            } else if (locationElem === 2.2) {
              // exit from dungeon's level
              direction = 'over';
            }

            const neighbor = this.getNeighborLocation(curPosition.location, direction);
            if (neighbor) {
              return {
                'location': neighbor,
                'y': curPosition.y,
                'x': curPosition.x,
                'direction': direction
              };
            }
          }
        }
      } else {
        // We will be check neighbors of location in worldMap buffer.
        const neighbor = this.getNeighborLocation(curPosition.location, direction);

        if (neighbor) {
          const transMutator = this.coordTransMutator[direction];

          if (transMutator.x === undefined) {
            newX = curPosition.x;
          } else {
            newX = transMutator.x;
          }

          if (transMutator.y === undefined) {
            newY = curPosition.y;
          } else {
            newY = transMutator.y;
          }

          return {
            'location': neighbor,
            'y': newY,
            'x': newX,
            'direction': direction};
          }
        }
  }

  getClientsForLocation(location) {
    let clientList = [];

    for (let log in this.clients) {
      let loc = this.clients[log].location;

      if (loc === location) {
        let clnt = this.clients[log].client;
        clientList.push(clnt);
      }
    }

    return clientList;
  }

  processUserActivity(message, client, clientId) {
    const login = message.login;
    const position = this.userPositionCache[login];

    if (message.direction) {
      let newPosition = this.getNewPosition(position, message.direction);

      if (newPosition) {
        // change position
        this.userPositionCache[login]['x'] = newPosition.x;
        this.userPositionCache[login]['y'] = newPosition.y;
        this.userPositionCache[login]['direction'] = newPosition.direction;

        if (newPosition.location) {
          // If new Location - checkLocationCache()
          this.clients[login] = {
            'location': newPosition.location,
            'client': client
          };

          const oldLocation = this.userPositionCache[login]['location'];
          this.userPositionCache[login]['location'] = newPosition.location;
          this.checkLocationCache(client, login, oldLocation, newPosition);
        } else {
          // same location
          let clientList = this.getClientsForLocation(this.userPositionCache[login].location);

          this.webAPI.sendChangePositionBroadcast(
            clientList,
            login,
            newPosition.direction,
            newPosition.x,
            newPosition.y);
        }
      }
    } else {
      // we have a new user connection
      this.clients[login] = {
        'location': position.location,
        'client': client
      };

      this.switchOnline(login, clientId);

      this.checkLocationCache(client, login, undefined, position);
    }
  }

  checkLocationCache (client, login, oldLocation, position) {
    if (this.locationCache[position.location] === undefined) {
      this.loadLocation(client, login, oldLocation, position);
    } else {
      if (oldLocation) {
        this.webAPI.sendRemoveUserBroadcast(this.getClientsForLocation(oldLocation), login);
      }

      WebAPI.WebAPI.sendInitialResponse(
        client,
        login,
        this.locationCache[position.location],
        position.x,
        position.y);
    }

  }

  loadLocation (client, login, oldLocation, position) {
    rethinkDB
      .table(position.location, {readMode: 'outdated'})
      .run(this.conn, (err, cursor) => {
        if (err) throw err;

        this.locationCache[position.location] = [];
        cursor.toArray( (err, res) => {
          if (err) throw err;

          let i = 0;
          for (; i < res.length; i++) {
            let e = res[i];

            if (this.locationCache[position.location][e.y] === undefined) {
              this.locationCache[position.location][e.y] = [];
            }

            this.locationCache[position.location][e.y][e.x] = e.type;
          }

          log.info(`Location cache for ${position.location} is ready, ${i} elements.`);

          rethinkDB
            .table(position.location, {readMode: 'outdated'})
            .changes()
            .run(this.conn, (err, cursor) => {
              if (err) throw  err;

              cursor.each((err, row) => {
                if (err) throw err;

                log.info(`Location cache for ${position.location} has changed.`);
                const e = row.new_val;
                this.locationCache[position.location][e.y][e.x] = e.type;
              });
            });

          if (oldLocation) {
            this.webAPI.sendRemoveUserBroadcast(this.getClientsForLocation(oldLocation), login);
          }

          WebAPI.WebAPI.sendInitialResponse(
            client,
            login,
            this.locationCache[position.location],
            position.x,
            position.y);
        });
      });
  }

  switchOnline (login, clientId) {
    rethinkDB
      .table('userPosition', {readMode: 'outdated'})
      .get(this.userPositionCache[login].id)
      .update({'online': true})
      .run(this.conn, (err) => {
        if (err) throw  err;

        this.clientId[clientId] = login;
      });
  }

  switchOffline (clientId) {
    const login = this.clientId[clientId];

    rethinkDB
      .table('userPosition', {readMode: 'outdated'})
      .get(this.userPositionCache[login].id)
      .update({'online': false})
      .run(this.conn, (err) => {
        if (err) throw  err;

        delete this.clientId[clientId];
      });
  }
}
<commit_msg>fix bug<commit_after>'use strict';

const util = require('util');
const rethinkDB = require('rethinkdb');
const log = require('./log');

const WebAPI = require('./WebAPI');

export class UserDB{
  constructor (conn, dbName, dumpPeriod, port, locationSize) {
    this.conn = conn;
    this.dbName = dbName;
    this.port = port;
    this.dumpPeriod = dumpPeriod;

    this.conn.use(this.dbName);

    // dictionary for variant of offset
    this.offsets = {
      'up': {'x': 0, 'y': -1},
      'down': {'x': 0, 'y': 1},
      'left': {'x': -1, 'y': 0},
      'right': {'x': 1, 'y': 0}
    };

    this.locationSize = locationSize;
    this.coordTransMutator = {
      'up': {'y': this.locationSize - 1},
      'down': {'y': 0},
      'left': {'x': this.locationSize - 1},
      'right': {'x': 0}
    };

    this.locationCache = {};
    this.userPositionCache = {};
    this.worldMapCache = {};

    // for broadcast response on location
    // {'location': position.location, 'client': client};
    this.clients = {};
    this.clientId = {};
  }

  run () {
    this.startLocalMode();
  }

  startLocalMode() {
    log.info(`Start local mode, period of dump is ${this.dumpPeriod} sec`);

    rethinkDB
      .table('userPosition', {readMode: 'outdated'})
      .run(this.conn, (err, cursor) => {
        if (err) throw  err;

        cursor.toArray( (err, res) => {
          if (err) throw  err;

          for (let i = 0; i < res.length; i++) {
            let e = res[i];
            this.userPositionCache[e.login] = e;
          }

          log.info(`User position cache is ready.`);

          // 1. We will be get worldMap table too.
          rethinkDB
            .table('worldMap', {readMode: 'outdated'})
            .run(this.conn, (err, cursor) => {
              if (err) throw err;

              cursor.toArray( (err, res) => {
                if (err) throw err;

                for (let i = 0; i < res.length; i++) {
                  let e = res[i];
                  this.worldMapCache[e.location] = e;
                }

                log.info(`World map cache is ready.`);

                this.startPeriodicalDumper();
                this.startWebSocketServer();
              });
            });
        });
      });
  }

  startPeriodicalDumper() {
    setInterval( () => {
      log.info(`Let's start the dump`);

      for (let login in this.userPositionCache) {
        let pos = {
          login: login,
          x: this.userPositionCache[login].x,
          y: this.userPositionCache[login].y,
          direction: this.userPositionCache[login].direction,
          location: this.userPositionCache[login].location
        };

        rethinkDB
          .table('userPosition', {readMode: 'outdated'})
          .get(this.userPositionCache[login].id)
          .update(pos)
          .run(this.conn, function (err) {
            if (err) throw  err;
          });
      }
    }, this.dumpPeriod * 1000);
  }

  startWebSocketServer () {
    this.webAPI = new WebAPI.WebAPI(this, this.port);
  }

  getNeighborLocation (location, direction) {
    return this.worldMapCache[location][direction];
  }

  /**
  *
  * @param curPosition {y, x} current user position
  * @param direction 'up', or 'down', or 'left', or 'right'
  * @returns {{y: *, x: *, direction: *}} new position and direction
  *          or undefined if block ahead
  * @constructor
  */
  getNewPosition(curPosition, direction) {
    const offset = this.offsets[direction];

    let newY = curPosition.y + offset.y;
    let newX = curPosition.x + offset.x;

    const curLocation = this.locationCache[curPosition.location];

    if (curLocation
      && newX >= 0
      && newX < this.locationSize
      && newY >= 0
      && newY < this.locationSize) {
        if (curLocation[newY] && curLocation[newX] && curLocation[newY][newX] >= 1) {
          const locationElem = curLocation[newY][newX];

          if (locationElem >= 1 && locationElem < 2) {
            return {
              'y': newY,
              'x': newX,
              'direction': direction
            };
          } else if (locationElem >= 2) {
            if (locationElem === 2.1) {
              // entrance to the dungeon's level
              direction = 'under';
            } else if (locationElem === 2.2) {
              // exit from dungeon's level
              direction = 'over';
            }

            const neighbor = this.getNeighborLocation(curPosition.location, direction);
            if (neighbor) {
              return {
                'location': neighbor,
                'y': curPosition.y,
                'x': curPosition.x,
                'direction': direction
              };
            }
          }
        }
      } else {
        // We will be check neighbors of location in worldMap buffer.
        const neighbor = this.getNeighborLocation(curPosition.location, direction);

        if (neighbor) {
          const transMutator = this.coordTransMutator[direction];

          if (transMutator.x === undefined) {
            newX = curPosition.x;
          } else {
            newX = transMutator.x;
          }

          if (transMutator.y === undefined) {
            newY = curPosition.y;
          } else {
            newY = transMutator.y;
          }

          return {
            'location': neighbor,
            'y': newY,
            'x': newX,
            'direction': direction};
          }
        }
  }

  getClientsForLocation(location) {
    let clientList = [];

    for (let log in this.clients) {
      let loc = this.clients[log].location;

      if (loc === location) {
        let clnt = this.clients[log].client;
        clientList.push(clnt);
      }
    }

    return clientList;
  }

  processUserActivity(message, client, clientId) {
    const login = message.login;
    const position = this.userPositionCache[login];

    if (message.direction) {
      let newPosition = this.getNewPosition(position, message.direction);

      if (newPosition) {
        // change position
        this.userPositionCache[login]['x'] = newPosition.x;
        this.userPositionCache[login]['y'] = newPosition.y;
        this.userPositionCache[login]['direction'] = newPosition.direction;

        if (newPosition.location) {
          // If new Location - checkLocationCache()
          this.clients[login] = {
            'location': newPosition.location,
            'client': client
          };

          const oldLocation = this.userPositionCache[login]['location'];
          this.userPositionCache[login]['location'] = newPosition.location;
          this.checkLocationCache(client, login, oldLocation, newPosition);
        } else {
          // same location
          let clientList = this.getClientsForLocation(this.userPositionCache[login].location);

          this.webAPI.sendChangePositionBroadcast(
            clientList,
            login,
            newPosition.direction,
            newPosition.x,
            newPosition.y);
        }
      }
    } else {
      // we have a new user connection
      this.clients[login] = {
        'location': position.location,
        'client': client
      };

      this.switchOnline(login, clientId);

      this.checkLocationCache(client, login, undefined, position);
    }
  }

  checkLocationCache (client, login, oldLocation, position) {
    if (this.locationCache[position.location] === undefined) {
      this.loadLocation(client, login, oldLocation, position);
    } else {
      if (oldLocation) {
        this.webAPI.sendRemoveUserBroadcast(this.getClientsForLocation(oldLocation), login);
      }

      WebAPI.WebAPI.sendInitialResponse(
        client,
        login,
        this.locationCache[position.location],
        position.x,
        position.y);
    }

  }

  loadLocation (client, login, oldLocation, position) {
    rethinkDB
      .table(position.location, {readMode: 'outdated'})
      .run(this.conn, (err, cursor) => {
        if (err) throw err;

        this.locationCache[position.location] = [];
        cursor.toArray( (err, res) => {
          if (err) throw err;

          let i = 0;
          for (; i < res.length; i++) {
            let e = res[i];

            if (this.locationCache[position.location][e.y] === undefined) {
              this.locationCache[position.location][e.y] = [];
            }

            this.locationCache[position.location][e.y][e.x] = e.type;
          }

          log.info(`Location cache for ${position.location} is ready, ${i} elements.`);

          rethinkDB
            .table(position.location, {readMode: 'outdated'})
            .changes()
            .run(this.conn, (err, cursor) => {
              if (err) throw  err;

              cursor.each((err, row) => {
                if (err) throw err;

                log.info(`Location cache for ${position.location} has changed.`);
                const e = row.new_val;
                this.locationCache[position.location][e.y][e.x] = e.type;
              });
            });

          if (oldLocation) {
            this.webAPI.sendRemoveUserBroadcast(this.getClientsForLocation(oldLocation), login);
          }

          WebAPI.WebAPI.sendInitialResponse(
            client,
            login,
            this.locationCache[position.location],
            position.x,
            position.y);
        });
      });
  }

  switchOnline (login, clientId) {
    rethinkDB
      .table('userPosition', {readMode: 'outdated'})
      .get(this.userPositionCache[login].id)
      .update({'online': true})
      .run(this.conn, (err) => {
        if (err) throw  err;

        this.clientId[clientId] = login;
      });
  }

  switchOffline (clientId) {
    const login = this.clientId[clientId];
    delete this.clients[login];

    rethinkDB
      .table('userPosition', {readMode: 'outdated'})
      .get(this.userPositionCache[login].id)
      .update({'online': false})
      .run(this.conn, (err) => {
        if (err) throw  err;

        delete this.clientId[clientId];
      });
  }
}
<|endoftext|>


<commit_before>/* Copyright 2014, 2015 Krzysztof Daniel and Scott Weinstein.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.*/

var logger = require('./util/log.js').getLogger('exportmap');
var fs = require('fs');
var d3 = require('d3'), jsdom = require('jsdom');
var xmldom = require('xmldom');
var _ = require('underscore');
var path = require('path');

// TODO: map description
// TODO: action labels
var htmlStub = fs.readFileSync(path.join(__dirname, 'svgtemplate.html'), 'UTF8');

var draw = function(res, filename, map){

	jsdom.env({
		features : {
			QuerySelector : true
		},
		html : htmlStub,
		done : function(errors, window) {

			function pick(key) {
				return function(d) {
					return d[key];
				};
			}

			function unitify(unit) {
				return function(d) {
					return '' + d + unit;
				};
			}

			var x = 1280;
			var y = 1024;
			var thumbnailMargin = 20;

			var el = window.document.querySelector('#svg');
			var svgimg = d3.select(el);

			svgimg.append("text").text(map.name)
			.style('font-weight', 'bold')
			.attr('y', 20)
			.attr('x', 40);

			var nodes = _.groupBy(map.nodes, 'componentId');

			var _dependencyConnections = [];
			var _actionConnections = [];
			for(var i = 0; i < map.connections.length; i++){
				if(map.connections[i].scope === 'Actions'){
					_actionConnections.push(map.connections[i]);
				} else {
					_dependencyConnections.push(map.connections[i]);
				}
			}

			var dependencyConnections = _dependencyConnections.map(function(c) {
				return [ nodes[c.pageSourceId][0], nodes[c.pageTargetId][0] ];
			});

			var actionConnections = _actionConnections.map(function(c) {
				return [ nodes[c.pageSourceId][0], nodes[c.pageTargetId][0] ];
			});

			// basic size
			var margin = {top: (thumbnailMargin + 50), right: thumbnailMargin, bottom: thumbnailMargin, left: thumbnailMargin};
			var width = x - margin.left - margin.right;
			var height = y - margin.top - margin.bottom;

			// scales
			var x = d3.scale.linear().range([0, width]);
			var y = d3.scale.linear().range([0, height]);
			var line = d3.svg.line()
				.x(_.compose(x, pick('positionX')))
				.y(_.compose(y, pick('positionY')));

			// setup viz container
			var mapViz = svgimg
				.attr('width', width + margin.left + margin.right)
				.attr('height', height + margin.top + margin.bottom)
				.append('g')
				.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');

			// x legend
			var legendItems = ['Genesis', 'Custom built', 'Product(or rental)', 'Commodity/Utility'];

			var xLegend = d3.scale.ordinal()
				.domain(legendItems)
				.rangeBands([0, width], 0, 0.1);

			mapViz.append('g')
				.attr('class', 'x axis')
				.attr('transform', 'translate(0,' + height + ')')
				.call(function(el) {
					el.append('path')
						.attr('d', line([{positionX:0, positionY:0}, {positionX:1, positionY:0}]))
						.style('stroke','grey').style('stroke-width', '2px').style('marker-end', 'url(#arrow)');
					el.selectAll('g.label')
						.data(legendItems)
						.enter()
						.append('g')
						.classed('label', true)
						.attr('transform', function(d) { return 'translate(' + xLegend(d) + ',15)'; })
						.append('text')
						.text(_.identity);
			});

			mapViz.append('g')
				.classed('evolution-marker', true)
				.selectAll('path')
				.data(_.tail(legendItems))
				.enter()
				.append('path')
				.attr('transform', function(d) { return 'translate(' + (xLegend(d) - 40) + ',0)'; })
				.attr('d', line([{positionX:0, positionY:1}, {positionX:0, positionY:0}]))
				.style('stroke','grey').style('stroke-width', '1px').style('stroke-dasharray', '1,5');

			// y legend
			mapViz.append('g')
				.attr('class', 'y axis')
				.call(function(el) {
					el.append('path')
					.attr('d', line([{positionX:0, positionY:1}, {positionX:0, positionY:0}]))
					.style('stroke','grey').style('stroke-width', '2px').style('marker-end', 'url(#arrow)');
			});

			//action connections
			mapViz
				.selectAll('.connection')
				.data(actionConnections)
				.enter()
				.append('path')
				.classed('action', true)
				.attr('d', line)
				.style('stroke','green')
				.style('stroke-width', '2px')
				.style('marker-end', 'url(#actionarrow)');

			// regular dependencies
			mapViz
				.selectAll('.connection')
				.data(dependencyConnections)
				.enter()
				.append('path')
				.classed('connection', true)
				.attr('d', line)
				.style('stroke','grey').style('stroke-width', '2px');

			// nodes
			mapViz
				.append('g')
				.classed('nodes', true)
				.selectAll('node')
				.data(map.nodes)
				.enter()
				.append('g')
				.classed({ node: true, external: pick('external'), userneed: pick('userneed') })
				.call(function(gnode) {

					var moveX = _.compose(x, pick('positionX'));
					var moveY = _.compose(y, pick('positionY'));

					gnode
						.append('circle')
						.attr({ r: '10px', 'cx': moveX, 'cy': moveY })
						.style('fill','silver').style('stroke','black').style('stroke-width', '2px');

					gnode.append('text')
						.style('filter', 'url(#drop-shadow)')
						.attr('transform', function(d) { return 'translate(' + (moveX(d) + 12) + ',' + (moveY(d) - 8) + ')'; })
						.text(pick('name'));
					});

			mapViz.selectAll('.userneed > circle').style('stroke-width', '4px');
			mapViz.selectAll('.external > circle').style('fill', 'white');
			var svgXML = (new xmldom.XMLSerializer()).serializeToString(el);
			res.setHeader('Content-Type', 'image/svg+xml');
			res.send('<?xml version="1.0" encoding="UTF-8" standalone="no"?>' + svgXML);
		}
	});

};

var export_module = function(db) {
    return {
    createSVG : function(req, res, mapId, filename) {
        var userId = req.user.href;
        mapId = db.ObjectId(mapId);
        logger.debug("drawing svg", mapId, "for user", userId);

        db.maps.find({
            "userIdGoogle" : userId,
            "_id" : mapId
        }, {
            history : {
                $slice : -1
            }
        }).toArray(function(err, maps) {
            res.setHeader('Content-Type', 'application/json');
            if (err !== null) {
                logger.error(err);
                res.statusCode = 500;
                res.send(JSON.stringify(err));
            } else {
                draw(res, mapId, maps[0].history[0], filename);
            }
        });
    },

    createAnonymousSVG : function(req, res, mapId, filename) {
        mapId = db.ObjectId(mapId);
        logger.debug("drawing anonymous svg", mapId);

        db.maps.find({
            "_id" : mapId,
            deleted : false,
            anonymousShare : true
        }, {
            history : {
                $slice : -1
            }
        }).toArray(function(err, maps) {
            res.setHeader('Content-Type', 'application/json');
            if (err !== null) {
                logger.error(err);
                res.statusCode = 500;
                res.send(JSON.stringify(err));
            } else {
                // empty map
                if (maps.length === 0) {
                    res.redirect('/favicon.svg');
                } else {
                    draw(res, mapId, maps[0].history[0], filename);
                }
            }
        });
    },

    createThumbnail : function(req, res, mapId) {
        var userId = req.user.href;
        mapId = db.ObjectId(mapId);
        logger.debug("drawing thumbnail", mapId, "for user", userId);

        db.maps.find({
            "userIdGoogle" : userId,
            "_id" : mapId
        }, {
            history : {
                $slice : -1
            }
        }).toArray(function(err, maps) {
            res.setHeader('Content-Type', 'application/json');
            if (err !== null) {
                logger.error(err);
                res.statusCode = 500;
                res.send(JSON.stringify(err));
            } else {
                // empty map
                if (maps[0].history[0].nodes.length === 0) {
                    res.redirect('/favicon.svg');
                } else {
                    draw(res, mapId, maps[0].history[0]);
                }
            }
        });
    }
    };
};

module.exports = export_module;
<commit_msg>Be less vurnelable for issues with native jsdom.<commit_after>/* Copyright 2014, 2015 Krzysztof Daniel and Scott Weinstein.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.*/

var logger = require('./util/log.js').getLogger('exportmap');
var fs = require('fs');
var d3 = require('d3');
var jsdom = null;
try {
    jsdom = require('jsdom');
} catch (e){
    logger.error('Could not load jsdom');
}
var xmldom = require('xmldom');
var _ = require('underscore');
var path = require('path');

// TODO: map description
// TODO: action labels
var htmlStub = fs.readFileSync(path.join(__dirname, 'svgtemplate.html'), 'UTF8');

var draw = function(res, filename, map){
    if(!jsdom) {
        res.statusCode = 500;
        res.send('Could not create image');
        return;
    }
	jsdom.env({
		features : {
			QuerySelector : true
		},
		html : htmlStub,
		done : function(errors, window) {

			function pick(key) {
				return function(d) {
					return d[key];
				};
			}

			function unitify(unit) {
				return function(d) {
					return '' + d + unit;
				};
			}

			var x = 1280;
			var y = 1024;
			var thumbnailMargin = 20;

			var el = window.document.querySelector('#svg');
			var svgimg = d3.select(el);

			svgimg.append("text").text(map.name)
			.style('font-weight', 'bold')
			.attr('y', 20)
			.attr('x', 40);

			var nodes = _.groupBy(map.nodes, 'componentId');

			var _dependencyConnections = [];
			var _actionConnections = [];
			for(var i = 0; i < map.connections.length; i++){
				if(map.connections[i].scope === 'Actions'){
					_actionConnections.push(map.connections[i]);
				} else {
					_dependencyConnections.push(map.connections[i]);
				}
			}

			var dependencyConnections = _dependencyConnections.map(function(c) {
				return [ nodes[c.pageSourceId][0], nodes[c.pageTargetId][0] ];
			});

			var actionConnections = _actionConnections.map(function(c) {
				return [ nodes[c.pageSourceId][0], nodes[c.pageTargetId][0] ];
			});

			// basic size
			var margin = {top: (thumbnailMargin + 50), right: thumbnailMargin, bottom: thumbnailMargin, left: thumbnailMargin};
			var width = x - margin.left - margin.right;
			var height = y - margin.top - margin.bottom;

			// scales
			var x = d3.scale.linear().range([0, width]);
			var y = d3.scale.linear().range([0, height]);
			var line = d3.svg.line()
				.x(_.compose(x, pick('positionX')))
				.y(_.compose(y, pick('positionY')));

			// setup viz container
			var mapViz = svgimg
				.attr('width', width + margin.left + margin.right)
				.attr('height', height + margin.top + margin.bottom)
				.append('g')
				.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');

			// x legend
			var legendItems = ['Genesis', 'Custom built', 'Product(or rental)', 'Commodity/Utility'];

			var xLegend = d3.scale.ordinal()
				.domain(legendItems)
				.rangeBands([0, width], 0, 0.1);

			mapViz.append('g')
				.attr('class', 'x axis')
				.attr('transform', 'translate(0,' + height + ')')
				.call(function(el) {
					el.append('path')
						.attr('d', line([{positionX:0, positionY:0}, {positionX:1, positionY:0}]))
						.style('stroke','grey').style('stroke-width', '2px').style('marker-end', 'url(#arrow)');
					el.selectAll('g.label')
						.data(legendItems)
						.enter()
						.append('g')
						.classed('label', true)
						.attr('transform', function(d) { return 'translate(' + xLegend(d) + ',15)'; })
						.append('text')
						.text(_.identity);
			});

			mapViz.append('g')
				.classed('evolution-marker', true)
				.selectAll('path')
				.data(_.tail(legendItems))
				.enter()
				.append('path')
				.attr('transform', function(d) { return 'translate(' + (xLegend(d) - 40) + ',0)'; })
				.attr('d', line([{positionX:0, positionY:1}, {positionX:0, positionY:0}]))
				.style('stroke','grey').style('stroke-width', '1px').style('stroke-dasharray', '1,5');

			// y legend
			mapViz.append('g')
				.attr('class', 'y axis')
				.call(function(el) {
					el.append('path')
					.attr('d', line([{positionX:0, positionY:1}, {positionX:0, positionY:0}]))
					.style('stroke','grey').style('stroke-width', '2px').style('marker-end', 'url(#arrow)');
			});

			//action connections
			mapViz
				.selectAll('.connection')
				.data(actionConnections)
				.enter()
				.append('path')
				.classed('action', true)
				.attr('d', line)
				.style('stroke','green')
				.style('stroke-width', '2px')
				.style('marker-end', 'url(#actionarrow)');

			// regular dependencies
			mapViz
				.selectAll('.connection')
				.data(dependencyConnections)
				.enter()
				.append('path')
				.classed('connection', true)
				.attr('d', line)
				.style('stroke','grey').style('stroke-width', '2px');

			// nodes
			mapViz
				.append('g')
				.classed('nodes', true)
				.selectAll('node')
				.data(map.nodes)
				.enter()
				.append('g')
				.classed({ node: true, external: pick('external'), userneed: pick('userneed') })
				.call(function(gnode) {

					var moveX = _.compose(x, pick('positionX'));
					var moveY = _.compose(y, pick('positionY'));

					gnode
						.append('circle')
						.attr({ r: '10px', 'cx': moveX, 'cy': moveY })
						.style('fill','silver').style('stroke','black').style('stroke-width', '2px');

					gnode.append('text')
						.style('filter', 'url(#drop-shadow)')
						.attr('transform', function(d) { return 'translate(' + (moveX(d) + 12) + ',' + (moveY(d) - 8) + ')'; })
						.text(pick('name'));
					});

			mapViz.selectAll('.userneed > circle').style('stroke-width', '4px');
			mapViz.selectAll('.external > circle').style('fill', 'white');
			var svgXML = (new xmldom.XMLSerializer()).serializeToString(el);
			res.setHeader('Content-Type', 'image/svg+xml');
			res.send('<?xml version="1.0" encoding="UTF-8" standalone="no"?>' + svgXML);
		}
	});

};

var export_module = function(db) {
    return {
    createSVG : function(req, res, mapId, filename) {
        var userId = req.user.href;
        mapId = db.ObjectId(mapId);
        logger.debug("drawing svg", mapId, "for user", userId);

        db.maps.find({
            "userIdGoogle" : userId,
            "_id" : mapId
        }, {
            history : {
                $slice : -1
            }
        }).toArray(function(err, maps) {
            res.setHeader('Content-Type', 'application/json');
            if (err !== null) {
                logger.error(err);
                res.statusCode = 500;
                res.send(JSON.stringify(err));
            } else {
                draw(res, mapId, maps[0].history[0], filename);
            }
        });
    },

    createAnonymousSVG : function(req, res, mapId, filename) {
        mapId = db.ObjectId(mapId);
        logger.debug("drawing anonymous svg", mapId);

        db.maps.find({
            "_id" : mapId,
            deleted : false,
            anonymousShare : true
        }, {
            history : {
                $slice : -1
            }
        }).toArray(function(err, maps) {
            res.setHeader('Content-Type', 'application/json');
            if (err !== null) {
                logger.error(err);
                res.statusCode = 500;
                res.send(JSON.stringify(err));
            } else {
                // empty map
                if (maps.length === 0) {
                    res.redirect('/favicon.svg');
                } else {
                    draw(res, mapId, maps[0].history[0], filename);
                }
            }
        });
    },

    createThumbnail : function(req, res, mapId) {
        var userId = req.user.href;
        mapId = db.ObjectId(mapId);
        logger.debug("drawing thumbnail", mapId, "for user", userId);

        db.maps.find({
            "userIdGoogle" : userId,
            "_id" : mapId
        }, {
            history : {
                $slice : -1
            }
        }).toArray(function(err, maps) {
            res.setHeader('Content-Type', 'application/json');
            if (err !== null) {
                logger.error(err);
                res.statusCode = 500;
                res.send(JSON.stringify(err));
            } else {
                // empty map
                if (maps[0].history[0].nodes.length === 0) {
                    res.redirect('/favicon.svg');
                } else {
                    draw(res, mapId, maps[0].history[0]);
                }
            }
        });
    }
    };
};

module.exports = export_module;
<|endoftext|>


<commit_before>const express              = require('express');
const ab                   = require('express-ab');
const bp                   = require('body-parser');
const { PRISMIC_ENDPOINT } = require('./config');
const markdown             = require('./markdown');
const es                   = require('express-sanitizer');
const { join }             = require('path');

const { previewController, getPrismic } = require('./prismic');
const { getIntegrations, getIntegration } = require('./integrations');

const trustedPartnersCtrl = require('./controllers/trustedPartnersCtrl');
const contactCtrl = require('./controllers/contactCtrl');
const newsletterCtrl    = require('./controllers/newsletterCtrl');
const viewCtrl    = require('./controllers/viewCtrl');
// const integrations = require('./data/integrations');

function send404(res) {
  res.status(404).sendFile(join(__dirname, '/../_site/404.html'))
}

module.exports = function router(app) {

  var abTestTest = ab.test('pricing-test', {id: 'MRClmJX_QEakg3kJs2jH9g'});

  return new express.Router()
  // .get('/css/styles.min.css', abTestTest(null, 0.50), function(_, res) {
  //   res.sendFile('/css/styles.min.css', {root: './_site'});
  // })
  // .get('/css/styles.min.css', abTestTest(null, 0.50), function(_, res) {
  //   res.sendFile('/css/styles.test.min.css', {root: './_site'});
  // });

  // normal pages
  .get('/', (_, res) => res.render('index'))
  .get('/home', (_, res) => res.render('index'))
  .get('/about', (_, res) => res.render('about'))

  .get('/articles/pwa-architects-guide', (_, res) =>
    res.render('articles/pwa-architects-guide'))
  .get('/articles/pwa-architects-guide/preview', (_, res) =>
    res.render('articles/pwa-architects-guide-preview'))

  .get('/articles/why-hybrid', (_, res) => res.render('articles/why-hybrid'))

  .get('/books/hybrid-vs-native', (_, res) =>
    res.render('books/hybrid-vs-native'))
  .get('/books/hybrid-vs-native/preview', (_, res) =>
    res.render('books/hybrid-vs-native-preview'))

  .get('/community', (_, res) => res.render('community'))
  .get('/contact', (_, res) => res.render('contact'))
  .get('/contributors', (_, res) => res.render('contributors'))
  .get('/demo', (_, res) => res.render('demo'))
  .get('/developers', (_, res) => res.render('developers'))
  .get('/enterprise', (_, res) => res.render('enterprise/index'))
  .get('/enterprise/identity-vault', (_, res) =>
    res.render('enterprise/identity-vault'))
  .get('/enterprise/support', (_, res) => res.render('enterprise/support'))
  .get('/enterprise/training', (_, res) => res.render('enterprise/training'))
  .get('/framework', (_, res) => res.render('framework'))
  .get('/getting-started', (_, res) => res.render('getting-started'))

  .get('/go/pwa-architects-guide', (_, res) =>
    res.render('go/pwa-architects-guide/index'))
  .post('/go/pwa-architects-guide', (_, res) =>
    res.render('go/pwa-architects-guide/thank-you'))
  .get('/go/pwa-architects-guide/thank-you', (_, res) =>
    res.render('go/pwa-architects-guide/thank-you'))

  .get('/go/why-hybrid', (_, res) => res.render('go/why-hybrid/index'))
  .post('/go/why-hybrid', (_, res) => res.render('go/why-hybrid/thank-you'))
  .get('/go/why-hybrid/thank-you', (_, res) =>
    res.render('go/why-hybrid/thank-you'))

  .get('/integrations', (req, res) =>
    getIntegrations(req, res))
  .get('/integrations/category/:category', (req, res) =>
    getIntegrations(req, res, req.params.category))
  .get('/integrations/:integration', (req, res) =>
    getIntegration(req, res, req.params.integration))

  .get('/jobs', (_, res) => res.render('jobs'))
  .get('/press', (_, res) => res.render('press'))
  .get('/pricing', (_, res) => res.render('pricing/index'))
  .get('/privacy', (_, res) => markdown(res, 'privacy-policy'))

  .get('/appflow', (_, res) => res.render('products/appflow'))
  .get('/studio', (_, res) => res.render('products/studio'))
  .get('/enterprise-engine', (_, res) => res.render('products/enterprise-engine'))

  .get('/pro/contact', (_, res) => res.render('pro/contact'))
  .get('/pro/creator', (_, res) => res.render('pro/creator/index'))
  .get('/pro/creator/pricing', (_, res) => res.render('pro/creator/pricing'))
  .get('/pro/creator/support', (_, res) => res.render('pro/creator/support'))
  .get('/pro/deploy', (_, res) => res.render('pro/deploy'))
  .get('/pro/monitor', (_, res) => res.render('pro/monitor'))
  .get('/pro/package', (_, res) => res.render('pro/package'))
  // .get('/pro/teams', (_, res) => res.render('pro/teams'))
  .get('/products/studio', (_, res) => res.render('products/studio'))
  .get('/products/enterprise-core', (_, res) => res.render('products/enterprise-core'))
  .get('/pwa', (_, res) => res.render('pwa/index'))
  .get('/pwa/toolkit', (_, res) => res.render('pwa/toolkit'))

  .get('/resources', (_, res) =>
    res.render('resources/index', {currentCategory: 'featured'}))
  .get('/resources/:category', (req, res) =>
    res.render('resources/category', {currentCategory: req.params.category}))
  .get('/resources/case-studies/:caseStudy', (req, res) =>
    getPrismic(req, res, 'case_study', req.params['caseStudy'],
      'resources/case-studies'))
  .get('/resources/webinars/:webinar', (req, res) =>

    getPrismic(req, res, 'webinar', req.params.webinar, 'resources/webinars'))

  .get('/sales', (_, res) => res.render('sales'))
  .get('/startups', (_, res) => res.render('startups'))
  .get('/strategysession', (_, res) => res.render('strategysession'))
  .get('/support', (_, res) => res.render('support'))
  .get('/survey/2017', (_, res) => res.render('survey/2017'))
  .get('/team', (_, res) => res.render('team'))
  .get('/tos', (_, res) => markdown(res, 'tos'))

  .get('/trusted-partners', (_, res) => res.render('trusted-partners'))
  .post('/trusted-partners',
    bp.urlencoded({extended: true}), es(), trustedPartnersCtrl)

  .get('/values', (_, res) => { res.render('values'); })
  .get('/what-is-ionic', (_, res) => res.render('what-is-ionic'))

  // press releases
  .get('/press/release/2017/dev-survey-says-the-web-is-wining-in-mobile-dev',
    (_, res) => markdown(res, 'pr-170725-dev-survey-says-the-web-is-wi'))
  .get('/press/release/2017/ionic-brings-powerful-app-development-suite-to-teams-and-enterprises',
    (_, res) => markdown(res, 'pr-171206-ionic-brings-powerful-app-dev'))

  // JSON endpoints
  .post('/contact', bp.json(), es(), contactCtrl)
  .post('/api/v1/newsletter', bp.json(), es(), newsletterCtrl)
  .post('/api/v1/view/link', bp.json(), es(), viewCtrl)

  // Prismic Preview
  .get('/preview', previewController)
};
<commit_msg>router tidy up<commit_after>const express              = require('express');
const ab                   = require('express-ab');
const bp                   = require('body-parser');
const { PRISMIC_ENDPOINT } = require('./config');
const markdown             = require('./markdown');
const es                   = require('express-sanitizer');
const { join }             = require('path');

const { previewController, getPrismic } = require('./prismic');
const { getIntegrations, getIntegration } = require('./integrations');

const trustedPartnersCtrl = require('./controllers/trustedPartnersCtrl');
const contactCtrl = require('./controllers/contactCtrl');
const newsletterCtrl    = require('./controllers/newsletterCtrl');
const viewCtrl    = require('./controllers/viewCtrl');
// const integrations = require('./data/integrations');

function send404(res) {
  res.status(404).sendFile(join(__dirname, '/../_site/404.html'))
}

module.exports = function router(app) {

  var abTestTest = ab.test('pricing-test', {id: 'MRClmJX_QEakg3kJs2jH9g'});

  return new express.Router()
  // .get('/css/styles.min.css', abTestTest(null, 0.50), function(_, res) {
  //   res.sendFile('/css/styles.min.css', {root: './_site'});
  // })
  // .get('/css/styles.min.css', abTestTest(null, 0.50), function(_, res) {
  //   res.sendFile('/css/styles.test.min.css', {root: './_site'});
  // });

  // normal pages
  .get('/', (_, res) => res.render('index'))
  .get('/home', (_, res) => res.render('index'))

  .get('/about', (_, res) => res.render('about'))
  .get('/appflow', (_, res) => res.render('products/appflow'))

  .get('/articles/pwa-architects-guide', (_, res) =>
    res.render('articles/pwa-architects-guide'))
  .get('/articles/pwa-architects-guide/preview', (_, res) =>
    res.render('articles/pwa-architects-guide-preview'))

  .get('/articles/why-hybrid', (_, res) => res.render('articles/why-hybrid'))

  .get('/books/hybrid-vs-native', (_, res) =>
    res.render('books/hybrid-vs-native'))
  .get('/books/hybrid-vs-native/preview', (_, res) =>
    res.render('books/hybrid-vs-native-preview'))

  .get('/community', (_, res) => res.render('community'))
  .get('/contact', (_, res) => res.render('contact'))
  .get('/contributors', (_, res) => res.render('contributors'))
  .get('/demo', (_, res) => res.render('demo'))
  .get('/developers', (_, res) => res.render('developers'))
  .get('/enterprise', (_, res) => res.render('enterprise/index'))
  .get('/enterprise/identity-vault', (_, res) =>
    res.render('enterprise/identity-vault'))
  .get('/enterprise/support', (_, res) => res.render('enterprise/support'))
  .get('/enterprise/training', (_, res) => res.render('enterprise/training'))
  .get('/enterprise-engine', (_, res) => res.render('products/enterprise-engine'))
  .get('/framework', (_, res) => res.render('framework'))
  .get('/getting-started', (_, res) => res.render('getting-started'))

  .get('/go/pwa-architects-guide', (_, res) =>
    res.render('go/pwa-architects-guide/index'))
  .post('/go/pwa-architects-guide', (_, res) =>
    res.render('go/pwa-architects-guide/thank-you'))
  .get('/go/pwa-architects-guide/thank-you', (_, res) =>
    res.render('go/pwa-architects-guide/thank-you'))

  .get('/go/why-hybrid', (_, res) => res.render('go/why-hybrid/index'))
  .post('/go/why-hybrid', (_, res) => res.render('go/why-hybrid/thank-you'))
  .get('/go/why-hybrid/thank-you', (_, res) =>
    res.render('go/why-hybrid/thank-you'))

  .get('/integrations', (req, res) =>
    getIntegrations(req, res))
  .get('/integrations/category/:category', (req, res) =>
    getIntegrations(req, res, req.params.category))
  .get('/integrations/:integration', (req, res) =>
    getIntegration(req, res, req.params.integration))

  .get('/jobs', (_, res) => res.render('jobs'))
  .get('/press', (_, res) => res.render('press'))
  .get('/pricing', (_, res) => res.render('pricing/index'))
  .get('/privacy', (_, res) => markdown(res, 'privacy-policy'))

  .get('/pro', (_, res) => res.render('pro/index'))
  .get('/pro/contact', (_, res) => res.render('pro/contact'))
  .get('/pro/creator', (_, res) => res.render('pro/creator/index'))
  .get('/pro/creator/pricing', (_, res) => res.render('pro/creator/pricing'))
  .get('/pro/creator/support', (_, res) => res.render('pro/creator/support'))
  .get('/pro/deploy', (_, res) => res.render('pro/deploy'))
  .get('/pro/monitor', (_, res) => res.render('pro/monitor'))
  .get('/pro/package', (_, res) => res.render('pro/package'))
  // .get('/pro/teams', (_, res) => res.render('pro/teams'))
  .get('/pwa', (_, res) => res.render('pwa/index'))
  .get('/pwa/toolkit', (_, res) => res.render('pwa/toolkit'))

  .get('/resources', (_, res) =>
    res.render('resources/index', {currentCategory: 'featured'}))
  .get('/resources/:category', (req, res) =>
    res.render('resources/category', {currentCategory: req.params.category}))
  .get('/resources/case-studies/:caseStudy', (req, res) =>
    getPrismic(req, res, 'case_study', req.params['caseStudy'],
      'resources/case-studies'))
  .get('/resources/webinars/:webinar', (req, res) =>

    getPrismic(req, res, 'webinar', req.params.webinar, 'resources/webinars'))

  .get('/sales', (_, res) => res.render('sales'))
  .get('/startups', (_, res) => res.render('startups'))
  .get('/strategysession', (_, res) => res.render('strategysession'))
  .get('/studio', (_, res) => res.render('products/studio'))
  .get('/support', (_, res) => res.render('support'))
  .get('/survey/2017', (_, res) => res.render('survey/2017'))
  .get('/team', (_, res) => res.render('team'))
  .get('/tos', (_, res) => markdown(res, 'tos'))

  .get('/trusted-partners', (_, res) => res.render('trusted-partners'))
  .post('/trusted-partners',
    bp.urlencoded({extended: true}), es(), trustedPartnersCtrl)

  .get('/values', (_, res) => { res.render('values'); })
  .get('/what-is-ionic', (_, res) => res.render('what-is-ionic'))

  // press releases
  .get('/press/release/2017/dev-survey-says-the-web-is-wining-in-mobile-dev',
    (_, res) => markdown(res, 'pr-170725-dev-survey-says-the-web-is-wi'))
  .get('/press/release/2017/ionic-brings-powerful-app-development-suite-to-teams-and-enterprises',
    (_, res) => markdown(res, 'pr-171206-ionic-brings-powerful-app-dev'))

  // JSON endpoints
  .post('/contact', bp.json(), es(), contactCtrl)
  .post('/api/v1/newsletter', bp.json(), es(), newsletterCtrl)
  .post('/api/v1/view/link', bp.json(), es(), viewCtrl)

  // Prismic Preview
  .get('/preview', previewController)
};
<|endoftext|>


<commit_before>// server.js

var express = require('express')
var compression = require('compression')
var expires = require('expires-middleware')
var Application = require('../server/scripts/application.js')

require('../server/scripts/logger.js')

var gApplication = Application.withFullData()

var myPort = process.env.PORT || 8091

var app = express()

app.use(compression())
app.use(expires('24h'))

app.listen(myPort)

// static styles folder
app.use('/styles', express.static('server/styles'))
app.use('/scripts', express.static('server/scripts'))
app.use('/images', express.static('server/images'))

const options = { beautify: false }

app.set('views', __dirname + '/views');
app.set('view engine', 'jsx');
app.engine('jsx', require('express-react-views').createEngine(options));

app.get('/', function (req, resp, next) {
  resp.redirect('/photos')
})

app.get('/photos', function (req, resp, next) {
  logger.debug('/photos')
  resp.render('photos', gApplication.dataForPhotosTemplate())
})

app.get('/videos', function (req, resp, next) {
  logger.debug('/videos')
  resp.render('videos', gApplication.dataForPhotosTemplate())
})

app.get('/photos/dayofyear/:dayofyear', function (req, resp, next) {
  logger.debug('/photos/dayofyear/' + req.params.dayofyear)
  resp.render('photosdayofyear', gApplication.dataForPhotosDayOfYearTemplate(req))
})

app.get('/locations', function (req, resp, next) {
  logger.debug('/locations')
  resp.render('locations', gApplication.dataForLocationsTemplate())
})

app.get('/locations/vr', function (req, resp, next) {
  logger.debug('/locations/vr')
  resp.render('locationsvr', gApplication.dataForLocationsTemplate())
})

app.get('/bigdays', function (req, resp, next) {
  logger.debug('/bigdays')
  resp.render('bigdays', gApplication.dataForBigdaysTemplate())
})

app.get('/family/:family_name', function (req, resp, next) {
  logger.debug('/family/', req.params.family_name)
  resp.render('family', gApplication.dataForFamilyTemplate(req))
})

app.get('/taxons', function (req, resp, next) {
  logger.debug('/taxons')
  resp.render('taxons', gApplication.dataForTaxonsTemplate())
})

app.get('/chrono', function (req, resp, next) {
  resp.render('chrono', gApplication.dataForChronoTemplate())
})

app.get('/taxon/:common_name', function (req, resp, next) {
  logger.debug('/taxon/', req.params.common_name)
  resp.render('taxon', gApplication.dataForTaxonTemplate(req))
})

app.get('/trips', function (req, resp, next) {
  logger.debug('/trips')
  resp.render('trips', gApplication.dataForTripsTemplate())
})

app.get('/search', function (req, resp, next) {
  logger.debug('/search/', req.param.searchtext)
  resp.render('searchresults', gApplication.dataForSearchTemplate(req))
})

app.get('/searchdata', function (req, resp, next) {
  logger.debug('/searchdata/', req.param.searchtext)
  const searchResults = gApplication.dataForSearchTemplate(req)
  resp.json(searchResults.sightingList.getUniqueValues('Common Name'))
})

app.get('/sighting/:sighting_id', function (req, resp, next) {
  logger.debug('/sighting/', req.params.sighting_id)
  resp.render('sighting', gApplication.dataForSightingTemplate(req))
})

app.get('/photo/:photo_id', function (req, resp, next) {
  logger.debug('/photo/', req.params.photo_id)
  resp.render('photo', gApplication.dataForPhotoTemplate(req))
})

// Time Hierarchy

app.get('/time/:year', function (req, resp, next) {
  logger.debug('/year/', req.params.year)
  resp.render('year', gApplication.dataForYearTemplate(req))
})

app.get('/time/:year/:month', function (req, resp, next) {
  logger.debug('/month/', req.params.year, '/', req.params.month)
  resp.render('month', gApplication.dataForYearAndMonthTemplate(req))
})

app.get('/trip/:trip_date', function (req, resp, next) {
  logger.debug('/trip/', req.params.trip_date)
  resp.render('trip', gApplication.dataForTripTemplate(req))
})

// location hierarchy

app.get('/place/:state_name', function (req, resp, next) {
  logger.debug('/state/', req.params.state_name)
  resp.render('state', gApplication.dataForStateTemplate(req))
})

app.get('/place/:state_name/:county_name', function (req, resp, next) {
  logger.debug('/county/')
  resp.render('county', gApplication.dataForCountyTemplate(req))
})

app.get('/place/:state_name/:county_name/:location_name', function (req, resp, next) {
  logger.debug('LOCATION', req.params)
  resp.render('location', gApplication.dataForLocationTemplate(req))
})
<commit_msg>add redirect to new etsy shop<commit_after>// server.js

var express = require('express')
var compression = require('compression')
var expires = require('expires-middleware')
var Application = require('../server/scripts/application.js')

require('../server/scripts/logger.js')

var gApplication = Application.withFullData()

var myPort = process.env.PORT || 8091

var app = express()

app.use(compression())
app.use(expires('24h'))

app.listen(myPort)

// static styles folder
app.use('/styles', express.static('server/styles'))
app.use('/scripts', express.static('server/scripts'))
app.use('/images', express.static('server/images'))

const options = { beautify: false }

app.set('views', __dirname + '/views');
app.set('view engine', 'jsx');
app.engine('jsx', require('express-react-views').createEngine(options));

app.get('/', function (req, resp, next) {
  resp.redirect('/photos')
})

app.get('/photos', function (req, resp, next) {
  logger.debug('/photos')
  resp.render('photos', gApplication.dataForPhotosTemplate())
})

app.get('/videos', function (req, resp, next) {
  logger.debug('/videos')
  resp.render('videos', gApplication.dataForPhotosTemplate())
})

app.get('/shop', function (req, resp, next) {
  logger.debug('/shop')
  resp.redirect('https://www.etsy.com/shop/BirdWalkerShop')
})
app.get('/store', function (req, resp, next) {
  logger.debug('/store')
  resp.redirect('https://www.etsy.com/shop/BirdWalkerShop')
})
app.get('/postcards', function (req, resp, next) {
  logger.debug('/postcards')
  resp.redirect('https://www.etsy.com/shop/BirdWalkerShop')
})

app.get('/photos/dayofyear/:dayofyear', function (req, resp, next) {
  logger.debug('/photos/dayofyear/' + req.params.dayofyear)
  resp.render('photosdayofyear', gApplication.dataForPhotosDayOfYearTemplate(req))
})

app.get('/locations', function (req, resp, next) {
  logger.debug('/locations')
  resp.render('locations', gApplication.dataForLocationsTemplate())
})

app.get('/locations/vr', function (req, resp, next) {
  logger.debug('/locations/vr')
  resp.render('locationsvr', gApplication.dataForLocationsTemplate())
})

app.get('/bigdays', function (req, resp, next) {
  logger.debug('/bigdays')
  resp.render('bigdays', gApplication.dataForBigdaysTemplate())
})

app.get('/family/:family_name', function (req, resp, next) {
  logger.debug('/family/', req.params.family_name)
  resp.render('family', gApplication.dataForFamilyTemplate(req))
})

app.get('/taxons', function (req, resp, next) {
  logger.debug('/taxons')
  resp.render('taxons', gApplication.dataForTaxonsTemplate())
})

app.get('/chrono', function (req, resp, next) {
  resp.render('chrono', gApplication.dataForChronoTemplate())
})

app.get('/taxon/:common_name', function (req, resp, next) {
  logger.debug('/taxon/', req.params.common_name)
  resp.render('taxon', gApplication.dataForTaxonTemplate(req))
})

app.get('/trips', function (req, resp, next) {
  logger.debug('/trips')
  resp.render('trips', gApplication.dataForTripsTemplate())
})

app.get('/search', function (req, resp, next) {
  logger.debug('/search/', req.param.searchtext)
  resp.render('searchresults', gApplication.dataForSearchTemplate(req))
})

app.get('/searchdata', function (req, resp, next) {
  logger.debug('/searchdata/', req.param.searchtext)
  const searchResults = gApplication.dataForSearchTemplate(req)
  resp.json(searchResults.sightingList.getUniqueValues('Common Name'))
})

app.get('/sighting/:sighting_id', function (req, resp, next) {
  logger.debug('/sighting/', req.params.sighting_id)
  resp.render('sighting', gApplication.dataForSightingTemplate(req))
})

app.get('/photo/:photo_id', function (req, resp, next) {
  logger.debug('/photo/', req.params.photo_id)
  resp.render('photo', gApplication.dataForPhotoTemplate(req))
})

// Time Hierarchy

app.get('/time/:year', function (req, resp, next) {
  logger.debug('/year/', req.params.year)
  resp.render('year', gApplication.dataForYearTemplate(req))
})

app.get('/time/:year/:month', function (req, resp, next) {
  logger.debug('/month/', req.params.year, '/', req.params.month)
  resp.render('month', gApplication.dataForYearAndMonthTemplate(req))
})

app.get('/trip/:trip_date', function (req, resp, next) {
  logger.debug('/trip/', req.params.trip_date)
  resp.render('trip', gApplication.dataForTripTemplate(req))
})

// location hierarchy

app.get('/place/:state_name', function (req, resp, next) {
  logger.debug('/state/', req.params.state_name)
  resp.render('state', gApplication.dataForStateTemplate(req))
})

app.get('/place/:state_name/:county_name', function (req, resp, next) {
  logger.debug('/county/')
  resp.render('county', gApplication.dataForCountyTemplate(req))
})

app.get('/place/:state_name/:county_name/:location_name', function (req, resp, next) {
  logger.debug('LOCATION', req.params)
  resp.render('location', gApplication.dataForLocationTemplate(req))
})
<|endoftext|>


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

var Hapi = require('hapi');
var routes = require('./routes');

var server = function() {
	'use strict';

	var configureServerEventListeners = function(server) {
		server.on('log', function(event) {
			console.log(event);
		});
	};

	var configureTv = function(server) {
		var tvOptions = {
			webSocketPort : 3000,
			debugEndpoint : '/debug/console',
			queryKey : 'debug'
		};
		server.pack.require('tv', tvOptions, function(err) {

			if (!err) {
				server.log([ 'info', 'tv' ], 'Loaded plugin');
			} else {
				server.log([ 'error', 'tv' ], 'Failed loading plugin: '
						+ err.message);
			}
		});
	};

	var configureLout = function(server) {
		server.pack.require({
			lout : {
				endpoint : '/docs'
			}
		}, function(err) {

			if (err) {
				console.log('Failed loading plugins');
			}
		});
	};

	var config = {};
	var server = new Hapi.Server('0.0.0.0', 8080, config);
	configureLout(server);
	configureTv(server);

	configureServerEventListeners(server);

	server.addRoutes(routes);

	server.start(function() {
		server.log([ 'info' ], 'server started at : ' + server.info.uri);
	});

};

server();<commit_msg>added logging for more server events to check what the event looks like<commit_after>/**
 * Copyright [2013] [runrightfast.co]
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

var Hapi = require('hapi');
var routes = require('./routes');

var server = function() {
	'use strict';

	var configureServerEventListeners = function(server) {
		server.on('log', function(event) {
			event.serverEvent = 'log';
			console.log(event);
		});

		// request, response, and tail events logging is very verbose
		// //////////////////////////////////////////////////////////
		// server.on('request', function(event) {
		// event.serverEvent = 'log';
		// console.log(event);
		// });
		//
		// server.on('response', function(event) {
		// event.serverEvent = 'response';
		// console.log(event);
		// });
		//
		// server.on('tail', function(event) {
		// event.serverEvent = 'tail';
		// console.log(event);
		// });

		server.on('internalError', function(event) {
			event.serverEvent = 'internalError';
			console.log(event);
		});
	};

	var configureTv = function(server) {
		var tvOptions = {
			webSocketPort : 3000,
			debugEndpoint : '/debug/console',
			queryKey : 'debug'
		};
		server.pack.require('tv', tvOptions, function(err) {

			if (!err) {
				server.log([ 'info', 'tv' ], 'Loaded plugin');
			} else {
				server.log([ 'error', 'tv' ], 'Failed loading plugin: '
						+ err.message);
			}
		});
	};

	var configureLout = function(server) {
		server.pack.require({
			lout : {
				endpoint : '/docs'
			}
		}, function(err) {

			if (err) {
				console.log('Failed loading plugins');
			}
		});
	};

	var config = {};
	var server = new Hapi.Server('0.0.0.0', 8080, config);
	configureLout(server);
	configureTv(server);

	configureServerEventListeners(server);

	server.addRoutes(routes);

	server.start(function() {
		server.log([ 'info' ], 'server started at : ' + server.info.uri);
	});

};

server();<|endoftext|>


<commit_before>var
  _       = require('lodash'),
  express = require('express'),
  fs      = require('fs'),
  http    = require('http'),
  mkdirp  = require('mkdirp'),
  path    = require('path'),
  request = require('request'),
  url     = require('url'),

  port    = 8080
;

var folders = {
  articles: './../content/articles',
  config:   './../content/config',
  media:    './../content/media',
  metadata: './../content/metadata'
};

// Ensure the required folders exist.
Object.keys(folders).forEach(function(folder) {
  mkdirp(folders[folder], function(){});
});

var modules = {
  article: require('./modules/article.js'),
  config:  require('./modules/config.js'),
  media:   require('./modules/media.js'),
  search:  require('./modules/search.js')
};

var app = express();
app.use('/api/w', modules.article);
app.use('/api/config', modules.config);
app.use('/api/search', modules.search);
app.use('/media', modules.media);

_.forEach(['js', 'font', 'images', 'styles'], function(el) {
  app.use('/' + el, express.static(path.join(__dirname, '../build/develop/' + el)));
});

app.get('*', function (req, res) {
  fs.createReadStream(path.join(__dirname, '../build/develop', 'index.html'))
    .pipe(res);
});

http.createServer(app).listen(port, function() {
  console.log('Express server running on port ' + port);
});<commit_msg>Content directories are forced to be relative<commit_after>var
  _       = require('lodash'),
  express = require('express'),
  fs      = require('fs'),
  http    = require('http'),
  mkdirp  = require('mkdirp'),
  path    = require('path'),
  request = require('request'),
  url     = require('url'),

  port    = 8080
;

var folders = {
  articles: path.join(__dirname, '../content/articles'),
  config:   path.join(__dirname, '../content/config'),
  media:    path.join(__dirname, '../content/media'),
  metadata: path.join(__dirname, '../content/metadata')
};

// Ensure the required folders exist.
Object.keys(folders).forEach(function(folder) {
  mkdirp(folders[folder], function(){});
});

var modules = {
  article: require('./modules/article.js'),
  config:  require('./modules/config.js'),
  media:   require('./modules/media.js'),
  search:  require('./modules/search.js')
};

var app = express();
app.use('/api/w', modules.article);
app.use('/api/config', modules.config);
app.use('/api/search', modules.search);
app.use('/media', modules.media);

_.forEach(['js', 'font', 'images', 'styles'], function(el) {
  app.use('/' + el, express.static(path.join(__dirname, '../build/develop/' + el)));
});

app.get('*', function (req, res) {
  fs.createReadStream(path.join(__dirname, '../build/develop', 'index.html'))
    .pipe(res);
});

http.createServer(app).listen(port, function() {
  console.log('Express server running on port ' + port);
});<|endoftext|>


<commit_before>var path = require('path');
var express = require('express');
var app = express();
var http = require('http').Server(app);
var io = require('socket.io')(http);

var users = [];
var foods = [];
var sockets = [];

var maxSizeMass = 50;
var maxMoveSpeed = 100;

var massDecreaseRatio = 1000;

var foodMass = 1;

var newFoodPerPlayer = 3;
var respawnFoodPerPlayer = 1;

var foodRandomWidth = 500;
var foodRandomHeight = 500;
var maxFoodCount = 50;

var noPlayer = 0;

var defaultPlayerSize = 10;

var eatableMassDistance = 5;

app.use(express.static(__dirname + '/../client'));

function genPos(from, to) {
    return Math.floor(Math.random() * to) + from;
}

function addFoods(target) {
    foods.push({
        id: (new Date()).getTime(),
        x: genPos(0, target.screenWidth),
        y: genPos(0, target.screenHeight)
    });
}

function generateFood(target) {
    if (foods.length < maxFoodCount) {
        addFoods(target);
    }
}

// arr is for example users or foods
function findIndex(arr, id) {
    var len = arr.length;

    while (len--) {
        if (arr[len].id === id) {
            return len;
        }
    }

    return -1;

}

function findPlayer(id) {
    var index = findIndex(users, id);

    return index !== -1 ? users[index] : null;
}

function hitTest(start, end, min) {
    var distance = Math.sqrt((start.x - end.x) * (start.x - end.x) + (start.y - end.y) * (start.y - end.y));
    return (distance <= min);
}

io.on('connection', function (socket) {
    console.log('A user connected. Assigning UserID...');

    var userID = socket.id;
    var currentPlayer = {};

    socket.emit("welcome", userID);

    socket.on("gotit", function (player) {
        player.id = userID;
        sockets[player.id] = socket;

        if (findPlayer(player.id) == null) {
            console.log("Player " + player.id + " connected!");
            users.push(player);
            currentPlayer = player;
        }

        io.emit('playerJoin', {playersList: users, connectedName: player.name});
        console.log("Total player: " + users.length);

        // Add new food when player connected
        for (var i = 0; i < newFoodPerPlayer; i++) {
            generateFood(player);
        }
    });

    socket.on("ping", function () {
        socket.emit("pong");
    });

    socket.on('disconnect', function () {
        var playerIndex = findIndex(users, userID);
        var playerName = users[playerIndex].name;
        users.splice(playerIndex, 1);
        console.log('User #' + userID + ' disconnected');
        socket.broadcast.emit("playerDisconnect", {playersList: users, disconnectName: playerName});
    });

    socket.on("playerChat", function (data) {
        var _sender = data.sender.replace(/(<([^>]+)>)/ig, "");
        var _message = data.message.replace(/(<([^>]+)>)/ig, "");
        socket.broadcast.emit("serverSendPlayerChat", {sender: _sender, message: _message});
    });

    // Heartbeat function, update everytime
    socket.on("playerSendTarget", function (target) {
        if (target.x != currentPlayer.x && target.y != currentPlayer.y) {
            currentPlayer.x += (target.x - currentPlayer.x) / currentPlayer.speed;
            currentPlayer.y += (target.y - currentPlayer.y) / currentPlayer.speed;

            for (var f = 0; f < foods.length; f++) {
                if (hitTest(
                        {x: foods[f].x, y: foods[f].y},
                        {x: currentPlayer.x, y: currentPlayer.y},
                        currentPlayer.mass + defaultPlayerSize
                    )) {
                    foods[f] = {};
                    foods.splice(f, 1);

                    if (currentPlayer.mass < maxSizeMass) {
                        currentPlayer.mass += foodMass;
                    }

                    if (currentPlayer.speed < maxMoveSpeed) {
                        currentPlayer.speed += currentPlayer.mass / massDecreaseRatio;
                    }

                    console.log("Food eaten");

                    // Respawn food
                    for (var r = 0; r < respawnFoodPerPlayer; r++) {
                        generateFood(currentPlayer);
                    }
                    break;
                }
            }

            for (var e = 0; e < users.length; e++) {
                if (hitTest(
                        {x: users[e].x, y: users[e].y},
                        {x: currentPlayer.x, y: currentPlayer.y},
                        currentPlayer.mass + defaultPlayerSize
                    )) {
                    if (users[e].mass != 0 && users[e].mass < currentPlayer.mass - eatableMassDistance) {
                        if (currentPlayer.mass < maxSizeMass) {
                            currentPlayer.mass += users[e].mass;
                        }

                        if (currentPlayer.speed < maxMoveSpeed) {
                            currentPlayer.speed += currentPlayer.mass / massDecreaseRatio;
                        }

                        sockets[users[e].id].emit("RIP");
                        sockets[users[e].id].disconnect();
                        users.splice(e, 1);
                        break;
                    }
                }
            }

            // Do some continuos emit
            socket.emit("serverTellPlayerMove", currentPlayer);
            socket.emit("serverTellPlayerUpdateFoods", foods);
            socket.broadcast.emit("serverUpdateAllPlayers", users);
            socket.broadcast.emit("serverUpdateAllFoods", foods);
        }
    });
});

// Don't touch on ip
var ipaddress = process.env.OPENSHIFT_NODEJS_IP || process.env.IP || "127.0.0.1";
var serverport = process.env.OPENSHIFT_NODEJS_PORT || process.env.PORT || 3000;
http.listen( serverport, ipaddress, function() {
    console.log('listening on *:' + serverport);
});
<commit_msg>replace double quotes with single quotes to be consistent<commit_after>var path = require('path');
var express = require('express');
var app = express();
var http = require('http').Server(app);
var io = require('socket.io')(http);

var users = [];
var foods = [];
var sockets = [];

var maxSizeMass = 50;
var maxMoveSpeed = 100;

var massDecreaseRatio = 1000;

var foodMass = 1;

var newFoodPerPlayer = 3;
var respawnFoodPerPlayer = 1;

var foodRandomWidth = 500;
var foodRandomHeight = 500;
var maxFoodCount = 50;

var noPlayer = 0;

var defaultPlayerSize = 10;

var eatableMassDistance = 5;

app.use(express.static(__dirname + '/../client'));

function genPos(from, to) {
    return Math.floor(Math.random() * to) + from;
}

function addFoods(target) {
    foods.push({
        id: (new Date()).getTime(),
        x: genPos(0, target.screenWidth),
        y: genPos(0, target.screenHeight)
    });
}

function generateFood(target) {
    if (foods.length < maxFoodCount) {
        addFoods(target);
    }
}

// arr is for example users or foods
function findIndex(arr, id) {
    var len = arr.length;

    while (len--) {
        if (arr[len].id === id) {
            return len;
        }
    }

    return -1;

}

function findPlayer(id) {
    var index = findIndex(users, id);

    return index !== -1 ? users[index] : null;
}

function hitTest(start, end, min) {
    var distance = Math.sqrt((start.x - end.x) * (start.x - end.x) + (start.y - end.y) * (start.y - end.y));
    return (distance <= min);
}

io.on('connection', function (socket) {
    console.log('A user connected. Assigning UserID...');

    var userID = socket.id;
    var currentPlayer = {};

    socket.emit('welcome', userID);

    socket.on('gotit', function (player) {
        player.id = userID;
        sockets[player.id] = socket;

        if (findPlayer(player.id) == null) {
            console.log('Player ' + player.id + ' connected!');
            users.push(player);
            currentPlayer = player;
        }

        io.emit('playerJoin', {playersList: users, connectedName: player.name});
        console.log('Total player: ' + users.length);

        // Add new food when player connected
        for (var i = 0; i < newFoodPerPlayer; i++) {
            generateFood(player);
        }
    });

    socket.on('ping', function () {
        socket.emit('pong');
    });

    socket.on('disconnect', function () {
        var playerIndex = findIndex(users, userID);
        var playerName = users[playerIndex].name;
        users.splice(playerIndex, 1);
        console.log('User #' + userID + ' disconnected');
        socket.broadcast.emit('playerDisconnect', {playersList: users, disconnectName: playerName});
    });

    socket.on('playerChat', function (data) {
        var _sender = data.sender.replace(/(<([^>]+)>)/ig, '');
        var _message = data.message.replace(/(<([^>]+)>)/ig, '');
        socket.broadcast.emit('serverSendPlayerChat', {sender: _sender, message: _message});
    });

    // Heartbeat function, update everytime
    socket.on('playerSendTarget', function (target) {
        if (target.x != currentPlayer.x && target.y != currentPlayer.y) {
            currentPlayer.x += (target.x - currentPlayer.x) / currentPlayer.speed;
            currentPlayer.y += (target.y - currentPlayer.y) / currentPlayer.speed;

            for (var f = 0; f < foods.length; f++) {
                if (hitTest(
                        {x: foods[f].x, y: foods[f].y},
                        {x: currentPlayer.x, y: currentPlayer.y},
                        currentPlayer.mass + defaultPlayerSize
                    )) {
                    foods[f] = {};
                    foods.splice(f, 1);

                    if (currentPlayer.mass < maxSizeMass) {
                        currentPlayer.mass += foodMass;
                    }

                    if (currentPlayer.speed < maxMoveSpeed) {
                        currentPlayer.speed += currentPlayer.mass / massDecreaseRatio;
                    }

                    console.log('Food eaten');

                    // Respawn food
                    for (var r = 0; r < respawnFoodPerPlayer; r++) {
                        generateFood(currentPlayer);
                    }
                    break;
                }
            }

            for (var e = 0; e < users.length; e++) {
                if (hitTest(
                        {x: users[e].x, y: users[e].y},
                        {x: currentPlayer.x, y: currentPlayer.y},
                        currentPlayer.mass + defaultPlayerSize
                    )) {
                    if (users[e].mass != 0 && users[e].mass < currentPlayer.mass - eatableMassDistance) {
                        if (currentPlayer.mass < maxSizeMass) {
                            currentPlayer.mass += users[e].mass;
                        }

                        if (currentPlayer.speed < maxMoveSpeed) {
                            currentPlayer.speed += currentPlayer.mass / massDecreaseRatio;
                        }

                        sockets[users[e].id].emit('RIP');
                        sockets[users[e].id].disconnect();
                        users.splice(e, 1);
                        break;
                    }
                }
            }

            // Do some continuos emit
            socket.emit('serverTellPlayerMove', currentPlayer);
            socket.emit('serverTellPlayerUpdateFoods', foods);
            socket.broadcast.emit('serverUpdateAllPlayers', users);
            socket.broadcast.emit('serverUpdateAllFoods', foods);
        }
    });
});

// Don't touch on ip
var ipaddress = process.env.OPENSHIFT_NODEJS_IP || process.env.IP || '127.0.0.1';
var serverport = process.env.OPENSHIFT_NODEJS_PORT || process.env.PORT || 3000;
http.listen( serverport, ipaddress, function() {
    console.log('listening on *:' + serverport);
});
<|endoftext|>


<commit_before>// server.js
var express  = require('express.io');
var mongoose = require('mongoose');
var flash    = require('connect-flash');
var path     = require('path');
var compress = require('compression');
var favicon  = require('serve-favicon');
var cors     = require('cors');
var morgan   = require('morgan');
var session  = require('express-session');
var multipart = require('connect-multiparty');
var bodyParser = require('body-parser');
var cookieParser = require('cookie-parser');
var clientSession = require('client-sessions');
var fs = require('fs');
var _ = require('lodash');

// api
var api = require('../api/api');
var config = api.config;
var port = config.port;

// socket enabled server
var app = express().http().io();

// connect to our database
var sessionStore = mongoose.connect(config.mongo.url);

// set up our express application
app.use(bodyParser.urlencoded({limit: '2000mb', extended : true}));
app.use(bodyParser.json({limit:'2000mb'}));
app.set('view engine', 'ejs'); // set up ejs for templating
app.use(multipart()); // for resumable.js uploads

// cookie session options
var sessionOptions = {
	cookieName: 'session',
	secret: 'eg[isfd-8yF9-7w2335df{}+Ijsli;;to8',
	duration: 3 * 24 * 60 * 60 * 1000, // 3d
	activeDuration: 60 * 60 * 10000, // 10h
	cookie: {
		path: '/',
		ephemeral: false, // when true, cookie expires when the browser closes
		httpOnly: true, // when true, cookie is not accessible from javascript
		secureProxy : true,
	}
};

// use cookie session
app.use(clientSession(sessionOptions));

// socket auth middleware
app.io.use(socket_auth_middleware);

// set favicon
app.use(favicon(__dirname + '/../public/images/favicon.ico'));

// enable compression
app.use(compress());

// enable cors
app.use(cors());

// static files
var staticPath = '../public';
app.use(express.static(path.join(__dirname, staticPath)));
app.use(express.static(process.cwd() + '../views/debug'));

// catch route errors
app.use(function(err, req, res, next){
	err.status === 400 ? res.render('../../views/index.ejs') : next(err);
});

// load our routes and pass in our app
require('../routes/routes.js')(app);

// load our socket api
require('../routes/socket.routes.js')(app);

console.log('####')
console.log('####')
console.log('####')
console.log('####')
console.log('####')
console.log('mongo debug');

// ensure admin user is present
sessionStore.connection.on('open', function (ref) {

	// launch
	var server = app.listen(port);

	console.log('The magic happens @ ', port);

  	console.log('Connected to mongo server.');
  	// create admin user
	api.user.ensureAdminUser(function (err, options) {
		if (err) return console.log('There was an error creating mapic-admin user.', err);
		if (options.created) {
			console.log('User mapic-admin has been created. Log in to the portal with these credentials:')
			console.log('Email:', options.user.local.email);
			console.log('Password:', options.password);
		}
	});
});

// helper fn
function socket_auth_middleware (socket, next) {
	try {
	if (!socket || !socket.headers || !socket.headers.cookie) return next(new Error('No socket, fatal.'));
	var c = socket.headers.cookie;
	var session_cookie_raw = _.find(c.split('; '), function (sc) {
		return _.includes(sc, 'session');
	});
	if (!session_cookie_raw) return next(new Error('No session.'));
	var session_cookie = session_cookie_raw.split('=')[1];
	if (!session_cookie) return next(new Error('No session.'));
	var decoded_cookie = clientSession.util.decode(sessionOptions, session_cookie);
	if (!decoded_cookie) return next(new Error('Invalid access token.'));
	var tokens = decoded_cookie.content ? decoded_cookie.content.tokens : false;
	if (!tokens || !tokens.access_token) return next(new Error('Invalid access token.')); // public will fail here, returns 500...
	api.token._authenticate(tokens.access_token, function (err, user) {
		if (err) return next(err);
		socket.session = socket.session || {};
		socket.session.user_id = user._id;
		next();
	});
	} catch (e) {
		next(new Error('Something went wrong.'));
	}
}

<commit_msg>cleanup<commit_after>// server.js
var express  = require('express.io');
var mongoose = require('mongoose');
var flash    = require('connect-flash');
var path     = require('path');
var compress = require('compression');
var favicon  = require('serve-favicon');
var cors     = require('cors');
var morgan   = require('morgan');
var session  = require('express-session');
var multipart = require('connect-multiparty');
var bodyParser = require('body-parser');
var cookieParser = require('cookie-parser');
var clientSession = require('client-sessions');
var fs = require('fs');
var _ = require('lodash');

// api
var api = require('../api/api');
var config = api.config;
var port = config.port;

// socket enabled server
var app = express().http().io();

// connect to our database
var sessionStore = mongoose.connect(config.mongo.url);

// set up our express application
app.use(bodyParser.urlencoded({limit: '2000mb', extended : true}));
app.use(bodyParser.json({limit:'2000mb'}));
app.set('view engine', 'ejs'); // set up ejs for templating
app.use(multipart()); // for resumable.js uploads

// cookie session options
var sessionOptions = {
	cookieName: 'session',
	secret: 'eg[isfd-8yF9-7w2335df{}+Ijsli;;to8',
	duration: 3 * 24 * 60 * 60 * 1000, // 3d
	activeDuration: 60 * 60 * 10000, // 10h
	cookie: {
		path: '/',
		ephemeral: false, // when true, cookie expires when the browser closes
		httpOnly: true, // when true, cookie is not accessible from javascript
		secureProxy : true,
	}
};

// use cookie session
app.use(clientSession(sessionOptions));

// socket auth middleware
app.io.use(socket_auth_middleware);

// set favicon
app.use(favicon(__dirname + '/../public/images/favicon.ico'));

// enable compression
app.use(compress());

// enable cors
app.use(cors());

// static files
var staticPath = '../public';
app.use(express.static(path.join(__dirname, staticPath)));
app.use(express.static(process.cwd() + '../views/debug'));

// catch route errors
app.use(function(err, req, res, next){
	err.status === 400 ? res.render('../../views/index.ejs') : next(err);
});

// load our routes and pass in our app
require('../routes/routes.js')(app);

// load our socket api
require('../routes/socket.routes.js')(app);

// when mongoose is ready
sessionStore.connection.on('open', function (ref) {

	// launch
	var server = app.listen(port);
	console.log('The magic happens @ ', port);

  	// create admin user
	api.user.ensureAdminUser(function (err, options) {
		if (err) return console.log('There was an error creating mapic-admin user.', err);
		if (options.created) {
			console.log('User mapic-admin has been created. Log in to the portal with these credentials:')
			console.log('Email:', options.user.local.email);
			console.log('Password:', options.password);
		}
	});
});

// helper fn
function socket_auth_middleware (socket, next) {
	try {
	if (!socket || !socket.headers || !socket.headers.cookie) return next(new Error('No socket, fatal.'));
	var c = socket.headers.cookie;
	var session_cookie_raw = _.find(c.split('; '), function (sc) {
		return _.includes(sc, 'session');
	});
	if (!session_cookie_raw) return next(new Error('No session.'));
	var session_cookie = session_cookie_raw.split('=')[1];
	if (!session_cookie) return next(new Error('No session.'));
	var decoded_cookie = clientSession.util.decode(sessionOptions, session_cookie);
	if (!decoded_cookie) return next(new Error('Invalid access token.'));
	var tokens = decoded_cookie.content ? decoded_cookie.content.tokens : false;
	if (!tokens || !tokens.access_token) return next(new Error('Invalid access token.')); // public will fail here, returns 500...
	api.token._authenticate(tokens.access_token, function (err, user) {
		if (err) return next(err);
		socket.session = socket.session || {};
		socket.session.user_id = user._id;
		next();
	});
	} catch (e) {
		next(new Error('Something went wrong.'));
	}
}

process.on('uncaughtException', function(err) {
	// todo: add sentry.io
    console.log('Uncaught Exception!', err);
    throw new Error(err);
});

<|endoftext|>


<commit_before>import path from 'path';
import fs from 'fs';
import express from 'express';
import morgan from 'morgan';
import moment from 'moment-timezone';
import bunyan from 'bunyan';
import bunyanPretty from 'bunyan-pretty';
import * as Sentry from '@sentry/node';
import cookieParser from 'cookie-parser';
import render from './render';
import config from './env';
import healthCheck from './health';

moment.locale('nb-NO');
const app = express();

app.use(Sentry.Handlers.requestHandler());
app.use(cookieParser());

const log = bunyan.createLogger({
  name: 'lego-webapp',
  release: config.release,
  stream: process.stdout.isTTY ? bunyanPretty() : process.stdout,
  environment: config.environment,
});

app.set('host', config.host || '0.0.0.0');
app.set('port', config.port || 3000);
app.set('log', log);

const webpackClient = require('../config/webpack.client.js');

if (__DEV__) {
  const compiler = require('webpack')(
    webpackClient(undefined, {
      mode: 'development',
    })
  );
  app.use(
    require('webpack-dev-middleware')(compiler, {
      publicPath: webpackClient.publicPath,
      quiet: true,
      stats: {
        all: false,
        modules: false,
        errors: true,
        warnings: true,
        moduleTrace: true,
        errorDetails: true,
      },
    })
  );

  app.use(
    require('webpack-hot-middleware')(compiler, {
      log: false,
    })
  );
}

app.get('/healthz', healthCheck);

const styleguide = path.join(__dirname, '../styleguide');
if (fs.existsSync(styleguide)) {
  app.use('/styleguide', express.static(styleguide));
}

app.use(express.static(webpackClient.outputPath));
app.use(
  morgan((tokens, req, res) => {
    log.info(
      {
        method: tokens.method(req, res),
        url: tokens.url(req, res),
        status: tokens.status(req, res),
        'content-length': tokens.res(req, res, 'content-length'),
        'response-time': tokens['response-time'](req, res),
      },
      'request'
    );
  })
);

app.use(render);

app.use((req, res) => {
  res.status(404).send({
    message: 'Not Found',
  });
});

app.use(Sentry.Handlers.errorHandler());

app.use((err, req, res, next) => {
  log.error(err, 'internal_error');
  res.statusCode = 500;
  res.end('Internal Error');
});

export default app;
<commit_msg>Add simple config endpoint<commit_after>import path from 'path';
import fs from 'fs';
import express from 'express';
import morgan from 'morgan';
import moment from 'moment-timezone';
import bunyan from 'bunyan';
import bunyanPretty from 'bunyan-pretty';
import * as Sentry from '@sentry/node';
import cookieParser from 'cookie-parser';
import render from './render';
import config from './env';
import baseConfig from 'config/env';
import healthCheck from './health';

moment.locale('nb-NO');
const app = express();

app.use(Sentry.Handlers.requestHandler());
app.use(cookieParser());

const log = bunyan.createLogger({
  name: 'lego-webapp',
  release: config.release,
  stream: process.stdout.isTTY ? bunyanPretty() : process.stdout,
  environment: config.environment,
});

app.set('host', config.host || '0.0.0.0');
app.set('port', config.port || 3000);
app.set('log', log);

const webpackClient = require('../config/webpack.client.js');

if (__DEV__) {
  const compiler = require('webpack')(
    webpackClient(undefined, {
      mode: 'development',
    })
  );
  app.use(
    require('webpack-dev-middleware')(compiler, {
      publicPath: webpackClient.publicPath,
      quiet: true,
      stats: {
        all: false,
        modules: false,
        errors: true,
        warnings: true,
        moduleTrace: true,
        errorDetails: true,
      },
    })
  );

  app.use(
    require('webpack-hot-middleware')(compiler, {
      log: false,
    })
  );
}

app.get('/healthz', healthCheck);

const styleguide = path.join(__dirname, '../styleguide');
if (fs.existsSync(styleguide)) {
  app.use('/styleguide', express.static(styleguide));
}

app.use(express.static(webpackClient.outputPath));
app.use(
  morgan((tokens, req, res) => {
    log.info(
      {
        method: tokens.method(req, res),
        url: tokens.url(req, res),
        status: tokens.status(req, res),
        'content-length': tokens.res(req, res, 'content-length'),
        'response-time': tokens['response-time'](req, res),
      },
      'request'
    );
  })
);

app.get('/_config', (_, res) => res.json(baseConfig));
app.use(render);

app.use((req, res) => {
  res.status(404).send({
    message: 'Not Found',
  });
});

app.use(Sentry.Handlers.errorHandler());

app.use((err, req, res, next) => {
  log.error(err, 'internal_error');
  res.statusCode = 500;
  res.end('Internal Error');
});

export default app;
<|endoftext|>