1 const sleep
= (ms
) => new Promise(resolve
=> setTimeout(resolve
, ms
));
6 const formSubmitPolyfill
= (form
, callback
) => {
7 if (form
.requestSubmit
) {
14 const 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
));
25 const relativeToCtx
= (x1
, x2
, y1
, y2
, ctx
) => {
28 ctx
.lineTo(newX
, newY
);
33 * Return (x,y) of canvas
35 const getDimensions
= (canvas
) => [canvas
.width
, canvas
.height
];
38 * Return (x,y) midpoint of canvas
40 const getCenter
= (canvas
) => getDimensions(canvas
).map((dim
) => dim
/ 2);
42 const getRectangleDimensionsUnbound
= (canvas
, xScale
, yScale
) => {
43 [width
, height
] = getDimensions(canvas
);
44 return [width
* xScale
, height
* yScale
];
47 const getRectangleDimensions
= (canvas
) => getRectangleDimensionsUnbound(canvas
, .5, .1);
50 * Draw champion box and clear background.
52 const drawWinner
= (canvas
) => {
53 const ctx
= canvas
.getContext("2d");
54 const [width
, height
] = getDimensions(canvas
);
55 const [mid_x
, mid_y
] = getCenter(canvas
);
56 const [rect_width
, rect_height
] = getRectangleDimensions(canvas
);
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
);
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]
69 const drawBranchFrom
= (ctx
, x
, y
, xDist
, yDist
, left
, up
) => {
70 const newX
= x
+ (xDist
* left
)
71 const newY
= y
+ (yDist
* up
)
73 ctx
.lineTo(newX
, newY
);
78 const drawArtistOnCtx
= (ctx
, artistName
, x
, y
) => {
79 ctx
.font
= "1em sans serif";
80 ctx
.direction
= "ltr";
81 ctx
.strokeText(artistName
, x
, y
);
85 * Draws paths to the terminal nodes of a round
86 * @param x, y the point representation of the start of the branch
87 * @param baseCallback a callback that needs the terminal x,y context
89 const drawMatchup
= (canvas
, x
, y
, iter
, maxIter
, left
, artists
, baseCallback
) => {
90 if (iter
=== maxIter
) {
91 return baseCallback(x
, y
);
93 const ctx
= canvas
.getContext("2d");
94 const [width
, height
] = getDimensions(canvas
);
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);
98 const drawArtist
= (artistName
, x
, y
) => drawArtistOnCtx(ctx
, artistName
, x
, y
);
99 const drawArtist1
= (x
, y
) => drawArtist(artists
.shift()["name"], x
, y
);
100 const drawArtist2
= (x
, y
) => drawArtist(artists
.pop()["name"], x
, y
);
104 const branchDistances
= [width
/ (5 * (iter
+ 1)), height
/ (9 * (iter
+ 1))];
107 ...drawBranchUp(...branchDistances
),
118 ...drawBranchDown(...branchDistances
),
128 const drawBracket
= (canvas
, artists
) => {
130 const [mid_x
, mid_y
] = getCenter(canvas
);
131 const [rect_width
, rect_height
] = getRectangleDimensions(canvas
);
133 const rounds
= Math
.floor(Math
.log2(artists
.length
/ groups
));
134 for (let group
= 1; group
<= groups
; group
++) {
137 mid_x
+ (Math
.pow(-1, group
) * (rect_width
/ 4)),
138 mid_y
+ (Math
.pow(-1, Math
.floor(group
/ 2)) * (rect_height
* 2)),
143 (x
, y
) => console
.log("hello")
148 window
.onload
= () => {
149 const lStorage
= window
.localStorage
;
150 const genreList
= document
.getElementById("genre-list");
151 const genreInput
= document
.getElementById("genre-input");
152 const genreForm
= document
.getElementById("genre-form");
153 const canvas
= document
.getElementById("bracket");
155 const formSubmitAction
= () => {
156 fetch(encodeURI(`http://localhost:8080/artist/genre?genre_name=${genreInput.value}`))
157 .then((response
) => response
.json())
158 .then((data
) => drawBracket(canvas
, data
.slice(0, 33)));
161 const createGenreList
= (genreList
, genres
) => {
162 return createGenreListWithClickEvent(genreList
, genres
, (e
) => {
163 genreInput
.value
= e
.target
.innerText
;
164 formSubmitPolyfill(genreForm
, formSubmitAction
);
167 let genres
= JSON
.parse(lStorage
.getItem("genres"))
168 if (genres
=== null) {
169 fetch("http://localhost:8080/genre")
170 .then((response
) => response
.text())
172 window
.localStorage
.setItem("genres", text
);
173 genres
= JSON
.parse(text
);
174 createGenreList(genreList
, genres
);
177 createGenreList(genreList
, genres
);
180 genreForm
.addEventListener("submit", (e
) => {
185 genreInput
.addEventListener("input", (e
) => {
186 const input
= e
.target
;
187 Array
.from(genreList
.children
).forEach((item
) => item
.style
.display
= item
.dataset
.name
.includes(input
.value
.toLowerCase()) ? "block" : "none");
189 genreInput
.addEventListener("focus", (e
) => {
190 genreList
.style
.display
= "block";
192 genreInput
.addEventListener("blur", (e
) => {
193 sleep(150).then(() => genreList
.style
.display
= "none");
197 canvas
.width
= window
.innerWidth
;
198 canvas
.height
= window
.innerHeight
;
199 drawBracket(canvas
, ['dummy', 'dummy', 'dum' ,'dumhy']);
201 const bgImg
= new Image();
202 bgImg
.onload
= () => {
203 const ctx
= canvas
.getContext("2d");
204 //ctx.mozImageSmoothingEnabled = false;
205 //ctx.webkitImageSmoothingEnabled = false;
206 //ctx.msImageSmoothingEnabled = false;
207 //ctx.imageSmoothingEnabled = false;
212 (canvas
.width
/ bgImg
.width
) * bgImg
.width
,
213 (canvas
.height
/ bgImg
.height
) * bgImg
.height
217 const upload
= document
.getElementById("image-upload");
218 upload
.addEventListener("change", (e
) => {
219 bgImg
.src
= URL
.createObjectURL(e
.target
.files
[0]);