From 2c7a577232dca66fc56d8f049950897b4b908d39 Mon Sep 17 00:00:00 2001 From: "ms@Nicro" Date: Sun, 7 Jan 2024 16:07:30 +0100 Subject: [PATCH 1/3] Implemented evaluation for NON vocal exercises Still to do: -Evaluation of vocal exercises --- .../java/controller/ExerciseController.java | 2 + .../java/controller/ExerciseEvaluator.java | 151 ++++++++++++++++++ src/main/java/controller/ExerciseLogger.java | 12 +- src/main/java/model/DAO/DAOExercise.java | 33 ++++ .../service/exercise/ExerciseManager.java | 10 +- .../exercise/ExerciseManagerInterface.java | 3 +- src/main/webapp/JS/exercise.js | 24 +-- 7 files changed, 217 insertions(+), 18 deletions(-) create mode 100644 src/main/java/controller/ExerciseEvaluator.java diff --git a/src/main/java/controller/ExerciseController.java b/src/main/java/controller/ExerciseController.java index d7fd726..b4fba26 100644 --- a/src/main/java/controller/ExerciseController.java +++ b/src/main/java/controller/ExerciseController.java @@ -18,5 +18,7 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) ExerciseGlossary ex = em.getExercise(Integer.parseInt(id)); request.getSession().setAttribute("exercise", ex); response.sendRedirect(request.getContextPath() + "/JSP/exercise.jsp"); + + request.getSession().setAttribute("exerciseID", id); //TODO: RIMUOVI } } \ No newline at end of file diff --git a/src/main/java/controller/ExerciseEvaluator.java b/src/main/java/controller/ExerciseEvaluator.java new file mode 100644 index 0000000..0868dcb --- /dev/null +++ b/src/main/java/controller/ExerciseEvaluator.java @@ -0,0 +1,151 @@ +package controller; + +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; +import model.entity.ExerciseGlossary; +import model.service.exercise.ExerciseManager; +import model.service.exercise.ExerciseManagerInterface; + +import javax.servlet.ServletException; +import javax.servlet.annotation.MultipartConfig; +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.*; +import java.io.*; +import java.lang.reflect.Type; +import java.sql.Blob; +import java.sql.Date; +import java.sql.SQLException; +import java.util.Map; +import java.util.Set; + +@WebServlet("/exerciseEvaluator") +@MultipartConfig +public class ExerciseEvaluator extends HttpServlet { + protected void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { + HttpSession s = request.getSession(); + String contentType = request.getContentType(); + ExerciseManager em = new ExerciseManager(); + + int exerciseId = Integer.parseInt((String) s.getAttribute("exerciseID")); + //int userId = Integer.parseInt((String) s.getAttribute("id")); + //Date d = Date.valueOf((String) s.getAttribute("insertDate"); + + Date d = Date.valueOf("2024-01-07"); //TODO: prendilo dalla session + int userId = 8; //TODO: prendilo dalla session + + + if ("application/json".equals(contentType)) { + int score = evaluateNoAudio(exerciseId, userId, d); + em.saveEvaluation(userId, exerciseId, d, score); + } //else { + // evaluateAudio(request); + // } + } + + private int evaluateNoAudio(int exerciseId, int userId, Date date){ + Gson gson = new Gson(); + + ExerciseGlossary baseExercise = new ExerciseManager().getExercise(exerciseId); + String executionJSON = getJSONfromBlob(exerciseId, userId, date); + String type = baseExercise.getType(); + + int score = 0; + + switch (type) { + case "CROSSWORD" -> { + String[][] solution = gson.fromJson(baseExercise.getSolution(), String[][].class); + String[][] execution = gson.fromJson(executionJSON, String[][].class); + + score = evaluateCrossword(execution, solution); + } + case "IMAGESTOTEXT", "TEXTTOIMAGES" -> { + Type solutionType = new TypeToken>() {}.getType(); + Map solution = gson.fromJson(baseExercise.getSolution(), solutionType); + Map execution = gson.fromJson(executionJSON, solutionType); + + score = evaluateITTnTTI(execution, solution); + } + case "RIGHTTEXT" -> { + Type solutionType = new TypeToken>(){}.getType(); + Set solution = gson.fromJson(baseExercise.getSolution(), solutionType); + Set execution = gson.fromJson(executionJSON, solutionType); + + score = evaluateRightText(execution, solution); + } + default -> throw new IllegalStateException("Unexpected value: " + type); + } + + return score; + } + + private String getJSONfromBlob(int exerciseId, int userId, Date d){ + Blob executionBlob = new ExerciseManager().getExecution(exerciseId, userId, d); + StringBuilder stringBuilder = new StringBuilder(); + + try (InputStream binaryStream = executionBlob.getBinaryStream(); + InputStreamReader inputStreamReader = new InputStreamReader(binaryStream); + BufferedReader bufferedReader = new BufferedReader(inputStreamReader)) { + + String line; + while ((line = bufferedReader.readLine()) != null) { + stringBuilder.append(line); + } + + } catch (SQLException | IOException e) { + e.printStackTrace(); + } + + return stringBuilder.toString(); + } + + private int evaluateRightText(Set execution, Set solution) { + double right = 0; + int total = solution.size(); + for (String s : solution) { + if (execution.contains(s.toUpperCase())){ + right++; + } + } + return (int)((right /total)*100); + } + + private int evaluateITTnTTI(Map execution, Map solution) { + double right = 0; + int total = solution.size(); + + for (Map.Entry entry : execution.entrySet()) { + String k = entry.getKey(); + String executionValue = entry.getValue(); + String solutionValue = solution.get(k); + + if (executionValue != null) { + if (executionValue.equals(solutionValue.toUpperCase())) { + right++; + } + } + } + return (int)((right /total)*100); + } + + private int evaluateCrossword(String[][] execution, String[][] solution) { + double right = 0; + int total = 0; + + for (int i = 0; i < execution.length; i++) { + for (int j = 0; j < execution[0].length; j++) { + if (!execution[i][j].equals("#")){ + if (execution[i][j].equals(solution[i][j].toUpperCase())) { + right++; + } + total++; + } + } + } + return (int)((right /total)*100); + } + + // private void evaluateAudio(HttpServletRequest r){ + // //TODO: chiamata all'adapter, per python che valuta l'audio + // } + +} \ No newline at end of file diff --git a/src/main/java/controller/ExerciseLogger.java b/src/main/java/controller/ExerciseLogger.java index f27682c..2d589e3 100644 --- a/src/main/java/controller/ExerciseLogger.java +++ b/src/main/java/controller/ExerciseLogger.java @@ -3,6 +3,7 @@ import model.service.exercise.ExerciseManager; import org.apache.commons.io.IOUtils; +import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.annotation.MultipartConfig; import javax.servlet.annotation.WebServlet; @@ -27,6 +28,8 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) } else { handleAudioExercise(request); } + RequestDispatcher d = request.getRequestDispatcher("/exerciseEvaluator"); + d.forward(request, response); } private void handleNoAudioExercise(HttpServletRequest request) throws IOException { @@ -64,9 +67,12 @@ private void handleAudioExercise(HttpServletRequest request) throws ServletExcep private boolean saveInDB(HttpServletRequest request, Blob execution){ ExerciseManager em = new ExerciseManager(); HttpSession session = request.getSession(); - int userId = Integer.parseInt((String) session.getAttribute("userId")); - int exerciseId = Integer.parseInt((String) session.getAttribute("exerciseId")); - Date insertDate = Date.valueOf((String) session.getAttribute("insertDate")); +// int userId = Integer.parseInt((String) session.getAttribute("userId")); + int exerciseId = Integer.parseInt((String) session.getAttribute("exerciseID")); +// Date insertDate = Date.valueOf((String) session.getAttribute("insertDate")); +//TODO: RIMUOVI I COMMENTI + int userId = 8; + Date insertDate = Date.valueOf("2024-01-07"); return em.saveExecution(userId, exerciseId, insertDate, execution); } } \ No newline at end of file diff --git a/src/main/java/model/DAO/DAOExercise.java b/src/main/java/model/DAO/DAOExercise.java index 727782e..d5e9299 100644 --- a/src/main/java/model/DAO/DAOExercise.java +++ b/src/main/java/model/DAO/DAOExercise.java @@ -84,6 +84,39 @@ public Exercise getExerciseByPk(int userID, int exerciseID, Date insertDate) { return null; } + public Blob getExerciseExecution(int userID, int exerciseID, Date insertDate) { + String query = "SELECT Execution FROM exercise WHERE ID_user = ? AND ID_exercise = ? AND InsertionDate = ?"; + PreparedStatement preparedStatement = null; + ResultSet resultSet = null; + + try { + connection = connection.isClosed() ? DAOConnection.getConnection() : connection; + preparedStatement = connection.prepareStatement(query); + preparedStatement.setInt(1, userID); + preparedStatement.setInt(2, exerciseID); + preparedStatement.setDate(3, insertDate); + + resultSet = preparedStatement.executeQuery(); + + if (resultSet.next()) { + return resultSet.getBlob("Execution"); + } + + } catch (SQLException e) { + e.printStackTrace(); + } finally { + try { + if (resultSet != null) resultSet.close(); + if (preparedStatement != null) preparedStatement.close(); + DAOConnection.releaseConnection(connection); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + return null; + } + public boolean setExerciseExecution(int userID, int exerciseID, Date insertDate, Blob execution) { String query = "UPDATE exercise SET Execution = ? WHERE ID_user = ? AND ID_exercise = ? AND InsertionDate = ?;"; PreparedStatement preparedStatement = null; diff --git a/src/main/java/model/service/exercise/ExerciseManager.java b/src/main/java/model/service/exercise/ExerciseManager.java index 7509b56..5586454 100644 --- a/src/main/java/model/service/exercise/ExerciseManager.java +++ b/src/main/java/model/service/exercise/ExerciseManager.java @@ -10,16 +10,22 @@ public class ExerciseManager implements ExerciseManagerInterface { private final DAOExerciseGlossary daoEG = new DAOExerciseGlossary(); private final DAOExercise daoE = new DAOExercise(); + public ExerciseGlossary getExercise(int exerciseID) { return daoEG.getExerciseByCode(exerciseID); } - public Blob getExecution(int exerciseID, int userID) { - return null; + public Blob getExecution(int exerciseID, int userID, Date insertionDate) { + return daoE.getExerciseExecution(userID, exerciseID, insertionDate); } public boolean saveExecution(int userID, int exerciseId, Date insertDate, Blob execution) { return daoE.setExerciseExecution(userID, exerciseId, insertDate, execution); } + + public boolean saveEvaluation(int userID, int exerciseId, Date insertDate, int evaluation) { + + return daoE.setExerciseEvaluation(userID, exerciseId, insertDate, evaluation); + } } diff --git a/src/main/java/model/service/exercise/ExerciseManagerInterface.java b/src/main/java/model/service/exercise/ExerciseManagerInterface.java index 62d675d..243030e 100644 --- a/src/main/java/model/service/exercise/ExerciseManagerInterface.java +++ b/src/main/java/model/service/exercise/ExerciseManagerInterface.java @@ -18,9 +18,10 @@ public interface ExerciseManagerInterface { * Preleva un'esecuzione di un esercizio * @param exerciseID l'id dell'esercizio * @param userID l'id dell'utente che ha svolto l'esercizio + * @param insertionDate la data in cui l'esercizio è stata assegnata all'utente * @return un BLOB contenente l'esecuzione dell'esercizio */ - Blob getExecution(int exerciseID, int userID); + Blob getExecution(int exerciseID, int userID, Date insertionDate); /** * Salva l'esecuzione di un esercizio diff --git a/src/main/webapp/JS/exercise.js b/src/main/webapp/JS/exercise.js index 799e59a..ff4d476 100644 --- a/src/main/webapp/JS/exercise.js +++ b/src/main/webapp/JS/exercise.js @@ -514,17 +514,19 @@ function saveCT(n){ function saveExecution(execution){ $("#buttonDiv > button").prop("disabled", true).text("Esercizio Inviato!"); - $.post({ + + $.ajax({ + type: "POST", url: "../exerciseLogger", + data: JSON.stringify(execution), contentType: "application/json", - data: JSON.stringify(execution) - }).done(() => { - redirect("home"); - }).fail((error) => { - console.log("Errore durante la chiamata Post:"+error); - redirect("500.html") - }) + error: function (error) { + console.error("Errore durante l'invio dell'esecuzione alla servlet:", error); + redirect("500.html") + } + }); + redirect("home"); } function saveAudioExecution(execution){ @@ -533,7 +535,6 @@ function saveAudioExecution(execution){ let formData = new FormData(); formData.append("audioFile", execution, "User"+USERID+"exercise"+EXERCISEID+".wav"); - $.ajax({ type: "POST", url: "../exerciseLogger", @@ -541,13 +542,12 @@ function saveAudioExecution(execution){ processData: false, contentType: false, cache: false, - success: function (){ - redirect("home"); - }, error: function (error) { console.error("Errore durante l'invio dell'audio alla servlet:", error); redirect("500.html") } }); + + redirect("home"); } } \ No newline at end of file From c2f7004e1b74e0e518e1f32b31b1a51cdf573960 Mon Sep 17 00:00:00 2001 From: "ms@Nicro" Date: Mon, 8 Jan 2024 17:19:22 +0100 Subject: [PATCH 2/3] Implemented evaluation of vocal exercises --- pom.xml | 14 +++ .../java/controller/ExerciseController.java | 2 - .../java/controller/ExerciseEvaluator.java | 66 ++++++++--- src/main/java/controller/ExerciseLogger.java | 18 ++- .../service/exercise/SpeechRecognition.java | 109 ++++++++++++++++++ src/main/resources/azure.properties | 2 + src/main/webapp/JS/exercise.js | 11 +- 7 files changed, 192 insertions(+), 30 deletions(-) create mode 100644 src/main/java/model/service/exercise/SpeechRecognition.java create mode 100644 src/main/resources/azure.properties diff --git a/pom.xml b/pom.xml index 4303d24..da89044 100644 --- a/pom.xml +++ b/pom.xml @@ -125,6 +125,20 @@ javax.servlet-api 3.1.0 + + + com.microsoft.cognitiveservices.speech + client-sdk + 1.34.0 + + + + + info.debatty + java-string-similarity + RELEASE + + diff --git a/src/main/java/controller/ExerciseController.java b/src/main/java/controller/ExerciseController.java index b4fba26..d7fd726 100644 --- a/src/main/java/controller/ExerciseController.java +++ b/src/main/java/controller/ExerciseController.java @@ -18,7 +18,5 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) ExerciseGlossary ex = em.getExercise(Integer.parseInt(id)); request.getSession().setAttribute("exercise", ex); response.sendRedirect(request.getContextPath() + "/JSP/exercise.jsp"); - - request.getSession().setAttribute("exerciseID", id); //TODO: RIMUOVI } } \ No newline at end of file diff --git a/src/main/java/controller/ExerciseEvaluator.java b/src/main/java/controller/ExerciseEvaluator.java index 0868dcb..17ce3b7 100644 --- a/src/main/java/controller/ExerciseEvaluator.java +++ b/src/main/java/controller/ExerciseEvaluator.java @@ -2,9 +2,10 @@ import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; +import info.debatty.java.stringsimilarity.Levenshtein; import model.entity.ExerciseGlossary; import model.service.exercise.ExerciseManager; -import model.service.exercise.ExerciseManagerInterface; +import model.service.exercise.SpeechRecognition; import javax.servlet.ServletException; import javax.servlet.annotation.MultipartConfig; @@ -17,6 +18,8 @@ import java.sql.SQLException; import java.util.Map; import java.util.Set; +import java.util.concurrent.ExecutionException; + @WebServlet("/exerciseEvaluator") @MultipartConfig @@ -26,22 +29,25 @@ protected void doPost(HttpServletRequest request, HttpServletResponse response) String contentType = request.getContentType(); ExerciseManager em = new ExerciseManager(); - int exerciseId = Integer.parseInt((String) s.getAttribute("exerciseID")); - //int userId = Integer.parseInt((String) s.getAttribute("id")); - //Date d = Date.valueOf((String) s.getAttribute("insertDate"); - - Date d = Date.valueOf("2024-01-07"); //TODO: prendilo dalla session - int userId = 8; //TODO: prendilo dalla session + int exerciseId = (int) s.getAttribute("exerciseID"); + int userId = (int) s.getAttribute("id"); + Date d = (Date) s.getAttribute("insertDate"); + int score; if ("application/json".equals(contentType)) { - int score = evaluateNoAudio(exerciseId, userId, d); - em.saveEvaluation(userId, exerciseId, d, score); - } //else { - // evaluateAudio(request); - // } + score = evaluateNoAudio(exerciseId, userId, d); + } else { + try { + score = evaluateAudio(exerciseId, userId, d); + } catch (ExecutionException | InterruptedException e) { + throw new RuntimeException(e); + } + } + em.saveEvaluation(userId, exerciseId, d, score); } + private int evaluateNoAudio(int exerciseId, int userId, Date date){ Gson gson = new Gson(); @@ -49,7 +55,7 @@ private int evaluateNoAudio(int exerciseId, int userId, Date date){ String executionJSON = getJSONfromBlob(exerciseId, userId, date); String type = baseExercise.getType(); - int score = 0; + int score; switch (type) { case "CROSSWORD" -> { @@ -144,8 +150,36 @@ private int evaluateCrossword(String[][] execution, String[][] solution) { return (int)((right /total)*100); } - // private void evaluateAudio(HttpServletRequest r){ - // //TODO: chiamata all'adapter, per python che valuta l'audio - // } + private int evaluateAudio(int exerciseId, int userId, Date d) throws IOException, ExecutionException, InterruptedException { + SpeechRecognition s = new SpeechRecognition(); + Levenshtein l = new Levenshtein(); + Gson g = new Gson(); + ExerciseGlossary baseExercise = new ExerciseManager().getExercise(exerciseId); + String solution = g.fromJson(baseExercise.getInitialState(), String.class); + + InputStream audioExecution = getAudiofromBlob(exerciseId, userId, d); + String audioText = null; + if (audioExecution!=null){ + audioText = s.azureSTT(audioExecution); + } + System.out.println(audioText); + System.out.println("\n"+solution); + + if(audioText != null){ + double distance = l.distance(solution, audioText); + double result = ((solution.length()-distance)/solution.length())*100; + return (int) Math.round(result); + } + + return 0; + } + private InputStream getAudiofromBlob(int exerciseId, int userId, Date d){ + Blob executionBlob = new ExerciseManager().getExecution(exerciseId, userId, d); + try (InputStream audioInputStream = executionBlob.getBinaryStream()) { + return audioInputStream; + } catch (SQLException | IOException e) { + throw new RuntimeException(e); + } + } } \ No newline at end of file diff --git a/src/main/java/controller/ExerciseLogger.java b/src/main/java/controller/ExerciseLogger.java index 2d589e3..3c6c21b 100644 --- a/src/main/java/controller/ExerciseLogger.java +++ b/src/main/java/controller/ExerciseLogger.java @@ -52,13 +52,13 @@ private void handleNoAudioExercise(HttpServletRequest request) throws IOExceptio } private void handleAudioExercise(HttpServletRequest request) throws ServletException, IOException { - InputStream audioInputStream; try { Part audioPart = request.getPart("audioFile"); - audioInputStream = audioPart.getInputStream(); - Blob audioBlob = new SerialBlob(IOUtils.toByteArray(audioInputStream)); - saveInDB(request, audioBlob); + try (InputStream audioInputStream = audioPart.getInputStream()) { + Blob audioBlob = new SerialBlob(IOUtils.toByteArray(audioInputStream)); + saveInDB(request, audioBlob); + } } catch (SQLException e) { throw new RuntimeException(e); } @@ -67,12 +67,10 @@ private void handleAudioExercise(HttpServletRequest request) throws ServletExcep private boolean saveInDB(HttpServletRequest request, Blob execution){ ExerciseManager em = new ExerciseManager(); HttpSession session = request.getSession(); -// int userId = Integer.parseInt((String) session.getAttribute("userId")); - int exerciseId = Integer.parseInt((String) session.getAttribute("exerciseID")); -// Date insertDate = Date.valueOf((String) session.getAttribute("insertDate")); -//TODO: RIMUOVI I COMMENTI - int userId = 8; - Date insertDate = Date.valueOf("2024-01-07"); + int userId = (int) session.getAttribute("id"); + int exerciseId = (int) session.getAttribute("exerciseID"); + Date insertDate = (Date) session.getAttribute("insertDate"); + return em.saveExecution(userId, exerciseId, insertDate, execution); } } \ No newline at end of file diff --git a/src/main/java/model/service/exercise/SpeechRecognition.java b/src/main/java/model/service/exercise/SpeechRecognition.java new file mode 100644 index 0000000..46581bb --- /dev/null +++ b/src/main/java/model/service/exercise/SpeechRecognition.java @@ -0,0 +1,109 @@ +package model.service.exercise; + +import com.microsoft.cognitiveservices.speech.*; +import com.microsoft.cognitiveservices.speech.audio.AudioConfig; +import java.io.*; +import java.nio.file.*; +import java.util.Arrays; +import java.util.List; +import java.util.Properties; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; + + +public class SpeechRecognition { + private static final String AZURE_PROPERTIES = "/azure.properties"; + private static String speechKey; + private static String speechRegion; + + public SpeechRecognition(){ + Properties azureProps = loadProps(); + speechRegion = azureProps.getProperty("azure.region"); + speechKey = azureProps.getProperty("azure.key"); + } + + + public String azureSTT(InputStream audio) throws InterruptedException, ExecutionException, IOException { + SpeechConfig speechConfig = SpeechConfig.fromSubscription(speechKey, speechRegion); + speechConfig.setSpeechRecognitionLanguage("it-It"); + + AudioConfig audioConfig = AudioConfig.fromWavFileInput(generateFile(audio)); + SpeechRecognizer speechRecognizer = new SpeechRecognizer(speechConfig, audioConfig); + + Future task = speechRecognizer.recognizeOnceAsync(); + SpeechRecognitionResult speechRecognitionResult = task.get(); + + String result = null; + + if (speechRecognitionResult.getReason() == ResultReason.RecognizedSpeech) { + result = ("RECOGNIZED: Text= " + speechRecognitionResult.getText()); + } + else if (speechRecognitionResult.getReason() == ResultReason.NoMatch) { + result = ("NOMATCH: Speech could not be recognized."); + } + return result; + } + + public String generateFile(InputStream inputAudio) throws IOException { + //Crea temporaneamente il file creato dal DB + File tempFile = File.createTempFile("tempAudio", ".opus"); + try (FileOutputStream fos = new FileOutputStream(tempFile)) { + byte[] buffer = new byte[1024]; + int bytesRead; + while ((bytesRead = inputAudio.read(buffer)) != -1) { + fos.write(buffer, 0, bytesRead); + } + } + //Ottieni il path dell'output basandoti sul file creato + Path outputPath = Paths.get(tempFile.getPath()).getParent(); + String path = outputPath.toString() + "\\outputJava.wav"; + + //Controlla che non esista già un file + try { + // Use the delete method from Files class to delete the file + Files.delete(Paths.get(path)); + } catch (IOException e) { + System.err.println("Error deleting the file: " + e.getMessage()); + } + + + List command = Arrays.asList( + "ffmpeg", + "-i", tempFile.getPath(), + "-ar", "16000", + "-ac", "1", + "-acodec", "pcm_s16le", + path + ); + + try { + ProcessBuilder processBuilder = new ProcessBuilder(command); + Process process = processBuilder.start(); + + BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); + String line; + while ((line = reader.readLine()) != null) { + System.out.println(line); + } + int exitCode = process.waitFor(); + if(exitCode != 0){ + System.err.println("\nExited with error code : " + exitCode); + } + } catch (IOException | InterruptedException e) { + e.printStackTrace(); + } + + return path; + } + + private Properties loadProps() { + Properties props = new Properties(); + try (InputStream input = SpeechRecognition.class.getResourceAsStream(AZURE_PROPERTIES)) { + props.load(input); + } catch (IOException e) { + System.out.println(e.getMessage()); + } + + return props; + } +} \ No newline at end of file diff --git a/src/main/resources/azure.properties b/src/main/resources/azure.properties new file mode 100644 index 0000000..73bf85a --- /dev/null +++ b/src/main/resources/azure.properties @@ -0,0 +1,2 @@ +azure.key=4dc85598a1f64a54a190c8e6e0eddb0b +azure.region=westeurope \ No newline at end of file diff --git a/src/main/webapp/JS/exercise.js b/src/main/webapp/JS/exercise.js index ff4d476..95e92d5 100644 --- a/src/main/webapp/JS/exercise.js +++ b/src/main/webapp/JS/exercise.js @@ -29,10 +29,11 @@ function startUp(exerciseIS){ let mediaRecorder; let audioChunks = []; +let timeoutID; function micPreparation(){ if(navigator.mediaDevices && navigator.mediaDevices.getUserMedia) { - navigator.mediaDevices.getUserMedia({ audio: true }) + navigator.mediaDevices.getUserMedia({ audio: true }) .then(function(stream) { mediaRecorder = new MediaRecorder(stream); @@ -43,7 +44,7 @@ function micPreparation(){ }; mediaRecorder.onstop = function() { - let audioBlob = new Blob(audioChunks, { type: 'audio/wav' }); + let audioBlob = new Blob(audioChunks, { type: 'audio/opus' }); let audioUrl = URL.createObjectURL(audioBlob); $("#audioPlayer").attr("src", audioUrl); @@ -77,9 +78,15 @@ function micPreparation(){ mediaRecorder.start(); $("#startRecord").hide(); $("#stopRecord").show(); + + // Set a timeout to stop recording after 33 seconds + timeoutID = setTimeout(() => { + $("#stopRecord").click(); + }, 33000); }); $("#stopRecord").click(function() { + clearTimeout(timeoutID); mediaRecorder.stop(); $("#stopRecord").hide(); $("#audioDiv").show(); From 9225f26d3cb43f13a07a5d288d2095fdca8c03b9 Mon Sep 17 00:00:00 2001 From: "ms@Nicro" Date: Mon, 8 Jan 2024 17:25:02 +0100 Subject: [PATCH 3/3] Implemented Completion Date after evaluation --- src/main/java/model/DAO/DAOExercise.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/model/DAO/DAOExercise.java b/src/main/java/model/DAO/DAOExercise.java index d5e9299..0899039 100644 --- a/src/main/java/model/DAO/DAOExercise.java +++ b/src/main/java/model/DAO/DAOExercise.java @@ -145,7 +145,7 @@ public boolean setExerciseExecution(int userID, int exerciseID, Date insertDate, } public boolean setExerciseEvaluation(int userID, int exerciseID, Date insertDate, int evaluation) { - String query = "UPDATE exercise SET Evaluation = ? WHERE ID_user = ? AND ID_exercise = ? AND InsertionDate = ?;"; + String query = "UPDATE exercise SET Evaluation = ? , CompletionDate = CURRENT_DATE WHERE ID_user = ? AND ID_exercise = ? AND InsertionDate = ?;"; PreparedStatement preparedStatement = null; try {