Add full FSA mode (resolves #3)
This commit is contained in:
parent
2ef91956b4
commit
c19a7941fa
|
@ -91,8 +91,10 @@
|
||||||
</div>
|
</div>
|
||||||
<form>
|
<form>
|
||||||
</form>
|
</form>
|
||||||
|
<div id="fsateamcounttroll"></div>
|
||||||
<input type="button" value="Submit" onclick="submitQuiz()" style="background: #008029" id="quizSubmitButton">
|
<input type="button" value="Submit" onclick="submitQuiz()" style="background: #008029" id="quizSubmitButton">
|
||||||
<input type="button" value="Abort" onclick="abortQuiz()">
|
<input type="button" value="Abort" onclick="abortQuiz()">
|
||||||
|
<span id="submitinfo"></span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="postscreen" class="view">
|
<div id="postscreen" class="view">
|
||||||
|
|
144
web/quiz.js
144
web/quiz.js
|
@ -1,19 +1,44 @@
|
||||||
|
function showFSATeamCountTroll() {
|
||||||
|
|
||||||
|
var fsatctel = document.getElementById('fsateamcounttroll')
|
||||||
|
fsatctel.innerHTML = (state.fsaTeamCountTroll + ' teams have already answered this question')
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateFSATeamCountTroll() {
|
||||||
|
|
||||||
|
if (state.fsaTeamCountTroll > (128*Math.random())) {
|
||||||
|
showFSATeamCountTroll()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var time = state.questions[state.currentQuestion].time
|
||||||
|
var timeratio = 1 - (state.submitTimer / time)
|
||||||
|
var slowAnswerChance = Math.random()*2*Math.pow(timeratio, 2)
|
||||||
|
var quickAnswerChance = (Math.random()+Math.sqrt(69/time))/3
|
||||||
|
var chance = Math.round(slowAnswerChance + quickAnswerChance)
|
||||||
|
var magnitude = Math.round((Math.random()/2+timeratio)*6)
|
||||||
|
var nt = chance * magnitude
|
||||||
|
state.fsaTeamCountTroll += nt
|
||||||
|
|
||||||
|
showFSATeamCountTroll()
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
function updateTotalTimer() {
|
function updateTotalTimer() {
|
||||||
|
|
||||||
var timerEls = document.querySelectorAll('.totaltimer')
|
var timerEls = document.querySelectorAll('.totaltimer')
|
||||||
|
|
||||||
var minutes = Math.floor(state.totalTimer / 60)
|
|
||||||
var seconds = state.totalTimer % 60
|
|
||||||
|
|
||||||
var text = minutes + ':' + ('0' + seconds).slice(-2)
|
|
||||||
|
|
||||||
for (timerEl of timerEls)
|
for (timerEl of timerEls)
|
||||||
timerEl.innerHTML = text
|
timerEl.innerHTML = formatTime(state.totalTimer);
|
||||||
|
|
||||||
state.totalTimer++
|
state.totalTimer++
|
||||||
|
|
||||||
localStorage.setItem('state', JSON.stringify(state))
|
localStorage.setItem('state', JSON.stringify(state))
|
||||||
|
|
||||||
|
if (state.style == 'FSA')
|
||||||
|
updateFSATeamCountTroll()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -27,9 +52,34 @@ function startTotalTimer() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateSubmitButton() {
|
function updateSubmitInfo() {
|
||||||
|
|
||||||
var button = document.getElementById('quizSubmitButton')
|
var button = document.getElementById('quizSubmitButton')
|
||||||
|
var si = document.getElementById('submitinfo')
|
||||||
|
|
||||||
|
if (getRule('submitTimeout') || state.waitNextQuestion) {
|
||||||
|
if (state.submitTimer > 0) {
|
||||||
|
si.innerHTML = state.waitNextQuestion ? 'Waiting for next question' : 'Wait to retry'
|
||||||
|
button.value = 'Wait ' + formatTime(state.submitTimer)
|
||||||
|
button.disabled = true
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
si.innerHTML = ''
|
||||||
|
button.disabled = false
|
||||||
|
|
||||||
|
if (getRule('questionTimeout')) {
|
||||||
|
if (state.submitTimer > 0) {
|
||||||
|
if (getRule('allowQOvertime'))
|
||||||
|
si.innerHTML = ('Losing bonus points in ' + formatTime(state.submitTimer))
|
||||||
|
else
|
||||||
|
si.innerHTML = ('Forced hand-in in ' + formatTime(state.submitTimer))
|
||||||
|
} else {
|
||||||
|
if (getRule('allowQOvertime'))
|
||||||
|
document.getElementById('submitinfo').innerHTML = 'Bonus points lost.'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var lastQuestion = (state.currentQuestion == (state.questions.length - 1))
|
var lastQuestion = (state.currentQuestion == (state.questions.length - 1))
|
||||||
|
|
||||||
|
@ -37,39 +87,23 @@ function updateSubmitButton() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function resetSubmitButton() {
|
|
||||||
|
|
||||||
updateSubmitButton()
|
|
||||||
document.getElementById('quizSubmitButton').disabled = false
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
function formatTime(seconds) {
|
|
||||||
return (seconds > 60)
|
|
||||||
? Math.floor(seconds / 60) + ':' + (('0' + (seconds % 60)).slice(-2))
|
|
||||||
: seconds + 's'
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateSubmitTimer() {
|
function updateSubmitTimer() {
|
||||||
|
|
||||||
var button = document.getElementById('quizSubmitButton')
|
if (state.submitTimer > 0)
|
||||||
|
|
||||||
if (state.submitTimer > 0) {
|
|
||||||
|
|
||||||
button.value = 'Wait ' + formatTime(state.submitTimer)
|
|
||||||
button.disabled = true
|
|
||||||
state.submitTimer -= 1
|
state.submitTimer -= 1
|
||||||
|
|
||||||
} else {
|
if (state.submitTimer == 0) {
|
||||||
|
|
||||||
resetSubmitButton()
|
|
||||||
clearInterval(state.submitInterval)
|
clearInterval(state.submitInterval)
|
||||||
|
|
||||||
if (getRule('sequential') && !getRule('allowQOvertime'))
|
if (getRule('questionTimeout'))
|
||||||
submitQuiz()
|
if (state.waitNextQuestion || !getRule('allowQOvertime'))
|
||||||
|
submitQuiz() // Force next question
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateSubmitInfo()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -88,16 +122,16 @@ function startSubmitTimer(time) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function showSequentialQuestion() {
|
function showSequentialQuestion(n) {
|
||||||
|
|
||||||
var questions = document.querySelectorAll('.question')
|
var questions = document.querySelectorAll('.question')
|
||||||
for (q of questions)
|
for (q of questions)
|
||||||
q.style.display = null
|
q.style.display = null
|
||||||
|
|
||||||
updateSubmitButton()
|
updateSubmitInfo()
|
||||||
|
|
||||||
if (state.currentQuestion !== null) {
|
if (n !== null) {
|
||||||
var q = document.querySelector('#quiz form #question' + state.currentQuestion)
|
var q = document.querySelector('#quiz form #question' + n)
|
||||||
q.style.display = 'block'
|
q.style.display = 'block'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,6 +142,21 @@ function nextQuestion() {
|
||||||
// Save time taken
|
// Save time taken
|
||||||
state.questions[state.currentQuestion].timeTaken = state.totalTimer - state.questionStartTotalTimer
|
state.questions[state.currentQuestion].timeTaken = state.totalTimer - state.questionStartTotalTimer
|
||||||
|
|
||||||
|
if (getRule('questionTimeout') && (state.submitTimer > 0)
|
||||||
|
&& (state.currentQuestion != (state.questions.length-1))) {
|
||||||
|
state.waitNextQuestion = true;
|
||||||
|
showSequentialQuestion(null) // hide question
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
state.waitNextQuestion = false
|
||||||
|
|
||||||
|
if (state.style == 'FSA') {
|
||||||
|
state.fsaTeamCountTroll = 0
|
||||||
|
showFSATeamCountTroll()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start next question
|
||||||
state.questionStartTotalTimer = state.totalTimer
|
state.questionStartTotalTimer = state.totalTimer
|
||||||
|
|
||||||
state.currentQuestion++
|
state.currentQuestion++
|
||||||
|
@ -115,13 +164,11 @@ function nextQuestion() {
|
||||||
if (state.currentQuestion == state.questions.length)
|
if (state.currentQuestion == state.questions.length)
|
||||||
state.currentQuestion = null
|
state.currentQuestion = null
|
||||||
|
|
||||||
showSequentialQuestion()
|
showSequentialQuestion(state.currentQuestion)
|
||||||
|
|
||||||
if (state.currentQuestion !== null && getRule('questionTimeout'))
|
if (state.currentQuestion !== null && getRule('questionTimeout'))
|
||||||
startSubmitTimer()
|
startSubmitTimer()
|
||||||
|
|
||||||
return state.currentQuestion
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -184,14 +231,14 @@ function startQuiz() {
|
||||||
changeView('quiz')
|
changeView('quiz')
|
||||||
|
|
||||||
if (getRule('sequential'))
|
if (getRule('sequential'))
|
||||||
showSequentialQuestion()
|
showSequentialQuestion(state.currentQuestion)
|
||||||
|
|
||||||
if (state.submitTimer > 0)
|
if (state.submitTimer > 0)
|
||||||
startSubmitTimer(state.submitTimer)
|
startSubmitTimer(state.submitTimer)
|
||||||
else if (getRule('questionTimeout'))
|
else if (getRule('questionTimeout'))
|
||||||
startSubmitTimer()
|
startSubmitTimer()
|
||||||
else
|
else
|
||||||
resetSubmitButton()
|
updateSubmitInfo()
|
||||||
|
|
||||||
startTotalTimer()
|
startTotalTimer()
|
||||||
state.running = true
|
state.running = true
|
||||||
|
@ -206,6 +253,7 @@ function reStartQuiz() {
|
||||||
|
|
||||||
state.responses = defaultState.responses
|
state.responses = defaultState.responses
|
||||||
state.currentQuestion = defaultState.currentQuestion
|
state.currentQuestion = defaultState.currentQuestion
|
||||||
|
state.waitNextQuestion = defaultState.waitNextQuestion
|
||||||
state.success = defaultState.success
|
state.success = defaultState.success
|
||||||
state.submitTry = defaultState.submitTry
|
state.submitTry = defaultState.submitTry
|
||||||
state.submitTimer = defaultState.submitTimer
|
state.submitTimer = defaultState.submitTimer
|
||||||
|
@ -213,6 +261,7 @@ function reStartQuiz() {
|
||||||
state.questionStartTotalTimer = defaultState.questionStartTotalTimer
|
state.questionStartTotalTimer = defaultState.questionStartTotalTimer
|
||||||
state.totalTimer = defaultState.totalTimer
|
state.totalTimer = defaultState.totalTimer
|
||||||
state.totalInterval = defaultState.totalInterval
|
state.totalInterval = defaultState.totalInterval
|
||||||
|
state.fsaTeamCountTroll = defaultState.fsaTeamCountTroll
|
||||||
|
|
||||||
changeView('prescreen')
|
changeView('prescreen')
|
||||||
|
|
||||||
|
@ -319,7 +368,13 @@ function showQuizResults() {
|
||||||
el.appendChild(meta)
|
el.appendChild(meta)
|
||||||
|
|
||||||
var qinfo = (value.correct) ? '✅ Correct' : '❌ Incorrect'
|
var qinfo = (value.correct) ? '✅ Correct' : '❌ Incorrect'
|
||||||
if (q.timeTaken) qinfo += ('. Time taken: ' + formatTime(q.timeTaken))
|
if (q.timeTaken) {
|
||||||
|
qinfo += ('. Time taken: ' + formatTime(q.timeTaken))
|
||||||
|
if (value.correct && getRule('allowQOvertime'))
|
||||||
|
qinfo += (', Bonus points ' + ((q.timeTaken <= q.time) ? 'received' : 'lost'))
|
||||||
|
else if (q.timeTaken == q.time)
|
||||||
|
qinfo += ', Time ran out'
|
||||||
|
}
|
||||||
el.querySelector('h3').innerHTML += ` <span class="meta">${qinfo}</span>`
|
el.querySelector('h3').innerHTML += ` <span class="meta">${qinfo}</span>`
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -344,14 +399,17 @@ function mergeKeyReducer(acc, entry) {
|
||||||
function submitQuiz() {
|
function submitQuiz() {
|
||||||
|
|
||||||
// If not running, we're most likely in review mode. Just switch back.
|
// If not running, we're most likely in review mode. Just switch back.
|
||||||
if (state.running == false)
|
if (state.running == false) {
|
||||||
changeView('postscreen')
|
changeView('postscreen')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if (getRule('sequential')) {
|
if (getRule('sequential')) {
|
||||||
|
|
||||||
var n = nextQuestion()
|
nextQuestion()
|
||||||
|
|
||||||
if (n !== null)
|
// Not at the end of the quiz yet
|
||||||
|
if (state.currentQuestion !== null)
|
||||||
return
|
return
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -182,3 +182,15 @@ input[type="radio"]:hover + p, input[type="checkbox"]:hover + p {
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
margin: 16px 0;
|
margin: 16px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#submitinfo {
|
||||||
|
float: right;
|
||||||
|
margin: 16px 0;
|
||||||
|
padding: 12px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#fsateamcounttroll {
|
||||||
|
text-align: right;
|
||||||
|
font-size: 15px;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ const defaultState = {
|
||||||
questions: [],
|
questions: [],
|
||||||
responses: null,
|
responses: null,
|
||||||
currentQuestion: 0,
|
currentQuestion: 0,
|
||||||
|
waitNextQuestion: false,
|
||||||
success: false,
|
success: false,
|
||||||
submitTry: 0,
|
submitTry: 0,
|
||||||
submitTries: 1,
|
submitTries: 1,
|
||||||
|
@ -15,6 +16,7 @@ const defaultState = {
|
||||||
questionStartTotalTimer: 0,
|
questionStartTotalTimer: 0,
|
||||||
totalTimer: 0,
|
totalTimer: 0,
|
||||||
totalInterval: null,
|
totalInterval: null,
|
||||||
|
fsaTeamCountTroll: 0
|
||||||
}
|
}
|
||||||
|
|
||||||
var state
|
var state
|
||||||
|
@ -88,6 +90,13 @@ function applyRuleSettingsFromForm() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function formatTime(seconds) {
|
||||||
|
return (seconds > 60)
|
||||||
|
? Math.floor(seconds / 60) + ':' + (('0' + (seconds % 60)).slice(-2))
|
||||||
|
: seconds + 's'
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
function changeView(view) {
|
function changeView(view) {
|
||||||
|
|
||||||
for (el of document.querySelectorAll('.view'))
|
for (el of document.querySelectorAll('.view'))
|
||||||
|
|
Loading…
Reference in New Issue