Skip to content
Snippets Groups Projects
Commit 62a7e2b4 authored by srosse's avatar srosse
Browse files

OO-30: show the feedback after the last question of a test

parent 3654be08
No related branches found
No related tags found
No related merge requests found
......@@ -142,14 +142,26 @@ public class DefaultNavigator implements Serializable {
* @see org.olat.qti.process.Navigator#submitAssessment()
*/
public void submitAssessment() {
Output pendingOutput = null;
boolean pendingFeedback = getInfo().isFeedback();
if(pendingFeedback && getAssessmentInstance().getAssessmentContext().getCurrentSectionContext() != null) {
ItemContext itc = getAssessmentInstance().getAssessmentContext().getCurrentSectionContext().getCurrentItemContext();
pendingOutput = itc.getOutput();
}
getAssessmentInstance().close();
AssessmentContext ac = getAssessmentContext();
info.clear();
if (ac.isFeedbackavailable()) {
Output outp = ac.getOutput();
getInfo().setCurrentOutput(outp);
getInfo().setFeedback(true);
} else if (pendingFeedback) {
getInfo().setCurrentOutput(pendingOutput);
getInfo().setFeedback(true);
}
info.clear();
//info.clear();
info.setMessage(QTIConstants.MESSAGE_ASSESSMENT_SUBMITTED);
info.setStatus(QTIConstants.ASSESSMENT_FINISHED);
info.setRenderItems(false);
......
......@@ -25,7 +25,6 @@
package org.olat.modules.iq;
import java.io.UnsupportedEncodingException;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
......@@ -116,23 +115,8 @@ public class IQComponentRenderer implements ComponentRenderer {
displayFeedback(sb, el_solution, ai, translator.getLocale());
}
// item fb?
if (info.isFeedback()) {
if (info.getCurrentOutput().hasItem_Responses()) {
int fbcount = info.getCurrentOutput().getFeedbackCount();
int i=0;
while (i < fbcount) {
Element el_anschosen = info.getCurrentOutput().getItemAnswerChosen(i);
if (el_anschosen != null) {
sb.append("<br /><br /><i>");
displayFeedback(sb, new Material(el_anschosen), ai, translator.getLocale());
sb.append("</i>");
}
Element el_resp= info.getCurrentOutput().getItemFeedback(i);
displayFeedback(sb, new ItemFeedback(el_resp), ai, translator.getLocale());
i++;
}
}
}
renderFeedback(info, sb, ai, translator);
if(!comp.getMenuDisplayConf().isEnabledMenu() && comp.getMenuDisplayConf().isItemPageSequence() && !info.isRenderItems()) {
//if item was submitted and sequence is pageSequence and menu not enabled and isRenderItems returns false show section info
SectionContext sc = ai.getAssessmentContext().getCurrentSectionContext();
......@@ -146,7 +130,11 @@ public class IQComponentRenderer implements ComponentRenderer {
if (info.isFeedback()) {
Output outp = info.getCurrentOutput();
GenericQTIElement el_feedback = outp.getEl_response();
if (el_feedback != null) displayFeedback(sb, el_feedback, ai, translator.getLocale());
if (el_feedback != null) {
displayFeedback(sb, el_feedback, ai, translator.getLocale());
} else {
renderFeedback(info, sb, ai, translator);
}
}
if(!comp.getMenuDisplayConf().isEnabledMenu() && !comp.getMenuDisplayConf().isItemPageSequence()) {
SectionContext sc = ai.getAssessmentContext().getCurrentSectionContext();
......@@ -275,11 +263,44 @@ public class IQComponentRenderer implements ComponentRenderer {
if (info.isFeedback()) {
Output outp = info.getCurrentOutput();
GenericQTIElement el_feedback = outp.getEl_response();
if (el_feedback != null) displayFeedback(sb, el_feedback, ai, null);
if (el_feedback != null) {
displayFeedback(sb, el_feedback, ai, null);
} else {
renderFeedback(info, sb, ai, translator);
//add the next button
sb.append("<a class=\"b_button\" onclick=\"return o2cl()\" href=\"");
ubu.buildURI(sb, new String[] { VelocityContainer.COMMAND_ID }, new String[] { "sitsec" });
String title = translator.translate("next");
sb.append("\" title=\"" + StringEscapeUtils.escapeHtml(title) + "\">");
sb.append("<span>").append(title).append("</title>");
sb.append("</a>");
}
}
}
return sb;
}
protected void renderFeedback(Info info, StringOutput sb, AssessmentInstance ai, Translator translator) {
if (info.isFeedback()) {
if (info.getCurrentOutput().hasItem_Responses()) {
int fbcount = info.getCurrentOutput().getFeedbackCount();
int i=0;
while (i < fbcount) {
Element el_anschosen = info.getCurrentOutput().getItemAnswerChosen(i);
if (el_anschosen != null) {
sb.append("<br /><br /><i>");
displayFeedback(sb, new Material(el_anschosen), ai, translator.getLocale());
sb.append("</i>");
}
Element el_resp= info.getCurrentOutput().getItemFeedback(i);
displayFeedback(sb, new ItemFeedback(el_resp), ai, translator.getLocale());
i++;
}
}
}
}
protected static String getFormattedLimit(long millis) {
long sSec = millis / 1000;
......
......@@ -82,9 +82,6 @@ public class IQDisplayController extends DefaultController implements Activateab
private static Logger log = Logger.getLogger(IQDisplayController.class.getName());
// used for logging
private static final String IMSQTI = "IMSQTI";
private VelocityContainer myContent;
private Translator translator;
......@@ -403,7 +400,22 @@ public class IQDisplayController extends DefaultController implements Activateab
navig.submitItems(iInp);
}
if (ai.isClosed()) { // do all the finishing stuff
event(ureq, source, new Event(QTIConstants.QTI_WF_SUBMIT));
if(navig.getInfo().isFeedback()) {
//render the feedback
} else {
event(ureq, source, new Event(QTIConstants.QTI_WF_SUBMIT));
return;
}
}
} else if (wfCommand.equals("sitsec")) { // submit
if (ai.isClosed()) { // do all the finishing stuff
if (!qtistatus.isSurvey()) {
// for test and self-assessment, generate detailed results
generateDetailsResults(ureq, ai);
} else {
// Send also finished event in case of survey
fireEvent(ureq, new IQSubmittedEvent());
}
return;
}
} else if (wfCommand.equals("sflash")) { // submit flash answer
......@@ -439,44 +451,7 @@ public class IQDisplayController extends DefaultController implements Activateab
} else if (wfCommand.equals(QTIConstants.QTI_WF_SUBMIT)) { // submit
// Assessment
navig.submitAssessment();
// Persist data in all cases: test, selftest, surveys except previews
// In case of survey, data will be anonymized when reading from the
// table (using the archiver)
if (!qtistatus.isPreview()) {
iqm.persistResults(ai, callingResId, callingResDetail, ureq);
getWindowControl().setInfo(translator.translate("status.results.saved"));
} else {
getWindowControl().setInfo(translator.translate("status.results.notsaved"));
}
if (!qtistatus.isSurvey()) { // for test and self-assessment, generate
// detailed results
Document docResReporting = iqm.getResultsReporting(ai, ureq);
if (!iqsec.isPreview()) {
FilePersister.createResultsReporting(docResReporting, ureq.getIdentity(), ai.getFormattedType(), ai.getAssessID());
// Send score and passed to parent controller. Maybe it is necessary
// to save some data there
// Do this now and not later, maybe user will never click on
// 'close'...
AssessmentContext ac = ai.getAssessmentContext();
fireEvent(ureq, new IQSubmittedEvent(ac.getScore(), ac.isPassed(), ai.getAssessID()));
}
Boolean showResultsOnFinishObj = (Boolean)modConfig.get(IQEditController.CONFIG_KEY_RESULT_ON_FINISH);
boolean showResultsOnFinish = showResultsOnFinishObj==null || showResultsOnFinishObj!=null && showResultsOnFinishObj.booleanValue();
if (ai.getSummaryType() == AssessmentInstance.SUMMARY_NONE || !showResultsOnFinish) {
// do not display results reporting
myContent.contextPut("displayreporting", Boolean.FALSE);
} else { // display results reporting
String resReporting = iqm.transformResultsReporting(docResReporting, ureq.getLocale(), ai.getSummaryType() );
myContent.contextPut("resreporting", resReporting);
myContent.contextPut("displayreporting", Boolean.TRUE);
}
myContent.setPage(VELOCITY_ROOT + "/result.html");
} else {
// Send also finished event in case of survey
fireEvent(ureq, new IQSubmittedEvent());
}
postSubmitAssessment(ureq, ai);
} else if (wfCommand.equals(QTIConstants.QTI_WF_CANCEL)) { // cancel
// assessment
navig.cancelAssessment();
......@@ -503,6 +478,55 @@ public class IQDisplayController extends DefaultController implements Activateab
return;
}
}
/**
* Persist data in all cases: test, selftest, surveys except previews
* In case of survey, data will be anonymized when reading from the
* table (using the archiver)
*/
protected void postSubmitAssessment(UserRequest ureq, AssessmentInstance ai) {
if (!qtistatus.isPreview()) {
iqm.persistResults(ai, callingResId, callingResDetail, ureq);
getWindowControl().setInfo(translator.translate("status.results.saved"));
} else {
getWindowControl().setInfo(translator.translate("status.results.notsaved"));
}
if (!qtistatus.isSurvey()) {
// for test and self-assessment, generate detailed results
generateDetailsResults(ureq, ai);
} else {
// Send also finished event in case of survey
fireEvent(ureq, new IQSubmittedEvent());
}
}
protected void generateDetailsResults(UserRequest ureq, AssessmentInstance ai) {
Document docResReporting = iqm.getResultsReporting(ai, ureq);
if (!iqsec.isPreview()) {
FilePersister.createResultsReporting(docResReporting, ureq.getIdentity(), ai.getFormattedType(), ai.getAssessID());
// Send score and passed to parent controller. Maybe it is necessary
// to save some data there
// Do this now and not later, maybe user will never click on
// 'close'...
AssessmentContext ac = ai.getAssessmentContext();
fireEvent(ureq, new IQSubmittedEvent(ac.getScore(), ac.isPassed(), ai.getAssessID()));
}
Boolean showResultsOnFinishObj = (Boolean)modConfig.get(IQEditController.CONFIG_KEY_RESULT_ON_FINISH);
boolean showResultsOnFinish = showResultsOnFinishObj==null || showResultsOnFinishObj!=null && showResultsOnFinishObj.booleanValue();
if (ai.getSummaryType() == AssessmentInstance.SUMMARY_NONE || !showResultsOnFinish) {
// do not display results reporting
myContent.contextPut("displayreporting", Boolean.FALSE);
} else { // display results reporting
String resReporting = iqm.transformResultsReporting(docResReporting, ureq.getLocale(), ai.getSummaryType() );
myContent.contextPut("resreporting", resReporting);
myContent.contextPut("displayreporting", Boolean.TRUE);
}
myContent.setPage(VELOCITY_ROOT + "/result.html");
}
/**
* @param ureq
......
......@@ -236,6 +236,10 @@ public class IQStatus {
* @return true if assessment instance is not closed
*/
public boolean isOpen() { return isOpen; }
/**
* @return true if assessment instance is not closed
*/
public boolean isClosed() { return !isOpen; }
/**
* @return true if of type survey (questionnaire)
*/
......
......@@ -187,6 +187,12 @@ function confirmSuspend() {
</div>
</div>
#elseif($qtistatus.isClosed())
<div class="b_subcr">
<div id="o_qti_run_content_inner" class="b_floatscrollbox">
$r.render("qticomp", "qtiform")
</div>
</div>
#end
</div>
</div>
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment