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