From 42eb4eaf62becc9260897277e1cfe5882eba2017 Mon Sep 17 00:00:00 2001 From: Benjamin Auder <benjamin.auder@somewhere> Date: Wed, 6 Feb 2019 19:16:12 +0100 Subject: [PATCH] Seemingly failed attempt at 'componentifying VariantRules' --- client/package-lock.json | 17 ++- client/package.json | 1 + client/src/components/Diagrammer.vue | 181 +++++++++++++++++++++++++ client/src/components/VariantRules.vue | 48 +++++++ client/src/rules/Alice/en.pug | 4 +- client/src/rules/Chess960/fr.pug | 3 +- client/src/utils/printDiagram.js | 110 --------------- client/src/views/Rules.vue | 55 ++++---- 8 files changed, 270 insertions(+), 149 deletions(-) create mode 100644 client/src/components/Diagrammer.vue create mode 100644 client/src/components/VariantRules.vue delete mode 100644 client/src/utils/printDiagram.js diff --git a/client/package-lock.json b/client/package-lock.json index 020d47e0..76d6211d 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -8837,6 +8837,17 @@ "pug-walk": "^1.1.7" } }, + "pug-loader": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/pug-loader/-/pug-loader-2.4.0.tgz", + "integrity": "sha512-cD4bU2wmkZ1EEVyu0IfKOsh1F26KPva5oglO1Doc3knx8VpBIXmFHw16k9sITYIjQMCnRv1vb4vfQgy7VdR6eg==", + "dev": true, + "requires": { + "loader-utils": "^1.1.0", + "pug-walk": "^1.0.0", + "resolve": "^1.1.7" + } + }, "pug-parser": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/pug-parser/-/pug-parser-5.0.0.tgz", @@ -9005,9 +9016,9 @@ }, "dependencies": { "ajv-keywords": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.2.0.tgz", - "integrity": "sha1-6GuBnGAs+IIa1jdBNpjx3sAhhHo=", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.3.0.tgz", + "integrity": "sha512-CMzN9S62ZOO4sA/mJZIO4S++ZM7KFWzH3PPWkveLhy4OZ9i1/VatgwWMD46w/XbGCBy7Ye0gCk+Za6mmyfKK7g==", "dev": true }, "schema-utils": { diff --git a/client/package.json b/client/package.json index 62781668..6f8f270a 100644 --- a/client/package.json +++ b/client/package.json @@ -21,6 +21,7 @@ "lint-staged": "^8.1.0", "node-sass": "^4.9.0", "pug": "^2.0.3", + "pug-loader": "^2.4.0", "pug-plain-loader": "^1.0.0", "raw-loader": "^1.0.0", "sass-loader": "^7.0.1", diff --git a/client/src/components/Diagrammer.vue b/client/src/components/Diagrammer.vue new file mode 100644 index 00000000..04767dfe --- /dev/null +++ b/client/src/components/Diagrammer.vue @@ -0,0 +1,181 @@ +<script> +import { store } from "@/store"; +import { ArrayFun } from "@/utils/array"; +export default { + name: "my-diagrammer", + props: ["fen","vname"], + data: { + function() { + return { + st: store.state, + // args: object with position (mandatory), and + // orientation, marks, shadow (optional) + args: this.parseFen(this.fen), + }; + } + }, + render(h) { + if (!window.V) + return; + // Obtain the array of pieces images names: + const board = V.GetBoard(this.args.position); + const orientation = this.args.orientation || "w"; + const markArray = this.getMarkArray(this.args.marks); + const shadowArray = this.getShadowArray(this.args.shadow); +// const [startX,startY,inc] = orientation == 'w' +// ? [0, 0, 1] +// : [V.size.x-1, V.size.y-1, -1]; + const diagDiv = h( + 'div', + { + 'class': { + 'diagram': true, + }, + }, + [...Array(V.size.x).keys()].map(i => { + let ci = (orientation=='w' ? i : sizeX-i-1); + return h( + 'div', + { + 'class': { + 'row': true, + }, + }, + [...Array(V.size.y).keys()].map(j => { + let cj = (orientation=='w' ? j : sizeY-j-1); + let elems = []; + if (board[ci][cj] != V.EMPTY) + { + elems.push( + h( + 'img', + { + 'class': { + 'piece': true, + }, + attrs: { + src: require("@/assets/images/pieces/" + + V.getPpath(board[ci][cj]) + ".svg"), + }, + } + ) + ); + } + if (markArray.length > 0 && markArray[ci][cj]) + { + elems.push( + h( + 'img', + { + 'class': { + 'mark-square': true, + }, + attrs: { + src: "/images/mark.svg", + }, + } + ) + ); + } + return h( + 'div', + { + 'class': { + 'board': true, + ['board'+V.size.y]: true, + 'light-square': (i+j)%2==0, + 'dark-square': (i+j)%2==1, + [this.st.bcolor]: true, + 'in-shadow': shadowArray.length > 0 && shadowArray[ci][cj], + }, + }, + elems + ); + }) + ); + }) + ); + return diagDiv; + }, + methods: { + parseFen: function(fen) { + const fenParts = fen.split(" "); + return { + position: fenParts[0], + marks: fenParts[1], + orientation: fenParts[2], + shadow: fenParts[3], + }; + }, + // Turn (human) marks into coordinates + getMarkArray: function(marks) { + if (!marks || marks == "-") + return []; + let markArray = ArrayFun.init(V.size.x, V.size.y, false); + const squares = marks.split(","); + for (let i=0; i<squares.length; i++) + { + const coords = V.SquareToCoords(squares[i]); + markArray[coords.x][coords.y] = true; + } + return markArray; + }, + // Turn (human) shadow indications into coordinates + getShadowArray: function(shadow) { + if (!shadow || shadow == "-") + return []; + let shadowArray = ArrayFun.init(V.size.x, V.size.y, false); + const squares = shadow.split(","); + for (let i=0; i<squares.length; i++) + { + const rownum = V.size.x - parseInt(squares[i]); + if (!isNaN(rownum)) + { + // Shadow a full row + for (let i=0; i<V.size.y; i++) + shadowArray[rownum][i] = true; + continue; + } + if (squares[i].length == 1) + { + // Shadow a full column + const colnum = V.ColumnToCoord(squares[i]); + for (let i=0; i<V.size.x; i++) + shadowArray[i][colnum] = true; + continue; + } + if (squares[i].indexOf("-") >= 0) + { + // Shadow a range of squares, horizontally or vertically + const firstLastSq = squares[i].split("-"); + const range = + [ + V.SquareToCoords(firstLastSq[0]), + V.SquareToCoords(firstLastSq[1]) + ]; + const step = + [ + range[1].x == range[0].x + ? 0 + : (range[1].x - range[0].x) / Math.abs(range[1].x - range[0].x), + range[1].y == range[0].y + ? 0 + : (range[1].y - range[0].y) / Math.abs(range[1].y - range[0].y) + ]; + // Convention: range always from smaller to larger number + for (let x=range[0].x, y=range[0].y; x <= range[1].x && y <= range[1].y; + x += step[0], y += step[1]) + { + shadowArray[x][y] = true; + } + continue; + } + // Shadow just one square: + const coords = V.SquareToCoords(squares[i]); + shadowArray[coords.x][coords.y] = true; + } + return shadowArray; + }, + }, +}; +</script> diff --git a/client/src/components/VariantRules.vue b/client/src/components/VariantRules.vue new file mode 100644 index 00000000..a2c89e32 --- /dev/null +++ b/client/src/components/VariantRules.vue @@ -0,0 +1,48 @@ +<!--<template :src="require(`@/rules/${vname}/${st.lang}.pug`)"> +</template> +--> + +<template lang="pug"> +.section-content(v-html="content") +</template> + +<script> +import Diagrammer from "@/components/Diagrammer"; +import { store } from "@/store"; +export default { + name: "my-variant-rules", + components: { + Diagrammer, + }, + props: ["vname"], + data: function() { + return { + st: store.state, + content: "", + }; + }, + watch: { + vname: function() { + this.loadVariantFile(); + }, + }, + methods: { + loadVariantFile: function() { + if (this.vname != "_unknown") + { + // TODO (to understand): no loader required here ? Pug preset ? + const content = require("raw-loader!@/rules/" + this.vname + "/" + this.st.lang + ".pug"); + console.log(content); + this.content = content; + } + }, + }, + created: function() { + this.loadVariantFile(); + }, +}; +</script> + +<!-- + TODO: template + script dans rules/Alice/en.pug (-> .vue), puis dynamic import ici ?! +--> diff --git a/client/src/rules/Alice/en.pug b/client/src/rules/Alice/en.pug index be97d1b4..6bba6407 100644 --- a/client/src/rules/Alice/en.pug +++ b/client/src/rules/Alice/en.pug @@ -21,8 +21,8 @@ ul figure.diagram-container // TODO: sub-component + use pug-loader instead of raw-loader - Diagram(:fen="rnbqkbnr/ppp1pppp/8/8/2p5/5O2/PP1PPPPP/RNBQKB1R") - .diagram + Diagram(fen="rnbqkbnr/ppp1pppp/8/8/2p5/5O2/PP1PPPPP/RNBQKB1R" vname="Alice") + //.diagram | fen:rnbqkbnr/ppp1pppp/8/8/2p5/5O2/PP1PPPPP/RNBQKB1R: figcaption After the moves 1.Nf3 Pd5 2.Pc4 Sxc4 diff --git a/client/src/rules/Chess960/fr.pug b/client/src/rules/Chess960/fr.pug index 9b62de16..3325f810 100644 --- a/client/src/rules/Chess960/fr.pug +++ b/client/src/rules/Chess960/fr.pug @@ -16,8 +16,7 @@ p. en arrivant sur une case occupée (avec une seule exception, détaillée plus bas). figure.diagram-container - .diagram - | fen:rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR: + Diagrammer(fen="rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR" vname="Chess960") figcaption Position de départ habituelle. p. diff --git a/client/src/utils/printDiagram.js b/client/src/utils/printDiagram.js deleted file mode 100644 index 7ae23228..00000000 --- a/client/src/utils/printDiagram.js +++ /dev/null @@ -1,110 +0,0 @@ -import { ArrayFun } from "@/utils/array"; - -// Turn (human) marks into coordinates -function getMarkArray(marks) -{ - if (!marks || marks == "-") - return []; - let markArray = ArrayFun.init(V.size.x, V.size.y, false); - const squares = marks.split(","); - for (let i=0; i<squares.length; i++) - { - const coords = V.SquareToCoords(squares[i]); - markArray[coords.x][coords.y] = true; - } - return markArray; -} - -// Turn (human) shadow indications into coordinates -function getShadowArray(shadow) -{ - if (!shadow || shadow == "-") - return []; - let shadowArray = ArrayFun.init(V.size.x, V.size.y, false); - const squares = shadow.split(","); - for (let i=0; i<squares.length; i++) - { - const rownum = V.size.x - parseInt(squares[i]); - if (!isNaN(rownum)) - { - // Shadow a full row - for (let i=0; i<V.size.y; i++) - shadowArray[rownum][i] = true; - continue; - } - if (squares[i].length == 1) - { - // Shadow a full column - const colnum = V.ColumnToCoord(squares[i]); - for (let i=0; i<V.size.x; i++) - shadowArray[i][colnum] = true; - continue; - } - if (squares[i].indexOf("-") >= 0) - { - // Shadow a range of squares, horizontally or vertically - const firstLastSq = squares[i].split("-"); - const range = - [ - V.SquareToCoords(firstLastSq[0]), - V.SquareToCoords(firstLastSq[1]) - ]; - const step = - [ - range[1].x == range[0].x - ? 0 - : (range[1].x - range[0].x) / Math.abs(range[1].x - range[0].x), - range[1].y == range[0].y - ? 0 - : (range[1].y - range[0].y) / Math.abs(range[1].y - range[0].y) - ]; - // Convention: range always from smaller to larger number - for (let x=range[0].x, y=range[0].y; x <= range[1].x && y <= range[1].y; - x += step[0], y += step[1]) - { - shadowArray[x][y] = true; - } - continue; - } - // Shadow just one square: - const coords = V.SquareToCoords(squares[i]); - shadowArray[coords.x][coords.y] = true; - } - return shadowArray; -} - -// args: object with position (mandatory), and -// orientation, marks, shadow (optional) -export function getDiagram(args) -{ - // Obtain the array of pieces images names: - const board = V.GetBoard(args.position); - const orientation = args.orientation || "w"; - const markArray = getMarkArray(args.marks); - const shadowArray = getShadowArray(args.shadow); - let boardDiv = ""; - const [startX,startY,inc] = orientation == 'w' - ? [0, 0, 1] - : [V.size.x-1, V.size.y-1, -1]; - for (let i=startX; i>=0 && i<V.size.x; i+=inc) - { - boardDiv += "<div class='row'>"; - for (let j=startY; j>=0 && j<V.size.y; j+=inc) - { - boardDiv += "<div class='board board" + V.size.y + " " + - ((i+j)%2==0 ? "light-square-diag" : "dark-square-diag") + - (shadowArray.length > 0 && shadowArray[i][j] ? " in-shadow" : "") + - "'>"; - if (board[i][j] != V.EMPTY) - { - boardDiv += "<img :src='require(`@/assets/images/pieces/" + - V.getPpath(board[i][j]) + ".svg`) class='piece'/>"; - } - if (markArray.length > 0 && markArray[i][j]) - boardDiv += "<img src='/images/mark.svg' class='mark-square'/>"; - boardDiv += "</div>"; - } - boardDiv += "</div>"; - } - return boardDiv; -} diff --git a/client/src/views/Rules.vue b/client/src/views/Rules.vue index fd26f16b..fd668462 100644 --- a/client/src/views/Rules.vue +++ b/client/src/views/Rules.vue @@ -9,7 +9,7 @@ | Beat the computer! button(v-show="gameInProgress" @click="stopGame") | Stop game - div(v-show="display=='rules'" v-html="content" class="section-content") + VariantRules(v-show="display=='rules'" :vname="variant.name") Game(v-show="display=='computer'" :gid-or-fen="fen" :mode="mode" :sub-mode="subMode" :variant="variant" @computer-think="gameInProgress=false" @game-over="stopGame") @@ -18,17 +18,17 @@ <script> import Game from "@/components/Game.vue"; import { store } from "@/store"; -import { getDiagram } from "@/utils/printDiagram"; +import VariantRules from "@/components/VariantRules"; export default { name: 'my-rules', components: { Game, + VariantRules, }, data: function() { return { st: store.state, - variant: {id: 0, name: "Unknown"}, //...yet - content: "", + variant: {id: 0, name: "_unknown"}, //...yet display: "rules", mode: "computer", subMode: "", //'auto' for game CPU vs CPU @@ -37,37 +37,28 @@ export default { fen: "", }; }, - mounted: async function() { + watch: { + $route: function(newRoute) { + this.tryChangeVariant(newRoute.params["vname"]); + }, + }, + created: async function() { // NOTE: variant cannot be set before store is initialized - const vname = this.$route.params["vname"]; - //const idxOfVar = this.st.variants.indexOf(e => e.name == vname); - //this.variant = this.st.variants[idxOfVar]; //TODO: is it the right timing?! - this.variant.name = vname; - const vModule = await import("@/variants/" + vname + ".js"); - window.V = vModule.VariantRules; - // Method to replace diagrams in loaded HTML - const replaceByDiag = (match, p1, p2) => { - const args = this.parseFen(p2); - return getDiagram(args); - }; - // (AJAX) Request to get rules content (plain text, HTML) - // TODO: find a way to have Diagram(er) as a component, - // thus allowing images import through require(), handled by Webpack - // ==> the rules files should be less static - this.content = - // TODO: why doesn't this work? require("raw-loader!pug-plain-loader!@/rules/"...) - require("raw-loader!@/rules/" + vname + "/" + this.st.lang + ".pug") - .replace(/(fen:)([^:]*):/g, replaceByDiag); + this.tryChangeVariant(this.$route.params["vname"]); }, methods: { - parseFen(fen) { - const fenParts = fen.split(" "); - return { - position: fenParts[0], - marks: fenParts[1], - orientation: fenParts[2], - shadow: fenParts[3], - }; + tryChangeVariant: async function(vname) { + if (vname == "_unknown") + return; + if (this.st.variants.length > 0) + { + const idxOfVar = this.st.variants.findIndex(e => e.name == vname); + this.variant = this.st.variants[idxOfVar]; + } + else + this.variant.name = vname; + const vModule = await import("@/variants/" + vname + ".js"); + window.V = vModule.VariantRules; }, startGame: function() { if (this.gameInProgress) -- 2.44.0