Refactor this shit
This commit is contained in:
parent
c39284729d
commit
83544a28be
|
@ -17,7 +17,7 @@
|
|||
|
||||
<header>
|
||||
|
||||
<h1>FS Czech Quiz Tool</h1>
|
||||
<h1>FS Quiz Tool</h1>
|
||||
|
||||
<noscript><span class="warning">Please enable JavaScript</span></noscript>
|
||||
|
||||
|
@ -75,7 +75,10 @@
|
|||
· <span id="meme"></span>
|
||||
</footer>
|
||||
|
||||
<script src="main.js"></script>
|
||||
<script src="util.js"></script>
|
||||
<script src="ssparser.js"></script>
|
||||
<script src="share.js"></script>
|
||||
<script src="quiz.js"></script>
|
||||
|
||||
</body>
|
||||
|
||||
|
|
|
@ -1,98 +1,3 @@
|
|||
const defaultState = {
|
||||
style: 'FSCzech',
|
||||
id: null,
|
||||
title: null,
|
||||
questions: [],
|
||||
success: 0,
|
||||
submitTimer: 0,
|
||||
submitInterval: null,
|
||||
totalTimer: 0,
|
||||
totalInterval: null,
|
||||
}
|
||||
|
||||
var state = defaultState
|
||||
|
||||
function clearState() {
|
||||
|
||||
state = JSON.parse(JSON.stringify(defaultState))
|
||||
|
||||
}
|
||||
|
||||
|
||||
function changeView(view) {
|
||||
|
||||
for (el of document.querySelectorAll('.view'))
|
||||
el.style.display = 'none'
|
||||
|
||||
document.getElementById(view).style.display = 'block'
|
||||
|
||||
}
|
||||
|
||||
|
||||
function showLink() {
|
||||
|
||||
var link = location.origin + '/?id=' + state.id
|
||||
|
||||
var linkEl = document.getElementById('shareLink')
|
||||
linkEl.href = link
|
||||
linkEl.innerHTML = link
|
||||
|
||||
document.querySelector('#sharing input').style.display = 'none'
|
||||
|
||||
}
|
||||
|
||||
|
||||
function removeLink() {
|
||||
|
||||
var linkEl = document.getElementById('shareLink')
|
||||
linkEl.href = ''
|
||||
linkEl.innerHTML = ''
|
||||
|
||||
document.querySelector('#sharing input').style.display = 'inline-block'
|
||||
|
||||
}
|
||||
|
||||
|
||||
async function shareQuiz() {
|
||||
|
||||
if (state.id) {
|
||||
console.log('Showing saved local link')
|
||||
showLink()
|
||||
return
|
||||
}
|
||||
|
||||
console.log('Saving quiz to server. QuizData:')
|
||||
|
||||
var quizData = {
|
||||
title: state.title,
|
||||
questions: state.questions
|
||||
}
|
||||
|
||||
console.log(quizData)
|
||||
console.log('Waiting for id')
|
||||
|
||||
var db = location.origin + '/db'
|
||||
|
||||
var response = await fetch(db, {
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'text/plain'},
|
||||
body: JSON.stringify(quizData)
|
||||
})
|
||||
|
||||
if (response.ok == false) {
|
||||
alert('Something went wrong while sharing')
|
||||
return
|
||||
}
|
||||
|
||||
var responseBody = await response.text()
|
||||
console.log('Received id: ' + responseBody)
|
||||
state.id = responseBody
|
||||
|
||||
showLink()
|
||||
|
||||
}
|
||||
|
||||
|
||||
function updateTotalTimer() {
|
||||
|
||||
var timerEls = document.querySelectorAll('.totaltimer')
|
||||
|
@ -157,104 +62,6 @@ function startSubmitTimer(time) {
|
|||
}
|
||||
|
||||
|
||||
function parseLine(line) {
|
||||
|
||||
// replace newline markers with html newlines
|
||||
var els = line.replace(/⎊/g, '<br>').split('\t')
|
||||
|
||||
var q = {}
|
||||
|
||||
if (els[0] != '') {
|
||||
if ( els[0] == 'ChooseOne' ||
|
||||
els[0] == 'ChooseAny' ||
|
||||
els[0] == 'Text') {
|
||||
q.type = els[0]
|
||||
} else {
|
||||
alert('Invalid type given on one line')
|
||||
return null
|
||||
}
|
||||
} else {
|
||||
alert('No type given on one line')
|
||||
return null
|
||||
}
|
||||
|
||||
if (els[1]) {
|
||||
q.question = els[1]
|
||||
} else {
|
||||
alert('No question given on one line')
|
||||
return null
|
||||
}
|
||||
|
||||
// Split choices into array
|
||||
// Choices for text questions are labels
|
||||
// No choices (empty string) are okay for text questions
|
||||
// Also filter out empty lines because some people can't use spreadsheets
|
||||
if (els[2] || (q.type == 'Text' && els[2] == '')) {
|
||||
q.choices = els[2].split('<br>').filter(el => el != "")
|
||||
} else {
|
||||
alert('No choices given at question "'
|
||||
+ q.question + '"')
|
||||
return null
|
||||
}
|
||||
|
||||
// If multiple answers are allowed, they are newline-separated
|
||||
// Also filter out empty lines because some people can't use spreadsheets
|
||||
if (els[3] && els[3] != '') {
|
||||
q.answers = els[3].split('<br>').filter(el => el != "")
|
||||
} else {
|
||||
alert('No answers given at question "'
|
||||
+ q.question + '"')
|
||||
return null
|
||||
}
|
||||
|
||||
// Optional parameters
|
||||
q.explanation = els[4] || '[No explanation provided]'
|
||||
q.author = els[5] || '[No author provided]'
|
||||
q.picture = els[6] || null
|
||||
|
||||
return q
|
||||
|
||||
}
|
||||
|
||||
|
||||
function parseSpreadsheet() {
|
||||
|
||||
console.log('Parsing spreadsheet data')
|
||||
|
||||
var textEl = document.getElementById('questions')
|
||||
|
||||
/* MAGIC:
|
||||
* 1. Find quoted multiline cells (<tab>"a<newline>b"<tab>)
|
||||
* 2. Replace all newlines inside with a special char so the cell won't be
|
||||
* split later (<tab>"a<specialchar>b"<tab>)
|
||||
* 3. Replace escaped quotes ("a ""b"" c") with single ones ("a "b" c")
|
||||
* 4. Remove the outer quotes and tabs (a<specialchar>b)
|
||||
* 5. Replace all tabs inside with spaces
|
||||
* 6. Re-add outer tabs (<tab>a<specialchar>b<tab>)
|
||||
*/
|
||||
|
||||
var text = textEl.value.replace(/\t"([^"\n]|"")+\n([^"]|"")*"/g,
|
||||
m => m.replace(/\n/g, '⎊')
|
||||
.replace(/""/g, '"')
|
||||
.replace(/^\t"(.*)"$/, '$1')
|
||||
.replace(/\t/g, ' ')
|
||||
.replace(/^(.*)$/g, '\t$1')
|
||||
)
|
||||
|
||||
state.questions = text.split('\n').map(parseLine)
|
||||
|
||||
if (state.questions.some(el => el == null)) {
|
||||
alert('Erroneous data. Please check and re-enter.')
|
||||
return {success: false}
|
||||
}
|
||||
|
||||
localStorage.setItem('state', JSON.stringify(state))
|
||||
|
||||
return {success: true}
|
||||
|
||||
}
|
||||
|
||||
|
||||
function renderQuiz() {
|
||||
|
||||
var quizForm = document.querySelector('#quiz form')
|
||||
|
@ -332,11 +139,6 @@ function reStartQuiz() {
|
|||
}
|
||||
|
||||
|
||||
function updateTitles() {
|
||||
document.querySelector('#prescreen h1').innerHTML = state.title || ''
|
||||
document.querySelector('#quiz h1').innerHTML = state.title || ''
|
||||
}
|
||||
|
||||
function createQuiz() {
|
||||
|
||||
console.log('Creating new quiz')
|
||||
|
@ -471,75 +273,6 @@ function abortQuiz() {
|
|||
|
||||
}
|
||||
|
||||
function idFromUrl() {
|
||||
|
||||
var s = window.location.search.split('id=')
|
||||
|
||||
if (s.length <= 1)
|
||||
return null
|
||||
|
||||
return s[1].split('&')[0]
|
||||
|
||||
}
|
||||
|
||||
async function fetchQuiz(id) {
|
||||
|
||||
console.log('Fetching quiz')
|
||||
|
||||
var url = location.origin + '/db/' + id
|
||||
|
||||
var response = await fetch(url)
|
||||
|
||||
if (response.ok == false) {
|
||||
alert('Something went wrong while loading this quiz')
|
||||
return
|
||||
}
|
||||
|
||||
var json = await response.json()
|
||||
|
||||
console.log('Quiz fetched. Response:')
|
||||
console.log(json)
|
||||
|
||||
return json
|
||||
|
||||
}
|
||||
|
||||
const memes = [
|
||||
'GE-SUND-BRUN-NEN-CENTER!',
|
||||
'Deine Mudda! Berlin!',
|
||||
'Eine Runde Kicker?',
|
||||
'Hulkdrian!',
|
||||
'Jetz\' bin i\' wieda doa',
|
||||
'Mmmmh Carbonstaub',
|
||||
'#würthshausfranz',
|
||||
'#berlinerluft',
|
||||
'FaST<b>TUBe</b>, not Fast<b>COCUE</b>',
|
||||
'Yes, we CAN',
|
||||
'Ist in der Cloud.',
|
||||
'Ist im Wiki.',
|
||||
'Ich liiebe Teamcenter <3',
|
||||
'Podio kann alles!',
|
||||
'Let\'s build 3 fucking racecars!',
|
||||
'Der Fahrstuhl ist kaputt',
|
||||
'Frau Ipta reißt euch den Kopf ab!',
|
||||
'Max, Max, Max, Max, Max, Max, MaxMax!',
|
||||
'Julian, Anwärter, Firewall',
|
||||
'Diese Webseite ist geerdet.',
|
||||
'Wer AMS sagt muss auch BMS sagen',
|
||||
'Ist der Kabelbinder in der BOM?',
|
||||
'*Fistbump*',
|
||||
'Nividia!',
|
||||
'Ihr schafft das! :)',
|
||||
'Klotzen, nicht kleckern!',
|
||||
'*revving noises*',
|
||||
'Resistance is futile',
|
||||
'Jan schweißt das noch',
|
||||
'Would Claude approve of this?',
|
||||
'Im CAD hat\'s noch gepasst',
|
||||
'¯\\_(ツ)_/¯',
|
||||
'AMK Brudi',
|
||||
'Mmmhh cones',
|
||||
]
|
||||
|
||||
window.onload = async function() {
|
||||
|
||||
|
@ -547,6 +280,7 @@ window.onload = async function() {
|
|||
|
||||
var browserWarning = document.getElementById('browserwarning')
|
||||
|
||||
// If arrow functions are supported, it's modern enough :P
|
||||
browserWarning.style.display = (() => 'none')()
|
||||
|
||||
var stateString = localStorage.getItem('state')
|
||||
|
@ -577,7 +311,8 @@ window.onload = async function() {
|
|||
}
|
||||
|
||||
updateTitles()
|
||||
document.getElementById('meme').innerHTML = memes[Math.floor(Math.random()*memes.length)]
|
||||
var meme = memes[Math.floor(Math.random()*memes.length)]
|
||||
document.getElementById('meme').innerHTML = meme
|
||||
|
||||
if (stateString && !useUrl)
|
||||
startQuiz()
|
|
@ -0,0 +1,96 @@
|
|||
function showLink() {
|
||||
|
||||
var link = location.origin + '/?id=' + state.id
|
||||
history.pushState(state.id, '', link)
|
||||
|
||||
var linkEl = document.getElementById('shareLink')
|
||||
linkEl.href = link
|
||||
linkEl.innerHTML = link
|
||||
|
||||
document.querySelector('#sharing input').style.display = 'none'
|
||||
|
||||
}
|
||||
|
||||
|
||||
function removeLink() {
|
||||
|
||||
var linkEl = document.getElementById('shareLink')
|
||||
linkEl.href = ''
|
||||
linkEl.innerHTML = ''
|
||||
|
||||
document.querySelector('#sharing input').style.display = 'inline-block'
|
||||
|
||||
}
|
||||
|
||||
|
||||
async function shareQuiz() {
|
||||
|
||||
if (state.id) {
|
||||
console.log('Showing saved local link')
|
||||
showLink()
|
||||
return
|
||||
}
|
||||
|
||||
console.log('Saving quiz to server. QuizData:')
|
||||
|
||||
var quizData = {
|
||||
title: state.title,
|
||||
questions: state.questions
|
||||
}
|
||||
|
||||
console.log(quizData)
|
||||
console.log('Waiting for id')
|
||||
|
||||
var db = location.origin + '/db'
|
||||
|
||||
var response = await fetch(db, {
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'text/plain'},
|
||||
body: JSON.stringify(quizData)
|
||||
})
|
||||
|
||||
if (response.ok == false) {
|
||||
alert('Something went wrong while sharing')
|
||||
return
|
||||
}
|
||||
|
||||
var responseBody = await response.text()
|
||||
console.log('Received id: ' + responseBody)
|
||||
state.id = responseBody
|
||||
|
||||
showLink()
|
||||
|
||||
}
|
||||
|
||||
function idFromUrl() {
|
||||
|
||||
var s = window.location.search.split('id=')
|
||||
|
||||
if (s.length <= 1)
|
||||
return null
|
||||
|
||||
return s[1].split('&')[0]
|
||||
|
||||
}
|
||||
|
||||
async function fetchQuiz(id) {
|
||||
|
||||
console.log('Fetching quiz')
|
||||
|
||||
var url = location.origin + '/db/' + id
|
||||
|
||||
var response = await fetch(url)
|
||||
|
||||
if (response.ok == false) {
|
||||
alert('Something went wrong while loading this quiz')
|
||||
return
|
||||
}
|
||||
|
||||
var json = await response.json()
|
||||
|
||||
console.log('Quiz fetched. Response:')
|
||||
console.log(json)
|
||||
|
||||
return json
|
||||
|
||||
}
|
|
@ -0,0 +1,96 @@
|
|||
function parseLine(line) {
|
||||
|
||||
// replace newline markers with html newlines
|
||||
var els = line.replace(/⎊/g, '<br>').split('\t')
|
||||
|
||||
var q = {}
|
||||
|
||||
if (els[0] != '') {
|
||||
if ( els[0] == 'ChooseOne' ||
|
||||
els[0] == 'ChooseAny' ||
|
||||
els[0] == 'Text') {
|
||||
q.type = els[0]
|
||||
} else {
|
||||
alert('Invalid type given on one line')
|
||||
return null
|
||||
}
|
||||
} else {
|
||||
alert('No type given on one line')
|
||||
return null
|
||||
}
|
||||
|
||||
if (els[1]) {
|
||||
q.question = els[1]
|
||||
} else {
|
||||
alert('No question given on one line')
|
||||
return null
|
||||
}
|
||||
|
||||
// Split choices into array
|
||||
// Choices for text questions are labels
|
||||
// No choices (empty string) are okay for text questions
|
||||
// Also filter out empty lines because some people can't use spreadsheets
|
||||
if (els[2] || (q.type == 'Text' && els[2] == '')) {
|
||||
q.choices = els[2].split('<br>').filter(el => el != "")
|
||||
} else {
|
||||
alert('No choices given at question "'
|
||||
+ q.question + '"')
|
||||
return null
|
||||
}
|
||||
|
||||
// If multiple answers are allowed, they are newline-separated
|
||||
// Also filter out empty lines because some people can't use spreadsheets
|
||||
if (els[3] && els[3] != '') {
|
||||
q.answers = els[3].split('<br>').filter(el => el != "")
|
||||
} else {
|
||||
alert('No answers given at question "'
|
||||
+ q.question + '"')
|
||||
return null
|
||||
}
|
||||
|
||||
// Optional parameters
|
||||
q.explanation = els[4] || '[No explanation provided]'
|
||||
q.author = els[5] || '[No author provided]'
|
||||
q.picture = els[6] || null
|
||||
|
||||
return q
|
||||
|
||||
}
|
||||
|
||||
|
||||
function parseSpreadsheet() {
|
||||
|
||||
console.log('Parsing spreadsheet data')
|
||||
|
||||
var textEl = document.getElementById('questions')
|
||||
|
||||
/* MAGIC:
|
||||
* 1. Find quoted multiline cells (<tab>"a<newline>b"<tab>)
|
||||
* 2. Replace all newlines inside with a special char so the cell won't be
|
||||
* split later (<tab>"a<specialchar>b"<tab>)
|
||||
* 3. Replace escaped quotes ("a ""b"" c") with single ones ("a "b" c")
|
||||
* 4. Remove the outer quotes and tabs (a<specialchar>b)
|
||||
* 5. Replace all tabs inside with spaces
|
||||
* 6. Re-add outer tabs (<tab>a<specialchar>b<tab>)
|
||||
*/
|
||||
|
||||
var text = textEl.value.replace(/\t"([^"\n]|"")+\n([^"]|"")*"/g,
|
||||
m => m.replace(/\n/g, '⎊')
|
||||
.replace(/""/g, '"')
|
||||
.replace(/^\t"(.*)"$/, '$1')
|
||||
.replace(/\t/g, ' ')
|
||||
.replace(/^(.*)$/g, '\t$1')
|
||||
)
|
||||
|
||||
state.questions = text.split('\n').map(parseLine)
|
||||
|
||||
if (state.questions.some(el => el == null)) {
|
||||
alert('Erroneous data. Please check and re-enter.')
|
||||
return {success: false}
|
||||
}
|
||||
|
||||
localStorage.setItem('state', JSON.stringify(state))
|
||||
|
||||
return {success: true}
|
||||
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
const defaultState = {
|
||||
style: 'FSCzech', // enum of { FSG, FSA, FSN, FSEast, FSCzech, FSSpain, FSSwitzerland }
|
||||
id: null,
|
||||
title: null,
|
||||
questions: [],
|
||||
success: 0,
|
||||
submitTimer: 0,
|
||||
submitInterval: null,
|
||||
totalTimer: 0,
|
||||
totalInterval: null,
|
||||
}
|
||||
|
||||
var state
|
||||
|
||||
|
||||
function clearState() {
|
||||
|
||||
state = JSON.parse(JSON.stringify(defaultState))
|
||||
|
||||
}
|
||||
|
||||
clearState()
|
||||
|
||||
|
||||
function updateTitles() {
|
||||
document.querySelector('#prescreen h1').innerHTML = state.title || ''
|
||||
document.querySelector('#quiz h1').innerHTML = state.title || ''
|
||||
}
|
||||
|
||||
|
||||
function changeView(view) {
|
||||
|
||||
for (el of document.querySelectorAll('.view'))
|
||||
el.style.display = 'none'
|
||||
|
||||
document.getElementById(view).style.display = 'block'
|
||||
|
||||
}
|
||||
|
||||
|
||||
const memes = [
|
||||
"GE-SUND-BRUN-NEN-CENTER!",
|
||||
"Deine Mudda! Berlin!",
|
||||
"Eine Runde Kicker?",
|
||||
"Hulkdrian!",
|
||||
"Jetz' bin i' wieda doa",
|
||||
"Mmmmh Carbonstaub",
|
||||
"#würthshausfranz",
|
||||
"#berlinerluft",
|
||||
"FaST<b>TUBe</b>, not Fast<b>COQUE</b>",
|
||||
"Yes, we CAN",
|
||||
"Ist in der Cloud.",
|
||||
"Ist im Wiki.",
|
||||
"Ich liiebe Teamcenter <3",
|
||||
"Podio kann alles!",
|
||||
"Let's build 3 fucking racecars!",
|
||||
"Der Fahrstuhl ist kaputt",
|
||||
"Frau Ipta reißt euch den Kopf ab!",
|
||||
"Max, Max, Max, Max, Max, Max, MaxMax!",
|
||||
"Julian, Anwärter, Firewall",
|
||||
"Diese Webseite ist geerdet.",
|
||||
"Wer AMS sagt muss auch BMS sagen",
|
||||
"Ist der Kabelbinder in der BOM?",
|
||||
"*Fistbump*",
|
||||
"Nividia!",
|
||||
"Ihr schafft das! :)",
|
||||
"Klotzen, nicht kleckern!",
|
||||
"*revving noises*",
|
||||
"Resistance is futile",
|
||||
"Jan schweißt das noch",
|
||||
"Would Claude approve of this?",
|
||||
"Im CAD hat's noch gepasst",
|
||||
"¯\\_(ツ)_/¯",
|
||||
"AMK Brudi",
|
||||
"Mmmhh cones",
|
||||
"Best viewed in Netscape Navigator 1.22",
|
||||
]
|
Loading…
Reference in New Issue