use of uk.ac.ed.ph.jqtiplus.types.StringResponseData in project OpenOLAT by OpenOLAT.
the class HottextAssessmentItemBuilderTest method createHottextAssessmentItem_perAnswer.
/**
* This is an hottextInteraction with 3 choices, one with 3.0 points and correct,
* one with 0.0 points but correct and one false with -1.0 points.
*
* @throws IOException
*/
@Test
public void createHottextAssessmentItem_perAnswer() throws IOException {
QtiSerializer qtiSerializer = new QtiSerializer(new JqtiExtensionManager());
HottextAssessmentItemBuilder itemBuilder = new HottextAssessmentItemBuilder("Hot texts", "This is a hot ", "text", qtiSerializer);
itemBuilder.setQuestion("<p>This is <hottext identifier=\"RESPONSE_HOT_1\">hot</hottext>, <hottext identifier=\"RESPONSE_HOT_2\">cold</hottext> or <hottext identifier=\"RESPONSE_HOT_3\">freezing</hottext></p>");
itemBuilder.addCorrectAnswer(Identifier.parseString("RESPONSE_HOT_2"));
itemBuilder.addCorrectAnswer(Identifier.parseString("RESPONSE_HOT_3"));
itemBuilder.setMapping(Identifier.parseString("RESPONSE_HOT_1"), -1.0d);
itemBuilder.setMapping(Identifier.parseString("RESPONSE_HOT_2"), 0.0d);
itemBuilder.setMapping(Identifier.parseString("RESPONSE_HOT_3"), 3.0d);
itemBuilder.setMaxScore(3.0d);
itemBuilder.setScoreEvaluationMode(ScoreEvaluation.perAnswer);
itemBuilder.build();
File itemFile = new File(WebappHelper.getTmpDir(), "hottextAssessmentItem" + UUID.randomUUID() + ".xml");
try (FileOutputStream out = new FileOutputStream(itemFile)) {
qtiSerializer.serializeJqtiObject(itemBuilder.getAssessmentItem(), out);
} catch (Exception e) {
log.error("", e);
}
{
// correct answers
Map<Identifier, ResponseData> responseMap = new HashMap<>();
Identifier responseIdentifier = itemBuilder.getInteraction().getResponseIdentifier();
responseMap.put(responseIdentifier, new StringResponseData("RESPONSE_HOT_2", "RESPONSE_HOT_3"));
ItemSessionController itemSessionController = RunningItemHelper.run(itemFile, responseMap);
Value score = itemSessionController.getItemSessionState().getOutcomeValue(QTI21Constants.SCORE_IDENTIFIER);
Assert.assertEquals(new FloatValue(3.0d), score);
Value feedbackBasic = itemSessionController.getItemSessionState().getOutcomeValue(QTI21Constants.FEEDBACKBASIC_IDENTIFIER);
Assert.assertEquals(new IdentifierValue(QTI21Constants.CORRECT_IDENTIFIER), feedbackBasic);
}
{
// max score but not all correct
Map<Identifier, ResponseData> responseMap = new HashMap<>();
Identifier responseIdentifier = itemBuilder.getInteraction().getResponseIdentifier();
responseMap.put(responseIdentifier, new StringResponseData("RESPONSE_HOT_3"));
ItemSessionController itemSessionController = RunningItemHelper.run(itemFile, responseMap);
Value score = itemSessionController.getItemSessionState().getOutcomeValue(QTI21Constants.SCORE_IDENTIFIER);
Assert.assertEquals(new FloatValue(3.0d), score);
Value feedbackBasic = itemSessionController.getItemSessionState().getOutcomeValue(QTI21Constants.FEEDBACKBASIC_IDENTIFIER);
Assert.assertEquals(new IdentifierValue(QTI21Constants.INCORRECT_IDENTIFIER), feedbackBasic);
}
{
// all wrong
Map<Identifier, ResponseData> responseMap = new HashMap<>();
Identifier responseIdentifier = itemBuilder.getInteraction().getResponseIdentifier();
responseMap.put(responseIdentifier, new StringResponseData("RESPONSE_HOT_1"));
ItemSessionController itemSessionController = RunningItemHelper.run(itemFile, responseMap);
Value score = itemSessionController.getItemSessionState().getOutcomeValue(QTI21Constants.SCORE_IDENTIFIER);
Assert.assertEquals(new FloatValue(0.0d), score);
Value feedbackBasic = itemSessionController.getItemSessionState().getOutcomeValue(QTI21Constants.FEEDBACKBASIC_IDENTIFIER);
Assert.assertEquals(new IdentifierValue(QTI21Constants.INCORRECT_IDENTIFIER), feedbackBasic);
}
FileUtils.deleteDirsAndFiles(itemFile.toPath());
}
use of uk.ac.ed.ph.jqtiplus.types.StringResponseData in project OpenOLAT by OpenOLAT.
the class AssessmentItemDisplayController method handleTemporaryResponses.
public void handleTemporaryResponses(UserRequest ureq, Map<Identifier, ResponseInput> stringResponseMap) {
/* Retrieve current JQTI state and set up JQTI controller */
NotificationRecorder notificationRecorder = new NotificationRecorder(NotificationLevel.INFO);
ItemSessionState itemSessionState = itemSessionController.getItemSessionState();
/* Make sure an attempt is allowed */
if (itemSessionState.isEnded()) {
candidateAuditLogger.logAndThrowCandidateException(candidateSession, CandidateExceptionReason.RESPONSES_NOT_EXPECTED, null);
logError("RESPONSES_NOT_EXPECTED", null);
return;
}
/* Build response map in required format for JQTI+.
* NB: The following doesn't test for duplicate keys in the two maps. I'm not sure
* it's worth the effort.
*/
final Map<Identifier, ResponseData> responseDataMap = new HashMap<>();
final Map<Identifier, AssessmentResponse> assessmentResponseDataMap = new HashMap<>();
if (stringResponseMap != null) {
for (final Entry<Identifier, ResponseInput> stringResponseEntry : stringResponseMap.entrySet()) {
Identifier identifier = stringResponseEntry.getKey();
ResponseInput responseData = stringResponseEntry.getValue();
if (responseData instanceof StringInput) {
responseDataMap.put(identifier, new StringResponseData(((StringInput) responseData).getResponseData()));
}
}
}
final Date timestamp = ureq.getRequestTimestamp();
/* Attempt to bind responses */
boolean allResponsesValid = false;
boolean allResponsesBound = false;
try {
itemSessionController.bindResponses(timestamp, responseDataMap);
} catch (final QtiCandidateStateException e) {
candidateAuditLogger.logAndThrowCandidateException(candidateSession, CandidateExceptionReason.RESPONSES_NOT_EXPECTED, null);
logError("RESPONSES_NOT_EXPECTED", e);
return;
} catch (final RuntimeException e) {
logError("", e);
return;
}
/* Record resulting attempt and event */
final CandidateItemEventType eventType = allResponsesBound ? (allResponsesValid ? CandidateItemEventType.ATTEMPT_VALID : CandidateItemEventType.RESPONSE_INVALID) : CandidateItemEventType.RESPONSE_BAD;
final CandidateEvent candidateEvent = qtiService.recordCandidateItemEvent(candidateSession, null, entry, eventType, itemSessionState, notificationRecorder);
candidateAuditLogger.logCandidateEvent(candidateEvent, assessmentResponseDataMap);
lastEvent = candidateEvent;
}
use of uk.ac.ed.ph.jqtiplus.types.StringResponseData in project OpenOLAT by OpenOLAT.
the class AssessmentTestDisplayController method handleTemporaryResponse.
private void handleTemporaryResponse(UserRequest ureq, Map<Identifier, ResponseInput> stringResponseMap) {
NotificationRecorder notificationRecorder = new NotificationRecorder(NotificationLevel.INFO);
TestSessionState testSessionState = testSessionController.getTestSessionState();
TestPlanNodeKey currentItemKey = testSessionState.getCurrentItemKey();
if (currentItemKey == null) {
//
return;
}
String cmd = ureq.getParameter("tmpResponse");
if (!qtiWorksCtrl.validateResponseIdentifierCommand(cmd, currentItemKey)) {
// this is not the right node in the plan
return;
}
final Date timestamp = ureq.getRequestTimestamp();
final Map<Identifier, ResponseData> responseDataMap = new HashMap<>();
if (stringResponseMap != null) {
for (final Entry<Identifier, ResponseInput> responseEntry : stringResponseMap.entrySet()) {
final Identifier identifier = responseEntry.getKey();
final ResponseInput responseData = responseEntry.getValue();
if (responseData instanceof StringInput) {
responseDataMap.put(identifier, new StringResponseData(((StringInput) responseData).getResponseData()));
}
}
}
ParentPartItemRefs parentParts = getParentSection(currentItemKey);
String assessmentItemIdentifier = currentItemKey.getIdentifier().toString();
AssessmentItemSession itemSession = qtiService.getOrCreateAssessmentItemSession(candidateSession, parentParts, assessmentItemIdentifier);
TestPlanNode currentItemRefNode = testSessionState.getTestPlan().getNode(currentItemKey);
ItemSessionController itemSessionController = (ItemSessionController) testSessionController.getItemProcessingContext(currentItemRefNode);
ItemSessionState itemSessionState = itemSessionController.getItemSessionState();
List<Interaction> interactions = itemSessionController.getInteractions();
Map<Identifier, Interaction> interactionMap = new HashMap<>();
for (Interaction interaction : interactions) {
interactionMap.put(interaction.getResponseIdentifier(), interaction);
}
Map<Identifier, AssessmentResponse> candidateResponseMap = qtiService.getAssessmentResponses(itemSession);
for (Entry<Identifier, ResponseData> responseEntry : responseDataMap.entrySet()) {
Identifier responseIdentifier = responseEntry.getKey();
ResponseData responseData = responseEntry.getValue();
AssessmentResponse candidateItemResponse;
if (candidateResponseMap.containsKey(responseIdentifier)) {
candidateItemResponse = candidateResponseMap.get(responseIdentifier);
} else {
candidateItemResponse = qtiService.createAssessmentResponse(candidateSession, itemSession, responseIdentifier.toString(), ResponseLegality.VALID, responseData.getType());
}
switch(responseData.getType()) {
case STRING:
{
List<String> data = ((StringResponseData) responseData).getResponseData();
String stringuifiedResponse = ResponseFormater.format(data);
candidateItemResponse.setStringuifiedResponse(stringuifiedResponse);
break;
}
default:
throw new OLATRuntimeException("Unexpected switch case: " + responseData.getType());
}
candidateResponseMap.put(responseIdentifier, candidateItemResponse);
itemSessionState.setRawResponseData(responseIdentifier, responseData);
try {
Interaction interaction = interactionMap.get(responseIdentifier);
interaction.bindResponse(itemSessionController, responseData);
} catch (final ResponseBindingException e) {
//
}
}
/* Copy uncommitted responses over */
for (final Entry<Identifier, Value> uncommittedResponseEntry : itemSessionState.getUncommittedResponseValues().entrySet()) {
final Identifier identifier = uncommittedResponseEntry.getKey();
final Value value = uncommittedResponseEntry.getValue();
itemSessionState.setResponseValue(identifier, value);
}
/* Persist CandidateResponse entities */
qtiService.recordTestAssessmentResponses(itemSession, candidateResponseMap.values());
/* Record resulting event */
final CandidateEvent candidateEvent = qtiService.recordCandidateTestEvent(candidateSession, testEntry, entry, CandidateTestEventType.ITEM_EVENT, null, currentItemKey, testSessionState, notificationRecorder);
candidateAuditLogger.logCandidateEvent(candidateEvent, candidateResponseMap);
/* Record current result state */
AssessmentResult assessmentResult = computeTestAssessmentResult(timestamp, candidateSession);
synchronized (this) {
qtiService.recordTestAssessmentResult(candidateSession, testSessionState, assessmentResult, candidateAuditLogger);
}
}
use of uk.ac.ed.ph.jqtiplus.types.StringResponseData in project openolat by klemens.
the class AssessmentItemDisplayController method handleTemporaryResponses.
public void handleTemporaryResponses(UserRequest ureq, Map<Identifier, ResponseInput> stringResponseMap) {
/* Retrieve current JQTI state and set up JQTI controller */
NotificationRecorder notificationRecorder = new NotificationRecorder(NotificationLevel.INFO);
ItemSessionState itemSessionState = itemSessionController.getItemSessionState();
/* Make sure an attempt is allowed */
if (itemSessionState.isEnded()) {
candidateAuditLogger.logAndThrowCandidateException(candidateSession, CandidateExceptionReason.RESPONSES_NOT_EXPECTED, null);
logError("RESPONSES_NOT_EXPECTED", null);
return;
}
/* Build response map in required format for JQTI+.
* NB: The following doesn't test for duplicate keys in the two maps. I'm not sure
* it's worth the effort.
*/
final Map<Identifier, ResponseData> responseDataMap = new HashMap<>();
final Map<Identifier, AssessmentResponse> assessmentResponseDataMap = new HashMap<>();
if (stringResponseMap != null) {
for (final Entry<Identifier, ResponseInput> stringResponseEntry : stringResponseMap.entrySet()) {
Identifier identifier = stringResponseEntry.getKey();
ResponseInput responseData = stringResponseEntry.getValue();
if (responseData instanceof StringInput) {
responseDataMap.put(identifier, new StringResponseData(((StringInput) responseData).getResponseData()));
}
}
}
final Date timestamp = ureq.getRequestTimestamp();
/* Attempt to bind responses */
boolean allResponsesValid = false;
boolean allResponsesBound = false;
try {
itemSessionController.bindResponses(timestamp, responseDataMap);
} catch (final QtiCandidateStateException e) {
candidateAuditLogger.logAndThrowCandidateException(candidateSession, CandidateExceptionReason.RESPONSES_NOT_EXPECTED, null);
logError("RESPONSES_NOT_EXPECTED", e);
return;
} catch (final RuntimeException e) {
logError("", e);
return;
}
/* Record resulting attempt and event */
final CandidateItemEventType eventType = allResponsesBound ? (allResponsesValid ? CandidateItemEventType.ATTEMPT_VALID : CandidateItemEventType.RESPONSE_INVALID) : CandidateItemEventType.RESPONSE_BAD;
final CandidateEvent candidateEvent = qtiService.recordCandidateItemEvent(candidateSession, null, entry, eventType, itemSessionState, notificationRecorder);
candidateAuditLogger.logCandidateEvent(candidateEvent, assessmentResponseDataMap);
lastEvent = candidateEvent;
}
use of uk.ac.ed.ph.jqtiplus.types.StringResponseData in project openolat by klemens.
the class AssessmentTestDisplayController method handleTemporaryResponse.
private void handleTemporaryResponse(UserRequest ureq, Map<Identifier, ResponseInput> stringResponseMap) {
NotificationRecorder notificationRecorder = new NotificationRecorder(NotificationLevel.INFO);
TestSessionState testSessionState = testSessionController.getTestSessionState();
TestPlanNodeKey currentItemKey = testSessionState.getCurrentItemKey();
if (currentItemKey == null) {
//
return;
}
String cmd = ureq.getParameter("tmpResponse");
if (!qtiWorksCtrl.validateResponseIdentifierCommand(cmd, currentItemKey)) {
// this is not the right node in the plan
return;
}
final Date timestamp = ureq.getRequestTimestamp();
final Map<Identifier, ResponseData> responseDataMap = new HashMap<>();
if (stringResponseMap != null) {
for (final Entry<Identifier, ResponseInput> responseEntry : stringResponseMap.entrySet()) {
final Identifier identifier = responseEntry.getKey();
final ResponseInput responseData = responseEntry.getValue();
if (responseData instanceof StringInput) {
responseDataMap.put(identifier, new StringResponseData(((StringInput) responseData).getResponseData()));
}
}
}
ParentPartItemRefs parentParts = getParentSection(currentItemKey);
String assessmentItemIdentifier = currentItemKey.getIdentifier().toString();
AssessmentItemSession itemSession = qtiService.getOrCreateAssessmentItemSession(candidateSession, parentParts, assessmentItemIdentifier);
TestPlanNode currentItemRefNode = testSessionState.getTestPlan().getNode(currentItemKey);
ItemSessionController itemSessionController = (ItemSessionController) testSessionController.getItemProcessingContext(currentItemRefNode);
ItemSessionState itemSessionState = itemSessionController.getItemSessionState();
List<Interaction> interactions = itemSessionController.getInteractions();
Map<Identifier, Interaction> interactionMap = new HashMap<>();
for (Interaction interaction : interactions) {
interactionMap.put(interaction.getResponseIdentifier(), interaction);
}
Map<Identifier, AssessmentResponse> candidateResponseMap = qtiService.getAssessmentResponses(itemSession);
for (Entry<Identifier, ResponseData> responseEntry : responseDataMap.entrySet()) {
Identifier responseIdentifier = responseEntry.getKey();
ResponseData responseData = responseEntry.getValue();
AssessmentResponse candidateItemResponse;
if (candidateResponseMap.containsKey(responseIdentifier)) {
candidateItemResponse = candidateResponseMap.get(responseIdentifier);
} else {
candidateItemResponse = qtiService.createAssessmentResponse(candidateSession, itemSession, responseIdentifier.toString(), ResponseLegality.VALID, responseData.getType());
}
switch(responseData.getType()) {
case STRING:
{
List<String> data = ((StringResponseData) responseData).getResponseData();
String stringuifiedResponse = ResponseFormater.format(data);
candidateItemResponse.setStringuifiedResponse(stringuifiedResponse);
break;
}
default:
throw new OLATRuntimeException("Unexpected switch case: " + responseData.getType());
}
candidateResponseMap.put(responseIdentifier, candidateItemResponse);
itemSessionState.setRawResponseData(responseIdentifier, responseData);
try {
Interaction interaction = interactionMap.get(responseIdentifier);
interaction.bindResponse(itemSessionController, responseData);
} catch (final ResponseBindingException e) {
//
}
}
/* Copy uncommitted responses over */
for (final Entry<Identifier, Value> uncommittedResponseEntry : itemSessionState.getUncommittedResponseValues().entrySet()) {
final Identifier identifier = uncommittedResponseEntry.getKey();
final Value value = uncommittedResponseEntry.getValue();
itemSessionState.setResponseValue(identifier, value);
}
/* Persist CandidateResponse entities */
qtiService.recordTestAssessmentResponses(itemSession, candidateResponseMap.values());
/* Record resulting event */
final CandidateEvent candidateEvent = qtiService.recordCandidateTestEvent(candidateSession, testEntry, entry, CandidateTestEventType.ITEM_EVENT, null, currentItemKey, testSessionState, notificationRecorder);
candidateAuditLogger.logCandidateEvent(candidateEvent, candidateResponseMap);
/* Record current result state */
AssessmentResult assessmentResult = computeTestAssessmentResult(timestamp, candidateSession);
synchronized (this) {
qtiService.recordTestAssessmentResult(candidateSession, testSessionState, assessmentResult, candidateAuditLogger);
}
}
Aggregations