From 14c9c66a3bc1abfeb3097a0c9fe4f0ff25fe2b8b Mon Sep 17 00:00:00 2001
From: Benjamin Auder <benjamin.auder@somewhere>
Date: Thu, 15 Feb 2018 20:22:14 +0100
Subject: [PATCH] 'update'

---
 models/evaluation.js                        | 13 ++---
 public/javascripts/components/statements.js | 12 +++--
 public/javascripts/course.js                | 14 ++++--
 public/javascripts/utils/validation.js      | 53 ++++++++++++++-------
 4 files changed, 64 insertions(+), 28 deletions(-)

diff --git a/models/evaluation.js b/models/evaluation.js
index 89f2560..be5dbc2 100644
--- a/models/evaluation.js
+++ b/models/evaluation.js
@@ -20,13 +20,15 @@ const EvaluationModel =
 	 *   coefficient: number, default 1
 	 *   questions: array of
 	 *     index: for paper test, like 2.1.a (?!); and quiz: 0, 1, 2, 3...
-	 *     wording: varchar (HTML)
+	 *     wording: varchar (HTML) with potential placeholders for params
 	 *     options: array of varchar --> if present, question type == quiz!
 	 *     fixed: bool, options in fixed order (default: false)
-	 *     answer: array of integers (for quiz) or html text (for paper); striped in exam mode
-	 *     active: boolean, is question in current evaluation?
 	 *     points: points for this question (default 1)
-	 *     param: parameter (if applicable)
+	 *   answers:
+	 *     array of index +
+	 *       array of integers (for quiz) or
+	 *       html text (for paper) or
+	 *       function (as string, for parameterized questions)
 	 *   papers : array of
 	 *     number: student number
 	 *     inputs: array of {index,answer[array of integers or html text],startTime}
@@ -73,6 +75,7 @@ const EvaluationModel =
 				introduction: "",
 				coefficient: 1,
 				questions: [ ],
+				answers: [ ],
 				papers: [ ],
 			},
 			callback
@@ -243,7 +246,6 @@ const EvaluationModel =
 				"papers.password": password,
 			},
 			{ $set: {
-				"papers.$.endTime": Date.now(),
 				"papers.$.password": "",
 			} },
 			callback
