Skip to content

Commit

Permalink
Fixed issue #05861: Group level relevance error: irrelevant mandatory…
Browse files Browse the repository at this point in the history
… questions within group are not ignored

Dev added sample survey to test this functionality
Dev Partial fix: works fine for group-by-group and survey-at-a-time mode; but not for question-by-question
Dev Issue:  Navigation index is showing hidden groups
Dev - this ports commit 4b5e240 to Yii
  • Loading branch information
TMSWhite committed Mar 2, 2012
1 parent abd6a6d commit 514c9df
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 28 deletions.
8 changes: 7 additions & 1 deletion application/helpers/SurveyRuntimeHelper.php
Expand Up @@ -874,7 +874,13 @@ function checkconditions(value, name, type, evt_type)
$redata = compact(array_keys(get_defined_vars()));

echo "\n\n<!-- START THE GROUP -->\n";
echo "\n\n<div id='group-$gid'>\n";
echo "\n\n<div id='group-$gid'";
$gnoshow = LimeExpressionManager::GroupIsIrrelevantOrHidden($gid);
if ($gnoshow)
{
echo " style='display: none;'";
}
echo ">\n";
echo templatereplace(file_get_contents("$thistpl/startgroup.pstpl"), array(), $redata);
echo "\n";

Expand Down
94 changes: 67 additions & 27 deletions application/helpers/expressions/em_manager_helper.php
Expand Up @@ -2496,12 +2496,13 @@ static function QuestionIsRelevant($qid)
* @param <type> $gid
* @return boolean
*/
static function GroupIsRelevant($gid)
static function GroupIsIrrelevantOrHidden($gid)
{
$LEM =& LimeExpressionManager::singleton();
$grel = (isset($_SESSION['relevanceStatus']['G' . $gid]) ? $_SESSION['relevanceStatus']['G' . $gid] : 1); // group-level relevance based upon grelevance equation
$qgrel = (isset($LEM->gid2relevanceStatus[$gid]) ? isset($LEM->gid2relevanceStatus[$gid]) : 1); // group-level relevance based upon ensuring at least one contained question is relevant
return ($grel && $qgrel);
$gseq = (isset($LEM->groupId2groupSeq[$gid]) ? $LEM->groupId2groupSeq[$gid] : -1);
$gshow = (isset($LEM->indexGseq[$gseq]['show']) ? $LEM->indexGseq[$gseq]['show'] : true); // default to true?
return !($grel && $gshow);
}

