From b398c36cb72c7b8efc153fdd012cb363d034fa01 Mon Sep 17 00:00:00 2001 From: Oisin Date: Sun, 15 Jun 2025 12:10:05 +0100 Subject: [PATCH 01/21] Added new lesson and retry lesson buttons --- src/main/resources/templates/result.html | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/main/resources/templates/result.html b/src/main/resources/templates/result.html index 57667c0..3d3bbb9 100644 --- a/src/main/resources/templates/result.html +++ b/src/main/resources/templates/result.html @@ -37,9 +37,14 @@

-
- +
+ + +
+ +
+
From 78de761e88d70ad863e291366e7a382b4c53de16 Mon Sep 17 00:00:00 2001 From: Oisin Date: Sun, 15 Jun 2025 12:10:27 +0100 Subject: [PATCH 02/21] Added stylings for new lesson and retry lesson buttons --- src/main/resources/static/css/styles.css | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/resources/static/css/styles.css b/src/main/resources/static/css/styles.css index 8125076..de5bcef 100644 --- a/src/main/resources/static/css/styles.css +++ b/src/main/resources/static/css/styles.css @@ -78,4 +78,9 @@ a { #lessonNCorrectMessage { padding-bottom:20px; +} + +#buttonContainer, #newLessonButtonForm, #retryLessonButtonForm, #newLessonButton, #retryLessonButton { + display: inline-block; + margin-left: 5px; } \ No newline at end of file From 202e53ba8c5c794c33c32ce8c5fd553331d24741 Mon Sep 17 00:00:00 2001 From: Oisin Date: Sun, 15 Jun 2025 12:11:22 +0100 Subject: [PATCH 03/21] Updated controller funcitonality to index on questions using lesson question id. Added logic to retry and overwrite previous lesson questions and results --- .../controller/ApplicationController.java | 114 ++++++++++++++---- 1 file changed, 92 insertions(+), 22 deletions(-) diff --git a/src/main/java/com/czechtutor/controller/ApplicationController.java b/src/main/java/com/czechtutor/controller/ApplicationController.java index 3ae11ef..cc37130 100644 --- a/src/main/java/com/czechtutor/controller/ApplicationController.java +++ b/src/main/java/com/czechtutor/controller/ApplicationController.java @@ -153,7 +153,7 @@ public String createLesson(@ModelAttribute LessonModel lessonModel) { lessonService.save(lessonModel); // redirect to view String path = String.valueOf(lessonModel.getLessonId()); - String view = "/lesson/" + path; + String view = "/newLessonQuestion/" + path; logger.info(lessonModel.getLessonPayload()); return "redirect:" + view; } @@ -165,8 +165,8 @@ public String createLesson(@ModelAttribute LessonModel lessonModel) { * @param lessonId the generated lesson id path variable * @return redirects to the lesson template with the generated lesson id */ - @GetMapping(value = "/lesson/{lessonId}") - public String createQuestion(@PathVariable("lessonId") Integer lessonId) { + @GetMapping(value = "/newLessonQuestion/{lessonId}") + public String createLessonQuestion(@PathVariable("lessonId") Integer lessonId) { // check NQuestions for lessonId against database Integer nQuestions = lessonService.get(lessonId).getNQuestions(); Integer nLessonQuestions = questionService.findByLessonId(lessonId).size(); @@ -176,9 +176,10 @@ public String createQuestion(@PathVariable("lessonId") Integer lessonId) { LessonModel lessonModel = lessonService.get(lessonId); QuestionModel questionModel = questionService.create(lessonModel, null); questionService.save(questionModel); - Integer questionId = questionModel.getQuestionId(); + // Integer questionId = questionModel.getQuestionId(); + Integer lessonQuestionId = questionModel.getLessonQuestionId(); // redirect to view - String path = String.valueOf(lessonId) + "/" + String.valueOf(questionId); + String path = String.valueOf(lessonId) + "/" + String.valueOf(lessonQuestionId); String view = "/lesson/" + path; logger.info(view); logger.info(questionModel.getQuestionPayload()); @@ -215,11 +216,13 @@ public String createQuestion(@PathVariable("lessonId") Integer lessonId) { * Thymeleaf * @return the lesson template for the given lesson id and question id */ - @GetMapping(value = "/lesson/{lessonId}/{questionId}") - public String getLessonPage(@PathVariable("lessonId") Integer lessonId, @PathVariable("questionId") Integer questionId, Model model) { + @GetMapping(value = "/lesson/{lessonId}/{lessonQuestionId}") + public String getLessonPage(@PathVariable("lessonId") Integer lessonId, @PathVariable("lessonQuestionId") Integer lessonQuestionId, Model model) { logger.info("~~~~~ Redirecting to lesson."); - QuestionModel questionModel = questionService.get(questionId); - String path = String.valueOf(lessonId) + "/" + String.valueOf(questionId); + // pull lesson model for lesson id and lesson question id + QuestionModel questionModel = questionService.getQuestionByLessonQuestionIds(lessonId, lessonQuestionId); + // QuestionModel questionModel = questionService.get(questionId); + String path = String.valueOf(lessonId) + "/" + String.valueOf(lessonQuestionId); model.addAttribute("questionModel", questionModel); model.addAttribute("answerModel", new AnswerModel()); model.addAttribute("path", path); @@ -236,21 +239,68 @@ public String getLessonPage(@PathVariable("lessonId") Integer lessonId, @PathVar * @param answerModel the completed answer model form * @return redirects to the lesson template with the lesson id */ - @PostMapping(value = "/lesson/{lessonId}/{questionId}") - public String createAnswer(@PathVariable("lessonId") Integer lessonId, @PathVariable("questionId") Integer questionId, @ModelAttribute AnswerModel answerModel) { + @PostMapping(value = "/lesson/{lessonId}/{lessonQuestionId}") + public String createAnswer(@PathVariable("lessonId") Integer lessonId, @PathVariable("lessonQuestionId") Integer lessonQuestionId, @ModelAttribute AnswerModel answerModel) { logger.info("~~~~~ Creating answer"); + // pull lesson model for lesson id and lesson question id + QuestionModel questionModel = questionService.getQuestionByLessonQuestionIds(lessonId, lessonQuestionId); + // QuestionModel questionModel = questionService.get(questionId); // generate a answer - QuestionModel questionModel = questionService.get(questionId); + answerModel.setQuestionId(questionModel.getQuestionId()); answerModel.setCorrect(answerService.isCorrect(questionModel, answerModel)); answerModel.setDateTime(LocalDateTime.now()); answerModel.setDateTimeHash(utilityService.MD5DateTimeHash(answerModel.getDateTime())); + // check if answer already exists for the question id + if (answerService.existsById(questionModel.getQuestionId())) { + // if ot does assign answer id and overwrite existing result + answerModel.setAnswerId(questionModel.getQuestionId()); + } answerService.save(answerModel); - // redirect to view - String path = String.valueOf(lessonId); - String view = "/lesson/" + path; - logger.info(view); - logger.info(answerModel.getAnswerPayload()); - return "redirect:" + view; + // check NQuestions for lessonId against database + Integer nQuestions = lessonService.get(lessonId).getNQuestions(); + Integer nLessonQuestions = questionService.findByLessonId(lessonId).size(); + Boolean allLessonQuestionsExist = nLessonQuestions.equals(nQuestions); + if (!allLessonQuestionsExist) { + // redirect to view + String path = String.valueOf(lessonId); + String view = "/newLessonQuestion/" + path; + logger.info(view); + logger.info(answerModel.getAnswerPayload()); + return "redirect:" + view; + } else if (lessonQuestionId < nQuestions) { + // pull the next lesson question model + Integer nextLessonQuestionId = lessonQuestionId + 1; + QuestionModel nextQuestionModel = questionService.getQuestionByLessonQuestionIds(lessonId, nextLessonQuestionId); + // redirect to view + String path = String.valueOf(lessonId) + "/" + String.valueOf(lessonQuestionId + 1); + String view = "/lesson/" + path; + logger.info(view); + logger.info(nextQuestionModel.getQuestionPayload()); + return "redirect:" + view; + } else { + logger.info("~~~~~ Creating result."); + // define decimal formatter + DecimalFormat decimalFormatter = new DecimalFormat("#.##"); + decimalFormatter.setRoundingMode(RoundingMode.HALF_EVEN); + // generate the results of the lesson + ArrayList lessonAnswers = answerService.findByLessonId(lessonId); + Integer nCorrect = resultService.countTotalCorrect(lessonAnswers); + Float score = Float.valueOf(decimalFormatter.format(Float.valueOf(nCorrect) / Float.valueOf(nQuestions) * 100)); + // create a result + ResultModel resultModel = resultService.create(lessonId, nCorrect, score); + // check if an existing results model already exists for the lesson id + if (resultService.existsByLessonId(lessonId)) { + // overwrite the result id with the result id from the result model corresponding to the existing lesson id + resultModel.setResultId(resultService.findByLessonId(lessonId).getResultId()); + } + resultService.save(resultModel); + // redirect to view + String path = String.valueOf(lessonId); + String view = "/result/" + path; + logger.info(view); + logger.info(resultModel.getResultPayload()); + return "redirect:" + view; + } } /** @@ -305,9 +355,9 @@ public String redirectResulttoHome(@PathVariable("lessonId") Integer lessonId) { * @return redirects to the lesson template with the same lesson * configurations */ - @PostMapping(value = "/resultRedo/{lessonId}") - public String redirectResulttoLesson(@PathVariable("lessonId") Integer lessonId) { - logger.info("~~~~~ Creating lesson"); + @PostMapping(value = "/resultNew/{lessonId}") + public String redirectResultToNewLesson(@PathVariable("lessonId") Integer lessonId) { + logger.info("~~~~~ Creating new lesson"); // generate a new lesson from the current lesson LessonModel currentLessonModel = lessonService.get(lessonId); LessonModel newLessonModel = new LessonModel(); @@ -321,9 +371,29 @@ public String redirectResulttoLesson(@PathVariable("lessonId") Integer lessonId) lessonService.save(newLessonModel); // redirect to view String path = String.valueOf(newLessonModel.getLessonId()); - String view = "/lesson/" + path; + String view = "/newLessonQuestion/" + path; logger.info(newLessonModel.getLessonPayload()); return "redirect:" + view; } + /** + *

+ * Posts user input from the result template page

+ * + * @param lessonId the generated lesson id path variable + * @return redirects to the lesson template with the same lesson + * configurations + */ + @PostMapping(value = "/resultRetry/{lessonId}") + public String redirectResultToRetryLesson(@PathVariable("lessonId") Integer lessonId) { + logger.info("~~~~~ Retrying lesson"); + // generate a new lesson from the current lesson + LessonModel currentLessonModel = lessonService.get(lessonId); + // redirect to view + String path = String.valueOf(lessonId) + "/1"; + String view = "/lesson/" + path; + logger.info(currentLessonModel.getLessonPayload()); + return "redirect:" + view; + } + } From ed9e3c3d4b6f39dec8b1f4f2319698c29e148994 Mon Sep 17 00:00:00 2001 From: Oisin Date: Sun, 15 Jun 2025 12:12:05 +0100 Subject: [PATCH 04/21] Added lesson question id to question model --- .../com/czechtutor/model/QuestionModel.java | 32 ++++++++++++++++--- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/czechtutor/model/QuestionModel.java b/src/main/java/com/czechtutor/model/QuestionModel.java index 2e6034a..a1a5e16 100644 --- a/src/main/java/com/czechtutor/model/QuestionModel.java +++ b/src/main/java/com/czechtutor/model/QuestionModel.java @@ -18,6 +18,7 @@ public class QuestionModel { @Id private Integer questionId; private Integer lessonId; + private Integer lessonQuestionId; private String phrase; private String option1; private String option2; @@ -38,6 +39,7 @@ public void set(HashMap payload) { // set the class objects //this.questionId = (Integer) payload.get("questionId"); this.lessonId = (Integer) payload.get("lessonId"); + this.lessonQuestionId = (Integer) payload.get("lessonQuestionId"); this.phrase = (String) payload.get("phrase"); this.option1 = (String) payload.get("option1"); this.option2 = (String) payload.get("option2"); @@ -60,6 +62,7 @@ public HashMap getQuestionPayload() { HashMap questionPayload = new HashMap<>(); questionPayload.put("questionId", questionId); questionPayload.put("lessonId", lessonId); + questionPayload.put("lessonQuestionId", lessonQuestionId); questionPayload.put("phrase", phrase); questionPayload.put("option1", option1); questionPayload.put("option2", option2); @@ -93,9 +96,9 @@ public void setQuestionId(Integer questionId) { /** *

- * Gets the question lesson id attribute of a question model

+ * Gets the lesson id attribute of a question model

* - * @return the question lesson id attribute + * @return the lesson id attribute */ public Integer getLessonId() { return lessonId; @@ -103,14 +106,35 @@ public Integer getLessonId() { /** *

- * Sets the question lesson id attribute of a question model

+ * Sets the lesson id attribute of a question model

* - * @param lessonId the question lesson id attribute + * @param lessonId the lesson id attribute */ public void setLessonId(Integer lessonId) { this.lessonId = lessonId; } + + /** + *

+ * Gets the question lesson id attribute of a question model

+ * + * @return the question lesson id attribute + */ + public Integer getLessonQuestionId() { + return lessonQuestionId; + } + + /** + *

+ * Sets the question lesson id attribute of a question model

+ * + * @param lessonId the question lesson id attribute + */ + public void setQuestionLessonId(Integer lessonQuestionId) { + this.lessonQuestionId = lessonQuestionId; + } + /** *

* Gets the question phrase attribute of a question model

From 89109b594f350d0db386ff3a87fd19f8fe24b6d4 Mon Sep 17 00:00:00 2001 From: Oisin Date: Sun, 15 Jun 2025 12:12:57 +0100 Subject: [PATCH 05/21] Added custom sql query to pull question using lesson id and question lesson id --- .../repository/crud/QuestionCrudRepository.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/main/java/com/czechtutor/repository/crud/QuestionCrudRepository.java b/src/main/java/com/czechtutor/repository/crud/QuestionCrudRepository.java index ce57895..0401400 100644 --- a/src/main/java/com/czechtutor/repository/crud/QuestionCrudRepository.java +++ b/src/main/java/com/czechtutor/repository/crud/QuestionCrudRepository.java @@ -2,7 +2,9 @@ import java.util.ArrayList; +import org.springframework.data.jdbc.repository.query.Query; import org.springframework.data.repository.CrudRepository; +import org.springframework.data.repository.query.Param; import com.czechtutor.model.QuestionModel; @@ -24,4 +26,11 @@ public interface QuestionCrudRepository extends CrudRepository findByLessonId(String LessonId); + public static final String GET_QUESTION_BY_LESSON_QUESTION_IDS_QUERY = """ + select * from questions where lesson_id = :#{#lessonId.intValue()} and lesson_question_id = :#{#LessonQuestionId.intValue()} + """; + + @Query(GET_QUESTION_BY_LESSON_QUESTION_IDS_QUERY) + QuestionModel getQuestionByLessonQuestionIds(@Param("lessonId") Integer lessonId, @Param("LessonQuestionId") Integer LessonQuestionId); + } From 6538edf658807ab88aee7220abe62996b65728e2 Mon Sep 17 00:00:00 2001 From: Oisin Date: Sun, 15 Jun 2025 12:13:33 +0100 Subject: [PATCH 06/21] Added custom function to check if results exist for a given lesson id --- .../czechtutor/repository/crud/ResultCrudRepository.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/main/java/com/czechtutor/repository/crud/ResultCrudRepository.java b/src/main/java/com/czechtutor/repository/crud/ResultCrudRepository.java index ea12d35..f655e8f 100644 --- a/src/main/java/com/czechtutor/repository/crud/ResultCrudRepository.java +++ b/src/main/java/com/czechtutor/repository/crud/ResultCrudRepository.java @@ -22,4 +22,13 @@ public interface ResultCrudRepository extends CrudRepository + * Determines if a results model exists for a lesson id

+ * + * @param LessonId the lesson id to find if results exist for + * @return whether the result model exists + */ + Boolean existsByLessonId(String LessonId); + } From 9740f28e98497d6ebdaf2c63602717eaa5476d3b Mon Sep 17 00:00:00 2001 From: Oisin Date: Sun, 15 Jun 2025 12:14:39 +0100 Subject: [PATCH 07/21] Extending answer service to include existsById look up --- .../java/com/czechtutor/service/AnswerService.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/main/java/com/czechtutor/service/AnswerService.java b/src/main/java/com/czechtutor/service/AnswerService.java index 18893c8..8faddba 100644 --- a/src/main/java/com/czechtutor/service/AnswerService.java +++ b/src/main/java/com/czechtutor/service/AnswerService.java @@ -69,4 +69,15 @@ public ArrayList findByLessonId(Integer lessonId) { return answerCrudRepository.findByLessonId(String.valueOf(lessonId)); } + /** + *

+ * Determines if an answer already exists by an answer id

+ * + * @param answerId the answer id to find if exists + * @return whether the answer model exists or not + */ + public Boolean existsById(Integer answerId) { + return answerCrudRepository.existsById(answerId); + } + } From 6d9b037dbdc6123c09c7dcc8565df2fa91f49352 Mon Sep 17 00:00:00 2001 From: Oisin Date: Sun, 15 Jun 2025 12:15:06 +0100 Subject: [PATCH 08/21] Extending answer service to include existsById and existsByLessonId look ups --- .../com/czechtutor/service/ResultService.java | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/main/java/com/czechtutor/service/ResultService.java b/src/main/java/com/czechtutor/service/ResultService.java index 302dce3..a36af3c 100644 --- a/src/main/java/com/czechtutor/service/ResultService.java +++ b/src/main/java/com/czechtutor/service/ResultService.java @@ -111,4 +111,26 @@ public ResultModel findByLessonId(Integer lessonId) { return resultCrudRepository.findByLessonId(String.valueOf(lessonId)); } + /** + *

+ * Determines if a result already exists by a result id

+ * + * @param resultId the result id to find if exists + * @return whether the result model exists or not + */ + public Boolean existsById(Integer resultId) { + return resultCrudRepository.existsById(resultId); + } + + /** + *

+ * Determines if a result already exists by a lesson id

+ * + * @param lessonId the lesson id to find if results exists for + * @return whether the result model exists or not + */ + public Boolean existsByLessonId(Integer lessonId) { + return resultCrudRepository.existsByLessonId(String.valueOf(lessonId)); + } + } From ebbf4f144fcb221fad6128b0fe4039bad1b748ab Mon Sep 17 00:00:00 2001 From: Oisin Date: Sun, 15 Jun 2025 12:16:16 +0100 Subject: [PATCH 09/21] Extending question service with get question by lesson id and lesson question id --- .../com/czechtutor/service/QuestionService.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/main/java/com/czechtutor/service/QuestionService.java b/src/main/java/com/czechtutor/service/QuestionService.java index df160c2..956acf7 100644 --- a/src/main/java/com/czechtutor/service/QuestionService.java +++ b/src/main/java/com/czechtutor/service/QuestionService.java @@ -97,6 +97,7 @@ public QuestionModel create(LessonModel lessonModel, Long randomSeed) { // create a question QuestionModel questionModel = new QuestionModel(); questionModel.setLessonId(lessonModel.getLessonId()); + questionModel.setQuestionLessonId(questionCrudRepository.findByLessonId(String.valueOf(lessonModel.getLessonId())).size()+1); questionModel.setPhrase((String) cesModelArray.get(phaseIndex).getCesPayload().get(lessonModel.getFromLanguage())); questionModel.setOption1(optionsArray.get(0)); questionModel.setOption2(optionsArray.get(1)); @@ -118,4 +119,16 @@ public QuestionModel create(LessonModel lessonModel, Long randomSeed) { public ArrayList findByLessonId(Integer lessonId) { return questionCrudRepository.findByLessonId(String.valueOf(lessonId)); } + + /** + *

+ * Retrieves a question model using a lesson id and a question lesson id.

+ * + * @param lessonLid the lesson question to find + * @param lessonQuestionId the lesson question id to find + * @return the question model + */ + public QuestionModel getQuestionByLessonQuestionIds(Integer lessonLid, Integer lessonQuestionId) { + return questionCrudRepository.getQuestionByLessonQuestionIds(lessonLid, lessonQuestionId); + } } From adc1be32843af39ff07b80dea44618c098e7ab8e Mon Sep 17 00:00:00 2001 From: Oisin Date: Sun, 15 Jun 2025 12:17:06 +0100 Subject: [PATCH 10/21] Added lesson question to model schema --- src/main/resources/schema.sql | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/resources/schema.sql b/src/main/resources/schema.sql index fb2e3a4..d2c6de8 100644 --- a/src/main/resources/schema.sql +++ b/src/main/resources/schema.sql @@ -12,6 +12,7 @@ create table if not exists lessons ( create table if not exists questions ( question_id bigint auto_increment primary key, lesson_id bigint not null, + lesson_question_id tinyint not null, phrase varchar(255) not null, option1 varchar(255) not null, option2 varchar(255) not null, From d3d67d64d5b734f25cb17e6e274b708f9e02eee4 Mon Sep 17 00:00:00 2001 From: Oisin Date: Sun, 15 Jun 2025 12:43:47 +0100 Subject: [PATCH 11/21] Updated flowchart to show connection between lessons and results pages --- .../web_app_flowchart.drawio | 16 ++++++++++++++-- doc/web_app_flowchart/web_app_flowchart.jpg | Bin 27475 -> 28112 bytes 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/doc/web_app_flowchart/web_app_flowchart.drawio b/doc/web_app_flowchart/web_app_flowchart.drawio index d603bf4..e9a0477 100644 --- a/doc/web_app_flowchart/web_app_flowchart.drawio +++ b/doc/web_app_flowchart/web_app_flowchart.drawio @@ -1,6 +1,6 @@ - + @@ -67,12 +67,24 @@ - + + + + + + + + + + + + + diff --git a/doc/web_app_flowchart/web_app_flowchart.jpg b/doc/web_app_flowchart/web_app_flowchart.jpg index 51a09de91a4d44d44131aa1932a07df56a9f945d..662dfb3d08a8e1482a3abe3a973b036d8bbe77fe 100644 GIT binary patch literal 28112 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 S3j+YUX@?8{@6Xl4;r{|B1p(3k From 4c0ae1058d5a12aa9409f78730e5f4ed987a7dfa Mon Sep 17 00:00:00 2001 From: Oisin Date: Sun, 15 Jun 2025 12:44:38 +0100 Subject: [PATCH 12/21] Added custom message when lesson is incomplete --- .../com/czechtutor/controller/ApplicationController.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/czechtutor/controller/ApplicationController.java b/src/main/java/com/czechtutor/controller/ApplicationController.java index cc37130..c948ae4 100644 --- a/src/main/java/com/czechtutor/controller/ApplicationController.java +++ b/src/main/java/com/czechtutor/controller/ApplicationController.java @@ -320,8 +320,12 @@ public String getResultPage(@PathVariable("lessonId") Integer lessonId, Model mo LessonModel lessonModel = lessonService.get(lessonId); // create results messages ResultModel resultModel = resultService.findByLessonId(lessonId); - String scoreMessage = "Score: " + String.valueOf(resultModel.getScore()) + "%"; - String nCorrectMessage = "Answered " + String.valueOf(resultModel.getNCorrect()) + " out of " + String.valueOf(nQuestions) + " questions correctly"; + String scoreMessage = "This lesson is incomplete."; + String nCorrectMessage = "Complete using 'Retry Lesson' below."; + if (resultService.existsByLessonId(lessonId)) { + scoreMessage = "Score: " + String.valueOf(resultModel.getScore()) + "%"; + nCorrectMessage = "Answered " + String.valueOf(resultModel.getNCorrect()) + " out of " + String.valueOf(nQuestions) + " questions correctly"; + } String path = String.valueOf(lessonId); // generate combined lesson questions and answers ArrayList lessonQuestionsAnswers = lessonQuestionAnswerService.createLessonSummary(lessonModel); From 6fdd7764182409dd8930faa743fce87491755069 Mon Sep 17 00:00:00 2001 From: Oisin Date: Sun, 15 Jun 2025 12:45:30 +0100 Subject: [PATCH 13/21] Applying left join and ordering by question id --- .../crud/custom/LessonQuestionAnswerCrudRepository.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/czechtutor/repository/crud/custom/LessonQuestionAnswerCrudRepository.java b/src/main/java/com/czechtutor/repository/crud/custom/LessonQuestionAnswerCrudRepository.java index d84c1fa..979b254 100644 --- a/src/main/java/com/czechtutor/repository/crud/custom/LessonQuestionAnswerCrudRepository.java +++ b/src/main/java/com/czechtutor/repository/crud/custom/LessonQuestionAnswerCrudRepository.java @@ -24,9 +24,10 @@ public interface LessonQuestionAnswerCrudRepository extends CrudRepository Date: Sun, 15 Jun 2025 12:45:49 +0100 Subject: [PATCH 14/21] Applying left join and ordering by lesson id --- .../repository/crud/custom/LessonResultCrudRepository.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/czechtutor/repository/crud/custom/LessonResultCrudRepository.java b/src/main/java/com/czechtutor/repository/crud/custom/LessonResultCrudRepository.java index d48ebe3..8575ba6 100644 --- a/src/main/java/com/czechtutor/repository/crud/custom/LessonResultCrudRepository.java +++ b/src/main/java/com/czechtutor/repository/crud/custom/LessonResultCrudRepository.java @@ -21,7 +21,8 @@ public interface LessonResultCrudRepository extends CrudRepository Date: Sun, 15 Jun 2025 14:17:06 +0100 Subject: [PATCH 15/21] Removed results generation logic from new lesson view. Updating retry answers using answer_id instead of question_id. Updated routing logic when post to lesson/id/jd to catch three cases; 1 where a new question needs to be generated, 2 where a question already exists, and lastly where all quesitons have been answer and results should be generated --- .../controller/ApplicationController.java | 91 +++++++------------ 1 file changed, 31 insertions(+), 60 deletions(-) diff --git a/src/main/java/com/czechtutor/controller/ApplicationController.java b/src/main/java/com/czechtutor/controller/ApplicationController.java index c948ae4..b501983 100644 --- a/src/main/java/com/czechtutor/controller/ApplicationController.java +++ b/src/main/java/com/czechtutor/controller/ApplicationController.java @@ -167,42 +167,18 @@ public String createLesson(@ModelAttribute LessonModel lessonModel) { */ @GetMapping(value = "/newLessonQuestion/{lessonId}") public String createLessonQuestion(@PathVariable("lessonId") Integer lessonId) { - // check NQuestions for lessonId against database - Integer nQuestions = lessonService.get(lessonId).getNQuestions(); - Integer nLessonQuestions = questionService.findByLessonId(lessonId).size(); - if (nLessonQuestions < nQuestions) { - logger.info("~~~~~ Creating question."); - // generate a question - LessonModel lessonModel = lessonService.get(lessonId); - QuestionModel questionModel = questionService.create(lessonModel, null); - questionService.save(questionModel); - // Integer questionId = questionModel.getQuestionId(); - Integer lessonQuestionId = questionModel.getLessonQuestionId(); - // redirect to view - String path = String.valueOf(lessonId) + "/" + String.valueOf(lessonQuestionId); - String view = "/lesson/" + path; - logger.info(view); - logger.info(questionModel.getQuestionPayload()); - return "redirect:" + view; - } else { - logger.info("~~~~~ Creating result."); - // define decimal formatter - DecimalFormat decimalFormatter = new DecimalFormat("#.##"); - decimalFormatter.setRoundingMode(RoundingMode.HALF_EVEN); - // generate the results of the lesson - ArrayList lessonAnswers = answerService.findByLessonId(lessonId); - Integer nCorrect = resultService.countTotalCorrect(lessonAnswers); - Float score = Float.valueOf(decimalFormatter.format(Float.valueOf(nCorrect) / Float.valueOf(nQuestions) * 100)); - // create a result - ResultModel resultModel = resultService.create(lessonId, nCorrect, score); - resultService.save(resultModel); - // redirect to view - String path = String.valueOf(lessonId); - String view = "/result/" + path; - logger.info(view); - logger.info(resultModel.getResultPayload()); - return "redirect:" + view; - } + logger.info("~~~~~ Creating question."); + // generate a question + LessonModel lessonModel = lessonService.get(lessonId); + QuestionModel questionModel = questionService.create(lessonModel, null); + questionService.save(questionModel); + Integer lessonQuestionId = questionModel.getLessonQuestionId(); + // redirect to view + String path = String.valueOf(lessonId) + "/" + String.valueOf(lessonQuestionId); + String view = "/lesson/" + path; + logger.info(view); + logger.info(questionModel.getQuestionPayload()); + return "redirect:" + view; } /** @@ -211,7 +187,7 @@ public String createLessonQuestion(@PathVariable("lessonId") Integer lessonId) { * id

* * @param lessonId the generated lesson id path variable - * @param questionId the generated question id path variable + * @param lessonQuestionId the generated lesson question id path variable * @param model the Model ui object for populating the lesson template with * Thymeleaf * @return the lesson template for the given lesson id and question id @@ -221,7 +197,6 @@ public String getLessonPage(@PathVariable("lessonId") Integer lessonId, @PathVar logger.info("~~~~~ Redirecting to lesson."); // pull lesson model for lesson id and lesson question id QuestionModel questionModel = questionService.getQuestionByLessonQuestionIds(lessonId, lessonQuestionId); - // QuestionModel questionModel = questionService.get(questionId); String path = String.valueOf(lessonId) + "/" + String.valueOf(lessonQuestionId); model.addAttribute("questionModel", questionModel); model.addAttribute("answerModel", new AnswerModel()); @@ -235,7 +210,7 @@ public String getLessonPage(@PathVariable("lessonId") Integer lessonId, @PathVar * Posts user input from the lesson template page

* * @param lessonId the generated lesson id path variable - * @param questionId the generated question id path variable + * @param lessonQuestionId the generated lesson question id path variable * @param answerModel the completed answer model form * @return redirects to the lesson template with the lesson id */ @@ -244,31 +219,33 @@ public String createAnswer(@PathVariable("lessonId") Integer lessonId, @PathVari logger.info("~~~~~ Creating answer"); // pull lesson model for lesson id and lesson question id QuestionModel questionModel = questionService.getQuestionByLessonQuestionIds(lessonId, lessonQuestionId); - // QuestionModel questionModel = questionService.get(questionId); // generate a answer answerModel.setQuestionId(questionModel.getQuestionId()); answerModel.setCorrect(answerService.isCorrect(questionModel, answerModel)); answerModel.setDateTime(LocalDateTime.now()); answerModel.setDateTimeHash(utilityService.MD5DateTimeHash(answerModel.getDateTime())); // check if answer already exists for the question id - if (answerService.existsById(questionModel.getQuestionId())) { + if (answerService.existsByQuestionId(questionModel.getQuestionId())) { // if ot does assign answer id and overwrite existing result - answerModel.setAnswerId(questionModel.getQuestionId()); + answerModel.setAnswerId(answerService.findByQuestionId(questionModel.getQuestionId()).getAnswerId()); } answerService.save(answerModel); // check NQuestions for lessonId against database Integer nQuestions = lessonService.get(lessonId).getNQuestions(); Integer nLessonQuestions = questionService.findByLessonId(lessonId).size(); - Boolean allLessonQuestionsExist = nLessonQuestions.equals(nQuestions); - if (!allLessonQuestionsExist) { - // redirect to view + // if the lesson question id is greater than the number of available questions, and also less than the total required questions + if (lessonQuestionId >= nLessonQuestions && lessonQuestionId < nQuestions) { + logger.info("~~~~~ Redirecting to new question."); + // redirect to new lesson question view String path = String.valueOf(lessonId); String view = "/newLessonQuestion/" + path; logger.info(view); logger.info(answerModel.getAnswerPayload()); return "redirect:" + view; - } else if (lessonQuestionId < nQuestions) { - // pull the next lesson question model + // otherwise if the lesson question id is less than the number of available question, and also less the total required questions + } else if (lessonQuestionId < nQuestions && lessonQuestionId < nQuestions) { + logger.info("~~~~~ Redirecting to next question."); + // redirect to the the new question in the lesson view Integer nextLessonQuestionId = lessonQuestionId + 1; QuestionModel nextQuestionModel = questionService.getQuestionByLessonQuestionIds(lessonId, nextLessonQuestionId); // redirect to view @@ -277,6 +254,7 @@ public String createAnswer(@PathVariable("lessonId") Integer lessonId, @PathVari logger.info(view); logger.info(nextQuestionModel.getQuestionPayload()); return "redirect:" + view; + // otherwise all questions have been completed and redirect to results view } else { logger.info("~~~~~ Creating result."); // define decimal formatter @@ -329,6 +307,12 @@ public String getResultPage(@PathVariable("lessonId") Integer lessonId, Model mo String path = String.valueOf(lessonId); // generate combined lesson questions and answers ArrayList lessonQuestionsAnswers = lessonQuestionAnswerService.createLessonSummary(lessonModel); + // map solution to null if answers have not been provided + for (LessonQuestionAnswer lessonQuestionAnswer : lessonQuestionsAnswers) { + if (lessonQuestionAnswer.getAnswerId() == null) { + lessonQuestionAnswer.setSolution(null); + } + } // add attributes to model object model.addAttribute("scoreMessage", scoreMessage); model.addAttribute("nCorrectMessage", nCorrectMessage); @@ -338,19 +322,6 @@ public String getResultPage(@PathVariable("lessonId") Integer lessonId, Model mo return "result"; } - /** - *

- * Posts user input from the result template page

- * - * @param lessonId the generated lesson id path variable - * @return redirects to the home template - */ - @PostMapping(value = "/resultHome/{lessonId}") - public String redirectResulttoHome(@PathVariable("lessonId") Integer lessonId) { - logger.info("~~~~~ Redirecting home."); - return "redirect:/home"; - } - /** *

* Posts user input from the result template page

From 2888c4029664508964b0adc20866686508be0032 Mon Sep 17 00:00:00 2001 From: Oisin Date: Sun, 15 Jun 2025 14:17:41 +0100 Subject: [PATCH 16/21] Added find and exists by question id to answers repository --- .../repository/crud/AnswerCrudRepository.java | 22 +++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/czechtutor/repository/crud/AnswerCrudRepository.java b/src/main/java/com/czechtutor/repository/crud/AnswerCrudRepository.java index 3909c0c..224de0d 100644 --- a/src/main/java/com/czechtutor/repository/crud/AnswerCrudRepository.java +++ b/src/main/java/com/czechtutor/repository/crud/AnswerCrudRepository.java @@ -19,9 +19,27 @@ public interface AnswerCrudRepository extends CrudRepository * Finds all answer models with a specified lesson id as an array list

* - * @param LessonId the lesson id to find by + * @param lessonId the lesson id to find by * @return the answer models as an array list */ - ArrayList findByLessonId(String LessonId); + ArrayList findByLessonId(String lessonId); + + /** + *

+ * Finds a answer model by a question id

+ * + * @param questionId the question id to find an answer by + * @return the answer model + */ + AnswerModel findByQuestionId(String questionId); + + /** + *

+ * Determines if an answer model exists for a question id

+ * + * @param questionId the question id to find if answer exist for + * @return whether the answer model exists + */ + Boolean existsByQuestionId(String questionId); } From 2f9fdf2ba102e31e3f351009b971d70c73d463ae Mon Sep 17 00:00:00 2001 From: Oisin Date: Sun, 15 Jun 2025 14:17:59 +0100 Subject: [PATCH 17/21] Corrected doc strings --- .../com/czechtutor/repository/crud/CesCrudRepository.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/czechtutor/repository/crud/CesCrudRepository.java b/src/main/java/com/czechtutor/repository/crud/CesCrudRepository.java index 2612238..20dc00e 100644 --- a/src/main/java/com/czechtutor/repository/crud/CesCrudRepository.java +++ b/src/main/java/com/czechtutor/repository/crud/CesCrudRepository.java @@ -19,9 +19,9 @@ public interface CesCrudRepository extends CrudRepository { *

* Finds all ces models with a specified level as an array list

* - * @param Level the Level to find by + * @param level the Level to find by * @return the ces models as an array list */ - ArrayList findByLevel(String Level); + ArrayList findByLevel(String level); } From c0d8ebcd1f54bdabf4e843d08b43839f20c03488 Mon Sep 17 00:00:00 2001 From: Oisin Date: Sun, 15 Jun 2025 14:18:17 +0100 Subject: [PATCH 18/21] Corrected doc strings --- .../czechtutor/repository/crud/ResultCrudRepository.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/czechtutor/repository/crud/ResultCrudRepository.java b/src/main/java/com/czechtutor/repository/crud/ResultCrudRepository.java index f655e8f..b18a9b8 100644 --- a/src/main/java/com/czechtutor/repository/crud/ResultCrudRepository.java +++ b/src/main/java/com/czechtutor/repository/crud/ResultCrudRepository.java @@ -17,18 +17,18 @@ public interface ResultCrudRepository extends CrudRepository * Finds a result model with a specified lesson id

* - * @param LessonId the lesson id to find by + * @param lessonId the lesson id to find by * @return the result model */ - ResultModel findByLessonId(String LessonId); + ResultModel findByLessonId(String lessonId); /** *

* Determines if a results model exists for a lesson id

* - * @param LessonId the lesson id to find if results exist for + * @param lessonId the lesson id to find if results exist for * @return whether the result model exists */ - Boolean existsByLessonId(String LessonId); + Boolean existsByLessonId(String lessonId); } From ce8f2837e0c950a56b092ef37770d9575f64f56a Mon Sep 17 00:00:00 2001 From: Oisin Date: Sun, 15 Jun 2025 14:18:26 +0100 Subject: [PATCH 19/21] Corrected doc strings --- .../czechtutor/repository/crud/QuestionCrudRepository.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/czechtutor/repository/crud/QuestionCrudRepository.java b/src/main/java/com/czechtutor/repository/crud/QuestionCrudRepository.java index 0401400..b86bc9e 100644 --- a/src/main/java/com/czechtutor/repository/crud/QuestionCrudRepository.java +++ b/src/main/java/com/czechtutor/repository/crud/QuestionCrudRepository.java @@ -21,10 +21,10 @@ public interface QuestionCrudRepository extends CrudRepository * Finds all question models with a specified lesson id as an array list

* - * @param LessonId the lesson id to find by + * @param lessonId the lesson id to find by * @return the question models as an array list */ - ArrayList findByLessonId(String LessonId); + ArrayList findByLessonId(String lessonId); public static final String GET_QUESTION_BY_LESSON_QUESTION_IDS_QUERY = """ select * from questions where lesson_id = :#{#lessonId.intValue()} and lesson_question_id = :#{#LessonQuestionId.intValue()} From c7afc105345f377b47e7b0ef0b21494cd632d447 Mon Sep 17 00:00:00 2001 From: Oisin Date: Sun, 15 Jun 2025 14:18:52 +0100 Subject: [PATCH 20/21] Extendd answer service to include find by and exist by qustion id functions --- .../com/czechtutor/service/AnswerService.java | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/main/java/com/czechtutor/service/AnswerService.java b/src/main/java/com/czechtutor/service/AnswerService.java index 8faddba..f849179 100644 --- a/src/main/java/com/czechtutor/service/AnswerService.java +++ b/src/main/java/com/czechtutor/service/AnswerService.java @@ -80,4 +80,26 @@ public Boolean existsById(Integer answerId) { return answerCrudRepository.existsById(answerId); } + /** + *

+ * Finds a answer model by a question id

+ * + * @param questionId the question id to find an answer by + * @return the answer model + */ + public AnswerModel findByQuestionId(Integer questionId) { + return answerCrudRepository.findByQuestionId(String.valueOf(questionId)); + } + + /** + *

+ * Determines if an answer already exists by a question id

+ * + * @param questionId the question id to find if an answer exists for + * @return whether the answer model exists or not + */ + public Boolean existsByQuestionId(Integer questionId) { + return answerCrudRepository.existsByQuestionId(String.valueOf(questionId)); + } + } From b68297be8b4b7071460718ac44c2f3e6c65866ee Mon Sep 17 00:00:00 2001 From: Oisin Date: Sun, 15 Jun 2025 14:19:24 +0100 Subject: [PATCH 21/21] Adjusted table column order to show solution after answer --- src/main/resources/templates/result.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/resources/templates/result.html b/src/main/resources/templates/result.html index 3d3bbb9..e383d11 100644 --- a/src/main/resources/templates/result.html +++ b/src/main/resources/templates/result.html @@ -21,16 +21,16 @@
Phrase - Solution Answer + Solution Correct - +