Index: lams_common/src/java/org/lamsfoundation/lams/dbupdates/patch20190110.sql =================================================================== diff -u -r33b2d2a94b6efe456645757c16d4744e902d30ec -rfba7287887f6dd83d3098100af6320cccf1f3e36 --- lams_common/src/java/org/lamsfoundation/lams/dbupdates/patch20190110.sql (.../patch20190110.sql) (revision 33b2d2a94b6efe456645757c16d4744e902d30ec) +++ lams_common/src/java/org/lamsfoundation/lams/dbupdates/patch20190110.sql (.../patch20190110.sql) (revision fba7287887f6dd83d3098100af6320cccf1f3e36) @@ -12,10 +12,12 @@ `question_id` INT NOT NULL, `version` SMALLINT NOT NULL DEFAULT 1, `name` TEXT NOT NULL, + `description` TEXT, `mark` INT, `feedback` TEXT, - `tmp_question_id` BIGINT NOT NULL UNIQUE, + `tmp_question_id` BIGINT, PRIMARY KEY (uid), + INDEX (tmp_question_id), CONSTRAINT UQ_question_version UNIQUE INDEX (question_id, version), INDEX (`local`)); @@ -59,7 +61,7 @@ -- fill Question Bank question table with unique questions, with manually incremented question ID SET @question_id = (SELECT IF(MAX(question_id) IS NULL, 0, MAX(question_id)) FROM lams_qb_question); -INSERT INTO lams_qb_question SELECT NULL, 1, 1, @question_id:=@question_id + 1, 1, mcq.question, mcq.mark, mcq.feedback, q.target_uid +INSERT INTO lams_qb_question SELECT NULL, 1, 1, @question_id:=@question_id + 1, 1, mcq.question, NULL, mcq.mark, mcq.feedback, q.target_uid FROM (SELECT uid, TRIM(question) AS question, mark, @@ -113,11 +115,114 @@ REFERENCES lams_qb_option (uid) ON DELETE CASCADE ON UPDATE CASCADE; -- clean up +DROP TABLE tl_lamc11_options_content; + + + +-- prepare for Scratchie migration +DELETE FROM tmp_question; +DELETE FROM tmp_question_match; + +-- shift Scratchie question UIDs by offset equal to existing UIDs of MCQ in lams_qb_tool_question +SET @max_tool_question_id = (SELECT MAX(tool_question_uid) FROM lams_qb_tool_question); +UPDATE tl_lascrt11_scratchie_item SET uid = uid + @max_tool_question_id ORDER BY uid DESC; +UPDATE tl_lascrt11_scratchie_answer SET scratchie_item_uid = scratchie_item_uid + @max_tool_question_id ORDER BY scratchie_item_uid DESC; + +-- create a mapping of Scratchie question UID -> its question text + all answers in a single column +-- if this column is not *exactly* as in an other row, it means it should be a separate question in QB +INSERT INTO tmp_question + SELECT q.uid, + GROUP_CONCAT(TRIM(q.title), TRIM(o.description) ORDER BY o.order_id) + FROM tl_lascrt11_scratchie_item AS q + JOIN tl_lascrt11_scratchie_answer AS o ON q.uid = o.scratchie_item_uid + GROUP BY q.uid; + +-- create a similar mapping for existing questions in QB +CREATE TABLE tmp_qb_question + AS SELECT q.uid AS question_uid, + GROUP_CONCAT(TRIM(q.name), TRIM(o.name) ORDER BY o.display_order) AS content + FROM lams_qb_question AS q + JOIN lams_qb_option AS o ON q.uid = o.qb_question_uid + WHERE q.type = 1 + GROUP BY q.uid; + +-- create a mapping of Scratchie question UID -> UID of one of Scratchie questions which holds the same content +INSERT INTO tmp_question_match + SELECT q.question_uid, merged.question_uid + FROM (SELECT * FROM tmp_question GROUP BY content) AS merged + JOIN tmp_question AS q USING (content) + LEFT JOIN tmp_qb_question AS qb USING (content) + WHERE qb.question_uid IS NULL; + +-- reset column for matching QB questions with Scratchie questions +UPDATE lams_qb_question SET tmp_question_id = -1; + +-- fill Question Bank question table with unique questions, with manually incremented question ID +INSERT INTO lams_qb_question SELECT NULL, 1, 1, @question_id:=@question_id + 1, 1, sq.question, sq.description, NULL, NULL, q.target_uid + FROM (SELECT uid, + TRIM(title) AS question, + TRIM(description) AS description + FROM tl_lascrt11_scratchie_item) AS sq + JOIN (SELECT DISTINCT target_uid FROM tmp_question_match) AS q + ON sq.uid = q.target_uid; + +-- set up references to QB question UIDs created above +INSERT INTO lams_qb_tool_question + SELECT q.question_uid, qb.uid + FROM lams_qb_question AS qb + JOIN tmp_question_match AS q + ON qb.tmp_question_id = q.target_uid; + +-- set up references to QB question UIDs for existing questions +INSERT INTO lams_qb_tool_question + SELECT q.question_uid, qb.question_uid + FROM tmp_question AS q + JOIN tmp_qb_question qb + USING (content); + +-- delete obsolete columns +ALTER TABLE tl_lascrt11_scratchie_item DROP FOREIGN KEY FK_NEW_610529188_F52D1F93EC0D3147, + DROP COLUMN title, + DROP COLUMN description, + DROP COLUMN create_date, + DROP COLUMN create_by_author, + DROP COLUMN session_uid; + +-- fill table with options matching unique QB questions inserted above +INSERT INTO lams_qb_option (qb_question_uid, display_order, name, correct) + SELECT q.uid, o.order_id + 1, TRIM(o.description), o.correct + FROM tl_lascrt11_scratchie_answer AS o + JOIN lams_qb_question AS q ON o.scratchie_item_uid = q.tmp_question_id + ORDER BY o.order_id; + + +ALTER TABLE tl_lascrt11_answer_log ADD COLUMN scratchie_item_uid BIGINT, + DROP FOREIGN KEY FK_NEW_610529188_693580A438BF8DFE, + RENAME COLUMN scratchie_answer_uid TO qb_option_uid; + +-- rewrite references from Scratchie options to QB options +UPDATE tl_lascrt11_answer_log AS sl, tl_lascrt11_scratchie_answer AS sa, lams_qb_tool_question AS tq, lams_qb_option AS qo + SET sl.qb_option_uid = qo.uid, + sl.scratchie_item_uid = tq.tool_question_uid + WHERE sa.order_id + 1 = qo.display_order + AND sl.qb_option_uid = sa.uid + AND qo.qb_question_uid = tq.qb_question_uid + AND sa.scratchie_item_uid = tq.tool_question_uid; + + +ALTER TABLE tl_lascrt11_answer_log ADD CONSTRAINT FK_tl_lascrt11_answer_log_1 FOREIGN KEY (scratchie_item_uid) + REFERENCES tl_lascrt11_scratchie_item (uid) ON DELETE CASCADE ON UPDATE CASCADE, + ADD CONSTRAINT FK_tl_lascrt11_answer_log_2 FOREIGN KEY (qb_option_uid) + REFERENCES lams_qb_option (uid) ON DELETE CASCADE ON UPDATE CASCADE; + + +-- cleanup ALTER TABLE lams_qb_question DROP COLUMN tmp_question_id; -DROP TABLE tl_lamc11_options_content, - tmp_question, - tmp_question_match; +DROP TABLE tl_lascrt11_scratchie_answer, + tmp_question, + tmp_question_match, + tmp_qb_question; ----------------------Put all sql statements above here------------------------- -- If there were no errors, commit and restore autocommit to on Index: lams_common/src/java/org/lamsfoundation/lams/qb/model/QbQuestion.java =================================================================== diff -u -rc87bb47eb670934f10192c08922f83367bc36230 -rfba7287887f6dd83d3098100af6320cccf1f3e36 --- lams_common/src/java/org/lamsfoundation/lams/qb/model/QbQuestion.java (.../QbQuestion.java) (revision c87bb47eb670934f10192c08922f83367bc36230) +++ lams_common/src/java/org/lamsfoundation/lams/qb/model/QbQuestion.java (.../QbQuestion.java) (revision fba7287887f6dd83d3098100af6320cccf1f3e36) @@ -62,6 +62,9 @@ private String name; @Column + private String description; + + @Column private Integer mark; @Column @@ -81,13 +84,14 @@ public boolean equals(Object o) { QbQuestion other = (QbQuestion) o; // options are also checked if they are equal - return new EqualsBuilder().append(name, other.name).append(feedback, other.feedback).append(mark, other.mark) + return new EqualsBuilder().append(name, other.name).append(description, other.description) + .append(feedback, other.feedback).append(mark, other.mark) .append(qbOptions.toArray(), other.getQbOptions().toArray()).isEquals(); } @Override public int hashCode() { - return new HashCodeBuilder().append(name).append(feedback).append(mark).toHashCode(); + return new HashCodeBuilder().append(name).append(description).append(feedback).append(mark).toHashCode(); } @Override @@ -161,6 +165,14 @@ this.name = StringUtils.isBlank(name) ? null : name.trim(); } + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + public Integer getMark() { return mark; } Index: lams_tool_scratchie/conf/language/lams/ApplicationResources.properties =================================================================== diff -u -r4136105c4f65a13360d7f27ff195301735e14595 -rfba7287887f6dd83d3098100af6320cccf1f3e36 --- lams_tool_scratchie/conf/language/lams/ApplicationResources.properties (.../ApplicationResources.properties) (revision 4136105c4f65a13360d7f27ff195301735e14595) +++ lams_tool_scratchie/conf/language/lams/ApplicationResources.properties (.../ApplicationResources.properties) (revision fba7287887f6dd83d3098100af6320cccf1f3e36) @@ -230,6 +230,8 @@ outcome.authoring.input =Search and select by outcome name or code outcome.authoring.existing =Added outcomes outcome.authoring.existing.none =none +message.qb.modified.update =The question in Question Bank will be updated +message.qb.modified.version =A new version of the question will be created in Question Bank +message.qb.modified.new =A new question will be created in Question Bank - #======= End labels: Exported 224 labels for en AU ===== Index: lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/dao/DAO.java =================================================================== diff -u -r7475d08afc280b5e2e5ddf04e8bf35e3166aaf80 -rfba7287887f6dd83d3098100af6320cccf1f3e36 --- lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/dao/DAO.java (.../DAO.java) (revision 7475d08afc280b5e2e5ddf04e8bf35e3166aaf80) +++ lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/dao/DAO.java (.../DAO.java) (revision fba7287887f6dd83d3098100af6320cccf1f3e36) @@ -26,18 +26,20 @@ import java.io.Serializable; import java.util.List; +import org.lamsfoundation.lams.dao.IBaseDAO; + /** * Data Access Object (DAO) interface. This is an interface * used to tag our DAO classes and to provide common methods to all DAOs. * * @author Andrey Balan */ -public interface DAO { +public interface DAO extends IBaseDAO { /** * Generic method used to get all objects of a particular type. This * is the same as lookup up all rows in a table. - * + * * @param clazz * the type of objects (a.k.a. while table) to get data from * @return List of populated objects @@ -59,7 +61,7 @@ /** * Generic method to save an object - handles both update and insert. - * + * * @param o * the object to save */ Index: lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/dao/ScratchieAnswerVisitDAO.java =================================================================== diff -u -r62aaf160878735888d077bf28fac3c1989bb8fbd -rfba7287887f6dd83d3098100af6320cccf1f3e36 --- lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/dao/ScratchieAnswerVisitDAO.java (.../ScratchieAnswerVisitDAO.java) (revision 62aaf160878735888d077bf28fac3c1989bb8fbd) +++ lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/dao/ScratchieAnswerVisitDAO.java (.../ScratchieAnswerVisitDAO.java) (revision fba7287887f6dd83d3098100af6320cccf1f3e36) @@ -29,7 +29,7 @@ public interface ScratchieAnswerVisitDAO extends DAO { - ScratchieAnswerVisitLog getLog(Long answerUid, Long sessionId); + ScratchieAnswerVisitLog getLog(Long answerUid, Long itemUid, Long sessionId); int getLogCountTotal(Long sessionId); Index: lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/dao/hibernate/ScratchieAnswerVisitDAOHibernate.java =================================================================== diff -u -rceb74e3b4097cf6461280448f904fa21a176aaa4 -rfba7287887f6dd83d3098100af6320cccf1f3e36 --- lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/dao/hibernate/ScratchieAnswerVisitDAOHibernate.java (.../ScratchieAnswerVisitDAOHibernate.java) (revision ceb74e3b4097cf6461280448f904fa21a176aaa4) +++ lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/dao/hibernate/ScratchieAnswerVisitDAOHibernate.java (.../ScratchieAnswerVisitDAOHibernate.java) (revision fba7287887f6dd83d3098100af6320cccf1f3e36) @@ -34,10 +34,10 @@ public class ScratchieAnswerVisitDAOHibernate extends LAMSBaseDAO implements ScratchieAnswerVisitDAO { private static final String FIND_BY_SESSION_AND_ANSWER = "from " + ScratchieAnswerVisitLog.class.getName() - + " as r where r.sessionId = ? and r.scratchieAnswer.uid=?"; + + " as r where r.sessionId = ? and r.qbOption.uid=? and r.scratchieItemUid.uid = ?"; private static final String FIND_BY_SESSION_AND_ITEM = "from " + ScratchieAnswerVisitLog.class.getName() - + " as r where r.sessionId=? and r.scratchieAnswer.scratchieItem.uid = ? order by r.accessDate asc"; + + " as r where r.sessionId=? and r.scratchieItemUid.uid = ? order by r.accessDate asc"; private static final String FIND_BY_SESSION = "from " + ScratchieAnswerVisitLog.class.getName() + " as r where r.sessionId=? order by r.accessDate asc"; @@ -46,8 +46,8 @@ + ScratchieAnswerVisitLog.class.getName() + " as r where r.sessionId=?"; @Override - public ScratchieAnswerVisitLog getLog(Long answerUid, Long sessionId) { - List list = doFind(FIND_BY_SESSION_AND_ANSWER, new Object[] { sessionId, answerUid }); + public ScratchieAnswerVisitLog getLog(Long answerUid, Long itemUid, Long sessionId) { + List list = doFind(FIND_BY_SESSION_AND_ANSWER, new Object[] { sessionId, itemUid, answerUid }); if (list == null || list.size() == 0) { return null; } Index: lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/dao/hibernate/ScratchieItemDAOHibernate.java =================================================================== diff -u -r7475d08afc280b5e2e5ddf04e8bf35e3166aaf80 -rfba7287887f6dd83d3098100af6320cccf1f3e36 --- lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/dao/hibernate/ScratchieItemDAOHibernate.java (.../ScratchieItemDAOHibernate.java) (revision 7475d08afc280b5e2e5ddf04e8bf35e3166aaf80) +++ lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/dao/hibernate/ScratchieItemDAOHibernate.java (.../ScratchieItemDAOHibernate.java) (revision fba7287887f6dd83d3098100af6320cccf1f3e36) @@ -34,7 +34,7 @@ public class ScratchieItemDAOHibernate extends LAMSBaseDAO implements ScratchieItemDAO { private static final String FIND_AUTHORING_ITEMS = "from " + ScratchieItem.class.getName() - + " where scratchie_uid = ? order by create_date asc"; + + " where scratchie_uid = ?"; @SuppressWarnings("unchecked") @Override Index: lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/dto/ScratchieItemDTO.java =================================================================== diff -u -reef0b919074e388a593fb6d3e97ec35b60ffdcb5 -rfba7287887f6dd83d3098100af6320cccf1f3e36 --- lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/dto/ScratchieItemDTO.java (.../ScratchieItemDTO.java) (revision eef0b919074e388a593fb6d3e97ec35b60ffdcb5) +++ lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/dto/ScratchieItemDTO.java (.../ScratchieItemDTO.java) (revision fba7287887f6dd83d3098100af6320cccf1f3e36) @@ -1,7 +1,7 @@ package org.lamsfoundation.lams.tool.scratchie.dto; -import java.util.HashSet; -import java.util.Set; +import java.util.LinkedList; +import java.util.List; import org.lamsfoundation.lams.tool.scratchie.model.ScratchieAnswer; @@ -14,18 +14,18 @@ private Long uid; private String title; - private Set answers; + private List answers; private boolean unraveledOnFirstAttempt; private int userMark; private int userAttempts; - //sequence of answers selected by user in the form of "X, Y, Z" + //sequence of answers selected by user in the form of "X, Y, Z" private String answersSequence; /** * Default contruction method. */ public ScratchieItemDTO() { - answers = new HashSet(); + answers = new LinkedList<>(); } // ********************************************************** @@ -47,11 +47,11 @@ this.title = title; } - public Set getAnswers() { + public List getAnswers() { return answers; } - public void setAnswers(Set answers) { + public void setAnswers(List answers) { this.answers = answers; } @@ -80,17 +80,17 @@ } /** - * @return sequence of answers selected by user in the form of "X, Y, Z" + * @return sequence of answers selected by user in the form of "X, Y, Z" */ public String getAnswersSequence() { return answersSequence; } /** - * @param answersSequence sequence of answers selected by user in the form of "X, Y, Z" + * @param answersSequence + * sequence of answers selected by user in the form of "X, Y, Z" */ public void setAnswersSequence(String answersSequence) { this.answersSequence = answersSequence; } } - Index: lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/dto/Summary.java =================================================================== diff -u -r62aaf160878735888d077bf28fac3c1989bb8fbd -rfba7287887f6dd83d3098100af6320cccf1f3e36 --- lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/dto/Summary.java (.../Summary.java) (revision 62aaf160878735888d077bf28fac3c1989bb8fbd) +++ lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/dto/Summary.java (.../Summary.java) (revision fba7287887f6dd83d3098100af6320cccf1f3e36) @@ -21,7 +21,6 @@ * **************************************************************** */ - package org.lamsfoundation.lams.tool.scratchie.dto; import java.util.ArrayList; @@ -41,7 +40,7 @@ private Long itemUid; private short itemType; private String itemTitle; - private List itemInstructions = new ArrayList(); + private List itemInstructions = new ArrayList<>(); private int viewNumber; // true: initial group item, false, belong to some group. @@ -65,7 +64,7 @@ if (item != null) { this.itemUid = item.getUid(); // TODO maybe a,b,c,d ? - this.itemTitle = item.getDescription(); + this.itemTitle = item.getQbQuestion().getDescription(); } else { this.itemUid = new Long(-1); } Index: lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/model/Scratchie.java =================================================================== diff -u -r22ca3de0e9fe138e44fc36be1abc6fabbbdc4002 -rfba7287887f6dd83d3098100af6320cccf1f3e36 --- lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/model/Scratchie.java (.../Scratchie.java) (revision 22ca3de0e9fe138e44fc36be1abc6fabbbdc4002) +++ lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/model/Scratchie.java (.../Scratchie.java) (revision fba7287887f6dd83d3098100af6320cccf1f3e36) @@ -28,7 +28,6 @@ import java.util.Iterator; import java.util.Set; -import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; @@ -73,7 +72,7 @@ private boolean defineLater; // general infomation - + @Column(name = "create_date") private Date created; @@ -83,7 +82,7 @@ @Column(name = "submission_deadline") private Date submissionDeadline; - @OneToMany(cascade = CascadeType.ALL) + @OneToMany @OrderBy("order_id ASC") @JoinColumn(name = "scratchie_uid") private Set scratchieItems = new HashSet<>();; @@ -243,7 +242,7 @@ public void setSubmissionDeadline(Date submissionDeadline) { this.submissionDeadline = submissionDeadline; } - + public Long getUid() { return uid; } Index: lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/model/ScratchieAnswer.java =================================================================== diff -u -r1ee503e3d0e0228ea8a45025fddf15d9623c0377 -rfba7287887f6dd83d3098100af6320cccf1f3e36 --- lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/model/ScratchieAnswer.java (.../ScratchieAnswer.java) (revision 1ee503e3d0e0228ea8a45025fddf15d9623c0377) +++ lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/model/ScratchieAnswer.java (.../ScratchieAnswer.java) (revision fba7287887f6dd83d3098100af6320cccf1f3e36) @@ -24,124 +24,35 @@ import java.util.List; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.FetchType; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import javax.persistence.JoinColumn; -import javax.persistence.ManyToOne; -import javax.persistence.Table; -import javax.persistence.Transient; - -import org.apache.log4j.Logger; import org.lamsfoundation.lams.confidencelevel.ConfidenceLevelDTO; +import org.lamsfoundation.lams.qb.model.QbOption; /** * Tool may contain several questions. Which in turn contain answers. * * @author Andrey Balan */ -@Entity -@Table(name = "tl_lascrt11_scratchie_answer") -public class ScratchieAnswer implements Cloneable { - private static final Logger log = Logger.getLogger(ScratchieAnswer.class); +public class ScratchieAnswer implements Comparable { + private QbOption qbOption; - @Id - @Column - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long uid; - - @Column - private String description; - - @Column - private boolean correct; - - @Column(name = "order_id") - private Integer orderId; - - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "scratchie_item_uid") - private ScratchieItem scratchieItem; - - // ******************** DTO fields *************************** - @Transient private boolean scratched; - @Transient private int attemptOrder; - @Transient private int[] attempts; - @Transient private List confidenceLevelDtos; - // ********************************************************** - // Get/Set methods - // ********************************************************** - /** - * - * @return Returns the uid. - */ - public Long getUid() { - return uid; + @Override + public int compareTo(ScratchieAnswer o) { + return this.qbOption.compareTo(o.qbOption); } - /** - * @param uid - * The uid to set. - */ - public void setUid(Long userID) { - this.uid = userID; + public QbOption getQbOption() { + return qbOption; } - /** - * - * @return - */ - public String getDescription() { - return description; + public void setQbOption(QbOption qbOption) { + this.qbOption = qbOption; } - public void setDescription(String description) { - this.description = description; - } - - /** - * - * @return - */ - public boolean isCorrect() { - return correct; - } - - public void setCorrect(boolean correctScratchie) { - this.correct = correctScratchie; - } - - /** - * - * @return - */ - public Integer getOrderId() { - return orderId; - } - - public void setOrderId(Integer orderId) { - this.orderId = orderId; - } - - /** - * - */ - public ScratchieItem getScratchieItem() { - return scratchieItem; - } - - public void setScratchieItem(ScratchieItem scratchieItem) { - this.scratchieItem = scratchieItem; - } - public void setScratched(boolean complete) { this.scratched = complete; } @@ -163,8 +74,6 @@ /** * Used for item summary page in monitor - * - * @return */ public int[] getAttempts() { return attempts; @@ -181,17 +90,4 @@ public void setConfidenceLevelDtos(List confidenceLevelDtos) { this.confidenceLevelDtos = confidenceLevelDtos; } - - @Override - public Object clone() { - ScratchieAnswer obj = null; - try { - obj = (ScratchieAnswer) super.clone(); - obj.setUid(null); - } catch (CloneNotSupportedException e) { - ScratchieAnswer.log.error("When clone " + ScratchieAnswer.class + " failed"); - } - - return obj; - } -} +} \ No newline at end of file Index: lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/model/ScratchieAnswerVisitLog.java =================================================================== diff -u -r1ee503e3d0e0228ea8a45025fddf15d9623c0377 -rfba7287887f6dd83d3098100af6320cccf1f3e36 --- lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/model/ScratchieAnswerVisitLog.java (.../ScratchieAnswerVisitLog.java) (revision 1ee503e3d0e0228ea8a45025fddf15d9623c0377) +++ lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/model/ScratchieAnswerVisitLog.java (.../ScratchieAnswerVisitLog.java) (revision fba7287887f6dd83d3098100af6320cccf1f3e36) @@ -35,6 +35,8 @@ import javax.persistence.ManyToOne; import javax.persistence.Table; +import org.lamsfoundation.lams.qb.model.QbOption; + /** * Scratchie * @@ -50,15 +52,18 @@ private Long uid; @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "scratchie_answer_uid") - private ScratchieAnswer scratchieAnswer; + @JoinColumn(name = "qb_option_uid") + private QbOption qbOption; @Column(name = "access_date") private Date accessDate; @Column(name = "session_id") private Long sessionId; + @Column(name = "scratchie_item_uid") + private Long scratchieItemUid; + public Date getAccessDate() { return accessDate; } @@ -67,12 +72,12 @@ this.accessDate = accessDate; } - public ScratchieAnswer getScratchieAnswer() { - return scratchieAnswer; + public QbOption getQbOption() { + return qbOption; } - public void setScratchieAnswer(ScratchieAnswer item) { - this.scratchieAnswer = item; + public void setQbOption(QbOption qbOption) { + this.qbOption = qbOption; } public Long getUid() { @@ -91,4 +96,11 @@ this.sessionId = sessionId; } -} + public Long getScratchieItemUid() { + return scratchieItemUid; + } + + public void setScratchieItemUid(Long scratchieItemUid) { + this.scratchieItemUid = scratchieItemUid; + } +} \ No newline at end of file Index: lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/model/ScratchieItem.java =================================================================== diff -u -r22ca3de0e9fe138e44fc36be1abc6fabbbdc4002 -rfba7287887f6dd83d3098100af6320cccf1f3e36 --- lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/model/ScratchieItem.java (.../ScratchieItem.java) (revision 22ca3de0e9fe138e44fc36be1abc6fabbbdc4002) +++ lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/model/ScratchieItem.java (.../ScratchieItem.java) (revision fba7287887f6dd83d3098100af6320cccf1f3e36) @@ -23,24 +23,20 @@ package org.lamsfoundation.lams.tool.scratchie.model; -import java.util.Date; -import java.util.HashSet; -import java.util.Iterator; -import java.util.Set; +import java.io.Serializable; +import java.util.LinkedList; +import java.util.List; -import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import javax.persistence.JoinColumn; -import javax.persistence.OneToMany; -import javax.persistence.OrderBy; +import javax.persistence.PrimaryKeyJoinColumn; import javax.persistence.Table; import javax.persistence.Transient; import org.apache.log4j.Logger; +import org.lamsfoundation.lams.qb.model.QbOption; +import org.lamsfoundation.lams.qb.model.QbToolQuestion; +import org.lamsfoundation.lams.qb.service.IQbService; /** * Tool may contain several questions. Which in turn contain answers. @@ -49,111 +45,54 @@ */ @Entity @Table(name = "tl_lascrt11_scratchie_item") -public class ScratchieItem implements Cloneable { +//in this entity's table primary key is "uid", but it references "tool_question_uid" in lams_qb_tool_question +@PrimaryKeyJoinColumn(name = "uid") +public class ScratchieItem extends QbToolQuestion implements Serializable, Cloneable { + private static final long serialVersionUID = -2824051249870361117L; + private static final Logger log = Logger.getLogger(ScratchieItem.class); - @Id - @Column - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long uid; - - @Column - private String title; - - @Column - private String description; - @Column(name = "order_id") private Integer orderId; - @Column(name = "create_by_author") - private boolean isCreateByAuthor; - - @Column(name = "create_date") - private Date createDate; - - @OneToMany(cascade = CascadeType.ALL) - @OrderBy("order_id ASC") - @JoinColumn(name = "scratchie_item_uid") - private Set answers = new HashSet<>(); - // ************************ DTO fields *********************** @Transient private boolean isUnraveled; @Transient private String burningQuestion; + @Transient + private List answers = null; + @Transient + private int qbQuestionModified = IQbService.QUESTION_MODIFIED_NONE; @Override public Object clone() { ScratchieItem item = null; try { item = (ScratchieItem) super.clone(); - - item.setUid(null); - - if (answers != null) { - Iterator iter = answers.iterator(); - Set set = new HashSet<>(); - while (iter.hasNext()) { - ScratchieAnswer answer = iter.next(); - ScratchieAnswer newAnswer = (ScratchieAnswer) answer.clone(); - // just clone old file without duplicate it in repository - set.add(newAnswer); - } - item.answers = set; - } - + item.uid = null; } catch (CloneNotSupportedException e) { log.error("When clone " + ScratchieItem.class + " failed"); } - return item; } - // ********************************************************** - // Get/Set methods - // ********************************************************** - - public Long getUid() { - return uid; + public List getAnswers() { + if (answers == null) { + answers = new LinkedList<>(); + for (QbOption option : qbQuestion.getQbOptions()) { + ScratchieAnswer answer = new ScratchieAnswer(); + answer.setQbOption(option); + answers.add(answer); + } + } + return answers; } - public void setUid(Long userID) { - this.uid = userID; + public void setAnswers(List answers) { + this.answers = answers; } - - public String getTitle() { - return title; - } - public void setTitle(String title) { - this.title = title; - } - - public String getDescription() { - return description; - } - - public void setDescription(String description) { - this.description = description; - } - - public Date getCreateDate() { - return createDate; - } - - public void setCreateDate(Date createDate) { - this.createDate = createDate; - } - - public boolean isCreateByAuthor() { - return isCreateByAuthor; - } - - public void setCreateByAuthor(boolean isCreateByAuthor) { - this.isCreateByAuthor = isCreateByAuthor; - } - public Integer getOrderId() { return orderId; } @@ -162,14 +101,6 @@ this.orderId = orderId; } - public Set getAnswers() { - return answers; - } - - public void setAnswers(Set answers) { - this.answers = answers; - } - public boolean isUnraveled() { return isUnraveled; } @@ -185,4 +116,13 @@ public void setBurningQuestion(String burningQuestion) { this.burningQuestion = burningQuestion; } -} + + public int getQbQuestionModified() { + return qbQuestionModified; + } + + public void setQbQuestionModified(int qbQuestionModified) { + this.qbQuestionModified = qbQuestionModified; + } + +} \ No newline at end of file Index: lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/model/ScratchieSession.java =================================================================== diff -u -r1ee503e3d0e0228ea8a45025fddf15d9623c0377 -rfba7287887f6dd83d3098100af6320cccf1f3e36 --- lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/model/ScratchieSession.java (.../ScratchieSession.java) (revision 1ee503e3d0e0228ea8a45025fddf15d9623c0377) +++ lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/model/ScratchieSession.java (.../ScratchieSession.java) (revision fba7287887f6dd83d3098100af6320cccf1f3e36) @@ -37,7 +37,6 @@ import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; import javax.persistence.OneToMany; -import javax.persistence.OrderBy; import javax.persistence.Table; import org.lamsfoundation.lams.tool.scratchie.ScratchieConstants; @@ -81,7 +80,6 @@ private int status; @OneToMany(cascade = CascadeType.ALL) - @OrderBy("create_date DESC") @JoinColumn(name = "session_uid") private Set scratchieItems = new HashSet<>(); Index: lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/scratchieApplicationContext.xml =================================================================== diff -u -r22ca3de0e9fe138e44fc36be1abc6fabbbdc4002 -rfba7287887f6dd83d3098100af6320cccf1f3e36 --- lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/scratchieApplicationContext.xml (.../scratchieApplicationContext.xml) (revision 22ca3de0e9fe138e44fc36be1abc6fabbbdc4002) +++ lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/scratchieApplicationContext.xml (.../scratchieApplicationContext.xml) (revision fba7287887f6dd83d3098100af6320cccf1f3e36) @@ -154,6 +154,7 @@ PROPAGATION_REQUIRED,+java.lang.Exception PROPAGATION_REQUIRED,+java.lang.Exception PROPAGATION_REQUIRED,+java.lang.Exception + PROPAGATION_REQUIRED Index: lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/service/IScratchieService.java =================================================================== diff -u -r3bb7e0141ae1cc15ccd737c95d90b5762a34ad61 -rfba7287887f6dd83d3098100af6320cccf1f3e36 --- lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/service/IScratchieService.java (.../IScratchieService.java) (revision 3bb7e0141ae1cc15ccd737c95d90b5762a34ad61) +++ lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/service/IScratchieService.java (.../IScratchieService.java) (revision fba7287887f6dd83d3098100af6320cccf1f3e36) @@ -29,16 +29,16 @@ import java.util.List; import java.util.Set; - import org.lamsfoundation.lams.events.IEventNotificationService; import org.lamsfoundation.lams.learningdesign.ToolActivity; import org.lamsfoundation.lams.notebook.model.NotebookEntry; +import org.lamsfoundation.lams.qb.model.QbOption; +import org.lamsfoundation.lams.qb.model.QbQuestion; import org.lamsfoundation.lams.tool.scratchie.dto.BurningQuestionItemDTO; import org.lamsfoundation.lams.tool.scratchie.dto.GroupSummary; import org.lamsfoundation.lams.tool.scratchie.dto.LeaderResultsDTO; import org.lamsfoundation.lams.tool.scratchie.dto.ReflectDTO; import org.lamsfoundation.lams.tool.scratchie.model.Scratchie; -import org.lamsfoundation.lams.tool.scratchie.model.ScratchieAnswer; import org.lamsfoundation.lams.tool.scratchie.model.ScratchieBurningQuestion; import org.lamsfoundation.lams.tool.scratchie.model.ScratchieConfigItem; import org.lamsfoundation.lams.tool.scratchie.model.ScratchieItem; @@ -62,22 +62,23 @@ * @return */ Scratchie getScratchieByContentId(Long contentId); - + /** * Populate scratchie items with the confidence levels from the activity specified in author - * + * * @param userId * @param toolSessionId * @param confidenceLevelsActivityUiid * @param items */ void populateItemsWithConfidenceLevels(Long userId, Long toolSessionId, Integer confidenceLevelsActivityUiid, Collection items); - + /** * Returns all activities that precede specified activity and produce confidence levels. - * - * @param toolContentId toolContentId of the specified activity + * + * @param toolContentId + * toolContentId of the specified activity * @return */ Set getPrecedingConfidenceLevelsActivities(Long toolContentId); @@ -89,18 +90,18 @@ * @param toolSessionId */ ScratchieUser checkLeaderSelectToolForSessionLeader(ScratchieUser user, Long toolSessionId); - + /** * Stores date when user has started activity with time limit. - * + * * @param sessionId - * @throws SchedulerException + * @throws SchedulerException */ void launchTimeLimit(Long sessionId) throws SchedulerException; - + /** * Checks if non-leaders should still wait for leader to submit notebook. - * + * * @param toolSession * @return */ @@ -118,7 +119,7 @@ */ void saveBurningQuestion(Long sessionId, Long itemUid, String question); - ScratchieAnswer getScratchieAnswerByUid(Long answerUid); + QbOption getQbOptionByUid(Long optionUid); /** * Get a cloned copy of tool default tool content (Scratchie) and assign the toolContentId of that copy as the given @@ -160,9 +161,9 @@ * @return */ List getUsersBySession(Long toolSessionId); - + ScratchieUser getUserByUserIDAndContentID(Long userId, Long contentId); - + int countUsersByContentId(Long contentId); /** @@ -202,10 +203,10 @@ * @return */ ScratchieSession getScratchieSessionBySessionId(Long sessionId); - + /** * Return all sessions realted to the specified toolContentId. - * + * * @param toolContentId * @return */ @@ -251,16 +252,16 @@ * Leader has scratched the specified answer. Will store this scratch for all users in his group. It will also * update all the marks. */ - void recordItemScratched(Long toolSessionId, Long scratchieItemUid); + void recordItemScratched(Long toolSessionId, Long itemUid, Long scratchieItemUid); void recalculateMarkForSession(Long sessionId, boolean isPropagateToGradebook); /** * Mark all users in agroup as ScratchingFinished so that users can't continue scratching after this. * * @param toolSessionId - * @throws IOException - * @throws JSONException + * @throws IOException + * @throws JSONException */ void setScratchingFinished(Long toolSessionId) throws IOException; @@ -292,7 +293,8 @@ * @param sessionId * optional parameter, if it's specified, BurningQuestionDTOs will also contain information what leader * of this group has liked - * @param includeEmptyItems whether it should include questions that don't have any burning questions + * @param includeEmptyItems + * whether it should include questions that don't have any burning questions * @return */ List getBurningQuestionDtos(Scratchie scratchie, Long sessionId, boolean includeEmptyItems); @@ -386,31 +388,34 @@ void releaseItemsFromCache(Scratchie scratchie); + void releaseFromCache(Object object); + ScratchieConfigItem getConfigItem(String key); void saveOrUpdateScratchieConfigItem(ScratchieConfigItem item); - + /** * Return preset marks that is going to be used for calculating learners' marks. Return scratchie.presetMarks if * it's not null, otherwise returns default setting stored as admin config setting. - * + * * @param scratchie * @return */ String[] getPresetMarks(Scratchie scratchie); - + /** * Return a maximum possible mark that user can get on answering all questions. - * + * * @param scratchie * @return */ int getMaxPossibleScore(Scratchie scratchie); - + /** Get the raw marks for display in a graph in monitoring */ List getMarksArray(Long contentId); /** Get the statistics such as average, max, min for the marks. Used in monitoring */ LeaderResultsDTO getLeaderResultsDTOForLeaders(Long contentId); -} + int isQbQuestionModified(QbQuestion baseLine, QbQuestion modifiedQuestion); +} \ No newline at end of file Index: lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/service/ScratchieServiceImpl.java =================================================================== diff -u -r3bb7e0141ae1cc15ccd737c95d90b5762a34ad61 -rfba7287887f6dd83d3098100af6320cccf1f3e36 --- lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/service/ScratchieServiceImpl.java (.../ScratchieServiceImpl.java) (revision 3bb7e0141ae1cc15ccd737c95d90b5762a34ad61) +++ lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/service/ScratchieServiceImpl.java (.../ScratchieServiceImpl.java) (revision fba7287887f6dd83d3098100af6320cccf1f3e36) @@ -57,6 +57,9 @@ import org.lamsfoundation.lams.notebook.model.NotebookEntry; import org.lamsfoundation.lams.notebook.service.CoreNotebookConstants; import org.lamsfoundation.lams.notebook.service.ICoreNotebookService; +import org.lamsfoundation.lams.qb.model.QbOption; +import org.lamsfoundation.lams.qb.model.QbQuestion; +import org.lamsfoundation.lams.qb.service.IQbService; import org.lamsfoundation.lams.rest.RestTags; import org.lamsfoundation.lams.rest.ToolRestManager; import org.lamsfoundation.lams.tool.ToolCompletionStatus; @@ -90,7 +93,6 @@ import org.lamsfoundation.lams.tool.scratchie.model.ScratchieItem; import org.lamsfoundation.lams.tool.scratchie.model.ScratchieSession; import org.lamsfoundation.lams.tool.scratchie.model.ScratchieUser; -import org.lamsfoundation.lams.tool.scratchie.util.ScratchieAnswerComparator; import org.lamsfoundation.lams.tool.scratchie.util.ScratchieItemComparator; import org.lamsfoundation.lams.tool.service.ILamsToolService; import org.lamsfoundation.lams.usermanagement.User; @@ -206,17 +208,27 @@ @Override public void saveOrUpdateScratchie(Scratchie scratchie) { + for (ScratchieItem item : scratchie.getScratchieItems()) { + scratchieItemDao.saveObject(item.getQbQuestion()); + scratchieItemDao.saveObject(item); + } scratchieDao.saveObject(scratchie); } @Override public void releaseItemsFromCache(Scratchie scratchie) { for (ScratchieItem item : scratchie.getScratchieItems()) { scratchieItemDao.releaseItemFromCache(item); + scratchieItemDao.releaseFromCache(item.getQbQuestion()); } } @Override + public void releaseFromCache(Object object) { + scratchieDao.releaseFromCache(object); + } + + @Override public ScratchieConfigItem getConfigItem(String key) { return scratchieConfigItemDao.getConfigItemByKey(key); } @@ -272,21 +284,22 @@ for (ScratchieItem item : items) { //init answers' confidenceLevelDtos list - for (ScratchieAnswer answer : (Set) item.getAnswers()) { - LinkedList confidenceLevelDtosTemp = new LinkedList(); + for (ScratchieAnswer answer : item.getAnswers()) { + LinkedList confidenceLevelDtosTemp = new LinkedList<>(); answer.setConfidenceLevelDtos(confidenceLevelDtosTemp); } //Assessment (similar with Scratchie) adds '\n' at the end of question, MCQ - '\r\n' - String question = item.getDescription() == null ? "" : item.getDescription().replaceAll("(\\r|\\n)", ""); + String question = item.getQbQuestion().getDescription() == null ? "" + : item.getQbQuestion().getDescription().replaceAll("(\\r|\\n)", ""); //find according confidenceLevelDto for (ConfidenceLevelDTO confidenceLevelDto : confidenceLevelDtos) { if (question.equals(confidenceLevelDto.getQuestion().replaceAll("(\\r|\\n)", ""))) { //find according answer for (ScratchieAnswer answer : (Set) item.getAnswers()) { - String answerText = answer.getDescription().replaceAll("(\\r|\\n)", ""); + String answerText = answer.getQbOption().getName().replaceAll("(\\r|\\n)", ""); if (answerText.equals(confidenceLevelDto.getAnswer().replaceAll("(\\r|\\n)", ""))) { answer.getConfidenceLevelDtos().add(confidenceLevelDto); } @@ -420,17 +433,18 @@ } @Override - public void recordItemScratched(Long sessionId, Long answerUid) { - ScratchieAnswer answer = this.getScratchieAnswerByUid(answerUid); + public void recordItemScratched(Long sessionId, Long itemUid, Long answerUid) { + QbOption answer = this.getQbOptionByUid(answerUid); if (answer == null) { return; } - ScratchieAnswerVisitLog log = scratchieAnswerVisitDao.getLog(answerUid, sessionId); + ScratchieAnswerVisitLog log = scratchieAnswerVisitDao.getLog(answerUid, itemUid, sessionId); if (log == null) { log = new ScratchieAnswerVisitLog(); - log.setScratchieAnswer(answer); + log.setQbOption(answer); log.setSessionId(sessionId); + log.setScratchieItemUid(itemUid); log.setAccessDate(new Timestamp(new Date().getTime())); scratchieAnswerVisitDao.saveObject(log); } @@ -487,19 +501,19 @@ boolean isItemModified = false; // title or description is different - if (!oldItem.getTitle().equals(newItem.getTitle()) - || !oldItem.getDescription().equals(newItem.getDescription())) { + if (!oldItem.getQbQuestion().getName().equals(newItem.getQbQuestion().getName()) || !oldItem + .getQbQuestion().getDescription().equals(newItem.getQbQuestion().getDescription())) { isItemModified = true; } // options are different - Set oldAnswers = oldItem.getAnswers(); - Set newAnswers = newItem.getAnswers(); - for (ScratchieAnswer oldAnswer : oldAnswers) { - for (ScratchieAnswer newAnswer : newAnswers) { + List oldAnswers = oldItem.getQbQuestion().getQbOptions(); + List newAnswers = newItem.getQbQuestion().getQbOptions(); + for (QbOption oldAnswer : oldAnswers) { + for (QbOption newAnswer : newAnswers) { if (oldAnswer.getUid().equals(newAnswer.getUid())) { - if (!StringUtils.equals(oldAnswer.getDescription(), newAnswer.getDescription()) + if (!StringUtils.equals(oldAnswer.getName(), newAnswer.getName()) || (oldAnswer.isCorrect() != newAnswer.isCorrect())) { isItemModified = true; } @@ -585,8 +599,9 @@ } @Override - public ScratchieAnswer getScratchieAnswerByUid(Long answerUid) { - ScratchieAnswer res = (ScratchieAnswer) userManagementService.findById(ScratchieAnswer.class, answerUid); + public QbOption getQbOptionByUid(Long optionUid) { + QbOption res = (QbOption) userManagementService.findById(QbOption.class, optionUid); + releaseFromCache(res); return res; } @@ -692,10 +707,11 @@ List itemLogs = scratchieAnswerVisitDao.getLogsBySessionAndItem(sessionId, item.getUid()); - for (ScratchieAnswer answer : (Set) item.getAnswers()) { + for (ScratchieAnswer answer : item.getAnswers()) { int attemptNumber; - ScratchieAnswerVisitLog log = scratchieAnswerVisitDao.getLog(answer.getUid(), sessionId); + ScratchieAnswerVisitLog log = scratchieAnswerVisitDao.getLog(answer.getQbOption().getUid(), + item.getUid(), sessionId); if (log == null) { // -1 if there is no log attemptNumber = -1; @@ -726,12 +742,13 @@ for (ScratchieItem item : items) { - for (ScratchieAnswer answer : (Set) item.getAnswers()) { + for (ScratchieAnswer answer : item.getAnswers()) { // find according log if it exists ScratchieAnswerVisitLog log = null; for (ScratchieAnswerVisitLog userLog : userLogs) { - if (userLog.getScratchieAnswer().getUid().equals(answer.getUid())) { + if (userLog.getQbOption().getUid().equals(answer.getQbOption().getUid()) + && userLog.getScratchieItemUid().equals(item.getUid())) { log = userLog; break; } @@ -762,11 +779,11 @@ private boolean isItemUnraveled(ScratchieItem item, List userLogs) { boolean isItemUnraveled = false; - for (ScratchieAnswer answer : (Set) item.getAnswers()) { + for (QbOption answer : item.getQbQuestion().getQbOptions()) { ScratchieAnswerVisitLog log = null; for (ScratchieAnswerVisitLog userLog : userLogs) { - if (userLog.getScratchieAnswer().getUid().equals(answer.getUid())) { + if (userLog.getQbOption().getUid().equals(answer.getUid())) { log = userLog; break; } @@ -819,7 +836,7 @@ int itemAttempts = 0; for (ScratchieAnswerVisitLog userLog : userLogs) { - if (userLog.getScratchieAnswer().getScratchieItem().getUid().equals(item.getUid())) { + if (userLog.getScratchieItemUid().equals(item.getUid())) { itemAttempts++; } } @@ -832,7 +849,7 @@ List groupSummaryList = new ArrayList<>(); ScratchieItem item = scratchieItemDao.getByUid(itemUid); - Collection answers = item.getAnswers(); + List answers = item.getQbQuestion().getQbOptions(); List sessionList = scratchieSessionDao.getByContentId(contentId); for (ScratchieSession session : sessionList) { Long sessionId = session.getSessionId(); @@ -841,11 +858,11 @@ GroupSummary groupSummary = new GroupSummary(session); Map answerMap = new HashMap<>(); - for (ScratchieAnswer dbAnswer : (Set) answers) { + for (QbOption dbAnswer : answers) { // clone it so it doesn't interfere with values from other sessions - ScratchieAnswer answer = (ScratchieAnswer) dbAnswer.clone(); - answer.setUid(dbAnswer.getUid()); + ScratchieAnswer answer = new ScratchieAnswer(); + answer.setQbOption(dbAnswer); int[] attempts = new int[answers.size()]; answer.setAttempts(attempts); answerMap.put(dbAnswer.getUid(), answer); @@ -860,14 +877,14 @@ int attemptNumber = 0; for (ScratchieAnswerVisitLog attempt : sessionAttempts) { - ScratchieAnswer answer = answerMap.get(attempt.getScratchieAnswer().getUid()); + ScratchieAnswer answer = answerMap.get(attempt.getQbOption().getUid()); int[] attempts = answer.getAttempts(); // +1 for corresponding choice attempts[attemptNumber++]++; } } - Collection sortedAnswers = new TreeSet<>(new ScratchieAnswerComparator()); + Collection sortedAnswers = new LinkedList<>(); sortedAnswers.addAll(answerMap.values()); groupSummary.setAnswers(sortedAnswers); groupSummaryList.add(groupSummary); @@ -881,9 +898,11 @@ groupSummaryTotal.setMark(0); Map answerMapTotal = new HashMap<>(); - for (ScratchieAnswer dbAnswer : (Set) answers) { + for (QbOption dbAnswer : answers) { + // clone it so it doesn't interfere with values from other sessions - ScratchieAnswer answer = (ScratchieAnswer) dbAnswer.clone(); + ScratchieAnswer answer = new ScratchieAnswer(); + answer.setQbOption(dbAnswer); int[] attempts = new int[answers.size()]; answer.setAttempts(attempts); answerMapTotal.put(dbAnswer.getUid(), answer); @@ -894,15 +913,15 @@ for (ScratchieAnswer sortedAnswer : sortedAnswers) { int[] attempts = sortedAnswer.getAttempts(); - ScratchieAnswer answerTotal = answerMapTotal.get(sortedAnswer.getUid()); + ScratchieAnswer answerTotal = answerMapTotal.get(sortedAnswer.getQbOption().getUid()); int[] attemptsTotal = answerTotal.getAttempts(); for (int i = 0; i < attempts.length; i++) { attemptsTotal[i] += attempts[i]; } } } - Collection sortedAnswers = new TreeSet<>(new ScratchieAnswerComparator()); + Collection sortedAnswers = new TreeSet<>(); sortedAnswers.addAll(answerMapTotal.values()); groupSummaryTotal.setAnswers(sortedAnswers); groupSummaryList.add(0, groupSummaryTotal); @@ -949,9 +968,10 @@ // handle general burning question BurningQuestionItemDTO generalBurningQuestionItemDto = new BurningQuestionItemDTO(); ScratchieItem generalDummyItem = new ScratchieItem(); - generalDummyItem.setUid(0L); + generalDummyItem.setQbQuestion(new QbQuestion()); + // generalDummyItem.setUid(0L); final String generalQuestionMessage = messageService.getMessage("label.general.burning.question"); - generalDummyItem.setTitle(generalQuestionMessage); + generalDummyItem.getQbQuestion().setName(generalQuestionMessage); generalBurningQuestionItemDto.setScratchieItem(generalDummyItem); List burningQuestionDtosOfSpecifiedItem = new ArrayList<>(); for (BurningQuestionDTO burningQuestionDto : burningQuestionDtos) { @@ -1153,7 +1173,7 @@ String correctAnswerLetter = ""; int answerCount = 1; for (ScratchieAnswer answer : (Set) item.getAnswers()) { - if (answer.isCorrect()) { + if (answer.getQbOption().isCorrect()) { correctAnswerLetter = String.valueOf((char) ((answerCount + 'A') - 1)); break; } @@ -1337,11 +1357,12 @@ List itemSummary = getQuestionSummary(contentId, item.getUid()); row = new ExcelCell[1]; - row[0] = new ExcelCell(getMessage("label.question.semicolon", new Object[] { item.getTitle() }), true); + row[0] = new ExcelCell( + getMessage("label.question.semicolon", new Object[] { item.getQbQuestion().getName() }), true); rowList.add(row); row = new ExcelCell[1]; - row[0] = new ExcelCell(removeHtmlMarkup(item.getDescription()), true); + row[0] = new ExcelCell(removeHtmlMarkup(item.getQbQuestion().getDescription()), true); rowList.add(row); rowList.add(ScratchieServiceImpl.EMPTY_ROW); rowList.add(ScratchieServiceImpl.EMPTY_ROW); @@ -1363,9 +1384,9 @@ for (ScratchieAnswer answer : answers) { row = new ExcelCell[1 + answers.size()]; - String answerTitle = removeHtmlMarkup(answer.getDescription()); + String answerTitle = removeHtmlMarkup(answer.getQbOption().getName()); IndexedColors color = null; - if (answer.isCorrect()) { + if (answer.getQbOption().isCorrect()) { answerTitle += "(" + getMessage("label.monitoring.item.summary.correct") + ")"; color = IndexedColors.GREEN; } @@ -1403,8 +1424,8 @@ for (ScratchieAnswer answer : answers) { row = new ExcelCell[1 + answers.size()]; - String answerTitle = removeHtmlMarkup(answer.getDescription()); - if (answer.isCorrect()) { + String answerTitle = removeHtmlMarkup(answer.getQbOption().getName()); + if (answer.getQbOption().isCorrect()) { answerTitle += "(" + getMessage("label.monitoring.item.summary.correct") + ")"; } columnCount = 0; @@ -1451,7 +1472,8 @@ for (ScratchieItem item : items) { row = new ExcelCell[1]; - row[0] = new ExcelCell(getMessage("label.question.semicolon", new Object[] { item.getTitle() }), + row[0] = new ExcelCell( + getMessage("label.question.semicolon", new Object[] { item.getQbQuestion().getName() }), false); rowList.add(row); rowList.add(ScratchieServiceImpl.EMPTY_ROW); @@ -1462,7 +1484,7 @@ for (ScratchieAnswerVisitLog log : logs) { row = new ExcelCell[4]; row[0] = new ExcelCell(new Long(i++), false); - String answerDescr = removeHtmlMarkup(log.getScratchieAnswer().getDescription()); + String answerDescr = removeHtmlMarkup(log.getQbOption().getName()); row[1] = new ExcelCell(answerDescr, false); row[3] = new ExcelCell(fullDateFormat.format(log.getAccessDate()), false); rowList.add(row); @@ -1536,10 +1558,10 @@ // correct answer String correctAnswer = ""; - Set answers = itemDto.getAnswers(); + List answers = itemDto.getAnswers(); for (ScratchieAnswer answer : answers) { - if (answer.isCorrect()) { - correctAnswer = removeHtmlMarkup(answer.getDescription()); + if (answer.getQbOption().isCorrect()) { + correctAnswer = removeHtmlMarkup(answer.getQbOption().getName()); } } row[columnCount++] = new ExcelCell(correctAnswer, false); @@ -1569,7 +1591,7 @@ } for (ScratchieAnswerVisitLog log : logs) { - String answer = removeHtmlMarkup(log.getScratchieAnswer().getDescription()); + String answer = removeHtmlMarkup(log.getQbOption().getName()); row[columnCount++] = new ExcelCell(answer, false); } for (int i = logs.size(); i < itemDto.getAnswers().size(); i++) { @@ -1630,7 +1652,7 @@ for (BurningQuestionItemDTO burningQuestionItemDto : burningQuestionItemDtos) { ScratchieItem item = burningQuestionItemDto.getScratchieItem(); row = new ExcelCell[1]; - row[0] = new ExcelCell(item.getTitle(), false); + row[0] = new ExcelCell(item.getQbQuestion().getName(), false); rowList.add(row); List burningQuestionDtos = burningQuestionItemDto.getBurningQuestionDtos(); @@ -1676,6 +1698,16 @@ return newDto; } + @Override + public int isQbQuestionModified(QbQuestion baseLine, QbQuestion modifiedQuestion) { + if (baseLine.getUid() == null) { + return IQbService.QUESTION_MODIFIED_ID_BUMP; + } + + return baseLine.isModified(modifiedQuestion) ? IQbService.QUESTION_MODIFIED_VERSION_BUMP + : IQbService.QUESTION_MODIFIED_NONE; + } + // ***************************************************************************** // private methods // ***************************************************************************** @@ -1719,7 +1751,7 @@ //create a list of attempts user done for the current item List itemAttempts = new ArrayList<>(); for (ScratchieAnswerVisitLog answerLog : answerLogs) { - if (answerLog.getScratchieAnswer().getScratchieItem().getUid().equals(item.getUid())) { + if (answerLog.getScratchieItemUid().equals(item.getUid())) { itemAttempts.add(answerLog); } } @@ -1733,14 +1765,14 @@ // find out answers' sequential letters - A,B,C... for (ScratchieAnswerVisitLog itemAttempt : itemAttempts) { String sequencialLetter = ScratchieServiceImpl.getSequencialLetter(item, - itemAttempt.getScratchieAnswer()); + itemAttempt.getQbOption()); answersSequence += answersSequence.isEmpty() ? sequencialLetter : ", " + sequencialLetter; } } itemDto.setUid(item.getUid()); - itemDto.setTitle(item.getTitle()); + itemDto.setTitle(item.getQbQuestion().getName()); itemDto.setAnswers(item.getAnswers()); itemDto.setUserAttempts(numberOfAttempts); itemDto.setUserMark(mark); @@ -1760,12 +1792,12 @@ /** * Return specified answer's sequential letter (e.g. A,B,C) among other possible answers */ - private static String getSequencialLetter(ScratchieItem item, ScratchieAnswer asnwer) { + private static String getSequencialLetter(ScratchieItem item, QbOption asnwer) { String sequencialLetter = ""; int answerCount = 1; for (ScratchieAnswer answer : (Set) item.getAnswers()) { - if (answer.getUid().equals(asnwer.getUid())) { + if (answer.getQbOption().getUid().equals(asnwer.getUid())) { sequencialLetter = String.valueOf((char) ((answerCount + 'A') - 1)); break; } @@ -1806,7 +1838,7 @@ public void auditLogStartEditingActivityInMonitor(long toolContentID) { toolService.auditLogStartEditingActivityInMonitor(toolContentID); } - + @Override public boolean isLastActivity(Long toolSessionId) { return toolService.isLastActivity(toolSessionId); @@ -1885,9 +1917,9 @@ // include the hibernate object version of the ScratchieItem within the XML Set items = toolContentObj.getScratchieItems(); for (ScratchieItem item : items) { - Set answers = item.getAnswers(); - for (ScratchieAnswer answer : answers) { - answer.setScratchieItem(null); + Collection answers = item.getQbQuestion().getQbOptions(); + for (QbOption answer : answers) { + answer.setQbQuestion(null); } } @@ -1976,17 +2008,7 @@ } Scratchie toContent = Scratchie.newInstance(scratchie, toContentId); - scratchieDao.saveObject(toContent); - - // save scratchie items as well - Set items = toContent.getScratchieItems(); - if (items != null) { - Iterator iter = items.iterator(); - while (iter.hasNext()) { - ScratchieItem item = iter.next(); - // createRootTopic(toContent.getUid(),null,msg); - } - } + saveOrUpdateScratchie(toContent); } @Override @@ -2276,31 +2298,29 @@ ObjectNode questionData = (ObjectNode) questions.get(i); ScratchieItem item = new ScratchieItem(); - item.setCreateDate(updateDate); - item.setCreateByAuthor(true); item.setOrderId(JsonUtil.optInt(questionData, RestTags.DISPLAY_ORDER)); - item.setTitle(JsonUtil.optString(questionData, RestTags.QUESTION_TITLE)); - item.setDescription(JsonUtil.optString(questionData, RestTags.QUESTION_TEXT)); + item.getQbQuestion().setName(JsonUtil.optString(questionData, RestTags.QUESTION_TITLE)); + item.getQbQuestion().setDescription(JsonUtil.optString(questionData, RestTags.QUESTION_TEXT)); newItems.add(item); // set options - Set newAnswers = new LinkedHashSet<>(); + List newAnswers = new LinkedList<>(); ArrayNode answersData = JsonUtil.optArray(questionData, RestTags.ANSWERS); for (int j = 0; j < answersData.size(); j++) { ObjectNode answerData = (ObjectNode) answersData.get(j); - ScratchieAnswer answer = new ScratchieAnswer(); + QbOption answer = new QbOption(); // Removes redundant new line characters from options left by CKEditor (otherwise it will break // Javascript in monitor). Copied from AuthoringAction. String answerDescription = JsonUtil.optString(answerData, RestTags.ANSWER_TEXT); - answer.setDescription(answerDescription != null ? answerDescription.replaceAll("[\n\r\f]", "") : ""); + answer.setName(answerDescription != null ? answerDescription.replaceAll("[\n\r\f]", "") : ""); answer.setCorrect(JsonUtil.optBoolean(answerData, RestTags.CORRECT)); - answer.setOrderId(JsonUtil.optInt(answerData, RestTags.DISPLAY_ORDER)); - answer.setScratchieItem(item); + answer.setDisplayOrder(JsonUtil.optInt(answerData, RestTags.DISPLAY_ORDER)); + answer.setQbQuestion(item.getQbQuestion()); newAnswers.add(answer); } - item.setAnswers(newAnswers); + item.getQbQuestion().setQbOptions(newAnswers); } Fisheye: Tag fba7287887f6dd83d3098100af6320cccf1f3e36 refers to a dead (removed) revision in file `lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/util/ScratchieAnswerComparator.java'. Fisheye: No comparison available. Pass `N' to diff? Index: lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/util/ScratchieItemComparator.java =================================================================== diff -u -r7475d08afc280b5e2e5ddf04e8bf35e3166aaf80 -rfba7287887f6dd83d3098100af6320cccf1f3e36 --- lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/util/ScratchieItemComparator.java (.../ScratchieItemComparator.java) (revision 7475d08afc280b5e2e5ddf04e8bf35e3166aaf80) +++ lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/util/ScratchieItemComparator.java (.../ScratchieItemComparator.java) (revision fba7287887f6dd83d3098100af6320cccf1f3e36) @@ -15,12 +15,10 @@ } else { return -1; } - } else if (o1 != null && o2 != null & o1.getCreateDate() != null && o2.getCreateDate() != null) { - return (o1.getCreateDate().getTime() - o2.getCreateDate().getTime()) > 0 ? 1 : -1; } else if (o1 != null) { return 1; } else { return -1; } } -} +} \ No newline at end of file Index: lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/web/controller/AuthoringController.java =================================================================== diff -u -rf2ad75cef0c507a64877942631fee13efbc6ed50 -rfba7287887f6dd83d3098100af6320cccf1f3e36 --- lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/web/controller/AuthoringController.java (.../AuthoringController.java) (revision f2ad75cef0c507a64877942631fee13efbc6ed50) +++ lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/web/controller/AuthoringController.java (.../AuthoringController.java) (revision fba7287887f6dd83d3098100af6320cccf1f3e36) @@ -28,6 +28,7 @@ import java.net.URLDecoder; import java.sql.Timestamp; import java.util.ArrayList; +import java.util.Collection; import java.util.Date; import java.util.HashMap; import java.util.HashSet; @@ -48,18 +49,19 @@ import org.apache.commons.lang.math.NumberUtils; import org.apache.log4j.Logger; import org.lamsfoundation.lams.learningdesign.ToolActivity; +import org.lamsfoundation.lams.qb.model.QbOption; +import org.lamsfoundation.lams.qb.model.QbQuestion; +import org.lamsfoundation.lams.qb.service.IQbService; import org.lamsfoundation.lams.questions.Answer; import org.lamsfoundation.lams.questions.Question; import org.lamsfoundation.lams.questions.QuestionExporter; import org.lamsfoundation.lams.questions.QuestionParser; import org.lamsfoundation.lams.tool.ToolAccessMode; import org.lamsfoundation.lams.tool.scratchie.ScratchieConstants; import org.lamsfoundation.lams.tool.scratchie.model.Scratchie; -import org.lamsfoundation.lams.tool.scratchie.model.ScratchieAnswer; import org.lamsfoundation.lams.tool.scratchie.model.ScratchieConfigItem; import org.lamsfoundation.lams.tool.scratchie.model.ScratchieItem; import org.lamsfoundation.lams.tool.scratchie.service.IScratchieService; -import org.lamsfoundation.lams.tool.scratchie.util.ScratchieAnswerComparator; import org.lamsfoundation.lams.tool.scratchie.util.ScratchieItemComparator; import org.lamsfoundation.lams.tool.scratchie.web.form.ScratchieForm; import org.lamsfoundation.lams.tool.scratchie.web.form.ScratchieItemForm; @@ -90,6 +92,9 @@ private IScratchieService scratchieService; @Autowired + private IQbService qbService; + + @Autowired @Qualifier("scratchieMessageService") private MessageService messageService; @@ -177,14 +182,6 @@ // init it to avoid null exception in following handling if (items == null) { items = new ArrayList<>(); - } else { - for (ScratchieItem item : items) { - - // sort answers by order id. it's needed only for the default answers. rest could be skipped - TreeSet answerList = new TreeSet<>(new ScratchieAnswerComparator()); - answerList.addAll(item.getAnswers()); - item.setAnswers(answerList); - } } // init scratchie item list SortedSet itemList = getItemList(sessionMap); @@ -257,23 +254,18 @@ //allow using old and modified questions and references altogether if (mode.isTeacher()) { oldItems = (scratchiePO == null) ? new HashSet<>() : scratchiePO.getScratchieItems(); - - // initialize oldItems' answers - for (ScratchieItem oldItem : oldItems) { - for (ScratchieAnswer answer : (Set) oldItem.getAnswers()) { - } - } - - scratchieService.releaseItemsFromCache(scratchiePO); } if (scratchiePO == null) { // new Scratchie, create it. scratchiePO = scratchie; scratchiePO.setCreated(new Timestamp(new Date().getTime())); scratchiePO.setUpdated(new Timestamp(new Date().getTime())); - } else { + // copyProperties() below sets scratchiePO's items to empty collection + // but the items still exist in Hibernate cache, so we need to evict them now + scratchieService.releaseItemsFromCache(scratchiePO); + scratchiePO.getScratchieItems().clear(); Long uid = scratchiePO.getUid(); PropertyUtils.copyProperties(scratchiePO, scratchie); // set back UID @@ -296,6 +288,26 @@ if (item != null) { removeNewLineCharacters(item); items.add(item); + // modification status was already set in AuthoringController#saveItem() + switch (item.getQbQuestionModified()) { + case IQbService.QUESTION_MODIFIED_VERSION_BUMP: { + // new version of the old question gets created + QbQuestion qbQuestion = item.getQbQuestion().clone(); + item.setQbQuestion(qbQuestion); + qbQuestion.clearID(); + qbQuestion.setVersion(qbService.getMaxQuestionVersion(qbQuestion.getQuestionId())); + } + break; + case IQbService.QUESTION_MODIFIED_ID_BUMP: { + // new question gets created + QbQuestion qbQuestion = item.getQbQuestion().clone(); + item.setQbQuestion(qbQuestion); + qbQuestion.clearID(); + qbQuestion.setVersion(1); + qbQuestion.setQuestionId(qbService.getMaxQuestionId()); + } + break; + } } } scratchiePO.setScratchieItems(items); @@ -342,10 +354,10 @@ scratchieItemForm.setSessionMapID(sessionMapID); scratchieItemForm.setContentFolderID(contentFolderID); - List answerList = new ArrayList<>(); + List answerList = new ArrayList<>(); for (int i = 0; i < ScratchieConstants.INITIAL_ANSWERS_NUMBER; i++) { - ScratchieAnswer answer = new ScratchieAnswer(); - answer.setOrderId(i + 1); + QbOption answer = new QbOption(); + answer.setDisplayOrder(i + 1); answerList.add(answer); } request.setAttribute(ScratchieConstants.ATTR_ANSWER_LIST, answerList); @@ -374,13 +386,13 @@ List rList = new ArrayList<>(itemList); item = rList.get(itemIdx); if (item != null) { - scratchieItemForm.setTitle(item.getTitle()); - scratchieItemForm.setDescription(item.getDescription()); + scratchieItemForm.setTitle(item.getQbQuestion().getName()); + scratchieItemForm.setDescription(item.getQbQuestion().getDescription()); if (itemIdx >= 0) { scratchieItemForm.setItemIndex(new Integer(itemIdx).toString()); } - Set answerList = item.getAnswers(); + List answerList = item.getQbQuestion().getQbOptions(); request.setAttribute(ScratchieConstants.ATTR_ANSWER_LIST, answerList); scratchieItemForm.setContentFolderID(contentFolderID); @@ -410,7 +422,9 @@ if (itemIdx == -1) { // add item = new ScratchieItem(); - item.setCreateDate(new Timestamp(new Date().getTime())); + QbQuestion qbQuestion = new QbQuestion(); + qbQuestion.setType(QbQuestion.TYPE_MULTIPLE_CHOICE_SINGLE_ANSWER); + item.setQbQuestion(qbQuestion); int maxSeq = 1; if (itemList != null && itemList.size() > 0) { ScratchieItem last = itemList.last(); @@ -423,19 +437,29 @@ item = rList.get(itemIdx); } - item.setTitle(scratchieItemForm.getTitle()); - item.setDescription(scratchieItemForm.getDescription()); + QbQuestion baseLine = item.getQbQuestion().clone(); + // evict everything manually as we do not use DTOs, just real entities + // without eviction changes would be saved immediately into DB + scratchieService.releaseFromCache(item); + scratchieService.releaseFromCache(baseLine); + scratchieService.releaseFromCache(item.getQbQuestion()); + item.getQbQuestion().setName(scratchieItemForm.getTitle()); + item.getQbQuestion().setDescription(scratchieItemForm.getDescription()); + // set options - Set answerList = getAnswersFromRequest(request, true); - Set answers = new LinkedHashSet<>(); + Set answerList = getAnswersFromRequest(request, true); + List answers = new ArrayList<>(); int orderId = 0; - for (ScratchieAnswer answer : answerList) { - answer.setOrderId(orderId++); + for (QbOption answer : answerList) { + answer.setDisplayOrder(orderId++); answers.add(answer); } - item.setAnswers(answers); + item.getQbQuestion().setQbOptions(answers); + item.setQbQuestionModified(scratchieService.isQbQuestionModified(baseLine, item.getQbQuestion())); + request.setAttribute("qbQuestionModified", item.getQbQuestionModified()); + // set session map ID so that itemlist.jsp can get sessionMAP request.setAttribute(ScratchieConstants.ATTR_SESSION_MAP_ID, scratchieItemForm.getSessionMapID()); return "pages/authoring/parts/itemlist"; @@ -457,18 +481,17 @@ Question[] questions = QuestionParser.parseQuestionChoiceForm(request); for (Question question : questions) { ScratchieItem item = new ScratchieItem(); - item.setCreateDate(new Timestamp(new Date().getTime())); int maxSeq = 1; if (itemList != null && itemList.size() > 0) { ScratchieItem last = itemList.last(); maxSeq = last.getOrderId() + 1; } item.setOrderId(maxSeq); - item.setTitle(question.getTitle()); - item.setDescription(QuestionParser.processHTMLField(question.getText(), false, contentFolderID, - question.getResourcesFolderPath())); + item.getQbQuestion().setName(question.getTitle()); + item.getQbQuestion().setDescription(QuestionParser.processHTMLField(question.getText(), false, + contentFolderID, question.getResourcesFolderPath())); - TreeSet answerList = new TreeSet<>(new ScratchieAnswerComparator()); + TreeSet answerList = new TreeSet<>(); String correctAnswer = null; int orderId = 1; if (question.getAnswers() != null) { @@ -479,9 +502,9 @@ log.warn("Skipping an answer with same text as the correct answer: " + answerText); continue; } - ScratchieAnswer scratchieAnswer = new ScratchieAnswer(); - scratchieAnswer.setDescription(answerText); - scratchieAnswer.setOrderId(orderId++); + QbOption scratchieAnswer = new QbOption(); + scratchieAnswer.setName(answerText); + scratchieAnswer.setDisplayOrder(orderId++); if ((answer.getScore() != null) && (answer.getScore() > 0)) { if (correctAnswer == null) { @@ -505,7 +528,7 @@ continue; } - item.setAnswers(answerList); + item.getQbQuestion().setQbOptions(new ArrayList<>(answerList)); itemList.add(item); if (log.isDebugEnabled()) { log.debug("Added question: " + question.getText()); @@ -533,16 +556,16 @@ Question question = new Question(); question.setType(Question.QUESTION_TYPE_MULTIPLE_CHOICE); - question.setTitle(item.getTitle()); - question.setText(item.getDescription()); + question.setTitle(item.getQbQuestion().getName()); + question.setText(item.getQbQuestion().getDescription()); List answers = new ArrayList<>(); - Set scratchieAnswers = new TreeSet<>(new ScratchieAnswerComparator()); - scratchieAnswers.addAll(item.getAnswers()); + Set scratchieAnswers = new TreeSet<>(); + scratchieAnswers.addAll(item.getQbQuestion().getQbOptions()); - for (ScratchieAnswer itemAnswer : scratchieAnswers) { + for (QbOption itemAnswer : scratchieAnswers) { Answer answer = new Answer(); - answer.setText(itemAnswer.getDescription()); + answer.setText(itemAnswer.getName()); // there is no LAMS interface to adjust, so use the default 1 point Float score = itemAnswer.isCorrect() ? 1F : 0; answer.setScore(score); @@ -669,15 +692,15 @@ @RequestMapping("/addAnswer") private String addAnswer(HttpServletRequest request) { - SortedSet answerList = getAnswersFromRequest(request, false); + SortedSet answerList = getAnswersFromRequest(request, false); - ScratchieAnswer answer = new ScratchieAnswer(); + QbOption answer = new QbOption(); int maxSeq = 1; if (answerList != null && answerList.size() > 0) { - ScratchieAnswer last = answerList.last(); - maxSeq = last.getOrderId() + 1; + QbOption last = answerList.last(); + maxSeq = last.getDisplayOrder() + 1; } - answer.setOrderId(maxSeq); + answer.setDisplayOrder(maxSeq); answerList.add(answer); request.setAttribute(ScratchieConstants.ATTR_ANSWER_LIST, answerList); @@ -698,11 +721,11 @@ @RequestMapping("/removeAnswer") private String removeAnswer(HttpServletRequest request) { - SortedSet answerList = getAnswersFromRequest(request, false); + SortedSet answerList = getAnswersFromRequest(request, false); int answerIndex = NumberUtils.toInt(request.getParameter(ScratchieConstants.PARAM_ANSWER_INDEX), -1); if (answerIndex != -1) { - List rList = new ArrayList<>(answerList); + List rList = new ArrayList<>(answerList); rList.remove(answerIndex); answerList.clear(); answerList.addAll(rList); @@ -743,24 +766,24 @@ } private String switchAnswer(HttpServletRequest request, boolean up) { - SortedSet answerList = getAnswersFromRequest(request, false); + SortedSet answerList = getAnswersFromRequest(request, false); int answerIndex = NumberUtils.toInt(request.getParameter(ScratchieConstants.PARAM_ANSWER_INDEX), -1); if (answerIndex != -1) { - List rList = new ArrayList<>(answerList); + List rList = new ArrayList<>(answerList); // get current and the target item, and switch their sequnece - ScratchieAnswer answer = rList.get(answerIndex); - ScratchieAnswer repAnswer; + QbOption answer = rList.get(answerIndex); + QbOption repAnswer; if (up) { repAnswer = rList.get(--answerIndex); } else { repAnswer = rList.get(++answerIndex); } - int upSeqId = repAnswer.getOrderId(); - repAnswer.setOrderId(answer.getOrderId()); - answer.setOrderId(upSeqId); + int upSeqId = repAnswer.getDisplayOrder(); + repAnswer.setDisplayOrder(answer.getDisplayOrder()); + answer.setDisplayOrder(upSeqId); // put back list, it will be sorted again answerList.clear(); @@ -852,34 +875,39 @@ * whether the blank options will be preserved or not * */ - private TreeSet getAnswersFromRequest(HttpServletRequest request, boolean isForSaving) { + private TreeSet getAnswersFromRequest(HttpServletRequest request, boolean isForSaving) { Map paramMap = splitRequestParameter(request, ScratchieConstants.ATTR_ANSWER_LIST); Integer correctAnswerIndex = (paramMap.get(ScratchieConstants.ATTR_ANSWER_CORRECT) == null) ? null : NumberUtils.toInt(paramMap.get(ScratchieConstants.ATTR_ANSWER_CORRECT)); int count = NumberUtils.toInt(paramMap.get(ScratchieConstants.ATTR_ANSWER_COUNT)); - TreeSet answerList = new TreeSet<>(new ScratchieAnswerComparator()); + TreeSet answerList = new TreeSet<>(); for (int i = 0; i < count; i++) { String answerDescription = paramMap.get(ScratchieConstants.ATTR_ANSWER_DESCRIPTION_PREFIX + i); if ((answerDescription == null) && isForSaving) { continue; } - ScratchieAnswer answer = new ScratchieAnswer(); + QbOption answer = null; String uidStr = paramMap.get(ScratchieConstants.ATTR_ANSWER_UID_PREFIX + i); if (uidStr != null) { Long uid = NumberUtils.toLong(uidStr); - answer.setUid(uid); + answer = scratchieService.getQbOptionByUid(uid); + scratchieService.releaseFromCache(answer.getQbQuestion()); + } else { + answer = new QbOption(); } + String orderIdStr = paramMap.get(ScratchieConstants.ATTR_ANSWER_ORDER_ID_PREFIX + i); Integer orderId = NumberUtils.toInt(orderIdStr); - answer.setOrderId(orderId); - answer.setDescription(answerDescription); + answer.setDisplayOrder(orderId); + answer.setName(answerDescription); if ((correctAnswerIndex != null) && correctAnswerIndex.equals(orderId)) { answer.setCorrect(true); } answerList.add(answer); + } return answerList; @@ -920,17 +948,16 @@ * monitor) */ private void removeNewLineCharacters(ScratchieItem item) { - Set answers = item.getAnswers(); + Collection answers = item.getQbQuestion().getQbOptions(); if (answers != null) { - for (ScratchieAnswer answer : answers) { - String answerDescription = answer.getDescription(); + for (QbOption answer : answers) { + String answerDescription = answer.getName(); if (answerDescription != null) { answerDescription = answerDescription.replaceAll("[\n\r\f]", ""); - answer.setDescription(answerDescription); + answer.setName(answerDescription); } } } } - -} +} \ No newline at end of file Index: lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/web/controller/LearningController.java =================================================================== diff -u -r3ee06bc1b00b1673399c1871a73cfa1d8ec2c0db -rfba7287887f6dd83d3098100af6320cccf1f3e36 --- lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/web/controller/LearningController.java (.../LearningController.java) (revision 3ee06bc1b00b1673399c1871a73cfa1d8ec2c0db) +++ lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/web/controller/LearningController.java (.../LearningController.java) (revision fba7287887f6dd83d3098100af6320cccf1f3e36) @@ -46,12 +46,12 @@ import org.apache.log4j.Logger; import org.lamsfoundation.lams.notebook.model.NotebookEntry; import org.lamsfoundation.lams.notebook.service.CoreNotebookConstants; +import org.lamsfoundation.lams.qb.model.QbOption; import org.lamsfoundation.lams.tool.ToolAccessMode; import org.lamsfoundation.lams.tool.scratchie.ScratchieConstants; import org.lamsfoundation.lams.tool.scratchie.dto.BurningQuestionItemDTO; import org.lamsfoundation.lams.tool.scratchie.dto.ReflectDTO; import org.lamsfoundation.lams.tool.scratchie.model.Scratchie; -import org.lamsfoundation.lams.tool.scratchie.model.ScratchieAnswer; import org.lamsfoundation.lams.tool.scratchie.model.ScratchieBurningQuestion; import org.lamsfoundation.lams.tool.scratchie.model.ScratchieItem; import org.lamsfoundation.lams.tool.scratchie.model.ScratchieSession; @@ -168,7 +168,7 @@ if (isUserLeader) { Set answerUids = new HashSet<>(); for (ScratchieItem item : scratchie.getScratchieItems()) { - for (ScratchieAnswer answer : (Set) item.getAnswers()) { + for (QbOption answer : item.getQbQuestion().getQbOptions()) { answerUids.add(answer.getUid()); } } @@ -355,6 +355,7 @@ .getAttribute(sessionMapID); final Long toolSessionId = (Long) sessionMap.get(AttributeNames.PARAM_TOOL_SESSION_ID); final Long answerUid = NumberUtils.createLong(request.getParameter(ScratchieConstants.PARAM_ANSWER_UID)); + final Long itemUid = NumberUtils.createLong(request.getParameter(ScratchieConstants.PARAM_ITEM_UID)); ScratchieSession toolSession = scratchieService.getScratchieSessionBySessionId(toolSessionId); @@ -371,7 +372,7 @@ } // Return whether scratchie answer is correct or not - ScratchieAnswer answer = scratchieService.getScratchieAnswerByUid(answerUid); + QbOption answer = scratchieService.getQbOptionByUid(answerUid); if (answer == null) { return null; } @@ -386,7 +387,7 @@ Thread recordItemScratchedThread = new Thread(new Runnable() { @Override public void run() { - scratchieService.recordItemScratched(toolSessionId, answerUid); + scratchieService.recordItemScratched(toolSessionId, itemUid, answerUid); } }, "LAMS_recordItemScratched_thread"); recordItemScratchedThread.start(); Index: lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/web/controller/LearningWebsocketServer.java =================================================================== diff -u -r9b4a3799f9589dbda9a792e10a4ebd649db1e3db -rfba7287887f6dd83d3098100af6320cccf1f3e36 --- lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/web/controller/LearningWebsocketServer.java (.../LearningWebsocketServer.java) (revision 9b4a3799f9589dbda9a792e10a4ebd649db1e3db) +++ lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/web/controller/LearningWebsocketServer.java (.../LearningWebsocketServer.java) (revision fba7287887f6dd83d3098100af6320cccf1f3e36) @@ -163,8 +163,8 @@ } } - Long answerUid = answer.getUid(); - Boolean answerStoredIsCorrect = answer.isCorrect(); + Long answerUid = answer.getQbOption().getUid(); + Boolean answerStoredIsCorrect = answer.getQbOption().isCorrect(); Boolean answerCache = itemCache.get(answerUid); // check if the correct answer is stored in cache if ((answerCache == null) || !answerCache.equals(answerStoredIsCorrect)) { @@ -227,8 +227,8 @@ sessionWebsockets.add(websocket); if (log.isDebugEnabled()) { - log.debug("User " + websocket.getUserPrincipal().getName() - + " entered Scratchie with toolSessionId: " + toolSessionId); + log.debug("User " + websocket.getUserPrincipal().getName() + " entered Scratchie with toolSessionId: " + + toolSessionId); } } @@ -243,8 +243,8 @@ if (log.isDebugEnabled()) { // If there was something wrong with the connection, put it into logs. - log.debug("User " + websocket.getUserPrincipal().getName() - + " left Scratchie with Tool Session ID: " + toolSessionId + log.debug("User " + websocket.getUserPrincipal().getName() + " left Scratchie with Tool Session ID: " + + toolSessionId + (!(reason.getCloseCode().equals(CloseCodes.GOING_AWAY) || reason.getCloseCode().equals(CloseCodes.NORMAL_CLOSURE)) ? ". Abnormal close. Code: " + reason.getCloseCode() + ". Reason: " Index: lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/web/controller/MonitoringController.java =================================================================== diff -u -rf2ad75cef0c507a64877942631fee13efbc6ed50 -rfba7287887f6dd83d3098100af6320cccf1f3e36 --- lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/web/controller/MonitoringController.java (.../MonitoringController.java) (revision f2ad75cef0c507a64877942631fee13efbc6ed50) +++ lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/web/controller/MonitoringController.java (.../MonitoringController.java) (revision fba7287887f6dd83d3098100af6320cccf1f3e36) @@ -149,9 +149,9 @@ // escape JS sensitive characters in answer descriptions for (GroupSummary summary : summaryList) { for (ScratchieAnswer answer : summary.getAnswers()) { - String description = (answer.getDescription() == null) ? "" - : StringEscapeUtils.escapeJavaScript(answer.getDescription()); - answer.setDescription(description); + String description = (answer.getQbOption().getName() == null) ? "" + : StringEscapeUtils.escapeJavaScript(answer.getQbOption().getName()); + answer.getQbOption().setName(description); } } Index: lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/web/controller/TblMonitorController.java =================================================================== diff -u -rf2ad75cef0c507a64877942631fee13efbc6ed50 -rfba7287887f6dd83d3098100af6320cccf1f3e36 --- lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/web/controller/TblMonitorController.java (.../TblMonitorController.java) (revision f2ad75cef0c507a64877942631fee13efbc6ed50) +++ lams_tool_scratchie/src/java/org/lamsfoundation/lams/tool/scratchie/web/controller/TblMonitorController.java (.../TblMonitorController.java) (revision fba7287887f6dd83d3098100af6320cccf1f3e36) @@ -29,7 +29,6 @@ import java.util.Collections; import java.util.Comparator; import java.util.LinkedHashMap; -import java.util.LinkedHashSet; import java.util.LinkedList; import java.util.List; import java.util.Set; @@ -125,7 +124,7 @@ long toolContentId = WebUtil.readLongParam(request, AttributeNames.PARAM_TOOL_CONTENT_ID); Scratchie scratchie = scratchieService.getScratchieByContentId(toolContentId); - Set items = new TreeSet(new ScratchieItemComparator()); + Set items = new TreeSet<>(new ScratchieItemComparator()); items.addAll(scratchie.getScratchieItems()); request.setAttribute("items", items); @@ -163,14 +162,14 @@ String answersSequence = groupRow[i].getCellValue().toString(); String[] answerLetters = answersSequence.split(", "); - Set answers = new LinkedHashSet<>(); + List answers = new LinkedList<>(); for (int j = 0; j < answerLetters.length; j++) { String answerLetter = answerLetters[j]; String correctAnswerLetter = correctAnswersRow[i].getCellValue().toString(); ScratchieAnswer answer = new ScratchieAnswer(); - answer.setDescription(answerLetter); - answer.setCorrect(correctAnswerLetter.equals(answerLetter)); + answer.getQbOption().setName(answerLetter); + answer.getQbOption().setCorrect(correctAnswerLetter.equals(answerLetter)); answers.add(answer); } Index: lams_tool_scratchie/web/pages/authoring/parts/additem.jsp =================================================================== diff -u -raced7ba6c1e7c5a9a50d3f64d8cdd96dd7e76194 -rfba7287887f6dd83d3098100af6320cccf1f3e36 --- lams_tool_scratchie/web/pages/authoring/parts/additem.jsp (.../additem.jsp) (revision aced7ba6c1e7c5a9a50d3f64d8cdd96dd7e76194) +++ lams_tool_scratchie/web/pages/authoring/parts/additem.jsp (.../additem.jsp) (revision fba7287887f6dd83d3098100af6320cccf1f3e36) @@ -233,7 +233,7 @@
- +
Index: lams_tool_scratchie/web/pages/authoring/parts/answerlist.jsp =================================================================== diff -u -r7475d08afc280b5e2e5ddf04e8bf35e3166aaf80 -rfba7287887f6dd83d3098100af6320cccf1f3e36 --- lams_tool_scratchie/web/pages/authoring/parts/answerlist.jsp (.../answerlist.jsp) (revision 7475d08afc280b5e2e5ddf04e8bf35e3166aaf80) +++ lams_tool_scratchie/web/pages/authoring/parts/answerlist.jsp (.../answerlist.jsp) (revision fba7287887f6dd83d3098100af6320cccf1f3e36) @@ -7,15 +7,15 @@ - + &#${status.index + 65};) - + - checked="checked" > + checked="checked" > Index: lams_tool_scratchie/web/pages/authoring/parts/itemlist.jsp =================================================================== diff -u -r7475d08afc280b5e2e5ddf04e8bf35e3166aaf80 -rfba7287887f6dd83d3098100af6320cccf1f3e36 --- lams_tool_scratchie/web/pages/authoring/parts/itemlist.jsp (.../itemlist.jsp) (revision 7475d08afc280b5e2e5ddf04e8bf35e3166aaf80) +++ lams_tool_scratchie/web/pages/authoring/parts/itemlist.jsp (.../itemlist.jsp) (revision fba7287887f6dd83d3098100af6320cccf1f3e36) @@ -1,5 +1,27 @@ <%@ include file="/common/taglibs.jsp"%> + +<%@ page import="org.lamsfoundation.lams.qb.service.IQbService" %> + +
@@ -20,7 +42,7 @@ - + Index: lams_tool_scratchie/web/pages/learning/learning.jsp =================================================================== diff -u -r588920f0bcb20d715a58bb2bbde3da5520b7e9b0 -rfba7287887f6dd83d3098100af6320cccf1f3e36 --- lams_tool_scratchie/web/pages/learning/learning.jsp (.../learning.jsp) (revision 588920f0bcb20d715a58bb2bbde3da5520b7e9b0) +++ lams_tool_scratchie/web/pages/learning/learning.jsp (.../learning.jsp) (revision fba7287887f6dd83d3098100af6320cccf1f3e36) @@ -81,7 +81,7 @@ function scratchItem(itemUid, answerUid){ $.ajax({ url: '', - data: 'sessionMapID=${sessionMapID}&answerUid=' + answerUid, + data: 'sessionMapID=${sessionMapID}&answerUid=' + answerUid + '&itemUid=' + itemUid, dataType: 'json', type: 'post', success: function (json) { Index: lams_tool_scratchie/web/pages/learning/results.jsp =================================================================== diff -u -r3bb7e0141ae1cc15ccd737c95d90b5762a34ad61 -rfba7287887f6dd83d3098100af6320cccf1f3e36 --- lams_tool_scratchie/web/pages/learning/results.jsp (.../results.jsp) (revision 3bb7e0141ae1cc15ccd737c95d90b5762a34ad61) +++ lams_tool_scratchie/web/pages/learning/results.jsp (.../results.jsp) (revision fba7287887f6dd83d3098100af6320cccf1f3e36) @@ -177,7 +177,7 @@ }, {name:'count', index:'count', width:50, align:"right", title: false} ], - caption: "${scratchieItem.title}""${scratchieItem.title}" + " [${fn:length(burningQuestionItemDto.burningQuestionDtos)}]", + caption: "${scratchieItem.qbQuestion.name}""${scratchieItem.qbQuestion.name}" + " [${fn:length(burningQuestionItemDto.burningQuestionDtos)}]", editurl: '?sessionId=${toolSessionID}&itemUid=${scratchieItem.uid}', beforeEditRow: function (options, rowid) { alert("aaa"); Index: lams_tool_scratchie/web/pages/learning/scratchies.jsp =================================================================== diff -u -r588920f0bcb20d715a58bb2bbde3da5520b7e9b0 -rfba7287887f6dd83d3098100af6320cccf1f3e36 --- lams_tool_scratchie/web/pages/learning/scratchies.jsp (.../scratchies.jsp) (revision 588920f0bcb20d715a58bb2bbde3da5520b7e9b0) +++ lams_tool_scratchie/web/pages/learning/scratchies.jsp (.../scratchies.jsp) (revision fba7287887f6dd83d3098100af6320cccf1f3e36) @@ -1,33 +1,33 @@
- +
- +
- +
- + + id="image-${item.uid}-${answer.qbOption.uid}"> - + + id="image-${item.uid}-${answer.qbOption.uid}"> + id="image-${item.uid}-${answer.qbOption.uid}"> - + id="image-${item.uid}-${answer.qbOption.uid}" /> @@ -45,7 +45,7 @@ class="answer-with-confidence-level-portrait" >
- +
Index: lams_tool_scratchie/web/pages/monitoring/parts/itemSummary.jsp =================================================================== diff -u -r5a0c67fe7b338c1f3ad27b7e309d993feb90a0b5 -rfba7287887f6dd83d3098100af6320cccf1f3e36 --- lams_tool_scratchie/web/pages/monitoring/parts/itemSummary.jsp (.../itemSummary.jsp) (revision 5a0c67fe7b338c1f3ad27b7e309d993feb90a0b5) +++ lams_tool_scratchie/web/pages/monitoring/parts/itemSummary.jsp (.../itemSummary.jsp) (revision fba7287887f6dd83d3098100af6320cccf1f3e36) @@ -94,7 +94,7 @@ - ${fn:escapeXml(item.title)} + ${fn:escapeXml(item.qbQuestion.name)} Index: lams_tool_scratchie/web/pages/monitoring/summary.jsp =================================================================== diff -u -r7475d08afc280b5e2e5ddf04e8bf35e3166aaf80 -rfba7287887f6dd83d3098100af6320cccf1f3e36 --- lams_tool_scratchie/web/pages/monitoring/summary.jsp (.../summary.jsp) (revision 7475d08afc280b5e2e5ddf04e8bf35e3166aaf80) +++ lams_tool_scratchie/web/pages/monitoring/summary.jsp (.../summary.jsp) (revision fba7287887f6dd83d3098100af6320cccf1f3e36) @@ -125,7 +125,7 @@ {name:'feedback', index:'feedback', width:520}, {name:'count', index:'count', align:"right", width:70} ], - // caption: "${scratchieItem.title}" + // caption: "${scratchieItem.qbQuestion.name}" }); @@ -281,7 +281,7 @@ @@ -342,7 +342,7 @@
-
${burningQuestionItemDto.scratchieItem.title}
+
${burningQuestionItemDto.scratchieItem.qbQuestion.name}