From 26b8e4f7c71030d49e44fe1d89632ef91b886d67 Mon Sep 17 00:00:00 2001
From: Benjamin Auder <benjamin.auder@somewhere>
Date: Wed, 9 Jan 2019 18:26:13 +0100
Subject: [PATCH] rename getOppCol into static GetOppCol + start thinking about
 problems page

---
 TODO                                      |  8 +++--
 app.js                                    |  1 +
 public/javascripts/base_rules.js          |  6 ++--
 public/javascripts/components/problems.js | 14 ++++++--
 public/javascripts/contactForm.js         |  5 +--
 public/javascripts/index.js               | 40 ++++-------------------
 public/javascripts/variants/Alice.js      | 10 +++---
 public/javascripts/variants/Antiking.js   |  6 ++--
 public/javascripts/variants/Atomic.js     |  8 ++---
 public/javascripts/variants/Baroque.js    | 10 +++---
 public/javascripts/variants/Checkered.js  | 12 +++----
 public/javascripts/variants/Dark.js       |  6 ++--
 public/javascripts/variants/Losers.js     |  2 +-
 public/javascripts/variants/Magnetic.js   |  6 ++--
 public/javascripts/variants/Marseille.js  | 14 ++++----
 public/javascripts/variants/Switching.js  |  4 +--
 public/javascripts/variants/Zen.js        |  2 +-
 views/index.pug                           | 16 +++------
 views/layout.pug                          |  1 +
 views/userMenu.pug                        | 10 ++++++
 views/variant.pug                         | 27 +++++----------
 21 files changed, 95 insertions(+), 113 deletions(-)
 create mode 100644 views/userMenu.pug

diff --git a/TODO b/TODO
index 667f8cda..a4a9d5b9 100644
--- a/TODO
+++ b/TODO
@@ -1,10 +1,12 @@
+mat en 2 échiqueté : brnkr3/pppp1p1p/4ps2/8/2P2P2/P1qP4/2c1s1PP/R1K5
+(Bb3+ Kb1 Ba2#)
+
 // TODO: decodeURIComponent() for GET/DELETE parameters
 
 1) Finish problems tab
 2) Integrate computer play into rules tab
-3) Retrieve users system from old code
-4) Allow correspondance play (no need for P2P: online moves through the server (which also store them))
-5) Write my-games tab (included current/finished/imported)
+3) Allow correspondance play (no need for P2P: online moves through the server (which also store them))
+4) Write my-games tab (included current/finished/imported)
    Use Dexie.js, or anything to store games locally
 5) Write room tab
    Use this: https://github.com/feross/simple-peer for online games+challenges+chat
