-// TODO: YAML format for questions, parsed from text (nested questions)
-// Then yaml parsed to json --> array of indexed questions
-// Use open mode for question banks: add setting "nbQuestions" to show nbQuestions
-// at random among active questions
+/*Draft format (compiled to json)
+
+> Some global (HTML) intro
+
+<some html question (or/+ exercise intro)>
+
+ <some html subQuestion>
+ * some answer [trigger input/index in answers]
+
+ <another subquestion>
+
+ <sub-subQuestion>
+ + choix1
+ - choix 2
+ + choix 3
+ - choix4
+
+ <another sub sub>
+ * answer 2 (which can
+ be on
+ several lines)
+
+<Some second question>
+* With answer
+*/
new Vue({
el: '#course',
display: "assessments", //or "students", or "grades" (admin mode)
course: course,
mode: "view", //or "edit" (some assessment)
- // assessment data:
monitorPwd: "",
newAssessment: { name: "" },
assessmentArray: assessmentArray,
assessmentIndex: 0, //current edited assessment index
assessment: { }, //copy of assessment at editing index in array
assessmentText: "", //questions in an assessment, in text format
- // grades data:
- settings: {
- totalPoints: 20,
- halfPoints: false,
- zeroSum: false,
- },
- group: 1, //for detailed grades tables
- grades: { }, //computed
},
mounted: function() {
$('.modal').each( (i,elem) => {
);
},
// NOTE: artifact required for Vue v-model to behave well
- checkBoxFixedId: function(i) {
+ checkboxFixedId: function(i) {
return "questionFixed" + i;
},
- checkBoxActiveId: function(i) {
+ checkboxActiveId: function(i) {
return "questionActive" + i;
},
- // GRADES:
- gradeSettings: function() {
- $("#gradeSettings").modal("open");
- Materialize.updateTextFields(); //total points field in grade settings overlap
- },
- download: function() {
- // Download (all) grades as a CSV file
- let data = [ ];
- this.studentList(0).forEach( s => {
- let finalGrade = 0.;
- let gradesCount = 0;
- if (!!this.grades[s.number])
- {
- Object.keys(this.grades[s.number]).forEach( assessmentName => {
- s[assessmentName] = this.grades[s.number][assessmentName];
- if (_.isNumeric(s[assessmentName]) && !isNaN(s[assessmentName]))
- {
- finalGrade += s[assessmentName];
- gradesCount++;
- }
- if (gradesCount >= 1)
- finalGrade /= gradesCount;
- s["final"] = finalGrade; //TODO: forbid "final" as assessment name
- });
- }
- data.push(s); //number,name,group,assessName1...assessNameN,final
- });
- let csv = Papa.unparse(data, {
- quotes: true,
- header: true,
- });
- let downloadAnchor = $("#download");
- downloadAnchor.attr("download", this.course.code + "_results.csv");
- downloadAnchor.attr("href", "data:text/plain;charset=utf-8," + encodeURIComponent(csv));
- this.$refs.download.click()
- //downloadAnchor.click(); //fails
- },
- showDetails: function(group) {
- this.group = group;
- $("#detailedGrades").modal("open");
- },
- groupList: function() {
- let maxGrp = 1;
- this.course.students.forEach( s => {
- if (s.group > maxGrp)
- maxGrp = s.group;
- });
- return _.range(1,maxGrp+1);
- },
- grade: function(assessmentIndex, studentNumber) {
- if (!this.grades[assessmentIndex] || !this.grades[assessmentIndex][studentNumber])
- return ""; //no grade yet
- return this.grades[assessmentIndex][studentNumber];
- },
- groupId: function(group, prefix) {
- return (prefix || "") + "group" + group;
- },
- togglePresence: function(number, index) {
- // UNIMPLEMENTED
- // TODO: if no grade (thus automatic 0), toggle "exempt" state on student for current exam
- // --> automatic update of grades view (just a few number to change)
- },
- computeGrades: function() {
- // UNIMPLEMENTED
- // TODO: compute all grades using settings (points, coefficients, bonus/malus...).
- // If some questions with free answers (open), display answers and ask teacher action.
- // TODO: need a setting for that too (by student, by exercice, by question)
- },
},
});