Small fixes
[vchess.git] / client / src / utils / printDiagram.js
1 import { ArrayFun } from "@/utils/array";
2 import { store } from "@/store";
3
4 // Turn (human) marks into coordinates
5 function getMarkArray(marks) {
6 if (!marks || marks == "-") return [];
7 let markArray = ArrayFun.init(V.size.x, V.size.y, false);
8 const squares = marks.split(",");
9 for (let i = 0; i < squares.length; i++) {
10 const coords = V.SquareToCoords(squares[i]);
11 markArray[coords.x][coords.y] = true;
12 }
13 return markArray;
14 }
15
16 // Turn (human) shadow indications into coordinates
17 function getShadowArray(shadow) {
18 if (!shadow || shadow == "-") return [];
19 let shadowArray = ArrayFun.init(V.size.x, V.size.y, false);
20 const squares = shadow.split(",");
21 for (let i = 0; i < squares.length; i++) {
22 const rownum = V.size.x - parseInt(squares[i], 10);
23 if (!isNaN(rownum)) {
24 // Shadow a full row
25 for (let i = 0; i < V.size.y; i++) shadowArray[rownum][i] = true;
26 continue;
27 }
28 if (squares[i].length == 1) {
29 // Shadow a full column
30 const colnum = V.ColumnToCoord(squares[i]);
31 for (let i = 0; i < V.size.x; i++) shadowArray[i][colnum] = true;
32 continue;
33 }
34 if (squares[i].indexOf("-") >= 0) {
35 // Shadow a range of squares, horizontally or vertically
36 const firstLastSq = squares[i].split("-");
37 const range = [
38 V.SquareToCoords(firstLastSq[0]),
39 V.SquareToCoords(firstLastSq[1])
40 ];
41 const step = [
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
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 ) {
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;
64 }
65
66 // args: object with position (mandatory), and
67 // orientation, marks, shadow (optional)
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?
72 export function getDiagram(args) {
73 // Obtain the array of pieces images names:
74 const board = V.GetBoard(args.position);
75 const orientation = args.orientation || "w";
76 const darkBottomRight = !!args.darkBottomRight;
77 const markArray = getMarkArray(args.marks);
78 const shadowArray = getShadowArray(args.shadow);
79 const vr = new V(); //just for pieces images paths
80 let boardDiv = "";
81 const [startX, startY, inc] =
82 orientation == "w" ? [0, 0, 1] : [V.size.x - 1, V.size.y - 1, -1];
83 for (let i = startX; i >= 0 && i < V.size.x; i += inc) {
84 boardDiv += "<div class='row";
85 if (i == startX && V.Monochrome) boardDiv += " border-top";
86 boardDiv += "'>";
87 for (let j = startY; j >= 0 && j < V.size.y; j += inc) {
88 boardDiv += "<div class='board board" + V.size.y + " ";
89 if (V.Monochrome) {
90 boardDiv += "monochrome " +
91 (V.Notoodark ? "middle-square" : "dark-square");
92 if (j == startY) boardDiv += " border-left";
93 }
94 else {
95 const oddity = (i + j) % 2;
96 if (
97 (oddity == 0 && !V.DarkBottomRight) ||
98 (oddity == 1 && V.DarkBottomRight)
99 ) {
100 boardDiv += "light-square";
101 }
102 else boardDiv += "dark-square";
103 }
104 boardDiv += " " + store.state.settings.bcolor;
105 if (shadowArray.length > 0 && shadowArray[i][j])
106 boardDiv += " in-shadow";
107 boardDiv += "'>";
108 if (board[i][j] != V.EMPTY) {
109 boardDiv +=
110 "<img " +
111 "src='/images/pieces/" +
112 vr.getPpath(board[i][j], null, null, orientation) +
113 V.IMAGE_EXTENSION + "' " +
114 "class='piece'/>";
115 }
116 if (markArray.length > 0 && markArray[i][j])
117 boardDiv += "<img src='/images/diag_mark.svg' class='mark-square'/>";
118 boardDiv += "</div>";
119 }
120 boardDiv += "</div>";
121 }
122 return boardDiv;
123 }
124
125 // Method to replace diagrams in loaded HTML
126 export function replaceByDiag(match, p1, p2) {
127 const diagParts = p2.split(" ");
128 return getDiagram({
129 position: diagParts[0],
130 marks: diagParts[1],
131 orientation: diagParts[2],
132 shadow: diagParts[3]
133 });
134 }