Remove commented out image smoothing code
[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"];
74f7e922
JC
17 const option = document.createElement("option");
18 option.setAttribute("data-name", name);
19 option.addEventListener("click", callback);
20 option.appendChild(document.createTextNode(name));
21 return option;
98344134
JC
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);
692ff642 74 ctx.stroke();
1ffe1db0
JC
75 return [newX, newY];
76}
77
692ff642 78const drawArtistOnCtx = (ctx, artistName, x, y) => {
59a851b3 79 ctx.font = "20px sans serif";
692ff642
JC
80 ctx.strokeText(artistName, x, y);
81}
1ffe1db0
JC
82
83/**
84 * Draws paths to the terminal nodes of a round
85 * @param x, y the point representation of the start of the branch
692ff642 86 * @param baseCallback a callback that needs the terminal x,y context
1ffe1db0 87 */
692ff642
JC
88const drawMatchup = (canvas, x, y, iter, maxIter, left, artists, baseCallback) => {
89 if (iter === maxIter) {
90 return baseCallback(x, y);
91 }
1ffe1db0 92 const ctx = canvas.getContext("2d");
0230aa11 93 ctx.direction = left === -1 ? "ltr" : "rtl";
1ffe1db0
JC
94 const [width, height] = getDimensions(canvas);
95
692ff642
JC
96 const drawBranchUp = (xDist, yDist) => drawBranchFrom(ctx, x, y, xDist, yDist, left, -1);
97 const drawBranchDown = (xDist, yDist) => drawBranchFrom(ctx, x, y, xDist, yDist, left, 1);
1ffe1db0 98 const drawArtist = (artistName, x, y) => drawArtistOnCtx(ctx, artistName, x, y);
4b4b1eff
JC
99 const drawArtist1 = (x, y) => {
100 const artist1 = artists.shift();
101 if (!artist1) {
102 return;
103 }
104 drawArtist(artist1["name"], x, y);
105 }
106
107 const drawArtist2 = (x, y) => {
108 const artist2 = artists.pop();
109 if (!artist2) {
110 return;
111 }
112 drawArtist(artist2["name"], x, y);
113 }
98344134 114
98344134 115 ctx.beginPath();
1ffe1db0 116 ctx.moveTo(x, y);
692ff642
JC
117 const branchDistances = [width / (5 * (iter + 1)), height / (9 * (iter + 1))];
118 drawMatchup(
119 canvas,
120 ...drawBranchUp(...branchDistances),
121 iter + 1,
122 maxIter,
123 left,
124 artists,
125 drawArtist1,
1ffe1db0 126 );
692ff642 127
1ffe1db0 128 ctx.moveTo(x, y);
692ff642
JC
129 drawMatchup(
130 canvas,
131 ...drawBranchDown(...branchDistances),
132 iter + 1,
133 maxIter,
134 left,
135 artists,
136 drawArtist2,
1ffe1db0 137 );
98344134
JC
138}
139
a6490680
JC
140const drawBracket = (canvas, artists, genre) => {
141 const context = canvas.getContext("2d");
142 context.clearRect(0, 0, canvas.width, canvas.height);
1ffe1db0
JC
143 drawWinner(canvas);
144 const [mid_x, mid_y] = getCenter(canvas);
a6490680 145 context.font = '28px sans serif'
f512a462
JC
146 context.textAlign = "center";
147 context.strokeText(genre.toUpperCase(), mid_x, 40);
148 context.textAlign = "start";
dce15b01 149 const [rect_width, rect_height] = getRectangleDimensions(canvas);
581e4442 150 const groups = 4;
e4763c42
JC
151 const rounds = Math.max(
152 Math.floor(Math.log2(artists.length / groups)),
153 1
154 );
581e4442 155 for (let group = 1; group <= groups; group++) {
4b4b1eff
JC
156 if (artists.length === 0) {
157 break;
158 }
692ff642
JC
159 drawMatchup(
160 canvas,
59a851b3
JC
161 mid_x + (Math.pow(-1, group) * (rect_width / 6)),
162 mid_y + (Math.pow(-1, Math.floor(group / 2)) * (rect_height * 2.5)),
692ff642
JC
163 0,
164 rounds,
165 Math.pow(-1, group),
166 artists,
167 (x, y) => console.log("hello")
168 );
581e4442 169 }
1ffe1db0
JC
170}
171
98344134
JC
172window.onload = () => {
173 const lStorage = window.localStorage;
174 const genreList = document.getElementById("genre-list");
175 const genreInput = document.getElementById("genre-input");
176 const genreForm = document.getElementById("genre-form");
177 const canvas = document.getElementById("bracket");
178
01952c94 179 const formSubmitAction = () => {
1520458e 180 fetch(encodeURI(`http://api.brackets.jacobcasper.com/artist/genre?genre_name=${genreInput.value}`))
01952c94 181 .then((response) => response.json())
a6490680 182 .then((data) => drawBracket(canvas, data.slice(0, 33), genreInput.value));
01952c94
JC
183 }
184
74f7e922
JC
185 const genreFormSubmitPolyfill = () => formSubmitPolyfill(genreList, formSubmitAction)
186
98344134
JC
187 const createGenreList = (genreList, genres) => {
188 return createGenreListWithClickEvent(genreList, genres, (e) => {
189 genreInput.value = e.target.innerText;
74f7e922 190 genreFormSubmitPolyfill()
98344134
JC
191 })
192 }
193 let genres = JSON.parse(lStorage.getItem("genres"))
194 if (genres === null) {
1520458e 195 fetch("http://api.brackets.jacobcasper.com/genre")
98344134
JC
196 .then((response) => response.text())
197 .then((text) => {
198 window.localStorage.setItem("genres", text);
199 genres = JSON.parse(text);
200 createGenreList(genreList, genres);
201 });
202 } else {
203 createGenreList(genreList, genres);
204 }
205
206 genreForm.addEventListener("submit", (e) => {
207 e.preventDefault();
01952c94 208 formSubmitAction()
98344134
JC
209 });
210
74f7e922
JC
211 genreInput.addEventListener("change", (e) => {
212 genreFormSubmitPolyfill()
98344134
JC
213 });
214
215
216 canvas.width = window.innerWidth;
217 canvas.height = window.innerHeight;
4b4b1eff 218 drawBracket(canvas, [], "");
98344134
JC
219
220 const bgImg = new Image();
221 bgImg.onload = () => {
222 const ctx = canvas.getContext("2d");
98344134
JC
223 ctx.drawImage(
224 bgImg,
225 0,
226 0,
227 (canvas.width / bgImg.width) * bgImg.width,
228 (canvas.height / bgImg.height) * bgImg.height
229 );
230 }
231
232 const upload = document.getElementById("image-upload");
233 upload.addEventListener("change", (e) => {
234 bgImg.src = URL.createObjectURL(e.target.files[0]);
235 });
236}