WebFund 2014W Midterm Review

From Soma-notes
Revision as of 19:27, 11 February 2014 by Soma (talk | contribs)

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');
var path = require('path');
var http = require('http');
var MongoStore = require('connect-mongo')(express);

var app = express();

app.set('port', process.env.PORT || 3000);
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) {
    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