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