diff --git a/backend/README.md b/backend/README.md index 9b8f781da50c9e37ed0cff46a40ea69e0c2c4a28..8e995ed35798904d6a4fa4921f706ff6a3d48a82 100644 --- a/backend/README.md +++ b/backend/README.md @@ -11,7 +11,7 @@ Runs on port 8000 This project is a simple quiz converter that takes a DOCX file and converts it to a Moodle XML format or to the Coursera DOCX depending on which endpoint is used. -Currently, question description nor answer can't start with the words "question", "feedback" nor "\t". +Currently, question description can't start with the words "question", "feedback" nor "default feedback". Feedback doesn't support pictures. diff --git a/backend/src/main/java/com/quiz/converter/handlers/FeedbackHandler.java b/backend/src/main/java/com/quiz/converter/handlers/FeedbackHandler.java index 42269f4713f73a3d3d2ba40309876bde3f26c705..e77b2b57065dddcddf848f59a682ae7d7bff0b43 100644 --- a/backend/src/main/java/com/quiz/converter/handlers/FeedbackHandler.java +++ b/backend/src/main/java/com/quiz/converter/handlers/FeedbackHandler.java @@ -15,7 +15,7 @@ public class FeedbackHandler { public void add(String text, ParagraphType paragraphType) { switch (paragraphType) { case DEFAULT_FEEDBACK -> state.setDefaultFeedback(text.replaceAll("^\s*([dD][eE][fF][aA][uU][lL][tT])\s*([fF][eE][eE][dD][bB][aA][cC][kK])\s*(:)", "").strip()); - case FEEDBACK -> { + case ANSWER_OPTION_FEEDBACK -> { var feedbackText = text.toLowerCase().replace("feedback", "").strip().replace(":", "").strip(); state.getAnswerOptions().get(state.getAnswerOptions().size() - 1).setFeedback(Optional.of(feedbackText)); } diff --git a/backend/src/main/java/com/quiz/converter/models/enums/ParagraphType.java b/backend/src/main/java/com/quiz/converter/models/enums/ParagraphType.java index b1ae58cf78a9cc50082f86a3c06d8ddb98d9688c..0082334182cfd8d45f12fd12ea58a2320e8ff67b 100644 --- a/backend/src/main/java/com/quiz/converter/models/enums/ParagraphType.java +++ b/backend/src/main/java/com/quiz/converter/models/enums/ParagraphType.java @@ -1,7 +1,7 @@ package com.quiz.converter.models.enums; public enum ParagraphType { - FEEDBACK, + ANSWER_OPTION_FEEDBACK, QUESTION_DESCRIPTION, ANSWER_OPTION, QUESTION_DETAILS, @@ -9,3 +9,4 @@ public enum ParagraphType { DEFAULT_FEEDBACK, UNKNOWN } + diff --git a/backend/src/main/java/com/quiz/converter/models/enums/QuestionErrorType.java b/backend/src/main/java/com/quiz/converter/models/enums/QuestionErrorType.java index 0c6d301e0c823d67dc6f51b792acc0e7b2e9071e..8e5f2128fb4ad2f7323a14b78757b9d7422247d3 100644 --- a/backend/src/main/java/com/quiz/converter/models/enums/QuestionErrorType.java +++ b/backend/src/main/java/com/quiz/converter/models/enums/QuestionErrorType.java @@ -5,5 +5,6 @@ public enum QuestionErrorType { NO_ANSWER_OPTIONS_FOUND, NO_CORRECT_ANSWER_FOUND, ANSWER_OPTIONS_DONT_MATCH_TYPE, - INVALID_REGEX + INVALID_REGEX, + NO_ANSWER_OPTION_FOR_FEEDBACK } diff --git a/backend/src/main/java/com/quiz/converter/services/CourseraDocxCreatorService.java b/backend/src/main/java/com/quiz/converter/services/CourseraDocxCreatorService.java index f64d880dd97dc23e8638218b448435f2278b68c7..1773e6aebd8798861c74a36f4711cac35dcc29e4 100644 --- a/backend/src/main/java/com/quiz/converter/services/CourseraDocxCreatorService.java +++ b/backend/src/main/java/com/quiz/converter/services/CourseraDocxCreatorService.java @@ -108,7 +108,12 @@ public class CourseraDocxCreatorService { var pictureRun = pictureParagraph.createRun(); var pictureData = Base64.getDecoder().decode(p.base64()); try { - pictureRun.addPicture(new ByteArrayInputStream(pictureData), p.type(), p.name(), Units.toEMU(p.width()), Units.toEMU(p.height())); + pictureRun.addPicture( + new ByteArrayInputStream(pictureData), + p.type(), + p.name(), + Units.toEMU(p.width()), + Units.toEMU(p.height())); } catch (InvalidFormatException | IOException e) { throw new RuntimeException(e); } diff --git a/backend/src/main/java/com/quiz/converter/services/FileUploadService.java b/backend/src/main/java/com/quiz/converter/services/FileUploadService.java index 54d12a99a7072e5b5631bc04a7884c4971c289a8..764b419d882e78b9134158655547a323b912f1e9 100644 --- a/backend/src/main/java/com/quiz/converter/services/FileUploadService.java +++ b/backend/src/main/java/com/quiz/converter/services/FileUploadService.java @@ -5,10 +5,9 @@ import com.quiz.converter.handlers.QuestionHandler; import com.quiz.converter.handlers.QuestionValidationHandler; import com.quiz.converter.models.*; import com.quiz.converter.models.enums.ParagraphType; +import com.quiz.converter.models.enums.QuestionErrorType; import com.quiz.converter.models.enums.QuestionWarningType; -import org.apache.poi.xwpf.usermodel.XWPFDocument; -import org.apache.poi.xwpf.usermodel.XWPFParagraph; -import org.apache.poi.xwpf.usermodel.XWPFSDT; +import org.apache.poi.xwpf.usermodel.*; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; @@ -55,7 +54,7 @@ public class FileUploadService { descriptionPictures.addAll(paragraphPictures); state.setPreviousParagraphType(paragraphType); } - case FEEDBACK, DEFAULT_FEEDBACK -> { + case ANSWER_OPTION_FEEDBACK, DEFAULT_FEEDBACK -> { var feedbackHandler = new FeedbackHandler(state); feedbackHandler.add(text, paragraphType); state.setPreviousParagraphType(paragraphType); @@ -88,7 +87,12 @@ public class FileUploadService { if (text.replaceAll("\t", "").isEmpty() || text.replaceAll("\n", "").isEmpty()) return ParagraphType.EMPTY_TEXT; var lowerCaseText = text.toLowerCase().strip(); if (lowerCaseText.matches("\s*(question).*")) return ParagraphType.QUESTION_DETAILS; - if (lowerCaseText.matches("\s*(feedback).*")) return ParagraphType.FEEDBACK; + if (lowerCaseText.matches("\s*(feedback).*")) { + if (state.getPreviousParagraphType().equals(ParagraphType.ANSWER_OPTION)) + return ParagraphType.ANSWER_OPTION_FEEDBACK; + state.getErrors().add(QuestionErrorType.NO_ANSWER_OPTION_FOR_FEEDBACK); + return ParagraphType.UNKNOWN; + } if (lowerCaseText.matches(".*(default)\s*(feedback).*")) return ParagraphType.DEFAULT_FEEDBACK; if (lowerCaseText.matches("(\\s*\\**\\s*)*[a-zA-Z\\d]\\s*[:)].*")) return ParagraphType.ANSWER_OPTION; if (state.getPreviousParagraphType().equals(ParagraphType.QUESTION_DETAILS)) diff --git a/backend/src/main/resources/application.properties b/backend/src/main/resources/application.properties index 5ee314c7e5e5c3a5287a5da528ae02a575bcabb4..1a93679716174eb2b1668a59df54fd2076abe7a5 100644 --- a/backend/src/main/resources/application.properties +++ b/backend/src/main/resources/application.properties @@ -1 +1,3 @@ server.port=8000 +spring.servlet.multipart.max-file-size=10MB +spring.servlet.multipart.max-request-size=10MB diff --git a/frontend/app/data/en.json b/frontend/app/data/en.json index 8a4902ccdf92a7913fcd47a35326b8584bd35be5..70c74d1040a76cea536e396d64c78ed7771e8ad6 100644 --- a/frontend/app/data/en.json +++ b/frontend/app/data/en.json @@ -45,7 +45,8 @@ "NO_ANSWER_OPTIONS_FOUND": "No answer options found", "NO_CORRECT_ANSWER_FOUND": "No correct answer found", "ANSWER_OPTIONS_DONT_MATCH_TYPE": "Answer options don't match type", - "INVALID_REGEX": "Invalid regex" + "INVALID_REGEX": "Invalid regex", + "NO_ANSWER_OPTION_FOR_FEEDBACK": "Feedback for the answer does not have an answer option before it" }, "warnings": { "CHECK_QUESTION_NAME": "Couldn't find the end of the name. Name should be followed by hypen (-).",