parent
76a038e0b8
commit
0670f8d288
@ -0,0 +1,67 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
/* For licensing terms, see /license.txt */ |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Claro Team <cvs@claroline.net> |
||||||
|
* @author Yannick Warnier <yannick.warnier@beeznest.com> - |
||||||
|
* updated ImsAnswerHotspot to match QTI norms |
||||||
|
*/ |
||||||
|
class Ims2Question extends Question |
||||||
|
{ |
||||||
|
/** |
||||||
|
* Include the correct answer class and create answer. |
||||||
|
* |
||||||
|
* @return Answer |
||||||
|
*/ |
||||||
|
public function setAnswer() |
||||||
|
{ |
||||||
|
switch ($this->type) { |
||||||
|
case MCUA: |
||||||
|
$answer = new ImsAnswerMultipleChoice($this->id); |
||||||
|
|
||||||
|
return $answer; |
||||||
|
case MCMA: |
||||||
|
$answer = new ImsAnswerMultipleChoice($this->id); |
||||||
|
|
||||||
|
return $answer; |
||||||
|
case TF: |
||||||
|
$answer = new ImsAnswerMultipleChoice($this->id); |
||||||
|
|
||||||
|
return $answer; |
||||||
|
case FIB: |
||||||
|
$answer = new ImsAnswerFillInBlanks($this->id); |
||||||
|
|
||||||
|
return $answer; |
||||||
|
case MATCHING: |
||||||
|
case MATCHING_DRAGGABLE: |
||||||
|
$answer = new ImsAnswerMatching($this->id); |
||||||
|
|
||||||
|
return $answer; |
||||||
|
case FREE_ANSWER: |
||||||
|
$answer = new ImsAnswerFree($this->id); |
||||||
|
|
||||||
|
return $answer; |
||||||
|
case HOT_SPOT: |
||||||
|
$answer = new ImsAnswerHotspot($this->id); |
||||||
|
|
||||||
|
return $answer; |
||||||
|
default: |
||||||
|
$answer = null; |
||||||
|
|
||||||
|
break; |
||||||
|
} |
||||||
|
|
||||||
|
return $answer; |
||||||
|
} |
||||||
|
|
||||||
|
public function createAnswersForm($form) |
||||||
|
{ |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
public function processAnswersCreation($form, $exercise) |
||||||
|
{ |
||||||
|
return true; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,55 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
/** |
||||||
|
* Class. |
||||||
|
*/ |
||||||
|
class ImsAnswerFillInBlanks extends Answer implements ImsAnswerInterface |
||||||
|
{ |
||||||
|
private $answerList = []; |
||||||
|
private $gradeList = []; |
||||||
|
|
||||||
|
/** |
||||||
|
* Export the text with missing words. |
||||||
|
*/ |
||||||
|
public function imsExportResponses($questionIdent, $questionStatment) |
||||||
|
{ |
||||||
|
$this->answerList = $this->getAnswersList(true); |
||||||
|
$text = isset($this->answerText) ? $this->answerText : ''; |
||||||
|
if (is_array($this->answerList)) { |
||||||
|
foreach ($this->answerList as $key => $answer) { |
||||||
|
$key = $answer['id']; |
||||||
|
$answer = $answer['answer']; |
||||||
|
$len = api_strlen($answer); |
||||||
|
$text = str_replace('['.$answer.']', '<textEntryInteraction responseIdentifier="fill_'.$key.'" expectedLength="'.api_strlen($answer).'"/>', $text); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return $text; |
||||||
|
} |
||||||
|
|
||||||
|
public function imsExportResponsesDeclaration($questionIdent, Question $question = null) |
||||||
|
{ |
||||||
|
$this->answerList = $this->getAnswersList(true); |
||||||
|
$this->gradeList = $this->getGradesList(); |
||||||
|
$out = ''; |
||||||
|
if (is_array($this->answerList)) { |
||||||
|
foreach ($this->answerList as $answer) { |
||||||
|
$answerKey = $answer['id']; |
||||||
|
$answer = $answer['answer']; |
||||||
|
$out .= ' <responseDeclaration identifier="fill_'.$answerKey.'" cardinality="single" baseType="identifier">'."\n"; |
||||||
|
$out .= ' <correctResponse>'."\n"; |
||||||
|
$out .= ' <value><![CDATA['.formatExerciseQtiText($answer).']]></value>'."\n"; |
||||||
|
$out .= ' </correctResponse>'."\n"; |
||||||
|
if (isset($this->gradeList[$answerKey])) { |
||||||
|
$out .= ' <mapping>'."\n"; |
||||||
|
$out .= ' <mapEntry mapKey="'.$answer.'" mappedValue="'.$this->gradeList[$answerKey].'"/>'."\n"; |
||||||
|
$out .= ' </mapping>'."\n"; |
||||||
|
} |
||||||
|
|
||||||
|
$out .= ' </responseDeclaration>'."\n"; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return $out; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,39 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
/** |
||||||
|
* Class. |
||||||
|
*/ |
||||||
|
class ImsAnswerFree extends Answer implements ImsAnswerInterface |
||||||
|
{ |
||||||
|
/** |
||||||
|
* @todo implement |
||||||
|
* Export the question part as a matrix-choice, with only one possible answer per line. |
||||||
|
* |
||||||
|
* @param string $questionIdent |
||||||
|
* @param string $questionStatment |
||||||
|
* @param string $questionDesc |
||||||
|
* @param string $questionMedia |
||||||
|
* |
||||||
|
* @return string |
||||||
|
*/ |
||||||
|
public function imsExportResponses($questionIdent, $questionStatment, $questionDesc = '', $questionMedia = '') |
||||||
|
{ |
||||||
|
$questionDesc = formatExerciseQtiText($questionDesc); |
||||||
|
|
||||||
|
return '<extendedTextInteraction responseIdentifier="'.$questionIdent.'" > |
||||||
|
<prompt> |
||||||
|
'.$questionDesc.' |
||||||
|
</prompt> |
||||||
|
</extendedTextInteraction>'; |
||||||
|
} |
||||||
|
|
||||||
|
public function imsExportResponsesDeclaration($questionIdent, Question $question = null) |
||||||
|
{ |
||||||
|
$out = ' <responseDeclaration identifier="'.$questionIdent.'" cardinality="single" baseType="string">'; |
||||||
|
$out .= '<outcomeDeclaration identifier="SCORE" cardinality="single" baseType="float"> |
||||||
|
<defaultValue><value>'.$question->weighting.'</value></defaultValue></outcomeDeclaration>'; |
||||||
|
$out .= ' </responseDeclaration>'."\n"; |
||||||
|
|
||||||
|
return $out; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,97 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
/** |
||||||
|
* Class. |
||||||
|
*/ |
||||||
|
class ImsAnswerHotspot extends Answer implements ImsAnswerInterface |
||||||
|
{ |
||||||
|
private $answerList = []; |
||||||
|
private $gradeList = []; |
||||||
|
|
||||||
|
/** |
||||||
|
* @todo update this to match hot spots instead of copying matching |
||||||
|
* Export the question part as a matrix-choice, with only one possible answer per line. |
||||||
|
* |
||||||
|
* @param string $questionIdent |
||||||
|
* @param string $questionStatment |
||||||
|
* @param string $questionDesc |
||||||
|
* @param string $questionMedia |
||||||
|
* |
||||||
|
* @return string |
||||||
|
*/ |
||||||
|
public function imsExportResponses($questionIdent, $questionStatment, $questionDesc = '', $questionMedia = '') |
||||||
|
{ |
||||||
|
$this->answerList = $this->getAnswersList(true); |
||||||
|
$mediaFilePath = api_get_course_path().'/document/images/'.$questionMedia; |
||||||
|
$sysQuestionMediaPath = api_get_path(SYS_COURSE_PATH).$mediaFilePath; |
||||||
|
$questionMedia = api_get_path(WEB_COURSE_PATH).$mediaFilePath; |
||||||
|
$mimetype = mime_content_type($sysQuestionMediaPath); |
||||||
|
if (empty($mimetype)) { |
||||||
|
$mimetype = 'image/jpeg'; |
||||||
|
} |
||||||
|
|
||||||
|
$text = ' <p>'.$questionStatment.'</p>'."\n"; |
||||||
|
$text .= ' <graphicOrderInteraction responseIdentifier="hotspot_'.$questionIdent.'">'."\n"; |
||||||
|
$text .= ' <prompt>'.$questionDesc.'</prompt>'."\n"; |
||||||
|
$text .= ' <object type="'.$mimetype.'" width="250" height="230" data="'.$questionMedia.'">-</object>'."\n"; |
||||||
|
if (is_array($this->answerList)) { |
||||||
|
foreach ($this->answerList as $key => $answer) { |
||||||
|
$key = $answer['id']; |
||||||
|
$answerTxt = $answer['answer']; |
||||||
|
$len = api_strlen($answerTxt); |
||||||
|
//coords are transformed according to QTIv2 rules here: http://www.imsproject.org/question/qtiv2p1pd/imsqti_infov2p1pd.html#element10663 |
||||||
|
$coords = ''; |
||||||
|
$type = 'default'; |
||||||
|
switch ($answer['hotspot_type']) { |
||||||
|
case 'square': |
||||||
|
$type = 'rect'; |
||||||
|
$res = []; |
||||||
|
$coords = preg_match('/^\s*(\d+);(\d+)\|(\d+)\|(\d+)\s*$/', $answer['hotspot_coord'], $res); |
||||||
|
$coords = $res[1].','.$res[2].','.((int) $res[1] + (int) $res[3]).','.((int) $res[2] + (int) $res[4]); |
||||||
|
|
||||||
|
break; |
||||||
|
case 'circle': |
||||||
|
$type = 'circle'; |
||||||
|
$res = []; |
||||||
|
$coords = preg_match('/^\s*(\d+);(\d+)\|(\d+)\|(\d+)\s*$/', $answer['hotspot_coord'], $res); |
||||||
|
$coords = $res[1].','.$res[2].','.sqrt(pow($res[1] - $res[3], 2) + pow($res[2] - $res[4])); |
||||||
|
|
||||||
|
break; |
||||||
|
case 'poly': |
||||||
|
$type = 'poly'; |
||||||
|
$coords = str_replace([';', '|'], [',', ','], $answer['hotspot_coord']); |
||||||
|
|
||||||
|
break; |
||||||
|
case 'delineation': |
||||||
|
$type = 'delineation'; |
||||||
|
$coords = str_replace([';', '|'], [',', ','], $answer['hotspot_coord']); |
||||||
|
|
||||||
|
break; |
||||||
|
} |
||||||
|
$text .= ' <hotspotChoice shape="'.$type.'" coords="'.$coords.'" identifier="'.$key.'"/>'."\n"; |
||||||
|
} |
||||||
|
} |
||||||
|
$text .= ' </graphicOrderInteraction>'."\n"; |
||||||
|
|
||||||
|
return $text; |
||||||
|
} |
||||||
|
|
||||||
|
public function imsExportResponsesDeclaration($questionIdent, Question $question = null) |
||||||
|
{ |
||||||
|
$this->answerList = $this->getAnswersList(true); |
||||||
|
$this->gradeList = $this->getGradesList(); |
||||||
|
$out = ' <responseDeclaration identifier="hotspot_'.$questionIdent.'" cardinality="ordered" baseType="identifier">'."\n"; |
||||||
|
if (is_array($this->answerList)) { |
||||||
|
$out .= ' <correctResponse>'."\n"; |
||||||
|
foreach ($this->answerList as $answerKey => $answer) { |
||||||
|
$answerKey = $answer['id']; |
||||||
|
$answer = $answer['answer']; |
||||||
|
$out .= '<value><![CDATA['.formatExerciseQtiText($answerKey).']]></value>'; |
||||||
|
} |
||||||
|
$out .= ' </correctResponse>'."\n"; |
||||||
|
} |
||||||
|
$out .= ' </responseDeclaration>'."\n"; |
||||||
|
|
||||||
|
return $out; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,29 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
/* For licensing terms, see /license.txt */ |
||||||
|
|
||||||
|
/** |
||||||
|
* Interface ImsAnswerInterface. |
||||||
|
*/ |
||||||
|
interface ImsAnswerInterface |
||||||
|
{ |
||||||
|
/** |
||||||
|
* @param string $questionIdent |
||||||
|
* @param string $questionStatment |
||||||
|
* @param string $questionDesc |
||||||
|
* @param string $questionMedia |
||||||
|
* |
||||||
|
* @return string |
||||||
|
*/ |
||||||
|
public function imsExportResponses($questionIdent, $questionStatment, $questionDesc = '', $questionMedia = ''); |
||||||
|
|
||||||
|
/** |
||||||
|
* @param $questionIdent |
||||||
|
* |
||||||
|
* @return mixed |
||||||
|
*/ |
||||||
|
public function imsExportResponsesDeclaration($questionIdent, Question $question = null); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,94 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
/** |
||||||
|
* Class. |
||||||
|
*/ |
||||||
|
class ImsAnswerMatching extends Answer implements ImsAnswerInterface |
||||||
|
{ |
||||||
|
public $leftList = []; |
||||||
|
public $rightList = []; |
||||||
|
private $answerList = []; |
||||||
|
|
||||||
|
/** |
||||||
|
* Export the question part as a matrix-choice, with only one possible answer per line. |
||||||
|
* |
||||||
|
* @param string $questionIdent |
||||||
|
* @param string $questionStatment |
||||||
|
* @param string $questionDesc |
||||||
|
* @param string $questionMedia |
||||||
|
* |
||||||
|
* @return string |
||||||
|
*/ |
||||||
|
public function imsExportResponses($questionIdent, $questionStatment, $questionDesc = '', $questionMedia = '') |
||||||
|
{ |
||||||
|
$this->answerList = $this->getAnswersList(true); |
||||||
|
$maxAssociation = max(count($this->leftList), count($this->rightList)); |
||||||
|
|
||||||
|
$out = '<matchInteraction responseIdentifier="'.$questionIdent.'" maxAssociations="'.$maxAssociation.'">'."\n"; |
||||||
|
$out .= $questionStatment; |
||||||
|
|
||||||
|
//add left column |
||||||
|
$out .= ' <simpleMatchSet>'."\n"; |
||||||
|
if (is_array($this->leftList)) { |
||||||
|
foreach ($this->leftList as $leftKey => $leftElement) { |
||||||
|
$out .= ' |
||||||
|
<simpleAssociableChoice identifier="left_'.$leftKey.'" > |
||||||
|
<![CDATA['.formatExerciseQtiText($leftElement['answer']).']]> |
||||||
|
</simpleAssociableChoice>'."\n"; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
$out .= ' </simpleMatchSet>'."\n"; |
||||||
|
|
||||||
|
//add right column |
||||||
|
$out .= ' <simpleMatchSet>'."\n"; |
||||||
|
$i = 0; |
||||||
|
|
||||||
|
if (is_array($this->rightList)) { |
||||||
|
foreach ($this->rightList as $rightKey => $rightElement) { |
||||||
|
$out .= '<simpleAssociableChoice identifier="right_'.$i.'" > |
||||||
|
<![CDATA['.formatExerciseQtiText($rightElement['answer']).']]> |
||||||
|
</simpleAssociableChoice>'."\n"; |
||||||
|
$i++; |
||||||
|
} |
||||||
|
} |
||||||
|
$out .= ' </simpleMatchSet>'."\n"; |
||||||
|
$out .= '</matchInteraction>'."\n"; |
||||||
|
|
||||||
|
return $out; |
||||||
|
} |
||||||
|
|
||||||
|
public function imsExportResponsesDeclaration($questionIdent, Question $question = null) |
||||||
|
{ |
||||||
|
$this->answerList = $this->getAnswersList(true); |
||||||
|
$out = ' <responseDeclaration identifier="'.$questionIdent.'" cardinality="single" baseType="identifier">'."\n"; |
||||||
|
$out .= ' <correctResponse>'."\n"; |
||||||
|
|
||||||
|
$gradeArray = []; |
||||||
|
if (isset($this->leftList) && is_array($this->leftList)) { |
||||||
|
foreach ($this->leftList as $leftKey => $leftElement) { |
||||||
|
$i = 0; |
||||||
|
foreach ($this->rightList as $rightKey => $rightElement) { |
||||||
|
if (($leftElement['match'] == $rightElement['code'])) { |
||||||
|
$out .= ' <value>left_'.$leftKey.' right_'.$i.'</value>'."\n"; |
||||||
|
$gradeArray['left_'.$leftKey.' right_'.$i] = $leftElement['grade']; |
||||||
|
} |
||||||
|
$i++; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
$out .= ' </correctResponse>'."\n"; |
||||||
|
|
||||||
|
if (is_array($gradeArray)) { |
||||||
|
$out .= ' <mapping>'."\n"; |
||||||
|
foreach ($gradeArray as $gradeKey => $grade) { |
||||||
|
$out .= ' <mapEntry mapKey="'.$gradeKey.'" mappedValue="'.$grade.'"/>'."\n"; |
||||||
|
} |
||||||
|
$out .= ' </mapping>'."\n"; |
||||||
|
} |
||||||
|
|
||||||
|
$out .= ' </responseDeclaration>'."\n"; |
||||||
|
|
||||||
|
return $out; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,84 @@ |
|||||||
|
<?php |
||||||
|
|
||||||
|
/* For licensing terms, see /license.txt */ |
||||||
|
|
||||||
|
/** |
||||||
|
* Class. |
||||||
|
*/ |
||||||
|
class ImsAnswerMultipleChoice extends Answer implements ImsAnswerInterface |
||||||
|
{ |
||||||
|
/** |
||||||
|
* Return the XML flow for the possible answers. |
||||||
|
* |
||||||
|
* @param string $questionIdent |
||||||
|
* @param string $questionStatment |
||||||
|
* @param string $questionDesc |
||||||
|
* @param string $questionMedia |
||||||
|
* |
||||||
|
* @return string |
||||||
|
*/ |
||||||
|
public function imsExportResponses($questionIdent, $questionStatment, $questionDesc = '', $questionMedia = '') |
||||||
|
{ |
||||||
|
// @todo getAnswersList() converts the answers using api_html_entity_decode() |
||||||
|
$this->answerList = $this->getAnswersList(true); |
||||||
|
$out = ' <choiceInteraction responseIdentifier="'.$questionIdent.'" >'."\n"; |
||||||
|
$out .= ' <prompt><![CDATA['.formatExerciseQtiText($questionStatment).']]></prompt>'."\n"; |
||||||
|
if (is_array($this->answerList)) { |
||||||
|
foreach ($this->answerList as $current_answer) { |
||||||
|
$out .= '<simpleChoice identifier="answer_'.$current_answer['id'].'" fixed="false"> |
||||||
|
<![CDATA['.formatExerciseQtiText($current_answer['answer']).']]>'; |
||||||
|
if (isset($current_answer['comment']) && '' != $current_answer['comment']) { |
||||||
|
$out .= '<feedbackInline identifier="answer_'.$current_answer['id'].'"> |
||||||
|
<![CDATA['.formatExerciseQtiText($current_answer['comment']).']]> |
||||||
|
</feedbackInline>'; |
||||||
|
} |
||||||
|
$out .= '</simpleChoice>'."\n"; |
||||||
|
} |
||||||
|
} |
||||||
|
$out .= ' </choiceInteraction>'."\n"; |
||||||
|
|
||||||
|
return $out; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Return the XML flow of answer ResponsesDeclaration. |
||||||
|
*/ |
||||||
|
public function imsExportResponsesDeclaration($questionIdent, Question $question = null) |
||||||
|
{ |
||||||
|
$this->answerList = $this->getAnswersList(true); |
||||||
|
$type = $this->getQuestionType(); |
||||||
|
if (MCMA == $type) { |
||||||
|
$cardinality = 'multiple'; |
||||||
|
} else { |
||||||
|
$cardinality = 'single'; |
||||||
|
} |
||||||
|
|
||||||
|
$out = ' <responseDeclaration identifier="'.$questionIdent.'" cardinality="'.$cardinality.'" baseType="identifier">'."\n"; |
||||||
|
|
||||||
|
// Match the correct answers. |
||||||
|
if (is_array($this->answerList)) { |
||||||
|
$out .= ' <correctResponse>'."\n"; |
||||||
|
foreach ($this->answerList as $current_answer) { |
||||||
|
if ($current_answer['correct']) { |
||||||
|
$out .= ' <value>answer_'.$current_answer['id'].'</value>'."\n"; |
||||||
|
} |
||||||
|
} |
||||||
|
$out .= ' </correctResponse>'."\n"; |
||||||
|
} |
||||||
|
|
||||||
|
// Add the grading |
||||||
|
if (is_array($this->answerList)) { |
||||||
|
$out .= ' <mapping>'."\n"; |
||||||
|
foreach ($this->answerList as $current_answer) { |
||||||
|
if (isset($current_answer['grade'])) { |
||||||
|
$out .= ' <mapEntry mapKey="answer_'.$current_answer['id'].'" mappedValue="'.$current_answer['grade'].'" />'."\n"; |
||||||
|
} |
||||||
|
} |
||||||
|
$out .= ' </mapping>'."\n"; |
||||||
|
} |
||||||
|
|
||||||
|
$out .= ' </responseDeclaration>'."\n"; |
||||||
|
|
||||||
|
return $out; |
||||||
|
} |
||||||
|
} |
@ -1,422 +0,0 @@ |
|||||||
<?php |
|
||||||
|
|
||||||
/* For licensing terms, see /license.txt */ |
|
||||||
|
|
||||||
/** |
|
||||||
* Interface ImsAnswerInterface. |
|
||||||
*/ |
|
||||||
interface ImsAnswerInterface |
|
||||||
{ |
|
||||||
/** |
|
||||||
* @param $questionIdent |
|
||||||
* @param $questionStatment |
|
||||||
*/ |
|
||||||
public function imsExportResponses($questionIdent, $questionStatment); |
|
||||||
|
|
||||||
/** |
|
||||||
* @param $questionIdent |
|
||||||
*/ |
|
||||||
public function imsExportResponsesDeclaration($questionIdent, Question $question = null); |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* @author Claro Team <cvs@claroline.net> |
|
||||||
* @author Yannick Warnier <yannick.warnier@beeznest.com> - |
|
||||||
* updated ImsAnswerHotspot to match QTI norms |
|
||||||
*/ |
|
||||||
class Ims2Question extends Question |
|
||||||
{ |
|
||||||
/** |
|
||||||
* Include the correct answer class and create answer. |
|
||||||
* |
|
||||||
* @return Answer |
|
||||||
*/ |
|
||||||
public function setAnswer() |
|
||||||
{ |
|
||||||
switch ($this->type) { |
|
||||||
case MCUA: |
|
||||||
$answer = new ImsAnswerMultipleChoice($this->id); |
|
||||||
|
|
||||||
return $answer; |
|
||||||
case MCMA: |
|
||||||
$answer = new ImsAnswerMultipleChoice($this->id); |
|
||||||
|
|
||||||
return $answer; |
|
||||||
case TF: |
|
||||||
$answer = new ImsAnswerMultipleChoice($this->id); |
|
||||||
|
|
||||||
return $answer; |
|
||||||
case FIB: |
|
||||||
$answer = new ImsAnswerFillInBlanks($this->id); |
|
||||||
|
|
||||||
return $answer; |
|
||||||
case MATCHING: |
|
||||||
case MATCHING_DRAGGABLE: |
|
||||||
$answer = new ImsAnswerMatching($this->id); |
|
||||||
|
|
||||||
return $answer; |
|
||||||
case FREE_ANSWER: |
|
||||||
$answer = new ImsAnswerFree($this->id); |
|
||||||
|
|
||||||
return $answer; |
|
||||||
case HOT_SPOT: |
|
||||||
$answer = new ImsAnswerHotspot($this->id); |
|
||||||
|
|
||||||
return $answer; |
|
||||||
default: |
|
||||||
$answer = null; |
|
||||||
|
|
||||||
break; |
|
||||||
} |
|
||||||
|
|
||||||
return $answer; |
|
||||||
} |
|
||||||
|
|
||||||
public function createAnswersForm($form) |
|
||||||
{ |
|
||||||
return true; |
|
||||||
} |
|
||||||
|
|
||||||
public function processAnswersCreation($form, $exercise) |
|
||||||
{ |
|
||||||
return true; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Class. |
|
||||||
*/ |
|
||||||
class ImsAnswerMultipleChoice extends Answer implements ImsAnswerInterface |
|
||||||
{ |
|
||||||
/** |
|
||||||
* Return the XML flow for the possible answers. |
|
||||||
*/ |
|
||||||
public function imsExportResponses($questionIdent, $questionStatment) |
|
||||||
{ |
|
||||||
// @todo getAnswersList() converts the answers using api_html_entity_decode() |
|
||||||
$this->answerList = $this->getAnswersList(true); |
|
||||||
$out = ' <choiceInteraction responseIdentifier="'.$questionIdent.'" >'."\n"; |
|
||||||
$out .= ' <prompt><![CDATA['.formatExerciseQtiText($questionStatment).']]></prompt>'."\n"; |
|
||||||
if (is_array($this->answerList)) { |
|
||||||
foreach ($this->answerList as $current_answer) { |
|
||||||
$out .= '<simpleChoice identifier="answer_'.$current_answer['id'].'" fixed="false"> |
|
||||||
<![CDATA['.formatExerciseQtiText($current_answer['answer']).']]>'; |
|
||||||
if (isset($current_answer['comment']) && '' != $current_answer['comment']) { |
|
||||||
$out .= '<feedbackInline identifier="answer_'.$current_answer['id'].'"> |
|
||||||
<![CDATA['.formatExerciseQtiText($current_answer['comment']).']]> |
|
||||||
</feedbackInline>'; |
|
||||||
} |
|
||||||
$out .= '</simpleChoice>'."\n"; |
|
||||||
} |
|
||||||
} |
|
||||||
$out .= ' </choiceInteraction>'."\n"; |
|
||||||
|
|
||||||
return $out; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Return the XML flow of answer ResponsesDeclaration. |
|
||||||
*/ |
|
||||||
public function imsExportResponsesDeclaration($questionIdent, Question $question = null) |
|
||||||
{ |
|
||||||
$this->answerList = $this->getAnswersList(true); |
|
||||||
$type = $this->getQuestionType(); |
|
||||||
if (MCMA == $type) { |
|
||||||
$cardinality = 'multiple'; |
|
||||||
} else { |
|
||||||
$cardinality = 'single'; |
|
||||||
} |
|
||||||
|
|
||||||
$out = ' <responseDeclaration identifier="'.$questionIdent.'" cardinality="'.$cardinality.'" baseType="identifier">'."\n"; |
|
||||||
|
|
||||||
// Match the correct answers. |
|
||||||
if (is_array($this->answerList)) { |
|
||||||
$out .= ' <correctResponse>'."\n"; |
|
||||||
foreach ($this->answerList as $current_answer) { |
|
||||||
if ($current_answer['correct']) { |
|
||||||
$out .= ' <value>answer_'.$current_answer['id'].'</value>'."\n"; |
|
||||||
} |
|
||||||
} |
|
||||||
$out .= ' </correctResponse>'."\n"; |
|
||||||
} |
|
||||||
|
|
||||||
// Add the grading |
|
||||||
if (is_array($this->answerList)) { |
|
||||||
$out .= ' <mapping>'."\n"; |
|
||||||
foreach ($this->answerList as $current_answer) { |
|
||||||
if (isset($current_answer['grade'])) { |
|
||||||
$out .= ' <mapEntry mapKey="answer_'.$current_answer['id'].'" mappedValue="'.$current_answer['grade'].'" />'."\n"; |
|
||||||
} |
|
||||||
} |
|
||||||
$out .= ' </mapping>'."\n"; |
|
||||||
} |
|
||||||
|
|
||||||
$out .= ' </responseDeclaration>'."\n"; |
|
||||||
|
|
||||||
return $out; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Class. |
|
||||||
*/ |
|
||||||
class ImsAnswerFillInBlanks extends Answer implements ImsAnswerInterface |
|
||||||
{ |
|
||||||
private $answerList = []; |
|
||||||
private $gradeList = []; |
|
||||||
|
|
||||||
/** |
|
||||||
* Export the text with missing words. |
|
||||||
*/ |
|
||||||
public function imsExportResponses($questionIdent, $questionStatment) |
|
||||||
{ |
|
||||||
$this->answerList = $this->getAnswersList(true); |
|
||||||
$text = isset($this->answerText) ? $this->answerText : ''; |
|
||||||
if (is_array($this->answerList)) { |
|
||||||
foreach ($this->answerList as $key => $answer) { |
|
||||||
$key = $answer['id']; |
|
||||||
$answer = $answer['answer']; |
|
||||||
$len = api_strlen($answer); |
|
||||||
$text = str_replace('['.$answer.']', '<textEntryInteraction responseIdentifier="fill_'.$key.'" expectedLength="'.api_strlen($answer).'"/>', $text); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
return $text; |
|
||||||
} |
|
||||||
|
|
||||||
public function imsExportResponsesDeclaration($questionIdent, Question $question = null) |
|
||||||
{ |
|
||||||
$this->answerList = $this->getAnswersList(true); |
|
||||||
$this->gradeList = $this->getGradesList(); |
|
||||||
$out = ''; |
|
||||||
if (is_array($this->answerList)) { |
|
||||||
foreach ($this->answerList as $answer) { |
|
||||||
$answerKey = $answer['id']; |
|
||||||
$answer = $answer['answer']; |
|
||||||
$out .= ' <responseDeclaration identifier="fill_'.$answerKey.'" cardinality="single" baseType="identifier">'."\n"; |
|
||||||
$out .= ' <correctResponse>'."\n"; |
|
||||||
$out .= ' <value><![CDATA['.formatExerciseQtiText($answer).']]></value>'."\n"; |
|
||||||
$out .= ' </correctResponse>'."\n"; |
|
||||||
if (isset($this->gradeList[$answerKey])) { |
|
||||||
$out .= ' <mapping>'."\n"; |
|
||||||
$out .= ' <mapEntry mapKey="'.$answer.'" mappedValue="'.$this->gradeList[$answerKey].'"/>'."\n"; |
|
||||||
$out .= ' </mapping>'."\n"; |
|
||||||
} |
|
||||||
|
|
||||||
$out .= ' </responseDeclaration>'."\n"; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
return $out; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Class. |
|
||||||
*/ |
|
||||||
class ImsAnswerMatching extends Answer implements ImsAnswerInterface |
|
||||||
{ |
|
||||||
public $leftList = []; |
|
||||||
public $rightList = []; |
|
||||||
private $answerList = []; |
|
||||||
|
|
||||||
/** |
|
||||||
* Export the question part as a matrix-choice, with only one possible answer per line. |
|
||||||
*/ |
|
||||||
public function imsExportResponses($questionIdent, $questionStatment) |
|
||||||
{ |
|
||||||
$this->answerList = $this->getAnswersList(true); |
|
||||||
$maxAssociation = max(count($this->leftList), count($this->rightList)); |
|
||||||
|
|
||||||
$out = '<matchInteraction responseIdentifier="'.$questionIdent.'" maxAssociations="'.$maxAssociation.'">'."\n"; |
|
||||||
$out .= $questionStatment; |
|
||||||
|
|
||||||
//add left column |
|
||||||
$out .= ' <simpleMatchSet>'."\n"; |
|
||||||
if (is_array($this->leftList)) { |
|
||||||
foreach ($this->leftList as $leftKey => $leftElement) { |
|
||||||
$out .= ' |
|
||||||
<simpleAssociableChoice identifier="left_'.$leftKey.'" > |
|
||||||
<![CDATA['.formatExerciseQtiText($leftElement['answer']).']]> |
|
||||||
</simpleAssociableChoice>'."\n"; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
$out .= ' </simpleMatchSet>'."\n"; |
|
||||||
|
|
||||||
//add right column |
|
||||||
$out .= ' <simpleMatchSet>'."\n"; |
|
||||||
$i = 0; |
|
||||||
|
|
||||||
if (is_array($this->rightList)) { |
|
||||||
foreach ($this->rightList as $rightKey => $rightElement) { |
|
||||||
$out .= '<simpleAssociableChoice identifier="right_'.$i.'" > |
|
||||||
<![CDATA['.formatExerciseQtiText($rightElement['answer']).']]> |
|
||||||
</simpleAssociableChoice>'."\n"; |
|
||||||
$i++; |
|
||||||
} |
|
||||||
} |
|
||||||
$out .= ' </simpleMatchSet>'."\n"; |
|
||||||
$out .= '</matchInteraction>'."\n"; |
|
||||||
|
|
||||||
return $out; |
|
||||||
} |
|
||||||
|
|
||||||
public function imsExportResponsesDeclaration($questionIdent, Question $question = null) |
|
||||||
{ |
|
||||||
$this->answerList = $this->getAnswersList(true); |
|
||||||
$out = ' <responseDeclaration identifier="'.$questionIdent.'" cardinality="single" baseType="identifier">'."\n"; |
|
||||||
$out .= ' <correctResponse>'."\n"; |
|
||||||
|
|
||||||
$gradeArray = []; |
|
||||||
if (isset($this->leftList) && is_array($this->leftList)) { |
|
||||||
foreach ($this->leftList as $leftKey => $leftElement) { |
|
||||||
$i = 0; |
|
||||||
foreach ($this->rightList as $rightKey => $rightElement) { |
|
||||||
if (($leftElement['match'] == $rightElement['code'])) { |
|
||||||
$out .= ' <value>left_'.$leftKey.' right_'.$i.'</value>'."\n"; |
|
||||||
$gradeArray['left_'.$leftKey.' right_'.$i] = $leftElement['grade']; |
|
||||||
} |
|
||||||
$i++; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
$out .= ' </correctResponse>'."\n"; |
|
||||||
|
|
||||||
if (is_array($gradeArray)) { |
|
||||||
$out .= ' <mapping>'."\n"; |
|
||||||
foreach ($gradeArray as $gradeKey => $grade) { |
|
||||||
$out .= ' <mapEntry mapKey="'.$gradeKey.'" mappedValue="'.$grade.'"/>'."\n"; |
|
||||||
} |
|
||||||
$out .= ' </mapping>'."\n"; |
|
||||||
} |
|
||||||
|
|
||||||
$out .= ' </responseDeclaration>'."\n"; |
|
||||||
|
|
||||||
return $out; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Class. |
|
||||||
*/ |
|
||||||
class ImsAnswerHotspot extends Answer implements ImsAnswerInterface |
|
||||||
{ |
|
||||||
private $answerList = []; |
|
||||||
private $gradeList = []; |
|
||||||
|
|
||||||
/** |
|
||||||
* TODO update this to match hot spots instead of copying matching |
|
||||||
* Export the question part as a matrix-choice, with only one possible answer per line. |
|
||||||
*/ |
|
||||||
public function imsExportResponses($questionIdent, $questionStatment, $questionDesc = '', $questionMedia = '') |
|
||||||
{ |
|
||||||
$this->answerList = $this->getAnswersList(true); |
|
||||||
$mediaFilePath = api_get_course_path().'/document/images/'.$questionMedia; |
|
||||||
$sysQuestionMediaPath = api_get_path(SYS_COURSE_PATH).$mediaFilePath; |
|
||||||
$questionMedia = api_get_path(WEB_COURSE_PATH).$mediaFilePath; |
|
||||||
$mimetype = mime_content_type($sysQuestionMediaPath); |
|
||||||
if (empty($mimetype)) { |
|
||||||
$mimetype = 'image/jpeg'; |
|
||||||
} |
|
||||||
|
|
||||||
$text = ' <p>'.$questionStatment.'</p>'."\n"; |
|
||||||
$text .= ' <graphicOrderInteraction responseIdentifier="hotspot_'.$questionIdent.'">'."\n"; |
|
||||||
$text .= ' <prompt>'.$questionDesc.'</prompt>'."\n"; |
|
||||||
$text .= ' <object type="'.$mimetype.'" width="250" height="230" data="'.$questionMedia.'">-</object>'."\n"; |
|
||||||
if (is_array($this->answerList)) { |
|
||||||
foreach ($this->answerList as $key => $answer) { |
|
||||||
$key = $answer['id']; |
|
||||||
$answerTxt = $answer['answer']; |
|
||||||
$len = api_strlen($answerTxt); |
|
||||||
//coords are transformed according to QTIv2 rules here: http://www.imsproject.org/question/qtiv2p1pd/imsqti_infov2p1pd.html#element10663 |
|
||||||
$coords = ''; |
|
||||||
$type = 'default'; |
|
||||||
switch ($answer['hotspot_type']) { |
|
||||||
case 'square': |
|
||||||
$type = 'rect'; |
|
||||||
$res = []; |
|
||||||
$coords = preg_match('/^\s*(\d+);(\d+)\|(\d+)\|(\d+)\s*$/', $answer['hotspot_coord'], $res); |
|
||||||
$coords = $res[1].','.$res[2].','.((int) $res[1] + (int) $res[3]).','.((int) $res[2] + (int) $res[4]); |
|
||||||
|
|
||||||
break; |
|
||||||
case 'circle': |
|
||||||
$type = 'circle'; |
|
||||||
$res = []; |
|
||||||
$coords = preg_match('/^\s*(\d+);(\d+)\|(\d+)\|(\d+)\s*$/', $answer['hotspot_coord'], $res); |
|
||||||
$coords = $res[1].','.$res[2].','.sqrt(pow($res[1] - $res[3], 2) + pow($res[2] - $res[4])); |
|
||||||
|
|
||||||
break; |
|
||||||
case 'poly': |
|
||||||
$type = 'poly'; |
|
||||||
$coords = str_replace([';', '|'], [',', ','], $answer['hotspot_coord']); |
|
||||||
|
|
||||||
break; |
|
||||||
case 'delineation': |
|
||||||
$type = 'delineation'; |
|
||||||
$coords = str_replace([';', '|'], [',', ','], $answer['hotspot_coord']); |
|
||||||
|
|
||||||
break; |
|
||||||
} |
|
||||||
$text .= ' <hotspotChoice shape="'.$type.'" coords="'.$coords.'" identifier="'.$key.'"/>'."\n"; |
|
||||||
} |
|
||||||
} |
|
||||||
$text .= ' </graphicOrderInteraction>'."\n"; |
|
||||||
|
|
||||||
return $text; |
|
||||||
} |
|
||||||
|
|
||||||
public function imsExportResponsesDeclaration($questionIdent, Question $question = null) |
|
||||||
{ |
|
||||||
$this->answerList = $this->getAnswersList(true); |
|
||||||
$this->gradeList = $this->getGradesList(); |
|
||||||
$out = ' <responseDeclaration identifier="hotspot_'.$questionIdent.'" cardinality="ordered" baseType="identifier">'."\n"; |
|
||||||
if (is_array($this->answerList)) { |
|
||||||
$out .= ' <correctResponse>'."\n"; |
|
||||||
foreach ($this->answerList as $answerKey => $answer) { |
|
||||||
$answerKey = $answer['id']; |
|
||||||
$answer = $answer['answer']; |
|
||||||
$out .= '<value><![CDATA['.formatExerciseQtiText($answerKey).']]></value>'; |
|
||||||
} |
|
||||||
$out .= ' </correctResponse>'."\n"; |
|
||||||
} |
|
||||||
$out .= ' </responseDeclaration>'."\n"; |
|
||||||
|
|
||||||
return $out; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Class. |
|
||||||
*/ |
|
||||||
class ImsAnswerFree extends Answer implements ImsAnswerInterface |
|
||||||
{ |
|
||||||
/** |
|
||||||
* TODO implement |
|
||||||
* Export the question part as a matrix-choice, with only one possible answer per line. |
|
||||||
*/ |
|
||||||
public function imsExportResponses( |
|
||||||
$questionIdent, |
|
||||||
$questionStatment, |
|
||||||
$questionDesc = '', |
|
||||||
$questionMedia = '' |
|
||||||
) { |
|
||||||
$questionDesc = formatExerciseQtiText($questionDesc); |
|
||||||
|
|
||||||
return '<extendedTextInteraction responseIdentifier="'.$questionIdent.'" > |
|
||||||
<prompt> |
|
||||||
'.$questionDesc.' |
|
||||||
</prompt> |
|
||||||
</extendedTextInteraction>'; |
|
||||||
} |
|
||||||
|
|
||||||
public function imsExportResponsesDeclaration($questionIdent, Question $question = null) |
|
||||||
{ |
|
||||||
$out = ' <responseDeclaration identifier="'.$questionIdent.'" cardinality="single" baseType="string">'; |
|
||||||
$out .= '<outcomeDeclaration identifier="SCORE" cardinality="single" baseType="float"> |
|
||||||
<defaultValue><value>'.$question->weighting.'</value></defaultValue></outcomeDeclaration>'; |
|
||||||
$out .= ' </responseDeclaration>'."\n"; |
|
||||||
|
|
||||||
return $out; |
|
||||||
} |
|
||||||
} |
|
@ -0,0 +1,7 @@ |
|||||||
|
{# Displayed from exercise_result.php #} |
||||||
|
|
||||||
|
{{ page_top }} |
||||||
|
|
||||||
|
{{ page_content }} |
||||||
|
|
||||||
|
{{ page_bottom }} |
Loading…
Reference in new issue