Index: docs/conversion/samigo_2_8_x-2_9_0_mysql_conversion.sql
===================================================================
--- docs/conversion/samigo_2_8_x-2_9_0_mysql_conversion.sql (revision 133459)
+++ docs/conversion/samigo_2_8_x-2_9_0_mysql_conversion.sql (working copy)
@@ -28,4 +28,26 @@
VALUES(NULL, (SELECT ID FROM SAM_ASSESSMENTBASE_T WHERE TITLE='Timed Test'
AND TYPEID='142' AND ISTEMPLATE=1),
'lockedBrowser_isInstructorEditable', 'true')
-;
\ No newline at end of file
+;
+
+-- SAK-17243
+alter table SAM_ATTACHMENT_T add ITEMTEXTID bigint(20) DEFAULT NULL;
+alter table SAM_ITEMTEXT_T add REQUIRED_OPTIONS_COUNT int(11) DEFAULT NULL;
+alter table SAM_ITEM_T add ANSWER_OPTIONS_RICH_COUNT int(11) DEFAULT NULL;
+alter table SAM_ITEM_T add ANSWER_OPTIONS_SIMPLE_OR_RICH int(11) DEFAULT NULL;
+
+create index SAM_ATTACH_ITEMTEXTID_I ON SAM_ATTACHMENT_T (ITEMTEXTID);
+alter table SAM_ATTACHMENT_T add CONSTRAINT FOREIGN KEY (ITEMTEXTID) REFERENCES SAM_ITEMTEXT_T (ITEMTEXTID);
+
+alter table SAM_PUBLISHEDATTACHMENT_T add ITEMTEXTID bigint(20) DEFAULT NULL;
+alter table SAM_PUBLISHEDITEMTEXT_T add REQUIRED_OPTIONS_COUNT int(11) DEFAULT NULL;
+alter table SAM_PUBLISHEDITEM_T add ANSWER_OPTIONS_RICH_COUNT int(11) DEFAULT NULL;
+alter table SAM_PUBLISHEDITEM_T add ANSWER_OPTIONS_SIMPLE_OR_RICH int(11) DEFAULT NULL;
+
+create index SAM_PUBATTACH_ITEMTEXTID_I ON SAM_PUBLISHEDATTACHMENT_T (ITEMTEXTID);
+alter table SAM_PUBLISHEDATTACHMENT_T add CONSTRAINT FOREIGN KEY (ITEMTEXTID) REFERENCES SAM_PUBLISHEDITEMTEXT_T (ITEMTEXTID);
+
+INSERT INTO SAM_TYPE_T (TYPEID ,AUTHORITY ,DOMAIN, KEYWORD, DESCRIPTION,
+ STATUS, CREATEDBY, CREATEDDATE, LASTMODIFIEDBY, LASTMODIFIEDDATE )
+ VALUES (14 , 'stanford.edu' ,'assessment.item' ,'Extended Matching Items' ,NULL ,1 ,1 ,
+ '2009-11-23 12:00:00',1 ,'2009-11-23 12:00:00');
\ No newline at end of file
Index: docs/conversion/samigo_2_8_x-2_9_0_oracle_conversion.sql
===================================================================
--- docs/conversion/samigo_2_8_x-2_9_0_oracle_conversion.sql (revision 133459)
+++ docs/conversion/samigo_2_8_x-2_9_0_oracle_conversion.sql (working copy)
@@ -27,6 +27,13 @@
VALUES (13 , 'stanford.edu' ,'assessment.item' ,'Matrix Choices Survey' ,NULL ,1 ,1 ,
SYSDATE ,1 ,SYSDATE);
+INSERT INTO SAM_TYPE_T ("TYPEID" ,"AUTHORITY" ,"DOMAIN" ,"KEYWORD",
+ "DESCRIPTION" ,
+ "STATUS" ,"CREATEDBY" ,"CREATEDDATE" ,"LASTMODIFIEDBY" ,
+ "LASTMODIFIEDDATE" )
+ VALUES (14 , 'stanford.edu' ,'assessment.item' ,'Extended Matching_Items' ,NULL ,1 ,1 ,
+ SYSDATE ,1 ,SYSDATE);
+
-- SAM-1255
Update SAM_ASSESSEVALUATION_T
Set ANONYMOUSGRADING = 2
Index: pom.xml
===================================================================
--- pom.xml (revision 133459)
+++ pom.xml (working copy)
@@ -15,6 +15,10 @@
10.0-SNAPSHOTpom
+
+ UTF-8
+
+
samigo-apisamigo-app
@@ -34,18 +38,35 @@
scm:svn:https://source.sakaiproject.org/svn/sam/trunkhttps://source.sakaiproject.org/svn/sam/trunk
-
+
-
+ sakai-siteSakai release Sitescpexe://source.sakaiproject.org/var/www/html/release/samigo/${project.version}
-
-
+
+
+ org.sakaiproject.samigo
+ samigo-api
+ ${project.version}
+ provided
+
+
+ org.sakaiproject.samigo
+ samigo-services
+ ${project.version}
+ provided
+
+
+ org.sakaiproject.samigo
+ samigo-app
+ ${project.version}
+
+ org.sakaiproject.samigosamigo-cp${project.version}
@@ -64,6 +85,36 @@
${project.version}jar
+
+ org.sakaiproject.samigo
+ samigo-import
+ ${project.version}
+
+
+ org.sakaiproject.samigo
+ samigo-deploy
+ ${project.version}
+
+
+ org.sakaiproject.samigo
+ samigo-assembly
+ ${project.version}
+
+
+ org.sakaiproject.samigo
+ samigo-shared
+ ${project.version}
+
+
+ org.sakaiproject.samigo
+ samigo-help
+ ${project.version}
+
+
+ org.sakaiproject.samigo
+ samigo-pack
+ ${project.version}
+ org.sakaiproject.samigo
Index: samigo-api/src/java/org/sakaiproject/tool/assessment/data/ifc/assessment/AnswerIfc.java
===================================================================
--- samigo-api/src/java/org/sakaiproject/tool/assessment/data/ifc/assessment/AnswerIfc.java (revision 133459)
+++ samigo-api/src/java/org/sakaiproject/tool/assessment/data/ifc/assessment/AnswerIfc.java (working copy)
@@ -23,12 +23,12 @@
package org.sakaiproject.tool.assessment.data.ifc.assessment;
-import java.util.ArrayList;
import java.util.HashMap;
+import java.util.List;
import java.util.Set;
public interface AnswerIfc
- extends java.io.Serializable
+ extends Comparable, java.io.Serializable
{
Long getId();
@@ -75,15 +75,15 @@
Double getPartialCredit();
- Set getAnswerFeedbackSet();
+ Set getAnswerFeedbackSet();
- ArrayList getAnswerFeedbackArray();
+ List getAnswerFeedbackArray();
- void setAnswerFeedbackSet(Set answerFeedbackSet);
+ void setAnswerFeedbackSet(Set answerFeedbackSet);
String getAnswerFeedback(String typeId);
- HashMap getAnswerFeedbackMap();
+ HashMap getAnswerFeedbackMap();
String getCorrectAnswerFeedback();
Index: samigo-api/src/java/org/sakaiproject/tool/assessment/data/ifc/assessment/AssessmentAccessControlIfc.java
===================================================================
--- samigo-api/src/java/org/sakaiproject/tool/assessment/data/ifc/assessment/AssessmentAccessControlIfc.java (revision 133459)
+++ samigo-api/src/java/org/sakaiproject/tool/assessment/data/ifc/assessment/AssessmentAccessControlIfc.java (working copy)
@@ -64,8 +64,7 @@
// lateHandling
public static Integer ACCEPT_LATE_SUBMISSION = Integer.valueOf(1);
public static Integer NOT_ACCEPT_LATE_SUBMISSION = Integer.valueOf(2);
-
- // gopalrc - group release
+ // group release
public static String RELEASE_TO_SELECTED_GROUPS = "Selected Groups";
Long getId();
Index: samigo-api/src/java/org/sakaiproject/tool/assessment/data/ifc/assessment/AttachmentIfc.java
===================================================================
--- samigo-api/src/java/org/sakaiproject/tool/assessment/data/ifc/assessment/AttachmentIfc.java (revision 133459)
+++ samigo-api/src/java/org/sakaiproject/tool/assessment/data/ifc/assessment/AttachmentIfc.java (working copy)
@@ -36,6 +36,7 @@
//This parameter is for SAM_GRADINGATTACHMENT_T table
public static Long ITEMGRADING_ATTACHMENT = Long.valueOf(1);
+ public static Long ITEM_TEXT_ATTACHMENT = Long.valueOf(5);//for EMI sub-item attachments
public static Integer ACTIVE_STATUS = Integer.valueOf(1);
public static Integer INACTIVE_STATUS = Integer.valueOf(0);
Index: samigo-api/src/java/org/sakaiproject/tool/assessment/data/ifc/assessment/ItemDataIfc.java
===================================================================
--- samigo-api/src/java/org/sakaiproject/tool/assessment/data/ifc/assessment/ItemDataIfc.java (revision 133459)
+++ samigo-api/src/java/org/sakaiproject/tool/assessment/data/ifc/assessment/ItemDataIfc.java (working copy)
@@ -22,16 +22,16 @@
package org.sakaiproject.tool.assessment.data.ifc.assessment;
-import java.util.ArrayList;
+
import java.util.Date;
-import java.util.HashMap;
import java.util.Set;
import java.util.List;
import org.sakaiproject.tool.assessment.data.ifc.shared.TypeIfc;
-public interface ItemDataIfc extends java.io.Serializable {
+public interface ItemDataIfc extends Comparable, java.io.Serializable {
+
public static Integer ACTIVE_STATUS = Integer.valueOf(1);
public static Integer INACTIVE_STATUS = Integer.valueOf(0);
@@ -115,19 +115,19 @@
void setLastModifiedDate(Date lastModifiedDate);
- Set getItemTextSet();
+ Set getItemTextSet();
- void setItemTextSet(Set itemTextSet) ;
+ void setItemTextSet(Set itemTextSet) ;
- void addItemText(String itemText, Set answerSet);
+ void addItemText(String itemText, Set answerSet);
- Set getItemMetaDataSet();
+ Set getItemMetaDataSet();
- void setItemMetaDataSet(Set itemMetaDataSet);
+ void setItemMetaDataSet(Set itemMetaDataSet);
- Set getItemFeedbackSet();
+ Set getItemFeedbackSet();
- void setItemFeedbackSet(Set itemFeedbackSet);
+ void setItemFeedbackSet(Set itemFeedbackSet);
String getItemMetaDataByLabel(String label);
@@ -159,15 +159,40 @@
TypeIfc getType();
- ArrayList getItemTextArray();
+ List getItemTextArray();
- ArrayList getItemTextArraySorted();
+ List getItemTextArraySorted();
String getAnswerKey();
- Set getItemAttachmentSet();
+ Set getItemAttachmentSet();
- void setItemAttachmentSet(Set itemAttachmentSet);
+ void setItemAttachmentSet(Set itemAttachmentSet);
- List getItemAttachmentList();
+ List getItemAttachmentList();
+
+ String getLeadInText();
+ String getThemeText();
+ //public ItemTextIfc getEmiAnswerComponentsItemText();
+ public int getNumberOfCorrectEmiOptions();
+ public String getEmiAnswerOptionLabels();
+ public boolean isValidEmiAnswerOptionLabel(String label);
+
+ public List getEmiAnswerOptions();
+ public List getEmiQuestionAnswerCombinations();
+
+ public ItemTextIfc getItemTextBySequence(Long itemTextSequence);
+ public Integer getAnswerOptionsRichCount();
+ public void setAnswerOptionsRichCount(Integer answerOptionsRichCount);
+
+ // for EMI
+ public static final String ANSWER_OPTION_LABELS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ public static final String ANSWER_OPTION_VALID_DELIMITERS = " ,;:.";
+ public static final Integer ANSWER_OPTIONS_SIMPLE = 0;
+ public static final Integer ANSWER_OPTIONS_RICH = 1;
+ public Integer getAnswerOptionsSimpleOrRich();
+ public void setAnswerOptionsSimpleOrRich(Integer answerOptionsSimpleOrRich);
+ public String getEmiAnswerOptionsRichText();
+ public boolean getIsAnswerOptionsSimple();
+ public boolean getIsAnswerOptionsRich();
}
Index: samigo-api/src/java/org/sakaiproject/tool/assessment/data/ifc/assessment/ItemTextAttachmentIfc.java
===================================================================
--- samigo-api/src/java/org/sakaiproject/tool/assessment/data/ifc/assessment/ItemTextAttachmentIfc.java (revision 0)
+++ samigo-api/src/java/org/sakaiproject/tool/assessment/data/ifc/assessment/ItemTextAttachmentIfc.java (working copy)
@@ -0,0 +1,37 @@
+/**
+ * ********************************************************************************
+ * $URL:
+ * https://source.sakaiproject.org/svn/sam/trunk/samigo-api/src/java/org/sakaiproject/tool/assessment/data/ifc/grading/MediaIfc.java
+ * $ $Id: MediaIfc.java 11438 2006-06-30 20:06:03Z daisyf@stanford.edu $
+ * **********************************************************************************
+ *
+ * Copyright (c) 2004, 2005, 2006, 2008 The Sakai Foundation
+ *
+ * Licensed under the Educational Community License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.osedu.org/licenses/ECL-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ *
+ *********************************************************************************
+ */
+package org.sakaiproject.tool.assessment.data.ifc.assessment;
+
+public interface ItemTextAttachmentIfc
+ extends AttachmentIfc {
+
+ Long getAttachmentType();
+
+ void setAttachmentType(Long attachmentType);
+
+ ItemTextIfc getItemText();
+
+ void setItemText(ItemTextIfc itemText);
+
+}
Index: samigo-api/src/java/org/sakaiproject/tool/assessment/data/ifc/assessment/ItemTextIfc.java
===================================================================
--- samigo-api/src/java/org/sakaiproject/tool/assessment/data/ifc/assessment/ItemTextIfc.java (revision 133459)
+++ samigo-api/src/java/org/sakaiproject/tool/assessment/data/ifc/assessment/ItemTextIfc.java (working copy)
@@ -23,12 +23,16 @@
package org.sakaiproject.tool.assessment.data.ifc.assessment;
-import java.util.ArrayList;
+import java.util.List;
import java.util.Set;
public interface ItemTextIfc
- extends java.io.Serializable
+ extends Comparable, java.io.Serializable
{
+ public static Long EMI_THEME_TEXT_SEQUENCE = Long.valueOf(-1);
+ public static Long EMI_ANSWER_OPTIONS_SEQUENCE = Long.valueOf(-2);
+ public static Long EMI_LEAD_IN_TEXT_SEQUENCE = Long.valueOf(-3);
+
Long getId();
void setId(Long id);
@@ -45,11 +49,40 @@
void setText(String text);
- Set getAnswerSet();
+ Set getAnswerSet();
- void setAnswerSet(Set answerSet);
+ void setAnswerSet(Set answerSet);
- ArrayList getAnswerArray();
+ List getAnswerArray();
- ArrayList getAnswerArraySorted();
+ List getAnswerArraySorted();
+
+ Set getItemTextAttachmentSet();
+
+ void setItemTextAttachmentSet(Set itemTextAttachmentSet);
+
+ List getItemTextAttachmentList();
+
+ /**
+ * This is an actual EMI Question Item (i.e. not Theme or Lead In Text or
+ * Complete Answer Options List)
+ *
+ * @return
+ * @since 2.10
+ */
+ public boolean isEmiQuestionItemText();
+
+ /**
+ * Get the number of required option
+ *
+ * @return the number of required options or 1 if not defined
+ * @since 2.10
+ */
+ public Integer getRequiredOptionsCount();
+
+ public void setRequiredOptionsCount(Integer requiredOptionsCount);
+
+ public String getEmiCorrectOptionLabels();
+
+ public boolean getHasAttachment();
}
Index: samigo-api/src/java/org/sakaiproject/tool/assessment/data/ifc/assessment/SecureDeliveryModuleIfc.java
===================================================================
--- samigo-api/src/java/org/sakaiproject/tool/assessment/data/ifc/assessment/SecureDeliveryModuleIfc.java (revision 133459)
+++ samigo-api/src/java/org/sakaiproject/tool/assessment/data/ifc/assessment/SecureDeliveryModuleIfc.java (working copy)
@@ -4,7 +4,6 @@
import javax.servlet.http.HttpServletRequest;
-import org.sakaiproject.tool.assessment.shared.api.assessment.SecureDeliveryServiceAPI;
import org.sakaiproject.tool.assessment.shared.api.assessment.SecureDeliveryServiceAPI.Phase;
import org.sakaiproject.tool.assessment.shared.api.assessment.SecureDeliveryServiceAPI.PhaseStatus;
Index: samigo-api/src/java/org/sakaiproject/tool/assessment/data/ifc/shared/TypeIfc.java
===================================================================
--- samigo-api/src/java/org/sakaiproject/tool/assessment/data/ifc/shared/TypeIfc.java (revision 133459)
+++ samigo-api/src/java/org/sakaiproject/tool/assessment/data/ifc/shared/TypeIfc.java (working copy)
@@ -26,22 +26,24 @@
public interface TypeIfc extends java.io.Serializable {
// This has the exact same list as TypeFacade. Please keep both list updated
- public static Long MULTIPLE_CHOICE = Long.valueOf(1);
- public static Long MULTIPLE_CORRECT = Long.valueOf(2);
- public static Long MULTIPLE_CHOICE_SURVEY = Long.valueOf(3);
- public static Long TRUE_FALSE = Long.valueOf(4);
- public static Long ESSAY_QUESTION = Long.valueOf(5);
- public static Long FILE_UPLOAD = Long.valueOf(6);
- public static Long AUDIO_RECORDING = Long.valueOf(7);
- public static Long FILL_IN_BLANK = Long.valueOf(8);
- public static Long MATCHING = Long.valueOf(9);
- public static Long FILL_IN_NUMERIC = Long.valueOf(11);
- public static Long MULTIPLE_CORRECT_SINGLE_SELECTION = Long.valueOf(12);
- public static Long MATRIX_CHOICES_SURVEY = Long.valueOf(13);
- public static Long CALCULATED_QUESTION = Long.valueOf(15); // CALCULATED_QUESTION
+ public static final Long MULTIPLE_CHOICE = Long.valueOf(1);
+ public static final Long MULTIPLE_CORRECT = Long.valueOf(2);
+ public static final Long MULTIPLE_CHOICE_SURVEY = Long.valueOf(3);
+ public static final Long TRUE_FALSE = Long.valueOf(4);
+ public static final Long ESSAY_QUESTION = Long.valueOf(5);
+ public static final Long FILE_UPLOAD = Long.valueOf(6);
+ public static final Long AUDIO_RECORDING = Long.valueOf(7);
+ public static final Long FILL_IN_BLANK = Long.valueOf(8);
+ public static final Long MATCHING = Long.valueOf(9);
+ public static final Long FILL_IN_NUMERIC = Long.valueOf(11);
+ public static final Long MULTIPLE_CORRECT_SINGLE_SELECTION = Long.valueOf(12);
+ public static final Long MATRIX_CHOICES_SURVEY = Long.valueOf(13);
+ public static final Long EXTENDED_MATCHING_ITEMS = Long.valueOf(14);
+ public static final Long CALCULATED_QUESTION = Long.valueOf(15); // CALCULATED_QUESTION
// these are section type available in this site,
public static Long DEFAULT_SECTION = Long.valueOf(21);
// these are assessment template type available in this site,
+ public static final Long TEMPLATE_SYSTEM_DEFINED = Long.valueOf(142);
public static Long TEMPLATE_QUIZ = Long.valueOf(41);
public static Long TEMPLATE_HOMEWORK = Long.valueOf(42);
public static Long TEMPLATE_MIDTERM = Long.valueOf(43);
@@ -53,6 +55,17 @@
public static Long FINAL = Long.valueOf(64);
public static String SITE_AUTHORITY = "stanford.edu";
public static String DOMAIN_ASSESSMENT_ITEM = "assessment.item";
+
+ enum TypeId{
+ MULTIPLE_CHOICE_ID(MULTIPLE_CHOICE);
+ int id;
+ TypeId(Long l){
+ id = l.intValue();
+ }
+ public int id(){
+ return id;
+ }
+ }
Long getTypeId();
Index: samigo-api/src/java/org/sakaiproject/tool/assessment/samlite/api/Answer.java
===================================================================
--- samigo-api/src/java/org/sakaiproject/tool/assessment/samlite/api/Answer.java (revision 133459)
+++ samigo-api/src/java/org/sakaiproject/tool/assessment/samlite/api/Answer.java (working copy)
@@ -21,5 +21,9 @@
return text;
}
-
+ public void postProcessing(int questionType) {
+ if (questionType == Question.EXTENDED_MATCHING_ITEMS_QUESTION) {
+ text = text.substring(text.lastIndexOf("[")+1, text.lastIndexOf("]")).trim();
+ }
+ }
}
Index: samigo-api/src/java/org/sakaiproject/tool/assessment/samlite/api/Question.java
===================================================================
--- samigo-api/src/java/org/sakaiproject/tool/assessment/samlite/api/Question.java (revision 133459)
+++ samigo-api/src/java/org/sakaiproject/tool/assessment/samlite/api/Question.java (working copy)
@@ -1,5 +1,6 @@
package org.sakaiproject.tool.assessment.samlite.api;
+import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Iterator;
@@ -11,6 +12,12 @@
public static final int FILL_IN_THE_BLANK_QUESTION = 20;
public static final int TRUE_FALSE_QUESTION = 30;
public static final int SHORT_ESSAY_QUESTION = 40;
+ public static final int EXTENDED_MATCHING_ITEMS_QUESTION = 50;
+ // for EMI question
+ private String themeText;
+ private String leadInText;
+ private ArrayList emiAnswerOptions; // store List of possible options for an EMI question's anwers
+ private ArrayList emiQuestionAnswerCombinations; // store List of possible options for an EMI question's anwers
private int questionNumber;
private String questionPoints;
@@ -96,7 +103,7 @@
public boolean hasPoints() {
return hasPoints;
}
-
+
public int getQuestionType() {
return questionType;
}
@@ -105,6 +112,40 @@
this.questionType = questionType;
}
+ public void postProcessing() {
+ if (getQuestionType() == EXTENDED_MATCHING_ITEMS_QUESTION) {
+ int themeLineIndex = 1;
+ int optionLine = 2;
+ questionLines.set(themeLineIndex, questionLines.get(themeLineIndex).toString() + "
");
+ Iterator answerLines = answers.iterator();
+ String textToAdd = "Options: ";
+ questionLines.add(optionLine++, textToAdd + " ");
+ while (answerLines.hasNext()) {
+ Answer answer = (Answer) answerLines.next();
+ textToAdd = answer.getId() + ". " + answer.getText();
+ if (!answer.isCorrect()) {
+ // add at next options position
+ questionLines.add(optionLine++, textToAdd + " ");
+ }
+ else {
+ // add at end
+ //textToAdd = textToAdd.substring(0, textToAdd.indexOf("[")).trim() + " ";
+ questionLines.add(textToAdd);
+ }
+ }
+ answerLines = answers.iterator();
+ while (answerLines.hasNext()) {
+ Answer answer = (Answer)answerLines.next();
+ if (!answer.isCorrect()) {
+ answerLines.remove();
+ }
+ else {
+ answer.postProcessing(questionType);
+ }
+ }
+ }
+ }
+
public String getQuestionTypeAsString() {
return questionTypeAsString;
}
@@ -112,5 +153,57 @@
public void setQuestionTypeAsString(String questionTypeAsString) {
this.questionTypeAsString = questionTypeAsString;
}
-
+
+//************ Theme and Lead-In Text ******************
+
+ public String getLeadInText() {
+ if (leadInText == null) {
+ setThemeAndLeadInText();
+ }
+ return leadInText;
+ }
+
+ public String getThemeText() {
+ if (themeText == null) {
+ setThemeAndLeadInText();
+ }
+ return themeText;
+ }
+
+ public void setThemeAndLeadInText() {
+ themeText = (String)questionLines.get(1);
+ leadInText = (String)questionLines.get(2);
+ }
+
+
+ //************ EMI Answer Options and Q-A combinations******************
+
+ public ArrayList getEmiAnswerOptions() {
+ if (emiAnswerOptions==null) {
+ setEmiOptionsAndQACombinations();
+ }
+ return emiAnswerOptions;
+ }
+
+ public ArrayList getEmiQuestionAnswerCombinations() {
+ if (emiQuestionAnswerCombinations==null) {
+ setEmiOptionsAndQACombinations();
+ }
+ return emiQuestionAnswerCombinations;
+ }
+
+ private void setEmiOptionsAndQACombinations() {
+ emiAnswerOptions = new ArrayList();
+ emiQuestionAnswerCombinations = new ArrayList();
+ Iterator iter = answers.iterator();
+ while (iter.hasNext()) {
+ Answer answer = (Answer)iter.next();
+ if (answer.getId().matches("[0-9]+")) {
+ emiQuestionAnswerCombinations.add(answer);
+ }
+ else {
+ emiAnswerOptions.add(answer);
+ }
+ }
+ }
}
Index: samigo-api/src/java/org/sakaiproject/tool/assessment/shared/api/grading/GradingSectionAwareServiceAPI.java
===================================================================
--- samigo-api/src/java/org/sakaiproject/tool/assessment/shared/api/grading/GradingSectionAwareServiceAPI.java (revision 133459)
+++ samigo-api/src/java/org/sakaiproject/tool/assessment/shared/api/grading/GradingSectionAwareServiceAPI.java (working copy)
@@ -97,7 +97,6 @@
/**
- * added by gopalrc - Jan 2008
* @return
* an EnrollmentRecord list for each student that the current user
* is allowed to grade, who is in at least one of the release groups
Index: samigo-api/src/java/xml/author/v1p2/emiTemplate.xml
===================================================================
--- samigo-api/src/java/xml/author/v1p2/emiTemplate.xml (revision 0)
+++ samigo-api/src/java/xml/author/v1p2/emiTemplate.xml (working copy)
@@ -0,0 +1,75 @@
+
+
+ This is a QTI implementation for Extended Matching Items (EMIs).
+ Note that this is only valid for Samigo's import export of EMI's.
+ This is not FULL QTI Standard
+
+
+
+
+ qmd_itemtype
+ Extended Matching Items
+
+
+ TEXT_FORMAT
+ HTML
+
+
+ ITEM_OBJECTIVE
+
+
+
+ ITEM_KEYWORD
+
+
+
+ ITEM_RUBRIC
+
+
+
+ ATTACHMENT
+
+
+
+ hasRationale
+ false
+
+
+ RANDOMIZE
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Overall Score
+
+
+
+
+
+
+
+
+
+
Index: samigo-api/src/java/xml/author/v2p0/emiTemplate.xml
===================================================================
--- samigo-api/src/java/xml/author/v2p0/emiTemplate.xml (revision 0)
+++ samigo-api/src/java/xml/author/v2p0/emiTemplate.xml (working copy)
@@ -0,0 +1,64 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ 0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+ 0
+
+
+
+
+
Index: samigo-api/src/java/xml/xsd/ccv1p2_qtiasiv1p2p1_v1p0.xsd
===================================================================
--- samigo-api/src/java/xml/xsd/ccv1p2_qtiasiv1p2p1_v1p0.xsd (revision 0)
+++ samigo-api/src/java/xml/xsd/ccv1p2_qtiasiv1p2p1_v1p0.xsd (working copy)
@@ -0,0 +1,1916 @@
+
+
+
+
+
+ XSD Data File Information
+ -------------------------
+ Author: Colin Smythe
+ Date: 1st October, 2011
+ Version: 1.2
+ Status: Final Release
+ Description: This model forms part of the IMS Common Cartridge v1.2 specification. This model is the
+ profile of the IMS QTI v1.2.1 specification. The changes made to the original specification
+ to create this profile are:
+
+ Root
+ (a) Only one Assessment or one ObjectBank can be exchanged i.e. not Sections or Items;
+ (b) The qticomment attribute has been removed.
+
+ Assessment
+ (a) Only a single Section must be contained in the Assessment;
+ (b) The metadata is mandatory (see the specification for the fields that must be defined) with a multiplicity of 1;
+ (c) All of the other Assessment fields have been removed apart from the optional PresentationMaterial;
+ (d) The title attribute has been made mandatory.
+
+ Object Bank
+ (a) Only Items can be containd in the object bank;
+ (b) The Qticomment structure has been removed.
+
+ Section
+ (a) All of the internal structure has been removed except the containment of Items (at least one is required);
+ (b) The language attribute has been removed.
+
+ Item
+ (a) The deprecated attributes have been removed from the ItemMetadata class;
+ (b) All qticomment attributes have been removed from various classes;
+ (c) The Item pre and post condition attributes have been removed from the Item class;
+ (d) The itemproc_extension structure has been removed from the Item class;
+ (e) The reference structure has been removed from the Item class;
+ (f) The objectives attribute has been removed from the Item class;
+ (g) The itemcontrol attribute has been removed from the Item class;
+ (h) The item rubric attribute and its associated classes have been removed from the Item class;
+ (i) The duration attribute has been removed from the Item class;
+ (j) The itemmetadata attribute has been made mandatory in the Item class;
+ (k) The label, language and maxattempts attributes have been removed from the Item class;
+ (l) The interpretvar attribute has been removed frm the Outcomes class;
+ (m) The response_xy, response_num, response_grp and response_extension attributes have
+ been removed from the Presentation class;
+ (n) All extension attributes have been removed from various classes;
+ (o) The ItemType, LevelofDifficulty, RenderingType, ResponseMultiplicity, Status and TypeofSolution
+ have been deleted;
+ (p) The ItemFeedback Class has been restructured as only flow_mat is used;
+ (q) A single decvar is required i.e. for the default variable SCORE.
+
+ Item-Response
+ (a) The Rrange and Rarea attributes have been removed from the ResponseLabel Class.
+
+ Item-Render
+ (a) The render_hotspot attributes and the RenderHotspot class have been removed;
+ (b) The render_slider attributes and the RenderSlider class have been removed;
+ (c) The render_extension attribute has been removed from the ResponseType class;
+ (d) The response_na attribute has been removed;
+ (e) The qticomment attribute has been removed from the ResponseLabel class;
+
+ Item-General
+ (a) The Interpretvar class has been removed;
+ (b) The DurationBase class has been removed and all derived attributes from the Conditionvar and CompositionLogic classes;
+ (c) The var_extension attribute has been removed from the Conditionvar class;
+ (d) The qticomment attributes have been removed from the Hint and Solution classes;
+ (e) Setvar is restricted to the Set action;
+ (f) Variable types are restricted to 'Integer' and 'Decimal';
+ (g) The defaultval and cutvalue, attributes for decvar have been removed;
+ (h) Outcomes is limtied to a single decvar which must have only the variable "SCORE" declared;
+ (i) The classes varlt, varlte, vargt, vargte, varinside, varsubset and unanswered have been removed;
+ (j) The classes 'and', 'or', 'not' and 'conditionvar' have been significantly simplied i.e. see clause above for detail
+ (k) The feedbacktype attribute for displayfeedback has been made mandatory with no default.
+
+ Selection and Ordering
+ (a) The entire Selection and Ordering (Package) has been removed.
+
+ Outcomes
+ (a) The entire Outcomes Processing (Package) has been removed.
+
+ Material
+ (a) The Reference Class has been removed as this is not required;
+ (b) All entityref attributes have been removed;
+ (c) Extensions have been removed;
+ (d) Only 'mattext', 'matref' and 'matbreak' are permitted as types of material.
+
+ Common
+ (a) The Rubric class has been removed Items and Sections and it is only permitted to contain a single instance of material;
+ (b) The ContextControl class has been removed i.e. no Control switches required;
+ (c) The QtiComment Class has been removed;
+ (d) The MetadataRule Class has been removed;
+ (e) the Parameterization Class has been removed;
+ (f) The 'view' attribute has been removed;
+ (g) The Vocabulary Class has been removed and its attribute in the QtiMetadata Class also removed.
+
+ History: Version 1.0: This profile is taken from the UML description of the QTIv1.2.1 specification.
+ Version 1.1: Material has been returned as an alternative to flow_mat in ItemFeedback,
+ SolutionMaterial and HintMaterial. Also, Assessment Rubric has been permitted but it must
+ only contain a single instance of material.
+ Version 1.2: The 'or' element has been re-introduced.
+
+ License: IPR, License and Distribution Notices
+ This machine readable file is derived from IMS Global Learning Consortium (GLC) specification IMS Common Cartridge Version 1.2
+ found at http://www.imsglobal.org/cc/ and the original IMS GLC schema binding or code base
+ http://www.imsglobal.org/cc/.
+
+ Recipients of this document are requested to submit, with their comments, notification of any
+ relevant patent claims or other intellectual property rights of which they may be aware that might be
+ infringed by the schema binding contained in this document.
+
+ IMS GLC takes no position regarding the validity or scope of any intellectual property or other
+ rights that might be claimed to pertain to the implementation or use of the technology described in this
+ document or the extent to which any license under such rights might or might not be available; neither
+ does it represent that it has made any effort to identify any such rights. Information on IMS GLCs
+ procedures with respect to rights in IMS GLC specifications can be found at the IMS GLC Intellectual Property
+ Rights web page: http://www.imsglobal.org/ipr/imsipr_policyFinal.pdf.
+
+ Copyright (c) IMS Global Learning Consortium 1999-2011. All Rights Reserved.
+
+ License Notice for Users
+
+ Users of products or services that include this document are hereby granted a worldwide, royalty-free,
+ non-exclusive license to use this document.
+
+ Distribution Notice for Developers
+
+ Developers of products or services that are not original incorporators of this document and
+ have not changed this document, that is, are distributing a software product that incorporates this
+ document as is from a third-party source other than IMS, are hereby granted permission to copy,
+ display and distribute the contents of this document in any medium for any purpose without fee or
+ royalty provided that you include this IPR, License and Distribution notice in its entirety on ALL
+ copies, or portions thereof.
+
+ Developers of products or services that are original incorporators of this document and wish
+ to provide distribution of this document as is or with modifications and developers of products and
+ services that are not original incorporators of this document and have changed this document, are
+ required to register with the IMS GLC community on the IMS GLC website as described in the following two
+ paragraphs:-
+
+ * If you wish to distribute this document as is, with no modifications, you are hereby granted
+ permission to copy, display and distribute the contents of this document in any medium for any
+ purpose without fee or royalty provided that you include this IPR, License and Distribution notice in
+ its entirety on ALL copies, or portions thereof, that you make and you complete a valid license
+ registration with IMS and receive an email from IMS granting the license. To register, follow the
+ instructions on the IMS website: http://www.imsglobal.org/specificationdownload.cfm. Once
+ registered you are granted permission to transfer unlimited distribution rights of this document for the
+ purposes of third-party or other distribution of your product or service that incorporates this
+ document as long as this IPR, License and Distribution notice remains in place in its entirety;
+
+ * If you wish to create and distribute a derived work from this document, you are hereby
+ granted permission to copy, display and distribute the contents of the derived work in any medium for
+ any purpose without fee or royalty provided that you include this IPR, License and Distribution
+ notice in its entirety on ALL copies, or portions thereof, that you make and you complete a valid
+ profile registration with IMS GLC and receive an email from IMS GLC granting the license. To register, follow
+ the instructions on the IMS GLC website: http://www.imsglobal.org/profile/. Once registered you are
+ granted permission to transfer unlimited distribution rights of the derived work for the purposes of
+ third-party or other distribution of your product or service that incorporates the derived work as long
+ as this IPR, License and Distribution notice remains in place in its entirety.
+
+ The limited permissions granted above are perpetual and will not be revoked by IMS GLC or its
+ successors or assigns.
+
+ THIS SPECIFICATION IS BEING OFFERED WITHOUT ANY WARRANTY WHATSOEVER, AND IN PARTICULAR, ANY WARRANTY OF NONINFRINGEMENT IS
+ EXPRESSLY DISCLAIMED. ANY USE OF THIS SPECIFICATION SHALL BE MADE ENTIRELY AT THE IMPLEMENTERS OWN RISK, AND NEITHER THE CONSORTIUM
+ NOR ANY OF ITS MEMBERS OR SUBMITTERS, SHALL HAVE ANY LIABILITY WHATSOEVER TO ANY IMPLEMENTER OR THIRD PARTY FOR ANY DAMAGES OF
+ ANY NATURE WHATSOEVER, DIRECTLY OR INDIRECTLY, ARISING FROM THE USE OF THIS SPECIFICATION.
+
+ Source UML File Information
+ ---------------------------
+ The source file information must be supplied as an XMI file (without diagram layout information).
+ The supported UML authoring tools are:
+ (a) Poseidon - v6 (and later)
+
+ Source XSLT File Information
+ ----------------------------
+ XSL Generator: UMLtoXSDTransformv0p9p5.xsl
+ XSLT Processor: Xalan
+ Release: 1.0 Beta 4
+ Date: 31st March, 2011
+
+ IMS GLC Auto-generation Binding Tool-kit (I-BAT)
+ ------------------------------------------------
+ This file was auto-generated using the IMS GLC Binding Auto-generation Tool-kit (I-BAT). While every
+ attempt has been made to ensure that this tool auto-generates the files correctly, users should be aware
+ that this is an experimental tool. Permission is given to make use of this tool. IMS GLC makes no
+ claim on the materials created by third party users of this tool. Details on how to use this tool
+ are contained in the IMS GLC "I-BAT" Documentation available at the IMS GLC web-site.
+
+ Tool Copyright: 2005-2011 (c) IMS Global Learning Consortium Inc. All Rights Reserved.
+
+
+
+
+
+ Schematron Validation Rules Information
+ ---------------------------------------
+ Author: Colin Smythe
+ Date: 1st October, 2011
+ Version: 1.2
+ Status: Final Release
+
+ Description: This set of schematron rules have been created to increase the validation capability of the QTIv1.2.1 XSD.
+ A total of 12 rule sets have been created to ensure that:
+ [1] Only valid Assessment metadata is defined;
+ [2] Only valid Question types are defined in the Itemmetatadata fields;
+ [3] The structure of a True/False question is correct;
+ [4] The structure of a Multiple-Choice (Single Response) question is correct;
+ [5] The structure of a Multiple-Choice (Multiple Response) question is correct;
+ [6] The structure of a Fill In Blank question is correct;
+ [7] The structure of a Pattern Match question is correct;
+ [8] The structure of an Essay question is correct;
+ [9] The structures of the response processing/response-label are correct;
+ [10] The structure of a Hint in an Item is correct;
+ [11] The structure of a Solution in an Item is correct;
+ [12] The structure of the response processing feedback structure in an Item is correct;
+ [13] Generic features of an Item are correctly implemented.
+
+ Rule Set: [1] The set of rules to ensure that only valid Assessment metadata is defined.
+ The rules are:
+ (a) Only valid entries are defined for the Assessment metadata fieldlabel values;
+ (b) Only valid entries are defined for the Assessment metadata fieldentry values for fieldlabel = 'qmd_assessmenttype';
+ (c) Only valid entries are defined for the Assessment metadata fieldentry values for fieldlabel = 'qmd_scoretype';
+ (d) Only valid entries are defined for the Assessment metadata fieldentry values for fieldlabel = 'qmd_feedbackpermitted';
+ (e) Only valid entries are defined for the Assessment metadata fieldentry values for fieldlabel = 'qmd_hintspermitted';
+ (f) Only valid entries are defined for the Assessment metadata fieldentry values for fieldlabel = 'qmd_solutionspermitted';
+ (g) Only valid entries are defined for the Assessment metadata fieldentry values for fieldlabel = 'qmd_timelimit';
+ (h) Only valid entries are defined for the Assessment metadata fieldentry values for fieldlabel = 'cc_allow_late_submission';
+ (i) Only valid entries are defined for the Assessment metadata fieldentry values for fieldlabel = 'cc_maxattempts';
+ (j) Only valid entries are defined for the Assessment metadata fieldentry values for fieldlabel = 'cc_profile';
+ (k) There must be only one Assessment metadata field with fieldlabel='cc_profile' i.e. it is mandatory;
+ (l) There must be no more than one Assessment metadata field with fieldlabel='qmd_assessmenttype';
+ (m) There must be no more than one Assessment metadata field with fieldlabel='qmd_scoretype';
+ (n) There must be no more than one Assessment metadata field with fieldlabel='qmd_feedbackpermitted';
+ (o) There must be no more than one Assessment metadata field with fieldlabel='qmd_hintspermitted';
+ (p) There must be no more than one Assessment metadata field with fieldlabel='qmd_solutionspermitted';
+ (q) There must be no more than one Assessment metadata field with fieldlabel='qmd_timelimit';
+ (r) There must be no more than one Assessment metadata field with fieldlabel='cc_allow_late_submission';
+ (s) There must be no more than one Assessment metadata field with fieldlabel='cc_maxattempts'.
+
+ [2] The set of rules to ensure that only valid Question types are defined in the Itemmetatadata fields.
+ The rules are:
+ (a) Only valid entries are defined for the Itemmetadata fieldlabel values;
+ (b) Only valid entries are defined for the Itemmetadata fieldentry values for fieldlabel = 'cc_profile';
+ (c) Only valid entries are defined for the Itemmetadata fieldentry values for fieldlabel = 'cc_weighting';
+ (d) Only valid entries are defined for the Itemmetadata fieldentry values for fieldlabel = 'qmd_scoringpermitted';
+ (e) Only valid entries are defined for the Itemmetadata fieldentry values for fieldlabel = 'qmd_computerscored';
+ (f) The Item metadata field with fieldlabel='cc_profile' must be present;
+ (g) There must only be one Item metadata fields with fieldlabel='cc_profile'for each Item;
+ (h) There must be no more than one Item metadata field with fieldlabel='cc_weighting'for each Item;
+ (i) There must be no more than one Item metadata field with fieldlabel='qmd_scoringpermitted' for each Item;
+ (j) There must be no more than one Item metadata field with fieldlabel='qmd_computerscored'for each Item.
+
+ [3] The set of rules to ensure that the structure of a True/False question is correct.
+ The rules are:
+ (a) That @rcardinality='Single';
+ (b) The element 'response_str' is not used;
+ (c) The element 'render_fib' is not used;
+ (d) That there are zero or two response labels;
+ (e) That the response processing uses the correct identifiers i.e. varequal/@respident value is equal to the response_lid/@ident;
+ (f) The varsubstring element must not be used.
+
+ [4] The set of rules to ensure that the structure of a Multiple-Choice (Single Response) question is correct.
+ The rules are:
+ (a) That @rcardinality='Single';
+ (b) The element 'response_str' is not used;
+ (c) The element 'render_fib' is not used;
+ (d) That there are at least three response labels;
+ (e) That the response processing uses the correct identifiers i.e. varequal/@respident value is equal to the response_lid/@ident;
+ (f) The varsubstring element must not be used.
+
+ [5] The set of rules to ensure that the structure of a Multiple-Choice (Multiple Response) question is correct.
+ The rules are:
+ (a) That @rcardinality='Multiple';
+ (b) The element 'response_str' is not used;
+ (c) The element 'render_fib' is not used;
+ (d) That there are at least two response labels;
+ (e) That the response processing uses the correct identifiers i.e. varequal/@respident value is equal to the response_lid/@ident;
+ (f) The varsubstring element must not be used..
+
+ [6] The set of rules to ensure that the structure of a Fill-in-Blank question is correct.
+ The rules are:
+ (a) The element 'response_lid' is not used;
+ (b) The element 'render_choice' is not used;
+ (c) That the response processing uses the correct identifiers i.e. varequal/@respident value is equal to the response_str/@ident;
+ (d) There is no use of the 'varsubstring' element.
+
+ [7] The set of rules to ensure that the structure of a Pattern Match question is correct.
+ The rules are:
+ (a) The element 'response_lid' is not used;
+ (b) The element 'render_choice' is not used;
+ (c) That the response processing uses the correct identifiers i.e. varequal/@respident value is equal to the response_str/@ident.
+
+ [8] The set of rules to ensure that the structure of an Essay question is correct.
+ The rules are:
+ (a) The element 'response_lid' is not used;
+ (b) The element 'render_choice' is not used;
+ (c) There is no use of the 'varequal' element;
+ (d) There is no use of the 'varsubstring' element;
+ (e) No more than a single Solution feedback can be supplied;
+ (f) The fieldentry Item metadata for an Essay question with the fieldlabel='qmd_computerscored' must be set as 'No'.
+
+ [9] The set of rules to ensure that the Response Processing/Response-Label structures are valid.
+ The rules are:
+ (a) There are no invalid response labels used in the 'varequal' element for T/F and MC questions.
+
+ [10] The set of rules to ensure that the structure of a Hint in an Item is correct.
+ The rules are:
+ (a) The element 'displayfeedback@feedbacktype=Hint' is accompanied by the @linkrefid='hint' attribute;
+ (b) The element 'itemfeedback@ident=hint' is not followed by the 'solution' element;
+ (c) The element 'itemfeedback@ident=hint' is not followed by the 'flow_mat' element;
+ (d) If the element 'displayfeedback@feedbacktype=Hint' is used it must be accompanied by hint feedback.
+
+ [11] The set of rules to ensure that the structure of a Solution in an Item is correct.
+ The rules are:
+ (a) The element 'displayfeedback@feedbacktype=Solution' is accompanied by the @linkrefid='solution' attribute;
+ (b) The element 'itemfeedback@ident=solution' is not followed by the 'hint' element;
+ (c) The element 'itemfeedback@ident=solution' is not followed by the 'flow_mat' element;
+ (d) If the element 'displayfeedback@feedbacktype=Solution' is used it must be accompanied by solution feedback.
+
+ [12] The set of rules to ensure that the general structure of the Response Processing in an Item is correct.
+ The rules are:
+ (a) The element 'displayfeedback@feedbacktype=Response' is not accompanied by the @linkrefid='solution' attribute;
+ (b) The element 'displayfeedback@feedbacktype=Response' is not accompanied by the @linkrefid='hint' attribute;
+ (c) To check that for each element 'displayfeedback@feedbacktype=Response' the corresponding 'itemfeedback' element exists;
+ (d) To check that a given response processing itemfeedback identifier there is a corresponding displayfeedback trigger for that identifier.
+
+ [13] The set of rules to ensure that the general features in an Item are correct.
+ The rules are:
+ (a) To ensure that each Item has a unique @ident attribute.
+
+
+
+ Schematron validation rules for the Common Cartridge v1p1 profile of QTI v1.2.1
+
+
+
+ RULE SET 1: Ensure that only valid metadata is defined in the Assessment metadata fields
+
+
+
+ [RULE 1a] Invalid Assessment metadata fieldlabel value: .
+
+
+
+
+
+ [RULE 1b] Invalid fieldentry Assessment metadata for the fieldlabel='qmd_assessmenttype' value: .
+
+
+
+
+
+ [RULE 1c] Invalid fieldentry Assessment metadata for the fieldlabel='qmd_scoretype' value: .
+
+
+
+
+
+ [RULE 1d] Invalid fieldentry Assessment metadata for the fieldlabel='qmd_feedbackpermitted' value: .
+
+
+
+
+
+ [RULE 1e] Invalid fieldentry Assessment metadata for the fieldlabel='qmd_hintspermitted' value: .
+
+
+
+
+
+ [RULE 1f] Invalid fieldentry Assessment metadata for the fieldlabel='qmd_solutionspermitted' value: .
+
+
+
+
+
+ [RULE 1g] Invalid fieldentry Assessment metadata for the fieldlabel='qmd_timelimit' i.e. not a valid integer with value: .
+
+
+
+
+
+ [RULE 1h] Invalid fieldentry Assessment metadata for the fieldlabel='cc_allow_late_submission' value: .
+
+
+
+
+
+ [RULE 1i] Invalid fieldentry Assessment metadata for the fieldlabel='cc_maxattempts' value: .
+
+
+
+
+
+ [RULE 1j] Invalid fieldentry Assessment metadata for the fieldlabel='cc_profile' value: .
+
+
+
+
+
+
+ [RULE 1k] The required metadata fields of fieldlabel='cc_profile' is either missing or too many i.e. it has count=.
+
+
+
+ [RULE 1l] There are repeated assessment metadata fields of fieldlabel='qmd_assessmenttype' with count=.
+
+
+
+ [RULE 1m] There are repeated assessment metadata fields of fieldlabel='qmd_scoretype' with count=.
+
+
+
+ [RULE 1n] There are repeated assessment metadata fields of fieldlabel='qmd_feedbackpermitted' with count=.
+
+
+
+ [RULE 1o] There are repeated assessment metadata fields of fieldlabel='qmd_hintspermitted' with count=.
+
+
+
+ [RULE 1p] There are repeated assessment metadata fields of fieldlabel='qmd_solutionspermitted' with count=.
+
+
+
+ [RULE 1q] There are repeated assessment metadata fields of fieldlabel='qmd_timelimit' with count=.
+
+
+
+ [RULE 1r] There are repeated assessment metadata fields of fieldlabel='cc_allow_late_submission' with count=.
+
+
+
+ [RULE 1s] There are repeated assessment metadata fields of fieldlabel='cc_maxattempts' with count=.
+
+
+
+
+
+
+
+
+
+ RULE SET 2: Ensure that only valid metadata is defined in the Itemmetatadata fields
+
+
+
+ [RULE 2a] Invalid Itemmetadata fieldlabel value: .
+
+
+
+
+
+ [RULE 2b] Invalid fieldentry Question Type (fieldlabel='cc_profile') value: .
+
+
+
+
+
+ [RULE 2c] Invalid fieldentry Item metadata weighting for the fieldlabel='cc_weighting' i.e. not an integer in the range 1..99, with value: .
+
+
+
+
+
+ [RULE 2d] Invalid fieldentry Item metadata for the fieldlabel='qmd_scoringpermitted' with value: .
+
+
+
+
+
+ [RULE 2e] Invalid fieldentry Item metadata for the fieldlabel='qmd_computerscored' with value: .
+
+
+
+
+
+
+ [RULE 2f] The Item metadata field with fieldlabel='cc_profile' is missing.
+
+
+
+ [RULE 2g] There are too many Item metadata fields with fieldlabel='cc_profile' i.e. count=.
+
+
+
+ [RULE 2h] There are too many Item metadata fields with fieldlabel='cc_weighting' i.e. count=.
+
+
+
+ [RULE 2i] There are too many Item metadata fields with fieldlabel='qmd_scoringpermitted' i.e. count=.
+
+
+
+ [RULE 2j] There are too many Item metadata fields with fieldlabel='qmd_computerscored' i.e. count=.
+
+
+
+
+
+
+
+
+
+ RULE SET 3: Ensure that the structure of a True/False question is correct
+
+
+
+ [RULE 3a] Incorrect cardinality attribute value for the T/F question:
+
+
+
+ [RULE 3b] The invalid 'response_str' element has been used for a T/F question.
+
+
+
+ [RULE 3c] The invalid 'render_fib' element has been used for a T/F question.
+
+
+
+ [RULE 3d] There are too many or too few response labels for the T/F question.
+
+
+
+ [RULE 3e] The T/F response processing Varequal respident attribute
+ ()
+ value is not equal to the corresonding Response_lid ident
+ ()
+ attribute for the True/False question.
+
+
+
+ [RULE 3f] There is an invalid use of the varsubstring element in a T/F question.
+
+
+
+
+
+
+
+
+
+ RULE SET 4: Ensure that the structure of a MC-SR question is correct
+
+
+
+ [RULE 4a] Incorrect cardinality attribute value for the MC-SR question: .
+
+
+
+ [RULE 4b] The invalid 'response_str' element has been used for a MC-SR question.
+
+
+
+ [RULE 4c] The invalid 'render_fib' element has been used for a MC-SR question.
+
+
+
+ [RULE 4d] There are too too few response labels for the MC-SR question.
+
+
+
+ [RULE 4e] The MC-SR response processing Varequal respident attribute
+ ()
+ value is not equal to the corresonding Response_lid ident
+ ()
+ attribute for the Multiple Choice single response question.
+
+
+
+ [RULE 4f] There is an invalid use of the varsubstring element in a MC-SR question.
+
+
+
+
+
+
+
+
+
+ RULE SET 5: Ensure that the structure of a MC-MR question is correct
+
+
+
+
+ [RULE 5a] Incorrect cardinality attribute value for the MC-MR question: .
+
+
+
+ [RULE 5b] The invalid 'response_str' element has been used for a MC-MR question.
+
+
+
+ [RULE 5c] The invalid 'render_fib' element has been used for a MC-MR question.
+
+
+
+ [RULE 5d] There are too too few response labels for the MC-MR question.
+
+
+
+ [RULE 5e] The MC-MR response processing Varequal respident attribute
+ ()
+ value is not equal to the corresonding Response_lid ident
+ ()
+ attribute for the Multiple Choice multiple response question.
+
+
+
+ [RULE 5f] There is an invalid use of the varsubstring element in a MC-MR question.
+
+
+
+
+
+
+
+
+
+ RULE SET 6: Ensure that the structure of a FIB question is correct
+
+
+
+
+ [RULE 6a] The invalid 'response_lid' element has been used for a FIB question.
+
+
+
+ [RULE 6b] The invalid 'render_choice' element has been used for a FIB question.
+
+
+
+ [RULE 6c] The FIB response processing Varequal respident attribute
+ ()
+ value is not equal to the corresonding Response_str ident
+ ()
+ attribute for the FIB question.
+
+
+
+ [RULE 6d] There is an invalid use of the 'varsubstring' element in the FIB question.
+
+
+
+
+
+
+
+
+
+ RULE SET 7: Ensure that the structure of a Pattern Match question is correct
+
+
+
+
+ [RULE 7a] The invalid 'response_lid' element has been used for a Pattern Match question.
+
+
+
+ [RULE 7b] The invalid 'render_choice' element has been used for a Pattern Match question.
+
+
+
+ [RULE 7c] The FIB response processing Varequal respident attribute
+ ()
+ value is not equal to the corresonding Response_str ident
+ ()
+ attribute for the Pattern Match question.
+
+
+
+
+
+
+
+
+
+ RULE SET 8: Ensure that the structure of a Essay question is correct
+
+
+
+
+ [RULE 8a] The invalid 'response_lid' element has been used for an Essay question.
+
+
+
+ [RULE 8b] The invalid 'render_choice' element has been used for an Essay question.
+
+
+
+ [RULE 8c] There is an invalid use of the 'varequal' element in an Essay question.
+
+
+
+ [RULE 8d] There is an invalid use of the 'varsubstring' element in an Essay question.
+
+
+
+ [RULE 8e] Too many Solution feedback structures are supplied.
+
+
+
+ [RULE 8f] Invalid fieldentry Item metadata for an Essay question with the fieldlabel='qmd_computerscored' with value: .
+
+
+
+
+
+
+
+
+
+
+
+
+
+ RULE SET 10: Ensure that the structure of a Hint in an Item is correct
+
+
+
+
+ [RULE 10a] The displayfeedback@feedbacktype='Solution' has been used to identify a Hint.
+
+
+
+ [RULE 10b] The itemfeedback@ident='hint' has been used to identify a Solution.
+
+
+
+ [RULE 10c] The itemfeedback@ident='hint' has been used to identify Response feedback.
+
+
+
+
+
+
+ [RULE 10d] A displayfeedback[@feedbacktype='Hint'] trigger has no accompanying hint feedback.
+
+
+
+
+
+
+
+
+ RULE SET 11: Ensure that the structure of a Solution in an Item is correct
+
+
+
+
+ [RULE 11a] The displayfeedback@feedbacktype='Hint' has been used to identify a Solution.
+
+
+
+ [RULE 11b] The itemfeedback@ident='solution' has been used to identify a Hint.
+
+
+
+ [RULE 11c] The itemfeedback@ident='solution' has been used to identify Response feedback.
+
+
+
+
+
+
+ [RULE 11d] A displayfeedback[@feedbacktype='Solution'] trigger has no accompanying solution feedback.
+
+
+
+
+
+
+
+
+ RULE SET 12: Ensure that the structure of the response processing feedback structure in an Item is correct
+
+
+
+
+ [RULE 12a] The displayfeedback@feedbacktype='Response' has been used to identify a Solution.
+
+
+
+ [RULE 12b] The displayfeedback@feedbacktype='Response' has been used to identify a Hint.
+
+
+
+
+
+
+ [RULE 12c] For the given displayfeedback identifier () there is no itemfeedback with the correct identifier ().
+
+
+
+
+
+ [RULE 12d] For the given response processing itemfeedback identifier () there is no displayfeedback trigger with the correct identifier ().
+
+
+
+
+
+
+
+
+ RULE SET 13: Ensure that the generic features of an Item are correct
+
+
+
+
+ [RULE 13a] There are Items that have common identifiers: .
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ This is the container for alternative content. This content is to be
+ displayed if, for whatever reason, the primary content cannot be
+ rendered. Alternative language implementations of the host 'material'
+ element are also supported using this structure.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ QTI General
+
+ This defines the set of clauses that can be used within the
+ logic statements of 'and', 'or' and 'not'. These logic statements
+ enable the construction of complex conditional tests.
+
+ Common Cartridge Profile
+
+ The extension has been removed. All of the conditions operating
+ on duration have been removed. The 'or' conditional has been removed
+ and 'and' and 'not' have been considerably simplified.
+
+
+
+
+
+
+
+
+
+
+
+
+
+ QTI General
+
+ An Assessment object is the logical construction of the test. An Assessment must
+ contain at least one Section which in turn will contain Items and/or Sections. An
+ Assessment must eventually be constructed from a set of Items i.e. questions
+ that are to be offered in the test. An Assessment object contains all of the information
+ to make the use of individual Items meaningful i.e. apart from the Sections the object
+ includes the relationships between the Sections, the group evaluation processing and
+ the corresponding feedback.
+
+ Common Cartridge Profile
+
+ The Assessment must consist of only one Section. The only other permitted attributes
+ are the mandatory identifier and title. Optional language, metadata, rubric and
+ presentation_material is also supported.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ QTI General
+
+ The conditional test that is to be applied to the user’s response.
+ A wide range of separate and combinatorial tests can be applied.
+
+ Common Cartridge Profile
+
+ The extension has been removed. All of the conditions operating
+ on duration have been removed. The only permited conditions are
+ 'varequal', 'varsubstring', 'and', 'other'.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ This is the container for all of the instructions for the presentation with flow
+ blocking of the question during a test. This information includes the actual
+ material to be presented. The labels for the possible responses are also
+ identified and these are used by the response processing element defined
+ elsewhere in the Item.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ This is the blocking/paragraph equivalent to the 'response_label'
+ structure. This structure shold always be used to encapsulate the
+ 'response_label construct.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ This allows the materials to be displayed to the users to be grouped together
+ using flows. The manner in which these flows are handled is dependent upon
+ the display-engine.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ QTI General
+
+ Contains the hints(s) that are to be revealed to the participant. When these hints are revealed is outside the scope of the
+ specification. The information can be revealed in several manners. The default mode is to show the 'Complete' hint.
+
+ Common Cartridge Profile
+
+ The material is presented in the form of flow_mat only. The only form of feedback is 'Complete'.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ This is the information that is presented as a hint.
+
+
+
+
+
+
+
+
+
+
+
+ An Item the smallest exchangeable object within QTI-XML. An Item is more than a
+ ‘Question’ in that it contains the ‘Question’, the presentation/rendering instructions,
+ the response processing to be applied to the participant’s response(s), the feedback
+ that may be presented (including hints and solutions) and the meta-data describing
+ the Item.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ The container for the feedback that is to be presented as a result of the
+ user’s responses. The feedback can include hints and solutions and
+ both of these can be revealed in a variety of different ways.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Contains all of the QTI-specific metada-data
+ to be applied to the Item. This meta-data can
+ consist of either entries defined using an
+ external vocabulary or the individually named
+ entries. Usage of the contained attributes are
+ deprecated apart from the 'qtimetadata' attribute.
+
+
+
+
+
+
+
+
+
+
+ This is the container for any content that is to be displayed by the question-engine.
+ The supported content types are text (emphasised or not), images, audio, video,
+ application and applet. The content can be internally referenced to avoid the need
+ for duplicate copies. Alternative information can be defined – this is used if the
+ primary content cannot be displayed.
+
+ Common Cartridge Profile
+
+ Only the 'mattext', 'matref' and 'matbreak' types are permitted.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ QTI General
+
+ This defines the set of clauses that can be used within the
+ logic statements of 'and', 'or' and 'not'. These logic statements
+ enable the construction of complex conditional tests.
+
+ Common Cartridge Profile
+
+ The extension has been removed. All of the conditions operating
+ on duration have been removed. The 'or' conditional has been removed
+ and 'and' and 'not' have been considerably simplified.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ QTI General
+
+ An object bank is an unordered set of items and sections. It is recommended
+ that there is a metadata description for the object bank as a whole. The object
+ bank should have a globally unique identifier.
+
+ Common Cartridge Profile
+
+ In the Common Cartridge the object-bank can only contain Items. Meta-data
+ support is available but the profile has no mandated entries.
+
+
+
+
+
+
+
+
+
+
+
+
+ QTI General
+
+ This defines the set of clauses that can be used within the
+ logic statements of 'and', 'or' and 'not'. These logic statements
+ enable the construction of complex conditional tests.
+
+ Common Cartridge Profile
+
+ The extension has been removed. All of the conditions operating
+ on duration have been removed. The 'or' conditional has been removed
+ and 'and' and 'not' have been considerably simplified.
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Contains all of the variable declarations that are to be
+ made available to the scoring algorithm. Each variable
+ is declared using the 'decvar' structure apart from the
+ default variable called ‘SCORE’ that is an integer and
+ has a default value of zero (0).
+
+ Common Cartridge Profile
+
+ A single variable is permitted. This is "SCORE".
+
+
+
+
+
+
+
+
+
+
+ Contains all of the instructions for the presentation of the question
+ during an evaluation. This information includes the actual material
+ to be presented. The labels for the possible responses are also
+ identified and these are used by the response processing element
+ defined elsewhere in the Item.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ This is the information that is to be presented to set the context for the
+ contained objects. This can be used to contain question-based material
+ that is common to all of the child objects. This is used in Assessment and
+ Section objects.
+
+
+ This is the information that is used to describe the solution.
+
+
+
+
+
+
+
+
+
+
+ QTI General
+
+ The QTI-specific meta-data assigned to the parent object i.e.
+ Assessment, Section, Item or Object-bank. This approach
+ requires that the approriate external vocabulary is defined and
+ referenced in label/field tuple.
+
+ Common Cartridge Profile
+
+ The Vocabulary structure has been removed.
+
+
+
+
+
+
+
+
+
+
+ The structure responsible for containing each of
+ the QTI-specific meta-data fields. The label should
+ appear in the vocabulary. If no vocabulary is used
+ then external validation cannot take place.
+
+
+
+
+
+
+
+
+
+
+
+
+ The root structure can consist of either:
+
+ * A single object bank;
+ * An assessment;
+ * A set of item(s);
+ * A set of section(s);
+ * Any combination of items and sections.
+
+ As the root this is mandatory and can
+ occur once.
+
+ Common Cartridge Profile
+
+ A Commn Cartridge is allowed to contain
+ only an objectbank or an assessement.
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Contains the instructions for the question-engine to render the question
+ using a classical multiple choice format. The number of possible responses
+ is determined by the 'response_label' structures contained. Both flowed and
+ non-flowed formats are supported
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Contains the instructions for the question-engine to render the question
+ using a classical fill-in blank format. The number of possible responses
+ is determined by the 'response_label' structures contained. Both flowed
+ and non-flowed formats are supported.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Contains the actual test to be applied to the user responses
+ to determine their correctness or otherwise. Each 'respcondition'
+ contains an actual test, the assignment of a value to the associate
+ scoring variables and the identification of the feedback to be
+ associated with the test.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ This contains the possible response choices that are presented
+ to the user. This information includes the material to be shown
+ to the user and the logical label that is associated with that
+ response. The label is used in the response processing. Flow
+ and non-flow approaches are supported.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ QTI General
+
+ This contains the instructions for the presentation of questions whose response will be either a 'response_lid' (logical identifier),
+ 'response_xy' (xy-co-ordinate), 'response_str' (a string), 'response_num' (a number) and 'response_grp' ( a group of logical
+ identifiers). The question can be rendered in a variety of ways depending on the way in which the material is to be presented to the
+ participant.
+
+ Common Cartridge Profile
+
+ Only the response_lid and response_str response types are supported with render_choice and render_fib rendering.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ QTI General
+
+ This contains the instructions for the presentation of questions whose response will be either a 'response_lid' (logical identifier),
+ 'response_xy' (xy-co-ordinate), 'response_str' (a string), 'response_num' (a number) and 'response_grp' ( a group of logical
+ identifiers). The question can be rendered in a variety of ways depending on the way in which the material is to be presented to the
+ participant.
+
+ Common Cartridge Profile
+
+ Only the response_lid and response_str response types are supported with render_choice and render_fib rendering.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ This contains all of the instructions for the response
+ processing. This includes the scoring variables to contain
+ the associated scores and the set of response condition
+ tests that are to be applied to the received user response.
+
+
+
+
+
+
+
+
+
+
+
+
+
+ This is used to contain contextual information i.e. rubric that
+ is important to the object e.g. it could contain standard data
+ values that might or might not be useful for answering the
+ question.
+
+ Common Cartridge Profile
+
+ This is used in assessments to provide instructions. Only a
+ single mattext is permitted in the material.
+
+
+
+
+
+
+
+
+
+
+ QTI General
+
+ A Section is the core grouping concept within QTI. A Section consists of one or more Items or Sections (or
+ references to Items and Sections). In general, the objects contained within a Secton will have some relationship
+ either in terms of content or content delivery. The Section data structure is used to define arbitrarily complex
+ hierarchical section and item data structures. It may contain meta-data, objectives, rubric control switches,
+ assessment-level processing, feedback and selection and sequencing information for sections and items.
+
+ Common Cartridge Profile
+
+ In Common Cartridge the Section can only contain a list of Items. No metadata is permitted. The identifier is
+ mandatory but the title and language are optional.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ QTI General
+
+ Contains the solution(s) that are to be revealed to the participant. When these solutions are revealed is outside the scope of the
+ specification. The information can be revealed in several manners. The default mode is to show the 'Complete' solution.
+
+ Common Cartridge Profile
+
+ The material is presented in the form of flow_mat only. The only form of feedback is 'Complete'.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ This is the information that is used to describe the solution.
+
+
+
+
+
+
+
+
+
+
+
+ This is the container of any text that is to be displayed to the users.
+ It is the base type for normal and emphasised text.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ This is used to contain a reference to the required full material block. This
+ material will have had an identifier assigned to enable such a reference to
+ be reconciled when the instance is parsed into the system.
+
+
+
+
+
+
+
+
+
+
+
+
+ This is used to contain a reference to the required full material block. This
+ material will have had an identifier assigned to enable such a reference to
+ be reconciled when the instance is parsed into the system.
+
+
+
+
+
+
+
+
+
+
+
+
+ QTI General
+
+ This is used for the declaration of the scoring variables.
+ The name of the variable that is to be declared. The default
+ name is ‘SCORE’. All numeric variables have the associated
+ ‘x.min’, ‘x.max’ and ‘x.normalised’ variables declared.
+ Several of the optional attributes depend upon the type of
+ variable that is declared.
+
+ Common Cartridge Profile
+
+ Only the variable types of decimal and integer are permitted.
+ Only a single "SCORE" variable is permitted.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ QTI General
+
+ This is responsible for changing the value of the scoring
+ variable as a result of the associated response processing test.
+ The default action is to 'Set' the 'SCORE' variable to the value
+ given in the string.
+
+ Common Cartridge Profile
+
+ Only the actons Set, Add and Subtract are premitted.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ This is the test of equivalence. The data for the test is
+ contained as a string. The accompanying attributes are
+ the identifier for the associated 'response_label', the
+ ordinal 'index' of the response and whether or not the
+ value is case-sensitive when processing strings.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ This is used for assigning an associated feedback to the
+ aggregated scoring if the ‘True’ state results. Feedback
+ for hints, solutions and response processing are supported.
+ The feedback is identified using the pointer 'linkrefid'.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ This is the test for a contained substring.
+ The data for comparison is presented as a
+ string. The associated attributes are the
+ response label identifier, the ordinal index of
+ the response and whether or not the value is
+ case-sensitive when processing the strings.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Index: samigo-api/src/java/xml/xsl/dataTransform/import/v1p2/extractEMIItem.xsl
===================================================================
--- samigo-api/src/java/xml/xsl/dataTransform/import/v1p2/extractEMIItem.xsl (revision 0)
+++ samigo-api/src/java/xml/xsl/dataTransform/import/v1p2/extractEMIItem.xsl (working copy)
@@ -0,0 +1,87 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ []()
+
+
+
+
+ []()
+
+
+
+
+ []()
+
+
+
+
+ []()
+
+
+
+
+ []
+
+
+
+
+
+
+
+
+
+ [|]
+ @ATTACH@
+
+ @[]()
+
+
+ @[]()
+
+
+ @[]()
+
+
+ @[]()
+
+ @ANSWERS@
+
+ [](|)
+
+
+
+
+
+
+
Index: samigo-api/src/java/xml/xsl/dataTransform/import/v1p2/extractItem.xsl
===================================================================
--- samigo-api/src/java/xml/xsl/dataTransform/import/v1p2/extractItem.xsl (revision 133459)
+++ samigo-api/src/java/xml/xsl/dataTransform/import/v1p2/extractItem.xsl (working copy)
@@ -13,6 +13,7 @@
+
@@ -20,6 +21,7 @@
+
Index: samigo-app/pom.xml
===================================================================
--- samigo-app/pom.xml (revision 133459)
+++ samigo-app/pom.xml (working copy)
@@ -127,6 +127,7 @@
javax.servlet.jspjsp-api
+ providedjavax.servlet
@@ -179,6 +180,7 @@
org.springframeworkspring-webmvc
+ runtimestruts
Index: samigo-app/src/java/org/sakaiproject/jsf/renderer/RichTextEditArea.java
===================================================================
--- samigo-app/src/java/org/sakaiproject/jsf/renderer/RichTextEditArea.java (revision 133459)
+++ samigo-app/src/java/org/sakaiproject/jsf/renderer/RichTextEditArea.java (working copy)
@@ -37,7 +37,6 @@
import org.sakaiproject.component.cover.ServerConfigurationService;
import org.sakaiproject.tool.assessment.services.assessment.AssessmentService;
-import org.sakaiproject.tool.assessment.ui.listener.util.ContextUtil;
import org.sakaiproject.tool.assessment.util.TextFormat;
import org.sakaiproject.tool.cover.ToolManager;
import org.sakaiproject.util.EditorConfiguration;
@@ -88,6 +87,7 @@
ResponseWriter writer = context.getResponseWriter();
Object value = null;
+ String identity = (String) component.getAttributes().get("identity");
String reset = (String) component.getAttributes().get("reset");
if (reset == null || !reset.equals("true")) {
if (component instanceof UIInput)
@@ -180,18 +180,18 @@
String justArea = (String) component.getAttributes().get("justArea");
if (editor.equalsIgnoreCase("FCKeditor") || editor.equalsIgnoreCase("ckeditor")) {
- encodeFCK(writer, contextPath, (String) value, outCol,
+ encodeFCK(writer, contextPath, (String) value, identity, outCol,
outRow, justArea, clientId, valueHasRichText, hasToggle);
}
else
{
- encodeHtmlarea(writer, contextPath, (String) value, outCol + "px", outRow + "px",
+ encodeHtmlarea(writer, contextPath, (String) value, identity, outCol + "px", outRow + "px",
tmpCol, tmpRow, lineOfToolBar, justArea, clientId);
}
}
- private void encodeHtmlarea(ResponseWriter writer, String contextPath, String value, String outCol,
+ private void encodeHtmlarea(ResponseWriter writer, String contextPath, String value, String identity, String outCol,
String outRow, String tmpCol, String tmpRow, int lineOfToolBar, String justArea, String clientId) throws IOException
{
@@ -212,7 +212,9 @@
writer.write(clientId);
writer.write("_textinput\" id=\"");
writer.write(clientId);
- writer.write("_textinput\" disabled>");
+ writer.write("_textinput\" ");
+ writer.write(getIdentityAttribute(identity));
+ writer.write("disabled>");
writer.write( (String) value);
writer.write("\n");
if ( (tmpCol != null) && (tmpRow != null))
@@ -286,7 +288,8 @@
writer.write(clientId);
writer.write("_textinput\" id=\"");
writer.write(clientId);
- writer.write("_textinput\"");
+ writer.write("_textinput\" ");
+ writer.write(getIdentityAttribute(identity));
writer.write(">\n");
if (lineOfToolBar == 3)
@@ -344,7 +347,9 @@
writer.write(clientId);
writer.write("_textinput\" id=\"");
writer.write(clientId);
- writer.write("_textinput\">");
+ writer.write("_textinput\" ");
+ writer.write(getIdentityAttribute(identity));
+ writer.write(">");
writer.write( (String) value);
writer.write("\n");
if (lineOfToolBar == 3)
@@ -401,7 +406,7 @@
}
- private void encodeFCK(ResponseWriter writer, String contextPath, String value, String outCol,
+ private void encodeFCK(ResponseWriter writer, String contextPath, String value, String identity, String outCol,
String outRow, String justArea, String clientId, boolean valueHasRichText, String hasToggle) throws IOException
{
//come up w/ rows/cols for the textarea if needed
@@ -429,7 +434,7 @@
value = FormattedText.escapeHtmlFormattedTextarea((String) value);
}
- writer.write("
@@ -77,14 +80,33 @@
ItemAuthorBean itemauthorBean = (ItemAuthorBean) ContextUtil.lookupBean("itemauthor");
String itemId = itemauthorBean.getItemId();
- if (itemId !=null && !("").equals(itemId)){
- ItemDataIfc item = itemService.getItem(itemId);
- log.debug("*** item attachment="+item.getItemAttachmentList());
- resetItemAttachment(itemauthorBean.getResourceHash(), item.getItemAttachmentList(), assessmentService);
- }
- else{
- resetItemAttachment(itemauthorBean.getResourceHash(), new ArrayList(), assessmentService);
- }
+
+// Object aBean = itemauthorBean.getCurrentAnswer();
+ AnswerBean answerBean = itemauthorBean.getCurrentAnswer();
+
+ if (answerBean == null) {
+ if (itemId !=null && !("").equals(itemId)){
+ ItemDataIfc item = itemService.getItem(itemId);
+ log.debug("*** item attachment="+item.getItemAttachmentList());
+ resetItemAttachment(itemauthorBean.getResourceHash(), item.getItemAttachmentList(), assessmentService);
+ }
+ else{
+ resetItemAttachment(itemauthorBean.getResourceHash(), new ArrayList(), assessmentService);
+ }
+ }
+ else {
+ Long sequence = answerBean.getSequence();
+ if (itemId !=null && !("").equals(itemId)){
+ ItemDataIfc item = itemService.getItem(itemId);
+ ItemTextIfc itemText = item.getItemTextBySequence(sequence);
+ //log.debug("*** item attachment="+item.getItemAttachmentList());
+ resetItemTextAttachment(answerBean.getResourceHash(), itemText.getItemTextAttachmentList(), assessmentService);
+ }
+ else{
+ resetItemTextAttachment(answerBean.getResourceHash(), new ArrayList(), assessmentService);
+ }
+
+ }
}
private void resetItemAttachment(HashMap resourceHash, List attachmentList, AssessmentService service){
@@ -166,6 +188,44 @@
}
}
*/
+
+ private void resetItemTextAttachment(HashMap resourceHash, List attachmentList, AssessmentService service){
+ // 1. we need to make sure that attachment removed/added by file picker
+ // will be restored/remove when user cancels the entire modification
+ if (attachmentList != null){
+ for (int i=0; i0){
log.debug("**** DeliveryActionListener #1a");
ag = setAssessmentGradingFromItemData(delivery, itemGradingHash, true);
@@ -892,10 +892,10 @@
//questionCount = secFacade.getItemSet().size();
// need to get ItemArraySort, insteand of getItemSet, to return corr number for random draw parts
- ArrayList itemlist = secFacade.getItemArray();
+ List itemlist = secFacade.getItemArray();
long seed = getSeed(secFacade, delivery, (long) AgentFacade.getAgentString().hashCode());
- ArrayList sortedlist = getItemArraySortedWithRandom(secFacade, itemlist, seed);
+ List sortedlist = getItemArraySortedWithRandom(secFacade, itemlist, seed);
questionCount = sortedlist.size();
if ((delivery.getNoQuestions() || questionCount != 0) && itemIndex > (questionCount - 1) && sectionCount == sectionIndex) {
@@ -971,8 +971,8 @@
// daisy change to use this existing constructor instead 11/09/05
SectionContentsBean sec = new SectionContentsBean(part);
- ArrayList itemSet = null;
- ArrayList itemlist = part.getItemArray();
+ List itemSet = null;
+ List itemlist = part.getItemArray();
long seed = 0;
if (delivery.getActionMode()==DeliveryBean.GRADE_ASSESSMENT) {
StudentScoresBean studentscorebean = (StudentScoresBean) ContextUtil.lookupBean("studentScores");
@@ -1064,9 +1064,9 @@
//SectionContentsBean sec = new SectionContentsBean();
SectionContentsBean sec = new SectionContentsBean(part);
- ArrayList itemlist = part.getItemArray();
+ List itemlist = part.getItemArray();
long seed = getSeed(part, delivery, (long) AgentFacade.getAgentString().hashCode());
- ArrayList itemSet= getItemArraySortedWithRandom(part, itemlist, seed);
+ List itemSet= getItemArraySortedWithRandom(part, itemlist, seed);
sec.setQuestions(itemSet.size());
@@ -1201,6 +1201,7 @@
item.getTypeId().equals(TypeIfc.MULTIPLE_CHOICE_SURVEY) ||
item.getTypeId().equals(TypeIfc.AUDIO_RECORDING) ||
item.getTypeId().equals(TypeIfc.MATRIX_CHOICES_SURVEY))
+
{
itemBean.setFeedback(item.getGeneralItemFeedback());
}
@@ -1227,8 +1228,8 @@
// this doesn't happen very often.
- ArrayList itemgradingList = itemBean.getItemGradingDataArray();
- Iterator iterAnswer = itemgradingList.iterator();
+ List itemgradingList = itemBean.getItemGradingDataArray();
+ Iterator iterAnswer = itemgradingList.iterator();
boolean haswronganswer =true;
HashMap fibmap = new HashMap();
int mcmc_match_counter = 0;
@@ -1240,11 +1241,11 @@
//calculate total # of correct answers.
int correctAnswers = 0;
- if ((item.getTypeId().equals(TypeIfc.MULTIPLE_CORRECT) )|| (item.getTypeId().equals(TypeIfc.MULTIPLE_CORRECT_SINGLE_SELECTION) )||(item.getTypeId().equals(TypeIfc.MATCHING) )){
+ if ((item.getTypeId().equals(TypeIfc.EXTENDED_MATCHING_ITEMS)) || (item.getTypeId().equals(TypeIfc.MULTIPLE_CORRECT) )|| (item.getTypeId().equals(TypeIfc.MULTIPLE_CORRECT_SINGLE_SELECTION) )||(item.getTypeId().equals(TypeIfc.MATCHING) )){
Iterator itemTextIter = item.getItemTextArray().iterator();
while (itemTextIter.hasNext()){
ItemTextIfc itemText = (ItemTextIfc) itemTextIter.next();
- ArrayList answerArray = itemText.getAnswerArray();
+ List answerArray = itemText.getAnswerArray();
if (answerArray != null){
for (int indexAnswer =0; indexAnswer 1);
+ }
+
public void populateMatching(ItemDataIfc item, ItemContentsBean bean, HashMap publishedAnswerHash)
{
// used only for questions with distractors where the user has selected None of the Above
@@ -1787,7 +1900,7 @@
fbean.setText("");
fbean.setHasInput(true);
- ArrayList datas = bean.getItemGradingDataArray();
+ List datas = bean.getItemGradingDataArray();
if (datas == null || datas.isEmpty())
{
fbean.setIsCorrect(false);
@@ -1794,10 +1907,10 @@
}
else
{
- Iterator iter2 = datas.iterator();
+ Iterator iter2 = datas.iterator();
while (iter2.hasNext())
{
- ItemGradingData data = (ItemGradingData) iter2.next();
+ ItemGradingData data = iter2.next();
if ((data.getPublishedAnswerId()!=null) && data.getPublishedAnswerId().equals(answer.getId()))
{
fbean.setItemGradingData(data);
@@ -1937,7 +2050,7 @@
fbean.setText("");
fbean.setHasInput(true);
- ArrayList datas = bean.getItemGradingDataArray();
+ List datas = bean.getItemGradingDataArray();
if (datas == null || datas.isEmpty())
{
fbean.setIsCorrect(false);
@@ -1944,10 +2057,10 @@
}
else
{
- Iterator iter2 = datas.iterator();
+ Iterator iter2 = datas.iterator();
while (iter2.hasNext())
{
- ItemGradingData data = (ItemGradingData) iter2.next();
+ ItemGradingData data = iter2.next();
log.debug(" " + data.getPublishedAnswerId() + " = " + answer.getId());
@@ -1997,8 +2110,8 @@
ArrayList matrixArray = new ArrayList();
List columnIndexList = new ArrayList();
- ArrayList itemTextArray = item.getItemTextArraySorted();
- ArrayList answerArray = ((ItemTextIfc)itemTextArray.get(0)).getAnswerArraySorted();
+ List itemTextArray = item.getItemTextArraySorted();
+ List answerArray = ((ItemTextIfc)itemTextArray.get(0)).getAnswerArraySorted();
MatrixSurveyBean mbean = null;
List stringList = new ArrayList();
@@ -2028,7 +2141,7 @@
for(int i=0; i alist = new ArrayList();
List slist = new ArrayList();
for(int j= 0; j itemGradingArray = bean.getItemGradingDataArray();
for (int k=0; k< itemGradingArray.size(); k++)
{
- ItemGradingData data = (ItemGradingData)itemGradingArray.get(k);
+ ItemGradingData data = itemGradingArray.get(k);
if((data.getPublishedItemTextId()).longValue() == text.getId().longValue()){
mbean.setItemGradingData(data);
if (data.getPublishedAnswerId() != null)
@@ -2201,7 +2314,7 @@
}
fbean.setHasInput(true); // input box
- ArrayList datas = bean.getItemGradingDataArray();
+ List datas = bean.getItemGradingDataArray();
if (datas == null || datas.isEmpty())
{
fbean.setIsCorrect(false);
@@ -2398,7 +2511,7 @@
SectionDataIfc section = (SectionDataIfc) i1.next();
Iterator i2 = null;
- ArrayList itemlist = section.getItemArray();
+ List itemlist = section.getItemArray();
long seed = 0;
if (delivery.getActionMode()==DeliveryBean.GRADE_ASSESSMENT) {
StudentScoresBean studentscorebean = (StudentScoresBean) ContextUtil.lookupBean("studentScores");
@@ -2407,7 +2520,7 @@
else {
seed = getSeed(section, delivery, (long) AgentFacade.getAgentString().hashCode());
}
- ArrayList sortedlist = getItemArraySortedWithRandom(section, itemlist, seed);
+ List sortedlist = getItemArraySortedWithRandom(section, itemlist, seed);
i2 = sortedlist.iterator();
while (i2.hasNext()) {
@@ -2589,7 +2702,7 @@
/* this method takes the list returned from the data/dao class, and checks for part type and returns a sorted list of items. If part type is not random then return the original list
*/
- private ArrayList getItemArraySortedWithRandom(SectionDataIfc part, ArrayList list, long seed) {
+ private List getItemArraySortedWithRandom(SectionDataIfc part, List list, long seed) {
Integer numberToBeDrawn= null;
Index: samigo-app/src/java/org/sakaiproject/tool/assessment/ui/listener/delivery/SaCharCountListener.java
===================================================================
--- samigo-app/src/java/org/sakaiproject/tool/assessment/ui/listener/delivery/SaCharCountListener.java (revision 133459)
+++ samigo-app/src/java/org/sakaiproject/tool/assessment/ui/listener/delivery/SaCharCountListener.java (working copy)
@@ -3,6 +3,7 @@
import java.util.ArrayList;
import java.util.Formatter;
import java.util.Iterator;
+import java.util.List;
import java.util.Set;
import javax.faces.event.AbortProcessingException;
@@ -41,11 +42,11 @@
while (iter2.hasNext()) {
ItemContentsBean item = (ItemContentsBean) iter2.next();
ItemDataIfc itemData = item.getItemData();
- ArrayList itemGradingDataArray = item.getItemGradingDataArray();
+ List itemGradingDataArray = item.getItemGradingDataArray();
if (itemGradingDataArray != null && itemGradingDataArray.size() != 0) {
- Iterator iter3 = itemGradingDataArray.iterator();
+ Iterator iter3 = itemGradingDataArray.iterator();
while (iter3.hasNext()) {
- ItemGradingData itemGrading = (ItemGradingData) iter3.next();
+ ItemGradingData itemGrading = iter3.next();
if (itemData != null) {
if (itemId.equals(itemData.getItemIdString()) && itemGrading.getAnswerText() != null) {
if (itemGrading.getAnswerText() != null) {
Index: samigo-app/src/java/org/sakaiproject/tool/assessment/ui/listener/delivery/SubmitToGradingActionListener.java
===================================================================
--- samigo-app/src/java/org/sakaiproject/tool/assessment/ui/listener/delivery/SubmitToGradingActionListener.java (revision 133459)
+++ samigo-app/src/java/org/sakaiproject/tool/assessment/ui/listener/delivery/SubmitToGradingActionListener.java (working copy)
@@ -22,10 +22,12 @@
package org.sakaiproject.tool.assessment.ui.listener.delivery;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
+import java.util.List;
import java.util.Set;
import javax.faces.application.FacesMessage;
@@ -264,7 +266,7 @@
log.debug("****1b. inside submitToGradingService, iter= " + iter);
HashSet adds = new HashSet();
HashSet removes = new HashSet();
-
+
// we go through all the answer collected from JSF form per each
// publsihedItem and
// work out which answer is an new addition and in cases like
@@ -325,7 +327,7 @@
tmpAnchorName = redrawAnchorName.toString();
}
ArrayList list = (ArrayList) invalidFINMap.get(itemId);
- ArrayList finArray = item.getFinArray();
+ List finArray = item.getFinArray();
Iterator iterFin = finArray.iterator();
while (iterFin.hasNext()) {
FinBean finBean = iterFin.next();
@@ -386,6 +388,7 @@
HashMap finMap = getFINMap(publishedAssessment);
HashMap calcQuestionMap = getCalcQuestionMap(publishedAssessment); // CALCULATED_QUESTION
HashMap mcmrMap = getMCMRMap(publishedAssessment);
+ HashMap emiMap = getEMIMap(publishedAssessment);
Set itemGradingSet = adata.getItemGradingSet();
log.debug("*** 2a. before removal & addition " + (new Date()));
if (itemGradingSet != null) {
@@ -416,7 +419,7 @@
+ adds.size());
HashSet updateItemGradingSet = getUpdateItemGradingSet(
- itemGradingSet, adds, fibMap, finMap, calcQuestionMap,mcmrMap, adata);
+ itemGradingSet, adds, fibMap, finMap, calcQuestionMap, mcmrMap, emiMap, adata);
adata.setItemGradingSet(updateItemGradingSet);
}
}
@@ -487,9 +490,14 @@
return publishedAssesmentService.prepareMCMRItemHash(publishedAssessment);
}
+ private HashMap getEMIMap(PublishedAssessmentIfc publishedAssessment) {
+ PublishedAssessmentService s = new PublishedAssessmentService();
+ return s.prepareEMIItemHash(publishedAssessment);
+ }
+
private HashSet getUpdateItemGradingSet(Set oldItemGradingSet,
Set newItemGradingSet, HashMap fibMap, HashMap finMap, HashMap calcQuestionMap, HashMap mcmrMap,
- AssessmentGradingData adata) {
+ HashMap emiMap, AssessmentGradingData adata) {
log.debug("Submitforgrading: oldItemGradingSet.size = "
+ oldItemGradingSet.size());
log.debug("Submitforgrading: newItemGradingSet.size = "
@@ -535,6 +543,7 @@
|| (newAnswerText != null && !newAnswerText
.equals(oldAnswerText))
|| fibMap.get(oldItem.getPublishedItemId()) != null
+ || emiMap.get(oldItem.getPublishedItemId()) != null
|| finMap.get(oldItem.getPublishedItemId())!=null
|| calcQuestionMap.get(oldItem.getPublishedItemId())!=null
|| mcmrMap.get(oldItem.getPublishedItemId()) != null) {
@@ -591,7 +600,7 @@
return adata;
}
- /*
+ /**
* This is specific to JSF - question for each type is layout differently in
* JSF and the answers submitted are being collected differently too. e.g.
* for each MC/Survey/MCMR, an itemgrading is associated with each choice.
@@ -601,7 +610,7 @@
*/
private void prepareItemGradingPerItem(ActionEvent ae, DeliveryBean delivery,
ItemContentsBean item, HashSet adds, HashSet removes) {
- ArrayList grading = item.getItemGradingDataArray();
+ List grading = item.getItemGradingDataArray();
int typeId = item.getItemData().getTypeId().intValue();
//no matter what kinds of type questions, if it marks as review, add it in.
@@ -761,6 +770,43 @@
}
}
break;
+ case 14: // Extended Matching Item
+ Long assessmentGradingId = delivery.getAssessmentGrading().getAssessmentGradingId();
+ Long publishedItemId = item.getItemData().getItemId();
+ log.debug("Updating answer set for EMI question: publishedItemId=" + publishedItemId + " grading.size()=" + grading.size() +
+ " item id=" + item.getItemData().getItemId() + " assessmentGradingId=" + assessmentGradingId);
+
+ for (int m = 0; m < grading.size(); m++) {
+ ItemGradingData itemgrading = (ItemGradingData) grading.get(m);
+ if (itemgrading.getItemGradingId() != null
+ && itemgrading.getItemGradingId().intValue() > 0) {
+ // old answer, check which one to keep, not keeping null answer
+ if (itemgrading.getPublishedAnswerId() != null) {
+ itemgrading.setAgentId(AgentFacade.getAgentString());
+ itemgrading.setSubmittedDate(new Date());
+ adds.add(itemgrading);
+ log.debug("adding answer: " + itemgrading.getItemGradingId());
+ } else {
+ removes.add(itemgrading);
+ log.debug("remove answer: " + itemgrading.getItemGradingId());
+ }
+ } else {
+ // new answer
+ if (itemgrading.getPublishedAnswerId() != null) {
+ // new addition not accepting any new answer with null for EMI
+ itemgrading.setAgentId(AgentFacade.getAgentString());
+ itemgrading.setSubmittedDate(new Date());
+ adds.add(itemgrading);
+ log.debug("adding new answer answer: " + itemgrading.getItemGradingId());
+ }
+ }
+
+ }
+
+ // We need to remove any answer (response) items in the storage that are not in the above lists
+ removes.addAll(identifyOrphanedEMIAnswers(grading, publishedItemId, assessmentGradingId));
+
+ break;
case 6: // File Upload
case 7: // Audio
handleMarkForReview(grading, adds);
@@ -828,7 +874,36 @@
}
}
- private void handleMarkForReview(ArrayList grading, HashSet adds){
+ /**
+ * Identify the items in an EMI Answer that are orphaned
+ * @param grading
+ * @return a list of ItemGradings to be removed
+ */
+ private Collection identifyOrphanedEMIAnswers(List grading, Long publishedItemId, Long assessmentGradingId) {
+ Set ret = new HashSet();
+
+ List itemsInGrading = new ArrayList();
+ for (int i = 0; i < grading.size(); i++) {
+ ItemGradingData data = grading.get(i);
+ itemsInGrading.add(data.getItemGradingId());
+ }
+
+ GradingService gradingService = new GradingService();
+ List data = gradingService.getAllItemGradingDataForItemInGrading(assessmentGradingId, publishedItemId);
+ log.debug("got " + data.size() + " answers from storage");
+ log.debug("got " + grading.size() + " items in the grading object");
+ for (int i = 0; i < data.size(); i++) {
+ ItemGradingData item = data.get(i);
+ if (!itemsInGrading.contains(item.getItemGradingId())) {
+ log.debug("we will remove " + item.getItemGradingId());
+ ret.add(item);
+ }
+ }
+
+ return ret;
+ }
+
+ private void handleMarkForReview(List grading, HashSet adds){
for (int m = 0; m < grading.size(); m++) {
ItemGradingData itemgrading = grading.get(m);
if (itemgrading.getItemGradingId() != null
@@ -868,7 +943,7 @@
private LRS_Result getLRS_Result(AssessmentGradingData gradingData, PublishedAssessmentFacade publishedAssessment) {
double score = gradingData.getFinalScore();
- LRS_Result result = new LRS_Result(new Float(score), new Float(0.0), new Float(publishedAssessment.getTotalScore()), null);
+ LRS_Result result = new LRS_Result(new Double(score), new Double(0.0), new Double(publishedAssessment.getTotalScore()), null);
result.setCompletion(true);
return result;
}
Index: samigo-app/src/java/org/sakaiproject/tool/assessment/ui/listener/evaluation/HistogramListener.java
===================================================================
--- samigo-app/src/java/org/sakaiproject/tool/assessment/ui/listener/evaluation/HistogramListener.java (revision 133459)
+++ samigo-app/src/java/org/sakaiproject/tool/assessment/ui/listener/evaluation/HistogramListener.java (working copy)
@@ -5,8 +5,8 @@
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Collection;
import java.util.Collections;
+import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
@@ -13,6 +13,7 @@
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.TreeSet;
import javax.faces.component.html.HtmlSelectOneMenu;
import javax.faces.context.FacesContext;
@@ -27,6 +28,7 @@
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.sakaiproject.tool.assessment.api.SamigoApiFactory;
+import org.sakaiproject.tool.assessment.data.dao.assessment.PublishedSectionData;
import org.sakaiproject.tool.assessment.data.dao.grading.AssessmentGradingComparatorByScoreAndUniqueIdentifier;
import org.sakaiproject.tool.assessment.data.dao.grading.AssessmentGradingData;
import org.sakaiproject.tool.assessment.data.dao.grading.ItemGradingData;
@@ -36,6 +38,7 @@
import org.sakaiproject.tool.assessment.data.ifc.assessment.ItemTextIfc;
import org.sakaiproject.tool.assessment.data.ifc.assessment.PublishedAssessmentIfc;
import org.sakaiproject.tool.assessment.data.ifc.assessment.SectionDataIfc;
+import org.sakaiproject.tool.assessment.data.ifc.shared.TypeIfc;
import org.sakaiproject.tool.assessment.facade.AgentFacade;
import org.sakaiproject.tool.assessment.services.GradingService;
import org.sakaiproject.tool.assessment.services.assessment.PublishedAssessmentService;
@@ -162,8 +165,6 @@
}
/**
- * modified by gopalrc Nov 2007
- *
* Calculate the detailed statistics
*
* This will populate the HistogramScoresBean with the data associated with the
@@ -190,11 +191,10 @@
log.error("SAK-16437 happens!! publishedId = " + publishedId + ", agentId = " + AgentFacade.getAgentString());
}
- ResourceLoader rb = new ResourceLoader("org.sakaiproject.tool.assessment.bundle.AuthorMessages");
+ ResourceLoader rb = new ResourceLoader("org.sakaiproject.tool.assessment.bundle.EvaluationMessages");
ResourceLoader rbEval = new ResourceLoader("org.sakaiproject.tool.assessment.bundle.EvaluationMessages");
String assessmentName = "";
- // gopalrc Dec 2007
histogramScores.clearLowerQuartileStudents();
histogramScores.clearUpperQuartileStudents();
@@ -216,7 +216,7 @@
for(AssessmentGradingData agd: allscores){
agd.setItemGradingSet(delegate.getItemGradingSet(String.valueOf(agd.getAssessmentGradingId())));
}
- if (allscores.size() == 0) {
+ if (allscores.isEmpty()) {
// Similar case in Bug 1537, but clicking Statistics link instead of assignment title.
// Therefore, redirect the the same page.
delivery.setOutcome("reviewAssessmentError");
@@ -259,14 +259,10 @@
return false;
}
- /*
- * gopalrc - moved up from (1)
- */
// here scores contain AssessmentGradingData
Map assessmentMap = getAssessmentStatisticsMap(scores);
/*
- * gopalrc Nov 2007
* find students in upper and lower quartiles
* of assessment scores
*/
@@ -276,9 +272,7 @@
int numSubmissions = scores.size();
//int percent27 = ((numSubmissions*10*27/100)+5)/10; // rounded
int percent27 = numSubmissions*27/100; // rounded down
- if (percent27 == 0) percent27 = 1; // gopalrc - check this - only relevant for very small samples
- //double q1 = Double.valueOf((String) assessmentMap.get("q1")).doubleValue();
- //double q3 = Double.valueOf((String) assessmentMap.get("q3")).doubleValue();
+ if (percent27 == 0) percent27 = 1;
for (int i=0; i parts = pub.getSectionArraySorted();
+ histogramScores.setAssesmentParts((List)parts);
ArrayList info = new ArrayList();
Iterator partsIter = parts.iterator();
int secseq = 1;
@@ -389,21 +383,21 @@
}
if (section.getSequence() == null)
section.setSequence(Integer.valueOf(secseq++));
- String title = rb.getString("p") + " "
+ String title = rb.getString("part") + " "
+ section.getSequence().toString();
- title += ", " + rb.getString("q") + " ";
- ArrayList itemset = section.getItemArraySortedForGrading();
+ title += ", " + rb.getString("question") + " ";
+ List itemset = section.getItemArraySortedForGrading();
int seq = 1;
- Iterator itemsIter = itemset.iterator();
+ Iterator itemsIter = itemset.iterator();
// Iterate through the assessment questions (items)
while (itemsIter.hasNext()) {
HistogramQuestionScoresBean questionScores = new HistogramQuestionScoresBean();
- questionScores.setNumberOfParts(parts.size()); // gopalrc
+ questionScores.setNumberOfParts(parts.size());
//if this part is a randompart , then set randompart = true
questionScores.setRandomType(isRandompart);
questionScores.setPoolName(poolName);
- ItemDataIfc item = (ItemDataIfc) itemsIter.next();
+ ItemDataIfc item = itemsIter.next();
//String type = delegate.getTextForId(item.getTypeId());
String type = getType(item.getTypeId().intValue());
@@ -429,17 +423,23 @@
questionScores.setItemId(item.getItemId());
questionScores.setTitle(title + item.getSequence().toString()
+ " (" + type + ")");
- questionScores.setQuestionText(item.getText());
+
+ if (item.getTypeId().equals(TypeIfc.EXTENDED_MATCHING_ITEMS)) { // emi question
+ questionScores.setQuestionText(item.getLeadInText());
+ }
+ else {
+ questionScores.setQuestionText(item.getText());
+ }
+
questionScores.setQuestionType(item.getTypeId().toString());
//totalpossible = totalpossible + item.getScore().doubleValue();
//ArrayList responses = null;
+ //for each question (item) in the published assessment's current part/section
determineResults(pub, questionScores, (ArrayList) itemScores
.get(item.getItemId()));
questionScores.setTotalScore(item.getScore().toString());
-
- // below - gopalrc Nov 2007
questionScores.setN(""+numSubmissions);
questionScores.setItemId(item.getItemId());
Set studentsWithAllCorrect = questionScores.getStudentsWithAllCorrect();
@@ -519,9 +519,7 @@
questionScores.setDiscrimination(rbEval.getString("na"));
}
}
- // above - gopalrc Nov 2007
-
info.add(questionScores);
} // end-while - items
@@ -532,39 +530,60 @@
histogramScores.setInfo(info);
histogramScores.setRandomType(hasRandompart);
- // below - gopalrc Dec 2007
int maxNumOfAnswers = 0;
- ArrayList detailedStatistics = new ArrayList();
+ List detailedStatistics = new ArrayList();
Iterator infoIter = info.iterator();
while (infoIter.hasNext()) {
HistogramQuestionScoresBean questionScores = (HistogramQuestionScoresBean)infoIter.next();
- if (questionScores.getQuestionType().equals("1")
- || questionScores.getQuestionType().equals("2")
- || questionScores.getQuestionType().equals("3")
- || questionScores.getQuestionType().equals("4")
- || questionScores.getQuestionType().equals("8")
- || questionScores.getQuestionType().equals("9")
- || questionScores.getQuestionType().equals("11")
- || questionScores.getQuestionType().equals("12")
- || questionScores.getQuestionType().equals("15")
+ if (questionScores.getQuestionType().equals(TypeIfc.MULTIPLE_CHOICE.toString())
+ || questionScores.getQuestionType().equals(TypeIfc.MULTIPLE_CORRECT.toString())
+ || questionScores.getQuestionType().equals(TypeIfc.MULTIPLE_CHOICE_SURVEY.toString())
+ || questionScores.getQuestionType().equals(TypeIfc.TRUE_FALSE.toString())
+ || questionScores.getQuestionType().equals(TypeIfc.FILL_IN_BLANK.toString())
+ || questionScores.getQuestionType().equals(TypeIfc.MATCHING.toString())
+ || questionScores.getQuestionType().equals(TypeIfc.FILL_IN_NUMERIC.toString())
+ || questionScores.getQuestionType().equals(TypeIfc.MULTIPLE_CORRECT_SINGLE_SELECTION.toString())
+ || questionScores.getQuestionType().equals(TypeIfc.CALCULATED_QUESTION.toString())
) {
+ questionScores.setShowIndividualAnswersInDetailedStatistics(true);
detailedStatistics.add(questionScores);
if (questionScores.getHistogramBars() != null) {
maxNumOfAnswers = questionScores.getHistogramBars().length >maxNumOfAnswers ? questionScores.getHistogramBars().length : maxNumOfAnswers;
}
}
+ //i.e. for EMI questions we add detailed stats for the whole
+ //question as well as for the sub-questions
+ if (questionScores.getQuestionType().equals(TypeIfc.EXTENDED_MATCHING_ITEMS.toString())
+ ) {
+ questionScores.setShowIndividualAnswersInDetailedStatistics(false);
+ detailedStatistics.addAll(questionScores.getInfo());
+
+ Iterator subInfoIter = questionScores.getInfo().iterator();
+ while (subInfoIter.hasNext()) {
+ HistogramQuestionScoresBean subQuestionScores = (HistogramQuestionScoresBean) subInfoIter.next();
+ if (subQuestionScores.getHistogramBars() != null) {
+ subQuestionScores.setN(questionScores.getN());
+ maxNumOfAnswers = subQuestionScores.getHistogramBars().length >maxNumOfAnswers ? subQuestionScores.getHistogramBars().length : maxNumOfAnswers;
+ }
+ }
+/*
+ Object numberOfStudentsWithZeroAnswers = numberOfStudentsWithZeroAnswersForQuestion.get(questionScores.getItemId());
+ if (numberOfStudentsWithZeroAnswers == null) {
+ questionScores.setNumberOfStudentsWithZeroAnswers(0);
+ }
+ else {
+ questionScores.setNumberOfStudentsWithZeroAnswers( ((Integer) numberOfStudentsWithZeroAnswersForQuestion.get(questionScores.getItemId())).intValue() );
+ }
+*/
+ }
+
+
}
+ //VULA-1948: sort the detailedStatistics list by Question Label
+ sortQuestionScoresByLabel(detailedStatistics);
histogramScores.setDetailedStatistics(detailedStatistics);
histogramScores.setMaxNumberOfAnswers(maxNumOfAnswers);
- // above - gopalrc Dec 2007
-
- /*
- * gopalrc - moved up (1)
- // here scores contain AssessmentGradingData
- Map assessmentMap = getAssessmentStatisticsMap(scores);
- */
-
// test to see if it gets back empty map
if (assessmentMap.isEmpty()) {
histogramScores.setNumResponses(0);
@@ -642,6 +661,14 @@
return true;
}
+ /**
+ * For each question (item) in the published assessment's current part/section
+ * determine the results by calculating statistics for whole question or
+ * individual answers depending on the question type
+ * @param pub
+ * @param qbean
+ * @param itemScores
+ */
private void determineResults(PublishedAssessmentIfc pub, HistogramQuestionScoresBean qbean,
ArrayList itemScores)
{
@@ -665,26 +692,35 @@
qbean.setNumResponses(responses);
qbean.setNumberOfStudentsWithZeroAnswers(numStudentsWithZeroAnswers);
- if (qbean.getQuestionType().equals("1") || // mcsc
- qbean.getQuestionType().equals("2") || // mcmcms
- qbean.getQuestionType().equals("12") || // mcmcss
- qbean.getQuestionType().equals("3") || // mc survey
- qbean.getQuestionType().equals("4") || // tf
- qbean.getQuestionType().equals("9") || // matching
- qbean.getQuestionType().equals("8") || // Fill in the blank
- qbean.getQuestionType().equals("11") || // Numeric Response
- qbean.getQuestionType().equals("15") || // CALCULATED_QUESTION
- qbean.getQuestionType().equals("13")) // matrix survey
+ if (qbean.getQuestionType().equals(TypeIfc.MULTIPLE_CHOICE.toString()) || // mcsc
+ qbean.getQuestionType().equals(TypeIfc.MULTIPLE_CORRECT.toString()) || // mcmcms
+ qbean.getQuestionType().equals(TypeIfc.MULTIPLE_CORRECT_SINGLE_SELECTION.toString()) || // mcmcss
+ qbean.getQuestionType().equals(TypeIfc.MULTIPLE_CHOICE_SURVEY.toString()) || // mc survey
+ qbean.getQuestionType().equals(TypeIfc.TRUE_FALSE.toString()) || // tf
+ qbean.getQuestionType().equals(TypeIfc.MATCHING.toString()) || // matching
+ qbean.getQuestionType().equals(TypeIfc.FILL_IN_BLANK.toString()) || // Fill in the blank
+ qbean.getQuestionType().equals(TypeIfc.EXTENDED_MATCHING_ITEMS.toString()) || // Extended Matching Items
+ qbean.getQuestionType().equals(TypeIfc.FILL_IN_NUMERIC.toString()) || // Numeric Response
+ qbean.getQuestionType().equals(TypeIfc.CALCULATED_QUESTION.toString()) || // CALCULATED_QUESTION
+ qbean.getQuestionType().equals(TypeIfc.MATRIX_CHOICES_SURVEY.toString())) // matrix survey
doAnswerStatistics(pub, qbean, itemScores);
- if (qbean.getQuestionType().equals("5") || // essay
- qbean.getQuestionType().equals("6") || // file upload
- qbean.getQuestionType().equals("7")) // audio recording
+ if (qbean.getQuestionType().equals(TypeIfc.ESSAY_QUESTION.toString()) || // essay
+ qbean.getQuestionType().equals(TypeIfc.FILE_UPLOAD.toString()) || // file upload
+ qbean.getQuestionType().equals(TypeIfc.AUDIO_RECORDING.toString())) // audio recording
doScoreStatistics(qbean, itemScores);
}
+ /**
+ * For each question where statistics are required for seperate answers,
+ * this method calculates the answer statistics by calling a different
+ * getXXXScores() method for each question type.
+ * @param pub
+ * @param qbean
+ * @param scores
+ */
private void doAnswerStatistics(PublishedAssessmentIfc pub, HistogramQuestionScoresBean qbean,
- ArrayList scores)
+ List scores)
{
// Don't return here. This will cause questions to be displayed inconsistently on the stats page
@@ -704,40 +740,534 @@
//int numAnswers = 0;
ItemDataIfc item = (ItemDataIfc) publishedItemHash.get(qbean.getItemId());
- ArrayList text = item.getItemTextArraySorted();
- ArrayList answers = null;
- if (!qbean.getQuestionType().equals("9")) // matching
+ List text = item.getItemTextArraySorted();
+ List answers = null;
+
+ //keys number of correct answers required by sub-question (ItemText)
+ HashMap emiRequiredCorrectAnswersCount = null;
+ if (qbean.getQuestionType().equals(TypeIfc.EXTENDED_MATCHING_ITEMS.toString())) { //EMI
+ emiRequiredCorrectAnswersCount = new HashMap();
+ answers = new ArrayList();
+ for (int i=0; i0) {
+ requireAllCorrectAnswers = false;
+ numCorrectAnswersRequired = iText.getRequiredOptionsCount().intValue();
+ }
+ if (iText.getAnswerArraySorted() == null) continue;
+ Iterator ansIter = iText.getAnswerArraySorted().iterator();
+ while (ansIter.hasNext()) {
+ AnswerIfc answer = (AnswerIfc)ansIter.next();
+ answers.add(answer);
+ if (requireAllCorrectAnswers && answer.getIsCorrect()) {
+ numCorrectAnswersRequired++;
+ }
+ }
+ emiRequiredCorrectAnswersCount.put(iText.getId(), Integer.valueOf(numCorrectAnswersRequired));
+ }
+ }
+ }
+ else if (!qbean.getQuestionType().equals(TypeIfc.MATCHING.toString())) // matching
{
ItemTextIfc firstText = (ItemTextIfc) publishedItemTextHash.get(((ItemTextIfc) text.toArray()[0]).getId());
answers = firstText.getAnswerArraySorted();
}
- if (qbean.getQuestionType().equals("1")) // mcsc
+ if (qbean.getQuestionType().equals(TypeIfc.MULTIPLE_CHOICE.toString())) // mcsc
getTFMCScores(publishedAnswerHash, scores, qbean, answers);
- else if (qbean.getQuestionType().equals("2")) // mcmc
+ else if (qbean.getQuestionType().equals(TypeIfc.MULTIPLE_CORRECT.toString())) // mcmc
getFIBMCMCScores(publishedItemHash, publishedAnswerHash, scores, qbean, answers);
- else if (qbean.getQuestionType().equals("12"))
+ else if (qbean.getQuestionType().equals(TypeIfc.MULTIPLE_CORRECT_SINGLE_SELECTION.toString()))
getTFMCScores(publishedAnswerHash, scores, qbean, answers);
- else if (qbean.getQuestionType().equals("3"))
+ else if (qbean.getQuestionType().equals(TypeIfc.MULTIPLE_CHOICE_SURVEY.toString()))
getTFMCScores(publishedAnswerHash, scores, qbean, answers);
- else if (qbean.getQuestionType().equals("4")) // tf
+ else if (qbean.getQuestionType().equals(TypeIfc.TRUE_FALSE.toString())) // tf
getTFMCScores(publishedAnswerHash, scores, qbean, answers);
- else if ((qbean.getQuestionType().equals("8"))||(qbean.getQuestionType().equals("11")) )
+ else if ((qbean.getQuestionType().equals(TypeIfc.FILL_IN_BLANK.toString()))||(qbean.getQuestionType().equals(TypeIfc.FILL_IN_NUMERIC.toString())) )
getFIBMCMCScores(publishedItemHash, publishedAnswerHash, scores, qbean, answers);
//else if (qbean.getQuestionType().equals("11"))
// getFINMCMCScores(publishedItemHash, publishedAnswerHash, scores, qbean, answers);
- else if (qbean.getQuestionType().equals("9"))
+ else if (qbean.getQuestionType().equals(TypeIfc.MATCHING.toString()))
getMatchingScores(publishedItemTextHash, publishedAnswerHash, scores, qbean, text);
- else if (qbean.getQuestionType().equals("15")) // CALCULATED_QUESTION
+ else if (qbean.getQuestionType().equals(TypeIfc.EXTENDED_MATCHING_ITEMS.toString()))
+ getEMIScores(publishedItemHash, publishedAnswerHash, emiRequiredCorrectAnswersCount, scores, qbean, answers);
+ else if (qbean.getQuestionType().equals(TypeIfc.MATRIX_CHOICES_SURVEY.toString())) // matrix survey question
+ getMatrixSurveyScores(publishedItemTextHash, publishedAnswerHash, scores, qbean, text);
+ else if (qbean.getQuestionType().equals(TypeIfc.CALCULATED_QUESTION.toString())) // CALCULATED_QUESTION
getCalculatedQuestionScores(scores, qbean, text);
- else if (qbean.getQuestionType().equals("13")) // matrix survey question
- getMatrixSurveyScores(publishedItemTextHash, publishedAnswerHash, scores, qbean, text);
}
+ /**
+ * calculates statistics for EMI questions
+ */
+ private void getEMIScores(HashMap publishedItemHash,
+ HashMap publishedAnswerHash, HashMap emiRequiredCorrectAnswersCount, List scores,
+ HistogramQuestionScoresBean qbean, List answers) {
+ ResourceLoader rb = new ResourceLoader(
+ "org.sakaiproject.tool.assessment.bundle.EvaluationMessages");
+
+ // Answers keyed by answer-id
+ HashMap answersById = new HashMap();
+
+ //keys the number of student responses selecting a particular answer
+ //by the Answer ID
+ HashMap results = new HashMap();
+
+ //keys Answer-IDs by subQuestion/ItemTextSequence-answerSequence (concatenated)
+ HashMap sequenceMap = new HashMap();
+
+ //list of answers for each sub-question/ItemText
+ ArrayList subQuestionAnswers = null;
+
+ //Map which keys above lists by the sub-question/ItemText sequence
+ HashMap subQuestionAnswerMap = new HashMap();
+
+ //Create a Map where each Sub-Question's Answers-ArrayList
+ //is keyed by sub-question and answer sequence
+ Iterator iter = answers.iterator();
+ while (iter.hasNext()) {
+ AnswerIfc answer = (AnswerIfc) iter.next();
+ answersById.put(answer.getId(), answer);
+ results.put(answer.getId(), Integer.valueOf(0));
+ sequenceMap.put(answer.getItemText().getSequence() + "-" + answer.getSequence(), answer.getId());
+ Long subQuestionSequence = answer.getItemText().getSequence();
+ Object subSeqAns = subQuestionAnswerMap.get(subQuestionSequence);
+ if (subSeqAns == null) {
+ subQuestionAnswers = new ArrayList();
+ subQuestionAnswerMap.put(subQuestionSequence, subQuestionAnswers);
+ }
+ else {
+ subQuestionAnswers = (ArrayList) subSeqAns;
+ }
+ subQuestionAnswers.add(answer);
+ }
+ //Iterate through the student answers (ItemGradingData)
+ iter = scores.iterator();
+ //Create a map that keys all the responses/answers (ItemGradingData)
+ //for this question from a specific student (assessment)
+ //by the id of that assessment (AssessmentGradingData)
+ HashMap responsesPerStudentPerQuestionMap = new HashMap();
+ //and do the same for seperate sub-questions
+ HashMap responsesPerStudentPerSubQuestionMap = new HashMap();
+ while (iter.hasNext()) {
+ ItemGradingData data = (ItemGradingData) iter.next();
+ //Get the published answer that corresponds to the student's reponse
+ AnswerIfc answer = (AnswerIfc) publishedAnswerHash.get(data
+ .getPublishedAnswerId());
+ //This should always be the case as only valid responses
+ //from the list of available options are allowed
+ if (answer != null) {
+ // log.info("Gopal: looking for " + answer.getId());
+ // found a response
+ Integer num = null;
+ // num is a counter for the number of responses that select this published answer
+ try {
+ // we found a response, now get existing count from the
+ // hashmap
+ num = (Integer) results.get(answer.getId());
+
+ } catch (Exception e) {
+ log.warn("No results for " + answer.getId());
+ }
+
+ //If this published answer has not been selected before
+ if (num == null)
+ num = Integer.valueOf(0);
+
+ //Now create a map that keys all the responses (ItemGradingData)
+ //for this question from a specific student (or assessment)
+ //by the id of that assessment (AssessmentGradingData)
+ ArrayList studentResponseList = (ArrayList) responsesPerStudentPerQuestionMap
+ .get(data.getAssessmentGradingId());
+ if (studentResponseList == null) {
+ studentResponseList = new ArrayList();
+ }
+ studentResponseList.add(data);
+ responsesPerStudentPerQuestionMap.put(data.getAssessmentGradingId(),
+ studentResponseList);
+
+ //Do the same for the sub-questions
+ String key = data.getAssessmentGradingId() + "-" + answer.getItemText().getId();
+ ArrayList studentResponseListForSubQuestion = (ArrayList) responsesPerStudentPerSubQuestionMap
+ .get(key);
+ if (studentResponseListForSubQuestion == null) {
+ studentResponseListForSubQuestion = new ArrayList();
+ }
+ studentResponseListForSubQuestion.add(data);
+ responsesPerStudentPerSubQuestionMap.put(key, studentResponseListForSubQuestion);
+
+
+ results.put(answer.getId(), Integer.valueOf(
+ num.intValue() + 1));
+ }
+ }
+
+ HistogramBarBean[] bars = new HistogramBarBean[results.keySet().size()];
+ int[] numarray = new int[results.keySet().size()];
+
+ //List of "ItemText.sequence-Answer.sequence"
+ List sequenceList = new ArrayList();
+ iter = answers.iterator();
+ while (iter.hasNext()) {
+ AnswerIfc answer = (AnswerIfc) iter.next();
+ sequenceList.add(answer.getItemText().getSequence() + "-" + answer.getSequence());
+ }
+ // sort the sequence
+ Collections.sort(sequenceList, new Comparator(){
+
+ public int compare(String o1, String o2) {
+ Integer a1 = Integer.valueOf(o1.substring(0, o1.indexOf("-")));
+ Integer a2 = Integer.valueOf(o2.substring(0, o1.indexOf("-")));
+ int val = a1.compareTo(a2);
+ if(val != 0){
+ return val;
+ }
+ a1 = Integer.valueOf(o1.substring(o1.indexOf("-")+1));
+ a2 = Integer.valueOf(o2.substring(o1.indexOf("-")+1));
+ return a1.compareTo(a2);
+ }
+ });
+ // iter = results.keySet().iterator();
+ iter = sequenceList.iterator();
+ int i = 0;
+ int responses = 0;
+ int correctresponses = 0;
+ while (iter.hasNext()) {
+ String sequenceId = (String) iter.next();
+ Long answerId = (Long) sequenceMap.get(sequenceId);
+ AnswerIfc answer = (AnswerIfc) answersById.get(answerId);
+ int num = ((Integer) results.get(answerId)).intValue();
+ numarray[i] = num;
+ bars[i] = new HistogramBarBean();
+ if (answer != null) {
+ bars[i].setSubQuestionSequence(answer.getItemText().getSequence());
+ if (answer.getItem().getIsAnswerOptionsSimple()) {
+ bars[i].setLabel(answer.getItemText().getSequence() + ". " + answer.getLabel() + " " + answer.getText());
+ }
+ else { //rich text or attachment options
+ bars[i].setLabel(answer.getItemText().getSequence() + ". " + answer.getLabel());
+ }
+
+ if (answer.getLabel().equals("A")) {
+ String title = rb.getString("item") + " " + answer.getItemText().getSequence();
+ String text = answer.getItemText().getText();
+ if (text != null && !text.equals(null)) {
+ title += " : " + text;
+ bars[i].setTitle(title);
+ }
+ }
+ bars[i].setIsCorrect(answer.getIsCorrect());
+ }
+
+ bars[i].setNumStudentsText(num + " " + rb.getString("responses"));
+ bars[i].setNumStudents(num);
+ i++;
+ }// end while
+
+ responses = responsesPerStudentPerQuestionMap.size();
+
+ //Determine the number of students with all correct responses for the whole question
+ for (Iterator it = responsesPerStudentPerQuestionMap.entrySet().iterator(); it.hasNext();) {
+ Map.Entry entry = (Map.Entry) it.next();
+ ArrayList resultsForOneStudent = (ArrayList) entry.getValue();
+
+ boolean hasIncorrect = false;
+ Iterator listiter = resultsForOneStudent.iterator();
+
+ // iterate through the results for one student
+ // for this question (qbean)
+ while (listiter.hasNext()) {
+ ItemGradingData item = (ItemGradingData) listiter.next();
+
+ // only answered choices are created in the
+ // ItemGradingData_T, so we need to check
+ // if # of checkboxes the student checked is == the number
+ // of correct answers
+ // otherwise if a student only checked one of the multiple
+ // correct answers,
+ // it would count as a correct response
+ try {
+ int corranswers = 0;
+ Iterator answeriter = answers.iterator();
+ while (answeriter.hasNext()) {
+ AnswerIfc answerchoice = (AnswerIfc) answeriter
+ .next();
+ if (answerchoice.getIsCorrect().booleanValue()) {
+ corranswers++;
+ }
+ }
+ if (resultsForOneStudent.size() != corranswers) {
+ hasIncorrect = true;
+ break;
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new RuntimeException(
+ "error calculating emi question.");
+ }
+
+ // now check each answer
+ AnswerIfc answer = (AnswerIfc) publishedAnswerHash.get(item
+ .getPublishedAnswerId());
+ if (answer != null
+ && (answer.getIsCorrect() == null || (!answer
+ .getIsCorrect().booleanValue()))) {
+ hasIncorrect = true;
+ break;
+ }
+ }
+
+ if (!hasIncorrect) {
+ correctresponses = correctresponses + 1;
+ qbean.addStudentWithAllCorrect(((ItemGradingData)resultsForOneStudent.get(0)).getAgentId());
+ }
+ qbean.addStudentResponded(((ItemGradingData)resultsForOneStudent.get(0)).getAgentId());
+ } // end for - number of students with all correct responses for the whole question
+
+ // NEW
+ int[] heights = calColumnHeight(numarray, responses);
+ // int[] heights = calColumnHeight(numarray);
+ for (i = 0; i < bars.length; i++)
+ {
+ try
+ {
+ bars[i].setColumnHeight(Integer.toString(heights[i]));
+ }
+ catch(NullPointerException npe)
+ {
+ log.warn("null column height " + npe);
+ }
+ }
+
+ qbean.setHistogramBars(bars);
+ qbean.setNumResponses(responses);
+ if (responses > 0)
+ qbean.setPercentCorrect(Integer.toString((int) (((double) correctresponses / (double) responses) * 100)));
+
+ HashMap numStudentsWithAllCorrectPerSubQuestion = new HashMap();
+ HashMap studentsWithAllCorrectPerSubQuestion = new HashMap();
+ HashMap studentsRespondedPerSubQuestion = new HashMap();
+ Iterator studentSubquestionResponseKeyIter = responsesPerStudentPerSubQuestionMap.keySet().iterator();
+ while (studentSubquestionResponseKeyIter.hasNext()) {
+ String key = (String)studentSubquestionResponseKeyIter.next();
+ ArrayList studentResponseListForSubQuestion = (ArrayList) responsesPerStudentPerSubQuestionMap
+ .get(key);
+ if (studentResponseListForSubQuestion != null && !studentResponseListForSubQuestion.isEmpty()) {
+ ItemGradingData response1 = (ItemGradingData)studentResponseListForSubQuestion.get(0);
+ Long subQuestionId = ((AnswerIfc)publishedAnswerHash.get(response1.getPublishedAnswerId())).getItemText().getId();
+
+ Set studentsResponded = (Set)studentsRespondedPerSubQuestion.get(subQuestionId);
+ if (studentsResponded == null) studentsResponded = new TreeSet();
+ studentsResponded.add(response1.getAgentId());
+ studentsRespondedPerSubQuestion.put(subQuestionId, studentsResponded);
+
+ boolean hasIncorrect = false;
+ //numCorrectSubQuestionAnswers = (Integer) correctAnswersPerSubQuestion.get(subQuestionId);
+ Integer numCorrectSubQuestionAnswers = (Integer) emiRequiredCorrectAnswersCount.get(subQuestionId);
+
+ if (studentResponseListForSubQuestion.size() < numCorrectSubQuestionAnswers.intValue()) {
+ hasIncorrect = true;
+ continue;
+ }
+ //now check each answer
+ Iterator studentResponseIter = studentResponseListForSubQuestion.iterator();
+ while (studentResponseIter.hasNext()) {
+ ItemGradingData response = (ItemGradingData)studentResponseIter.next();
+ AnswerIfc answer = (AnswerIfc) publishedAnswerHash.get(response
+ .getPublishedAnswerId());
+ if (answer != null
+ && (answer.getIsCorrect() == null || (!answer
+ .getIsCorrect().booleanValue()))) {
+ hasIncorrect = true;
+ break;
+ }
+ }
+ if (hasIncorrect) continue;
+ Integer numWithAllCorrect = (Integer)numStudentsWithAllCorrectPerSubQuestion.get(subQuestionId);
+ if (numWithAllCorrect == null) {
+ numWithAllCorrect = Integer.valueOf(0);
+ }
+ numStudentsWithAllCorrectPerSubQuestion.put(subQuestionId, Integer.valueOf(numWithAllCorrect.intValue() + 1));
+
+ Set studentsWithAllCorrect = (Set)studentsWithAllCorrectPerSubQuestion.get(subQuestionId);
+ if (studentsWithAllCorrect == null) studentsWithAllCorrect = new TreeSet();
+ studentsWithAllCorrect.add(response1.getAgentId());
+ studentsWithAllCorrectPerSubQuestion.put(subQuestionId, studentsWithAllCorrect);
+
+ }
+
+ }
+
+ //Map ItemText sequences to Ids
+ HashMap itemTextSequenceIdMap = new HashMap();
+ Iterator answersIter = answers.iterator();
+ while (answersIter.hasNext()) {
+ AnswerIfc answer = (AnswerIfc)answersIter.next();
+ itemTextSequenceIdMap.put(answer.getItemText().getSequence(), answer.getItemText().getId());
+ }
+
+ //Now select the the bars for each sub-questions
+ Set subQuestionKeySet = subQuestionAnswerMap.keySet();
+ ArrayList subQuestionKeyList = new ArrayList();
+ subQuestionKeyList.addAll(subQuestionKeySet);
+ Collections.sort(subQuestionKeyList);
+ Iterator subQuestionIter = subQuestionKeyList.iterator();
+ ArrayList subQuestionInfo = new ArrayList(); //List of sub-question HistogramQuestionScoresBeans - for EMI sub-questions
+ // Iterate through the assessment questions (items)
+ while (subQuestionIter.hasNext()) {
+ Long subQuestionSequence = (Long)subQuestionIter.next();
+
+ //While qbean is the HistogramQuestionScoresBean for the entire question
+ //questionScores are the HistogramQuestionScoresBeans for each sub-question
+ HistogramQuestionScoresBean questionScores = new HistogramQuestionScoresBean();
+ questionScores.setSubQuestionSequence(subQuestionSequence);
+
+ // Determine the number of bars (possible answers) for this sub-question
+ int numBars = 0;
+ for (int j=0; j 0) {
+ Integer numWithAllCorrect = (Integer)numStudentsWithAllCorrectPerSubQuestion.get(subQuestionId);
+ if (numWithAllCorrect != null) correctresponses = numWithAllCorrect.intValue();
+ questionScores.setPercentCorrect(Integer.toString((int) (((double) correctresponses / (double) responses) * 100)));
+ }
+ Set studentsWithAllCorrect = (Set)studentsWithAllCorrectPerSubQuestion.get(subQuestionId);
+ questionScores.setStudentsWithAllCorrect(studentsWithAllCorrect);
+
+ Set studentsResponded = (Set)studentsRespondedPerSubQuestion.get(subQuestionId);
+ questionScores.setStudentsResponded(studentsResponded);
+
+ subQuestionAnswers = (ArrayList) subQuestionAnswerMap.get(subQuestionSequence);
+ Iterator answerIter = subQuestionAnswers.iterator();
+ Double totalScore = new Double(0);
+ while (answerIter.hasNext()) {
+ AnswerIfc subQuestionAnswer = (AnswerIfc) answerIter.next();
+ totalScore += (subQuestionAnswer==null||subQuestionAnswer.getScore()==null?0.0:subQuestionAnswer.getScore());
+
+ }
+ questionScores.setTotalScore(totalScore.toString());
+
+ HistogramScoresBean histogramScores = (HistogramScoresBean) ContextUtil.lookupBean(
+ "histogramScores");
+
+ Iterator keys = responsesPerStudentPerSubQuestionMap.keySet().iterator();
+ int numSubmissions = 0;
+ while (keys.hasNext()) {
+ String assessmentAndSubquestionId = (String)keys.next();
+ if (assessmentAndSubquestionId.endsWith("-"+subQuestionId)) numSubmissions++;
+ }
+ int percent27 = numSubmissions*27/100; // rounded down
+ if (percent27 == 0) percent27 = 1;
+
+ studentsWithAllCorrect = questionScores.getStudentsWithAllCorrect();
+ studentsResponded = questionScores.getStudentsResponded();
+ if (studentsWithAllCorrect == null || studentsResponded == null ||
+ studentsWithAllCorrect.isEmpty() || studentsResponded.isEmpty()) {
+ questionScores.setPercentCorrectFromUpperQuartileStudents("0");
+ questionScores.setPercentCorrectFromLowerQuartileStudents("0");
+ questionScores.setDiscrimination("0.0");
+ }
+ else {
+ int numStudentsWithAllCorrectFromUpperQuartile = 0;
+ int numStudentsWithAllCorrectFromLowerQuartile = 0;
+ Iterator studentsIter = studentsWithAllCorrect.iterator();
+ while (studentsIter.hasNext()) {
+ String agentId = (String) studentsIter.next();
+ if (histogramScores.isUpperQuartileStudent(agentId)) {
+ numStudentsWithAllCorrectFromUpperQuartile++;
+ }
+ if (histogramScores.isLowerQuartileStudent(agentId)) {
+ numStudentsWithAllCorrectFromLowerQuartile++;
+ }
+ }
+ int numStudentsRespondedFromUpperQuartile = 0;
+ int numStudentsRespondedFromLowerQuartile = 0;
+ studentsIter = studentsResponded.iterator();
+ while (studentsIter.hasNext()) {
+ String agentId = (String) studentsIter.next();
+ if (histogramScores.isUpperQuartileStudent(agentId)) {
+ numStudentsRespondedFromUpperQuartile++;
+ }
+ if (histogramScores.isLowerQuartileStudent(agentId)) {
+ numStudentsRespondedFromLowerQuartile++;
+ }
+ }
+
+ double percentCorrectFromUpperQuartileStudents =
+ ((double) numStudentsWithAllCorrectFromUpperQuartile /
+ (double) percent27) * 100d;
+
+ double percentCorrectFromLowerQuartileStudents =
+ ((double) numStudentsWithAllCorrectFromLowerQuartile /
+ (double) percent27) * 100d;
+
+ questionScores.setPercentCorrectFromUpperQuartileStudents(
+ Integer.toString((int) percentCorrectFromUpperQuartileStudents));
+ questionScores.setPercentCorrectFromLowerQuartileStudents(
+ Integer.toString((int) percentCorrectFromLowerQuartileStudents));
+
+ double numResponses = (double)questionScores.getNumResponses();
+
+ double discrimination = ((double)numStudentsWithAllCorrectFromUpperQuartile -
+ (double)numStudentsWithAllCorrectFromLowerQuartile)/(double)percent27 ;
+
+ // round to 2 decimals
+ if (discrimination > 999999 || discrimination < -999999) {
+ questionScores.setDiscrimination("NaN");
+ }
+ else {
+ discrimination = ((int) (discrimination*100.00)) / 100.00;
+ questionScores.setDiscrimination(Double.toString(discrimination));
+ }
+ }
+
+ subQuestionInfo.add(questionScores);
+ } // end-while - items
+ qbean.setInfo(subQuestionInfo);
+
+ }
+
private void getFIBMCMCScores(HashMap publishedItemHash,
- HashMap publishedAnswerHash, ArrayList scores,
- HistogramQuestionScoresBean qbean, ArrayList answers) {
+ HashMap publishedAnswerHash, List scores,
+ HistogramQuestionScoresBean qbean, List answers) {
ResourceLoader rb = new ResourceLoader(
"org.sakaiproject.tool.assessment.bundle.EvaluationMessages");
HashMap texts = new HashMap();
@@ -875,10 +1405,10 @@
// it would count as a correct response
try {
- ArrayList itemTextArray = ((ItemDataIfc) publishedItemHash
+ List itemTextArray = ((ItemDataIfc) publishedItemHash
.get(item.getPublishedItemId()))
.getItemTextArraySorted();
- ArrayList answerArray = ((ItemTextIfc) itemTextArray
+ List answerArray = ((ItemTextIfc) itemTextArray
.get(0)).getAnswerArraySorted();
int corranswers = 0;
@@ -917,10 +1447,8 @@
if (!hasIncorrect) {
correctresponses = correctresponses + 1;
- // gopalrc - Nov 2007
qbean.addStudentWithAllCorrect(((ItemGradingData)resultsForOneStudent.get(0)).getAgentId());
}
- // gopalrc - Dec 2007
qbean.addStudentResponded(((ItemGradingData)resultsForOneStudent.get(0)).getAgentId());
}
// NEW
@@ -1038,8 +1566,8 @@
* correctresponses/(double) responses) * 100))); }
*/
- private void getTFMCScores(HashMap publishedAnswerHash, ArrayList scores,
- HistogramQuestionScoresBean qbean, ArrayList answers) {
+ private void getTFMCScores(HashMap publishedAnswerHash, List scores,
+ HistogramQuestionScoresBean qbean, List answers) {
ResourceLoader rb = new ResourceLoader(
"org.sakaiproject.tool.assessment.bundle.EvaluationMessages");
HashMap texts = new HashMap();
@@ -1087,7 +1615,6 @@
results.put(answer.getId(), Integer.valueOf(num.intValue() + 1));
- // gopalrc - Nov 2007
// this should work because for tf/mc(single)
// questions, there should be at most
// one submitted answer per student/assessment
@@ -1095,7 +1622,6 @@
&& answer.getIsCorrect().booleanValue()) {
qbean.addStudentWithAllCorrect(data.getAgentId());
}
- // gopalrc - Nov 2007
qbean.addStudentResponded(data.getAgentId());
}
@@ -1181,7 +1707,7 @@
-private void getCalculatedQuestionScores(List scores, HistogramQuestionScoresBean qbean, ArrayList labels) {
+private void getCalculatedQuestionScores(List scores, HistogramQuestionScoresBean qbean, List labels) {
final String CORRECT = "Correct";
final String INCORRECT = "Incorrect";
final int COLUMN_MAX_HEIGHT = 600;
@@ -1249,7 +1775,7 @@
}
private void getMatchingScores(HashMap publishedItemTextHash, HashMap publishedAnswerHash,
- ArrayList scores, HistogramQuestionScoresBean qbean, ArrayList labels)
+ List scores, HistogramQuestionScoresBean qbean, List labels)
{
ResourceLoader rb = new ResourceLoader("org.sakaiproject.tool.assessment.bundle.EvaluationMessages");
ResourceLoader rc = new ResourceLoader("org.sakaiproject.tool.assessment.bundle.CommonMessages");
@@ -1366,18 +1892,13 @@
if (!hasIncorrect) {
correctresponses = correctresponses + 1;
- // gopalrc - Nov 2007
qbean.addStudentWithAllCorrect(((ItemGradingData)resultsForOneStudent.get(0)).getAgentId());
}
- // gopalrc - Dec 2007
qbean.addStudentResponded(((ItemGradingData)resultsForOneStudent.get(0)).getAgentId());
}
-
-
-
//NEW
int[] heights = calColumnHeight(numarray, qbean.getNumResponses());
// int[] heights = calColumnHeight(numarray);
@@ -1397,7 +1918,7 @@
}
private void getMatrixSurveyScores(HashMap publishedItemTextHash, HashMap publishedAnswerHash,
- ArrayList scores, HistogramQuestionScoresBean qbean, ArrayList labels)
+ List scores, HistogramQuestionScoresBean qbean, List labels)
{
HashMap texts = new HashMap();
HashMap rows = new HashMap();
@@ -1634,7 +2155,7 @@
// depending on data's instanceof
Iterator iter = scoreList.iterator();
- ArrayList floats = new ArrayList();
+ ArrayList doubles = new ArrayList();
while (iter.hasNext())
{
Object data = iter.next();
@@ -1643,7 +2164,7 @@
if (finalScore == null) {
finalScore = Double.valueOf("0");
}
- floats.add(finalScore);
+ doubles.add(finalScore);
}
else
{
@@ -1654,13 +2175,13 @@
if (((ItemGradingData) data).getOverrideScore() != null)
overrideScore =
((ItemGradingData) data).getOverrideScore().doubleValue();
- floats.add(Double.valueOf(autoScore + overrideScore));
+ doubles.add(Double.valueOf(autoScore + overrideScore));
}
}
- if (floats.isEmpty())
- floats.add(new Double(0.0));
- Object[] array = floats.toArray();
+ if (doubles.isEmpty())
+ doubles.add(new Double(0.0));
+ Object[] array = doubles.toArray();
Arrays.sort(array);
double[] scores = new double[array.length];
@@ -2189,50 +2710,49 @@
private String getType(int typeId) {
ResourceLoader rb = new ResourceLoader("org.sakaiproject.tool.assessment.bundle.EvaluationMessages");
ResourceLoader rc = new ResourceLoader("org.sakaiproject.tool.assessment.bundle.CommonMessages");
- if (typeId == 1) {
+ if (typeId == TypeIfc.MULTIPLE_CHOICE.intValue()) {
return rc.getString("multiple_choice_sin");
}
- if (typeId == 2) {
+ if (typeId == TypeIfc.MULTIPLE_CORRECT.intValue()) {
return rc.getString("multipl_mc_ms");
}
- if (typeId == 12) {
+ if (typeId == TypeIfc.MULTIPLE_CORRECT_SINGLE_SELECTION.intValue()) {
return rc.getString("multipl_mc_ss");
}
- if (typeId == 3) {
+ if (typeId == TypeIfc.MULTIPLE_CHOICE_SURVEY.intValue()) {
return rb.getString("q_mult_surv");
}
- if (typeId == 4) {
+ if (typeId == TypeIfc.TRUE_FALSE.intValue()) {
return rb.getString("q_tf");
}
- if (typeId == 5) {
+ if (typeId == TypeIfc.ESSAY_QUESTION.intValue()) {
return rb.getString("q_short_ess");
}
- if (typeId == 6) {
+ if (typeId == TypeIfc.FILE_UPLOAD.intValue()) {
return rb.getString("q_fu");
}
- if (typeId == 7) {
+ if (typeId == TypeIfc.AUDIO_RECORDING.intValue()) {
return rb.getString("q_aud");
}
- if (typeId == 8) {
+ if (typeId == TypeIfc.FILL_IN_BLANK.intValue()) {
return rb.getString("q_fib");
}
- if (typeId == 9) {
+ if (typeId == TypeIfc.MATCHING.intValue()) {
return rb.getString("q_match");
}
- if (typeId == 11) {
+ if (typeId == TypeIfc.FILL_IN_NUMERIC.intValue()) {
return rb.getString("q_fin");
}
- if (typeId == 13) {
+ if (typeId == TypeIfc.EXTENDED_MATCHING_ITEMS.intValue()) {
+ return rb.getString("q_emi");
+ }
+ if (typeId == TypeIfc.MATRIX_CHOICES_SURVEY.intValue()) {
return rb.getString("q_matrix_choices_surv");
}
return "";
}
-
-
/**
- * added by gopalrc - Dec 2007
- *
* Standard process action method.
* @param ae ActionEvent
* @throws AbortProcessingException
@@ -2256,7 +2776,8 @@
}
ArrayList spreadsheetRows = new ArrayList();
- Collection detailedStatistics = bean.getDetailedStatistics();
+ List detailedStatistics = bean.getDetailedStatistics();
+
spreadsheetRows.add(bean.getShowPartAndTotalScoreSpreadsheetColumns());
//spreadsheetRows.add(bean.getShowDiscriminationColumn());
@@ -2316,9 +2837,9 @@
for (char colHeader=65; colHeader < 65+bean.getMaxNumberOfAnswers(); colHeader++) {
headerList.add(String.valueOf(colHeader));
}
- spreadsheetRows.add(headerList);
-
-
+ spreadsheetRows.add(headerList);
+ //VULA-1948: sort the detailedStatistics list by Question Label
+ sortQuestionScoresByLabel(detailedStatistics);
Iterator detailedStatsIter = detailedStatistics.iterator();
ArrayList statsLine = null;
while (detailedStatsIter.hasNext()) {
@@ -2387,18 +2908,24 @@
statsLine.add(dVal);
- for (int i=0; i filterGradingData(List submissionsSortedForDiscrim, Long itemId) {
+
+ /**
+ * This method sort the detailedStatistics List by Question Label value
+ *
+ * @param detailedStatistics
+ */
+ private void sortQuestionScoresByLabel(List detailedStatistics) {
+ //VULA-1948: sort the detailedStatistics list by Question Label
+ Collections.sort(detailedStatistics, new Comparator() {
+
+ @Override
+ public int compare(HistogramQuestionScoresBean arg0, HistogramQuestionScoresBean arg1) {
+
+ HistogramQuestionScoresBean bean1 = (HistogramQuestionScoresBean) arg0;
+ HistogramQuestionScoresBean bean2 = (HistogramQuestionScoresBean) arg1;
+
+ String lable1 = bean1.getQuestionLabel();
+ String lable2 = bean2.getQuestionLabel();
+
+ if (bean1.getNumberOfParts() > 1 && bean2.getNumberOfParts() > 1) {
+
+ if (Integer.valueOf(lable1.substring(1, lable1.indexOf("-"))).compareTo(
+ Integer.valueOf(lable2.substring(1, lable2.indexOf("-")))) > 0) {
+ return 1;
+ } else if (Integer.valueOf(lable1.substring(1, lable1.indexOf("-"))).compareTo(
+ Integer.valueOf(lable2.substring(1, lable2.indexOf("-")))) < 0) {
+ return -1;
+ }
+
+ lable1 = lable1.substring(lable1.indexOf("-") + 1, lable1.length());
+ lable2 = lable2.substring(lable2.indexOf("-") + 1, lable2.length());
+ }
+
+ if (lable1.indexOf("-") == -1 && lable2.indexOf("-") == -1) {
+ return Integer.valueOf(lable1.substring(1)).compareTo(Integer.valueOf(lable2.substring(1)));
+
+ } else if (lable1.indexOf("-") == -1 && lable2.indexOf("-") != -1) {
+ int val = Integer.valueOf(lable1.substring(1)).compareTo(
+ Integer.valueOf(lable2.substring(1, lable2.lastIndexOf("-"))));
+ if (val == 0) {
+ val = -1;
+ }
+ return val;
+
+ } else if (lable1.indexOf("-") != -1 && lable2.indexOf("-") == -1) {
+ int val = Integer.valueOf(lable1.substring(1, lable1.lastIndexOf("-"))).compareTo(
+ Integer.valueOf(lable2.substring(1)));
+ if (val == 0) {
+ val = 1;
+ }
+ return val;
+
+ } else if (lable1.indexOf("-") != -1 && lable2.indexOf("-") != -1) {
+ int val = Integer.valueOf(lable1.substring(1, lable1.lastIndexOf("-"))).compareTo(
+ Integer.valueOf(lable2.substring(1, lable2.lastIndexOf("-"))));
+ if (val == 0) {
+ val = Integer.valueOf(lable1.substring(lable1.lastIndexOf("-") + 1, lable1.length())).compareTo(
+ Integer.valueOf(lable2.substring(lable2.lastIndexOf("-") + 1, lable2.length())));
+ }
+ return val;
+ }
+ return lable1.substring(1).compareTo(lable2.substring(1));
+
+ }
+ });
+ }
+
+ private List filterGradingData(List submissionsSortedForDiscrim, Long itemId) {
List submissionsForItemSortedForDiscrim = new ArrayList();
for(AssessmentGradingData agd: submissionsSortedForDiscrim){
Set itemGradings = agd.getItemGradingSet();
Index: samigo-app/src/java/org/sakaiproject/tool/assessment/ui/listener/evaluation/QuestionScoreListener.java
===================================================================
--- samigo-app/src/java/org/sakaiproject/tool/assessment/ui/listener/evaluation/QuestionScoreListener.java (revision 133459)
+++ samigo-app/src/java/org/sakaiproject/tool/assessment/ui/listener/evaluation/QuestionScoreListener.java (working copy)
@@ -250,13 +250,6 @@
}
if ("true".equalsIgnoreCase(totalBean.getAnonymous())) {
- // reset sectionaware pulldown to -1 all sections
- //totalBean
- // .setSelectedSectionFilterValue(TotalScoresBean.ALL_SECTIONS_SELECT_VALUE);
-
- // changed from above by gopalrc - Jan 2008
- //PublishedAssessmentService publishedAssessmentService = new PublishedAssessmentService();
- //boolean groupRelease = publishedAssessmentService.isReleasedToGroups(publishedId);
boolean groupRelease = publishedAssessment.getAssessmentAccessControl().getReleaseTo().equals(AssessmentAccessControl.RELEASE_TO_SELECTED_GROUPS);
if (groupRelease) {
totalBean.setSelectedSectionFilterValue(TotalScoresBean.RELEASED_SECTIONS_GROUPS_SELECT_VALUE);
Index: samigo-app/src/java/org/sakaiproject/tool/assessment/ui/listener/evaluation/StudentScoreListener.java
===================================================================
--- samigo-app/src/java/org/sakaiproject/tool/assessment/ui/listener/evaluation/StudentScoreListener.java (revision 133459)
+++ samigo-app/src/java/org/sakaiproject/tool/assessment/ui/listener/evaluation/StudentScoreListener.java (working copy)
@@ -26,6 +26,7 @@
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
+import java.util.List;
import javax.faces.event.AbortProcessingException;
import javax.faces.event.ActionEvent;
@@ -166,10 +167,10 @@
while (iter2.hasNext()) {
ItemContentsBean itemContentsBean = (ItemContentsBean) iter2.next();
if (itemContentsBean != null) {
- ArrayList itemGradingDataArray = itemContentsBean.getItemGradingDataArray();
- Iterator iter3 = itemGradingDataArray.iterator();
+ List itemGradingDataArray = itemContentsBean.getItemGradingDataArray();
+ Iterator iter3 = itemGradingDataArray.iterator();
while (iter3.hasNext()) {
- ItemGradingData itemGradingData = (ItemGradingData) iter3.next();
+ ItemGradingData itemGradingData = iter3.next();
itemContentsMap.put(itemGradingData.getItemGradingId(), itemContentsBean);
}
}
Index: samigo-app/src/java/org/sakaiproject/tool/assessment/ui/listener/evaluation/StudentScoreUpdateListener.java
===================================================================
--- samigo-app/src/java/org/sakaiproject/tool/assessment/ui/listener/evaluation/StudentScoreUpdateListener.java (revision 133459)
+++ samigo-app/src/java/org/sakaiproject/tool/assessment/ui/listener/evaluation/StudentScoreUpdateListener.java (working copy)
@@ -123,7 +123,7 @@
while (iter2.hasNext())
{
ItemContentsBean question = (ItemContentsBean) iter2.next();
- ArrayList gradingarray = question.getItemGradingDataArray();
+ List gradingarray = question.getItemGradingDataArray();
log.debug("****1. pub questionId = " + question.getItemData().getItemId());
log.debug("****2. Gradingarray length = " + gradingarray.size());
// Create a new one if we need it.
@@ -304,11 +304,11 @@
while (iter2.hasNext())
{
ItemContentsBean question = (ItemContentsBean) iter2.next();
- ArrayList gradingarray = question.getItemGradingDataArray();
+ List gradingarray = question.getItemGradingDataArray();
log.debug("Gradingarray length2 = " + gradingarray.size());
- Iterator iter3 = gradingarray.iterator();
+ Iterator iter3 = gradingarray.iterator();
while (iter3.hasNext()) {
- ItemGradingData itemGradingData = (ItemGradingData) iter3.next();
+ ItemGradingData itemGradingData = iter3.next();
List oldList = itemGradingData.getItemGradingAttachmentList();
List newList = question.getItemGradingAttachmentList();
if ((oldList == null || oldList.size() == 0 ) && (newList == null || newList.size() == 0)) {
Index: samigo-app/src/java/org/sakaiproject/tool/assessment/ui/listener/evaluation/TotalScoreListener.java
===================================================================
--- samigo-app/src/java/org/sakaiproject/tool/assessment/ui/listener/evaluation/TotalScoreListener.java (revision 133459)
+++ samigo-app/src/java/org/sakaiproject/tool/assessment/ui/listener/evaluation/TotalScoreListener.java (working copy)
@@ -318,25 +318,6 @@
ArrayList scores = new ArrayList();
ArrayList students_not_submitted= new ArrayList();
- /*
- // if for anonymous, reset totalscorebean.getselectedsectionfiltervalue = ALL_SECTIONS_SELECT_VALUE
- if ("true".equalsIgnoreCase(bean.getAnonymous())){
- //reset sectionaware pulldown to -1 all sections
- //bean.setSelectedSectionFilterValue(TotalScoresBean.ALL_SECTIONS_SELECT_VALUE);
-
- // changed from above by gopalrc - Jan 2008
- //PublishedAssessmentService publishedAssessmentService = new PublishedAssessmentService();
- // boolean groupRelease = publishedAssessmentService.isReleasedToGroups(bean.getPublishedId());
- boolean groupRelease = p.getAssessmentAccessControl().getReleaseTo().equals(AssessmentAccessControlIfc.RELEASE_TO_SELECTED_GROUPS);
- if (groupRelease) {
- bean.setSelectedSectionFilterValue(TotalScoresBean.RELEASED_SECTIONS_GROUPS_SELECT_VALUE);
- }
- else {
- bean.setSelectedSectionFilterValue(TotalScoresBean.ALL_SECTIONS_SELECT_VALUE);
- }
-
- }
- */
Map useridMap= bean.getUserIdMap(TotalScoresBean.CALLED_FROM_TOTAL_SCORE_LISTENER);
ArrayList agents = new ArrayList();
prepareAgentResultList(bean, p, scores, students_not_submitted, useridMap);
Index: samigo-app/src/java/org/sakaiproject/tool/assessment/ui/listener/questionpool/SortQuestionListListener.java
===================================================================
--- samigo-app/src/java/org/sakaiproject/tool/assessment/ui/listener/questionpool/SortQuestionListListener.java (revision 133459)
+++ samigo-app/src/java/org/sakaiproject/tool/assessment/ui/listener/questionpool/SortQuestionListListener.java (working copy)
@@ -70,10 +70,9 @@
ArrayList list= null;
if (getItems != null && getItems.trim().equals("false")){
log.debug("Do not getItems: getItems = " + getItems);
- }
- else {
- if (qpid==null ||("").equals(qpid)){
- list = delegate.getAllItemsSorted(questionpoolbean.getCurrentPool().getId(), orderBy, ascending);
+ } else {
+ if (qpid == null || ("").equals(qpid.trim())){
+ list = delegate.getAllItemsSorted(questionpoolbean.getCurrentPool().getId(), orderBy, ascending);
}
else{
list = delegate.getAllItemsSorted(Long.valueOf(qpid),orderBy, ascending);
Index: samigo-app/src/java/org/sakaiproject/tool/assessment/ui/listener/select/SelectActionListener.java
===================================================================
--- samigo-app/src/java/org/sakaiproject/tool/assessment/ui/listener/select/SelectActionListener.java (revision 133459)
+++ samigo-app/src/java/org/sakaiproject/tool/assessment/ui/listener/select/SelectActionListener.java (working copy)
@@ -728,7 +728,7 @@
String showScore = "na";
// must meet 2 conditions: hasFeedback==true && feedback.getShowStudentScore()==true
AssessmentFeedbackIfc f= (AssessmentFeedbackIfc)feedbackHash.get(a.getPublishedAssessmentId());
- if (f!=null){
+ if (f!=null && f.getFeedbackComponentOption()!=null) {
boolean showScorecore = (Boolean.TRUE).equals(f.getShowStudentScore()) || Integer.valueOf(1).equals(f.getFeedbackComponentOption());
if (showScorecore && "show".equals(hasFeedback))
showScore = "show";
Index: samigo-app/src/java/org/sakaiproject/tool/assessment/ui/listener/util/TimeUtil.java
===================================================================
--- samigo-app/src/java/org/sakaiproject/tool/assessment/ui/listener/util/TimeUtil.java (revision 133459)
+++ samigo-app/src/java/org/sakaiproject/tool/assessment/ui/listener/util/TimeUtil.java (working copy)
@@ -32,7 +32,6 @@
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.sakaiproject.time.cover.TimeService;
-
/**
*
Description: Time conversion utility class
*/
@@ -52,7 +51,7 @@
/**
- * Convert a String reprepsentation of date and time in the client TimeZone
+ * Convert a String representation of date and time in the client TimeZone
* to Date representation of date and time in server TimeZone
* before saving to DB.
* tz1 is the client timezone, tz2 is the server timezone
@@ -75,7 +74,7 @@
/**
- * Convert a Date reprepsentation of date and time in the server TimeZone
+ * Convert a Date representation of date and time in the server TimeZone
* to String representation of date and time in client TimeZone
* used for display.
* tz1 is the client timezone, tz2 is the server timezone
@@ -119,7 +118,7 @@
/**
- * Convert a Date reprepsentation of date and time to String in the client timezone for display
+ * Convert a Date representation of date and time to String in the client timezone for display
*/
public String getDisplayDateTime(SimpleDateFormat ndf, Date serverDate ){
@@ -141,7 +140,7 @@
}
}
catch (RuntimeException e){
- log.warn("can not format the Date to a string");
+ log.warn("can not format the Date to a string", e);
}
return displayDate;
}
Index: samigo-app/src/java/org/sakaiproject/tool/assessment/ui/servlet/delivery/LoginServlet.java
===================================================================
--- samigo-app/src/java/org/sakaiproject/tool/assessment/ui/servlet/delivery/LoginServlet.java (revision 133459)
+++ samigo-app/src/java/org/sakaiproject/tool/assessment/ui/servlet/delivery/LoginServlet.java (working copy)
@@ -279,14 +279,6 @@
return isMember;
}
- /**
- * added by gopalrc - Nov 2007
- *
- * @param pub
- * @param req
- * @param res
- * @return
- */
private boolean checkMembershipForGroupRelease(PublishedAssessmentFacade pub,
HttpServletRequest req, HttpServletResponse res){
boolean isMember=false;
@@ -320,13 +312,6 @@
return isMember;
}
- /**
- * added by gopalrc - Nov 2007
- *
- * @param authorizedGroupId
- * @param userGroups
- * @return
- */
private boolean isUserInAuthorizedGroup(String authorizedGroupId, Collection userGroups) {
if (userGroups==null || userGroups.isEmpty()
|| authorizedGroupId==null || authorizedGroupId.equals("")) {
Index: samigo-app/src/test/org/sakaiproject/tool/assessment/business/entity/helper/AuthoringHelperTest.java
===================================================================
--- samigo-app/src/test/org/sakaiproject/tool/assessment/business/entity/helper/AuthoringHelperTest.java (revision 133459)
+++ samigo-app/src/test/org/sakaiproject/tool/assessment/business/entity/helper/AuthoringHelperTest.java (working copy)
@@ -196,7 +196,7 @@
log.debug("ITEM MAP=" + itemMap);
ItemFacade item = new ItemFacade();
- exHelper.updateItem(item, itemMap);
+ exHelper.updateItem(item, itemXml, itemMap);
// make sure required fields are set
item.setCreatedBy(me);
item.setCreatedDate(assessment.getCreatedDate());
@@ -286,7 +286,7 @@
Item itemXml = new Item(document, QTIVersion.VERSION_1_2);
Map itemMap = exHelper.mapItem(itemXml);
// log.debug("ITEM MAP=" + itemMap);
- exHelper.updateItem(item, itemMap);
+ exHelper.updateItem(item, itemXml, itemMap);
//ItemService itemService = new ItemService();
log.info("updating item");
// itemService.saveItem(item);
Index: samigo-app/src/webapp/WEB-INF/faces-config.xml
===================================================================
--- samigo-app/src/webapp/WEB-INF/faces-config.xml (revision 133459)
+++ samigo-app/src/webapp/WEB-INF/faces-config.xml (working copy)
@@ -334,6 +334,10 @@
true
+ showExtendedMatchingItems
+ true
+
+ selectFromQuestionBankfalse
@@ -1006,6 +1010,10 @@
/jsf/author/item/matching.jsp
+ emiItem
+ /jsf/author/item/extendedMatchingItems.jsp
+
+ matrixChoicesSurveyItem/jsf/author/item/matrixChoicesSurvey.jsp
@@ -1403,5 +1411,4 @@
-
Index: samigo-app/src/webapp/WEB-INF/samigo.tld
===================================================================
--- samigo-app/src/webapp/WEB-INF/samigo.tld (revision 133459)
+++ samigo-app/src/webapp/WEB-INF/samigo.tld (working copy)
@@ -292,6 +292,13 @@
JSP
+
+
+ identity
+ false
+ false
+ a identity for the textarea field
+ value
Index: samigo-app/src/webapp/css/jquery.alerts-1.1/images/help.gif
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: samigo-app/src/webapp/css/jquery.alerts-1.1/images/important.gif
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: samigo-app/src/webapp/css/jquery.alerts-1.1/images/info.gif
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: samigo-app/src/webapp/css/jquery.alerts-1.1/images/title.gif
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: samigo-app/src/webapp/css/jquery.alerts-1.1/jquery.alerts.css
===================================================================
--- samigo-app/src/webapp/css/jquery.alerts-1.1/jquery.alerts.css (revision 0)
+++ samigo-app/src/webapp/css/jquery.alerts-1.1/jquery.alerts.css (working copy)
@@ -0,0 +1,57 @@
+#popup_container {
+ font-family: Arial, sans-serif;
+ font-size: 12px;
+ min-width: 300px; /* Dialog will be no smaller than this */
+ max-width: 600px; /* Dialog will wrap after this width */
+ background: #FFF;
+ border: solid 5px #999;
+ color: #000;
+ -moz-border-radius: 5px;
+ -webkit-border-radius: 5px;
+ border-radius: 5px;
+}
+
+#popup_title {
+ font-size: 14px;
+ font-weight: bold;
+ text-align: center;
+ line-height: 1.75em;
+ color: #666;
+ background: #CCC url(images/title.gif) top repeat-x;
+ border: solid 1px #FFF;
+ border-bottom: solid 1px #999;
+ cursor: default;
+ padding: 0em;
+ margin: 0em;
+}
+
+#popup_content {
+ background: 16px 16px no-repeat url(images/info.gif);
+ padding: 1em 1.75em;
+ margin: 0em;
+}
+
+#popup_content.alert {
+ background-image: url(images/info.gif);
+}
+
+#popup_content.confirm {
+ background-image: url(images/important.gif);
+}
+
+#popup_content.prompt {
+ background-image: url(images/help.gif);
+}
+
+#popup_message {
+ padding-left: 48px;
+}
+
+#popup_panel {
+ text-align: center;
+ margin: 1em 0em 0em 1em;
+}
+
+#popup_prompt {
+ margin: .5em 0em;
+}
\ No newline at end of file
Index: samigo-app/src/webapp/css/tool_sam.css
===================================================================
--- samigo-app/src/webapp/css/tool_sam.css (revision 133459)
+++ samigo-app/src/webapp/css/tool_sam.css (working copy)
@@ -131,7 +131,6 @@
text-align:right;
}
-/* added gopalrc - Jan 2008 */
.detailedStatsCorrectAnswerText {
font-weight: bold;
}
@@ -142,7 +141,6 @@
font-weight: bold;
}
-/* added gopalrc - Jan 2008 */
.detailedStatsCorrectAnswerText {
font-weight: bold;
}
@@ -304,6 +302,30 @@
border: 0 none;
}
+/* Simple Borders for EMI Tables=====================*/
+table.simpleBorder {
+ border-bottom: 1px solid #ccc;
+ background-color: white;
+ vertical-align: top;
+}
+table.simpleBorder td {
+ padding: 4px;
+ border-top: 1px solid #ccc;
+ background-color: white;
+ vertical-align: top;
+}
+table.noBorder {
+ background-color: white;
+ vertical-align: top;
+ border: 1px solid #fff;
+}
+table.noBorder td {
+ padding: 4px;
+ background-color: white;
+ vertical-align: top;
+ border: 1px solid #fff;
+}
+
#samigo-create-container {
margin-bottom: 20px;
}
@@ -379,6 +401,29 @@
#tabs .ui-widget-content a:hover {
text-decoration: underline;
}
+#divider {
+ background: none repeat scroll 0 0 #88D0E8;
+ height: 150px;
+ width: 1px;
+ margin-left: 2px;
+ margin-right: 5px;
+}
+.iconAdd {
+ background: url("/library/image/silk/add.png") no-repeat scroll 0 0 transparent;
+ padding-left: 20px;
+}
+.iconAttach {
+ background: url("/library/image/silk/attach.png") no-repeat scroll 0 0 transparent;
+ padding-left: 20px;
+}
+.greyBox {
+ background: none repeat-x scroll 50% 50% #F6F6F6;
+ border: 1px solid #eee;
+ padding: 8px;
+}
+.alignTop {
+ vertical-align: top;
+}
tbody tr td.center{
text-align: center; /*centers radio buttons beneath column headings in matrix type survey questions */
@@ -456,7 +501,10 @@
color: #404040;
font-family: Arial,Helvetica,sans-serif;
}
-
+.placeholder
+{
+ color: #aaa;
+}
.submissionInfoCol1{
width: 200px;
}
@@ -465,6 +513,15 @@
width: 650px;
}
+.mcAnswerText {
+ display:inline-table;
+ width: 80%;
+}
+
+.mcColumn1 {
+ width: 40px;
+}
+
#jqueryui-accordion .ui-accordion-content {
background-color: #efefef;
}
Index: samigo-app/src/webapp/css/ui-lightness/jquery-ui-1.7.2.custom.css
===================================================================
--- samigo-app/src/webapp/css/ui-lightness/jquery-ui-1.7.2.custom.css (revision 133459)
+++ samigo-app/src/webapp/css/ui-lightness/jquery-ui-1.7.2.custom.css (working copy)
@@ -50,7 +50,7 @@
----------------------------------*/
.ui-widget { font-size: 1em; }
.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-size: 1em; }
-.ui-widget-content { border: 1px solid #dddddd; background: #fff url(images/ui-bg_highlight-soft_100_eeeeee_1x100.png) 50% top repeat-x; color: #333333; }
+.ui-widget-content { border: 1px solid #dddddd; background: #fff url(images/ui-bg_highlight-soft_100_eeeeee_1x100.png) 50% top repeat-x; color: black; }
.ui-widget-content a { color: #333333; }
.ui-widget-header { background-color: orange; color: #ffffff; font-weight: bold; }
#tabs .ui-widget-header { background-color: #eeeeee; color: #ffffff; font-weight: bold; }
@@ -353,8 +353,8 @@
height: 200px; /*must have*/
}/* Dialog
----------------------------------*/
-.ui-dialog { position: relative; padding: .2em; width: 300px; }
-.ui-dialog .ui-dialog-titlebar { padding: .5em .3em .3em 1em; position: relative; }
+.ui-dialog { position: relative; padding: .2em; width: 300px; background: none repeat scroll 0 0 white; }
+.ui-dialog .ui-dialog-titlebar { padding: .5em .3em .3em 1em; position: relative; background-color: #009DCE; }
.ui-dialog .ui-dialog-title { float: left; margin: .1em 0 .2em; }
.ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; }
.ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; }
Index: samigo-app/src/webapp/js/authoring-emi.js
===================================================================
--- samigo-app/src/webapp/js/authoring-emi.js (revision 0)
+++ samigo-app/src/webapp/js/authoring-emi.js (working copy)
@@ -0,0 +1,683 @@
+//this is to resolve an IE bug, aaaargh we are still in the dark ages
+if(typeof String.prototype.trim !== 'function') {
+ String.prototype.trim = function() {
+ return this.replace(/^\s+|\s+$/g, '');
+ }
+}
+
+//jQuery functions
+if (typeof $ === 'undefined') {
+ $ = jQuery;
+}
+//------------------------------------------//
+// The ready function, setup the form //
+// for all the events //
+//------------------------------------------//
+$(document).ready(function(){
+ var inReadyCall = true;
+
+ //only applies to EMI authoring
+ //this value is set in extendedMatchingItems.jsp
+ if (!emiAuthoring) return;
+
+ //------------------------------------------//
+ // Global variables //
+ // Variables used in the emi functions //
+ //------------------------------------------//
+ var highestOptionId = +25;
+ var highestItemId = +59;
+ var maxAvailableItems = +30;
+ var minOptions = +2;
+ var currentOptions = 0;
+ var optionsAtStart = +8;
+ var itemsAtStart = +4;
+ var removeLabel = "X";
+ var ANSWER_OPTION_LABELS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+
+ //----------------------------------------------//
+ // VALIDATION //
+ // set the validation variables from hidden //
+ // fields in the extendedMatchingItems.jsp //
+ //----------------------------------------------//
+ var answer_point_value_error = $("input[id='answer_point_value_error']").val();
+ var theme_text_error = $("input[id='theme_text_error']").val();
+ var number_of_rich_text_options_error = $("input[id='number_of_rich_text_options_error']").val();
+ var blank_or_non_integer_item_sequence_error = $("input[id='blank_or_non_integer_item_sequence_error']").val();
+ var correct_option_labels_error = $("input[id='correct_option_labels_error']").val();
+ var correct_option_labels_invalid_error = $("input[id='correct_option_labels_invalid_error']").val();
+ var at_least_two_options_required_error = $("input[id='at_least_two_options_required_error']").val();
+ var at_least_two_pasted_options_required_error = $("input[id='at_least_two_pasted_options_required_error']").val();
+
+ //----------------------------------------------//
+ // Create error message tags //
+ // Setup the table at the top of //
+ // extendedMatchingItems.jsp to hold the error //
+ // message. This replicate the way the errors //
+ // are shown in the normal jsf submits //
+ //----------------------------------------------//
+ var $errorMessageTable = $('#emiErrorMessageTable');
+ var $tableRowElement = $('
');
+ var $tableColumnElement = $('
');
+
+ //----------------------------------------------//
+ // Validation function on save //
+ //----------------------------------------------//
+ $("input[value='Save']").bind('click', function(){
+ updateAnswerPointScore();
+ $errorMessageTable.removeClass('messageSamigo');
+ $('#emiErrorMessageTable > tr').remove();
+ var errorMessages = new Array();
+ var errorNumber=+0;
+
+ //Validate Answer Point Value
+ var answerPointValue = $("input[name='itemForm:answerptr']").val();
+ if (answerPointValue.trim()=="" || /[^0-9.]/g.test(answerPointValue)) {
+ errorMessages[errorNumber++] = answer_point_value_error;
+ }
+
+ //Validate Theme Text
+ var themeText = $("input[name='itemForm:themetext']").val();
+ if (themeText.trim()=="") {
+ errorMessages[errorNumber++] = theme_text_error;
+ }
+
+ //Validate Options
+ var simpleOrRichAnswerOptions = $("input[name='itemForm:emiAnswerOptionsSimpleOrRich']:checked").val();
+ var optionLabels = "";
+
+ if (simpleOrRichAnswerOptions==0) { //simple text options
+ for (j=0; j 0) {
+ for (i=0; i 0) {
+ for (i=0; i tr').remove();
+ currentOptions = 0;
+ //VULA-1887: Simple text - for pasting options workflow error - leading to broken functionality
+ if (pastedOptions == null || pastedOptions.trim() == "") {
+ return;
+ }
+ var optionsArray = pastedOptions.split("\n");
+ for(i = 0; i < optionsArray.length; i++){
+ if (optionsArray[i] != null && optionsArray[i].trim()!="") {
+ var col = $tableColumnElement.clone().append(
+ ANSWER_OPTION_LABELS.substring(i, i+1) + '.) ' + optionsArray[i]);
+ var row = $tableRowElement.clone().appendTo($labelsTable);
+ col.appendTo(row);
+ currentOptions++;
+ }
+ }
+ });
+
+ //----------------------------------//
+ // Remove Option //
+ // //
+ //----------------------------------//
+ for (i=0; i<=highestOptionId; i++) {
+ var emiOptionRemoveLink = $("a[id='itemForm:emiAnswerOptions:" + i + ":RemoveLink']");
+ emiOptionRemoveLink.bind('click', function() {
+ var optionId = +($(this).attr("id").split(":")[2]);
+ for (j=optionId; j=0; i--) {
+ var optionText = $("input[id='itemForm:emiAnswerOptions:" + i + ":Text']");
+ if (optionText.val() === "" || optionText.val() === null) {
+ $("table[id='itemForm:emiAnswerOptions:" + i + ":Row']").parent().parent().hide();
+ currentOptions--;
+ }
+ else {
+ isAllNull = false;
+ break;
+ }
+ }
+ if (isAllNull) {
+ for (i=0; i'+ j +'');
+ }
+ else {
+ addEmiAnswerOptionsSelect.append('');
+ }
+ }
+ }
+
+ //----------------------------------------------//
+ // ******** Lead in Statement *************** //
+ //----------------------------------------------//
+ //------------------------------------------//
+ // Lead in Statement //
+ // set the lead in default and manage the //
+ // switch between user input and default //
+ //------------------------------------------//
+ var leadinStatementDescription = $('#default_lead_in_statement_description').val().replace(" ", "\n");
+ var leadinStatementField = $('[identity="lead_in_statement"]');
+ leadinStatementField.focus(function() {
+ var leadin = $(this);
+ if (leadin.val() == leadinStatementDescription) {
+ leadin.val('');
+ leadin.removeClass('placeholder');
+ }
+ }).blur(function() {
+ var leadin = $(this);
+ if (leadin.val() == '' || leadin.val() == leadinStatementDescription) {
+ leadin.addClass('placeholder');
+ leadin.val(leadinStatementDescription);
+ }
+ }).blur();
+ //set the default part on submit
+ leadinStatementField.parents('form').submit(function() {
+ leadinStatementField.each(function() {
+ var leadin = $(this);
+ if (leadin.val() == leadinStatementDescription) {
+ leadin.val($('#default_lead_in_statement').val());
+ }
+ })
+ });
+
+ //----------------------------------------------//
+ // ***************** Items ****************** //
+ //----------------------------------------------//
+ var emiItemAddLink = $("a[id='itemForm:addEmiQuestionAnswerCombinationsLink']");
+ var addEmiItemSelect = $("select[id='itemForm:addEmiQuestionAnswerCombinationsSelect']");
+
+ //----------------------------------//
+ // Hide excess Items at start //
+ //----------------------------------//
+ var emiVisibleItems = $("input[id='itemForm:emiVisibleItems']");
+ var availibleItems = +0;
+ var isAllNull = true;
+ for (i=highestItemId; i>=0; i--) {
+ var itemText = $("textarea[id^='itemForm:emiQuestionAnswerCombinations:" + i +"']");
+ var hasAttachment = $("input[id='itemForm:emiQuestionAnswerCombinations:" + i + ":hasAttachment']");
+ var labelInput = $("input[id='itemForm:emiQuestionAnswerCombinations:" + i + ":Label']");
+ if ((itemText.val() === "" && hasAttachment.val()==="false") || labelInput.val()==removeLabel) {
+ $("table[id='itemForm:emiQuestionAnswerCombinations:" + i + ":Row']").parent().parent().hide();
+ }
+ else {
+ isAllNull = false;
+ }
+ if(labelInput.val()!=removeLabel){
+ availibleItems++;
+ }
+ }
+ var itemsToShow=+0;
+ if (isAllNull) {
+ itemsToShow = +itemsAtStart;
+ emiVisibleItems.val(itemsToShow);
+ }
+ else {
+ itemsToShow = +emiVisibleItems.val();
+ }
+ availibleItems -= itemsToShow;
+ for (i=0; i<=highestItemId; i++) {
+ if (+itemsToShow == +0) break;
+ var labelInput = $("input[id='itemForm:emiQuestionAnswerCombinations:" + i + ":Label']");
+ if (labelInput.val() != removeLabel) {
+ $("table[id='itemForm:emiQuestionAnswerCombinations:" + i + ":Row']").parent().parent().show();
+ if (labelInput.val()==itemsToShow) {
+ break;
+ }
+ }
+ }
+ updateAddEmiItemsCount(+emiVisibleItems.val(), availibleItems, highestItemId+1);
+
+ //----------------------------------//
+ // Remove Items //
+ // //
+ //----------------------------------//
+ for (i=0; i<=highestItemId; i++) {
+ var emiItemRemoveLink = $("a[id='itemForm:emiQuestionAnswerCombinations:" + i + ":RemoveLink']");
+ emiItemRemoveLink.bind('click', function() {
+ var itemId = +($(this).attr("id").split(":")[2]);
+ var row = $("table[id='itemForm:emiQuestionAnswerCombinations:" + itemId + ":Row']").parent().parent();
+ var labelRemove = $("input[id='itemForm:emiQuestionAnswerCombinations:" + itemId + ":Label']");
+ labelRemove.val(removeLabel);
+ row.hide();
+ var seq=+0;
+ availibleItems=+0;
+ //Resequence items
+ for (j=0; j<=highestItemId; j++) {
+ row = $("table[id='itemForm:emiQuestionAnswerCombinations:" + j + ":Row']");
+ var labelInput = $("input[id='itemForm:emiQuestionAnswerCombinations:" + j + ":Label']");
+ if (row && row.is(':visible') && labelInput.val() !== removeLabel) {
+ seq++;
+ labelInput.val(seq);
+ labelInput.trigger('change');
+ }else if(labelInput.val() !== removeLabel){
+ availibleItems++;
+ }
+ }
+ emiVisibleItems.val(seq);
+ setContainerHeight();
+ updateAddEmiItemsCount(+emiVisibleItems.val(), availibleItems, highestItemId+1);
+ return false;
+ });
+ }
+
+ //----------------------------------//
+ // Add Items //
+ // //
+ //----------------------------------//
+ emiItemAddLink.bind('click', function(){
+ var j=+0;
+ var itemCount=+0;
+ var totalCount=+0;
+ availibleItems = +0;
+ var addCount = parseInt(addEmiItemSelect.val());
+
+ for (i=0; i<=highestItemId; i++) {
+ var row = $("table[id='itemForm:emiQuestionAnswerCombinations:" + i + ":Row']");
+ var labelInput = $("input[id='itemForm:emiQuestionAnswerCombinations:" + i + ":Label']");
+ if (row && !row.is(':visible') && labelInput.val() !== removeLabel) {
+ if(addCount != 0){
+ itemCount++;
+ labelInput.val(itemCount);
+ labelInput.trigger('change');
+ emiVisibleItems.val(itemCount);
+ row.parent().parent().show();
+ addCount--;
+ }else{
+ availibleItems++;
+ }
+ }
+ else if (row && row.is(':visible')) {
+ itemCount++;
+ labelInput.val(itemCount);
+ labelInput.trigger('change');
+ emiVisibleItems.val(itemCount);
+ }
+ if(row){
+ totalCount++;
+ }
+ }
+ setContainerHeight();
+ updateAddEmiItemsCount(itemCount, availibleItems, totalCount);
+ return false;
+ });
+
+ //------------------------------------------//
+ // updateAddEmiItemsCount //
+ // This function will update the //
+ // addEmiQuestionAnswerCombinationsSelect //
+ // with the correct number of items //
+ //------------------------------------------//
+ //var itemCountParam = $("")
+ function updateAddEmiItemsCount(itemCount, availibleItems, totalCount){
+ var currentItems = +emiVisibleItems.val();
+ if(!availibleItems){
+ availibleItems = highestItemId - currentItems + 1;
+ }
+
+ if (availibleItems==0) {
+ emiItemAddLink.hide();
+ addEmiItemSelect.hide();
+ }else{
+ emiItemAddLink.show();
+ addEmiItemSelect.show();
+ }
+
+ addEmiItemSelect.empty();
+ for (j=1; j<=availibleItems; j++) {
+ if (j == 1) {
+ addEmiItemSelect.append('');
+ }
+ else {
+ addEmiItemSelect.append('');
+ }
+ }
+ }
+
+ //--------------------------------------------------------------//
+ // CorrectOptionsLabels, RequiredOptionsCount and ItemPoints //
+ // This looks at the correctOptionLabels and then set the //
+ // number of select options on the requiredOptionsCount //
+ // select. //
+ // It also looks at the requiredOptionsCount and update the //
+ // item point value. //
+ // Also add a validator to the CorrectOptionsLabels fields //
+ // so only valid options can be entered //
+ //--------------------------------------------------------------//
+ var all_option = $("input[id=all]").val();
+ for (i=0; i<=highestItemId; i++) {
+ var emiCorrectOptionLabelsInput = $("input[id='itemForm:emiQuestionAnswerCombinations:" + i + ":correctOptionLabels']");
+ var requiredOptionsCountSelect = $("select[id='itemForm:emiQuestionAnswerCombinations:" + i + ":requiredOptionsCount']");
+ var itemScoreInput = $("input[id='itemForm:emiQuestionAnswerCombinations:" + i + ":itemScore']");
+ if (emiCorrectOptionLabelsInput==null) break;
+ //update required select
+ emiCorrectOptionLabelsInput.bind('change', function() {
+ var itemId = +($(this).attr("id").split(":")[2]);
+ requiredOptionsCountSelect = $("select[id='itemForm:emiQuestionAnswerCombinations:" + itemId + ":requiredOptionsCount']");
+ var currentSelection = requiredOptionsCountSelect.val();
+
+ var correctOpts = $(this).val().toUpperCase();
+ var maxOptions = +0;
+ for (var iMax=0; iMax' + all_option + '');
+ }else{
+ for (j=1; j<=maxOptions; j++) {//Note: here was a +3, not sure why?
+ var optionTag = '';
+ requiredOptionsCountSelect.append(optionTag);
+ }
+ }
+ //set score
+ if(currentSelection == 0 || currentSelection > maxOptions){
+ setItemScore(itemId, maxOptions);
+ }else{
+ setItemScore(itemId, currentSelection);
+ }
+ return false;
+ });
+ emiCorrectOptionLabelsInput.trigger('change');
+ //update item point value
+ requiredOptionsCountSelect.bind('change', function() {
+ var itemId = +($(this).attr("id").split(":")[2]);
+ if($(this).val() == 0){
+ setItemScore(itemId, $("input[id='itemForm:emiQuestionAnswerCombinations:" + itemId + ":correctOptionLabels']").val().length);
+ }else{
+ setItemScore(itemId, $(this).val());
+ }
+ });
+ //update overall score
+ itemScoreInput.keyup(function(event) {
+ updateAnswerPointScore();
+ });
+ itemScoreInput.keypress(function(event){
+ var itemId = +($(this).attr("id").split(":")[2]);
+ $("input[id='itemForm:emiQuestionAnswerCombinations:" + itemId + ":itemScoreUserSet']").val(true);
+ });
+
+ //------------------------------------------//
+ // Correct Option Labels //
+ // This does frontend validation for the //
+ // correct options labels entered //
+ //------------------------------------------//
+ emiCorrectOptionLabelsInput.keypress(function(event) {
+ return checkEMIOptions($(this).context, ANSWER_OPTION_LABELS.substring(0,currentOptions), event);
+ });
+ }
+
+ function setItemScore(itemId, score){
+ var itemScoreUserSet = $("input[id='itemForm:emiQuestionAnswerCombinations:" + itemId + ":itemScoreUserSet']").val();
+ var itemScoreInput = $("input[id='itemForm:emiQuestionAnswerCombinations:" + itemId + ":itemScore']");
+ if(itemScoreUserSet === "true"){
+ //don't override value, use the user value
+ score = itemScoreInput.val();
+ // trim ".0" from the end
+ if(score.length > 2 && (score.lastIndexOf("0") == score.length-1 && score.lastIndexOf(".") == score.length-2)){
+ score = score.substring(0, score.length-2);
+ }
+
+ }
+ itemScoreInput.val(score);
+ updateAnswerPointScore();
+ }
+
+ function updateAnswerPointScore(){
+ var total = 0;
+ for (j=0; j<=highestItemId; j++) {
+ var row = $("table[id='itemForm:emiQuestionAnswerCombinations:" + j + ":Row']");
+ if (row && row.is(':visible')){
+ total += parseFloat($("input[id='itemForm:emiQuestionAnswerCombinations:" + j + ":itemScore']").val());
+ }
+ }
+ if(!inReadyCall){
+ $("input[name='itemForm:answerptr']").val(total);
+ }
+ }
+
+ //--------------------------------------//
+ // Answer Combination Labels //
+ // Updates the span showning the //
+ // Answer Combination Label //
+ //--------------------------------------//
+ for (j=0; j<=highestItemId; j++) {
+ var labelInput = $("input[id='itemForm:emiQuestionAnswerCombinations:" + j + ":Label']");
+ labelInput.bind('change', function() {
+ $(this).parent().children("span[id='showItemLabel']").html($(this).val());
+ });
+ labelInput.trigger('change');
+ }
+
+ //Make the container visible after all processing
+ $("div[id=portletContent]").css('display','block');
+
+ function setContainerHeight() {
+ var containerFrame = $("iframe[class='portletMainIframe']", parent.document.body);
+ containerFrame.height($(document.body).height() + 30);
+ }
+ inReadyCall = false;
+});
Index: samigo-app/src/webapp/js/authoring.js
===================================================================
--- samigo-app/src/webapp/js/authoring.js (revision 133459)
+++ samigo-app/src/webapp/js/authoring.js (working copy)
@@ -57,7 +57,6 @@
*
*/
-
var checkflag = "false";
function checkAll(field) {
@@ -212,6 +211,28 @@
document.links[newindex].onclick();
}
+function clickAddEmiAnswerOptionsLink(){
+ var newindex = 0;
+ for (i=0; i=0){
+ newindex = i;
+ break;
+ }
+ }
+ document.links[newindex].onclick();
+}
+
+function clickAddEmiQuestionAnswerCombinationsLink(){
+ var newindex = 0;
+ for (i=0; i=0){
+ newindex = i;
+ break;
+ }
+ }
+ document.links[newindex].onclick();
+}
+
function countNum(){
var spanList= document.getElementsByTagName("SPAN");
var count=1;
@@ -297,7 +318,7 @@
// hide the match if needed
$pulldownHolder.change();
-};
+}
//consolidate common used functions here for assessment settings
//improve feedback UI, get rid of page reload bugid:5574 -Qu 10/31/2013
Index: samigo-app/src/webapp/js/jquery.alerts-1.1.js
===================================================================
--- samigo-app/src/webapp/js/jquery.alerts-1.1.js (revision 0)
+++ samigo-app/src/webapp/js/jquery.alerts-1.1.js (working copy)
@@ -0,0 +1,238 @@
+// jQuery Alert Dialogs Plugin
+//
+// Version 1.1
+//
+// Cory S.N. LaViska
+// A Beautiful Site (http://abeautifulsite.net/)
+// 14 May 2009
+//
+// Visit http://abeautifulsite.net/notebook/87 for more information
+//
+// Usage:
+// jAlert( message, [title, callback] )
+// jConfirm( message, [title, callback] )
+// jPrompt( message, [value, title, callback] )
+//
+// History:
+//
+// 1.00 - Released (29 December 2008)
+//
+// 1.01 - Fixed bug where unbinding would destroy all resize events
+//
+// License:
+//
+// This plugin is dual-licensed under the GNU General Public License and the MIT License and
+// is copyright 2008 A Beautiful Site, LLC.
+//
+(function($) {
+
+ $.alerts = {
+
+ // These properties can be read/written by accessing $.alerts.propertyName from your scripts at any time
+
+ verticalOffset: -75, // vertical offset of the dialog from center screen, in pixels
+ horizontalOffset: 0, // horizontal offset of the dialog from center screen, in pixels/
+ repositionOnResize: true, // re-centers the dialog on window resize
+ overlayOpacity: .01, // transparency level of overlay
+ overlayColor: '#FFF', // base color of overlay
+ draggable: true, // make the dialogs draggable (requires UI Draggables plugin)
+ okButton: ' OK ', // text for the OK button
+ cancelButton: ' Cancel ', // text for the Cancel button
+ dialogClass: null, // if specified, this class will be applied to all dialogs
+
+ // Public methods
+
+ alert: function(message, title, callback, image) {
+ if( title == null ) title = 'Alert';
+ if( image == null ) image = 'alert';
+ $.alerts._show(title, message, null, 'alert', image, function(result) {
+ if( callback ) callback(result);
+ });
+ },
+
+ confirm: function(message, title, callback, image) {
+ if( title == null ) title = 'Confirm';
+ if( image == null ) image = 'confirm';
+ $.alerts._show(title, message, null, 'confirm', image, function(result) {
+ if( callback ) callback(result);
+ });
+ },
+
+ prompt: function(message, value, title, callback, image) {
+ if( title == null ) title = 'Prompt';
+ if( image == null ) image = 'prompt';
+ $.alerts._show(title, message, value, 'prompt', image, function(result) {
+ if( callback ) callback(result);
+ });
+ },
+
+ // Private methods
+
+ _show: function(title, msg, value, type, imageType, callback) {
+
+ $.alerts._hide();
+ $.alerts._overlay('show');
+
+ $("BODY").append(
+ '