aboutsummaryrefslogtreecommitdiff
path: root/index.html
blob: 785667b8b26ca44d78758374347abe63c8f0c64c (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
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Name my Dragon - Home</title>
    <link rel="stylesheet" href="style.css">
</head>
<body>
    <center>
        <h1>Name my Dragon</h1>
        <audio id="audio-player" loop>
            <source src="audio/western-cover.m4a" type="audio/mp4">
            Enable audio on your browser to get the best experience.
        </audio>
        <div class="alert">
                Warning: The button below will play some sweet tunes! 
                Hit the "Stop music" button to stop it or just mute your device.
            <span class="closebtn" onclick="this.parentElement.style.display='none';">&times;</span>
        </div>
        <div class="container">
            <form id="nameForm" class="flex">
                <label style="color: black;" for="firstName">Enter your first name:</label>
                <input type="text" id="firstName" placeholder="bob" required>
                <button type="submit">Name my Dragon</button>
            </form>
            <div class="flex">
                <button id="stop-music" onclick="stopMusic();">Stop music</button>
            </div>
        </div>
        <p>And your Dragon is...</p>
        <div id="results" class="container">
            <div id="dragonName" class="flex flex1"></div>
            <div id="dragonStats" class="flex flex2"></div>
            <div id="lasso" class="flex"></div>
        </div>
        <div id="alternatives"></div>
        <div>
            <p>See a comparison of all the dragons here:</p>
            <img src="images/dragon-sizes.png" width="50%" alt="Comparison chart for all the dragons">
        </div>
        <a href="about.html">How it works</a>
    </center>

    <script type="text/javascript" src="dragons.js"></script>
    <script>
        const dragonNames = dragons.map(d => d.name);
        console.log(dragonNames);

        function levenshteinDistance(a, b) {
            if (a.length === 0) return b.length;
            if (b.length === 0) return a.length;

            const matrix = [];

            for (let i = 0; i <= b.length; i++) {
                matrix[i] = [i];
            }

            for (let j = 0; j <= a.length; j++) {
                matrix[0][j] = j;
            }

            for (let i = 1; i <= b.length; i++) {
                for (let j = 1; j <= a.length; j++) {
                    if (b.charAt(i - 1) === a.charAt(j - 1)) {
                        matrix[i][j] = matrix[i - 1][j - 1];
                    } else {
                        matrix[i][j] = Math.min(
                            matrix[i - 1][j - 1] + 1,
                            matrix[i][j - 1] + 1,
                            matrix[i - 1][j] + 1
                        );
                    }
                }
            }

            return matrix[b.length][a.length];
        }

        function cosineSimilarity(a, b) {
            const aSet = new Set(a.toLowerCase());
            const bSet = new Set(b.toLowerCase());
            const intersection = new Set([...aSet].filter(x => bSet.has(x)));
            return intersection.size / Math.sqrt(aSet.size * bSet.size);
        }

        function jaccardSimilarity(a, b) {
            const aSet = new Set(a.toLowerCase());
            const bSet = new Set(b.toLowerCase());
            const intersection = new Set([...aSet].filter(x => bSet.has(x)));
            const union = new Set([...aSet, ...bSet]);
            return intersection.size / union.size;
        }

        function calculateSimilarities(name) {
            const results = dragonNames.map(n => ({
                name: n,
                levenshtein: 1 - levenshteinDistance(name, n) / Math.max(name.length, n.length),
                cosine: cosineSimilarity(name, n),
                jaccard: jaccardSimilarity(name, n)
            }));

            return {
                levenshtein: results.sort((a, b) => b.levenshtein - a.levenshtein).slice(0, 5),
                cosine: results.sort((a, b) => b.cosine - a.cosine).slice(0, 5),
                jaccard: results.sort((a, b) => b.jaccard - a.jaccard).slice(0, 5)
            };
        }

        function getDragonObject(name) {
            return dragons.filter(dragon => (dragon.name === name))[0];
        }

        function stopMusic() {
            document.getElementById('audio-player').pause();
        }

        document.getElementById('nameForm').addEventListener('submit', function(e) {
            e.preventDefault();
            const name = document.getElementById('firstName').value;
            const similarities = calculateSimilarities(name);
            console.log(similarities);

            const topChoice = similarities.cosine[0].name;
            const topChoiceDragon = getDragonObject(topChoice);
            const possibleAlternatives = new Set(
                Array.prototype.concat(
                    similarities.jaccard.slice(0, 2).map(n => n.name),
                        similarities.levenshtein.slice(0, 2).map(n => n.name)
                )
            ).difference(
                new Set([topChoice])
            );

            document.getElementById('dragonName').innerHTML = 
                `<p><span style="font-size:xx-large;" class="legible">${topChoice}</span></p>`;
            document.getElementById('dragonName').style.backgroundColor = topChoiceDragon.primaryColor;

            document.getElementById('dragonStats').innerHTML = `
                <p>${topChoiceDragon.description}</p>
                <p>
                Size: ${topChoiceDragon.size}<br>
                Age: ${topChoiceDragon.age}<br>
                Abilities: ${topChoiceDragon.notableAbilities}<br>
                </p>`;
            document.getElementById('dragonStats').style.backgroundColor = topChoiceDragon.secondaryColor;

            document.getElementById('lasso').innerHTML = `
                <img src="images/hat-texas.gif" width="100%" alt="Cowboy lasso gif">`;
            document.getElementById('lasso').style.backgroundColor = topChoiceDragon.primaryColor;

            document.getElementById('alternatives').innerHTML = 
                `<p>Possible alternatives: <strong>${[...possibleAlternatives].join(', ')}</strong></p>`;

            document.getElementById('audio-player').play();
        });
    </script>
</body>
</html>