Esempio n. 1
0
const getPresentationStats = coroutine(function *getPresentationStats(req, res, next) {
  let slideshow ;
  try{
    slideshow = yield Slideshow.findById(req.params.presentationId).exec();
  }catch(err){
    logger.error("Presentation %s not found", req.params.presentationId);
    logger.error(err.message, { err: err.stack });
    res.status(404);
    return res.render('404', {'msg': 'Presentation not found'});
  }

  try{
    const statsObj = yield stats.getPresentationStats(slideshow);
    statsObj.presentationId = req.params.presentationId;
    statsObj.username = req.user.username;
    statsObj.host = req.app.locals.urlHost;
    statsObj.port = req.app.locals.urlPort;
    return res.render('presentationStats', statsObj);
  }catch(err){
    logger.error("Presentation %s not found", req.params.presentationId);
    logger.error(err.message, { err: err.stack });
    next(err)
  }
  
});
Esempio n. 2
0
 Session.findOne({_id: socket.request.sessionId}, function(err, session){
   if(err){
     logger.error(err.message, { err: err.stack });
   }else{
     try{
       var sessionFlow = flow[session.flow](socketUtils);
       sessionFlow.handleSocketEvent('asq:goto', socket, evt);
     }catch(err){
       logger.error(err.message, { err: err.stack });
     }
   }
 })
Esempio n. 3
0
var uploadPresentation = coroutine(function *uploadPresentationGen (req, res, next){
  try{
    let owner_id = req.user._id;
    let presentationFramework = req.body.presentationFramework;
    var name = req.body.title || req.files.upload.name;
    var uploadFilePath = req.files.upload.path;

    const slideshowid = yield upload.createPresentationFromFile( owner_id, name, presentationFramework, uploadFilePath);
    const slideshow = yield Slideshow.findById(slideshowid).lean().exec();

    logger.log({
      owner_id: req.user._id,
      slideshow: slideshow._id,
      file_path: uploadFilePath,
      file_name: name
    }, "uploaded presentation");

    res.redirect(303, ['/', req.user.username, '/presentations/?alert=',
      slideshow.title, ' uploaded successfully!&type=success']
      .join(''));

  }catch(err){
    console.log(err.stack);

    logger.error({
      err: err,
      owner_id: req.user._id,
      file_path: uploadFilePath,
      file_name: name
    }, "error uploading presentation");
  }
});
Esempio n. 4
0
 archiveStream.on('error', function(err) {
   logger.error({
     err: err,
     presentation: presentation,
   }, "creating zip archive failed");
   throw Boom.badImplementation(err.message);
 });