diff --git a/app.js b/app.js
index 28fd3757..e63aca44 100644
--- a/app.js
+++ b/app.js
@@ -55,6 +55,7 @@ app.use(function(req, res, next) {
 		{
 			req.userId = user.id;
 			res.locals.user = {
+				id: user.id,
 				name: user.name,
 				email: user.email,
 				notify: user.notify,
diff --git a/public/javascripts/base_rules.js b/public/javascripts/base_rules.js
index b6efa714..718261d2 100644
--- a/public/javascripts/base_rules.js
+++ b/public/javascripts/base_rules.js
@@ -498,15 +498,15 @@ class ChessRules
 	}
 
 	// Get opponent color
-	getOppCol(color)
+	static GetOppCol(color)
 	{
 		return (color=="w" ? "b" : "w");
 	}
 
 	// Get next color (for compatibility with 3 and 4 players games)
-	getNextCol(color)
+	static GetNextCol(color)
 	{
-		return this.getOppCol(color);
+		return V.GetOppCol(color);
 	}
 
 	// Pieces codes (for a clearer code)
diff --git a/public/javascripts/components/problems.js b/public/javascripts/components/problems.js
index 00cb944d..558f0bad 100644
--- a/public/javascripts/components/problems.js
+++ b/public/javascripts/components/problems.js
@@ -2,6 +2,7 @@ Vue.component('my-problems', {
 	data: function () {
 		return {
 			problems: [], //oldest first
+			myProblems: [], //same
 			curIdx: 0, //index in problems array
 			stage: "nothing", //or "preview" after new problem is filled
 			newProblem: {
@@ -30,7 +31,15 @@ Vue.component('my-problems', {
 		
 
 
-			if (this.mode == "problem")
+board qui bouge et activé que si #hash donnant numéro du problème
+deux listes : tous les problèmes sauf les miens
+              + les miens
+
+
+//TODO: filter "my problems" ==> liste séparée (lors de la requête serveur)
+--> bouton plutôt sous l'échiquier après soluce (sauf si anonymous)
+--> puis dans la vue "my problems (listing échiquier gauche / instrus + soluce cachée à droite
+if (this.mode == "problem")
 			{
 				// Show problem instructions
 				elementArray.push(
@@ -132,6 +141,7 @@ Vue.component('my-problems', {
 	created: function() {
 		// Analyse URL: if a single problem required, show it. Otherwise,
 		// TODO: fetch most recent problems from server
+		// If the requested problem is in the list, just show it
 	},
 	methods: {
 		translate: function(text) {
@@ -217,5 +227,3 @@ Vue.component('my-problems', {
 
 // TODO:
 // possibilité de supprimer / éditer si peer ID reconnu comme celui du probleme (champ "uploader")
-// --> côté serveur on vérifie un certain "secret"
-// --> filtre possible "mes problèmes"
diff --git a/public/javascripts/contactForm.js b/public/javascripts/contactForm.js
index 0c4fea3a..8b1a079f 100644
--- a/public/javascripts/contactForm.js
+++ b/public/javascripts/contactForm.js
@@ -4,8 +4,9 @@ function trySendMessage()
 	let email = document.getElementById("userEmail");
 	let subject = document.getElementById("mailSubject");
 	let content = document.getElementById("mailContent");
-	if (!email.value.match(/^[^@]+@[^@]+\.[^@]+$/))
-		return alert("Bad email");
+	const error = checkNameEmail({email: email});
+	if (!!error)
+		return alert(error);
 	if (content.value.trim().length == 0)
 		return alert("Empty message");
 	if (subject.value.trim().length == 0 && !confirm("No subject. Send anyway?"))
diff --git a/public/javascripts/index.js b/public/javascripts/index.js
index f59bc045..3d35c456 100644
--- a/public/javascripts/index.js
+++ b/public/javascripts/index.js
@@ -9,9 +9,10 @@ new Vue({
 	computed: {
 		sortedCounts: function () {
 			// TODO: priorité aux parties corr où c'est à nous de jouer !
+			const capitalizedPrefix = this.curPrefix.replace(/^\w/, c => c.toUpperCase());
 			const variantsCounts = variantArray
 			.filter( v => {
-				return v.name.startsWith(this.curPrefix);
+				return v.name.startsWith(capitalizedPrefix);
 			})
 			.map( v => {
 				return {
@@ -48,37 +49,10 @@ new Vue({
 		};
 		this.conn.onmessage = socketMessageListener;
 		this.conn.onclose = socketCloseListener;
+
+		// TODO:
+		// si dernier lastMove sur serveur n'est pas le mien et nextColor == moi, alors background orange
+		// ==> background orange si à moi de jouer par corr (sur main index)
+		// (helper: static fonction "GetNextCol()" dans base_rules.js)
 	},
-//	mounted: function() {
-//		// Handle key stroke
-//		document.onkeydown = event => {
-//			// Is it Back or Esc? If yes, apply action on current word
-//			if (event.keyCode == 8) //Back
-//			{
-//				event.preventDefault();
-//				this.curPrefix = this.curPrefix.slice(0,-1);
-//			}
-//			else if (event.keyCode == 27) //Esc
-//			{
-//				event.preventDefault();
-//				this.curPrefix = "";
-//			}
-//			// Is it alphanumeric? If yes, stack it
-//			else if (_.range(48,58).includes(event.keyCode)
-//				|| _.range(65,91).includes(event.keyCode)
-//				|| _.range(97,123).includes(event.keyCode))
-//			{
-//				let newChar = String.fromCharCode(event.keyCode);
-//				this.curPrefix += this.curPrefix.length==0
-//					? newChar.toUpperCase()
-//					: newChar.toLowerCase();
-//			}
-//			// ...ignore everything else
-//		};
-//	},
 });
-
-// TODO:
-// si dernier lastMove sur serveur n'est pas le mien et nextColor == moi, alors background orange
-// ==> background orange si à moi de jouer par corr (sur main index)
-// (fonction "getNextCol()" dans base_rules.js ?)
diff --git a/public/javascripts/variants/Alice.js b/public/javascripts/variants/Alice.js
index 57c7b25c..3a613585 100644
--- a/public/javascripts/variants/Alice.js
+++ b/public/javascripts/variants/Alice.js
@@ -154,7 +154,7 @@ class AliceRules extends ChessRules
 			if (m.vanish[0].p == V.PAWN && m.vanish.length == 2
 				&& this.board[m.end.x][m.end.y] == V.EMPTY)
 			{
-				m.vanish[1].c = this.getOppCol(this.getColor(x,y));
+				m.vanish[1].c = V.GetOppCol(this.getColor(x,y));
 				// In the special case of en-passant, if
 				//  - board1 takes board2 : vanish[1] --> Alice
 				//  - board2 takes board1 : vanish[1] --> normal
@@ -186,7 +186,7 @@ class AliceRules extends ChessRules
 	getAllValidMoves()
 	{
 		const color = this.turn;
-		const oppCol = this.getOppCol(color);
+		const oppCol = V.GetOppCol(color);
 		var potentialMoves = [];
 		let sideBoard = [this.getSideBoard(1), this.getSideBoard(2)];
 		for (var i=0; i<V.size.x; i++)
@@ -247,7 +247,7 @@ class AliceRules extends ChessRules
 		const mirrorSide = (sideBoard[0][kp[0]][kp[1]] != V.EMPTY ? 1 : 2);
 		let saveBoard = this.board;
 		this.board = sideBoard[mirrorSide-1];
-		let res = this.isAttacked(kp, [this.getOppCol(color)]);
+		let res = this.isAttacked(kp, [V.GetOppCol(color)]);
 		this.board = saveBoard;
 		return res;
 	}
@@ -260,7 +260,7 @@ class AliceRules extends ChessRules
 		let sideBoard = this.getSideBoard(mirrorSide);
 		let saveBoard = this.board;
 		this.board = sideBoard;
-		let res = this.isAttacked(this.kingPos[color], [this.getOppCol(color)])
+		let res = this.isAttacked(this.kingPos[color], [V.GetOppCol(color)])
 			? [ JSON.parse(JSON.stringify(this.kingPos[color])) ]
 			: [ ];
 		this.board = saveBoard;
@@ -299,7 +299,7 @@ class AliceRules extends ChessRules
 		let saveBoard = this.board;
 		this.board = sideBoard;
 		let res = "*";
-		if (!this.isAttacked(this.kingPos[color], [this.getOppCol(color)]))
+		if (!this.isAttacked(this.kingPos[color], [V.GetOppCol(color)]))
 			res = "1/2";
 		else
 			res = (color == "w" ? "0-1" : "1-0");
diff --git a/public/javascripts/variants/Antiking.js b/public/javascripts/variants/Antiking.js
index ed69ab71..45daa62b 100644
--- a/public/javascripts/variants/Antiking.js
+++ b/public/javascripts/variants/Antiking.js
@@ -90,7 +90,7 @@ class AntikingRules extends ChessRules
 
 	underCheck(color)
 	{
-		const oppCol = this.getOppCol(color);
+		const oppCol = V.GetOppCol(color);
 		let res = this.isAttacked(this.kingPos[color], [oppCol])
 			|| !this.isAttacked(this.antikingPos[color], [oppCol]);
 		return res;
@@ -99,7 +99,7 @@ class AntikingRules extends ChessRules
 	getCheckSquares(color)
 	{
 		let res = super.getCheckSquares(color);
-		if (!this.isAttacked(this.antikingPos[color], [this.getOppCol(color)]))
+		if (!this.isAttacked(this.antikingPos[color], [V.GetOppCol(color)]))
 			res.push(JSON.parse(JSON.stringify(this.antikingPos[color])));
 		return res;
 	}
@@ -128,7 +128,7 @@ class AntikingRules extends ChessRules
 	checkGameEnd()
 	{
 		const color = this.turn;
-		const oppCol = this.getOppCol(color);
+		const oppCol = V.GetOppCol(color);
 		if (!this.isAttacked(this.kingPos[color], [oppCol])
 			&& this.isAttacked(this.antikingPos[color], [oppCol]))
 		{
diff --git a/public/javascripts/variants/Atomic.js b/public/javascripts/variants/Atomic.js
index 2adb9884..255444f2 100644
--- a/public/javascripts/variants/Atomic.js
+++ b/public/javascripts/variants/Atomic.js
@@ -90,7 +90,7 @@ class AtomicRules extends ChessRules
 	{
 		super.unupdateVariables(move);
 		const c = move.vanish[0].c;
-		const oppCol = this.getOppCol(c);
+		const oppCol = V.GetOppCol(c);
 		if ([this.kingPos[c][0],this.kingPos[oppCol][0]].some(e => { return e < 0; }))
 		{
 			// There is a chance that last move blowed some king away..
@@ -104,7 +104,7 @@ class AtomicRules extends ChessRules
 
 	underCheck(color)
 	{
-		const oppCol = this.getOppCol(color);
+		const oppCol = V.GetOppCol(color);
 		let res = undefined;
 		// If our king disappeared, move is not valid
 		if (this.kingPos[color][0] < 0)
@@ -122,7 +122,7 @@ class AtomicRules extends ChessRules
 	{
 		let res = [ ];
 		if (this.kingPos[color][0] >= 0 //king might have exploded
-			&& this.isAttacked(this.kingPos[color], [this.getOppCol(color)]))
+			&& this.isAttacked(this.kingPos[color], [V.GetOppCol(color)]))
 		{
 			res = [ JSON.parse(JSON.stringify(this.kingPos[color])) ]
 		}
@@ -135,7 +135,7 @@ class AtomicRules extends ChessRules
 		const kp = this.kingPos[color];
 		if (kp[0] < 0) //king disappeared
 			return color == "w" ? "0-1" : "1-0";
-		if (!this.isAttacked(kp, [this.getOppCol(color)]))
+		if (!this.isAttacked(kp, [V.GetOppCol(color)]))
 			return "1/2";
 		return color == "w" ? "0-1" : "1-0"; //checkmate
 	}
diff --git a/public/javascripts/variants/Baroque.js b/public/javascripts/variants/Baroque.js
index fe0e8466..38d4012c 100644
--- a/public/javascripts/variants/Baroque.js
+++ b/public/javascripts/variants/Baroque.js
@@ -58,7 +58,7 @@ class BaroqueRules extends ChessRules
 	{
 		const piece = this.getPiece(x,y);
 		const color = this.getColor(x,y);
-		const oppCol = this.getOppCol(color);
+		const oppCol = V.GetOppCol(color);
 		const adjacentSteps = V.steps[V.ROOK].concat(V.steps[V.BISHOP]);
 		outerLoop:
 		for (let step of adjacentSteps)
@@ -137,7 +137,7 @@ class BaroqueRules extends ChessRules
 	{
 		const steps = V.steps[V.ROOK];
 		const color = this.turn;
-		const oppCol = this.getOppCol(color);
+		const oppCol = V.GetOppCol(color);
 		moves.forEach(m => {
 			if (!!byChameleon && m.start.x!=m.end.x && m.start.y!=m.end.y)
 				return; //chameleon not moving as pawn
@@ -180,7 +180,7 @@ class BaroqueRules extends ChessRules
 	addRookCaptures(moves, byChameleon)
 	{
 		const color = this.turn;
-		const oppCol = this.getOppCol(color);
+		const oppCol = V.GetOppCol(color);
 		const kp = this.kingPos[color];
 		moves.forEach(m => {
 			// Check piece-king rectangle (if any) corners for enemy pieces
@@ -221,7 +221,7 @@ class BaroqueRules extends ChessRules
 		// Look in every direction for captures
 		const steps = V.steps[V.ROOK].concat(V.steps[V.BISHOP]);
 		const color = this.turn;
-		const oppCol = this.getOppCol(color);
+		const oppCol = V.GetOppCol(color);
 		let moves = [];
 		const [x,y] = [startSquare[0],startSquare[1]];
 		const piece = this.getPiece(x,y); //might be a chameleon!
@@ -321,7 +321,7 @@ class BaroqueRules extends ChessRules
 		const adjacentSteps = V.steps[V.ROOK].concat(V.steps[V.BISHOP]);
 		let capturingDirections = [];
 		const color = this.turn;
-		const oppCol = this.getOppCol(color);
+		const oppCol = V.GetOppCol(color);
 		adjacentSteps.forEach(step => {
 			const [i,j] = [x+step[0],y+step[1]];
 			if (V.OnBoard(i,j) && this.board[i][j] != V.EMPTY && this.getColor(i,j) == oppCol
diff --git a/public/javascripts/variants/Checkered.js b/public/javascripts/variants/Checkered.js
index 4a9419a8..6864673c 100644
--- a/public/javascripts/variants/Checkered.js
+++ b/public/javascripts/variants/Checkered.js
@@ -181,15 +181,15 @@ class CheckeredRules extends ChessRules
 
 	underCheck(color)
 	{
-		return this.isAttacked(this.kingPos[color], [this.getOppCol(color),'c']);
+		return this.isAttacked(this.kingPos[color], [V.GetOppCol(color),'c']);
 	}
 
 	getCheckSquares(color)
 	{
 		// Artifically change turn, for checkered pawns
-		this.turn = this.getOppCol(color);
+		this.turn = V.GetOppCol(color);
 		const kingAttacked = this.isAttacked(
-			this.kingPos[color], [this.getOppCol(color),'c']);
+			this.kingPos[color], [V.GetOppCol(color),'c']);
 		let res = kingAttacked
 			? [JSON.parse(JSON.stringify(this.kingPos[color]))] //need to duplicate!
 			: [];
@@ -210,11 +210,11 @@ class CheckeredRules extends ChessRules
 	{
 		const color = this.turn;
 		// Artifically change turn, for checkered pawns
-		this.turn = this.getOppCol(this.turn);
-		const res = this.isAttacked(this.kingPos[color], [this.getOppCol(color),'c'])
+		this.turn = V.GetOppCol(this.turn);
+		const res = this.isAttacked(this.kingPos[color], [V.GetOppCol(color),'c'])
 			? (color == "w" ? "0-1" : "1-0")
 			: "1/2";
-		this.turn = this.getOppCol(this.turn);
+		this.turn = V.GetOppCol(this.turn);
 		return res;
 	}
 
diff --git a/public/javascripts/variants/Dark.js b/public/javascripts/variants/Dark.js
index 79d27b5b..e1ab30dd 100644
--- a/public/javascripts/variants/Dark.js
+++ b/public/javascripts/variants/Dark.js
@@ -65,7 +65,7 @@ class DarkRules extends ChessRules
 	getAllValidMoves()
 	{
 		const color = this.turn;
-		const oppCol = this.getOppCol(color);
+		const oppCol = V.GetOppCol(color);
 		let potentialMoves = [];
 		for (let i=0; i<V.size.x; i++)
 		{
@@ -112,7 +112,7 @@ class DarkRules extends ChessRules
 	{
 		super.unupdateVariables(move);
 		const c = move.vanish[0].c;
-		const oppCol = this.getOppCol(c);
+		const oppCol = V.GetOppCol(c);
 		if (this.kingPos[oppCol][0] < 0)
 		{
 			// Last move took opponent's king
@@ -146,7 +146,7 @@ class DarkRules extends ChessRules
 	{
 		const maxeval = V.INFINITY;
 		const color = this.turn;
-		const oppCol = this.getOppCol(color);
+		const oppCol = V.GetOppCol(color);
 		const pawnShift = (color == "w" ? -1 : 1);
 		const kp = this.kingPos[color];
 
diff --git a/public/javascripts/variants/Losers.js b/public/javascripts/variants/Losers.js
index c9509c6f..9af6776c 100644
--- a/public/javascripts/variants/Losers.js
+++ b/public/javascripts/variants/Losers.js
@@ -42,7 +42,7 @@ class LosersRules extends ChessRules
 	atLeastOneCapture()
 	{
 		const color = this.turn;
-		const oppCol = this.getOppCol(color);
+		const oppCol = V.GetOppCol(color);
 		for (let i=0; i<V.size.x; i++)
 		{
 			for (let j=0; j<V.size.y; j++)
diff --git a/public/javascripts/variants/Magnetic.js b/public/javascripts/variants/Magnetic.js
index 7b0d096c..8adb1bab 100644
--- a/public/javascripts/variants/Magnetic.js
+++ b/public/javascripts/variants/Magnetic.js
@@ -156,14 +156,14 @@ class MagneticRules extends ChessRules
 		if (move.vanish.length >= 2 && move.vanish[1].p == V.KING)
 		{
 			// We took opponent king !
-			const oppCol = this.getOppCol(c);
+			const oppCol = V.GetOppCol(c);
 			this.kingPos[oppCol] = [-1,-1];
 			this.castleFlags[oppCol] = [false,false];
 		}
 		// Did we magnetically move our (init) rooks or opponents' ones ?
 		const firstRank = (c == "w" ? 7 : 0);
 		const oppFirstRank = 7 - firstRank;
-		const oppCol = this.getOppCol(c);
+		const oppCol = V.GetOppCol(c);
 		move.vanish.forEach(psq => {
 			if (psq.x == firstRank && this.INIT_COL_ROOK[c].includes(psq.y))
 				this.castleFlags[c][psq.y==this.INIT_COL_ROOK[c][0] ? 0 : 1] = false;
@@ -176,7 +176,7 @@ class MagneticRules extends ChessRules
 	{
 		super.unupdateVariables(move);
 		const c = move.vanish[0].c;
-		const oppCol = this.getOppCol(c);
+		const oppCol = V.GetOppCol(c);
 		if (this.kingPos[oppCol][0] < 0)
 		{
 			// Last move took opponent's king
diff --git a/public/javascripts/variants/Marseille.js b/public/javascripts/variants/Marseille.js
index f372698d..1adb83f4 100644
--- a/public/javascripts/variants/Marseille.js
+++ b/public/javascripts/variants/Marseille.js
@@ -117,7 +117,7 @@ class MarseilleRules extends ChessRules
 		});
 		if (epSqs.length == 0)
 			return moves;
-		const oppCol = this.getOppCol(color);
+		const oppCol = V.GetOppCol(color);
 		for (let sq of epSqs)
 		{
 			if (this.subTurn == 1 || (epSqs.length == 2 &&
@@ -161,9 +161,9 @@ class MarseilleRules extends ChessRules
 			this.epSquares.push([epSq]);
 		}
 		// Does this move give check on subturn 1? If yes, skip subturn 2
-		else if (this.subTurn==1 && this.underCheck(this.getOppCol(this.turn)))
+		else if (this.subTurn==1 && this.underCheck(V.GetOppCol(this.turn)))
 		{
-			this.turn = this.getOppCol(this.turn);
+			this.turn = V.GetOppCol(this.turn);
 			this.epSquares.push([epSq]);
 			move.checkOnSubturn1 = true;
 		}
@@ -171,7 +171,7 @@ class MarseilleRules extends ChessRules
 		{
 			if (this.subTurn == 2)
 			{
-				this.turn = this.getOppCol(this.turn);
+				this.turn = V.GetOppCol(this.turn);
 				let lastEpsq = this.epSquares[this.epSquares.length-1];
 				lastEpsq.push(epSq);
 			}
@@ -196,7 +196,7 @@ class MarseilleRules extends ChessRules
 		}
 		else if (move.checkOnSubturn1)
 		{
-			this.turn = this.getOppCol(this.turn);
+			this.turn = V.GetOppCol(this.turn);
 			this.subTurn = 1;
 			this.epSquares.pop();
 		}
@@ -204,7 +204,7 @@ class MarseilleRules extends ChessRules
 		{
 			if (this.subTurn == 1)
 			{
-				this.turn = this.getOppCol(this.turn);
+				this.turn = V.GetOppCol(this.turn);
 				let lastEpsq = this.epSquares[this.epSquares.length-1];
 				lastEpsq.pop();
 			}
@@ -239,7 +239,7 @@ class MarseilleRules extends ChessRules
 
 		const maxeval = V.INFINITY;
 		const color = this.turn;
-		const oppCol = this.getOppCol(this.turn);
+		const oppCol = V.GetOppCol(this.turn);
 
 		// Search best (half) move for opponent turn
 		const getBestMoveEval = () => {
diff --git a/public/javascripts/variants/Switching.js b/public/javascripts/variants/Switching.js
index 67078f53..d898ff63 100644
--- a/public/javascripts/variants/Switching.js
+++ b/public/javascripts/variants/Switching.js
@@ -57,7 +57,7 @@ class SwitchingRules extends ChessRules
 		const piece = this.getPiece(x,y);
 		const steps = V.steps[V.ROOK].concat(V.steps[V.BISHOP]);
 		const kp = this.kingPos[color];
-		const oppCol = this.getOppCol(color);
+		const oppCol = V.GetOppCol(color);
 		for (let step of steps)
 		{
 			let [i,j] = [x+step[0],y+step[1]];
@@ -81,7 +81,7 @@ class SwitchingRules extends ChessRules
 	getAllValidMoves(computer)
 	{
 		const color = this.turn;
-		const oppCol = this.getOppCol(color);
+		const oppCol = V.GetOppCol(color);
 		let potentialMoves = [];
 		for (let i=0; i<V.size.x; i++)
 		{
diff --git a/public/javascripts/variants/Zen.js b/public/javascripts/variants/Zen.js
index 0675fbc9..7713b848 100644
--- a/public/javascripts/variants/Zen.js
+++ b/public/javascripts/variants/Zen.js
@@ -52,7 +52,7 @@ class ZenRules extends ChessRules
 				i += step[0];
 				j += step[1];
 			}
-			if (V.OnBoard(i,j) && this.getColor(i,j) == this.getOppCol(color)
+			if (V.OnBoard(i,j) && this.getColor(i,j) == V.GetOppCol(color)
 				&& this.getPiece(i,j) == asA)
 			{
 				// eat!
diff --git a/views/index.pug b/views/index.pug
index 45a2ec77..6b13a4e9 100644
--- a/views/index.pug
+++ b/views/index.pug
@@ -21,19 +21,14 @@ block content
 					img(src="/images/index/wildebeest.svg")
 				#flagMenu.clickable(onClick="doClick('modalLang')")
 					img(src="/images/flags/" + lang + ".svg")
-				#userMenu.clickable(onClick="doClick('modalUser')")
-					.info-container
-						if !user.email
-							p
-								span Login
-								i.material-icons person
-						else
-							p
-								span Update
-								i.material-icons person
+				include userMenu
 				#introductionMenu.clickable(onClick="doClick('modalWelcome')")
 					.info-container
 						p Introduction
+		.row
+			.col-sm-12.col-md-10.col-md-offset-1.col-lg-8.col-lg-offset-2
+				label(for="prefixFilter") Type first letters...
+				input#prefixFilter(v-model="curPrefix")
 		.row
 			my-variant-summary(v-for="(v,idx) in sortedCounts"
 				v-bind:vobj="v" v-bind:index="idx" v-bind:key="v.name")
@@ -41,7 +36,6 @@ block content
 block javascripts
 	script.
 		const variantArray = !{JSON.stringify(variantArray)};
-	script(src="/javascripts/utils/misc.js")
 	script(src="/javascripts/socket_url.js")
 	script(src="/javascripts/components/variantSummary.js")
 	script(src="/javascripts/index.js")
diff --git a/views/layout.pug b/views/layout.pug
index 6004fc32..e5883eef 100644
--- a/views/layout.pug
+++ b/views/layout.pug
@@ -44,6 +44,7 @@ html
 					=translations["Contact"]
 
 		script(src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.9.1/underscore-min.js")
+		script(src="/javascripts/utils/misc.js")
 		script(src="/javascripts/utils/ajax.js")
 		script(src="/javascripts/layout.js")
 		script(src="/javascripts/settings.js")
diff --git a/views/userMenu.pug b/views/userMenu.pug
new file mode 100644
index 00000000..f590a2ee
--- /dev/null
+++ b/views/userMenu.pug
@@ -0,0 +1,10 @@
+#userMenu.clickable(onClick="doClick('modalUser')")
+	.info-container
+		if !user.email
+			p
+				span Login
+				i.material-icons person
+		else
+			p
+				span Update
+				i.material-icons person
diff --git a/views/variant.pug b/views/variant.pug
index 5bfcba10..15c546d0 100644
--- a/views/variant.pug
+++ b/views/variant.pug
@@ -22,26 +22,17 @@ block content
 						=translations["Rules"]
 					a(href="#problems" @click="setDisplay('problems')")
 						=translations["Problems"]
-					#settings.clickable(
-							onClick="document.getElementById('modalSettings').checked=true")
+					#settings.clickable(onClick="doClick('modalSettings')")
 						i.material-icons settings
-					#userMenu.clickable(
-							onClick="document.getElementById('modalUser').checked=true")
-						.info-container
-							i.material-icons person
-							if !user.email
-								p Login
-							else
-								p Update
+					include userMenu
 		.row
-			my-room(v-show="display=='room'")
-			my-game-list(v-show="display=='gameList'")
+			//my-room(v-show="display=='room'")
+			//my-game-list(v-show="display=='gameList'")
 			my-rules(v-show="display=='rules'")
 			my-problems(v-show="display=='problems'")
-			my-game(v-show="display=='game'" :gameId="gameid")
+			//my-game(v-show="display=='game'" :gameId="gameid")
 
 block javascripts
-	script(src="/javascripts/utils/misc.js")
 	script(src="/javascripts/utils/array.js")
 	script(src="/javascripts/utils/printDiagram.js")
 	script(src="/javascripts/utils/datetime.js")
@@ -51,10 +42,10 @@ block javascripts
 	script.
 		const V = VariantRules; //because this variable is often used
 		const variant = !{JSON.stringify(variant)};
-	script(src="/javascripts/components/room.js")
-	script(src="/javascripts/components/gameList.js")
+	//script(src="/javascripts/components/room.js")
+	//script(src="/javascripts/components/gameList.js")
 	script(src="/javascripts/components/rules.js")
-	script(src="/javascripts/components/problemSummary.js")
+	script(src="/javascripts/components/problemPreview.js")
 	script(src="/javascripts/components/problems.js")
-	script(src="/javascripts/components/game.js")
+	//script(src="/javascripts/components/game.js")
 	script(src="/javascripts/variant.js")
-- 
2.44.0