-
Notifications
You must be signed in to change notification settings - Fork 209
/
ListeningChallenge.svelte
130 lines (117 loc) · 3.04 KB
/
ListeningChallenge.svelte
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
<script>
import { onMount } from "svelte"
import hotkeys from "hotkeys-js"
import levenshtein from "js-levenshtein"
import ChallengePanel from "./ChallengePanel"
import Icon from "lluis/Icon"
import InputFieldWithVirtualKeyboard from "./InputFieldWithVirtualKeyboard"
import playVoice from "../media/voice"
import Button from "lluis/Button"
import Column from "lluis/Column"
import Columns from "lluis/Columns"
export let challenge
export let registerResult
export let resolveChallenge
export let languageCode
export let specialCharacters
export let skipChallenge
let answer = ""
let submitted = false
let correct = null
let spellingSuggestion = ""
$: submitChallenge = () => {
if (!answer) return
if (submitted) return
const form = challenge.answer
correct = false
if (
levenshtein(
answer
.toLowerCase()
.replace(/^\s+|\s+$/g, "")
.replace(/\s+/g, " "),
form.toLowerCase()
) <= 1
) {
correct = true
spellingSuggestion =
form
.replace(/^\s+|\s+$/g, "")
.replace(/\s+/g, " ")
.toLowerCase() === answer.toLowerCase()
? ""
: `You made a small error. Correct spelling: ${form}`
}
registerResult(correct)
submitted = true
}
$: finishChallenge = () => {
answer = null
submitted = false
resolveChallenge()
}
const playChallengeVoice = () => playVoice(challenge.audio)
onMount(() => {
playChallengeVoice()
hotkeys.unbind("enter")
hotkeys("enter", () => {
if (submitted) {
finishChallenge()
} else {
submitChallenge()
}
})
})
</script>
<form on:submit|preventDefault="{submitChallenge}">
<div class="section">
<p class="is-size-1 is-size-2-tablet is-size-4-mobile has-text-centered">
Type what you hear
</p>
</div>
<Columns>
<Column size="1">
<Button size="large" primary on:click="{playChallengeVoice}">
<Icon icon="volume-up" />
</Button>
</Column>
<Column>
<InputFieldWithVirtualKeyboard
{specialCharacters}
{languageCode}
disabled="{submitted}"
bind:value="{answer}" />
</Column>
</Columns>
{#if answer && !submitted}
<ChallengePanel
message=""
buttonText="Submit"
submit
skipAction="{skipChallenge}" />
{/if}
{#if answer === '' && !submitted}
<ChallengePanel
message="{null}"
buttonText="{null}"
skipAction="{skipChallenge}" />
{/if}
{#if submitted}
{#if !correct}
<ChallengePanel
message="Incorrect solution!"
messageDetail="{`Correct answer: ${challenge.answer}`}"
buttonText="Continue"
incorrect
buttonAction="{finishChallenge}" />
{/if}
{#if correct}
<ChallengePanel
message="Correct solution!"
messageDetail="{spellingSuggestion || `Meaning: "${challenge.meaning}"`}"
buttonText="Continue"
correct
buttonAction="{finishChallenge}" />
{/if}
{/if}
</form>