/**
Expand Down Expand Up @@ -3781,13 +3782,13 @@ private function _ValidateSurvey()
if ($gStatus['relevant']) {
$srel = true;
}
if (!$gStatus['hidden']) {
if ($gStatus['relevant'] && !$gStatus['hidden']) {
$shidden=false;
}
if ($gStatus['mandViolation']) {
if ($gStatus['relevant'] && !$gStatus['hidden'] && $gStatus['mandViolation']) {
$smandViolation = true;
}
if (!$gStatus['valid']) {
if ($gStatus['relevant'] && !$gStatus['hidden'] && !$gStatus['valid']) {
$svalid=false;
}
if ($gStatus['anyUnanswered']) {
Expand Down Expand Up @@ -3866,19 +3867,19 @@ function _ValidateGroup($groupSeq)

$updatedValues = array_merge($updatedValues,$qStatus['updatedValues']);

if ($qStatus['relevant']==true) {
if ($gRelInfo['result']==true && $qStatus['relevant']==true) {
$grel = $gRelInfo['result']; // true; // at least one question relevant
}
if ($qStatus['hidden']==false && $qStatus['relevant'] == true) {
$ghidden=false; // at least one question is visible
}
if ($qStatus['mandViolation']==true) {
if ($qStatus['relevant']==true && $qStatus['hidden']==false && $qStatus['mandViolation']==true) {
$gmandViolation=true; // at least one relevant question fails mandatory test
}
if ($qStatus['anyUnanswered']==true) {
$ganyUnanswered=true;
}
if ($qStatus['valid']==false) {
if ($qStatus['relevant']==true && $qStatus['hidden']==false && $qStatus['valid']==false) {
$gvalid=false; // at least one question fails validity constraints
}
$currentQset[$qStatus['info']['qid']] = $qStatus;
Expand Down Expand Up @@ -4008,6 +4009,9 @@ function _ValidateQuestion($questionSeq)
$qhidden = $qInfo['hidden'];
$debug_qmessage='';

$gRelInfo = $LEM->gRelInfo[$qInfo['gseq']];
$grel = $gRelInfo['result'];

///////////////////////////
// IS QUESTION RELEVANT? //
///////////////////////////
Expand Down Expand Up @@ -4544,7 +4548,7 @@ function _ValidateQuestion($questionSeq)
// CREATE ARRAY OF VALUES THAT NEED TO BE SILENTLY UPDATED //
/////////////////////////////////////////////////////////////
$updatedValues=array();
if (!$qrel)
if (!$qrel || !$grel)
{
// If not relevant, then always NULL it in the database
$sgqas = explode('|',$LEM->qid2code[$qid]);
Expand Down Expand Up @@ -4927,6 +4931,7 @@ static function GetRelevanceAndTailoringJavaScript()
$pageRelevanceInfo=array();
$qidList = array(); // list of questions used in relevance and tailoring
$gidList = array(); // list of groups on this page
$gid_qidList = array(); // list of qids using relevance/tailoring within each group

if (is_array($LEM->pageRelevanceInfo))
{
Expand All @@ -4942,7 +4947,6 @@ static function GetRelevanceAndTailoringJavaScript()
$valEqns = array();
$relEqns = array();
$relChangeVars = array();
$relFnCalls = array();

if (is_array($pageRelevanceInfo))
{
Expand Down Expand Up @@ -4989,6 +4993,11 @@ static function GetRelevanceAndTailoringJavaScript()
}

$qidList[$arg['qid']] = $arg['qid'];
if (!isset($gid_qidList[$arg['gid']]))
{
$gid_qidList[$arg['gid']] = array();
}
$gid_qidList[$arg['gid']][$arg['qid']] = '0'; // means the qid is within this gid, but may not have a relevance equation

// Now check whether any sub-question validation needs to be performed
$subqValidations = array();
Expand All @@ -5013,24 +5022,18 @@ static function GetRelevanceAndTailoringJavaScript()
$validationEqns = $LEM->qid2validationEqn[$arg['qid']]['eqn'];
}

// Process relevance for question $arg['qid'];
$relevance = $arg['relevancejs'];

$relChangeVars[] = " relChange" . $arg['qid'] . "=false;\n"; // detect change in relevance status

if (($relevance == '' || $relevance == '1') && count($tailorParts) == 0 && count($subqParts) == 0 && count($subqValidations) == 0 && count($validationEqns) == 0)
{
// Only show constitutively true relevances if there is tailoring that should be done.
// $jsParts[] = "document.getElementById('relevance" . $arg['qid'] . "').value='1'; // always true\n";
$relParts[] = "$('#relevance" . $arg['qid'] . "').val('1'); // always true\n";
continue;
}
$relevance = ($relevance == '') ? '1' : $relevance;
// $jsResultVar = $LEM->em->GetJsVarFor($arg['jsResultVar']);
// $relParts[] = "\n// Process Relevance for Question " . $arg['qid'];
// if ($relevance != 1)
// {
// $relParts[] = ": { " . $arg['eqn'] . " }";
// }
$relParts[] = "\nif (" . $relevance . ")\n{\n";
////////////////////////////////////////////////////////////////////////
// DO ALL ARRAY FILTERING FIRST - MAY AFFECT VALIDATION AND TAILORING //
Expand Down Expand Up @@ -5268,7 +5271,7 @@ static function GetRelevanceAndTailoringJavaScript()
$jsResultVar = $LEM->em->GetJsVarFor($arg['jsResultVar']);
$relParts[] = " $('#" . substr($jsResultVar,1,-1) . "').val(escape(jQuery.trim(LEMstrip_tags($('#question" . $arg['qid'] . " .em_equation').find('span').html()))).replace(/%20/g,' '));\n";
}
$relParts[] = " relChange" . $arg['qid'] . "=true;\n";
$relParts[] = " relChange" . $arg['qid'] . "=true;\n"; // any change to this value should trigger a propagation of changess
$relParts[] = " $('#relevance" . $arg['qid'] . "').val('1');\n";

$relParts[] = "}\n";
Expand All @@ -5277,7 +5280,7 @@ static function GetRelevanceAndTailoringJavaScript()
$relParts[] = "else {\n";
$relParts[] = " $('#question" . $arg['qid'] . "').hide();\n";
$relParts[] = " $('#display" . $arg['qid'] . "').val('');\n";
$relParts[] = " if ($('#relevance" . $arg['qid'] . "').val()=='1') { relChange" . $arg['qid'] . "=true; }\n";
$relParts[] = " if ($('#relevance" . $arg['qid'] . "').val()=='1') { relChange" . $arg['qid'] . "=true; }\n"; // only propagate changes if changing from relevant to irrelevant
$relParts[] = " $('#relevance" . $arg['qid'] . "').val('0');\n";
$relParts[] = "}\n";
}
Expand All @@ -5292,6 +5295,7 @@ static function GetRelevanceAndTailoringJavaScript()
$relJsVarsUsed = array_merge($relJsVarsUsed,$valJsVarsUsed);
$relJsVarsUsed = array_unique($relJsVarsUsed);
$qrelQIDs = array();
$qrelGIDs = array(); // so that any group-level change is also propagated
foreach ($relJsVarsUsed as $jsVar)
{
if ($jsVar != '' && isset($LEM->knownVars[substr($jsVar,4)]['qid']))
Expand All @@ -5305,12 +5309,16 @@ static function GetRelevanceAndTailoringJavaScript()
continue; // don't make dependent upon itself
}
$qrelQIDs[] = 'relChange' . $_qid;
$qrelGIDs[] = 'relChangeG' . $knownVar['gid'];
}
}
$qrelGIDs[] = 'relChangeG' . $arg['gid']; // so if current group changes visibility, re-tailor it.
$qrelQIDs = array_unique($qrelQIDs);
$qrelGIDs = array_unique($qrelGIDs);
if ($LEM->surveyMode=='question')
{
$qrelQIDs=array(); // in question-by-questin mode, should never test for dependencies on self or other questions.
$qrelGIDs=array();
}

$qrelJS = "function LEMrel" . $arg['qid'] . "(sgqa){\n";
Expand All @@ -5319,16 +5327,26 @@ static function GetRelevanceAndTailoringJavaScript()
{
$qrelJS .= " if(" . implode(' || ', $qrelQIDs) . "){\n ;\n }\n else";
}
if (count($qrelGIDs) > 0)
{
$qrelJS .= " if(" . implode(' || ', $qrelGIDs) . "){\n ;\n }\n else";
}
$qrelJS .= " if (typeof sgqa !== 'undefined' && !LEMregexMatch('/ java' + sgqa + ' /', UsesVars)) {\n return;\n }\n";
$qrelJS .= implode("",$relParts);
$qrelJS .= "}\n";
$relEqns[] = $qrelJS;

$relFnCalls[] = " LEMrel" . $arg['qid'] . "(sgqa);\n";
$gid_qidList[$arg['gid']][$arg['qid']] = '1'; // means has an explicit LEMrel() function
}
}

// Finally do Group-level Relevance. Might consider surrounding questions with group-level relevance, but might message up Q.NAOK - not sure.
foreach(array_keys($gid_qidList) as $_gid)
{
$relChangeVars[] = " relChangeG" . $_gid . "=false;\n";
}
$jsParts[] = implode("",$relChangeVars);

// Process relevance for each group; and if group is relevant, process each contained question in order
foreach ($LEM->gRelInfo as $gr)
{
if (!array_key_exists($gr['gid'],$gidList)) {
Expand All @@ -5340,12 +5358,35 @@ static function GetRelevanceAndTailoringJavaScript()
// $jsParts[] = ": { " . $gr['eqn'] . " }";
$jsParts[] = "\nif (" . $gr['relevancejs'] . ") {\n";
$jsParts[] = " $('#group-" . $gr['gid'] . "').show();\n";
$jsParts[] = " relChangeG" . $gr['gid'] . "=true;\n";
$jsParts[] = " $('#relevanceG" . $gr['gid'] . "').val(1);\n";

$qids = $gid_qidList[$gr['gid']];
foreach ($qids as $_qid=>$_val)
{
if ($_val==1)
{
$jsParts[] = " LEMrel" . $_qid . "(sgqa);\n";
}
}

$jsParts[] = "}\nelse {\n";
$jsParts[] = " $('#group-" . $gr['gid'] . "').hide();\n";
$jsParts[] = " if ($('#relevanceG" . $gr['gid'] . "').val()=='1') { relChangeG" . $gr['gid'] . "=true; }\n";
$jsParts[] = " $('#relevanceG" . $gr['gid'] . "').val(0);\n";
$jsParts[] = "}\n";
}
else
{
$qids = $gid_qidList[$gr['gid']];
foreach ($qids as $_qid=>$_val)
{
if ($_val == 1)
{
$jsParts[] = " LEMrel" . $_qid . "(sgqa);\n";
}
}
}
// now make sure any needed variables are accessible
$vars = explode('|',$gr['relevanceVars']);
if (is_array($vars))
Expand All @@ -5354,9 +5395,6 @@ static function GetRelevanceAndTailoringJavaScript()
}
}

$jsParts[] = implode("",$relChangeVars);
$jsParts[] = implode("",$relFnCalls);

$jsParts[] = "\n}\n";

$jsParts[] = implode("\n",$relEqns);
Expand Down Expand Up @@ -5456,7 +5494,6 @@ static function GetRelevanceAndTailoringJavaScript()
$jsParts[] = "<input type='hidden' id='" . $jsVar . "' name='" . $jsVar . "' value='" . htmlspecialchars($undeclaredVal[$jsVar],ENT_QUOTES) . "'/>\n";
}
}
sort($qidList,SORT_NUMERIC);
foreach ($qidList as $qid)
{
if (isset($_SESSION['relevanceStatus'])) {
Expand Down Expand Up @@ -6107,8 +6144,11 @@ static function ProcessCurrentResponses()
{
$relevant=false;
$qid = $qinfo['info']['qid'];
$gid = $qinfo['info']['gid'];
$relevant = (isset($_POST['relevance' . $qid]) ? ($_POST['relevance' . $qid] == 1) : false);
$grelevant = (isset($_POST['relevanceG' . $gid]) ? ($_POST['relevanceG' . $gid] == 1) : false);
$_SESSION['relevanceStatus'][$qid] = $relevant;
$_SESSION['relevanceStatus']['G' . $gid] = $grelevant;
if (isset($qinfo['info']['rowdivid']) && $qinfo['info']['rowdivid']!='')
{
$rowdivid=$qinfo['info']['rowdivid'];
Expand All @@ -6120,7 +6160,7 @@ static function ProcessCurrentResponses()
}
foreach (explode('|',$qinfo['sgqa']) as $sq)
{
if ($relevant)
if ($relevant && $grelevant)
{
$value = (isset($_POST[$sq]) ? $_POST[$sq] : '');
$type = $qinfo['info']['type'];
Expand Down

0 comments on commit 514c9df

Please sign in to comment.