From: Benjamin Auder <benjamin.auder@somewhere>
Date: Fri, 18 Jan 2019 22:25:06 +0000 (+0100)
Subject: Fix challenge creation (TODO: decide a challenge structure)
X-Git-Url: https://git.auder.net/variants/current/doc/css/assets/mini-custom.min.css?a=commitdiff_plain;h=74ea2e8d9ec6980e2fb5a4f86afe33b4850e3d53;p=vchess.git

Fix challenge creation (TODO: decide a challenge structure)
---

diff --git a/models/Challenge.js b/models/Challenge.js
index e945daa5..96db0a2b 100644
--- a/models/Challenge.js
+++ b/models/Challenge.js
@@ -23,16 +23,17 @@ const ChallengeModel =
 	{
 		db.serialize(function() {
 			let query =
-				"INSERT INTO Challenges (added, uid, vid, nbPlayers, fen, mainTime, addTime) " +
-				"VALUES (" + Date.now() + "," + c.uid + "," + c.vid + "," + c.nbPlayers + "," +
-					c.fen + "," + c.mainTime + "," + c.increment + ")";
+				"INSERT INTO Challenges " +
+				"(added, uid, vid, nbPlayers, fen, mainTime, addTime) VALUES " +
+				"(" + Date.now() + "," + c.uid + "," + c.vid + "," + c.nbPlayers +
+					",'" + c.fen + "'," + c.mainTime + "," + c.increment + ")";
 			db.run(query, err => {
 				if (!!err)
 					return cb(err);
 				db.get("SELECT last_insert_rowid() AS rowid", (err2,lastId) => {
 					query =
 						"INSERT INTO WillPlay VALUES " +
-						"(" + lastId["rowid"] + "," + uid + ")";
+						"(" + lastId["rowid"] + "," + c.uid + ")";
 						db.run(query, (err,ret) => {
 							cb(err, lastId); //all we need is the challenge ID
 						});
@@ -64,6 +65,7 @@ const ChallengeModel =
 						return cb(err2);
 					const challenge = {
 						id: id,
+						uid: challengeInfo.uid,
 						vname: challengeInfo.name,
 						added: challengeInfo.added,
 						nbPlayers: challengeInfo.nbPlayers,
diff --git a/public/javascripts/components/challengeList.js b/public/javascripts/components/challengeList.js
index 66e809e1..2c997b7e 100644
--- a/public/javascripts/components/challengeList.js
+++ b/public/javascripts/components/challengeList.js
@@ -29,3 +29,5 @@ Vue.component("my-challenge-list", {
 		</table>
 	`,
 });
+
+// TODO: challenge format from/to ou uid/players ............
diff --git a/public/javascripts/components/correspondance.js b/public/javascripts/components/correspondance.js
index 35659c3f..7dbde157 100644
--- a/public/javascripts/components/correspondance.js
+++ b/public/javascripts/components/correspondance.js
@@ -9,7 +9,7 @@ Vue.component("my-correspondance", {
 				fen: "",
 				vid: 0,
 				nbPlayers: 0,
-				players: ["","",""],
+				players: [{id:0,name:""},{id:0,name:""},{id:0,name:""}],
 				mainTime: 0,
 				increment: 0,
 			},
@@ -25,11 +25,15 @@ Vue.component("my-correspondance", {
 					<fieldset>
 						<label for="selectVariant">{{ translate("Variant") }}</label>
 						<select id="selectVariant" v-model="newgameInfo.vid">
-							<option v-for="v in variants" :value="v.id">{{ v.name }}</option>
+							<option v-for="v in variants" :value="v.id">
+								{{ v.name }}
+							</option>
 						</select>
 					</fieldset>
 					<fieldset>
-						<label for="selectNbPlayers">{{ translate("Number of players") }}</label>
+						<label for="selectNbPlayers">
+							{{ translate("Number of players") }}
+						</label>
 						<select id="selectNbPlayers" v-model="newgameInfo.nbPlayers">
 							<option v-show="possibleNbplayers(2)" value="2">2</option>
 							<option v-show="possibleNbplayers(3)" value="3">3</option>
@@ -39,30 +43,37 @@ Vue.component("my-correspondance", {
 					<fieldset>
 						<label for="timeControl">Time control (in days)</label>
 						<div id="timeControl">
-							<input type="number" v-model="newgameInfo.mainTime" placeholder="Main time"/>
-							<input type="number" v-model="newgameInfo.increment" placeholder="Increment"/>
+							<input type="number" v-model="newgameInfo.mainTime"
+								placeholder="Main time"/>
+							<input type="number" v-model="newgameInfo.increment"
+								placeholder="Increment"/>
 						</div>
 					</fieldset>
 					<fieldset>
 						<label for="selectPlayers">{{ translate("Play with?") }}</label>
 						<div id="selectPlayers">
-							<input type="text" v-model="newgameInfo.players[0]"/>
+							<input type="text" v-model="newgameInfo.players[0].name"/>
 							<input v-show="newgameInfo.nbPlayers>=3" type="text"
-								v-model="newgameInfo.players[1]"/>
+								v-model="newgameInfo.players[1].name"/>
 							<input v-show="newgameInfo.nbPlayers==4" type="text"
-								v-model="newgameInfo.players[2]"/>
+								v-model="newgameInfo.players[2].name"/>
 						</div>
 					</fieldset>
 					<fieldset>
-						<label for="inputFen">{{ translate("FEN (ignored if players fields are blank)") }}</label>
+						<label for="inputFen">
+							{{ translate("FEN (ignored if players fields are blank)") }}
+						</label>
 						<input id="inputFen" type="text" v-model="newgameInfo.fen"/>
 					</fieldset>
 					<button @click="newGame">Launch game</button>
 				</div>
 			</div>
-			<p v-if="!userId">Correspondance play is reserved to registered users</p>
+			<p v-if="!userId">
+				Correspondance play is reserved to registered users
+			</p>
 			<div v-if="!!userId">
-				<my-challenge-list :challenges="challenges" @click-challenge="clickChallenge">
+				<my-challenge-list :challenges="challenges"
+					@click-challenge="clickChallenge">
 				</my-challenge-list>
 				<button onClick="doClick('modalNewgame')">New game</button>
 				<my-game-list :games="games" @show-game="showGame">
@@ -97,26 +108,53 @@ Vue.component("my-correspondance", {
 			location.href="/variant#game?id=" + g.id;
 		},
 		newGame: function() {
-			// NOTE: side-effect = set FEN
-			// TODO: (to avoid any cheating option) separate the GenRandInitFen() functions
-			// in separate files, load on server and generate FEN on server.
-			const error = checkChallenge(this.newgameInfo);
-			if (!!error)
-				return alert(error);
-			// Possible (server) error if filled player does not exist
-			ajax(
-				"/challenges/" + this.newgameInfo.vid,
-				"POST",
-				this.newgameInfo,
-				response => {
-					this.challenges.push(response.challenge);
-				}
-			);
+			const afterRulesAreLoaded = () => {
+				// NOTE: side-effect = set FEN
+				// TODO: (to avoid any cheating option) separate the GenRandInitFen() functions
+				// in separate files, load on server and generate FEN on server.
+				const error = checkChallenge(this.newgameInfo, vname);
+				if (!!error)
+					return alert(error);
+				// Possible (server) error if filled player does not exist
+				ajax(
+					"/challenges/" + this.newgameInfo.vid,
+					"POST",
+					this.newgameInfo,
+					response => {
+						const chall = Object.assign({},
+							this.newgameInfo,
+							{
+								id: response.cid,
+								uid: user.id,
+								added: Date.now(),
+								vname: vname,
+							},
+						this.challenges.push(response.challengei);
+					}
+				);
+			};
+			const idxInVariants =
+				variantArray.findIndex(v => v.id == this.newgameInfo.vid);
+			const vname = variantArray[idxInVariants].name;
+			const scriptId = vname + "RulesScript";
+			if (!document.getElementById(scriptId))
+			{
+				// Load variant rules (only once)
+				var script = document.createElement("script");
+				script.id = scriptId;
+				script.onload = afterRulesAreLoaded;
+				//script.addEventListener ("load", afterRulesAreLoaded, false);
+				script.src = "/javascripts/variants/" + vname + ".js";
+				document.body.appendChild(script);
+			}
+			else
+				afterRulesAreLoaded();
 		},
 		possibleNbplayers: function(nbp) {
 			if (this.newgameInfo.vid == 0)
 				return false;
-			const idxInVariants = variantArray.findIndex(v => v.id == this.newgameInfo.vid);
+			const idxInVariants =
+				variantArray.findIndex(v => v.id == this.newgameInfo.vid);
 			return NbPlayers[variantArray[idxInVariants].name].includes(nbp);
 		},
 	},
diff --git a/public/javascripts/components/game.js b/public/javascripts/components/game.js
index 534d9af4..fb4564f7 100644
--- a/public/javascripts/components/game.js
+++ b/public/javascripts/components/game.js
@@ -490,7 +490,7 @@ Vue.component('my-game', {
 				if (this.cursor == this.moves.length)
 					this.moves.push(move);
 				else
-					this.moves = this.moves.slice(0,this.cursor-1).concat([move]);
+					this.moves = this.moves.slice(0,this.cursor).concat([move]);
 			}
 			// Is opponent in check?
 			this.incheck = this.vr.getCheckSquares(this.vr.turn);
diff --git a/public/javascripts/shared/challengeCheck.js b/public/javascripts/shared/challengeCheck.js
index a5833f62..85d8571d 100644
--- a/public/javascripts/shared/challengeCheck.js
+++ b/public/javascripts/shared/challengeCheck.js
@@ -1,4 +1,5 @@
-function checkChallenge(c)
+// 'vname' for 'variant name' is defined when run on client side
+function checkChallenge(c, vname)
 {
 	const vid = parseInt(c.vid);
 	if (isNaN(vid) || vid <= 0)
@@ -15,44 +16,30 @@ function checkChallenge(c)
 	let playerCount = 0;
 	for (p of c.players)
 	{
-		if (p.length > 0)
+		if (p.name.length > 0)
 		{
-			if (!p.match(/^[\w]+$/))
+			if (!p.name.match(/^[\w]+$/))
 				return "Wrong characters in players names";
 			playerCount++;
 		}
 	}
 
-	if (playerCount > 0 && playerCount != c.nbPlayers)
+	if (playerCount > 0 && playerCount != c.nbPlayers-1)
 		return "None, or all of the opponent names must be filled"
 
-	if (!!document) //client side
+	if (typeof document !== "undefined") //client side
 	{
-		const idxInVariants = variantArray.findIndex(v => v.id == c.vid);
-		const vname = variantArray[idxInVariants].name;
-		const scriptId = vname + "RulesScript";
-		const afterRulesAreLoaded = () => {
-			const V = eval(vname + "Rules");
-			// Allow custom FEN (and check it) only for individual challenges
-			if (c.fen.length > 0 && playerCount > 0)
-			{
-				if (!V.IsGoodFen(c.fen))
-					return "Bad FEN string";
-			}
-			else
-			{
-				// Generate a FEN
-				c.fen = V.GenRandInitFen();
-			}
-		};
-		if (!document.getElementById(scriptId))
+		const V = eval(vname + "Rules");
+		// Allow custom FEN (and check it) only for individual challenges
+		if (c.fen.length > 0 && playerCount > 0)
 		{
-			// Load variant rules (only once)
-			var script = document.createElement("script");
-			script.id = scriptId;
-			script.src = "/javascripts/variants/" + vname + ".js";
-			document.body.appendChild(script);
-			script.onload = afterRulesAreLoaded;
+			if (!V.IsGoodFen(c.fen))
+				return "Bad FEN string";
+		}
+		else
+		{
+			// Generate a FEN
+			c.fen = V.GenRandInitFen();
 		}
 	}
 	else
diff --git a/routes/challenge.js b/routes/challenge.js
index 2131870f..8d996218 100644
--- a/routes/challenge.js
+++ b/routes/challenge.js
@@ -18,7 +18,7 @@ router.post("/challenges/:vid([0-9]+)", access.logged, access.ajax, (req,res) =>
 	};
 	const error = checkChallenge(chall);
 	ChallengeModel.create(chall, (err,lastId) => {
-		res.json(err || {challenge: Object.assign(chall, {id: lastId["rowid"]})});
+		res.json(err || {cid: lastId["rowid"]});
 	});
 });