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 `

${tpl.i + 1}. ${tpl.q}

` } 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); })()