Esempio n. 5
0
var putPresentation = coroutine(function *putPresentationGen(req, res, next) {

  try{
    let owner_id = req.user._id
    var name = req.body.title //if name is null of undefined it won't be updated
    let presentationFramework = req.body.presentationFramework; //if presentationFramework is null of undefined it won't be updated
    var zipPath = req.files.upload.path;

    let slideshow = yield Slideshow.findById(req.params.presentationId).exec();
    
    if(! slideshow){
      //treat it as new upload
      return next();
    }

    // TODO: handle this better
    if(slideshow.owner.toString() !== owner_id.toString() ){
      next(new Error("You are not the owner of this presentation"))
    }

    var options = {
      preserveSession: req.query.preserveSession
    }
  
    const slideshowid = yield upload.updatePresentationFromZipArchive(
      slideshow._id, name, presentationFramework, zipPath, options);
    slideshow = yield Slideshow.findById(slideshowid).lean().exec();

    //remove zip file
    yield fs.unlinkAsync(zipPath);

    // HACK: empty dust cache
    // if multiple servers are used then the rest of the servers WILL NOT
    // get notified :-(
    // TODO: should only delete the updated presentation path
    cons.clearCache()

    logger.log({
      owner_id: req.user._id,
      slideshow: slideshow._id,
      file_path: zipPath,
      file_name: name
    }, "updated presentation from zip");

    res.redirect(303, ['/', req.user.username, '/presentations/?alert=',
      slideshow.title, ' updated successfully!&type=success']
      .join(''));

  }catch(err){
    console.log(err.stack);

    logger.error({
      err: err,
      owner_id: req.user._id,
      file_path: zipPath,
      file_name: name
    }, "error updating presentation from zip");
  }
});
Esempio n. 6
0
 }).on('error',  function (error) {
   logger.error({
     err: error,
     source: source,
     destination: destination
   }, "error generating zipped HTML from PDF file");
    reject(error);
  }).on('end',  function (res) {
Esempio n. 7
0
  getPresentationsByCourse : coroutine(function *getPresentationsByCourseGen(userId, Session, Slideshow) {
    logger.debug('getPresentationsByCourse');
    var slidesByCourse = null; //to evaluate as false in dustjs
    try{
      var sessionPromise = Session.getLiveSessions(userId);
      var slideshowPromise = Slideshow.find({
        owner : userId
      }, '_id title course lastSession lastEdit thumbnails fontFaces pdfFile conversionStatus').exec();

      var results = yield Promise.all([sessionPromise, slideshowPromise])
      var sessions =  results[0];
      var slides = results[1];
      var live = {};
      sessions.forEach(function(session){
        live[session.slides.toString()]=session._id;
      });

      if (typeof slides != "undefined"
            && slides != null
            && slides.length > 0) {
        slidesByCourse = {};
        for (var i = 0; i < slides.length; i++) {
          var slideshow = slides[i].toJSON();
          if (live.hasOwnProperty(slideshow._id)) {
            slideshow.live = live[slideshow._id]
          }else{
            slideshow.live = null;
          }

          if (!slidesByCourse.hasOwnProperty(slideshow.course)) {
            slidesByCourse[slideshow.course] = [];
          }
          slideshow.lastEdit = moment( slideshow.lastEdit)
              .format('DD.MM.YYYY HH:mm');

          if( slideshow.lastSession){
            slideshow.lastSession = moment( slideshow.lastSession)
                .format('DD.MM.YYYY HH:mm');
          }

          slideshow.isConverting = !(!slideshow.pdfFile || 0 === slideshow.pdfFile.length) && (slideshow.conversionStatus !== 'done');

          slideshow.conversionMessage = getConverstionMsg(slideshow.conversionStatus);

          delete slideshow.pdfFile;
          delete slideshow.conversionStatus;

          slidesByCourse[slideshow.course].push(slideshow);
        }
      }
    }catch(err){
      logger.error( err.toString(), { err: err.stack });
    }
    return slidesByCourse;
  })
Esempio n. 8
0
  Slideshow.findById(req.params.presentationId, function(err, slideshow) {
    if (err) {
      logger.error(err.toString());
    } else {
      /* Load presentation html file */
      fs.readFileAsync(slideshow.presenterFile, 'utf-8').then(function(data) {

        //Array with one field per slide. Each field has questions and stats
        const slides = [];
        $ = cheerio.load(data);
        $('.step').each(function(slide) {
          //Get questions on this slide. Get their text and push it into an array
          const questionsOnSlide = [];
          $(this).find('.assessment').each(function(el) {
            var text = $(this).find('.stem').first().text();
            if (text == undefined || text.length == 0) {
              text = 'Missing question text';
            }
            questionsOnSlide.push(text);
          });

          //Get stats on this slide. Get their text and push it into an array
          var statsOnSlide = new Array();
          $(this).find('.stats').each(function(el) {
            var text = $(this).find('.stem').first().text();
            if (text == undefined || text.length == 0) {
              text = 'Missing question text';
            }
            statsOnSlide.push(text);
          });

          //Push questions and stats on this slide into array
          slides.push({
            questions : questionsOnSlide,
            stats     : statsOnSlide
          });
        });

        res.render('edit', {
          title     : slideshow.title,
          slides    : slides,
          slideshow : slideshow,
        });
      }, function(error){
        //TODO How about handling the error?
        logger.error('This is an error left unhandeled...');
        logger.error(error.toString());
      });
    }
  });
Esempio n. 9
0
exports.getSessionStats = coroutine(function *getSessionStatsGen(req, res, next) {
  var session ;
  try{
    var session = yield Session.findById(req.params.sessionId).exec();
  }catch(err){
    logger.error("Session %s not found", req.params.sessionId);
    logger.error(err.message, { err: err.stack });
    res.status(404);
    return res.render('404', {'msg': 'Presentation not found'});
  }

  try{
    var statsObj = yield stats.getSessionStats(session);
    var endDate = session.endDate 
      ? moment(session.endDate).format('MMMM Do YYYY, h:mm:ss a')
      : undefined;
    statsObj.session = {
      id : session._id.toString(),
      startDate:  moment(session.startDate).format('MMMM Do YYYY, h:mm:ss a'),
      endDate : endDate
    };
    statsObj.username = req.user.username;
    statsObj.questionWidth = (100/statsObj.questions.length);
    if(session.endData === null || session.endData === undefined){
      statsObj.host = req.app.locals.urlHost;
      statsObj.port = req.app.locals.urlPort;
      statsObj.live = true;
      statsObj.mode = 'ctrl';
    }
    return res.render('sessionStats', statsObj);
  }catch(err){
    logger.error("Session %s not found", req.params.sessionId);
    logger.error(err.message, { err: err.stack });
    next(err)
  }
});
Esempio n. 10
0
  Question.find({_id : {$in: this.questions}}, (err, questions) => {
    if (err) { done(err); }

    else if (questions.length !== this.questions.length) {
      let err = new Error(
        'All question items should have a real Question _id');
      logger.error({
            err: err,
            'presentation_id': this._id,
            'questions_length': questions.length,
            'this_questions_length': this.questions.length,
          }, 'error on saving presentation');
      return done(err);
    }
    done();
  });
Esempio n. 11
0
const terminatePresentation = coroutine(function *terminatePresentationGen(req, res, next) {

  try{
    logger.debug({
      owner_id: req.user._id,
      slideshow: req.params.presentationId
    }, 'Stopping session');


    const userId = req.user._id;
    const presentationId = req.params.presentationId;
    
    const terminatedSessions = yield Session.terminateAllSessionsForPresentation(userId, presentationId)

    // if sessions has zero length there was no live sessions
    if (! terminatedSessions.length) {
      const err404 = Error.http(404, 'No session found', {type:'invalid_request_error'});
      throw err404;
    }
    
    res.sendStatus(204);
    
    logger.log({
      owner_id: req.user._id,
      slideshow: req.params.presentationId,
      sessions: terminatedSessions.map( s => s._id.toString()),
    }, "stopped session");

  }catch(err){
    logger.error({
      err: err,
      owner_id: req.user._id,
      sessions: terminatedSessions,
    }, "error stopping session");

    //let error middleware take care of it
    next(err);
  }
});
Esempio n. 12
0
  var ctrlConnect = coroutine(function *ctrlConnectGen(socket) {

    try{

      var screenName = socket.request.screenName;
      var sessionId = socket.request.sessionId;
      var evt       = { screenName : screenName };

      var  session = yield Session.findById(sessionId);
      if(! session) throw new Error("Could not find session");


      ioConnect(socket, 'ctrl');
      socketUtils.emitToRoles('asq:ctrl-connected', evt, sessionId,
          'ctrl', 'ghost', 'folo');

      // async
      createSessionEvent("ctrl-connected", sessionId, socket.user);

      socketUtils.sendConnectedClients(sessionId, 'ctrl');
      socketUtils.sendProgresses(sessionId);


      var result =  yield hooks.doHook('presenter_connected', {
        socketId: socket.id,
        session_id: session._id,
        presentation_id: session.slides,
        whitelistId: socket.request.token
      });

    }catch(err){
      logger.error({ 
        err: require('util').inspect(err),
        stack: err.stack
      }, "err in ctrConnect");
    }
  });
Esempio n. 13
0
  var assessed = coroutine(function *assessedGen(socket, evt) {
    logger.debug('Assessment');
    try{
      if (!evt.assessment) {
        logger.error(new Error('Invalid Submission: Missing or invalid exercise.'));
        return;
      }
      if (!evt.assessment.exercise) {
        logger.error(new Error('Invalid or missing exercise reference.'));
      }

      var assessee = evt.assessment.assessee;
      var assessor = socket.request.token;

      var session = yield Session.findOne({_id: socket.request.sessionId}).exec();
      var exercise = yield Exercise.findById(evt.assessment.exercise).exec();
      var assessments = yield assessment.save(session, evt.assessment, assessor);
      var progress =  yield assessment.job
        .terminateJobsAndUpdateProgress(session, exercise._id, assessor, assessee);

      progress = progress.toObject(); // Convert to object to add audience.
      // Add audience size to progress.
      progress.audience = socketUtils.getNumOfConnectedClients('/folo', progress.session)

      var score=0;
      for (var i = assessments.length - 1; i >= 0; i--) {
        score += assessments[i].score;
      };

      score = ~~(score/assessments.length);
      //notify ctrl for the assessment
      var assessEvt={
        exerciseId : exercise._id,
        assessor: {token: assessor},
        assessee: {token: assessee},
        score: score
      }
      socketUtils.emitToRoles('asq:assess', assessEvt, session._id, 'ctrl');

      // Send updated progress to ctrl
      socketUtils.emitToRoles('asq:submitted', { progress: progress },
        progress.session, 'ctrl');

      socket.emit('asq:submitted', {
        exercise : exercise.id,
        resubmit : false,
        status   : 'success',
        type     : 'assessment'
      });

      var job = yield assessment.job.getNextAssessmentJob(progress.session, exercise, assessor);
      var jobEvt = {
          exerciseId: exercise._id,
          assessor: {token:job.assessor},
          assessee: {token:job.assessee}
        };

      socketUtils.emitToRoles('asq:new-assessment-job', jobEvt, session._id, 'ctrl');
      var html = yield assessment.render(job);
      if (html) {
        socket.emit('asq:assess', { html: html, exercise: exercise.id });
      }
    }catch(err){
      logger.error(err.message, { err: err.stack });
    }
  });
Esempio n. 14
0
function logErrors(err, req, res, next) {
  logger.error(err.stack);
  next(err);
}
Esempio n. 15
0
File: app.js Progetto: mlabaj/ASQ
  setTimeout(function() {
     logger.error("Could not close connections in time, forcefully shutting down");
      process.exit()
 }, 10*1000);
Esempio n. 16
0
 .catch(function onError(err) {
   logger.error( err.toString(), { err: err.stack });
 });
Esempio n. 17
0
 function(err){
   var where = "@ getLivePresentations";
   err = err instanceof Error ? err : new Error(err);
   logger.error(where + ': ', { error: err.stack });
   res.render('500', { where: where , error: err, stack: err.stack });
 });
Esempio n. 18
0
  var foloConnect = coroutine(function *foloConnectGen(socket) {
    try{

      var screenName = socket.request.screenName;
      var sessionId  = socket.request.sessionId;
      var token      = socket.request.token;
      var foloConnectedEvent = {
        screenName: screenName,
        token: token
      }

      var  session = yield Session.findById(sessionId);
      if(! session) throw new Error("Could not find session");

      ioConnect(socket, 'folo');

      yield socketUtils.saveConnectionToRedis(token, socket);
      logger.info('[Redis] saved socket id');
      socketUtils.emitToRoles('asq:folo-connected', foloConnectedEvent, sessionId, 'ctrl');
      socketUtils.sendConnectedClients(sessionId, 'ctrl');

      // async
      createSessionEvent("folo-connected", sessionId, socket.user);

      // send progress
      yield submission.progress.updateConnect(sessionId, token);
      yield socketUtils.sendProgresses(sessionId);
      yield socketUtils.sendSubmissions(socket, sessionId, token);

      // find assessment jobs
      var jobs = yield AssessmentJob.find({
        assessor : token,
        status   : 'active',
        session  : sessionId,
      });
      var exerciseIds = jobs.map(function(job) { return job.exercise });
      var dbExerciseIds = yield Answer.distinct('exercise', {
          answeree : token,
          session  : sessionId,
          exercise : {$nin: exerciseIds }
        }).exec();
      var exercises = yield Exercise.find({ _id: {$in: dbExerciseIds} });

      var jobs = yield Promise.map(exercises, function getNextJob(ex) {
        return assessment.job.getNextAssessmentJob(sessionId, ex, token);
      })

      jobs = _.remove(_.flatten(jobs), function(j) { return j !== null});
      socketUtils.notifyCtrlForNewJobs(jobs);

      //activate jobs
      yield Promise.map(jobs, function(j) { return assessment.job.activateJob(j); });

      //get and send assessment job html
      var htmls = yield Promise.map(jobs, function(j) { return assessment.render(j); });
      var i = Math.min(jobs.length, htmls.length);
      while(i--) {
        if (!! jobs[i] && !! htmls[i]) {
          socket.emit('asq:assess', {
            exercise : jobs[i]. exercise, html : htmls[i] });
        }
      }
      var hookResults = yield hooks.doHook('viewer_connected', {
        socketId: socket.id,
        session_id: session._id,
        presentation_id: session.slides,
        whitelistId: socket.request.token
      });
    
    }catch(err){
      logger.error({ 
        err: require('util').inspect(err),
        stack: err.stack
      }, "err in foloConnect");
    }
  });
Esempio n. 19
0
 function foloDisconnectErr(err) {
   logger.error('Failed to disconnect client from \'folo\':\n\t' +
     err.toString(), { err: err.stack });
 });
