1const ANIMATION_DELAY_MS = 250;
2const calcBtn = document.querySelector("#calcBtn");
3const tooltip = document.getElementById("tooltip");
4const reloadBtn = document.getElementById("reload");
5const p1Node = document.querySelector("#p1");
6const p2Node = document.querySelector("#p2");
7
8const QUOTES = {
9 F: [
10 "Oof! They friendzoned you faster than Wi-Fi connects.",
11 "You're giving off strong 'let's grab coffee... as friends' energy.",
12 "They said you're like a bruhhh... awkward.",
13 "Congrats! You're now the president of the Friendzone Association.",
14 "Even Cupid said, 'Nah, y'all better off as besties.'",
15 ],
16
17 L: [
18 "Look at you, catching feelings like it's a sport.",
19 "Someone's heart just got stolen — and it's definitely not theirs.",
20 "They're blushing. You're dangerous.",
21 "Cupid called. He wants to put you on speed dial.",
22 "If this was a K-drama, y'all just hit Episode 12: The Confession.",
23 ],
24
25 A: [
26 "They don't love you… but they definitely wouldn't swipe left.",
27 "You're not the one… but you're definitely the one before the one.",
28 "You're in their 'late night thoughts' playlist.",
29 "They flirt with you like it's their part-time job.",
30 "You're like that mystery snack they crave but won't admit to.",
31 ],
32
33 M: [
34 "Get the wedding playlist ready — it's happening!",
35 "You've unlocked the 'Eternal Drama Partner' level.",
36 "They're picturing you in matching pajamas already.",
37 "It's giving 'Netflix, kids, and a shared mortgage' vibes.",
38 "Hope you like joint bank accounts — you're headed for 'I Do'.",
39 ],
40
41 E: [
42 "Oof — they're plotting your downfall like it's a hobby.",
43 "They love to hate you. Emphasis on both.",
44 "You two have that enemies-to-lovers arc… just missing the lovers part.",
45 "They'd unplug your phone charger just out of spite.",
46 "It's less 'spark' and more 'burn.'",
47 ],
48
49 S: [
50 "You've unlocked the 'ew, that's like my sibling' zone.",
51 "They said you're like family… which is code for 'nope'.",
52 "Better start calling each other 'bro' — it's over.",
53 "You're so deep in the sibling zone, even ancestry.com is confused.",
54 "You're one DNA test away from this being weird.",
55 ],
56 SAME_NAME_QUOTES: [
57 "Dating yourself? Love the confidence, narcissist.",
58 "Well well well, someone clearly thinks they're their own soulmate.",
59 "You're so single, even your name is matching.",
60 "Mirror, mirror on the wall… you just fell for yourself after all.",
61 "Self-love is great, but this might be a *little* too literal.",
62 ],
63 ZERO_MAGIC_QUOTES: [
64 "Whoa. You broke the game. That's how rare your connection is.",
65 "There's no number for this vibe — you two are beyond calculation.",
66 "Some things can't be measured. Like how special you are.",
67 "Magic number? Nah, you *are* the magic.",
68 "When the universe glitches just for you — yeah, it's giving soulmate energy.",
69 ],
70};
71
72function clearName() {
73 p1Node.value = "";
74 p2Node.value = "";
75}
76
77async function playFlames(magicNumber) {
78 let FLAMES = ["F", "L", "A", "M", "E", "S"];
79 let current = 0;
80
81 let flamesContainer = Array.from(document.querySelectorAll(".flame-letter"));
82 while (FLAMES.length > 1) {
83 let count = 1;
84
85 while (count < magicNumber) {
86 flamesContainer[current].classList.add("highlight");
87 await sleep(ANIMATION_DELAY_MS);
88 flamesContainer[current].classList.remove("highlight");
89
90 current = (current + 1) % FLAMES.length;
91 count++;
92 }
93
94 flamesContainer[current].classList.add("highlight");
95 await sleep(ANIMATION_DELAY_MS);
96 flamesContainer[current].classList.remove("highlight");
97
98 console.log(`Removing "${FLAMES[current]}" at position ${current}`);
99 flamesContainer[current].classList.add("removed");
100
101 FLAMES.splice(current, 1);
102 flamesContainer.splice(current, 1);
103
104 if (current >= FLAMES.length) {
105 current = 0;
106 }
107
108 await sleep(ANIMATION_DELAY_MS);
109 }
110
111 flamesContainer[0].classList.add("highlight");
112 return FLAMES[0];
113}
114
115async function calculateFlames() {
116 const p1 = p1Node.value.toUpperCase().trim();
117 const p2 = p2Node.value.toUpperCase().trim();
118
119 if (p1 == "" || p2 == "") {
120 return;
121 }
122
123 calcBtn.disabled = true;
124 p1Node.disabled = true;
125 p2Node.disabled = true;
126 reloadBtn.classList.remove("hidden");
127
128 if (p1 == p2) {
129 tooltip.innerHTML = QUOTES["SAME_NAME_QUOTES"][Math.floor(Math.random() * 5)];
130 return;
131 }
132
133 let p1HashMap = {};
134 let p2HashMap = {};
135 let finalMap = {};
136 let magicNumber = 0;
137
138 for (let ch of p1) p1HashMap[ch] = (p1HashMap[ch] || 0) + 1;
139 for (let ch of p2) p2HashMap[ch] = (p2HashMap[ch] || 0) + 1;
140
141 let allKeys = new Set([...Object.keys(p1HashMap), ...Object.keys(p2HashMap)]);
142
143 for (let key of allKeys) {
144 const count1 = p1HashMap[key] || 0;
145 const count2 = p2HashMap[key] || 0;
146 finalMap[key] = Math.abs(count1 - count2);
147 }
148
149 for (let k in finalMap) {
150 magicNumber += finalMap[k];
151 }
152
153 if (magicNumber == 0) {
154 tooltip.innerHTML = QUOTES["ZERO_MAGIC_QUOTES"][Math.floor(Math.random() * 5)];
155 return;
156 }
157
158 const finalLetter = await playFlames(magicNumber);
159
160 let quote = QUOTES[finalLetter][Math.floor(Math.random() * 5)];
161 tooltip.innerHTML = quote;
162}
163
164calcBtn.onclick = calculateFlames;