-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrandom-loona.html
363 lines (318 loc) · 15.8 KB
/
random-loona.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
<!DOCTYPE html>
<html lang="en">
<head>
<title>Random Loona picker</title>
<meta property="og:site_name" content="orbit-loona.github.io" />
<meta property="og:type" content="website" />
<meta property="og:title" content="random loona picker" />
<meta property="og:url" content="https://orbit-loona.github.io/random-loona.html" />
<meta property="og:description" content="pick a random loona song" />
<meta property="og:locale" content="en_US" />
<meta property="og:image" content="https://orbit-loona.github.io/bin/ot12-why.png" />
<meta property="og:image:width" content="133" />
<meta property="og:image:height" content="87" />
<meta property="og:image:alt" content="why (OT12 edition)" />
<meta name="twitter:image:src" content="https://orbit-loona.github.io/bin/ot12-why.png" />
<meta name="twitter:title" content="random loona picker" />
<meta name="twitter:description" content="pick a random loona song" />
<link rel="stylesheet" href="main.css"/>
<meta name="SKYPE_TOOLBAR" content="SKYPE_TOOLBAR_PARSER_COMPATIBLE">
<meta name="format-detection" content="telephone=no">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="author" content="An Orbit">
<meta charset="UTF-8">
<style>
.small {
font-size: 80%;
}
.collapsed {
display: none;
overflow: hidden;
}
#list {
animation: loonaot12 12s linear 0s infinite normal none;
}
</style>
</head>
<body>
<h2>An overengineered Loona permuter</h2>
<p>Why did I do this?</p>
<span>Amount (leave blank for original length):</span> <input id="amount"/>
<button id="do" onClick="buildList();">Generate list</button><br>
<button class="settingsToggle" onClick="toggleCollapse('checkboxDiv')">Show/Hide settings</button>
<div id="checkboxDiv" class="collapsed">
<span>Deduplicate list</span><input type="checkbox" checked id="deduplicateArray"/><br/>
<button class="setting contentSetting" onclick="fillCheckboxes()">Check all</button> <button class="setting contentSetting" onclick="clearCheckboxes()">Uncheck all</button><br/><br/>
<button class="setting contentSetting" onclick="setPredebut(true)">Check pre-debut</button> <button class="setting contentSetting" onclick="setPredebut(false)">Uncheck pre-debut</button><br/>
<button class="setting contentSetting" onclick="setSolos(true)">Check solos </button> <button class="setting contentSetting" onclick="setSolos(false)">Uncheck solos</button><br/>
<button class="setting contentSetting" onclick="setWholeUnitReleases(true)">Check whole-unit releases</button> <button class="setting contentSetting" onclick="setWholeUnitReleases(false)">Uncheck whole-unit releases</button><br/>
<button class="setting contentSetting" onclick="setPostdebut(true)">Check post-debut</button> <button class="setting contentSetting" onclick="setPostdebut(false)">Uncheck post-debut</button><br/>
<button class="setting contentSetting" onclick="setOSTs(true)">Check OSTs</button> <button class="setting contentSetting" onclick="setOSTs(false)">Uncheck OSTs</button><br/><br/>
<button class="setting contentSetting" onclick="setOneThird(true)">Check 1/3 </button> <button class="setting contentSetting" onclick="setOneThird(false)">Uncheck 1/3</button><br/>
<button class="setting contentSetting" onclick="setOEC(true)">Check OEC </button> <button class="setting contentSetting" onclick="setOEC(false)">Uncheck OEC</button><br/>
<button class="setting contentSetting" onclick="setYYXY(true)">Check yyxy </button> <button class="setting contentSetting" onclick="setYYXY(false)">Uncheck yyxy</button><br/>
<button class="setting contentSetting" onclick="setViRryVes(true)">Check ViRryVes </button> <button class="setting contentSetting" onclick="setViRryVes(false)">Uncheck ViRryVes</button><br/>
</div>
<p id="list"></p>
<p class="small">Most data from {<a class="third" href="https://kprofiles.com/loona-discography/">kprofiles.com</a> by <em class="yeojin">YoonTaeKyung</em> & <em class="yeojin">sorrysweetie</em>,
with thanks to <em class="yeojin">g.eorgiiee 127</em> and additional compilation from the commenter <em class="yeojin">Jaehyun</em>}<br/>
Array shuffler code <a class="circle" href="https://stackoverflow.com/a/12646864">by StackOverflow user Laurens Holst</a><br/>
Deduplication code <a class="youth" href="https://stackoverflow.com/a/9229821">by other StackOveflow users</a></p>
<script>
//Functions
//Random integer from 0 to n
//the code is pasted from another thing but we'll never use negatives here
function randomIntegerFromZeroToValue(value) {
var absoluteValuePlusOne = Math.abs(value) + 1;
if(value >= 0) { //Positive case
return Math.floor(Math.random() * absoluteValuePlusOne)
} else { //Negative case: flip sign
return 0 - Math.floor(Math.random() * absoluteValuePlusOne)
};
};
//Random thing from array
function randomChoice(array) {
if(array.length === 0) { throw new Error(`The array ${array} is empty`) };
var length = array.length;
var randomIndex = randomIntegerFromZeroToValue(length - 1);
return array[randomIndex];
};
//Shuffler by SO user Laurens Holst
//https://stackoverflow.com/a/12646864
function shuffleArray(array) {
for (let i = array.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[array[i], array[j]] = [array[j], array[i]];
}
}
function readTextboxAsInt(elementID,defaultValue=null) {
var textbox = document.getElementById(elementID);
if(textbox == null) {
throw new Error(`Element ${elementID} doesn't exist!`);
};
if(textbox.value == "") {
throw new Error(`Textbox ${elementID} is empty`);
};
//End empty check
value = parseInt(textbox.value);
//NaN check
if(isNaN(value)) {
throw new Error(`Value in ${elementID} is not a number`);
};
return value;
};
//Limit number to [min, max]
function bound(number,lowerBound,upperBound) {
return Math.min(upperBound,Math.max(lowerBound,number));
};
//Data
keyOrder = ["HeeJin", "HyunJin", "HaSeul", "YeoJin", "Love & Live", "ViVi", "Love & Evil", "Kim Lip", "JinSoul", "Choerry", "Mix & Match", "LOONATIC (English Version)", "Max & Match", "Yves", "The Carol 2.0", "Chuu", "Go Won", "Olivia Hye", "beauty&thebeat", "favOriTe", "[+ +]", "Orbit 1.0", "[X X]", "365", "#", "12:00", "&", "PTT (Paint The Town) - Japanese Ver.", "MAXIS BY RYAN JHUN PT.2", "HULA HOOP/StarSeed〜カクセイ〜", "Not Friends Special Edition", "Yummy-Yummy - YeoJin, Kim Lip, Choerry, Go Won, Cocomong", "Tracer (Original Television Soundtrack), Pt. 4 - HeeJin & JinSoul", "I'll Be Your Spring (orig. Airman x Godak ft. J_ust) - Olivia Hye", "Flip That", "Lullaby - B.I & Chuu", "Honestly - HeeJin", "LUMINOUS", "Daily JoJo webtoon OST Part.1", "Song for you project Vol.4 : Dear My Winter (with 롯백)", "Cookie Run: Ovenbreak OST Complete Collection"];
data = {
"HeeJin": ["ViViD", "ViViD (Acoustic Mix)"],
"HyunJin": ["Around You (다녀가요)", "I’ll Be There"],
"HaSeul": ["Let Me In (소년, 소녀)", "The Carol"],
"YeoJin": ["Kiss Later (키스는 다음에)", "My Sunday", "My Melody"],
"Love & Live": ["Into the New Heart", "지금, 좋아해 (Love & Live)", "You and Me Together", "Fairy Tale", "3월을 기다려 (Valentine Girl)"],
"ViVi": ["Everyday I Love You", "Everyday I Need You"],
"Love & Evil": ["Love & Evil", "알 수 없는 비밀 (Sonatine)", "비의 목소리 51Db (Rain 51Db)", "지금, 좋아해 (Love & Live)", "You and Me Together", "Fairy Tale", "3월을 기다려 (Valentine Girl)"],
"Kim Lip": ["Eclipse", "Twilight"],
"JinSoul": ["Singing In The Rain", "Love Letter"],
"Choerry": ["Love Cherry Motion", "Puzzle"],
"Mix & Match": ["ODD", "Girl Front", "LOONATIC", "Chaotic", "Starlight"],
"LOONATIC (English Version)": ["LOONATIC (English Version)"],
"Max & Match": ["ADD", "Sweet Crazy Love", "Uncover", "Girl Front", "LOONATIC", "Chaotic", "Starlight", "ODD Front", "LOONATIC (English Version)"],
"Yves": ["new", "D-1"],
"The Carol 2.0": ["The Carol 2.0"],
"Chuu": ["Heart Attack", "Girl’s Talk"],
"Go Won": ["One & Only", "See Saw"],
"Olivia Hye": ["Egoist", "Rosy"],
"beauty&thebeat": ["dal segno", "love4eva (feat. Grimes)", "frozen", "one way", "rendezvous 18.6y"],
"favOriTe": ["favOriTe"],
"[+ +]": ["+ +", "Hi High", "favOriTe", "열기", "Perfect Love", "Stylish"],
"Orbit 1.0": ["Love & Live (Remix)", "Egoist (English Rap)", "Hi High (Remix)"],
"[X X]": ["X X", "Butterfly", "위성 (Satellite)", "Curiosity", "색깔 (Colors)", "Where You At", "Stylish", "Perfect Love", "열기", "favOriTe", "Hi High", "+ +"],
"365": ["365"],
"#": ["#", "So What", "Number 1", "Oh (Yes I Am)", "Ding Dong Dong", "365"],
"12:00": ["12:00", "Why Not?", "목소리 (Voice)", "기억해 (Fall Again)", "Universe", "숨바꼭질 (Hide & Seek)", "OOPS!", "Star (목소리 English Ver.)"],
"&": ["&", "PTT (Paint The Town)", "WOW", "Be Honest", "Dance On My Own", "A Different Night", "U R"],
"PTT (Paint The Town) - Japanese Ver.": ["PTT (Paint The Town) - Japanese Ver."],
"MAXIS BY RYAN JHUN PT.2": ["Not Friends (Sung by HeeJin, Kim Lip, JinSoul, Yves) (Prod. RYAN JHUN)"],
"HULA HOOP/StarSeed〜カクセイ〜": ["HULA HOOP", "StarSeed 〜カクセイ〜", "PTT (Paint The Town) Japanese Ver.", "HULA HOOP City Pop Ver."],
"Not Friends Special Edition": ["Not Friends (ALAWN REMIX)", "Not Friends (TIDO REMIX)", "Not Friends (ORBIT REMIX)", "Not Friends ORIGINAL MIX", "Not Friends INSTRUMENTAL"],
"Yummy-Yummy - YeoJin, Kim Lip, Choerry, Go Won, Cocomong": ["Yummy-Yummy", "Yummy-Yummy - Inst."],
"Tracer (Original Television Soundtrack), Pt. 4 - HeeJin & JinSoul": ["Masquerade", "Masquerade - Inst."],
"I'll Be Your Spring (orig. Airman x Godak ft. J_ust) - Olivia Hye": ["I'll Be Your Spring"],
"Flip That": ["The Journey", "Flip That", "Need U", "POSE", "Pale Blue Dot", "Playback"],
"Lullaby - B.I & Chuu": ["Lullaby"],
"Honestly - HeeJin": ["Honestly", "Honestly - Instrumental"],
"LUMINOUS": ["LUMINOUS", "SICK LOVE", "Hi High (Japanese Ver.)"],
"Daily JoJo webtoon OST Part.1": ["Brunch"],
"Song for you project Vol.4 : Dear My Winter (with 롯백)": ["Dear My Winter"],
"Cookie Run: Ovenbreak OST Complete Collection": ["My Favorite Road (오늘도 나는 달린다)", "My Favorite Road (Inst.)", "My Favorite Road (Marching Band Ver.)", "My Favorite Road (Marching Band Ver.) (Inst.)"]
};
songs = [];
//Code
var predebutRange = [1,19];
var postdebutRange = [20,31];
var postdebutExclaves = [35,38];
var ostRange = [32,41];
var thirdRanges = [[1,3],[5,7]];
var oecRange = [8,13];
var yyxyRange = [14,19];
var virryvesItems = [6,10,14,15];
var soloItems = [1,2,3,4,6,8,9,10,14,16,17,18];
var wholeUnitReleaseItems = [5,7,11,12,13,15,19];
var repackageItems = [7,12,13,23];
function setPredebut(boolean) {
var checks = document.querySelectorAll('input[type="checkbox"]')
for(i = predebutRange[0]; i <= predebutRange[1]; i++) {
checks[i].checked = boolean;
};
};
function setPostdebut(boolean) {
var checks = document.querySelectorAll('input[type="checkbox"]')
for(i = postdebutRange[0]; i <= postdebutRange[1]; i++) {
checks[i].checked = boolean;
};
for(j = 0; j < postdebutExclaves.length; j++) {
var index = postdebutExclaves[j];
checks[index].checked = boolean;
};
}
function setOSTs(boolean) {
var checks = document.querySelectorAll('input[type="checkbox"]')
for(i = ostRange[0]; i <= ostRange[1]; i++) {
if(postdebutExclaves.includes(i)) {
continue;
};
checks[i].checked = boolean;
};
}
function setOneThird(boolean) {
var checks = document.querySelectorAll('input[type="checkbox"]')
for(i = 0; i < thirdRanges.length; i++) {
for(j = thirdRanges[i][0]; j <= thirdRanges[i][1]; j++) {
checks[j].checked = boolean;
};
};
}
function setOEC(boolean) {
var checks = document.querySelectorAll('input[type="checkbox"]')
for(i = oecRange[0]; i <= oecRange[1]; i++) {
checks[i].checked = boolean;
};
}
function setYYXY(boolean) {
var checks = document.querySelectorAll('input[type="checkbox"]')
for(i = yyxyRange[0]; i <= yyxyRange[1]; i++) {
if(i == 15) { continue }; //skip setting carol 2
checks[i].checked = boolean;
};
}
function setViRryVes(boolean) {
var checks = document.querySelectorAll('input[type="checkbox"]')
for(i = 0; i < virryvesItems.length; i++) {
var index = virryvesItems[i];
checks[index].checked = boolean;
};
}
function setSolos(boolean) {
var checks = document.querySelectorAll('input[type="checkbox"]')
for(i = 0; i < soloItems.length; i++) {
var index = soloItems[i];
checks[index].checked = boolean;
};
}
function setWholeUnitReleases(boolean) {
var checks = document.querySelectorAll('input[type="checkbox"]')
for(i = 0; i < wholeUnitReleaseItems.length; i++) {
var index = wholeUnitReleaseItems[i];
checks[index].checked = boolean;
};
}
function setRepackages(boolean) {
var checks = document.querySelectorAll('input[type="checkbox"]')
for(i = 0; i < repackageItems.length; i++) {
var index = repackageItems[i];
checks[index].checked = boolean;
};
}
function clearCheckboxes() {
var checks = document.querySelectorAll('input[type="checkbox"]')
for(i = 1; i < checks.length; i++) { //skip dedupe box
checks[i].checked = false;
}
}
function fillCheckboxes() {
var checks = document.querySelectorAll('input[type="checkbox"]')
for(i = 1; i < checks.length; i++) {
checks[i].checked = true;
}
}
function generateCheckboxes() {
var checkboxDiv = document.getElementById("checkboxDiv");
for(i = 0; i < keyOrder.length; i++) {
//get name
var albumName = keyOrder[i];
//configure checkbox
var newLabel = document.createTextNode(albumName);
var newCheckbox = document.createElement("input");
newCheckbox.id = `checkbox-${albumName}`;
newCheckbox.type = "checkbox";
newCheckbox.checked = true;
//place checkbox
checkboxDiv.appendChild(newLabel);
checkboxDiv.appendChild(newCheckbox);
checkboxDiv.appendChild(document.createElement("br"));
};
};
function readCheckbox(elementID,defaultValue) {
theCheckbox = document.getElementById(elementID);
if(theCheckbox !== null) {
return theCheckbox.checked;
} else {
return defaultValue;
};
};
function generateArray() {
songs = []; //clear array
for(i = 0; i < keyOrder.length; i++) {
var albumName = keyOrder[i];
var songData = data[albumName];
var include = readCheckbox(`checkbox-${albumName}`,true);
if(include) { songs.push(...songData) };
};
}
function toggleCollapse(elementID) { //inspired by https://www.w3schools.com/howto/howto_js_collapsible.asp
var coll = document.getElementById(elementID);
coll.classList.toggle("collapsed");
};
function buildList() {
generateArray();
if(readCheckbox('deduplicateArray',true)) { songs = [...new Set(songs)] };
createList(songs);
};
window.onload = function() {
generateCheckboxes();
if(readCheckbox('deduplicateArray',true)) { songs = [...new Set(songs)] };
generateArray();
};
function createList(array) {
//console.log(array)
var length;
try {
length = readTextboxAsInt("amount");
} catch (error) {
//console.log(error);
length = array.length;
};
shuffleArray(array);
array.length = bound(length,1,array.length);
var HTML = array.join("<br/>");
var destination = document.getElementById("list");
destination.innerHTML = HTML;
}
</script>
</body>
<br/><br/><a href="index.html"><small>go to main page</small></a>
</html>