Show a score at the end of the quiz

Closes #9
This commit is contained in:
Lukas Fürderer 2020-09-04 20:53:09 +02:00
parent f4ce288914
commit 09e71c5d6e
3 changed files with 113 additions and 2 deletions

View File

@ -51,6 +51,7 @@
<button v-if="revealing_text != null" v-on:click="show_correction">{{ revealing_text }}</button> <button v-if="revealing_text != null" v-on:click="show_correction">{{ revealing_text }}</button>
<button v-if="next_column_text != null" v-on:click="open_next_column">{{ next_column_text }}</button> <button v-if="next_column_text != null" v-on:click="open_next_column">{{ next_column_text }}</button>
<button v-if="correction_visible && !solution_correct && !solution_revealed" v-on:click="reveal_solution">Lösung aufdecken</button> <button v-if="correction_visible && !solution_correct && !solution_revealed" v-on:click="reveal_solution">Lösung aufdecken</button>
<button v-if="finished_quiz" v-on:click="scoreboard_open = true">Auswertung anzeigen</button>
</div> </div>
<div class="close_button" v-on:click="is_open = false"> <div class="close_button" v-on:click="is_open = false">
<svg width="30" height="30"> <svg width="30" height="30">
@ -71,6 +72,31 @@
</div> </div>
</div> </div>
</div> </div>
<div v-if="scoreboard_open" class="scoreboard">
<table>
<thead>
<tr>
<th></th>
<th>Bei erster Überprüfung</th>
<th>Nach Korrektur</th>
</tr>
</thead>
<tbody>
<tr v-for="(round, idx) in score">
<td>{{ score_round_description(idx) }}</td>
<td class="single_value" v-for="points in round">{{ points }} / {{ max_score_in(idx) }}</td>
</tr>
<tr>
<td class="total" colspan="3">Gesamtpunktzahl: {{ achieved_total_score }} / {{ maximum_total_score }}</td>
</tr>
</tbody>
</table>
<div class="close_button" v-on:click="scoreboard_open = false">
<svg width="30" height="30">
<path d="M4 4L26 26M4 26L26 4" stroke="#000" stroke-width="2px" />
</svg>
</div>
</div>
</div> </div>
</div> </div>
</body> </body>

View File

@ -66,6 +66,7 @@ body {
font-family: "Roboto Slab"; font-family: "Roboto Slab";
font-size: 16px; font-size: 16px;
margin-top: 5px; margin-top: 5px;
margin-bottom: 10px;
padding: 5px 10px; padding: 5px 10px;
} }
#quiz .close_button { #quiz .close_button {
@ -143,3 +144,47 @@ body {
position: relative; position: relative;
top: -10px; top: -10px;
} }
#quiz .scoreboard {
background-color: #fff;
border: 2px solid #000;
display: grid;
grid-template-columns: auto 30px;
grid-template-rows: 30px auto;
height: 220px;
left: calc(50vw - 332px);
position: absolute;
top: calc(50vh - 112px);
width: 660px;
}
#quiz .scoreboard table {
border-collapse: collapse;
grid-area: 1 / 1 / 3 / 2;
height: 200px;
margin: 10px 0 10px 30px;
}
#quiz .scoreboard div.close_button {
grid-area: 1 / 2 / 2 / 3;
}
#quiz .scoreboard tbody tr:nth-child(2n+1) {
background-color: #eee;
}
#quiz .scoreboard tbody tr:nth-child(2n) {
background-color: #ddd;
}
#quiz .scoreboard thead tr, #quiz .scoreboard tbody tr:last-child {
background-color: #bbb;
}
#quiz .scoreboard th {
padding: 3px 10px;
}
#quiz .scoreboard td {
padding: 3px;
}
#quiz .scoreboard td.single_value {
text-align: center;
}
#quiz .scoreboard td.total {
font-weight: bold;
text-align: center;
}

44
quiz.js
View File