Esempio n. 20
0
 function statDisconnectErr(err) {
   logger.error('Failed to disconnect client from \'stat\':\n\t' +
     err.toString());
 });
Esempio n. 21
0
 }, function(error){
   //TODO How about handling the error?
   logger.error('This is an error left unhandeled...');
   logger.error(error.toString());
 });
Esempio n. 22
0
 .catch(function onError(err) {
   logger.error('Error on terminate session:\n\t' + err.toString());
 })
Esempio n. 23
0
 }).catch(function(err){
   logger.error('Failed to get user session stats' +
     err.message, { err: err.stack });
 });
Esempio n. 24
0
  var submit = coroutine(function *submitGen(socket, evt) {
    try{
      logger.debug('Submission');
      if (!evt.exercise || !evt.exercise.id) {
        logger.error(new Error('Invalid Submission: Missing or invalid exercise.'));
        return;
      }
      // Notify the sender
      socket.emit('asq:submitted', {
        exercise : evt.exercise.id,
        status   : 'processing'
      });

      var token = socket.request.token;
      var session = yield Session.findOne({_id: socket.request.sessionId}).exec();

      //TODO : return object instead of an array
      var data = yield submission.answer.save(session, token, evt.exercise);

      var exercise  = data[0];
      var questions = data[1];
      var answers   = data[2];
      var progress  = data[3];
      var self      = data[4];
      var peer      = data[5];

      socketUtils.sendProgress(progress, session.id);

      socket.emit('asq:submitted', {
        exercise : exercise.id,
        resubmit : exercise.allowResubmit,
        status   : 'success',
        type     : 'answer'
      });

      //see if automatic asssemsent was created
      var assessments = yield Assessment.find({
        session: session._id,
        exercise: exercise._id,
        assessee : token,
        type : 'auto'
      }, {'_id': 0,
       'assessee': '1',
       'question': '1',
       'answer' : '1',
       'score': '1', 
       'type': '1',
       'submittedDate' :'1'
     })
      .populate('question answer')
      .exec();

      assessments.forEach(function(assessment){
        socket.emit('asq:assessment', assessment.toObject());
        socketUtils.emitToRoles('asq:assessment',assessment.toObject() , session.id, 'ctrl');
      })

      //check if the user has answered every question
      var slideshow = yield Slideshow
        .findById(session.slides)
        .exec();

      var answeredQuestions = yield Answer.aggregate()
        .match({ session: session._id, answeree: token })
        .group({_id : 0, questions: { $addToSet: "$question" }})
        .project({ _id: 0 , sameElements: { '$setEquals': [ "$questions", slideshow.questions ] } } )
        .exec();
        
      if(answeredQuestions[0].sameElements === true){
        var entry = yield WhitelistEntry.findById(token).exec();
        entry.sessionData.answeredAllDate = new Date();
        entry.markModified('sessionData');
        //save user
        var saved = yield entry.save();
        
        socket.emit('asq:answered-all');
        socketUtils.emitToRoles('asq:answered-all', { userId: token }, session.id, 'ctrl');
      }

      //async
      calculateRankings(session);


      // Handle peer assessment
      if (self || peer) { // Add answers for peers
        // in the case of assessment -> add the answer to the queue
        var jobs = yield socketUtils.enqueueAnswersForAssessment(session._id, exercise, answers, token);
        var job = yield assessment.job.getNextAssessmentJob(session._id, exercise, token);
        job = assessment.job.activateJob(job);
        var html = yield assessment.render(job);

        if (!! html) {
          logger.info('Sending assessment to ' + socket.id);
          socket.emit('asq:assess', { html: html, exercise: exercise.id });
        }
        // notify ctrl of the assessment
        socketUtils.notifyCtrlForNewJobs([job]);

        var newJobs = yield assessment.job.getNextJobForIdleViewers(session._id, exercise); 
        var JobSocketsPairs = yield socketUtils.getSocketsForJobs(newJobs);
        JobSocketsPairs = yield socketUtils.activateJobsForSockets(JobSocketsPairs);
        var HtmlSocketsPairs = socketUtils.renderJobsForSockets(JobSocketsPairs);
        socketUtils.sendHtmlForSockets(HtmlSocketsPairs, exercise.id);
        socketUtils.notifyCtrlForNewJobs( newJobs);
      }
    }catch(err){
      logger.error(err.message, { err: err.stack });
    } 
  });