import { useState, useEffect } from 'react'; import TextField from '@mui/material/TextField'; import Typography from '@mui/material/Typography'; import Box from '@mui/material/Box'; import { SpeakButton } from '../common/SpeakButton'; import type { TranslationExercise } from '../../types/lesson'; interface TranslationProps { exercise: TranslationExercise; selectedAnswer: string | null; isChecked: boolean; onSelect: (answer: string) => void; } function levenshteinDistance(a: string, b: string): number { const matrix: number[][] = []; 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++) { const cost = b.charAt(i - 1) === a.charAt(j - 1) ? 0 : 1; matrix[i][j] = Math.min( matrix[i - 1][j] + 1, matrix[i][j - 1] + 1, matrix[i - 1][j - 1] + cost, ); } } return matrix[b.length][a.length]; } export function checkTranslation( input: string, acceptedAnswers: string[], ): boolean { const normalized = input.trim().toLowerCase(); return acceptedAnswers.some((answer) => { const normalizedAnswer = answer.trim().toLowerCase(); if (normalized === normalizedAnswer) return true; return levenshteinDistance(normalized, normalizedAnswer) <= 2; }); } export function Translation({ exercise, selectedAnswer, isChecked, onSelect, }: TranslationProps) { const [inputValue, setInputValue] = useState(''); useEffect(() => { setInputValue(selectedAnswer ?? ''); }, [selectedAnswer]); function handleChange(value: string) { setInputValue(value); onSelect(value); } return ( {exercise.promptAudio && } {exercise.prompt} {exercise.hint && ( Hint: {exercise.hint} )} handleChange(e.target.value)} disabled={isChecked} placeholder="Type your answer..." sx={{ '& .MuiOutlinedInput-root': { fontSize: '1.1rem', }, }} /> ); }