More intuitive variants-by-name page
[vchess.git] / client / src / utils / printDiagram.js
CommitLineData
d7083722 1import { ArrayFun } from "@/utils/array";
4f524197 2import { store } from "@/store";
d7083722
BA
3
4// Turn (human) marks into coordinates
6808d7a1
BA
5function getMarkArray(marks) {
6 if (!marks || marks == "-") return [];
dac39588
BA
7 let markArray = ArrayFun.init(V.size.x, V.size.y, false);
8 const squares = marks.split(",");
6808d7a1 9 for (let i = 0; i < squares.length; i++) {
dac39588
BA
10 const coords = V.SquareToCoords(squares[i]);
11 markArray[coords.x][coords.y] = true;
12 }
13 return markArray;
d7083722
BA
14}
15
16// Turn (human) shadow indications into coordinates
6808d7a1
BA
17function getShadowArray(shadow) {
18 if (!shadow || shadow == "-") return [];
dac39588
BA
19 let shadowArray = ArrayFun.init(V.size.x, V.size.y, false);
20 const squares = shadow.split(",");
6808d7a1 21 for (let i = 0; i < squares.length; i++) {
e50a8025 22 const rownum = V.size.x - parseInt(squares[i], 10);
6808d7a1 23 if (!isNaN(rownum)) {
dac39588 24 // Shadow a full row
6808d7a1 25 for (let i = 0; i < V.size.y; i++) shadowArray[rownum][i] = true;
dac39588
BA
26 continue;
27 }
6808d7a1 28 if (squares[i].length == 1) {
dac39588
BA
29 // Shadow a full column
30 const colnum = V.ColumnToCoord(squares[i]);
6808d7a1 31 for (let i = 0; i < V.size.x; i++) shadowArray[i][colnum] = true;
dac39588
BA
32 continue;
33 }
6808d7a1 34 if (squares[i].indexOf("-") >= 0) {
dac39588
BA
35 // Shadow a range of squares, horizontally or vertically
36 const firstLastSq = squares[i].split("-");
6808d7a1 37 const range = [
dac39588
BA
38 V.SquareToCoords(firstLastSq[0]),
39 V.SquareToCoords(firstLastSq[1])
40 ];
6808d7a1 41 const step = [
dac39588
BA
42 range[1].x == range[0].x
43 ? 0
44 : (range[1].x - range[0].x) / Math.abs(range[1].x - range[0].x),
45 range[1].y == range[0].y
46 ? 0
47 : (range[1].y - range[0].y) / Math.abs(range[1].y - range[0].y)
48 ];
49 // Convention: range always from smaller to larger number
6808d7a1
BA
50 for (
51 let x = range[0].x, y = range[0].y;
52 x <= range[1].x && y <= range[1].y;
53 x += step[0], y += step[1]
54 ) {
dac39588
BA
55 shadowArray[x][y] = true;
56 }
57 continue;
58 }
59 // Shadow just one square:
60 const coords = V.SquareToCoords(squares[i]);
61 shadowArray[coords.x][coords.y] = true;
62 }
63 return shadowArray;
d7083722
BA
64}
65
66// args: object with position (mandatory), and
67// orientation, marks, shadow (optional)
4f524197
BA
68// TODO: in time, find a strategy to draw middle lines (weiqi, xianqi...)
69// and maybe also some diagonals (fanorona...)
70// https://stackoverflow.com/questions/40697231/horizontal-line-in-the-middle-of-divs
71// + CSS rotate?
6808d7a1 72export function getDiagram(args) {
dac39588
BA
73 // Obtain the array of pieces images names:
74 const board = V.GetBoard(args.position);
75 const orientation = args.orientation || "w";
76 const markArray = getMarkArray(args.marks);
77 const shadowArray = getShadowArray(args.shadow);
241bf8f2 78 const vr = new V(); //just for pieces images paths
dac39588 79 let boardDiv = "";
6808d7a1
BA
80 const [startX, startY, inc] =
81 orientation == "w" ? [0, 0, 1] : [V.size.x - 1, V.size.y - 1, -1];
82 for (let i = startX; i >= 0 && i < V.size.x; i += inc) {
4f524197
BA
83 boardDiv += "<div class='row";
84 if (i == startX && V.Monochrome) boardDiv += " border-top";
85 boardDiv += "'>";
6808d7a1 86 for (let j = startY; j >= 0 && j < V.size.y; j += inc) {
4f524197
BA
87 boardDiv += "<div class='board board" + V.size.y + " ";
88 if (V.Monochrome) {
89 boardDiv += "monochrome " +
90 (V.Notoodark ? "middle-square" : "dark-square");
91 if (j == startY) boardDiv += " border-left";
92 }
157a72c8
BA
93 else {
94 const oddity = (i + j) % 2;
95 if (
96 (oddity == 0 && !V.DarkBottomRight) ||
97 (oddity == 1 && V.DarkBottomRight)
98 ) {
99 boardDiv += "light-square";
100 }
101 else boardDiv += "dark-square";
102 }
4f524197
BA
103 boardDiv += " " + store.state.settings.bcolor;
104 if (shadowArray.length > 0 && shadowArray[i][j])
105 boardDiv += " in-shadow";
106 boardDiv += "'>";
6808d7a1
BA
107 if (board[i][j] != V.EMPTY) {
108 boardDiv +=
109 "<img " +
110 "src='/images/pieces/" +
14edde72
BA
111 vr.getPpath(board[i][j], null, null, orientation) +
112 V.IMAGE_EXTENSION + "' " +
d7083722 113 "class='piece'/>";
dac39588
BA
114 }
115 if (markArray.length > 0 && markArray[i][j])
2f8dce6a 116 boardDiv += "<img src='/images/diag_mark.svg' class='mark-square'/>";
dac39588
BA
117 boardDiv += "</div>";
118 }
119 boardDiv += "</div>";
120 }
121 return boardDiv;
d7083722 122}
07052665
BA
123
124// Method to replace diagrams in loaded HTML
125export function replaceByDiag(match, p1, p2) {
126 const diagParts = p2.split(" ");
127 return getDiagram({
128 position: diagParts[0],
129 marks: diagParts[1],
130 orientation: diagParts[2],
131 shadow: diagParts[3]
132 });
133}