summaryrefslogtreecommitdiff
path: root/index.js
blob: 879e3e015aea98ca1291b87446a0e1eb243d52b3 (plain)
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
const wordElem = document.querySelector("#word");
const inputElem = document.querySelector("#input");
const candidateListElem = document.querySelector("#candidate-list");
const candidateContainerElem = document.querySelector("#candidate-container");
const reportElem = document.querySelector("#report")
const nextElem = document.querySelector("#next");
const hintElem = document.querySelector("#hint");
const showAnswerElem = document.querySelector("#show-answer");
const answerElem = document.querySelector("#answer");
const albumElem = document.querySelector("#album");
const trackElem = document.querySelector("#track");
const linesElem = document.querySelector("#lines");

let currentWord = {};
let hintsLeft = 2;
let songsPicked = 0;

function newWord() {
    if (WORDS.length == 0) {
        // what the hell
        // why would anyone click Next 1002 times
        wordElem.innerHTML = "There are no more words."
        return;
    }

    if (songsPicked && songsPicked % 50 == 0) {
        alert(`You have played this ${songsPicked} times. Consider taking a rest?`);
    }

    const idx = Math.floor(Math.random() * WORDS.length);
    currentWord = WORDS[idx];
    WORDS.splice(idx, 1); // remove word from WORDS so it will not show again

    for (let album in ALBUMS) {
        if (ALBUMS[album].tracks.includes(currentWord.track)) {
            currentWord.album = album;
        }
    }

    wordElem.innerHTML = currentWord.word;
    hintsLeft = 2;
    hintElem.innerHTML = "Hint (2)";

    // clean after the mess
    for (let elem of [inputElem, nextElem, hintElem, showAnswerElem]) {
        elem.disabled = false;
    }

    for (let elem of [candidateContainerElem, reportElem, answerElem]) {
        elem.hidden = true;
    }

    for (let elem of [candidateListElem, reportElem, albumElem, trackElem, linesElem]) {
        elem.innerHTML = "";
    }

    inputElem.focus();
}

function acronymOf(track) {
    // special case
    if (track.toLowerCase() === "heavydirtysoul") {
        return "hds";
    }

    let acronym = "";
    for (let word of track.split(" ")) {
        acronym += word[0].toLowerCase();
    }
    return acronym;
}

function makeCandidate(track, album) {
    /*
     * <tr class="candidate" onclick="pickSong()">
     *     <td><img class="album-cover" src="filepath"/></td>
     *     <td><span>Track Title</span></td>
     * </tr>
     */
    const candidate = document.createElement("tr");
    candidate.setAttribute("class", "candidate");
    candidate.addEventListener("click", pickSong);

    const albumCoverCell = document.createElement("td");
    const albumCover = document.createElement("img");
    albumCover.setAttribute("class", "album-cover");
    albumCover.setAttribute("src", album.cover);
    albumCoverCell.appendChild(albumCover);

    const trackTitleCell = document.createElement("td");
    const trackTitle = document.createElement("span");
    trackTitle.innerHTML = track;
    trackTitleCell.appendChild(trackTitle);

    candidate.appendChild(albumCoverCell);
    candidate.appendChild(trackTitleCell);
    return candidate;
}

inputElem.oninput = () => {
    // clear candidates
    candidateContainerElem.hidden = true;
    candidateListElem.innerHTML = "";
    const input = inputElem.value.toLowerCase();
    if (!input) { return; }

    let candidates = [];

    for (let albumTitle in ALBUMS) {
        album = ALBUMS[albumTitle];
        for (let track of album.tracks) {
            if (acronymOf(track).startsWith(input)) {
                candidates.unshift(makeCandidate(track, album));
            } else if (track.toLowerCase().startsWith(input)) {
                candidates.push(makeCandidate(track, album));
            }
        }
    }

    // display candidates if they exist and don't take forever to scroll
    if (candidates.length > 0 && candidates.length <= 5) {
        for (let candidate of candidates) {
            candidateListElem.appendChild(candidate);
        }
        candidateContainerElem.hidden = false;
    }
}

inputElem.onkeyup = (event) => {
    if (event.key == "Enter") {
        pickSong(); // no arguments passed, pick first option
    }
}

function pickSong(event) {
    const candidate = event ? event.currentTarget : candidateListElem.firstChild;
    const trackTitleElem = candidate.querySelector("span");
    if (trackTitleElem.innerText === currentWord.track) {
        // the guess is correct
        reportElem.innerHTML = "Correct!";
        reportElem.style.color = "#7faa55";
        for (let elem of [inputElem, hintElem, showAnswerElem]) {
            elem.disabled = true;
        }
        showAnswer();
        nextElem.focus();
    } else {
        if (hintsLeft > 0) {
            reportElem.innerHTML = "Sorry, not this song :) <br /> Try a hint?";
        } else {
            reportElem.innerHTML = "Not this one…";
        }
        reportElem.style.color = "#aa5555";
    }
    inputElem.value = "";
    reportElem.hidden = false;
    songsPicked++;
}

function hint() {
    if (hintsLeft == 0) { return; }

    answerElem.hidden = false;

    if (hintsLeft == 2) {
        // reveal album title
        albumElem.innerHTML = currentWord.album;
    } else if (hintsLeft == 1) {
        // reveal part of a line surrounding the word
        // thanks for the idea, u/Tarnoo
        const lines = currentWord.lines;
        const randLine = lines[Math.floor(Math.random() * lines.length)];
        const wordsInLine = randLine.split(" ");
        // normalize line and word, then locate word
        const normWordsInLine = randLine.toLowerCase().replace(/[,\.\"\?!]/g, "").split(" ");
        const wordIdx = normWordsInLine.indexOf(currentWord.word.toLowerCase());

        let hint = "";
        wordsInLine.forEach((word, idx) => {
            if (Math.abs(idx - wordIdx) <= 1) {
                hint += word;
            } else {
                hint += "_".repeat(word.length);
            }

            hint += " ";
        });

        linesElem.innerHTML = hint;
        hintElem.disabled = true;
    }

    hintsLeft--;
    hintElem.innerHTML = `Hint (${hintsLeft})`;
}

function showAnswer() {
    answerElem.hidden = false;
    albumElem.innerHTML = currentWord.album;
    trackElem.innerHTML = currentWord.track;
    linesElem.innerHTML = currentWord.lines.join("<br />");
    hintElem.disabled = true;
}

window.onload = newWord;
nextElem.onclick = newWord;
hintElem.onclick = hint;
showAnswerElem.onclick = showAnswer;