|
|
import gradio as gr |
|
|
import random |
|
|
|
|
|
|
|
|
ipa_data = { |
|
|
'p': {'Voicing': 'voiceless', 'Place': 'bilabial', 'Manner': 'stop','Oro-nasal': '(oral)','Centrality':'(central)'}, |
|
|
'b': {'Voicing': 'voiced', 'Place': 'bilabial', 'Manner': 'stop','Oro-nasal': '(oral)','Centrality':'(central)'}, |
|
|
't': {'Voicing': 'voiceless', 'Place': 'alveolar', 'Manner': 'stop','Oro-nasal': '(oral)','Centrality':'(central)'}, |
|
|
'd': {'Voicing': 'voiced', 'Place': 'alveolar', 'Manner': 'stop','Oro-nasal': '(oral)','Centrality':'(central)'}, |
|
|
'k': {'Voicing': 'voiceless', 'Place': 'velar', 'Manner': 'stop','Oro-nasal': '(oral)','Centrality':'(central)'}, |
|
|
'g': {'Voicing': 'voiced', 'Place': 'velar', 'Manner': 'stop','Oro-nasal': '(oral)','Centrality':'(central)'}, |
|
|
'f': {'Voicing': 'voiceless', 'Place': 'labio-dental', 'Manner': 'fricative','Oro-nasal': '(oral)','Centrality':'(central)'}, |
|
|
'v': {'Voicing': 'voiced', 'Place': 'labio-dental', 'Manner': 'fricative','Oro-nasal': '(oral)','Centrality':'(central)'}, |
|
|
'θ': {'Voicing': 'voiceless', 'Place': 'dental', 'Manner': 'fricative','Oro-nasal': '(oral)','Centrality':'(central)'}, |
|
|
'ð': {'Voicing': 'voiced', 'Place': 'dental', 'Manner': 'fricative','Oro-nasal': '(oral)','Centrality':'(central)'}, |
|
|
's': {'Voicing': 'voiceless', 'Place': 'alveolar', 'Manner': 'fricative','Oro-nasal': '(oral)','Centrality':'(central)'}, |
|
|
'z': {'Voicing': 'voiced', 'Place': 'alveolar', 'Manner': 'fricative','Oro-nasal': '(oral)','Centrality':'(central)'}, |
|
|
'ʃ': {'Voicing': 'voiceless', 'Place': 'palato-alveolar', 'Manner': 'fricative','Oro-nasal': '(oral)','Centrality':'(central)'}, |
|
|
'ʒ': {'Voicing': 'voiced', 'Place': 'palato-alveolar', 'Manner': 'fricative','Oro-nasal': '(oral)','Centrality':'(central)'}, |
|
|
'tʃ': {'Voicing': 'voiceless', 'Place': 'palato-alveolar', 'Manner': 'affricate','Oro-nasal': '(oral)','Centrality':'(central)'}, |
|
|
'dʒ': {'Voicing': 'voiced', 'Place': 'palato-alveolar', 'Manner': 'affricate','Oro-nasal': '(oral)','Centrality':'(central)'}, |
|
|
'h': {'Voicing': 'voiceless', 'Place': 'glottal', 'Manner': 'fricative','Oro-nasal': '(oral)','Centrality':'(central)'}, |
|
|
'm': {'Voicing': 'voiced', 'Place': 'bilabial', 'Manner': 'stop','Oro-nasal': 'nasal','Centrality':'(not applicable)'}, |
|
|
'n': {'Voicing': 'voiced', 'Place': 'alveolar', 'Manner': 'stop','Oro-nasal': 'nasal','Centrality':'(not applicable)'}, |
|
|
'ŋ': {'Voicing': 'voiced', 'Place': 'velar', 'Manner': 'stop','Oro-nasal': 'nasal','Centrality':'(not applicable)'}, |
|
|
'ɹ': {'Voicing': 'voiced', 'Place': 'alveolar', 'Manner': 'approximant','Oro-nasal': '(oral)','Centrality':'(central)'}, |
|
|
'l': {'Voicing': 'voiced', 'Place': 'alveolar', 'Manner': 'approximant','Oro-nasal': '(oral)','Centrality':'lateral'}, |
|
|
'j': {'Voicing': 'voiced', 'Place': 'palatal', 'Manner': 'approximant','Oro-nasal': '(oral)','Centrality':'(central)'}, |
|
|
'w': {'Voicing': 'voiced', 'Place': 'labio-velar', 'Manner': 'approximant','Oro-nasal': '(oral)','Centrality':'(central)'} |
|
|
} |
|
|
|
|
|
def select_random_symbol(): |
|
|
""" Select a random IPA symbol """ |
|
|
symbol = random.choice(list(ipa_data.keys())) |
|
|
return symbol, ipa_data[symbol] |
|
|
|
|
|
def validate_selections(ipa_symbol, user_voicing, user_place, user_manner, user_oronasal, user_centrality, correct_count, attempts): |
|
|
""" Check user's selections against the actual IPA symbol properties """ |
|
|
correct_data = ipa_data[ipa_symbol] |
|
|
correct = (correct_data['Voicing'] == user_voicing and |
|
|
correct_data['Place'] == user_place and |
|
|
correct_data['Manner'] == user_manner and |
|
|
correct_data['Oro-nasal'] == user_oronasal and |
|
|
correct_data['Centrality'] == user_centrality) |
|
|
attempts += 1 |
|
|
if correct: |
|
|
correct_count += 1 |
|
|
return "Correct!", correct_count, attempts |
|
|
else: |
|
|
return "Incorrect! Correct values are: \n- Voicing: {}, \n- Place: {}, \n- Manner: {}, \n- Oro-nasal: {}, \n- Centrality: {}"\ |
|
|
.format(correct_data['Voicing'], correct_data['Place'], correct_data['Manner'], correct_data['Oro-nasal'], correct_data['Centrality']), correct_count, attempts |
|
|
|
|
|
def setup_interface(): |
|
|
with gr.Blocks() as app: |
|
|
gr.Markdown("### IPA Practice App") |
|
|
|
|
|
new_symbol_button = gr.Button("Display a New Symbol") |
|
|
symbol_display = gr.Textbox(label="IPA Symbol", interactive=False) |
|
|
|
|
|
voicing_radio = gr.Radio(label="Voicing", choices=['voiceless', 'voiced']) |
|
|
place_radio = gr.Radio(label="Place", choices=['bilabial', 'labio-dental', 'labio-velar', 'dental', 'alveolar', 'palato-alveolar', 'palatal', 'velar', 'glottal']) |
|
|
centrality_radio = gr.Radio(label="Centrality", choices=['(central)', 'lateral', '(not applicable)']) |
|
|
oronasal_radio = gr.Radio(label="Oro-nasal", choices=['(oral)', 'nasal']) |
|
|
manner_radio = gr.Radio(label="Manner", choices=['stop', 'fricative', 'affricate', 'approximant']) |
|
|
|
|
|
submit_button = gr.Button("Submit") |
|
|
result_display = gr.Textbox(label="Result", interactive=False) |
|
|
correct_count = gr.State(0) |
|
|
attempts = gr.State(0) |
|
|
|
|
|
quit_button = gr.Button("See the total score") |
|
|
score_display = gr.Textbox(label="Score", interactive=False) |
|
|
|
|
|
def update_display(): |
|
|
symbol, _ = select_random_symbol() |
|
|
symbol_display.value = symbol |
|
|
return symbol |
|
|
|
|
|
def submit_results(ipa_symbol, voicing, place, manner, oronasal, centrality, correct_count, attempts): |
|
|
result, updated_correct_count, updated_attempts = validate_selections(ipa_symbol, voicing, place, manner, oronasal, centrality, correct_count, attempts) |
|
|
return result, updated_correct_count, updated_attempts |
|
|
|
|
|
def quit_session(correct_count, attempts): |
|
|
final_score = f"Final Score: {correct_count}/{attempts}" |
|
|
return final_score |
|
|
|
|
|
new_symbol_button.click( |
|
|
fn=update_display, |
|
|
inputs=[], |
|
|
outputs=[symbol_display] |
|
|
) |
|
|
|
|
|
submit_button.click( |
|
|
fn=submit_results, |
|
|
inputs=[symbol_display, voicing_radio, place_radio, manner_radio, oronasal_radio, centrality_radio, correct_count, attempts], |
|
|
outputs=[result_display, correct_count, attempts] |
|
|
) |
|
|
|
|
|
quit_button.click( |
|
|
fn=quit_session, |
|
|
inputs=[correct_count, attempts], |
|
|
outputs=[score_display] |
|
|
) |
|
|
|
|
|
gr.Row(new_symbol_button, symbol_display) |
|
|
gr.Row(submit_button, quit_button) |
|
|
gr.Row(result_display, score_display) |
|
|
|
|
|
return app |
|
|
|
|
|
app = setup_interface() |
|
|
app.launch(debug=True) |
|
|
|