/**
* <a href="http://www.openolat.org">
* OpenOLAT - Online Learning and Training</a><br>
* <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 the
* <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a>
* <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>
* Initial code contributed and copyrighted by<br>
* frentix GmbH, http://www.frentix.com
* <p>
*/
package org.olat.course.nodes.iq;
import java.io.File;
import java.util.Date;
import org.olat.core.gui.UserRequest;
import org.olat.core.gui.components.form.flexible.FormItem;
import org.olat.core.gui.components.form.flexible.FormItemContainer;
import org.olat.core.gui.components.form.flexible.elements.DateChooser;
import org.olat.core.gui.components.form.flexible.elements.MultipleSelectionElement;
import org.olat.core.gui.components.form.flexible.elements.SelectionElement;
import org.olat.core.gui.components.form.flexible.elements.SingleSelection;
import org.olat.core.gui.components.form.flexible.elements.StaticTextElement;
import org.olat.core.gui.components.form.flexible.impl.FormBasicController;
import org.olat.core.gui.components.form.flexible.impl.FormEvent;
import org.olat.core.gui.control.Controller;
import org.olat.core.gui.control.Event;
import org.olat.core.gui.control.WindowControl;
import org.olat.course.assessment.AssessmentHelper;
import org.olat.fileresource.FileResourceManager;
import org.olat.ims.qti.process.AssessmentInstance;
import org.olat.ims.qti21.QTI21AssessmentResultsOptions;
import org.olat.ims.qti21.QTI21DeliveryOptions;
import org.olat.ims.qti21.QTI21Service;
import org.olat.ims.qti21.model.xml.AssessmentTestBuilder;
import org.olat.modules.ModuleConfiguration;
import org.olat.repository.RepositoryEntry;
import org.springframework.beans.factory.annotation.Autowired;
import uk.ac.ed.ph.jqtiplus.node.test.AssessmentTest;
import uk.ac.ed.ph.jqtiplus.resolution.ResolvedAssessmentTest;
/**
*
* Initial date: 26.06.2015<br>
* @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
*
*/
public class QTI21EditForm extends FormBasicController {
private static final String[] onKeys = new String[]{ "on" };
private static final String[] onValues = new String[]{ "" };
private static final String[] correctionModeKeys = new String[]{ "auto", "manual" };
private static final String[] resultsOptionsKeys = new String[] {
QTI21AssessmentResultsOptions.METADATA, QTI21AssessmentResultsOptions.SECTION_SUMMARY,
QTI21AssessmentResultsOptions.QUESTION_SUMMARY, QTI21AssessmentResultsOptions.QUESTIONS,
QTI21AssessmentResultsOptions.USER_SOLUTIONS, QTI21AssessmentResultsOptions.CORRECT_SOLUTIONS
};
private SingleSelection correctionModeEl;
private SelectionElement showResultsOnHomePage;
private SelectionElement scoreInfo, showResultsDateDependentButton;
private DateChooser startDateElement, endDateElement;
private StaticTextElement minScoreEl, maxScoreEl, cutValueEl;
private MultipleSelectionElement showResultsOnFinishEl, assessmentResultsOnFinishEl;
private final boolean needManualCorrection;
private final ModuleConfiguration modConfig;
private final QTI21DeliveryOptions deliveryOptions;
@Autowired
private QTI21Service qtiService;
public QTI21EditForm(UserRequest ureq, WindowControl wControl, ModuleConfiguration modConfig,
QTI21DeliveryOptions deliveryOptions, boolean needManualCorrection) {
super(ureq, wControl);
this.modConfig = modConfig;
this.deliveryOptions = (deliveryOptions == null ? new QTI21DeliveryOptions() : deliveryOptions);
this.needManualCorrection = needManualCorrection;
initForm(ureq);
}
@Override
protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) {
formLayout.setElementCssClass("o_qti_21_configuration");
minScoreEl = uifactory.addStaticTextElement("score.min", "", formLayout);
minScoreEl.setVisible(false);
maxScoreEl = uifactory.addStaticTextElement("score.max", "", formLayout);
maxScoreEl.setVisible(false);
cutValueEl = uifactory.addStaticTextElement("score.cut", "", formLayout);
cutValueEl.setVisible(false);
String [] correctionModeValues = new String[]{
translate("correction.auto"),
translate("correction.manual")
};
correctionModeEl = uifactory.addRadiosVertical("correction.mode", "correction.mode", formLayout, correctionModeKeys, correctionModeValues);
correctionModeEl.setHelpText(translate("correction.mode.help"));
correctionModeEl.setHelpUrlForManualPage("Test editor QTI 2.1 in detail#details_testeditor_test_konf_kurs");
String mode = modConfig.getStringValue(IQEditController.CONFIG_CORRECTION_MODE);
boolean selected = false;
for(String correctionModeKey:correctionModeKeys) {
if(correctionModeKey.equals(mode)) {
correctionModeEl.select(correctionModeKey, true);
selected = true;
}
}
if(!selected) {
if(needManualCorrection) {
correctionModeEl.select(correctionModeKeys[1], true);
} else {
correctionModeEl.select(correctionModeKeys[0], true);
}
}
//Show score informations on start page
boolean enableScoreInfos = modConfig.getBooleanSafe(IQEditController.CONFIG_KEY_ENABLESCOREINFO);
scoreInfo = uifactory.addCheckboxesHorizontal("qti_scoreInfo", "qti.form.scoreinfo", formLayout, new String[]{"xx"}, new String[]{null});
scoreInfo.select("xx", enableScoreInfos);
scoreInfo.addActionListener(FormEvent.ONCLICK);
boolean showResultOnHomePage = modConfig.getBooleanSafe(IQEditController.CONFIG_KEY_RESULT_ON_HOME_PAGE);
showResultsOnHomePage = uifactory.addCheckboxesHorizontal("qti_enableResultsOnHomePage", "qti.form.results.onhomepage", formLayout, new String[]{"xx"}, new String[]{null});
showResultsOnHomePage.select("xx", showResultOnHomePage);
showResultsOnHomePage.setElementCssClass("o_sel_results_on_homepage");
showResultsOnHomePage.addActionListener(FormEvent.ONCLICK);
boolean showResultsDateDependent = modConfig.getBooleanSafe(IQEditController.CONFIG_KEY_DATE_DEPENDENT_RESULTS);
showResultsDateDependentButton = uifactory.addCheckboxesHorizontal("qti_showresult", "qti.form.show.results", formLayout, new String[]{"xx"}, new String[]{null});
showResultsDateDependentButton.select("xx", showResultsDateDependent);
showResultsDateDependentButton.addActionListener(FormEvent.ONCLICK);
Date startDate = modConfig.getDateValue(IQEditController.CONFIG_KEY_RESULTS_START_DATE);
startDateElement = uifactory.addDateChooser("qti_form_start_date", "qti.form.date.start", null, formLayout);
startDateElement.setDateChooserTimeEnabled(true);
startDateElement.setDate(startDate);
startDateElement.setMandatory(true);
Date endDate = modConfig.getDateValue(IQEditController.CONFIG_KEY_RESULTS_END_DATE);
endDateElement = uifactory.addDateChooser("qti_form_end_date", "qti.form.date.end", null, formLayout);
endDateElement.setDateChooserTimeEnabled(true);
endDateElement.setDate(endDate);
boolean configRef = modConfig.getBooleanSafe(IQEditController.CONFIG_KEY_CONFIG_REF, false);
QTI21AssessmentResultsOptions resultsOptions = configRef ? deliveryOptions.getAssessmentResultsOptions()
: QTI21AssessmentResultsOptions.parseString(modConfig.getStringValue(IQEditController.CONFIG_KEY_SUMMARY, AssessmentInstance.QMD_ENTRY_SUMMARY_COMPACT));
showResultsOnFinishEl = uifactory.addCheckboxesHorizontal("resultOnFinish", "qti.form.results.onfinish", formLayout, onKeys, onValues);
showResultsOnFinishEl.setElementCssClass("o_sel_qti_show_results");
showResultsOnFinishEl.addActionListener(FormEvent.ONCHANGE);
showResultsOnFinishEl.setEnabled(!configRef);
showResultsOnFinishEl.setHelpText(translate("qti.form.results.onfinish.help"));
String[] resultsOptionsValues = new String[] {
translate("qti.form.summary.metadata"), translate("qti.form.summary.sections"),
translate("qti.form.summary.questions.metadata"), translate("qti.form.summary.questions"),
translate("qti.form.summary.responses"), translate("qti.form.summary.solutions")
};
assessmentResultsOnFinishEl = uifactory.addCheckboxesVertical("typeResultOnFinish", "qti.form.summary", formLayout, resultsOptionsKeys, resultsOptionsValues, 1);
assessmentResultsOnFinishEl.setElementCssClass("o_sel_qti_show_results_options");
assessmentResultsOnFinishEl.setEnabled(!configRef);
assessmentResultsOnFinishEl.setHelpText(translate("qti.form.summary.help"));
assessmentResultsOnFinishEl.setHelpUrlForManualPage("Test editor QTI 2.1 in detail#overview_results");
if(!resultsOptions.none()) {
showResultsOnFinishEl.select(onKeys[0], true);
assessmentResultsOnFinishEl.uncheckAll();
if(resultsOptions.isMetadata()) {
assessmentResultsOnFinishEl.select(resultsOptionsKeys[0], true);
}
if(resultsOptions.isSectionSummary()) {
assessmentResultsOnFinishEl.select(resultsOptionsKeys[1], true);
}
if(resultsOptions.isQuestionSummary()) {
assessmentResultsOnFinishEl.select(resultsOptionsKeys[2], true);
}
if(resultsOptions.isQuestions()) {
assessmentResultsOnFinishEl.select(resultsOptionsKeys[3], true);
}
if(resultsOptions.isUserSolutions()) {
assessmentResultsOnFinishEl.select(resultsOptionsKeys[4], true);
}
if(resultsOptions.isCorrectSolutions()) {
assessmentResultsOnFinishEl.select(resultsOptionsKeys[5], true);
}
} else {
showResultsOnFinishEl.uncheckAll();
assessmentResultsOnFinishEl.uncheckAll();
}
uifactory.addFormSubmitButton("submit", formLayout);
update();
}
@Override
protected void doDispose() {
//
}
@Override
protected boolean validateFormLogic(UserRequest ureq) {
boolean allOk = true;
startDateElement.clearError();
if(showResultsDateDependentButton.isSelected(0)) {
if(startDateElement.getDate() == null) {
startDateElement.setErrorKey("form.legende.mandatory", null);
allOk &= false;
}
}
return allOk & super.validateFormLogic(ureq);
}
@Override
protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) {
if(showResultsOnFinishEl == source) {
update();
} else if(showResultsDateDependentButton == source || showResultsOnHomePage == source) {
update();
}
super.formInnerEvent(ureq, source, event);
}
private void update() {
showResultsDateDependentButton.setVisible(showResultsOnHomePage.isSelected(0));
assessmentResultsOnFinishEl.setVisible(showResultsOnFinishEl.isAtLeastSelected(1) || showResultsOnHomePage.isSelected(0));
if (!startDateElement.isVisible()) {
startDateElement.setValue("");
}
startDateElement.clearError();
startDateElement.setVisible(showResultsDateDependentButton.isVisible() && showResultsDateDependentButton.isSelected(0));
endDateElement.clearError();
if (!endDateElement.isVisible()){
endDateElement.setValue("");
}
endDateElement.setVisible(startDateElement.isVisible());
}
protected void update(RepositoryEntry testEntry) {
Double minValue = null;
Double maxValue = null;
Double cutValue = null;
FileResourceManager frm = FileResourceManager.getInstance();
File unzippedDirRoot = frm.unzipFileResource(testEntry.getOlatResource());
ResolvedAssessmentTest resolvedAssessmentTest = qtiService.loadAndResolveAssessmentTest(unzippedDirRoot, false, false);
AssessmentTest assessmentTest = resolvedAssessmentTest.getRootNodeLookup().extractIfSuccessful();
if(assessmentTest != null) {
AssessmentTestBuilder testBuilder = new AssessmentTestBuilder(assessmentTest);
maxValue = testBuilder.getMaxScore();
cutValue = testBuilder.getCutValue();
if(maxValue != null && "OpenOLAT".equals(assessmentTest.getToolName())) {
minValue = 0d;
}
}
// Put values to module configuration
minScoreEl.setValue(minValue == null ? "" : AssessmentHelper.getRoundedScore(minValue));
minScoreEl.setVisible(minValue != null);
maxScoreEl.setValue(maxValue == null ? "" : AssessmentHelper.getRoundedScore(maxValue));
maxScoreEl.setVisible(maxValue != null);
cutValueEl.setValue(cutValue == null ? "" : AssessmentHelper.getRoundedScore(cutValue));
cutValueEl.setVisible(cutValue != null);
}
@Override
protected void formOK(UserRequest ureq) {
if(correctionModeEl.isOneSelected()) {
modConfig.setStringValue(IQEditController.CONFIG_CORRECTION_MODE, correctionModeEl.getSelectedKey());
}
modConfig.setBooleanEntry(IQEditController.CONFIG_KEY_ENABLESCOREINFO, scoreInfo.isSelected(0));
modConfig.setBooleanEntry(IQEditController.CONFIG_KEY_DATE_DEPENDENT_RESULTS, showResultsDateDependentButton.isSelected(0));
modConfig.setDateValue(IQEditController.CONFIG_KEY_RESULTS_START_DATE, startDateElement.getDate());
modConfig.setDateValue(IQEditController.CONFIG_KEY_RESULTS_END_DATE, endDateElement.getDate());
modConfig.setBooleanEntry(IQEditController.CONFIG_KEY_RESULT_ON_HOME_PAGE, showResultsOnHomePage.isSelected(0));
if(showResultsOnFinishEl.isAtLeastSelected(1) || showResultsOnHomePage.isSelected(0)) {
if(assessmentResultsOnFinishEl.isAtLeastSelected(1)) {
String options = QTI21AssessmentResultsOptions.toString(assessmentResultsOnFinishEl.getSelectedKeys());
modConfig.set(IQEditController.CONFIG_KEY_SUMMARY, options);
} else {
modConfig.set(IQEditController.CONFIG_KEY_SUMMARY, AssessmentInstance.QMD_ENTRY_SUMMARY_NONE);
}
} else {
modConfig.set(IQEditController.CONFIG_KEY_SUMMARY, AssessmentInstance.QMD_ENTRY_SUMMARY_NONE);
}
fireEvent(ureq, Event.DONE_EVENT);
}
}