UNPKG

ripple-core

Version:

Ripple is an interactive audience response system that allows presenters to survey audience members in real time communication through their mobile devices.

242 lines (217 loc) 7.31 kB
// use moment.js for pretty date-stamping // var DB = require('./db-manager.js') , moment = require('moment') , logger = require('./log') , log = logger.logPair , async = require('async') , sanitize = require('validator').sanitize , GLOBALS = require('./globals'); var util = require('util'); var SSM = {}; SSM.dbSession = DB.init.collection('sessions'); SSM.dbQuestions = DB.init.collection('questions'); SSM.dbResponse = DB.init.collection('responses'); module.exports = SSM; // Store question SSM.questionSent = function(question, callback){ var sessionID = question.qSessionID; SSM.saveQuestion(sessionID, question,function (err, qID, sessionID){ if( !err ) { logger.debugPair('[SSM.questionSent] qID', qID); logger.debugPair('[SSM.questionSent] sessionID', sessionID); callback(qID, sessionID); } else { logger.errorPair('[SSM.questionSent] Error', err); callback(null, null); } }); } SSM.createSession = function(req, fnCallback){ req.session.rippleSession = req.session.rippleSession || {}; var sessionID = req.session.rippleSession.id; // Check to see if session ID is already created if( !sessionID ) { // Clear out rippleSession Object req.session.rippleSession = {}; logger.log("Creating Session ID"); var session = {} , currentTime = new Date(); // Define Session Data session.startTime = currentTime; session.author = req.session.user._id; req.session.question = req.session.question || {}; // Determine Expire Time var expireTime = GLOBALS.helperFn.setSessionExpire(req.session); if( expireTime ) { req.session.rippleSession.expireTime = expireTime; session.expireTime = expireTime; } // Create Session SSM.dbSession.insert(session, function(err, record){ if( !err ) { log('Session ID Created', record[0]._id) req.session.rippleSession.id = record[0]._id; fnCallback(null); } else fnCallback(err); }) } else { log('Session ID', sessionID); req.session.rippleSession.reload = true; fnCallback(null); } } SSM.saveQuestion = function(sessionID, question, fnCallback){ var sID = DB.convertToObjID(sessionID); var qID = DB.getObjID(); delete question.qSessionID; delete question.authorID; question.qID = qID; logger.debugPair("[SSM.saveQuestion] Submitted Question Data",util.inspect(question) ); SSM.dbSession.update({'_id': sID }, {'$push':{'questions':question}}, function(err, record) { if(!err) logger.log("Inserted Question Record in " + sessionID); fnCallback(err, qID, sID); }); } SSM.saveAnswer = function(answer, nowQuestion, clientName){ var err; logger.debugPair("[SSM.saveAnswer] Now Quesiton", util.inspect(nowQuestion) ); // Check for need variables if( arguments.length === 0 ){ logger.error("No parameters passed to function saveAnswer"); return false; } if( typeof nowQuestion == "undefined"){ logger.error("Question object is not found"); return false; } if( !( nowQuestion.hasOwnProperty('qID') && nowQuestion.qID != '' ) ) { logger.error("Question ID is not present"); return false; } if( !( nowQuestion.hasOwnProperty('qSessionID') && nowQuestion.qSessionID != '' ) ) { logger.error("Session ID is not present"); return false; } // Validate and Save async.waterfall([ (SSM.VALID.answer).bind(null, answer, nowQuestion, clientName), insertAnswerDB ], function(err, result){ if( !err ) { log("[SSM.saveAnswer] Answer saved to db", result); return true; } else { logger.errorPair("Error Saving Answer", err); return false; } }); } SSM.VALID = {}; SSM.VALID.answer = function(answer, nowQuestion, clientName, callback){ var err = null; logger.debugPair("Validating...") // Check for valid answers switch(nowQuestion.type){ case 'true-false': err = SSM.VALID.true(answer); break case 'multiple-choice': err = SSM.VALID.mc(answer); break; case 'slider': err = SSM.VALID.numeric(answer); break; case 'numeric': err = SSM.VALID.numeric(answer); break; case 'cloud': err = SSM.VALID.singleWord(answer); break; } if( err ) logger.errorPair("ERROR Validating", err) else logger.debugPair("Valid Answer", answer); callback(err, answer, nowQuestion, clientName); } SSM.VALID.true = function(answer){ var errMsg = null; if( !(answer === "True" || answer === "False" ) ) errMsg = "True/False can not have the answer - " + answer; return errMsg; } SSM.VALID.mc = function(answer){ var errMsg = null , pattern = /^[A-Za-z]{1}$/; if( !pattern.test(answer) ) errMsg = "Multiple Choice can not have the answer - " + answer; return errMsg; } SSM.VALID.numeric = function(answer){ var errMsg = null; if( isNaN( parseFloat(answer) ) || !isFinite( answer ) ) errMsg = "Answer is not a valid number - " + answer; return errMsg; } SSM.VALID.singleWord = function(answer){ var errMsg = null , patternWord = /[~`!#$%\^&*+=\-\[\]\\';,/{}|:<>\?\d]/ , patternMultiWord = /^\s*([\w]+\s*){1}$/; if( patternWord.test(answer) ) { errMsg = "Answers can only contain letters."; return errMsg; } if ( !patternMultiWord.test(answer) ) { errMsg = "Answers can only have word."; return errMsg; } } insertAnswerDB = function(answer, nowQuestion, clientName, callback){ // All variables available so create record var response = {}; response.answer = answer; response.time = new Date(); // response.qID = DB.getObjID( nowQuestion.qID ); // response.qSessionID = DB.getObjID( nowQuestion.qSessionID ); response.qID = DB.convertToObjID( nowQuestion.qID ); response.qSessionID = DB.convertToObjID( nowQuestion.qSessionID ); response.clientName = clientName; // Determine Expire Time logger.debugPair("[insertAnswerDB] Now Question", util.inspect(nowQuestion) ); var expireProp = 'expireTime' , hasExpire = nowQuestion.hasOwnProperty(expireProp) && nowQuestion[expireProp] !== ""; if( hasExpire ) response.expireTime = new Date(nowQuestion[expireProp]); // Insert Document SSM.dbResponse.insert(response, {safe: true}, function(err, records){ callback(err, records[0]._id, response); }); } // Export Private Functions for testing if (process.env['NODE_ENV'] == 'test') { SSM.insertAnswerDB = insertAnswerDB; } SSM.removeSession = function(sessionID, callback){ logger.debug("[SSM.removeSession] Params", util.inspect(arguments) ); // Check for sessionID if( !sessionID ) { callback("No Session ID provided"); return false; } //Convert ID to Obj var sessionIDObject = DB.convertToObjID(sessionID); SSM.dbSession.remove({_id:sessionIDObject},{safe:true}, function(err){ if(!err) SSM.removeSessionAnswersDB(sessionIDObject, callback); else callback(err); }) }; SSM.removeSessionAnswersDB = function(sessionIDObject, callback){ logger.debug("[SSM.removeSessionAnswersDB] Params", util.inspect(arguments) ); // Check for sessionIDObect if( !sessionIDObject ) { callback("No Session ObjectID provided"); return false; } // Remove responses associated to the sessionID SSM.dbResponse.remove({qSessionID:sessionIDObject},{safe:true},callback) }; SSM.closeSession = function(req, res, callback){ // Delete GUI Session Information logger.debugPair('Session Closed', req.session.rippleSession.id); delete req.session.rippleSession.id; callback(); };