Index: lams_common/src/java/org/lamsfoundation/lams/commonContext.xml =================================================================== diff -u -r646ad3f8f14c7577e5a1e863f31dacca0c38e860 -r292df3a6fb3cce2b31c9d9ee33c61bbe931e58ab --- lams_common/src/java/org/lamsfoundation/lams/commonContext.xml (.../commonContext.xml) (revision 646ad3f8f14c7577e5a1e863f31dacca0c38e860) +++ lams_common/src/java/org/lamsfoundation/lams/commonContext.xml (.../commonContext.xml) (revision 292df3a6fb3cce2b31c9d9ee33c61bbe931e58ab) @@ -486,6 +486,28 @@ + + + + + + + + + + + + + + + true + + + PROPAGATION_REQUIRED + + + + Index: lams_common/src/java/org/lamsfoundation/lams/dbupdates/patch20201122.sql =================================================================== diff -u --- lams_common/src/java/org/lamsfoundation/lams/dbupdates/patch20201122.sql (revision 0) +++ lams_common/src/java/org/lamsfoundation/lams/dbupdates/patch20201122.sql (revision 292df3a6fb3cce2b31c9d9ee33c61bbe931e58ab) @@ -0,0 +1,28 @@ +-- Turn off autocommit, so nothing is committed if there is an error +SET AUTOCOMMIT = 0; +SET FOREIGN_KEY_CHECKS=0; +-- Put all sql statements below here + +--LDEV- Log learner clicks on MCQ questions in Assessment + +CREATE TABLE lams_learner_interaction_event ( + uid BIGINT UNSIGNED auto_increment, + event_type TINYINT UNSIGNED NOT NULL, + occurred_date_time DATETIME NOT NULL, + user_id BIGINT NOT NULL, + qb_tool_question_uid BIGINT, + option_uid BIGINT, + PRIMARY KEY (uid), + INDEX (event_type), + CONSTRAINT lams_learner_interaction_event_FK1 FOREIGN KEY (user_id) REFERENCES lams_user (user_id) + ON DELETE CASCADE ON UPDATE CASCADE, + CONSTRAINT lams_learner_interaction_event_FK2 FOREIGN KEY (qb_tool_question_uid) REFERENCES lams_qb_tool_question (tool_question_uid) + ON DELETE RESTRICT ON UPDATE CASCADE +); + +-- Put all sql statements above here + +-- If there were no errors, commit and restore autocommit to on +COMMIT; +SET AUTOCOMMIT = 1; +SET FOREIGN_KEY_CHECKS=1; Index: lams_common/src/java/org/lamsfoundation/lams/logevent/LearnerInteractionEvent.java =================================================================== diff -u --- lams_common/src/java/org/lamsfoundation/lams/logevent/LearnerInteractionEvent.java (revision 0) +++ lams_common/src/java/org/lamsfoundation/lams/logevent/LearnerInteractionEvent.java (revision 292df3a6fb3cce2b31c9d9ee33c61bbe931e58ab) @@ -0,0 +1,98 @@ +package org.lamsfoundation.lams.logevent; + +import java.time.LocalDateTime; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; + +@Entity +@Table(name = "lams_learner_interaction_event") +public class LearnerInteractionEvent { + + public static final int RADIO_BUTTON_SELECTED = 1; + public static final int CHECKBOX_CHECKED = 2; + public static final int CHECKBOX_UNCHECKED = 3; + + @Id + @Column + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long uid; + + @Column(name = "event_type") + private int eventType; + + @Column(name = "occurred_date_time") + private LocalDateTime occuredDateTime; + + @Column(name = "user_id") + private int userId; + + @Column(name = "qb_tool_question_uid") + private Long qbToolQuestionUid; + + // For MCQ questions this is a reference to QbOption UID + // For true/false questions 1 = true, 2 = false + @Column(name = "option_uid") + private Long optionUid; + + public LearnerInteractionEvent() { + } + + public LearnerInteractionEvent(int eventType, int userId) { + this.eventType = eventType; + this.userId = userId; + this.occuredDateTime = LocalDateTime.now(); + } + + public Long getUid() { + return uid; + } + + public void setUid(Long uid) { + this.uid = uid; + } + + public int getEventType() { + return eventType; + } + + public void setEventType(int type) { + this.eventType = type; + } + + public LocalDateTime getOccuredDateTime() { + return occuredDateTime; + } + + public void setOccuredDateTime(LocalDateTime occuredDateTime) { + this.occuredDateTime = occuredDateTime; + } + + public int getUserId() { + return userId; + } + + public void setUserId(int userId) { + this.userId = userId; + } + + public Long getQbToolQuestionUid() { + return qbToolQuestionUid; + } + + public void setQbToolQuestionUid(Long toolQuestionUid) { + this.qbToolQuestionUid = toolQuestionUid; + } + + public Long getOptionUid() { + return optionUid; + } + + public void setOptionUid(Long qbOptionUid) { + this.optionUid = qbOptionUid; + } +} \ No newline at end of file Index: lams_common/src/java/org/lamsfoundation/lams/logevent/service/ILearnerInteractionService.java =================================================================== diff -u --- lams_common/src/java/org/lamsfoundation/lams/logevent/service/ILearnerInteractionService.java (revision 0) +++ lams_common/src/java/org/lamsfoundation/lams/logevent/service/ILearnerInteractionService.java (revision 292df3a6fb3cce2b31c9d9ee33c61bbe931e58ab) @@ -0,0 +1,7 @@ +package org.lamsfoundation.lams.logevent.service; + +import org.lamsfoundation.lams.logevent.LearnerInteractionEvent; + +public interface ILearnerInteractionService { + void saveEvent(LearnerInteractionEvent event); +} \ No newline at end of file Index: lams_common/src/java/org/lamsfoundation/lams/logevent/service/LearnerInteractionService.java =================================================================== diff -u --- lams_common/src/java/org/lamsfoundation/lams/logevent/service/LearnerInteractionService.java (revision 0) +++ lams_common/src/java/org/lamsfoundation/lams/logevent/service/LearnerInteractionService.java (revision 292df3a6fb3cce2b31c9d9ee33c61bbe931e58ab) @@ -0,0 +1,18 @@ +package org.lamsfoundation.lams.logevent.service; + +import org.lamsfoundation.lams.dao.IBaseDAO; +import org.lamsfoundation.lams.logevent.LearnerInteractionEvent; + +public class LearnerInteractionService implements ILearnerInteractionService { + + private IBaseDAO baseDAO; + + @Override + public void saveEvent(LearnerInteractionEvent event) { + baseDAO.insert(event); + } + + public void setBaseDAO(IBaseDAO baseDAO) { + this.baseDAO = baseDAO; + } +} \ No newline at end of file Index: lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/web/controller/LearningController.java =================================================================== diff -u -r79db1b495adba49dd54a6250c1221a326f153633 -r292df3a6fb3cce2b31c9d9ee33c61bbe931e58ab --- lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/web/controller/LearningController.java (.../LearningController.java) (revision 79db1b495adba49dd54a6250c1221a326f153633) +++ lams_tool_assessment/src/java/org/lamsfoundation/lams/tool/assessment/web/controller/LearningController.java (.../LearningController.java) (revision 292df3a6fb3cce2b31c9d9ee33c61bbe931e58ab) @@ -53,6 +53,8 @@ import org.apache.log4j.Logger; import org.lamsfoundation.lams.lesson.Lesson; import org.lamsfoundation.lams.lesson.service.ILessonService; +import org.lamsfoundation.lams.logevent.LearnerInteractionEvent; +import org.lamsfoundation.lams.logevent.service.ILearnerInteractionService; import org.lamsfoundation.lams.notebook.model.NotebookEntry; import org.lamsfoundation.lams.qb.model.QbOption; import org.lamsfoundation.lams.qb.model.QbQuestion; @@ -98,6 +100,8 @@ import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseStatus; @@ -128,6 +132,9 @@ private ILessonService lessonService; @Autowired + private ILearnerInteractionService learnerInteractionService; + + @Autowired private ISecurityService securityService; /** @@ -1277,6 +1284,19 @@ return "pages/learning/results" + (embedded ? "/allquestions" : ""); } + @RequestMapping(path = "/logLearnerInteractionEvent", method = RequestMethod.POST) + @ResponseStatus(code = HttpStatus.OK) + public void logLearnerInteractionEvent(@RequestParam int eventType, @RequestParam long qbToolQuestionUid, + @RequestParam long optionUid) { + UserDTO user = LearningController.getCurrentUser(); + + LearnerInteractionEvent learnerInteractionEvent = new LearnerInteractionEvent(eventType, user.getUserID()); + learnerInteractionEvent.setQbToolQuestionUid(qbToolQuestionUid); + learnerInteractionEvent.setOptionUid(optionUid); + + learnerInteractionService.saveEvent(learnerInteractionEvent); + } + /** * Store user answers in DB in last unfinished attempt and notify teachers about it. */ Index: lams_tool_assessment/web/pages/learning/learning.jsp =================================================================== diff -u -r47af8921ff7d63addfeff2b9624c23fa0602bf63 -r292df3a6fb3cce2b31c9d9ee33c61bbe931e58ab --- lams_tool_assessment/web/pages/learning/learning.jsp (.../learning.jsp) (revision 47af8921ff7d63addfeff2b9624c23fa0602bf63) +++ lams_tool_assessment/web/pages/learning/learning.jsp (.../learning.jsp) (revision 292df3a6fb3cce2b31c9d9ee33c61bbe931e58ab) @@ -546,6 +546,20 @@ var wordCount = value ? (value.replace(/['";:,.?\-!]+/g, '').match(/\S+/g) || []).length : 0; return wordCount; } + + function logLearnerInteractionEvent(eventType, qbToolQuestionUid, optionUid) { + $.ajax({ + url: '', + data: { + eventType : eventType, + qbToolQuestionUid : qbToolQuestionUid, + optionUid : optionUid + }, + cache : false, + type : 'post', + dataType : 'text' + }); + } Index: lams_tool_assessment/web/pages/learning/parts/multiplechoice.jsp =================================================================== diff -u -r993441a166bf0b72da19489e936ad4c725e805b3 -r292df3a6fb3cce2b31c9d9ee33c61bbe931e58ab --- lams_tool_assessment/web/pages/learning/parts/multiplechoice.jsp (.../multiplechoice.jsp) (revision 993441a166bf0b72da19489e936ad4c725e805b3) +++ lams_tool_assessment/web/pages/learning/parts/multiplechoice.jsp (.../multiplechoice.jsp) (revision 292df3a6fb3cce2b31c9d9ee33c61bbe931e58ab) @@ -21,15 +21,17 @@ question${status.index}_${option.uid} - checked="checked" disabled="disabled" /> question${status.index} ${inputName}_${option.uid} - checked="checked" disabled="disabled" /> Index: lams_tool_assessment/web/pages/learning/parts/truefalse.jsp =================================================================== diff -u -r2b3d3b2f61d37cf2fa7cccc0cf4565e5dfc4b88e -r292df3a6fb3cce2b31c9d9ee33c61bbe931e58ab --- lams_tool_assessment/web/pages/learning/parts/truefalse.jsp (.../truefalse.jsp) (revision 2b3d3b2f61d37cf2fa7cccc0cf4565e5dfc4b88e) +++ lams_tool_assessment/web/pages/learning/parts/truefalse.jsp (.../truefalse.jsp) (revision 292df3a6fb3cce2b31c9d9ee33c61bbe931e58ab) @@ -9,6 +9,7 @@ checked="checked" disabled="disabled" /> @@ -20,6 +21,7 @@ checked="checked" disabled="disabled" />