1
1
import QuestionGenerator from './QuestionGenerator' ;
2
2
import CreationHistoricalRecord from './CreationHistoricalRecord' ;
3
- import { useState } from 'react' ;
4
3
import "../../custom.css" ;
5
- import React from "react" ;
4
+ import React , { useState , useEffect , useCallback } from "react" ;
6
5
import Countdown from 'react-countdown' ;
7
6
import { useTranslation } from "react-i18next" ;
8
7
import $ from 'jquery' ;
@@ -21,8 +20,7 @@ function QuestionView({type= "COMPETITIVE", amount=5}){
21
20
const [ questions , setQuestions ] = useState ( null ) ;
22
21
const [ t , i18n ] = useTranslation ( "global" ) ;
23
22
const cookie = JSON . parse ( Cookies . get ( 'user' ) ?? JSON . stringify ( { username : playAsGuestUsername , token : playAsGuestToken } ) )
24
- const [ audio ] = useState ( new Audio ( '/tictac.mp3' ) ) ;
25
-
23
+
26
24
27
25
const generateQuestions = async ( numQuestion ) => {
28
26
if ( numQuestion < 0 ) {
@@ -56,11 +54,9 @@ function QuestionView({type= "COMPETITIVE", amount=5}){
56
54
} ) ;
57
55
}
58
56
if ( answerGiven === correctAnswer ) {
59
- audio . pause ( ) ;
60
57
audioCorrect . play ( ) ; // Reproduce el sonido de respuesta incorrecta
61
58
}
62
59
else {
63
- audio . pause ( ) ;
64
60
audioIncorrect . play ( ) ; // Reproduce el sonido de respuesta correcta
65
61
}
66
62
$ ( this ) . css ( 'pointer-events' , 'none' ) ;
@@ -80,15 +76,17 @@ function QuestionView({type= "COMPETITIVE", amount=5}){
80
76
function computePointsForQuestion ( correctAnswer , answerGiven ) {
81
77
if ( answerGiven === correctAnswer ) {
82
78
points += 100 ;
83
- audio . pause ( ) ;
84
79
} else if ( points - 50 >= 0 ) {
85
80
points -= 50 ;
86
- audio . pause ( ) ;
87
81
} else {
88
82
points = 0 ;
89
83
}
90
84
}
91
85
function handleClick ( text ) {
86
+ // Detener el síntesis de voz
87
+ if ( window . speechSynthesis . speaking )
88
+ window . speechSynthesis . cancel ( ) ;
89
+
92
90
//create the record to record the response
93
91
creationHistoricalRecord . addQuestion ( questions [ numQuestion ] . getQuestion ( ) ,
94
92
questions [ numQuestion ] . getAnswers ( ) ,
@@ -108,7 +106,6 @@ function QuestionView({type= "COMPETITIVE", amount=5}){
108
106
109
107
//Last question sends the record
110
108
if ( ! ( numQuestion < questions . length - 1 ) ) {
111
- audio . pause ( ) ;
112
109
creationHistoricalRecord . setCompetitive ( type === 'COMPETITIVE' ) ;
113
110
creationHistoricalRecord . setDate ( Date . now ( ) ) ;
114
111
creationHistoricalRecord . setPoints ( points ) ;
@@ -118,41 +115,28 @@ function QuestionView({type= "COMPETITIVE", amount=5}){
118
115
} , 1000 ) ;
119
116
120
117
}
121
-
118
+
122
119
if ( questions === null )
123
120
generateQuestions ( numQuestion )
124
121
125
122
126
123
return (
127
124
< div className = "question-view-container" >
128
125
{ numQuestion >= 0 ?
129
- < QuestionComponent t = { t } questions = { questions } numQuestion = { numQuestion } handleClick = { handleClick } points = { points } audio = { audio } language = { i18n . language } /> :
126
+ < QuestionComponent t = { t } questions = { questions } numQuestion = { numQuestion } handleClick = { handleClick } points = { points } language = { i18n . language } /> :
130
127
< h1 > { t ( "questionView.no_questions_message" ) } </ h1 > }
131
128
</ div > ) ;
132
129
}
133
130
134
- function QuestionComponent ( { questions, numQuestion, handleClick, t, points, audio , language} ) {
131
+ function QuestionComponent ( { questions, numQuestion, handleClick, t, points, language} ) {
135
132
136
133
137
- const speakQuestion = ( ) => {
138
- const speech = new SpeechSynthesisUtterance ( ) ;
139
- speech . lang = language ;
140
- console . log ( language ) ;
141
- getVoicesForLanguage ( language )
142
- . then ( voices => {
143
- // const voice = voices.find(voice => voice.lang === language);
144
- // speech.voice = voice || voices[0]; // If there is no voice for the lang, choose the first one
145
- window . speechSynthesis . speak ( speech ) ;
146
- } )
147
- . catch ( error => {
148
- console . error ( "Error al obtener las voces para el idioma:" , error ) ;
149
- } ) ;
150
- } ;
151
-
152
- // Función para obtener las voces disponibles para un idioma
153
- const getVoicesForLanguage = ( language ) => {
134
+ // To obtain available voices for language
135
+ const getVoicesForLanguage = useCallback ( ( language ) => {
154
136
return new Promise ( ( resolve , reject ) => {
155
137
const speech = new SpeechSynthesisUtterance ( ) ;
138
+
139
+ //speaks the question
156
140
speech . text = questions [ numQuestion ] . getQuestion ( ) ;
157
141
speech . lang = language ;
158
142
@@ -166,19 +150,70 @@ function QuestionComponent({questions, numQuestion, handleClick, t, points, audi
166
150
167
151
window . speechSynthesis . speak ( speech ) ;
168
152
} ) ;
169
- } ;
153
+ } , [ questions , numQuestion ] ) ;
154
+
155
+ const speakAnswers = useCallback ( ( answers ) => {
156
+ const speech = new SpeechSynthesisUtterance ( ) ;
157
+ speech . lang = language ;
158
+ let concatenatedAnswers = Array . isArray ( answers ) ? answers . map ( ( answer , index ) => `${ index + 1 } . ${ answer } ` ) . join ( ". " ) : '' ;
159
+
160
+ getVoicesForLanguage ( language )
161
+ . then ( voices => {
162
+ // const voice = voices.find(voice => voice.lang === language);
163
+ // speech.voice = voice || voices[0]; // If there is no voice for the lang, choose the first one
164
+ speech . text = concatenatedAnswers ;
165
+ window . speechSynthesis . speak ( speech ) ;
166
+ } )
167
+ . catch ( error => {
168
+ console . error ( "Error al obtener las voces para el idioma:" , error ) ;
169
+ } ) ;
170
+ } , [ getVoicesForLanguage , language ] ) ;
171
+
172
+ const speak = useCallback ( ( ) => {
173
+ speakAnswers ( questions [ numQuestion ] . getAnswers ( ) ) ;
174
+ } , [ numQuestion , questions , speakAnswers ] ) ;
175
+
176
+ useEffect ( ( ) => {
177
+ const handleKeyPress = ( event ) => {
178
+ if ( event . key === 's' ) {
179
+ speak ( ) ;
180
+ } else {
181
+ const answerIndex = parseInt ( event . key ) - 1 ;
182
+ if ( ! isNaN ( answerIndex ) && answerIndex >= 0 && answerIndex < questions [ numQuestion ] . getAnswers ( ) . length ) {
183
+
184
+ handleClick ( questions [ numQuestion ] . getAnswers ( ) [ answerIndex ] ) ;
185
+ }
186
+ }
187
+ } ;
188
+
189
+ window . addEventListener ( "keypress" , handleKeyPress ) ;
190
+
191
+ return ( ) => {
192
+ window . removeEventListener ( "keypress" , handleKeyPress ) ;
193
+ } ;
194
+ } , [ speak , numQuestion , questions , handleClick ] ) ;
195
+
196
+ //To stop the voice when changing of page
197
+ useEffect ( ( ) => {
198
+ const handleBeforeUnload = ( ) => {
199
+ if ( window . speechSynthesis . speaking )
200
+ window . speechSynthesis . cancel ( ) ;
201
+ } ;
202
+
203
+ window . addEventListener ( "beforeunload" , handleBeforeUnload ) ;
204
+
205
+ return ( ) => {
206
+ window . removeEventListener ( "beforeunload" , handleBeforeUnload ) ;
207
+ } ;
208
+ } , [ ] ) ;
170
209
171
210
172
211
173
212
const renderer = ( { seconds, completed } ) => {
174
213
if ( completed ) {
175
- audio . pause ( ) ;
176
214
return < span > { t ( "questionView.end_countdown" ) } </ span > ; // Rendered when countdown completes
177
215
} else {
178
- if ( audio . paused ) {
179
- audio . loop = true ; // Loop of tiktak
180
- audio . play ( ) ;
181
- }
216
+
182
217
return < span > { seconds } { t ( "questionView.seconds" ) } </ span > ; // Render countdown
183
218
}
184
219
} ;
@@ -189,7 +224,7 @@ function QuestionComponent({questions, numQuestion, handleClick, t, points, audi
189
224
< div className = 'questionContainer' >
190
225
191
226
< div className = 'topPanel' >
192
- < h2 > { questions [ numQuestion ] . getQuestion ( ) } < button className = "altavoz" onClick = { speakQuestion } > 🔊</ button > </ h2 >
227
+ < h2 > { questions [ numQuestion ] . getQuestion ( ) } < button className = "altavoz" onClick = { speak } > 🔊</ button > </ h2 >
193
228
< div className = "countdown" >
194
229
< Countdown key = { numQuestion } date = { Date . now ( ) + 10000 } renderer = { renderer } onComplete = { handleClick . bind ( this , "no-answer" ) } />
195
230
</ div >
0 commit comments