Refactor this shit
This commit is contained in:
parent
c39284729d
commit
83544a28be
@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
<header>
|
<header>
|
||||||
|
|
||||||
<h1>FS Czech Quiz Tool</h1>
|
<h1>FS Quiz Tool</h1>
|
||||||
|
|
||||||
<noscript><span class="warning">Please enable JavaScript</span></noscript>
|
<noscript><span class="warning">Please enable JavaScript</span></noscript>
|
||||||
|
|
||||||
@ -75,7 +75,10 @@
|
|||||||
· <span id="meme"></span>
|
· <span id="meme"></span>
|
||||||
</footer>
|
</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>
|
</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() {
|
function updateTotalTimer() {
|
||||||
|
|
||||||
var timerEls = document.querySelectorAll('.totaltimer')
|
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() {
|
function renderQuiz() {
|
||||||
|
|
||||||
var quizForm = document.querySelector('#quiz form')
|
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() {
|
function createQuiz() {
|
||||||
|
|
||||||
console.log('Creating new quiz')
|
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() {
|
window.onload = async function() {
|
||||||
|
|
||||||
@ -547,6 +280,7 @@ window.onload = async function() {
|
|||||||
|
|
||||||
var browserWarning = document.getElementById('browserwarning')
|
var browserWarning = document.getElementById('browserwarning')
|
||||||
|
|
||||||
|
// If arrow functions are supported, it's modern enough :P
|
||||||
browserWarning.style.display = (() => 'none')()
|
browserWarning.style.display = (() => 'none')()
|
||||||
|
|
||||||
var stateString = localStorage.getItem('state')
|
var stateString = localStorage.getItem('state')
|
||||||
@ -577,7 +311,8 @@ window.onload = async function() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
updateTitles()
|
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)
|
if (stateString && !useUrl)
|
||||||
startQuiz()
|
startQuiz()
|
96
web/share.js
Normal file
96
web/share.js
Normal file
@ -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
|
||||||
|
|
||||||
|
}
|
96
web/ssparser.js
Normal file
96
web/ssparser.js
Normal file
@ -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}
|
||||||
|
|
||||||
|
}
|
77
web/util.js
Normal file
77
web/util.js
Normal file
@ -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…
x
Reference in New Issue
Block a user