Skip to content
Snippets Groups Projects
Commit 88b4bf05 authored by srosse's avatar srosse
Browse files

OO-305. tightly couple the submit of the assessment results to the database and to "qti.ser"

parent eb359b91
No related branches found
No related tags found
No related merge requests found
...@@ -219,12 +219,12 @@ public class QTIResultDetailsController extends BasicController { ...@@ -219,12 +219,12 @@ public class QTIResultDetailsController extends BasicController {
AssessableCourseNode testNode = (AssessableCourseNode)course.getRunStructure().getNode(nodeIdent); AssessableCourseNode testNode = (AssessableCourseNode)course.getRunStructure().getNode(nodeIdent);
ModuleConfiguration modConfig = testNode.getModuleConfiguration(); ModuleConfiguration modConfig = testNode.getModuleConfiguration();
String resourcePathInfo = courseResourceableId + File.separator + nodeIdent; String resourcePathInfo = courseResourceableId + File.separator + nodeIdent;
AssessmentInstance ai = AssessmentFactory.createAssessmentInstance(assessedIdentity, modConfig, false ,resourcePathInfo); AssessmentInstance ai = AssessmentFactory.createAssessmentInstance(assessedIdentity, "", modConfig, false, courseResourceableId, nodeIdent, resourcePathInfo);
//close the test //close the test
ai.close(); ai.close();
//persist the results //persist the results
iqm.persistResults(ai, courseResourceableId.longValue(), nodeIdent, assessedIdentity, ""); iqm.persistResults(ai);
//reporting //reporting
Document docResReporting = iqm.getResultsReporting(ai, assessedIdentity, I18nModule.getDefaultLocale()); Document docResReporting = iqm.getResultsReporting(ai, assessedIdentity, I18nModule.getDefaultLocale());
......
...@@ -36,6 +36,7 @@ import org.olat.ims.qti.container.ItemsInput; ...@@ -36,6 +36,7 @@ import org.olat.ims.qti.container.ItemsInput;
import org.olat.ims.qti.container.Output; import org.olat.ims.qti.container.Output;
import org.olat.ims.qti.container.SectionContext; import org.olat.ims.qti.container.SectionContext;
import org.olat.ims.qti.process.AssessmentInstance; import org.olat.ims.qti.process.AssessmentInstance;
import org.olat.modules.iq.IQManager;
/** /**
*/ */
...@@ -144,12 +145,17 @@ public class DefaultNavigator implements Serializable { ...@@ -144,12 +145,17 @@ public class DefaultNavigator implements Serializable {
public void submitAssessment() { public void submitAssessment() {
Output pendingOutput = null; Output pendingOutput = null;
boolean pendingFeedback = getInfo().isFeedback(); boolean pendingFeedback = getInfo().isFeedback();
boolean alreadyClosed = getAssessmentInstance().isClosed();
if(pendingFeedback && getAssessmentInstance().getAssessmentContext().getCurrentSectionContext() != null) { if(pendingFeedback && getAssessmentInstance().getAssessmentContext().getCurrentSectionContext() != null) {
ItemContext itc = getAssessmentInstance().getAssessmentContext().getCurrentSectionContext().getCurrentItemContext(); ItemContext itc = getAssessmentInstance().getAssessmentContext().getCurrentSectionContext().getCurrentItemContext();
pendingOutput = itc.getOutput(); pendingOutput = itc.getOutput();
} }
getAssessmentInstance().close(); getAssessmentInstance().close();
if(!getAssessmentInstance().isPreview() && !alreadyClosed) {
IQManager.getInstance().persistResults(getAssessmentInstance());
}
AssessmentContext ac = getAssessmentContext(); AssessmentContext ac = getAssessmentContext();
info.clear(); info.clear();
......
...@@ -28,6 +28,7 @@ package org.olat.ims.qti.process; ...@@ -28,6 +28,7 @@ package org.olat.ims.qti.process;
import org.olat.core.id.Identity; import org.olat.core.id.Identity;
import org.olat.core.logging.Tracing; import org.olat.core.logging.Tracing;
import org.olat.core.util.CodeHelper; import org.olat.core.util.CodeHelper;
import org.olat.core.util.StringHelper;
import org.olat.course.nodes.iq.IQEditController; import org.olat.course.nodes.iq.IQEditController;
import org.olat.modules.ModuleConfiguration; import org.olat.modules.ModuleConfiguration;
import org.olat.repository.RepositoryEntry; import org.olat.repository.RepositoryEntry;
...@@ -45,7 +46,8 @@ public class AssessmentFactory { ...@@ -45,7 +46,8 @@ public class AssessmentFactory {
* @param resourcePathInfo * @param resourcePathInfo
* @return * @return
*/ */
public static AssessmentInstance createAssessmentInstance(Identity subj, ModuleConfiguration modConfig, boolean preview, String resourcePathInfo) { public static AssessmentInstance createAssessmentInstance(Identity subj, String remoteAddr, ModuleConfiguration modConfig, boolean preview,
long callingResId, String callingResDetail, String resourcePathInfo) {
AssessmentInstance ai = null; AssessmentInstance ai = null;
Persister persister = null; Persister persister = null;
...@@ -72,7 +74,7 @@ public class AssessmentFactory { ...@@ -72,7 +74,7 @@ public class AssessmentFactory {
Resolver resolver = new ImsRepositoryResolver(re.getKey()); Resolver resolver = new ImsRepositoryResolver(re.getKey());
long aiID = CodeHelper.getForeverUniqueID(); long aiID = CodeHelper.getForeverUniqueID();
try { try {
ai = new AssessmentInstance(re.getKey().longValue(), aiID, resolver, persister, modConfig); ai = new AssessmentInstance(subj, remoteAddr, re.getKey().longValue(), aiID, callingResId, callingResDetail, resolver, persister, modConfig);
} catch (Exception e) { return null; } } catch (Exception e) { return null; }
} }
else { else {
...@@ -81,6 +83,12 @@ public class AssessmentFactory { ...@@ -81,6 +83,12 @@ public class AssessmentFactory {
Resolver resolver = new ImsRepositoryResolver(new Long(ai.getRepositoryEntryKey())); Resolver resolver = new ImsRepositoryResolver(new Long(ai.getRepositoryEntryKey()));
ai.setResolver(resolver); ai.setResolver(resolver);
ai.setPersister(persister); ai.setPersister(persister);
ai.setAssessedIdentity(subj);
ai.setCallingResId(callingResId);
ai.setCallingResDetail(callingResDetail);
if(StringHelper.containsNonWhitespace(ai.getRemoteAddr())) {
ai.setRemoteAddr(remoteAddr);
}
} }
return ai; return ai;
...@@ -93,9 +101,9 @@ public class AssessmentFactory { ...@@ -93,9 +101,9 @@ public class AssessmentFactory {
* @param doc * @param doc
* @return * @return
*/ */
public static AssessmentInstance createAssessmentInstance(Resolver resolver, Persister persister, ModuleConfiguration modConfig) { public static AssessmentInstance createAssessmentInstance(Identity subj, String remoteAddr, long callingResId, String callingResDetail, Resolver resolver, Persister persister, ModuleConfiguration modConfig) {
long aiID = CodeHelper.getForeverUniqueID(); long aiID = CodeHelper.getForeverUniqueID();
return new AssessmentInstance(0, aiID, resolver, persister, modConfig); return new AssessmentInstance(null, remoteAddr, 0, aiID, callingResId, callingResDetail, resolver, persister, modConfig);
} }
} }
...@@ -31,6 +31,7 @@ import java.util.HashMap; ...@@ -31,6 +31,7 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import org.olat.core.id.Identity;
import org.olat.core.logging.AssertException; import org.olat.core.logging.AssertException;
import org.olat.course.nodes.iq.IQEditController; import org.olat.course.nodes.iq.IQEditController;
import org.olat.ims.qti.container.AssessmentContext; import org.olat.ims.qti.container.AssessmentContext;
...@@ -54,7 +55,12 @@ public class AssessmentInstance implements Serializable { ...@@ -54,7 +55,12 @@ public class AssessmentInstance implements Serializable {
private long assessID; // the key given to this instance by the constructor; identifying the assessment within the olat context; needed after deserialisation to find the correct qti tree private long assessID; // the key given to this instance by the constructor; identifying the assessment within the olat context; needed after deserialisation to find the correct qti tree
private long repositoryEntryKey; // the key to a repository entry private long repositoryEntryKey; // the key to a repository entry
private Navigator navigator; // optimise: make transient private Navigator navigator; // optimise: make transient
private long callingResId;
private String callingResDetail;
private List sourceBankRefs; private List sourceBankRefs;
private String remoteAddr;
private Identity assessedIdentity;
private AssessmentContext assessmentContext; private AssessmentContext assessmentContext;
...@@ -132,7 +138,12 @@ public class AssessmentInstance implements Serializable { ...@@ -132,7 +138,12 @@ public class AssessmentInstance implements Serializable {
* @param persistor the Persistor, may be null * @param persistor the Persistor, may be null
* @param modConfig * @param modConfig
*/ */
public AssessmentInstance(long repositoryEntryKey, long assessID, Resolver resolver, Persister persistor, ModuleConfiguration modConfig) { public AssessmentInstance(Identity identity, String remoteAddr, long repositoryEntryKey, long assessID, long callingResId, String callingResDetail,
Resolver resolver, Persister persistor, ModuleConfiguration modConfig) {
this.assessedIdentity = identity;
this.remoteAddr = remoteAddr;
this.callingResId = callingResId;
this.callingResDetail = callingResDetail;
this.repositoryEntryKey = repositoryEntryKey; this.repositoryEntryKey = repositoryEntryKey;
this.assessID = assessID; this.assessID = assessID;
this.resolver = resolver; this.resolver = resolver;
...@@ -203,6 +214,38 @@ public class AssessmentInstance implements Serializable { ...@@ -203,6 +214,38 @@ public class AssessmentInstance implements Serializable {
createNavigator(); createNavigator();
} }
public Identity getAssessedIdentity() {
return assessedIdentity;
}
public void setAssessedIdentity(Identity assessedIdentity) {
this.assessedIdentity = assessedIdentity;
}
public String getRemoteAddr() {
return remoteAddr;
}
public void setRemoteAddr(String remoteAddr) {
this.remoteAddr = remoteAddr;
}
public long getCallingResId() {
return callingResId;
}
public void setCallingResId(long callingResId) {
this.callingResId = callingResId;
}
public String getCallingResDetail() {
return callingResDetail;
}
public void setCallingResDetail(String callingResDetail) {
this.callingResDetail = callingResDetail;
}
public int getType() { return type; } public int getType() { return type; }
/** /**
......
...@@ -261,10 +261,12 @@ public class IQDisplayController extends DefaultController implements GenericEve ...@@ -261,10 +261,12 @@ public class IQDisplayController extends DefaultController implements GenericEve
//try{ //try{
if (repositorySoftkey != null) { // instantiate from repository if (repositorySoftkey != null) { // instantiate from repository
// build path information which will be used to store tempory qti file // build path information which will be used to store tempory qti file
String resourcePathInfo = this.callingResId + File.separator + this.callingResDetail; String resourcePathInfo = callingResId + File.separator + callingResDetail;
ai = AssessmentFactory.createAssessmentInstance(ureq.getIdentity(), modConfig, iqsec.isPreview(),resourcePathInfo); ai = AssessmentFactory.createAssessmentInstance(ureq.getIdentity(), ureq.getHttpReq().getRemoteAddr(),
modConfig, iqsec.isPreview(), callingResId, callingResDetail, resourcePathInfo);
} else if (resolver != null) { // instantiate from given resolver } else if (resolver != null) { // instantiate from given resolver
ai = AssessmentFactory.createAssessmentInstance(resolver, persister, modConfig); ai = AssessmentFactory.createAssessmentInstance(ureq.getIdentity(), ureq.getHttpReq().getRemoteAddr(),
callingResId, callingResDetail, resolver, persister, modConfig);
} }
//}finally{ //}finally{
//QTIEditorMainController.IS_SAVING_RWL.readLock().unlock(); //QTIEditorMainController.IS_SAVING_RWL.readLock().unlock();
...@@ -528,7 +530,7 @@ public class IQDisplayController extends DefaultController implements GenericEve ...@@ -528,7 +530,7 @@ public class IQDisplayController extends DefaultController implements GenericEve
*/ */
protected void postSubmitAssessment(UserRequest ureq, AssessmentInstance ai) { protected void postSubmitAssessment(UserRequest ureq, AssessmentInstance ai) {
if (!qtistatus.isPreview()) { if (!qtistatus.isPreview()) {
iqm.persistResults(ai, callingResId, callingResDetail, ureq.getIdentity(), ureq.getHttpReq().getRemoteAddr()); //iqm.persistResults(ai, callingResId, callingResDetail, ureq.getIdentity(), ureq.getHttpReq().getRemoteAddr());
getWindowControl().setInfo(translator.translate("status.results.saved")); getWindowControl().setInfo(translator.translate("status.results.saved"));
} else { } else {
getWindowControl().setInfo(translator.translate("status.results.notsaved")); getWindowControl().setInfo(translator.translate("status.results.notsaved"));
......
...@@ -317,20 +317,19 @@ public class IQManager extends BasicManager implements UserDataDeletable { ...@@ -317,20 +317,19 @@ public class IQManager extends BasicManager implements UserDataDeletable {
* @param ureq * @param ureq
*/ */
public void persistResults(AssessmentInstance ai, long resId, String resDetail, Identity assessedIdentity, String remoteAddr) { public void persistResults(AssessmentInstance ai) {
AssessmentContext ac = ai.getAssessmentContext(); AssessmentContext ac = ai.getAssessmentContext();
QTIResultSet qtiResultSet = new QTIResultSet(); QTIResultSet qtiResultSet = new QTIResultSet();
qtiResultSet.setLastModified(new Date(System.currentTimeMillis())); qtiResultSet.setLastModified(new Date(System.currentTimeMillis()));
qtiResultSet.setOlatResource(resId); qtiResultSet.setOlatResource(ai.getCallingResId());
qtiResultSet.setOlatResourceDetail(resDetail); qtiResultSet.setOlatResourceDetail(ai.getCallingResDetail());
qtiResultSet.setRepositoryRef(ai.getRepositoryEntryKey()); qtiResultSet.setRepositoryRef(ai.getRepositoryEntryKey());
qtiResultSet.setIdentity(assessedIdentity); qtiResultSet.setIdentity(ai.getAssessedIdentity());
qtiResultSet.setQtiType(ai.getType()); qtiResultSet.setQtiType(ai.getType());
qtiResultSet.setAssessmentID(ai.getAssessID()); qtiResultSet.setAssessmentID(ai.getAssessID());
qtiResultSet.setDuration(new Long(ai.getAssessmentContext().getDuration())); qtiResultSet.setDuration(new Long(ai.getAssessmentContext().getDuration()));
// TODO qtiResultSet.setLastModified();
if (ai.isSurvey()){ if (ai.isSurvey()){
qtiResultSet.setScore(0); qtiResultSet.setScore(0);
...@@ -359,7 +358,7 @@ public class IQManager extends BasicManager implements UserDataDeletable { ...@@ -359,7 +358,7 @@ public class IQManager extends BasicManager implements UserDataDeletable {
else qtiResult.setScore(ic.getScore()); else qtiResult.setScore(ic.getScore());
qtiResult.setTstamp(new Date(ic.getLatestAnswerTime())); qtiResult.setTstamp(new Date(ic.getLatestAnswerTime()));
qtiResult.setLastModified(new Date(System.currentTimeMillis())); qtiResult.setLastModified(new Date(System.currentTimeMillis()));
qtiResult.setIp(remoteAddr); qtiResult.setIp(ai.getRemoteAddr());
// Get user answers for this item // Get user answers for this item
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
......
...@@ -358,7 +358,7 @@ public class CourseAssessmentWebService { ...@@ -358,7 +358,7 @@ public class CourseAssessmentWebService {
// The consequence is that we must loop on section and items and set the // The consequence is that we must loop on section and items and set the
// navigator on // navigator on
// the right position before submitting the inputs. // the right position before submitting the inputs.
AssessmentInstance ai = AssessmentFactory.createAssessmentInstance(identity, modConfig, false, resourcePathInfo); AssessmentInstance ai = AssessmentFactory.createAssessmentInstance(identity, "", modConfig, false, course.getResourceableId(), courseNode.getIdent(), resourcePathInfo);
Navigator navigator = ai.getNavigator(); Navigator navigator = ai.getNavigator();
navigator.startAssessment(); navigator.startAssessment();
// The type of the navigator depends on the setting of the course node // The type of the navigator depends on the setting of the course node
......
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