/**
* OLAT - Online Learning and Training<br>
* http://www.olat.org
* <p>
* Licensed under the Apache License, Version 2.0 (the "License"); <br>
* you may not use this file except in compliance with the License.<br>
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing,<br>
* software distributed under the License is distributed on an "AS IS" BASIS, <br>
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br>
* See the License for the specific language governing permissions and <br>
* limitations under the License.
* <p>
* Copyright (c) since 2004 at Multimedia- & E-Learning Services (MELS),<br>
* University of Zurich, Switzerland.
* <p>
*/
package org.olat.course.nodes.iq;
import java.util.Date;
import org.olat.core.gui.components.form.Form;
import org.olat.core.gui.formelements.DateElement;
import org.olat.core.gui.formelements.RadioButtonGroupElement;
import org.olat.core.gui.formelements.StaticSingleSelectionElement;
import org.olat.core.gui.formelements.TitleElement;
import org.olat.core.gui.formelements.VisibilityDependsOnSelectionRule;
import org.olat.core.gui.translator.Translator;
import org.olat.ims.qti.process.AssessmentInstance;
import org.olat.modules.ModuleConfiguration;
/**
* Test configuration form.
* Used for configuring Test, Self-test, and Questionnaire(aka Survey).
* <p>
* Initial Date: Mar 3, 2004
*
* @author Mike Stock
*/
public class IQEditForm extends Form {
private RadioButtonGroupElement enableMenu;
private RadioButtonGroupElement displayMenu;
private RadioButtonGroupElement displayScoreProgress;
private RadioButtonGroupElement displayQuestionProgress;
private RadioButtonGroupElement displayQuestionTitle;
private StaticSingleSelectionElement sequence;
private RadioButtonGroupElement enableCancel;
private RadioButtonGroupElement enableSuspend;
private StaticSingleSelectionElement summary;
private StaticSingleSelectionElement attempts;
private StaticSingleSelectionElement menuRenderOptions;
private RadioButtonGroupElement scoreInfo;
private RadioButtonGroupElement showResultsDateDependentButton;
private DateElement startDateElement;
private DateElement endDateElement;
private RadioButtonGroupElement showResultsAfterFinishTest;
private RadioButtonGroupElement showResultsOnHomePage;
/**
* Constructor for the qti configuration form
* @param name
* @param translator
* @param modConfig
*/
public IQEditForm(String name, Translator translator, ModuleConfiguration modConfig) {
super(name, translator);
String[] yesnoKeys = { "y", "n" };
String[] yesnoValues = { translate("yes"), translate("no") };
String configKeyType = (String)modConfig.get(IQEditController.CONFIG_KEY_TYPE);
TitleElement testTitle = new TitleElement("qti.form.test.title");
if(configKeyType != null && AssessmentInstance.QMD_ENTRY_TYPE_SURVEY.equals(configKeyType)) {
testTitle = new TitleElement("qti.form.questionnaire.title");
} else if(configKeyType != null && AssessmentInstance.QMD_ENTRY_TYPE_SELF.equals(configKeyType)) {
testTitle = new TitleElement("qti.form.selftest.title");
}
addFormElement("testTitle", testTitle);
// enable menu
Boolean bEnableMenu = (Boolean)modConfig.get(IQEditController.CONFIG_KEY_ENABLEMENU);
boolean confEnableMenu = (bEnableMenu != null) ? bEnableMenu.booleanValue() : true;
enableMenu = new RadioButtonGroupElement(false, "qti.form.menuenable", yesnoKeys, yesnoValues);
enableMenu.select(confEnableMenu ? "y" : "n", true);
addFormElement("qti_enableMenu", enableMenu);
// display menu
Boolean bDisplayMenu = (Boolean)modConfig.get(IQEditController.CONFIG_KEY_DISPLAYMENU);
boolean confDisplayMenu = (bDisplayMenu != null) ? bDisplayMenu.booleanValue() : true;
displayMenu = new RadioButtonGroupElement(false, "qti.form.menudisplay", yesnoKeys, yesnoValues);
displayMenu.select(confDisplayMenu ? "y" : "n", true);
addFormElement("qti_displayMenu", displayMenu);
// render menu options depend on disabled menu link!
String[] menuRenderOptKeys = new String[] {Boolean.FALSE.toString(), Boolean.TRUE.toString()};
String[] menuRenderOptValues = new String[] {
translate("qti.form.menurender.allquestions"),
translate("qti.form.menurender.sectionsonly")
};
menuRenderOptions = new StaticSingleSelectionElement("qti.form.menurender",menuRenderOptKeys,menuRenderOptValues);
Boolean renderSectionsOnly;
if (modConfig.get(IQEditController.CONFIG_KEY_RENDERMENUOPTION) == null) {
// migration
modConfig.set(IQEditController.CONFIG_KEY_RENDERMENUOPTION, Boolean.FALSE);
renderSectionsOnly = Boolean.FALSE;
} else {
renderSectionsOnly = (Boolean)modConfig.get(IQEditController.CONFIG_KEY_RENDERMENUOPTION);
}
menuRenderOptions.select(renderSectionsOnly.toString(), true);
addFormElement("qti_form_menurenderoption", menuRenderOptions);
// sequence type
String[] sequenceKeys = new String[] {AssessmentInstance.QMD_ENTRY_SEQUENCE_ITEM, AssessmentInstance.QMD_ENTRY_SEQUENCE_SECTION};
String[] sequenceValues = new String[] {
translate("qti.form.sequence.item"),
translate("qti.form.sequence.section")};
sequence = new StaticSingleSelectionElement("qti.form.sequence", sequenceKeys, sequenceValues);
String confSequence = (String)modConfig.get(IQEditController.CONFIG_KEY_SEQUENCE);
if (confSequence == null) confSequence = AssessmentInstance.QMD_ENTRY_SEQUENCE_ITEM;
sequence.select(confSequence, true);
addFormElement("qti_form_sequence", sequence);
// question progress
Boolean bEnableQuestionProgress = (Boolean)modConfig.get(IQEditController.CONFIG_KEY_QUESTIONPROGRESS);
boolean confEnableQuestionProgress = (bEnableQuestionProgress != null) ? bEnableQuestionProgress.booleanValue() : true;
displayQuestionProgress = new RadioButtonGroupElement(false, "qti.form.questionprogress", yesnoKeys, yesnoValues);
displayQuestionProgress.select(confEnableQuestionProgress ? "y" : "n", true);
addFormElement("qti_enableQuestionProgress", displayQuestionProgress);
VisibilityDependsOnSelectionRule displayMenuVisibilityRule = new VisibilityDependsOnSelectionRule(
enableMenu, displayMenu, "n", true, "y", true);
addVisibilityDependsOnSelectionRule(displayMenuVisibilityRule);
VisibilityDependsOnSelectionRule displayMenuRenderOptionRule = new VisibilityDependsOnSelectionRule(
enableMenu, menuRenderOptions, "y", true, Boolean.FALSE.toString(), true);
addVisibilityDependsOnSelectionRule(displayMenuRenderOptionRule);
VisibilityDependsOnSelectionRule displayQuestionVisibilityRule = new VisibilityDependsOnSelectionRule(
enableMenu, displayQuestionProgress, "n", true, "n", true);
addVisibilityDependsOnSelectionRule(displayQuestionVisibilityRule);
// question title
Boolean bDisplayQuestionTitle = (Boolean)modConfig.get(IQEditController.CONFIG_KEY_QUESTIONTITLE);
boolean confDisplayQuestionTitle = (bDisplayQuestionTitle != null) ? bDisplayQuestionTitle.booleanValue() : true;
displayQuestionTitle = new RadioButtonGroupElement(false, "qti.form.questiontitle", yesnoKeys, yesnoValues);
displayQuestionTitle.select(confDisplayQuestionTitle ? "y" : "n", true);
addFormElement("qti_displayQuestionTitle", displayQuestionTitle);
// enable cancel
Boolean bEnableCancel = (Boolean)modConfig.get(IQEditController.CONFIG_KEY_ENABLECANCEL);
boolean confEnableCancel = true;
if (bEnableCancel != null) {
// if defined use config value
confEnableCancel = bEnableCancel.booleanValue();
} else {
// undefined... migrate according to old behaviour
if (configKeyType != null && configKeyType.equals(AssessmentInstance.QMD_ENTRY_TYPE_ASSESS))
confEnableCancel = false;
}
enableCancel = new RadioButtonGroupElement(false, "qti.form.enablecancel", yesnoKeys, yesnoValues);
enableCancel.select(confEnableCancel ? "y" : "n", true);
addFormElement("qti_enableCancel", enableCancel);
// enable suspend
Boolean bEnableSuspend = (Boolean)modConfig.get(IQEditController.CONFIG_KEY_ENABLESUSPEND);
boolean confEnableSuspend = (bEnableSuspend != null) ? bEnableSuspend.booleanValue() : false;
enableSuspend = new RadioButtonGroupElement(false, "qti.form.enablesuspend", yesnoKeys, yesnoValues);
enableSuspend.select(confEnableSuspend ? "y" : "n", true);
addFormElement("qti_enableSuspend", enableSuspend);
// Only tests have a limitation on number of attempts
if (configKeyType != null && configKeyType.equals(AssessmentInstance.QMD_ENTRY_TYPE_ASSESS) ) {
String[] attemptsKeys = new String[21];
attemptsKeys[0] = "0"; // position 0 means no restriction
for (int i = 1; i < 21; i++) {
attemptsKeys[i] = (String.valueOf(i));
}
String[] attemptsValues = new String[21];
attemptsValues[0] = translate("qti.form.attempts.noLimit");
for (int i = 1; i < 21; i++) {
attemptsValues[i] = (String.valueOf(i) + " x");
}
attempts = new StaticSingleSelectionElement("qti.form.attempts", attemptsKeys, attemptsValues);
Integer confAttempts = (Integer) modConfig.get(IQEditController.CONFIG_KEY_ATTEMPTS);
if (confAttempts == null) confAttempts = new Integer(0);
attempts.select(confAttempts.toString(), true);
addFormElement("qti_form_attempts", attempts);
}
// score progress
if (configKeyType != null && !configKeyType.equals(AssessmentInstance.QMD_ENTRY_TYPE_SURVEY)) {
//results options section
TitleElement resultTitle = new TitleElement("qti.form.result.title");
addFormElement("resultTitle", resultTitle);
Boolean bEnableScoreProgress = (Boolean)modConfig.get(IQEditController.CONFIG_KEY_SCOREPROGRESS);
boolean confEnableScoreProgress = (bEnableScoreProgress != null) ? bEnableScoreProgress.booleanValue() : true;
displayScoreProgress = new RadioButtonGroupElement(false, "qti.form.scoreprogress", yesnoKeys, yesnoValues);
displayScoreProgress.select(confEnableScoreProgress ? "y" : "n", true);
addFormElement("qti_enableScoreProgress", displayScoreProgress);
//Show score infos on start page
Boolean bEnableScoreInfos = (Boolean)modConfig.get(IQEditController.CONFIG_KEY_ENABLESCOREINFO);
boolean enableScoreInfos = (bEnableScoreInfos != null) ? bEnableScoreInfos.booleanValue() : true;
scoreInfo = new RadioButtonGroupElement(false, "qti.form.scoreinfo", yesnoKeys, yesnoValues);
scoreInfo.select(enableScoreInfos ? "y" : "n", true);
addFormElement("qti_scoreInfo", scoreInfo);
//migration: check if old tests have no summary
String configuredSummary = (String) modConfig.get(IQEditController.CONFIG_KEY_SUMMARY);
boolean noSummary = configuredSummary!=null && configuredSummary.equals(AssessmentInstance.QMD_ENTRY_SUMMARY_NONE) ? true : false;
//show results after finish (submit) test
Boolean showResultOnFinish = (Boolean) modConfig.get(IQEditController.CONFIG_KEY_RESULT_ON_FINISH);
boolean confEnableShowResultOnFinish = (showResultOnFinish != null) ? showResultOnFinish.booleanValue() : true;
confEnableShowResultOnFinish = !noSummary && confEnableShowResultOnFinish;
showResultsAfterFinishTest = new RadioButtonGroupElement(false, "qti.form.results.onfinish", yesnoKeys, yesnoValues);
showResultsAfterFinishTest.select(confEnableShowResultOnFinish ? "y" : "n", true);
addFormElement("qti_enableResultsOnFinish", showResultsAfterFinishTest);
// show results on test home page
Boolean showResultOnHomePage = (Boolean) modConfig.get(IQEditController.CONFIG_KEY_RESULT_ON_HOME_PAGE);
boolean confEnableShowResultOnHomePage = (showResultOnHomePage != null) ? showResultOnHomePage.booleanValue() : false;
confEnableShowResultOnHomePage = !noSummary && confEnableShowResultOnHomePage;
showResultsOnHomePage = new RadioButtonGroupElement(false, "qti.form.results.onhomepage", yesnoKeys, yesnoValues);
showResultsOnHomePage.select(confEnableShowResultOnHomePage ? "y" : "n", true);
addFormElement("qti_enableResultsOnHomePage", showResultsOnHomePage);
// enable show results depending on date only the "show results on test
// home page" is true
Boolean showResultsActive = (Boolean) modConfig.get(IQEditController.CONFIG_KEY_DATE_DEPENDENT_RESULTS);
boolean showResultsDateDependent = false; // default false
if (showResultsActive != null) {
// if defined use config value
showResultsDateDependent = showResultsActive.booleanValue();
}
showResultsDateDependentButton = new RadioButtonGroupElement(false, "qti.form.show.results", yesnoKeys, yesnoValues);
showResultsDateDependentButton.select(showResultsDateDependent ? "y" : "n", true);
addFormElement("qti_showresult", showResultsDateDependentButton);
// start date
Date startDate = (Date) modConfig.get(IQEditController.CONFIG_KEY_RESULTS_START_DATE);
startDateElement = new DateElement("qti.form.date.start", startDate, "dd.MM.yyyy HH:mm");
startDateElement.setMandatory(showResultsDateDependent);
startDateElement.setDateChooserTimeEnabled(true);
startDateElement.setDateChooserDateFormat("%d.%m.%Y %H:%M");
startDateElement.setExample(startDateElement.getExample());
addFormElement("qti.form.date.start", startDateElement);
// end date
Date endDate = (Date) modConfig.get(IQEditController.CONFIG_KEY_RESULTS_END_DATE);
endDateElement = new DateElement("qti.form.date.end", endDate, "dd.MM.yyyy HH:mm");
// endDateElement.setMandatory(showResultsDateDependent);
endDateElement.setDateChooserTimeEnabled(true);
endDateElement.setDateChooserDateFormat("%d.%m.%Y %H:%M");
endDateElement.setExample(endDateElement.getExample());
addFormElement("qti.form.date.end", endDateElement);
// hide showResultsOnHomePage if the results must not be shown on the test
// home page
VisibilityDependsOnSelectionRule showResultOnHomePageVisibilityRule1 = new VisibilityDependsOnSelectionRule(showResultsOnHomePage,
showResultsDateDependentButton, "n", false, "n", true);
addVisibilityDependsOnSelectionRule(showResultOnHomePageVisibilityRule1);
VisibilityDependsOnSelectionRule showResultOnHomePageVisibilityRule2 = new VisibilityDependsOnSelectionRule(showResultsOnHomePage,
startDateElement, "n", false, "", true);
addVisibilityDependsOnSelectionRule(showResultOnHomePageVisibilityRule2);
VisibilityDependsOnSelectionRule showResultOnHomePageVisibilityRule3 = new VisibilityDependsOnSelectionRule(showResultsOnHomePage,
endDateElement, "n", false, "", true);
addVisibilityDependsOnSelectionRule(showResultOnHomePageVisibilityRule3);
// hide start/end date element if show results is not date dependent
VisibilityDependsOnSelectionRule startDateVisibilityRule = new VisibilityDependsOnSelectionRule(showResultsDateDependentButton,
startDateElement, "n", false, "", true);
addVisibilityDependsOnSelectionRule(startDateVisibilityRule);
VisibilityDependsOnSelectionRule endDateVisibilityRule = new VisibilityDependsOnSelectionRule(showResultsDateDependentButton,
endDateElement, "n", false, "", true);
addVisibilityDependsOnSelectionRule(endDateVisibilityRule);
//TODO: LD: hide summary if no results are shown neither on finish test nor on test home page
// Only tests and selftests have summaries
if (configKeyType != null && !configKeyType.equals(AssessmentInstance.QMD_ENTRY_TYPE_SURVEY)) {
String[] summaryKeys = new String[] { AssessmentInstance.QMD_ENTRY_SUMMARY_COMPACT, AssessmentInstance.QMD_ENTRY_SUMMARY_SECTION,
AssessmentInstance.QMD_ENTRY_SUMMARY_DETAILED };
String[] summaryValues = new String[] { translate("qti.form.summary.compact"), translate("qti.form.summary.section"),
translate("qti.form.summary.detailed") };
summary = new StaticSingleSelectionElement("qti.form.summary", summaryKeys, summaryValues);
String confSummary = (String) modConfig.get(IQEditController.CONFIG_KEY_SUMMARY);
if (confSummary == null || noSummary) confSummary = AssessmentInstance.QMD_ENTRY_SUMMARY_COMPACT;
summary.select(confSummary, true);
addFormElement("qti_form_summary", summary);
}
}
addSubmitKey("submit");
}
/**
* Make sure that if the results are date dependent the start date is valid and not empty and the
* end date is valid, after the start date, or empty.
* @see org.olat.core.gui.components.Form#validate(org.olat.core.gui.UserRequest)
*/
public boolean validate() {
boolean valid = true;
if (showResultsDateDependentButton != null) {
String selectedKey = showResultsDateDependentButton.getSelectedKey();
if (selectedKey.equals("y")) {
valid = valid && startDateElement.notEmpty("qti.form.date.start.error.mandatory");
if (!valid) return false;
if (startDateElement.getDate() == null) {
startDateElement.setErrorKey("qti.form.date.error.format");
return false;
}
if (!endDateElement.getValue().equals("") && endDateElement.getDate() == null) {
endDateElement.setErrorKey("qti.form.date.error.format");
return false;
}
if (endDateElement.getDate() != null && endDateElement.getDate().before(startDateElement.getDate())) {
endDateElement.setErrorKey("qti.form.date.error.endbeforebegin");
return false;
}
}
}
if (showResultsAfterFinishTest != null && showResultsOnHomePage != null) {
if (showResultsAfterFinishTest.getSelectedKey().equals("n") && showResultsOnHomePage.getSelectedKey().equals("n")) {
summary.setReadOnly(true);
} else {
summary.setReadOnly(false);
}
}
if(displayMenu.getSelectedKey().equals("n")) {
menuRenderOptions.setReadOnly(true);
} else {
menuRenderOptions.setReadOnly(false);
}
return true;
}
/**
* @return true: menu is enabled
*/
public boolean isEnableMenu() { return enableMenu.getSelectedKey().equals("y"); }
/**
* @return true: menu should be displayed
*/
public boolean isDisplayMenu() { return displayMenu.getSelectedKey().equals("y"); }
/**
* @return true: score progress is enabled
*/
public boolean isDisplayScoreProgress() { return displayScoreProgress.getSelectedKey().equals("y"); }
/**
* @return true: score progress is enabled
*/
public boolean isDisplayQuestionProgress() { return displayQuestionProgress.getSelectedKey().equals("y"); }
/**
* @return true: question title is enabled
*/
public boolean isDisplayQuestionTitle() { return displayQuestionTitle.getSelectedKey().equals("y"); }
/**
* @return sequence configuration: section or item
*/
public String getSequence() { return sequence.getSelectedKey(); }
/**
* @return true: cancel is enabled
*/
public boolean isEnableCancel() { return enableCancel.getSelectedKey().equals("y"); }
/**
* @return true: suspend is enabled
*/
public boolean isEnableSuspend() { return enableSuspend.getSelectedKey().equals("y"); }
/**
* @return summary type: compact or detailed
*/
public String getSummary() { return summary.getSelectedKey(); }
/**
* @return number of max attempts
*/
public Integer getAttempts() {
if (attempts.getSelectedKey().equals("0")){
return null;
}
return Integer.valueOf(attempts.getSelectedKey());
}
/**
*
* @return true if only section title should be rendered
*/
public Boolean isMenuRenderSectionsOnly() {
return Boolean.valueOf(menuRenderOptions.getSelectedKey());
}
/**
* @return true: score-info on start-page is enabled
*/
public boolean isEnableScoreInfo() {
if(scoreInfo!=null) {
return scoreInfo.getSelectedKey().equals("y");
}
return false;
}
/**
*
* @return true is the results are shown date dependent
*/
public boolean isShowResultsDateDependent() {
if(showResultsDateDependentButton!=null) {
return showResultsDateDependentButton.getSelectedKey().equals("y");
}
return false;
}
/**
*
* @return Returns the start date for the result visibility.
*/
public Date getShowResultsStartDate() {
if(startDateElement!=null) {
return startDateElement.getDate();
}
return null;
}
/**
*
* @return Returns the end date for the result visibility.
*/
public Date getShowResultsEndDate() {
if(endDateElement!=null) {
return endDateElement.getDate();
}
return null;
}
/**
*
* @return Returns true if the results are shown after test finished.
*/
public boolean isShowResultsAfterFinishTest() {
if(showResultsAfterFinishTest!=null) {
return showResultsAfterFinishTest.getSelectedKey().equals("y");
}
return false;
}
/**
*
* @return Returns true if the results are shown on the test home page.
*/
public boolean isShowResultsOnHomePage() {
if(showResultsOnHomePage!=null) {
return showResultsOnHomePage.getSelectedKey().equals("y");
}
return false;
}
}