Difference between revisions of "WebFund 2014W Midterm Review"

From Soma-notes
Jump to navigation Jump to search
Line 13: Line 13:
<source line lang="javascript">
<source line lang="javascript">
var express = require('express');
var express = require('express');
var routes = require('./routes'); //the require
var routes = require('./routes'); //same as ('/routes/index.js'). The require() method returns the exports object
var path = require('path');
var path = require('path'); //imports the path module, or path.join will not be defined
var http = require('http');
var http = require('http');
var MongoStore = require('connect-mongo')(express);
var MongoStore = require('connect-mongo')(express);


var app = express();
var app = express(); //creates an express object instance and assigns the app variable to it.


app.set('port', process.env.PORT || 3000);
app.set('port', process.env.PORT || 3000); //listens on PORT environment variable OR port 3000 if not defined
app.set('views', path.join(__dirname, 'views'));
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
app.set('view engine', 'jade');

Revision as of 13:32, 13 March 2014

The video from the lecture given on Feb. 12, 2014 is available:

The midterm will be based on small-adventure, a version of adventure-demo that has been simplified by removing the use of cryptography (https and bcrypt) along with a few other minor tweaks to reduce the size of the source code.

No new tutorial this week; however, two TAs/instructors will be in the lab on Thursday 4-5:30 and Friday 8:30-10 to answer last minute questions.

Source for small-adventure

app.js

var express = require('express');
var routes = require('./routes'); //same as ('/routes/index.js'). The require() method returns the exports object
var path = require('path'); //imports the path module, or path.join will not be defined
var http = require('http');
var MongoStore = require('connect-mongo')(express);

var app = express(); //creates an express object instance and assigns the app variable to it.

app.set('port', process.env.PORT || 3000); //listens on PORT environment variable OR port 3000 if not defined
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.urlencoded());

app.use(express.cookieParser());
app.use(express.session({
    cookie: {maxAge: 60000 * 20} // 20 minutes
    , secret: "Shh... I'm a secret"
    , store: new MongoStore({db: "adventure-demo"})
}));

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

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

app.get('/', routes.redirectLoggedIn, routes.index);
app.post("/register", routes.register);
app.post("/start", routes.start);
app.post("/quit", routes.quit);

var createRooms = function() {
    var i, theRoom;

    routes.getRooms().toArray(
        function(err, docs) {
            if (err) {
                throw "Couldn't find active room list";
            }
            
            var activeRooms = docs[0].activeRooms;

            activeRooms.forEach(function(roomName) {
                console.log('Creating room: ' + roomName);
                app.get('/' + roomName,
                        routes.makeRoomHandler(roomName));
            });
        }
    );
}
routes.connectToDBs(createRooms);

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


routes/index.js

var mc = require('mongodb').MongoClient;
var playersCollection, roomsCollection;
exports.connectToDBs = function(callback) {
    mc.connect('mongodb://localhost/adventure-demo', function(err, db) {
        if (err) {
            throw err;
        }
        
        playersCollection = db.collection('players');
        roomsCollection = db.collection('rooms');

        callback();
    });
}
exports.index = function(req, res){
    res.render('index', { title: 'COMP 2406 Small Adventure Demo',
                          error: req.query.error });
}
exports.redirectLoggedIn = function(req, res, next) {
    if (req.session.player) {
        res.redirect("/" + req.session.player.room);
    } else {
        next();
    }
}
exports.redirectNotLoggedIn = function(req, res, next) {
    if (req.session.player) {
        next();
    } else {
        res.redirect("/");
    }
}
exports.register = function(req, res) {
    var playername = req.body.playername;
    var password = req.body.password;

    var addPlayer = function(err, players) {
        if(players.length!=0){
            res.redirect("/?error=player already exists");      
            return;
        }
        
        var newPlayer = {
            playername: playername,
            password: password,
            room: "bridge"
        };
                
        playersCollection.insert(newPlayer, function(err, newPlayers){
            if (err) {
                throw err;
            } else {
                res.send('Successfully registered ' + newPlayers[0].playername);
            }
        });    
    }
    
    playersCollection.find({playername: playername}).toArray(addPlayer);
}
exports.start = function(req, res){
    var playername = req.body.playername;
    var password = req.body.password;

    playersCollection.findOne({playername: playername}, function(err, player) {
        if (err || !player){
            req.session.destroy(function(err) {
                res.redirect("/?error=invalid playername or password"); 
            });
            return;
        }
        
        if (password === player.password) {
            req.session.player = player;
            delete req.session.player._id;
            res.redirect("/" + player.room);
        } else {
            req.session.destroy(function(err) {
                res.redirect("/?error=invalid playername or password");
            });
        }
    });
}
exports.quit = function(req, res){
    req.session.destroy(function(err){
        if(err){
            console.log("Error: %s", err);
        }
        res.redirect("/");
    }); 
}
exports.makeRoomHandler = function(roomName) {
    var handler = function(req, res) {
        if (req.session.player) {
            var player = req.session.player;
            player.room = roomName;
            playersCollection.update({"playername": player.playername},
                                     player, function(err, count) {
                                         if (err) {
                                             console.log(
                                                 "Couldn't save player state");
                                         }
                                     });
            roomsCollection.findOne(
                {name: roomName},
                function(err, room) {
                    if (err || !room) {
                        throw "Couldn't find room " + roomName;
                    }
                    res.render("room.jade", room);
                }
            );
        } else {
            res.redirect("/");
        }
    }
    return handler;
}
exports.getRooms = function() {
    return roomsCollection.find({name: "roomList"});
}

public/javascripts/home.js

$(function(){
	$("#register").on("click",function(){
		var $form = $("form");
		$form.attr("action","/register");
		$form.submit();
	});
});


views/layout.jade

doctype html
html
  head
    title= title
    script(src='/vendor/jquery/jquery.js')
    script('vendor/bootstrap/dist/js/bootstrap.js')
    link(rel='stylesheet', href='/vendor/bootstrap/dist/css/bootstrap.css')
    link(rel='stylesheet', href='/stylesheets/style.css')
    block header  
  body
    block content


views/index.jade

extends layout

block header
  script(src='/javascripts/home.js')

block content
  h1= title
  - if(error)
    div.alert-error #{error}
  p Please log in
  div
    form(action="/start", method="post")
        div.control-group.input-append
            input(type="text", name="playername")
            label.add-on(for="playername") Player Name
        div.control-group.input-append
            input(type="password", name="password")
            label.add-on(for="password") Password
            
        button(type="submit") Start
        button#register(type="button") Register


views/room.jade

extends layout

block content
  h1= title
  p #{description}
  p Go to:
  ul
    each theExit in roomExits
      li
        a(href= theExit) #{theExit}
  form(action="/quit", method="post")
     button(type="submit") Quit