diff --git a/public/scripts/history.js b/public/scripts/history.js index 2d9e015..e3516e0 100644 --- a/public/scripts/history.js +++ b/public/scripts/history.js @@ -1,99 +1,16 @@ -// global reference to the history; shouldn't be directly accessed outside -// this file. -// -// If we are using a remote backend cache the value here for easy access once -// we've done an initial retrieval -var _history = null; - -// this tracks if we're using local storage or some remote user system to -// keep timing data -var _historyUsesLocalStorage = true; - -// the key we store timing data under when in local storage mode -var _historyKey = 'response_history'; - /////////////////////////////////////////////////////////////////////////////// -// If we are storing things remotely the code to get them goes here -function getRemoteHistory() { - console.error('User accounts not yet implemented.'); - return null; -} - -// as above except saving -function saveRemoteHistory() { - console.error('User accounts not yet implementhed.'); - return false; -} - -// ensures that history has been loaded; returns true on success -function loadHistory() { - if (_history !== null) { - return true; - } - - if (!_historyUsesLocalStorage) { - var history = getRemoteHistory(); - if (history === null) { - console.error('Falling back to local history'); - } else { - _history = history; - return true; - } - } - - var history = localStorage.getItem(_historyKey); - if (history == null) { - localStorage.setItem(_historyKey, JSON.stringify({})); - history = "{}"; - } - _history = JSON.parse(history); - return true; -} - -// saves history; returns true on success -function saveHistory() { - if (!_historyUsesLocalStorage) { - if (saveRemoteHistory()) { - return true; - } - console.error('Falling back to local history'); - } - - localStorage.setItem(_historyKey, JSON.stringify(_history)); - return true; -} - -// clears historic timing data and saves the cleared state; returns true on -// success -function clearHistory() { - _history = {}; - return saveHistory(); -} - // returns an array with timing data for a given question number -function getHistory(questionNo) { - if (!loadHistory()) { - console.error('Unable to load history for question ' + questionNo); +async function getHistory(questionNo) { + let url = new URL(document.URL + 'user/answers/question/' + questionNo); + + try{ + let response = await fetch(url); + let body = await response.json(); + return body.previousTimingMs; + + }catch(error){ + console.error(error); return []; } - - var record = _history[questionNo]; - return !!record ? record : []; } - -// record the time taken to answer a given question based on the question -// number -function recordAnswer(questionNo, timeSpentMS) { - if (!loadHistory()) { - console.error('Unable to record new time for question ' + questionNo); - return false; - } - - // check for existing timing data, initialize if none found - if (!_history[questionNo]) { - _history[questionNo] = []; - } - _history[questionNo].push(timeSpentMS); - return true; -} \ No newline at end of file diff --git a/public/scripts/main.js b/public/scripts/main.js index 5dc05dd..7933dfa 100644 --- a/public/scripts/main.js +++ b/public/scripts/main.js @@ -280,19 +280,19 @@ function updateTimingDisplay() { $('#timing-feedback').html(''); var questionNo = localStorage.getItem('questionNo'); // grab the last bits of timing data - var timings = getHistory(questionNo).slice(-3); - - // and then drop them into the boxes - timings.forEach(function(t, idx) { - var element = $('#timing-' + idx); - element.html(t / 1000 + ' sec'); - element.show(); - }) - - // hide the boxes if we don't have timing data - for (var i = timings.length; i < 3; i++) { - $('#timing-' + i).hide(); - } + getHistory(questionNo).then(timings => { + // and then drop them into the boxes + timings.forEach(function(t, idx) { + var element = $('#timing-' + idx); + element.html(t / 1000 + ' sec'); + element.show(); + }) + + // hide the boxes if we don't have timing data + for (var i = timings.length; i < 3; i++) { + $('#timing-' + i).hide(); + } + }); } function onIncorrect() { @@ -303,36 +303,37 @@ function onIncorrect() { }; function handleTimingFeedback(questionNo, curMS) { - var previousTimings = getHistory(questionNo); - if (previousTimings.length == 0) { - return; - } - - var average = previousTimings.reduce( - function(acc, cur) { return acc + cur }, - 0, - ) / previousTimings.length; - - var delta = average - curMS; - - var template = null; - if (delta > 0) { - template = "
You were faster by ${delta} sec!"; - } - if (delta < 0) { - template = "
You were slower by ${delta} sec."; - } - if (template === null) { - return; - } - - // convert MS to S - delta = Math.abs(delta) / 1000; - // now we want to trunate to 2 decimals; the `+` will let us only use 2 - // decimals if we actually need them, e.g., we want 1.5 not 1.50 - // cf. https://stackoverflow.com/a/12830454 - delta = +delta.toFixed(2); - $('#timing-feedback').html(template.replace('${delta}', delta)); + getHistory(questionNo).then(previousTimings => { + if (previousTimings.length == 0) { + return; + } + + var average = previousTimings.reduce( + function(acc, cur) { return acc + cur }, + 0, + ) / previousTimings.length; + + var delta = average - curMS; + + var template = null; + if (delta > 0) { + template = "
You were faster by ${delta} sec!"; + } + if (delta < 0) { + template = "
You were slower by ${delta} sec."; + } + if (template === null) { + return; + } + + // convert MS to S + delta = Math.abs(delta) / 1000; + // now we want to trunate to 2 decimals; the `+` will let us only use 2 + // decimals if we actually need them, e.g., we want 1.5 not 1.50 + // cf. https://stackoverflow.com/a/12830454 + delta = +delta.toFixed(2); + $('#timing-feedback').html(template.replace('${delta}', delta)); + }); } // Function to execute when correct keys are pressed. @@ -340,8 +341,6 @@ function onSuccess() { var questionNo = localStorage.getItem("questionNo"); var thisAnswerMS = Date.now() - questionStartMS; handleTimingFeedback(questionNo, thisAnswerMS); - recordAnswer(questionNo, thisAnswerMS); - saveHistory(); document.querySelector("#textdiv span").textContent = 'Correct Keys pressed!'; clearPromptKeys(); clearPressedKeys(); diff --git a/routes/routes.js b/routes/routes.js index b133d8c..71be56a 100644 --- a/routes/routes.js +++ b/routes/routes.js @@ -1,7 +1,10 @@ const express = require('express'); const router = express.Router(); -const{ User, UserAnswers } = require('../JS/orm'); +const { User, UserAnswers } = require('../JS/orm'); + +const ANSWER_HISTORY_LIMIT = 3; + router.get('/', (req, res) => { res.render('index'); @@ -38,5 +41,24 @@ router.post('/user/answers/question/:questionNumber', (req, res) => { }) }) +router.get('/user/answers/question/:questionNumber', (req, res) => { + // TODO: When issue #74 be done, the userId should be handled from req object + let userId = 'guest'; + + UserAnswers.findAll({ + where: {question_number: req.params.questionNumber, user_id: userId}, + order: [ + ['created_at', 'DESC'] + ], + limit: ANSWER_HISTORY_LIMIT + }).then(userAnswers => { + return res.json({ + previousTimingMs: userAnswers.map(userAnswer => userAnswer.elapsed_time_ms) + }) + }).catch(error => { + console.log(error); + return res.status(500).json(error.errors) // TODO: handle better error messages + }) +}) module.exports = router;