brainbaking/static/cppst/test.js

165 lines
5.1 KiB
JavaScript

Object.defineProperty(Array.prototype, 'shuffle', {
value: function() {
for (let i = this.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[this[i], this[j]] = [this[j], this[i]];
}
return this;
}
});
(() => {
const unit = 5
const testmeta = document.querySelector('#testmeta')
const chartmeta = document.querySelector('#chartmeta')
let questionData = undefined
const hide = (el) => {
el.style.display = "none"
return el
}
const show = (el) => {
el.style.display = "block"
return el
}
const questionTemplate = (tpl) => {
return `
<div class="question">
<h3>${tpl.i + 1}. ${tpl.q}</h3>
<div class="input" data-q="${tpl.q}">
<label><input type="radio" name="q-${tpl.i}" value="5">&nbsp;&nbsp;${window.radios[4]}</label>
<label><input type="radio" name="q-${tpl.i}" value="4">&nbsp;&nbsp;${window.radios[3]}</label>
<label><input type="radio" name="q-${tpl.i}" value="3">&nbsp;&nbsp;${window.radios[2]}</label>
<label><input type="radio" name="q-${tpl.i}" value="2">&nbsp;&nbsp;${window.radios[1]}</label>
<label><input type="radio" name="q-${tpl.i}" value="1">&nbsp;&nbsp;${window.radios[0]}</label>
</div>
</div>`
}
const downloadResults = () => {
var dataStr = "data:text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(window.results))
var dlAnchorElem = document.querySelector('#downloadAnchorElem')
dlAnchorElem.setAttribute("href", dataStr)
dlAnchorElem.setAttribute("download", "results.json")
dlAnchorElem.click()
}
const fillInRandomResults = () => {
document.querySelectorAll('.input').forEach(d => { const r = Math.round(Math.random() * 4) + 1; d.querySelector(`input[value="${r}"]`).click(); })
calculateResults()
}
const calculateResults = () => {
const addResultsInHtml = (data) => {
data.forEach(d => {
const attr = d.attribute.replace(/ /g, '-')
document.querySelector(`#result_${attr}`).innerHTML = d.score;
})
}
const generateAmChart = (data) => {
// expected data: [{attribute: "Curiosity", score: 5}]
am4core.useTheme(am4themes_animated)
const chart = am4core.create("chartdiv", am4charts.RadarChart)
chart.data = data
const categoryAxis = chart.xAxes.push(new am4charts.CategoryAxis())
categoryAxis.dataFields.category = "attribute"
categoryAxis.cursorTooltipEnabled = false
const valueAxis = chart.yAxes.push(new am4charts.ValueAxis())
valueAxis.renderer.axisFills.template.fill = chart.colors.getIndex(2)
valueAxis.renderer.axisFills.template.fillOpacity = 0.05
valueAxis.min = 0
valueAxis.max = unit
const series = chart.series.push(new am4charts.RadarSeries())
series.dataFields.valueY = "score"
series.tooltipText = "[bold]{score}[/]"
//series.fill = am4core.color('black')
series.dataFields.categoryX = "attribute"
series.strokeWidth = 3
chart.cursor = new am4charts.RadarCursor()
chart.cursor.lineY.disabled = true
}
const vals = [0, 1, 2, 3, 4, 5]
const valsInverted = [0, 5, 4, 3, 2, 1]
const convertInputResultsToChartData = () => {
return questionData.attributes.map((attribute, i) => {
const calculatedQs = questionData.questions
.filter(q => q.v.find(v => v.attribute === attribute))
.map(q => {
const checked = document.querySelector(`.input[data-q="${q.q}"] input:checked`)
const value = checked ? parseInt(checked.value) : 0
const weight = q.v.find(v => v.attribute === attribute).weight
return {
weight,
question: q.q,
value: q.invert ? valsInverted[value] : vals[value]
}
})
const totalWeights = calculatedQs
.map(calc => calc.weight * unit)
.reduce((one, two) => one + two, 0)
const totalScore = calculatedQs
.map(calc => calc.weight * calc.value)
.reduce((one, two) => one + two, 0)
const theScore = (totalScore / (totalWeights == 0 ? 1 : totalWeights)) * unit
return {
attribute,
questions: calculatedQs,
score: (theScore === 0 ? 1 : theScore).toFixed(2)
}
})
}
if(document.querySelectorAll('input:checked').length < questionData.questions.length) {
alert("Plese answer all questions first!")
return
}
hide(testmeta)
show(chartmeta)
window.results = convertInputResultsToChartData()
generateAmChart(results)
addResultsInHtml(results)
window.scrollTo(0, 0)
}
const generateQuestions = (data) => {
questionData = data
/* data format:
attributes
questions { q, v [ weight, attrIndex ] } -> totals to 100 parts
*/
let html = ''
data.questions.slice().shuffle().forEach((q, i) => {
html += questionTemplate({
q: q.q,
i: i
})
})
document.querySelector('#test').innerHTML = html;
}
document.querySelector('#download').addEventListener('click', downloadResults)
document.querySelector('#random').addEventListener('click', fillInRandomResults)
document.querySelector('#calculate').addEventListener('click', calculateResults)
document.querySelector('#restart').addEventListener('click', () => {
location.reload()
})
fetch('data.json').then((res) => {
return res.json();
}).then(generateQuestions);
})()