Skip to content

Commit e46ba0a

Browse files
committed
feat: Added first version of learn site
1 parent c8a0cf1 commit e46ba0a

3 files changed

Lines changed: 196 additions & 0 deletions

File tree

app/index.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ export default function HomeScreen() {
1515
<TouchableOpacity style={styles.homeButton} onPress={() => router.push('/chat')}>
1616
<Text style={styles.homeButtonText}>Chat</Text>
1717
</TouchableOpacity>
18+
<TouchableOpacity style={styles.homeButton} onPress={() => router.push('/learn')}>
19+
<Text style={styles.homeButtonText}>Learn</Text>
20+
</TouchableOpacity>
1821
</View>
1922
</View>
2023
);

app/learn.js

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
import { KeyboardAvoidingView, View, Text, TextInput, TouchableOpacity, StyleSheet, Platform} from 'react-native';
2+
import { useState, useEffect } from 'react';
3+
import { useAudioPlayer } from "expo-audio";
4+
import BackArrowComponent from '../components/BackArrowComponent';
5+
import { textToMorse, encodeMorse } from '../morse_util';
6+
import Fontisto from '@expo/vector-icons/Fontisto';
7+
import AntDesign from '@expo/vector-icons/AntDesign';
8+
import learnWords from '../assets/data/learnwords.json';
9+
10+
export default function learn(){
11+
"use strict";
12+
13+
const [words, setWords] = useState(null);
14+
const [morse, setMorse] = useState("");
15+
const [textInput, setTextInput] = useState("");
16+
const [isCorrect, setIsCorrect] = useState(false);
17+
const player = useAudioPlayer();
18+
19+
useEffect (() => {
20+
initWords();
21+
}, []);
22+
23+
/**
24+
* Gets called after initialisation of the learning words, so that a first word is selected.
25+
*/
26+
useEffect (() => {
27+
if (words != null) {
28+
getNextMorse();
29+
}
30+
}, [words]);
31+
32+
/**
33+
* Gets called everytime the user enters a new letter, checks whether the input is equal to the given morse code.
34+
*/
35+
useEffect (() => {
36+
setIsCorrect(morse != "" && textToMorse(textInput) === morse);
37+
}, [textInput]);
38+
39+
/**
40+
* Gets called every time a new morse message to find is set.
41+
* Requests to play the new morse code.
42+
*/
43+
useEffect (() => {
44+
playMorse();
45+
}, [morse]);
46+
47+
/**
48+
* Initialises the useState which holds all learning words from the .josn file imported.
49+
*/
50+
function initWords() {
51+
setWords(learnWords.words);
52+
}
53+
54+
/**
55+
* Can only be called by the user when the correct word was entered.
56+
* Plays the morse code of the found word, resets the input and requests a new word to find.
57+
*/
58+
function handleNextButton() {
59+
setTextInput("");
60+
getNextMorse();
61+
}
62+
63+
/**
64+
* Uses the audio player to play the morse code of the found word.
65+
*/
66+
async function playMorse() {
67+
player.seekTo(0);
68+
const uri = await encodeMorse(morse, "last_learnword")
69+
player.replace({uri: uri});
70+
player.play();
71+
}
72+
73+
/**
74+
* Takes a random word of the learnword list and sets the corresponding useState.
75+
*/
76+
function getNextMorse() {
77+
setMorse(textToMorse(words.at(Math.random() * words.length)));
78+
}
79+
80+
return(
81+
<KeyboardAvoidingView behavior={Platform.OS === 'ios' ? 'padding' : 'height'} style={{ flex: 1, padding: 20, paddingTop: 30, gap: 20 }}>
82+
<BackArrowComponent></BackArrowComponent>
83+
<View style={styles.morse_box_container}>
84+
<Text style={styles.info_text}>Morse to Decode:</Text>
85+
<View style={styles.box_with_icon}>
86+
<Text style={styles.morse_text}>{morse}</Text>
87+
<Fontisto name="question" size={45} color={'black'} style={styles.icon}></Fontisto>
88+
</View>
89+
</View>
90+
<View style={styles.morse_box_container}>
91+
<Text style={styles.info_text}>Your Input:</Text>
92+
<View style={styles.box_with_icon}>
93+
<Text style={styles.morse_text}>{textToMorse(textInput)}</Text>
94+
{!isCorrect && <AntDesign name="closecircleo" size={45} color={'black'} style={styles.icon}></AntDesign>}
95+
{isCorrect && <AntDesign name="checkcircleo" size={45} color={'black'} style={styles.icon}></AntDesign>}
96+
</View>
97+
</View>
98+
<TextInput style={styles.input} value={textInput} onChangeText={setTextInput} ></TextInput>
99+
<TouchableOpacity style={isCorrect ? styles.next_button : styles.next_button_disabled} disabled={!isCorrect} onPress={() => handleNextButton()}>
100+
<Text style={styles.next_button_text}>Next</Text>
101+
</TouchableOpacity>
102+
</KeyboardAvoidingView>
103+
)
104+
}
105+
106+
const styles = StyleSheet.create({
107+
morse_box_container: {
108+
flexDirection: 'column'
109+
},
110+
box_with_icon: {
111+
flexDirection: 'row',
112+
columnGap: 10
113+
},
114+
icon: {
115+
alignSelf: 'center'
116+
},
117+
info_text: {
118+
fontSize: 20,
119+
alignSelf: 'flex-start'
120+
},
121+
morse_text: {
122+
fontSize: 30,
123+
borderWidth: 3,
124+
width: "80%",
125+
alignSelf: 'center',
126+
backgroundColor: 'lightgray'
127+
},
128+
input: {
129+
fontSize: 30,
130+
borderBottomWidth: 3,
131+
width: "80%",
132+
alignSelf: 'flex-start'
133+
},
134+
next_button: {
135+
backgroundColor: "green",
136+
borderRadius: 10,
137+
padding: 15,
138+
width: "50%",
139+
alignSelf: 'center'
140+
},
141+
next_button_disabled: {
142+
backgroundColor: "lightgray",
143+
borderRadius: 10,
144+
padding: 15,
145+
width: "50%",
146+
alignSelf: 'center'
147+
},
148+
next_button_text: {
149+
fontSize: 20.0,
150+
textAlign: "center"
151+
}
152+
})

assets/data/learnwords.json

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
{
2+
"words": [
3+
"SOS",
4+
"THM",
5+
"Hello",
6+
"Morsecode",
7+
"Schokokuchen",
8+
"MAYDAY",
9+
"HELP",
10+
"YES",
11+
"NO",
12+
"OK",
13+
"ORDER66",
14+
"NUMBER15",
15+
"42",
16+
"ROGER",
17+
"OVER",
18+
"OUT",
19+
"WAIT",
20+
"GO",
21+
"STOP",
22+
"EMERGENCY",
23+
"REPEAT",
24+
"CONFIRM",
25+
"ERROR",
26+
"CLEAR",
27+
"MESSAGE",
28+
"CALL",
29+
"RADIO",
30+
"SIGNAL",
31+
"WEATHER",
32+
"LOCATION",
33+
"TIME",
34+
"NORTH",
35+
"SOUTH",
36+
"EAST",
37+
"WEST",
38+
"DANGER",
39+
"SAFE"
40+
]
41+
}

0 commit comments

Comments
 (0)