Add rectangle dimension helper
[brackets.git] / frontend / index.js
CommitLineData
98344134
JC
1const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms));
2
01952c94
JC
3/**
4 * Safari iOS pls
5 */
6const formSubmitPolyfill = (form, callback) => {
7 if (form.requestSubmit) {
8 form.requestSubmit();
9 } else {
10 callback();
11 }
12}
13
98344134
JC
14const createGenreListWithClickEvent = (genreList, genres, callback) => {
15 genreList.append(...genres.map((genre) => {
16 const name = genre["name"];
17 const li = document.createElement("li");
18 li.setAttribute("data-name", name);
19 li.addEventListener("click", callback);
20 li.appendChild(document.createTextNode(name));
21 return li;
22 }));
23}
24
25const relativeToCtx = (x1, x2, y1, y2, ctx) => {
26 const newX = x1 + x2;
27 const newY = y1 + y2;
28 ctx.lineTo(newX, newY);
29 return [newX, newY];
30}
31
1ffe1db0
JC
32/**
33 * Return (x,y) of canvas
34 */
35const getDimensions = (canvas) => [canvas.width, canvas.height];
36
37/**
38 * Return (x,y) midpoint of canvas
39 */
40const getCenter = (canvas) => getDimensions(canvas).map((dim) => dim / 2);
41
dce15b01
JC
42const getRectangleDimensionsUnbound = (canvas, xScale, yScale) => {
43 [width, height] = getDimensions(canvas);
44 return [width * xScale, height * yScale];
45}
46
47const getRectangleDimensions = (canvas) => getRectangleDimensionsUnbound(canvas, .5, .1);
48
1ffe1db0
JC
49/**
50 * Draw champion box and clear background.
51 */
52const drawWinner = (canvas) => {
98344134 53 const ctx = canvas.getContext("2d");
1ffe1db0
JC
54 const [width, height] = getDimensions(canvas);
55 const [mid_x, mid_y] = getCenter(canvas);
dce15b01 56 const [rect_width, rect_height] = getRectangleDimensions(canvas);
98344134
JC
57 ctx.strokeRect(mid_x - rect_width / 2, mid_y - rect_height / 2, rect_width, rect_height);
58 ctx.clearRect(mid_x - rect_width / 2, mid_y - rect_height / 2, rect_width, rect_height);
1ffe1db0
JC
59}
60
61/**
62 * Draws a path in context from the current location to a point xDist * left, yDist * up away from it.
63 * @param ctx RenderingContext
64 * @param x, y float current location
65 * @param x, y float distance away
66 * @param up, left (-1|1) directions
67 * @return [newNodeX, newNodeY]
68 */
69const drawBranchFrom = (ctx, x, y, xDist, yDist, left, up) => {
70 const newX = x + (xDist * left)
71 const newY = y + (yDist * up)
72 ctx.lineTo(x, newY);
73 ctx.lineTo(newX, newY);
74 return [newX, newY];
75}
76
77const drawArtistOnCtx = (ctx, artistName, x, y) => ctx.strokeText(artistName, x, y);
78
79/**
80 * Draws paths to the terminal nodes of a round
81 * @param x, y the point representation of the start of the branch
82 */
581e4442 83const drawMatchup = (canvas, x, y, iter, left, artist1, artist2) => {
1ffe1db0
JC
84 const ctx = canvas.getContext("2d");
85 const [width, height] = getDimensions(canvas);
86
87 const drawBranchUp = (xDist, yDist) => drawBranchFrom(ctx, x, y, xDist, yDist, left, 1);
88 const drawBranchDown = (xDist, yDist) => drawBranchFrom(ctx, x, y, xDist, yDist, left, -1);
89 const drawArtist = (artistName, x, y) => drawArtistOnCtx(ctx, artistName, x, y);
98344134 90
98344134 91 ctx.beginPath();
1ffe1db0
JC
92 ctx.moveTo(x, y);
93 drawArtist(
581e4442 94 artist1["name"],
1ffe1db0
JC
95 ...drawBranchUp(width / iter, height / iter)
96 );
97 ctx.moveTo(x, y);
98 drawArtist(
581e4442 99 artist2["name"],
1ffe1db0
JC
100 ...drawBranchDown(width / iter, height / iter)
101 );
98344134
JC
102 ctx.stroke();
103}
104
581e4442 105const drawBracket = (canvas, artists) => {
1ffe1db0
JC
106 drawWinner(canvas);
107 const [mid_x, mid_y] = getCenter(canvas);
dce15b01 108 const [rect_width, rect_height] = getRectangleDimensions(canvas);
581e4442
JC
109 const groups = 4;
110 const rounds = Math.log2(artists.length / groups);
111 for (let group = 1; group <= groups; group++) {
112 for (let round = 0; round < rounds; round++) {
113 const matchup = [artists.shift(), artists.pop()];
114 drawMatchup(canvas, mid_x, mid_y, 2 * round, Math.pow(-1, group), ...matchup);
115 }
116 }
1ffe1db0
JC
117}
118
98344134
JC
119window.onload = () => {
120 const lStorage = window.localStorage;
121 const genreList = document.getElementById("genre-list");
122 const genreInput = document.getElementById("genre-input");
123 const genreForm = document.getElementById("genre-form");
124 const canvas = document.getElementById("bracket");
125
01952c94
JC
126 const formSubmitAction = () => {
127 fetch(encodeURI(`http://localhost:8080/artist/genre?genre_name=${genreInput.value}`))
128 .then((response) => response.json())
129 .then((data) => drawBracket(canvas, data.slice(0, 33)));
130 }
131
98344134
JC
132 const createGenreList = (genreList, genres) => {
133 return createGenreListWithClickEvent(genreList, genres, (e) => {
134 genreInput.value = e.target.innerText;
01952c94 135 formSubmitPolyfill(genreForm, formSubmitAction);
98344134
JC
136 })
137 }
138 let genres = JSON.parse(lStorage.getItem("genres"))
139 if (genres === null) {
140 fetch("http://localhost:8080/genre")
141 .then((response) => response.text())
142 .then((text) => {
143 window.localStorage.setItem("genres", text);
144 genres = JSON.parse(text);
145 createGenreList(genreList, genres);
146 });
147 } else {
148 createGenreList(genreList, genres);
149 }
150
151 genreForm.addEventListener("submit", (e) => {
152 e.preventDefault();
01952c94 153 formSubmitAction()
98344134
JC
154 });
155
156 genreInput.addEventListener("input", (e) => {
157 const input = e.target;
6861bd5a 158 Array.from(genreList.children).forEach((item) => item.style.display= item.dataset.name.includes(input.value.toLowerCase()) ? "block" : "none");
98344134
JC
159 });
160 genreInput.addEventListener("focus", (e) => {
161 genreList.style.display = "block";
162 });
163 genreInput.addEventListener("blur", (e) => {
164 sleep(150).then(() => genreList.style.display = "none");
165 });
166
167
168 canvas.width = window.innerWidth;
169 canvas.height = window.innerHeight;
581e4442 170 drawBracket(canvas, []);
98344134
JC
171
172 const bgImg = new Image();
173 bgImg.onload = () => {
174 const ctx = canvas.getContext("2d");
175 //ctx.mozImageSmoothingEnabled = false;
176 //ctx.webkitImageSmoothingEnabled = false;
177 //ctx.msImageSmoothingEnabled = false;
178 //ctx.imageSmoothingEnabled = false;
179 ctx.drawImage(
180 bgImg,
181 0,
182 0,
183 (canvas.width / bgImg.width) * bgImg.width,
184 (canvas.height / bgImg.height) * bgImg.height
185 );
186 }
187
188 const upload = document.getElementById("image-upload");
189 upload.addEventListener("change", (e) => {
190 bgImg.src = URL.createObjectURL(e.target.files[0]);
191 });
192}