Compare commits
16 Commits
bcbf149c6c
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
58932cdd7b
|
|||
| 366d368446 | |||
| 4fd9d1eb81 | |||
|
872e10ba08
|
|||
|
ca644a6e66
|
|||
|
5cb2182f4c
|
|||
|
d25f7f2f0c
|
|||
|
3f2fe5c9a1
|
|||
|
095716c2eb
|
|||
|
0a9055431f
|
|||
|
bfb7f477af
|
|||
|
27f8b6d5d0
|
|||
|
99da9da68a
|
|||
| 64ca89eefb | |||
| 314c9e8c67 | |||
| 6cdf7dbb4d |
@ -3,6 +3,13 @@ FS Quiz Tool question format
|
|||||||
|
|
||||||
This document provides examples for the question format
|
This document provides examples for the question format
|
||||||
|
|
||||||
|
The web tool will accept these in TSV format, as copied from a spreadsheet like Google Sheets. One Question is one row of the TSV, and each column is one of the following fields, like:
|
||||||
|
|
||||||
|
Input Type | Question | Choices/Answer Options | Answers | Explanation | Author | Picture Link | Time in minutes
|
||||||
|
-----------|----------|-------------------------|---------|-------------|--------|-----------------|----------------
|
||||||
|
ChooseOne | ... | a<br>b | 2 | ... | ... | https://url.jpg | 3
|
||||||
|
Text | ... | Answer in W, 2 decimals | 4.20 | ... | ... | | 5
|
||||||
|
|
||||||
## ChooseOne
|
## ChooseOne
|
||||||
|
|
||||||
Single-Choice question
|
Single-Choice question
|
||||||
|
|||||||
@ -12,3 +12,7 @@ python3 -m fs-quiz-tool-db
|
|||||||
```
|
```
|
||||||
|
|
||||||
Then, open <http://localhost:12345> in your browser.
|
Then, open <http://localhost:12345> in your browser.
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
See LICENSE.md
|
||||||
@ -19,8 +19,11 @@ def startup():
|
|||||||
try:
|
try:
|
||||||
fd = open(filename)
|
fd = open(filename)
|
||||||
data = json.load(fd)
|
data = json.load(fd)
|
||||||
|
fd.close()
|
||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
pass
|
print("DB file not found, creating on POST/write.")
|
||||||
|
|
||||||
|
print("Read", len(data), "quizzes from DB")
|
||||||
|
|
||||||
|
|
||||||
@app.route('/db/<id>', methods = ['GET'])
|
@app.route('/db/<id>', methods = ['GET'])
|
||||||
@ -45,20 +48,16 @@ def post():
|
|||||||
id = generateNewKey()
|
id = generateNewKey()
|
||||||
data[id] = request.data.decode('UTF-8')
|
data[id] = request.data.decode('UTF-8')
|
||||||
|
|
||||||
return id, 201
|
print("Received new quiz. ID:", id)
|
||||||
|
|
||||||
|
|
||||||
def dumpDB():
|
|
||||||
|
|
||||||
if len(data) == 0:
|
|
||||||
return
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
fd = open(filename, 'w+')
|
fd = open(filename, 'w+')
|
||||||
json.dump(data, fd)
|
json.dump(data, fd, indent=2)
|
||||||
finally:
|
|
||||||
fd.close()
|
fd.close()
|
||||||
|
except e:
|
||||||
|
print("Failed to open/create DB file for writing:", e)
|
||||||
|
|
||||||
|
return id, 201
|
||||||
|
|
||||||
|
|
||||||
startup()
|
startup()
|
||||||
atexit.register(dumpDB)
|
|
||||||
|
|||||||
@ -3,7 +3,7 @@ server {
|
|||||||
|
|
||||||
server_name quiz.fasttube.de;
|
server_name quiz.fasttube.de;
|
||||||
|
|
||||||
root /root/fs-quiz-tool/web;
|
root /opt/fs-quiz-tool/web;
|
||||||
|
|
||||||
index index.html;
|
index index.html;
|
||||||
|
|
||||||
@ -15,8 +15,6 @@ server {
|
|||||||
|
|
||||||
location /db {
|
location /db {
|
||||||
proxy_pass http://127.0.0.1:12345;
|
proxy_pass http://127.0.0.1:12345;
|
||||||
proxy_set_header Host $host;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ssl_certificate /usr/local/etc/letsencrypt/live/quiz.fasttube.de/fullchain.pem;
|
ssl_certificate /usr/local/etc/letsencrypt/live/quiz.fasttube.de/fullchain.pem;
|
||||||
|
|||||||
29
res/fs-quiz-tool.openrc
Normal file
29
res/fs-quiz-tool.openrc
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
#!/sbin/openrc-run
|
||||||
|
|
||||||
|
name="$RC_SVCNAME"
|
||||||
|
directory="/opt/fs-quiz-tool"
|
||||||
|
command="/opt/fs-quiz-tool/.venv/bin/python"
|
||||||
|
command_args="-m fs-quiz-tool-db"
|
||||||
|
command_user="www"
|
||||||
|
pidfile="/run/$RC_SVCNAME/$RC_SVCNAME.pid"
|
||||||
|
command_background="yes"
|
||||||
|
|
||||||
|
depend() {
|
||||||
|
need net
|
||||||
|
}
|
||||||
|
|
||||||
|
start_pre() {
|
||||||
|
checkpath --directory --owner $command_user:$command_user --mode 0775 \
|
||||||
|
/run/$RC_SVCNAME /var/log/$RC_SVCNAME
|
||||||
|
}
|
||||||
|
|
||||||
|
start() {
|
||||||
|
ebegin "Starting ${RC_SVCNAME}"
|
||||||
|
start-stop-daemon --start --exec ${command} \
|
||||||
|
--background --make-pidfile --pidfile ${pidfile} \
|
||||||
|
--chdir ${directory} \
|
||||||
|
--stdout /var/log/fs-quiz-tool/out.log \
|
||||||
|
--stderr /var/log/fs-quiz-tool/err.log \
|
||||||
|
-- ${command_args}
|
||||||
|
eend $?
|
||||||
|
}
|
||||||
@ -4,6 +4,9 @@ After=syslog.target network.target nginx.service
|
|||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
User=www-data
|
User=www-data
|
||||||
|
Group=www-data
|
||||||
|
ReadWriteDirectories=/var/fs-quiz-tool-db
|
||||||
|
WorkingDirectory=/var/fs-quiz-tool-db
|
||||||
ExecStart=/usr/bin/python3 -m fs-quiz-tool-db
|
ExecStart=/usr/bin/python3 -m fs-quiz-tool-db
|
||||||
Restart=always
|
Restart=always
|
||||||
|
|
||||||
|
|||||||
@ -91,7 +91,11 @@
|
|||||||
</div>
|
</div>
|
||||||
<form>
|
<form>
|
||||||
</form>
|
</form>
|
||||||
|
<div id="fsastuff">
|
||||||
|
<div id="fsabonuspointsinfo"></div>
|
||||||
<div id="fsateamcounttroll"></div>
|
<div id="fsateamcounttroll"></div>
|
||||||
|
<div id="fsapointbar"><div></div></div>
|
||||||
|
</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>
|
<span id="submitinfo"></span>
|
||||||
|
|||||||
BIN
web/nyan.png
Normal file
BIN
web/nyan.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 9.6 KiB |
141
web/quiz.js
141
web/quiz.js
@ -5,17 +5,16 @@ function showFSATeamCountTroll() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateFSATeamCountTroll() {
|
function updateFSATeamCountTroll(time) {
|
||||||
|
|
||||||
if (state.fsaTeamCountTroll > (128*Math.random())) {
|
if (state.fsaTeamCountTroll > (128*Math.random())) {
|
||||||
showFSATeamCountTroll()
|
showFSATeamCountTroll()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var time = state.questions[state.currentQuestion].time
|
var timeratio = 1 - state.submitTimer / time
|
||||||
var timeratio = 1 - (state.submitTimer / time)
|
|
||||||
var slowAnswerChance = Math.random()*2*Math.pow(timeratio, 2)
|
var slowAnswerChance = Math.random()*2*Math.pow(timeratio, 2)
|
||||||
var quickAnswerChance = (Math.random()+Math.sqrt(69/time))/3
|
var quickAnswerChance = (Math.random()+Math.sqrt(69/time))/4
|
||||||
var chance = Math.round(slowAnswerChance + quickAnswerChance)
|
var chance = Math.round(slowAnswerChance + quickAnswerChance)
|
||||||
var magnitude = Math.round((Math.random()/2+timeratio)*6)
|
var magnitude = Math.round((Math.random()/2+timeratio)*6)
|
||||||
var nt = chance * magnitude
|
var nt = chance * magnitude
|
||||||
@ -25,19 +24,46 @@ function updateFSATeamCountTroll() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function updateFSABonusPoints(time) {
|
||||||
|
|
||||||
|
if (state.waitNextQuestion)
|
||||||
|
return
|
||||||
|
|
||||||
|
var bonuspart = (state.submitTimer - 0.333 * time) / (time * 0.666)
|
||||||
|
|
||||||
|
var barel = document.querySelector('#fsapointbar > div')
|
||||||
|
barel.style.width = Math.round(bonuspart*100) + '%'
|
||||||
|
|
||||||
|
var bonusinfoel = document.getElementById('fsabonuspointsinfo')
|
||||||
|
var points = Math.round(bonuspart*10)
|
||||||
|
bonusinfoel.innerHTML = ((points > 0) ? points : 'No') + ' Bonus points'
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateFSAStuff() {
|
||||||
|
|
||||||
|
// `|| state.submitTime` is a workaround for saved Qs that don't have a time set yet
|
||||||
|
var time = state.questions[state.currentQuestion].time || state.submitTime
|
||||||
|
|
||||||
|
updateFSABonusPoints(time)
|
||||||
|
updateFSATeamCountTroll(time)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
function updateTotalTimer() {
|
function updateTotalTimer() {
|
||||||
|
|
||||||
var timerEls = document.querySelectorAll('.totaltimer')
|
var timerEls = document.querySelectorAll('.totaltimer')
|
||||||
|
|
||||||
for (timerEl of timerEls)
|
for (timerEl of timerEls)
|
||||||
timerEl.innerHTML = formatTime(state.totalTimer);
|
timerEl.innerHTML = 'Total time: ' + formatTime(state.totalTimer);
|
||||||
|
|
||||||
|
if (!state.waitNextQuestion)
|
||||||
state.totalTimer++
|
state.totalTimer++
|
||||||
|
|
||||||
localStorage.setItem('state', JSON.stringify(state))
|
localStorage.setItem('state', JSON.stringify(state))
|
||||||
|
|
||||||
if (state.style == 'FSA')
|
if (state.style == 'FSA')
|
||||||
updateFSATeamCountTroll()
|
updateFSAStuff()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -52,6 +78,18 @@ function startTotalTimer() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function skipWaitNextQuestion(event) {
|
||||||
|
|
||||||
|
if (!event.shiftKey)
|
||||||
|
return
|
||||||
|
|
||||||
|
console.log('Skipping/Bypassing wait timer')
|
||||||
|
|
||||||
|
state.submitTimer = 0
|
||||||
|
updateSubmitTimer()
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
function updateSubmitInfo() {
|
function updateSubmitInfo() {
|
||||||
|
|
||||||
var button = document.getElementById('quizSubmitButton')
|
var button = document.getElementById('quizSubmitButton')
|
||||||
@ -61,29 +99,51 @@ function updateSubmitInfo() {
|
|||||||
if (state.submitTimer > 0) {
|
if (state.submitTimer > 0) {
|
||||||
si.innerHTML = state.waitNextQuestion ? 'Waiting for next question' : 'Wait to retry'
|
si.innerHTML = state.waitNextQuestion ? 'Waiting for next question' : 'Wait to retry'
|
||||||
button.value = 'Wait ' + formatTime(state.submitTimer)
|
button.value = 'Wait ' + formatTime(state.submitTimer)
|
||||||
button.disabled = true
|
button.readOnly = true
|
||||||
|
button.addEventListener('click', skipWaitNextQuestion)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
si.innerHTML = ''
|
si.innerHTML = ''
|
||||||
button.disabled = false
|
button.readOnly = false
|
||||||
|
button.removeEventListener('click', skipWaitNextQuestion)
|
||||||
|
|
||||||
if (getRule('questionTimeout')) {
|
if (getRule('questionTimeout')) {
|
||||||
if (state.submitTimer > 0) {
|
if (state.submitTimer > 0) {
|
||||||
if (getRule('allowQOvertime'))
|
if (getRule('allowQOvertime'))
|
||||||
si.innerHTML = ('Losing bonus points in ' + formatTime(state.submitTimer))
|
si.innerHTML = ('Next question timer starts in ' + formatTime(state.submitTimer))
|
||||||
else
|
else
|
||||||
si.innerHTML = ('Forced hand-in in ' + formatTime(state.submitTimer))
|
si.innerHTML = ( 'Question failed in ' + formatTime(state.submitTimer))
|
||||||
} else {
|
} else {
|
||||||
if (getRule('allowQOvertime'))
|
if (getRule('allowQOvertime'))
|
||||||
document.getElementById('submitinfo').innerHTML = 'Bonus points lost.'
|
document.getElementById('submitinfo').innerHTML = 'Next question timer started.'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var lastQuestion = (state.currentQuestion == (state.questions.length - 1))
|
var lastQuestion = (state.currentQuestion == (state.questions.length - 1))
|
||||||
|
|
||||||
button.value = lastQuestion || !getRule('sequential') ? 'Submit Answers' : 'Next Question'
|
button.value = lastQuestion || !getRule('sequential') ? 'Submit Answers' :
|
||||||
|
((state.submitTimer > 0) ? 'Submit' : 'Next Question')
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function resetQuestionResponse(qn) {
|
||||||
|
|
||||||
|
var q = document.querySelector('#quiz form #question' + qn)
|
||||||
|
var inputs = q.querySelectorAll('input')
|
||||||
|
|
||||||
|
for (input of inputs) {
|
||||||
|
switch (input.type) {
|
||||||
|
case 'radio':
|
||||||
|
case 'checkbox':
|
||||||
|
input.checked = false
|
||||||
|
break;
|
||||||
|
case 'text':
|
||||||
|
input.value = ""
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,9 +156,15 @@ function updateSubmitTimer() {
|
|||||||
|
|
||||||
clearInterval(state.submitInterval)
|
clearInterval(state.submitInterval)
|
||||||
|
|
||||||
if (getRule('questionTimeout'))
|
if (getRule('questionTimeout') && !getRule('allowQOvertime')) {
|
||||||
if (state.waitNextQuestion || !getRule('allowQOvertime'))
|
|
||||||
|
if (!state.waitNextQuestion) {
|
||||||
|
console.log("Question not submitted, clearing input");
|
||||||
|
resetQuestionResponse(state.currentQuestion);
|
||||||
|
}
|
||||||
|
|
||||||
submitQuiz() // Force next question
|
submitQuiz() // Force next question
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -122,7 +188,7 @@ function startSubmitTimer(time) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function showSequentialQuestion(n) {
|
function updateSequentialQuestion() {
|
||||||
|
|
||||||
var questions = document.querySelectorAll('.question')
|
var questions = document.querySelectorAll('.question')
|
||||||
for (q of questions)
|
for (q of questions)
|
||||||
@ -130,8 +196,8 @@ function showSequentialQuestion(n) {
|
|||||||
|
|
||||||
updateSubmitInfo()
|
updateSubmitInfo()
|
||||||
|
|
||||||
if (n !== null) {
|
if (state.currentQuestion !== null && !state.waitNextQuestion) {
|
||||||
var q = document.querySelector('#quiz form #question' + n)
|
var q = document.querySelector('#quiz form #question' + state.currentQuestion)
|
||||||
q.style.display = 'block'
|
q.style.display = 'block'
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -142,10 +208,17 @@ 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)
|
// Last question
|
||||||
&& (state.currentQuestion != (state.questions.length-1))) {
|
if (state.currentQuestion == (state.questions.length - 1)) {
|
||||||
|
state.currentQuestion = null
|
||||||
|
updateSequentialQuestion()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Waiting for next question
|
||||||
|
if (getRule('questionTimeout') && (state.submitTimer > 0)) {
|
||||||
state.waitNextQuestion = true;
|
state.waitNextQuestion = true;
|
||||||
showSequentialQuestion(null) // hide question
|
updateSequentialQuestion() // hide question
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -154,6 +227,9 @@ function nextQuestion() {
|
|||||||
if (state.style == 'FSA') {
|
if (state.style == 'FSA') {
|
||||||
state.fsaTeamCountTroll = 0
|
state.fsaTeamCountTroll = 0
|
||||||
showFSATeamCountTroll()
|
showFSATeamCountTroll()
|
||||||
|
// a lil' surprise
|
||||||
|
document.querySelector('#fsapointbar > div').style.background =
|
||||||
|
(Math.random() < 0.05) ? "left / auto 100% url('nyan.png')" : "darkred"
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start next question
|
// Start next question
|
||||||
@ -161,12 +237,9 @@ function nextQuestion() {
|
|||||||
|
|
||||||
state.currentQuestion++
|
state.currentQuestion++
|
||||||
|
|
||||||
if (state.currentQuestion == state.questions.length)
|
updateSequentialQuestion()
|
||||||
state.currentQuestion = null
|
|
||||||
|
|
||||||
showSequentialQuestion(state.currentQuestion)
|
if (getRule('questionTimeout'))
|
||||||
|
|
||||||
if (state.currentQuestion !== null && getRule('questionTimeout'))
|
|
||||||
startSubmitTimer()
|
startSubmitTimer()
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -216,6 +289,9 @@ function renderQuiz() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var fsastuffel = document.getElementById('fsastuff')
|
||||||
|
fsastuffel.style.display = (state.style == 'FSA') ? 'block' : 'none'
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -231,7 +307,7 @@ function startQuiz() {
|
|||||||
changeView('quiz')
|
changeView('quiz')
|
||||||
|
|
||||||
if (getRule('sequential'))
|
if (getRule('sequential'))
|
||||||
showSequentialQuestion(state.currentQuestion)
|
updateSequentialQuestion()
|
||||||
|
|
||||||
if (state.submitTimer > 0)
|
if (state.submitTimer > 0)
|
||||||
startSubmitTimer(state.submitTimer)
|
startSubmitTimer(state.submitTimer)
|
||||||
@ -262,6 +338,7 @@ function reStartQuiz() {
|
|||||||
state.totalTimer = defaultState.totalTimer
|
state.totalTimer = defaultState.totalTimer
|
||||||
state.totalInterval = defaultState.totalInterval
|
state.totalInterval = defaultState.totalInterval
|
||||||
state.fsaTeamCountTroll = defaultState.fsaTeamCountTroll
|
state.fsaTeamCountTroll = defaultState.fsaTeamCountTroll
|
||||||
|
state.resultsShown = defaultState.resultsShown
|
||||||
|
|
||||||
changeView('prescreen')
|
changeView('prescreen')
|
||||||
|
|
||||||
@ -331,6 +408,10 @@ function showQuizResults() {
|
|||||||
|
|
||||||
changeView('quiz')
|
changeView('quiz')
|
||||||
|
|
||||||
|
// Prevent result metadata being added more than once
|
||||||
|
if (state.resultsShown)
|
||||||
|
return
|
||||||
|
|
||||||
for (var [idx, value] of state.responses.entries()) {
|
for (var [idx, value] of state.responses.entries()) {
|
||||||
|
|
||||||
console.log(idx + ':', value)
|
console.log(idx + ':', value)
|
||||||
@ -372,13 +453,17 @@ function showQuizResults() {
|
|||||||
qinfo += ('. Time taken: ' + formatTime(q.timeTaken))
|
qinfo += ('. Time taken: ' + formatTime(q.timeTaken))
|
||||||
if (value.correct && getRule('allowQOvertime'))
|
if (value.correct && getRule('allowQOvertime'))
|
||||||
qinfo += (', Bonus points ' + ((q.timeTaken <= q.time) ? 'received' : 'lost'))
|
qinfo += (', Bonus points ' + ((q.timeTaken <= q.time) ? 'received' : 'lost'))
|
||||||
else if (q.timeTaken == q.time)
|
else if (q.timeTaken >= (q.time - 1) && !getRule('allowQOvertime'))
|
||||||
qinfo += ', Time ran out'
|
qinfo += ', Time ran out'
|
||||||
}
|
}
|
||||||
el.querySelector('h3').innerHTML += ` <span class="meta">${qinfo}</span>`
|
el.querySelector('h3').innerHTML += ` <span class="meta">${qinfo}</span>`
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
state.resultsShown = true
|
||||||
|
|
||||||
|
document.querySelector('#fsateamcounttroll').innerHTML = ''
|
||||||
|
document.querySelector('#submitinfo').innerHTML = ''
|
||||||
document.querySelector('#quizSubmitButton').value = 'Back'
|
document.querySelector('#quizSubmitButton').value = 'Back'
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -467,7 +552,7 @@ function submitQuiz() {
|
|||||||
renderQuiz()
|
renderQuiz()
|
||||||
if (getRule('sequential')) {
|
if (getRule('sequential')) {
|
||||||
state.currentQuestion = 0
|
state.currentQuestion = 0
|
||||||
showSequentialQuestion(state.currentQuestion)
|
updateSequentialQuestion()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getRule('submitTimeout'))
|
if (getRule('submitTimeout'))
|
||||||
|
|||||||
@ -84,7 +84,7 @@ input[type="button"].center, input[type="submit"].center {
|
|||||||
float: none;
|
float: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type="button"]:disabled, input[type="submit"]:disabled {
|
input[type="button"][readonly], input[type="submit"][readonly] {
|
||||||
cursor: auto;
|
cursor: auto;
|
||||||
background: #888 !important;
|
background: #888 !important;
|
||||||
}
|
}
|
||||||
@ -189,8 +189,31 @@ input[type="radio"]:hover + p, input[type="checkbox"]:hover + p {
|
|||||||
padding: 12px 0;
|
padding: 12px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#fsastuff {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#fsabonuspointsinfo {
|
||||||
|
float: left;
|
||||||
|
font-size: 15px;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
#fsateamcounttroll {
|
#fsateamcounttroll {
|
||||||
text-align: right;
|
text-align: right;
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#fsapointbar {
|
||||||
|
width: 100%;
|
||||||
|
height: 42px;
|
||||||
|
border: 1px solid black
|
||||||
|
}
|
||||||
|
|
||||||
|
#fsapointbar > div {
|
||||||
|
height: 100%;
|
||||||
|
background: darkred;
|
||||||
|
width: 100%;
|
||||||
|
transition: 1s linear width;
|
||||||
|
}
|
||||||
|
|||||||
@ -16,7 +16,8 @@ const defaultState = {
|
|||||||
questionStartTotalTimer: 0,
|
questionStartTotalTimer: 0,
|
||||||
totalTimer: 0,
|
totalTimer: 0,
|
||||||
totalInterval: null,
|
totalInterval: null,
|
||||||
fsaTeamCountTroll: 0
|
fsaTeamCountTroll: 0,
|
||||||
|
resultsShown: false
|
||||||
}
|
}
|
||||||
|
|
||||||
var state
|
var state
|
||||||
@ -49,7 +50,7 @@ var rules = {
|
|||||||
'FSA' : { sequential: true, questionTimeout: 5, allowQOvertime: true },
|
'FSA' : { sequential: true, questionTimeout: 5, allowQOvertime: true },
|
||||||
'FSN' : { sequential: true },
|
'FSN' : { sequential: true },
|
||||||
'FSEast' : { sequential: false },
|
'FSEast' : { sequential: false },
|
||||||
'FSCzech' : { sequential: false, submitTries: Infinity, submitTimeout: 30 },
|
'FSCzech' : { sequential: false, submitTries: Infinity, submitTimeout: 60 },
|
||||||
'FSSpain' : { sequential: true, submitTries: 10 },
|
'FSSpain' : { sequential: true, submitTries: 10 },
|
||||||
'FSSwitzerland' : { sequential: true },
|
'FSSwitzerland' : { sequential: true },
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user