@ -193,6 +193,8 @@ var app = new Vue({
next_insert_num: null, next_insert_num: null,
solution: [], solution: [],
correction_visible: false, correction_visible: false,
score: [],
scoreboard_open: false,
}, },
computed: { computed: {
headings: function() { headings: function() {
@ -211,14 +213,14 @@ var app = new Vue({
"Schau dir die Reihenfolge genau an. Elemente die zuvor nicht korrekt einsortiert waren, sind nun grün markiert.", "Schau dir die Reihenfolge genau an. Elemente die zuvor nicht korrekt einsortiert waren, sind nun grün markiert.",
"Alle Bedeutungen sind jetzt am richtigen Platz. Die Bedeutungen die zuvor nicht korrekt zugeordnet waren, sind grün markiert.", "Alle Bedeutungen sind jetzt am richtigen Platz. Die Bedeutungen die zuvor nicht korrekt zugeordnet waren, sind grün markiert.",
"Die biblichen Bezüge sind nun zugeordnet. Bezüge die zuvor nicht korrekt platziert waren, sind grün markiert.", "Die biblichen Bezüge sind nun zugeordnet. Bezüge die zuvor nicht korrekt platziert waren, sind grün markiert.",
"Die Ministrantendienste sind nun am richtigen Platz. Was zuvor nicht korrekt zugeordnet war, ist grün markiert.\nDu hast es geschafft! Das Quiz ist nun zu Ende.", "Die Ministrantendienste sind nun am richtigen Platz. Was zuvor nicht korrekt zugeordnet war, ist grün markiert.\n\nDu hast " + this.achieved_total_score + " von " + this.maximum_total_score + " Punkten erreicht.",
][this.store.section]; ][this.store.section];
} else { } else {
return [ return [
"Perfekt! Die Reihenfolge ist korrekt.", "Perfekt! Die Reihenfolge ist korrekt.",
"Super! Alle Bedeutungen sind korrekt eingeordnet.", "Super! Alle Bedeutungen sind korrekt eingeordnet.",
"Sehr gut! Die biblischen Bezüge sind alle korrekt zugeordnet.", "Sehr gut! Die biblischen Bezüge sind alle korrekt zugeordnet.",
"Gut gemacht! Die Ministrantendienste sind alle passend zugeordnet.\nDu hast es geschafft! Das Quiz ist nun zu Ende.", "Gut gemacht! Die Ministrantendienste sind alle passend zugeordnet.\n\nDu hast " + this.achieved_total_score + " von " + this.maximum_total_score + " Punkten erreicht.",
][this.store.section]; ][this.store.section];
} }
} else if (this.store.section == 0) { } else if (this.store.section == 0) {
@ -322,6 +324,25 @@ var app = new Vue({
solution_revealed: function() { solution_revealed: function() {
return this.solution.some(elem => elem.got_revealed); return this.solution.some(elem => elem.got_revealed);
}, },
finished_quiz: function() {
return this.store.section == cards_content.length - 1 && this.solution_correct;
},
achieved_total_score: function() {
let sum = 0;
this.score.forEach(step => {
step.forEach(count => {
sum += count;
});
});
return sum;
},
maximum_total_score: function() {
let sum = 0;
cards_content.forEach(column => {
sum += column.filter(x => x != null).length;
});
return 2 * sum;
},
}, },
methods: { methods: {
store_text: function(idx) { store_text: function(idx) {
@ -390,6 +411,9 @@ var app = new Vue({
this.next_insert_num = 1; this.next_insert_num = 1;
} }
this.correction_visible = true; this.correction_visible = true;
let num_elements = cards_content[this.store.section].filter(x => x != null).length;
let num_wrong = this.incorrects.filter(x => x).length;
this.score.push([num_elements - num_wrong, num_elements]);
}, },
open_next_column: function() { open_next_column: function() {
this.store.section++; this.store.section++;
@ -408,6 +432,7 @@ var app = new Vue({
this.store.selected = null; this.store.selected = null;
}, },
reveal_solution: function() { reveal_solution: function() {
let needed_corrections = 0;
if (this.store.section == 0) { if (this.store.section == 0) {
// remove wrong elements // remove wrong elements
let incorrect_rows = []; let incorrect_rows = [];
@ -427,6 +452,7 @@ var app = new Vue({
idx: [i], idx: [i],
got_revealed: true, got_revealed: true,
}); });
needed_corrections++;
} }
} }
} else { } else {
@ -436,14 +462,28 @@ var app = new Vue({
if (!card_inserted && card_needed) { if (!card_inserted && card_needed) {
elem.idx.push(i); elem.idx.push(i);
elem.got_revealed = true; elem.got_revealed = true;
needed_corrections++;
} else if (card_inserted && !card_needed) { } else if (card_inserted && !card_needed) {
elem.idx.splice(this.store.section, 1); elem.idx.splice(this.store.section, 1);
} else if (card_inserted && card_needed && elem.idx[this.store.section] != i) { } else if (card_inserted && card_needed && elem.idx[this.store.section] != i) {
Vue.set(elem.idx, this.store.section, i); Vue.set(elem.idx, this.store.section, i);
elem.got_revealed = true; elem.got_revealed = true;
needed_corrections++;
} }
}); });
} }
this.score[this.store.section][1] -= needed_corrections;
},
score_round_description: function(idx) {
return [
"Runde 1: Ablauf",
"Runde 2: Bedeutung",
"Runde 3: Biblischer Bezug",
"Runde 4: Ministrantendienst",
][idx];
},
max_score_in: function(idx) {
return cards_content[idx].filter(x => x != null).length;
}, },
}, },
}); });