/* eslint-disable @next/next/no-img-element */ import {InteractiveSpeakingExercise} from "@/interfaces/exam"; import {CommonProps} from "."; import {useEffect, useState} from "react"; import Button from "../Low/Button"; import dynamic from "next/dynamic"; import axios from "axios"; import {speakingReverseMarking} from "@/utils/score"; import {Tab} from "@headlessui/react"; import clsx from "clsx"; import Modal from "../Modal"; import ReactDiffViewer, {DiffMethod} from "react-diff-viewer"; const Waveform = dynamic(() => import("../Waveform"), {ssr: false}); export default function InteractiveSpeaking({ id, type, title, text, prompts, userSolutions, onNext, onBack, }: InteractiveSpeakingExercise & CommonProps) { const [solutionsURL, setSolutionsURL] = useState([]); const [diffNumber, setDiffNumber] = useState(0); const tooltips: {[key: string]: string} = { "Grammatical Range and Accuracy": "Assesses the variety and correctness of grammatical structures used. A higher score indicates a wide range of complex and accurate grammar; a lower score suggests the need for more basic grammar practice.", "Fluency and Coherence": "Evaluates smoothness and logical flow of speech. A higher score means natural, effortless speech and clear idea progression; a lower score indicates frequent pauses and difficulty in maintaining coherence.", Pronunciation: "Measures clarity and accuracy of spoken words. A higher score reflects clear, well-articulated speech with correct intonation; a lower score shows challenges in being understood.", "Lexical Resource": "Looks at the range and appropriateness of vocabulary. A higher score demonstrates a rich and precise vocabulary; a lower score suggests limited vocabulary usage and appropriateness.", }; useEffect(() => { if (userSolutions && userSolutions.length > 0 && userSolutions[0].solution) { Promise.all(userSolutions[0].solution.map((x) => axios.post(`/api/speaking`, {path: x.answer}, {responseType: "arraybuffer"}))).then( (values) => { setSolutionsURL( values.map(({data}) => { const blob = new Blob([data], {type: "audio/wav"}); const url = URL.createObjectURL(blob); return url; }), ); }, ); } }, [userSolutions]); return (
setDiffNumber(0)}> <> {userSolutions && userSolutions.length > 0 && diffNumber !== 0 && userSolutions[0].evaluation && userSolutions[0].evaluation[`transcript_${diffNumber}`] && userSolutions[0].evaluation[`fixed_text_${diffNumber}`] && (
Transcript Recommended Improvements
)}
{title}
You should talk about the following things:
{prompts.map((x, index) => (
{x.text}
))}
{solutionsURL.map((x, index) => (
{userSolutions && userSolutions.length > 0 && userSolutions[0].evaluation && userSolutions[0].evaluation[`transcript_${index + 1}`] && userSolutions[0].evaluation[`fixed_text_${index + 1}`] && ( )}
))}
{userSolutions && userSolutions.length > 0 && userSolutions[0].evaluation && typeof userSolutions[0].evaluation !== "string" && (
{Object.keys(userSolutions[0].evaluation!.task_response).map((key, index) => { const taskResponse = userSolutions[0].evaluation!.task_response[key]; const grade: number = typeof taskResponse === "number" ? taskResponse : taskResponse.grade; return (
{key}: Level {grade}
); })}
{userSolutions[0].evaluation && Object.keys(userSolutions[0].evaluation).filter((x) => x.startsWith("perfect_answer")).length > 0 ? ( clsx( "w-full rounded-lg py-2.5 text-sm font-medium leading-5 text-ielts-speaking/80", "ring-white ring-opacity-60 ring-offset-2 ring-offset-ielts-speaking focus:outline-none focus:ring-2", "transition duration-300 ease-in-out", selected ? "bg-white shadow" : "text-blue-100 hover:bg-white/[0.12] hover:text-ielts-speaking", ) }> General Feedback clsx( "w-full rounded-lg py-2.5 text-sm font-medium leading-5 text-ielts-speaking/80", "ring-white ring-opacity-60 ring-offset-2 ring-offset-ielts-speaking focus:outline-none focus:ring-2", "transition duration-300 ease-in-out", selected ? "bg-white shadow" : "text-blue-100 hover:bg-white/[0.12] hover:text-ielts-speaking", ) }> Evaluation {Object.keys(userSolutions[0].evaluation) .filter((x) => x.startsWith("perfect_answer")) .map((key, index) => ( clsx( "w-full rounded-lg py-2.5 text-sm font-medium leading-5 text-ielts-speaking/80", "ring-white ring-opacity-60 ring-offset-2 ring-offset-ielts-speaking focus:outline-none focus:ring-2", "transition duration-300 ease-in-out", selected ? "bg-white shadow" : "text-blue-100 hover:bg-white/[0.12] hover:text-ielts-speaking", ) }> Recommended Answer
(Prompt {index + 1})
))}
{Object.keys(userSolutions[0].evaluation!.task_response).map((key) => { const taskResponse = userSolutions[0].evaluation!.task_response[key]; const grade: number = typeof taskResponse === "number" ? taskResponse : taskResponse.grade; return (
{key}: Level {grade}
{typeof taskResponse !== "number" && ( {taskResponse.comment} )}
); })}
{userSolutions[0].evaluation!.comment} {Object.keys(userSolutions[0].evaluation) .filter((x) => x.startsWith("perfect_answer")) .map((key, index) => ( {userSolutions[0].evaluation![`perfect_answer_${index + 1}`].answer.replaceAll( /\s{2,}/g, "\n\n", )} ))}
) : (
{userSolutions[0].evaluation!.comment}
)}
)}
); }