@@ -357,7 +359,6 @@ const EvaluationModel =
 					{ $push: { papers: {
 						number: number,
 						startTime: Date.now(),
-						endTime: undefined,
 						password: password,
 						totalDisco: 0,
 						discoCount: 0,
diff --git a/public/javascripts/components/statements.js b/public/javascripts/components/statements.js
index 824ce76..86138c0 100644
--- a/public/javascripts/components/statements.js
+++ b/public/javascripts/components/statements.js
@@ -26,10 +26,11 @@ Vue.component("statements", {
 	// 'inputs': object with key = question index and value = text or boolean array
 	// display: 'all', 'one', 'solution'
 	// iidx: current level-0 integer index (can match a group of questions / inputs)
-	props: ['questions','inputs','display','iidx'],
+	props: ['questions','inputs','answers','display','iidx'],
 	data: function() {
 		return {
 			displayStyle: "compact", //or "all": all on same page
+			parameters: 0, //TODO: DO NOT re-draw parameters for already answered questions
 		};
 	}
 	// Full questions tree is rendered, but some parts hidden depending on display settings
@@ -120,14 +121,15 @@ Vue.component("statements", {
 								}
 							)
 						);
+						const aIdx = (this.answers || [ ]).findIndex( item => { return item.index == q.index; });
 						optionList.push(
 							h(
 								"div",
 								{
 									"class": {
 										option: true,
-										choiceCorrect: this.display == "solution" && q.answer.includes(idx),
-										choiceWrong: this.display == "solution" && !!this.inputs && this.inputs[q.index][idx] && !q.answer.includes(idx),
+										choiceCorrect: this.display == "solution" && this.answers[aIdx].includes(idx),
+										choiceWrong: this.display == "solution" && !!this.inputs && this.inputs[q.index][idx] && !this.answers[aIdx].includes(idx),
 									},
 								},
 								option
@@ -146,6 +148,10 @@ Vue.component("statements", {
 						)
 					);
 				}
+				else
+				{
+					// Open question, or parameterized: TODO
+				}
 				const depth = (q.index.match(/\./g) || []).length;
 				return h(
 					"div",
diff --git a/public/javascripts/course.js b/public/javascripts/course.js
index 65b6ab7..6320538 100644
--- a/public/javascripts/course.js
+++ b/public/javascripts/course.js
@@ -1,4 +1,5 @@
 /*Draft format (compiled to json)
+ * TODO: separate questions and answers in Evaluation object
 
 <some html question (or/+ exercise intro)>
 
@@ -13,19 +14,26 @@
 		+ choix 3
 		- choix4
 
-		<another sub sub>
+		<another sub sub> with params interpolation £ (tout simplement)
+		/ params: javascript parameter generator (another function, body only)
 		* answer 2 (which can
 		be on
 		several lines)
 
 <Some second question>
 * With answer
-*/
+
+	dans le cas de parametetrized, answer est une fonction javascript !! qui prend en arg le(s) param(s)
+	coté serveur on stock parameterized question + body func
+	une fois côté client, extra work first to 1) execute each func 2) replace (and store!!!) all params
+https://stackoverflow.com/questions/7650071/is-there-a-way-to-create-a-function-from-a-string-with-javascript
+
+	*/
 
 new Vue({
 	el: '#course',
 	data: {
-		display: "evaluations", //or "students", or "grades" (admin mode)
+		display: "evaluations", //or "students" (in admin mode)
 		course: course,
 		monitorPwd: "",
 		newEvaluation: { name: "" },
diff --git a/public/javascripts/utils/validation.js b/public/javascripts/utils/validation.js
index f604f77..96ed184 100644
--- a/public/javascripts/utils/validation.js
+++ b/public/javascripts/utils/validation.js
@@ -8,12 +8,14 @@ Validator.Question = {
 	"wording": "string",
 	"options": "stringArray", //only for quiz
 	"fixed": "boolean",
-	"answer": "string", //both this and next are mutually exclusive
-	"choice": "integerArray",
-	"active": "boolean",
 	"points": "number",
 };
 
+Validator.Answer = {
+	"index": "section",
+	"value": "stringOrIntegerArray",
+};
+
 Validator.Input = {
 	"index": "section",
 	"input": "stringOrIntegerArray",
@@ -22,10 +24,9 @@ Validator.Input = {
 // One student response to an exam
 Validator.Paper = {
 	"number": "code",
-	// (array of) strings for open questions, arrays of integers for quizzes:
 	"inputs": Validator.Input,
 	"startTime": "positiveInteger",
-	"endTime": "positiveInteger",
+	"current": "positiveInteger",
 	"discoTime": "positiveInteger",
 	"discoCount": "positiveInteger",
 	"totalDisco": "positiveInteger",
@@ -44,6 +45,7 @@ Validator.Evaluation = {
 	"introduction": "string",
 	"coefficient": "number",
 	"questions": Validator.Question,
+	"answers": Validator.Answer,
 	"papers": Validator.Paper,
 };
 
@@ -51,10 +53,9 @@ Validator.User = {
 	"_id": "bson",
 	"email": "email",
 	"name": "name",
-	"initials": "unchecked", //not a user input
-	"loginToken": "unchecked",
-	"sessionTokens": "unchecked",
-	"token": "alphanumeric", //exception: for the purpose of user registration
+	"initials": "alphanumeric",
+	"loginToken": "alphanumeric",
+	"sessionTokens": "alphanumericArray",
 };
 
 Validator.Student = {
@@ -123,11 +124,6 @@ Object.assign(Validator,
 		return "";
 	},
 
-	"check_stringArray": function(arg)
-	{
-		return !_.isArray(arg) ? "not an array" : "";
-	},
-
 	"check_alphanumeric": function(arg)
 	{
 		return arg.match(/^[\w]{1,32}$/) === null ? "[1,32] alphanumerics" : "";
@@ -203,7 +199,7 @@ Object.assign(Validator,
 		if (!_.isString(arg))
 			return "not a string";
 		if (!/^[\x21-\x7E]{1,16}$/.test(arg))
-			return "[1,16] ASCII characters with code in [33,126]";
+			return "{1,16} ASCII characters with code in [33,126]";
 		return "";
 	},
 
@@ -230,6 +226,31 @@ Object.assign(Validator,
 		return "";
 	},
 
+	"check_stringArray": function(arg)
+	{
+		if (!_.isArray(arg))
+			return "not an array";
+		for (let i=0; i<arg.length; i++)
+		{
+			if (!_.isString(arg[i]));
+				return "not a string";
+		}
+		return "";
+	},
+
+	"check_alphanumericArray": function(arg)
+	{
+		if (!_.isArray(arg))
+			return "not an array";
+		for (let i=0; i<arg.length; i++)
+		{
+			let error = Validator["check_alphanumeric"](arg[i]);
+			if (error.length > 0)
+				return error;
+		}
+		return "";
+	},
+
 	"check_stringOrIntegerArray": function(arg)
 	{
 		if (!_.isString(arg))
@@ -238,4 +259,4 @@ Object.assign(Validator,
 	},
 });
 
-try { module.exports = Validator.checkObject; } catch (err) {} //for server
+try { module.exports = Validator.checkObject; } catch (err) { } //for server
-- 
2.44.0