Skip to content

Commit

Permalink
Template Defaults/Template Processing at test level enhancement.
Browse files Browse the repository at this point in the history
  • Loading branch information
= committed Oct 27, 2015
1 parent 692b8e1 commit 90c37db
Show file tree
Hide file tree
Showing 8 changed files with 174 additions and 96 deletions.
2 changes: 1 addition & 1 deletion src/qtism/data/AssessmentItem.php
Original file line number Diff line number Diff line change
Expand Up @@ -752,7 +752,7 @@ public function getComponents()
);

if ($this->hasTemplateProcessing() === true) {
$comp[] = $this->getResponseProcessing();
$comp[] = $this->getTemplateProcessing();
}

$comp = array_merge($comp, $this->getStylesheets()->getArrayCopy());
Expand Down
2 changes: 1 addition & 1 deletion src/qtism/data/ExtendedAssessmentItemRef.php
Original file line number Diff line number Diff line change
Expand Up @@ -513,7 +513,7 @@ public function getComponents()
);

if ($this->hasTemplateProcessing() === true) {
$components[] = $this->getResponseProcessing();
$components[] = $this->getTemplateProcessing();
}

if ($this->hasResponseProcessing() === true) {
Expand Down
54 changes: 43 additions & 11 deletions src/qtism/runtime/tests/AssessmentItemSession.php
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,13 @@ class AssessmentItemSession extends State
* @var \qtism\data\state\ShufflingCollection
*/
private $shufflingStates;

/**
* Whether or not the template processing must occur automatically.
*
* @var boolean
*/
private $autoTemplateProcessing = true;

/**
* Create a new AssessmentItemSession object.
Expand All @@ -247,18 +254,20 @@ class AssessmentItemSession extends State
* @param \qtism\data\IAssessmentItem $assessmentItem The description of the item that the session handles.
* @param integer $navigationMode (optional) A value from the NavigationMode enumeration.
* @param integer $submissionMode (optional) A value from the SubmissionMode enumeration.
* @param boolean $autoTemplateProcessing (optional) Whether or not template processing must occur automatically. Default is true.
* @throws \InvalidArgumentException If $navigationMode or $submission is not a value from the NavigationMode/SubmissionMode enumeration.
* @see \qtism\runtime\tests\AssessmentItemSession::setItemSessionControl() The setItemSessionControl() method.
* @see \qtism\runtime\tests\AssessmentItemSession::setTimeLimits() The setTimeLimits() method.
*/
public function __construct(IAssessmentItem $assessmentItem, $navigationMode = NavigationMode::LINEAR, $submissionMode = SubmissionMode::INDIVIDUAL)
public function __construct(IAssessmentItem $assessmentItem, $navigationMode = NavigationMode::LINEAR, $submissionMode = SubmissionMode::INDIVIDUAL, $autoTemplateProcessing = true)
{
parent::__construct();

$this->setAssessmentItem($assessmentItem);
$this->setItemSessionControl(new ItemSessionControl());
$this->setNavigationMode($navigationMode);
$this->setSubmissionMode($submissionMode);
$this->setAutoTemplateProcessing($autoTemplateProcessing);

// -- Create the built-in response variables.
$this->setVariable(new ResponseVariable('numAttempts', Cardinality::SINGLE, BaseType::INTEGER, new QtiInteger(0)));
Expand Down Expand Up @@ -532,9 +541,28 @@ public function setShufflingStates(ShufflingCollection $shufflingStates)
*
* @param \qtism\data\state\ShufflingCollection $shufflingStates
*/
public function getShufflingStates() {
public function getShufflingStates()
{
return $this->shufflingStates;
}

/**
* Set whether or not template processing must occur automatically.
*
* @param boolean $autoTemplateProcessing
*/
public function setAutoTemplateProcessing($autoTemplateProcessing)
{
$this->autoTemplateProcessing = $autoTemplateProcessing;
}

/**
* Know whether or not template processing must occur automatically.
*/
public function mustAutoTemplateProcessing()
{
return $this->autoTemplateProcessing;
}

/**
* Set the current time of the running assessment item session.
Expand Down Expand Up @@ -606,15 +634,18 @@ public function beginItemSession()
}
}

// Apply templateProcessing.
$templateProcessing = $this->templateProcessing();
// Apply templateProcessing if needed.
$templateProcessing = false;
if ($this->mustAutoTemplateProcessing() === true) {
$templateProcessing = $this->templateProcessing();

foreach ($data as $identifier => $variable) {
if (in_array($identifier, $filter) === false) {

// Outcome variables are applied their default value if any.
if ($variable instanceof OutcomeVariable || ($variable instanceof TemplateVariable && $templateProcessing === false)) {
$variable->applyDefaultValue();
foreach ($data as $identifier => $variable) {
if (in_array($identifier, $filter) === false) {

// Outcome variables are applied their default value if any.
if ($variable instanceof OutcomeVariable || ($variable instanceof TemplateVariable && $templateProcessing === false)) {
$variable->applyDefaultValue();
}
}
}
}
Expand Down Expand Up @@ -1287,7 +1318,7 @@ private function mustModalFeedback()
* @throws \qtism\runtime\rules\RuleProcessingException
* @return boolean Whether or not the template processing occured.
*/
protected function templateProcessing()
public function templateProcessing()
{
$assessmentItem = $this->getAssessmentItem();
if (($templateProcessing = $assessmentItem->getTemplateProcessing()) !== null) {
Expand All @@ -1296,6 +1327,7 @@ protected function templateProcessing()

return true;
} else {

return false;
}
}
Expand Down
129 changes: 78 additions & 51 deletions src/qtism/runtime/tests/AssessmentTestSession.php
Original file line number Diff line number Diff line change
Expand Up @@ -642,6 +642,11 @@ public function beginAttempt()
// Time limits are OK! Let's try to begin the attempt.
$routeItem = $this->getCurrentRouteItem();
$session = $this->getCurrentAssessmentItemSession();

if ($routeItem->getTestPart()->getNavigationMode() === NavigationMode::LINEAR && $session['numAttempts']->getValue() === 0) {
$this->applyTemplateDefaults($session);
$session->templateProcessing();
}

try {
if ($this->getCurrentSubmissionMode() === SubmissionMode::INDIVIDUAL) {
Expand Down Expand Up @@ -1812,17 +1817,29 @@ public function offsetExists($offset)
* @param integer $navigationMode
* @param integer $submissionMode
* @return \qtism\runtime\tests\AssessmentItemSession
* @throws \qtism\runtime\expressions\ExpressionProcessingException|\qtism\runtime\expressions\operators\OperatorProcessingException If something wrong happens when initializing templateDefaults.
*/
protected function createAssessmentItemSession(IAssessmentItem $assessmentItem, $navigationMode, $submissionMode)
{
$session = $this->getSessionManager()->createAssessmentItemSession($assessmentItem, $navigationMode, $submissionMode);
$session = $this->getSessionManager()->createAssessmentItemSession($assessmentItem, $navigationMode, $submissionMode, false);

return $session;
}

/**
* Apply the templateDefault values to the item $session.
*
* param \qtism\runtime\tests\AssessmentItemSession $session
* @throws \qtism\runtime\expressions\ExpressionProcessingException|\qtism\runtime\expressions\operators\OperatorProcessingException If something wrong happens when initializing templateDefaults.
*/
protected function applyTemplateDefaults(AssessmentItemSession $session)
{
$templateDefaults = $session->getAssessmentItem()->getTemplateDefaults();

if (count($templateDefaults) > 0) {
// Some templateVariable default values must have to be changed...

foreach ($session->getAssessmentItem()->getTemplateDefaults() as $templateDefault) {

$identifier = $templateDefault->getTemplateIdentifier();
$expression = $templateDefault->getExpression();
$variable = $session->getVariable($identifier);
Expand All @@ -1835,8 +1852,6 @@ protected function createAssessmentItemSession(IAssessmentItem $assessmentItem,
}
}
}

return $session;
}

/**
Expand Down Expand Up @@ -1877,62 +1892,74 @@ protected function initializeTestDurations()
protected function selectEligibleItems()
{
$route = $this->getRoute();
$oldPosition = $route->getPosition();
$adaptive = $this->isAdaptive();

// In this loop, we select at least the first routeItem we find as eligible.
while ($route->valid() === true) {

$routeItem = $route->current();
$itemRef = $routeItem->getAssessmentItemRef();
$occurence = $routeItem->getOccurence();

if ($route->valid() === true) {

$session = $this->getItemSession($itemRef, $occurence);
$oldPosition = $route->getPosition();
$adaptive = $this->isAdaptive();
$initialTestPart = $route->current()->getTestPart();
$isInitalRouteItemFirstOfTestPart = $route->isFirstOfTestPart();

// Does such a session exist for item + occurence?
if ($session === false) {

// Instantiate the item session...
$testPart = $routeItem->getTestPart();
$navigationMode = $testPart->getNavigationMode();
$submissionMode = $testPart->getSubmissionMode();

$session = $this->createAssessmentItemSession($itemRef, $navigationMode, $submissionMode);
// In this loop, we select at least the first routeItem we find as eligible.
while ($route->valid() === true) {

// Determine the item session control.
if (($control = $routeItem->getItemSessionControl()) !== null) {
$session->setItemSessionControl($control->getItemSessionControl());
}

// Determine the time limits.
if ($itemRef->hasTimeLimits() === true) {
$session->setTimeLimits($itemRef->getTimeLimits());
}

$this->addItemSession($session, $occurence);
$routeItem = $route->current();
$itemRef = $routeItem->getAssessmentItemRef();
$occurence = $routeItem->getOccurence();

// If we know "what time it is", we transmit
// that information to the eligible item.
if ($this->hasTimeReference() === true) {
$session->setTime($this->getTimeReference());
$session = $this->getItemSession($itemRef, $occurence);

// Does such a session exist for item + occurence?
if ($session === false) {

// Instantiate the item session...
$testPart = $routeItem->getTestPart();
$navigationMode = $testPart->getNavigationMode();
$submissionMode = $testPart->getSubmissionMode();

$session = $this->createAssessmentItemSession($itemRef, $navigationMode, $submissionMode);

// Determine the item session control.
if (($control = $routeItem->getItemSessionControl()) !== null) {
$session->setItemSessionControl($control->getItemSessionControl());
}

// Determine the time limits.
if ($itemRef->hasTimeLimits() === true) {
$session->setTimeLimits($itemRef->getTimeLimits());
}

$this->addItemSession($session, $occurence);

// If we know "what time it is", we transmit
// that information to the eligible item.
if ($this->hasTimeReference() === true) {
$session->setTime($this->getTimeReference());
}

$session->beginItemSession();

// Deal with template defaults and template processing for non linear case.
if ($testPart === $initialTestPart && $initialTestPart->getNavigationMode() === NavigationMode::NONLINEAR && $isInitalRouteItemFirstOfTestPart === true) {
$this->applyTemplateDefaults($session);
$session->templateProcessing();
}
}

$session->beginItemSession();
if ($adaptive === true) {
// We cannot foresee more items to be selected for presentation
// because the rest of the sequence is linear and might contain
// branching rules or preconditions.
break;
} else {
// We continue to search for route items that are selectable for
// presentation to the candidate.
$route->next();
}
}

if ($adaptive === true) {
// We cannot foresee more items to be selected for presentation
// because the rest of the sequence is linear and might contain
// branching rules or preconditions.
break;
} else {
// We continue to search for route items that are selectable for
// presentation to the candidate.
$route->next();
}
$route->setPosition($oldPosition);
}

$route->setPosition($oldPosition);
}

/**
Expand Down
2 changes: 1 addition & 1 deletion src/qtism/runtime/tests/Route.php
Original file line number Diff line number Diff line change
Expand Up @@ -914,7 +914,7 @@ public function isFirstOfTestPart()
}

$previousPosition = $this->getPosition() - 1;
if ($previousPosition === 0) {
if ($previousPosition === -1) {
// This is the very first RouteItem of the whole Route.
return true;
} elseif ($this->getRouteItemAt($previousPosition)->getTestPart() !== $this->current()->getTestPart()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -827,24 +827,25 @@ public function testTemplateDefault1() {
$QTPL1Session = $QTPL1Sessions[0];

// The the session is correctly instantiated, with the <templateDefault>s in force.
// In linear mode, the templateDefaults are applied just before the first attempt.
$this->assertEquals(AssessmentItemSessionState::INITIAL, $QTPL1Session->getState());
$this->assertEquals(1.0, $QTPL1Session->getVariable('GOODSCORE')->getDefaultValue()->getValue());
$this->assertEquals(0.0, $QTPL1Session->getVariable('WRONGSCORE')->getDefaultValue()->getValue());
$this->assertEquals(1.0, $session['QTPL1.GOODSCORE']->getValue());
$this->assertEquals(1.0, $QTPL1Session['GOODSCORE']->getValue());
$this->assertEquals(0.0, $session['QTPL1.WRONGSCORE']->getValue());
$this->assertEquals(0.0, $QTPL1Session['WRONGSCORE']->getValue());
$this->assertNull($QTPL1Session->getVariable('GOODSCORE')->getDefaultValue());
$this->assertNull($QTPL1Session->getVariable('WRONGSCORE')->getDefaultValue());
$this->assertNull($session['QTPL1.GOODSCORE']);
$this->assertNull($QTPL1Session['GOODSCORE']);
$this->assertNull($session['QTPL1.WRONGSCORE']);
$this->assertNull($QTPL1Session['WRONGSCORE']);

$QTPL2Sessions = $session->getAssessmentItemSessions('QTPL2');
$QTPL2Session = $QTPL2Sessions[0];

$this->assertEquals(AssessmentItemSessionState::INITIAL, $QTPL2Session->getState());
$this->assertEquals(2.0, $QTPL2Session->getVariable('GOODSCORE')->getDefaultValue()->getValue());
$this->assertEquals(-1.0, $QTPL2Session->getVariable('WRONGSCORE')->getDefaultValue()->getValue());
$this->assertEquals(2.0, $session['QTPL2.GOODSCORE']->getValue());
$this->assertEquals(2.0, $QTPL2Session['GOODSCORE']->getValue());
$this->assertEquals(-1.0, $session['QTPL2.WRONGSCORE']->getValue());
$this->assertEquals(-1.0, $QTPL2Session['WRONGSCORE']->getValue());
$this->assertNull($QTPL2Session->getVariable('GOODSCORE')->getDefaultValue());
$this->assertNull($QTPL2Session->getVariable('WRONGSCORE')->getDefaultValue());
$this->assertNull($session['QTPL2.GOODSCORE']);
$this->assertNull($QTPL2Session['GOODSCORE']);
$this->assertNull($session['QTPL2.WRONGSCORE']);
$this->assertNull($QTPL2Session['WRONGSCORE']);

// Now let's make sure the persistence works correctly when <templateDefault>s are in force...
// We do this by testing again that default values are correctly initialized within their respective
Expand All @@ -854,23 +855,23 @@ public function testTemplateDefault1() {
$session = $storage->retrieve($test, $sessionId);

$this->assertEquals(AssessmentItemSessionState::INITIAL, $QTPL1Session->getState());
$this->assertEquals(1.0, $QTPL1Session->getVariable('GOODSCORE')->getDefaultValue()->getValue());
$this->assertEquals(0.0, $QTPL1Session->getVariable('WRONGSCORE')->getDefaultValue()->getValue());
$this->assertEquals(1.0, $session['QTPL1.GOODSCORE']->getValue());
$this->assertEquals(1.0, $QTPL1Session['GOODSCORE']->getValue());
$this->assertEquals(0.0, $session['QTPL1.WRONGSCORE']->getValue());
$this->assertEquals(0.0, $QTPL1Session['WRONGSCORE']->getValue());
$this->assertNull($QTPL1Session->getVariable('GOODSCORE')->getDefaultValue());
$this->assertNull($QTPL1Session->getVariable('WRONGSCORE')->getDefaultValue());
$this->assertNull($session['QTPL1.GOODSCORE']);
$this->assertNull($QTPL1Session['GOODSCORE']);
$this->assertNull($session['QTPL1.WRONGSCORE']);
$this->assertNull($QTPL1Session['WRONGSCORE']);

$QTPL2Sessions = $session->getAssessmentItemSessions('QTPL2');
$QTPL2Session = $QTPL2Sessions[0];

$this->assertEquals(AssessmentItemSessionState::INITIAL, $QTPL2Session->getState());
$this->assertEquals(2.0, $QTPL2Session->getVariable('GOODSCORE')->getDefaultValue()->getValue());
$this->assertEquals(-1.0, $QTPL2Session->getVariable('WRONGSCORE')->getDefaultValue()->getValue());
$this->assertEquals(2.0, $session['QTPL2.GOODSCORE']->getValue());
$this->assertEquals(2.0, $QTPL2Session['GOODSCORE']->getValue());
$this->assertEquals(-1.0, $session['QTPL2.WRONGSCORE']->getValue());
$this->assertEquals(-1.0, $QTPL2Session['WRONGSCORE']->getValue());
$this->assertNull($QTPL2Session->getVariable('GOODSCORE')->getDefaultValue());
$this->assertNull($QTPL2Session->getVariable('WRONGSCORE')->getDefaultValue());
$this->assertNull($session['QTPL2.GOODSCORE']);
$this->assertNull($QTPL2Session['GOODSCORE']);
$this->assertNull($session['QTPL2.WRONGSCORE']);
$this->assertNull($QTPL2Session['WRONGSCORE']);

// It seems to be ok! Let's take the test!
$session->beginAttempt();
Expand Down Expand Up @@ -949,4 +950,4 @@ public function testTemplateDefault1() {
$this->assertEquals(AssessmentItemSessionState::CLOSED, $QTPL1Session->getState());
$this->assertEquals(AssessmentItemSessionState::CLOSED, $QTPL2Session->getState());
}
}
}
Loading

0 comments on commit 90c37db

Please sign in to comment.