Jump to content

Need help upgrading script featuring arrays within an array


PHPBear

Recommended Posts

I'm developing a database-powered quiz and need help upgrading the basic script. The original script (posted below) works fine, but it has some limitations. So someone suggested an alternate script (posted next) that turns each answer (or group of answers into an array within an array.

 

However, I can't get the new script to work. My latest attempt is posted below the first two scripts.

 

var_dump($_POST) tells me that the answer key ($answers) is working in all examples, but that's about all.

 

One error message I'm getting is array_diff(): Argument #1 is not an array

 

- in reference to this code:

    if(is_array($answer)){
        if(array_diff($qa[$num], $answer) == array()){

I get the same error message if I change it to this:

if(array_diff($qa, $answer) == array()){

If a quiz has 10 questions, then each question has an ID (e.g. q1 or q10). If the first question has four possible answers, each answer has its own ID, from q1-A to q1-D. I posted the HTML for two questions at the end of this post.

 

Sorry for all the code. I think my problem is relatively simple, but I just can't figure out what I'm doing wrong.

 

Thanks!

 

ORIGINAL SCRIPT

if (isset($_POST)):
    
    $totalCorrect = 0;
    $answers = array(1 => 'A', 2 => 'Jupiter', 3 => 'C', 4 => 'D', 5 => 'A', 6 => 'C', 7 => 'C', 8 => 'C', 9 => 'B', 10 => array('A','B','C'));
 
foreach ($answers as $num => $answer):
    
        $question = 'q'.$num;
      
        if(is_array($answer) && isset($_POST[$question])){
            $ans_cnt = count($answer);
            $ans_value = (1 / $ans_cnt);
            
            $post_cnt = count($_POST[$question]);
            
            //find matches between answer array and post array
            $matches = array_intersect($answer,$_POST[$question]);
            $good_answers = count($matches);
            //Get bad answer count, which be be subtracted from overall score
            $bad_answers  = 0;
            foreach($_POST[$question] as $post_answer):
                if(!in_array($post_answer,$answer)):
                    $bad_answers++;
                endif;
            endforeach;
 
if($good_answers ==3 && $bad_answers==0){
$result = 1;
}else{
$result = 0;
}
 
            if(($post_cnt != $ans_cnt) || ($post_cnt == $ans_cnt && $ans_cnt != count($matches))){
                $result = $result * $ans_value;
                $totalCorrect = $totalCorrect + $result;    
            }else{            
                $totalCorrect++;        
            }
 
            
        }elseif(isset($_POST[$question]) && strtolower($_POST[$question]) === strtolower($answer)){
            $totalCorrect++;
        }
    endforeach;
 
    $pct = round( (($totalCorrect/count($answers)) * 100), 0);
    echo $totalCorrect.' correct ('.$pct.'%)';
endif;

REVISED SCRIPT

if ($_SERVER['REQUEST_METHOD'] == 'POST') {
$qa = 'q'.$num;
$correct = 0;
$answers = array(1 => array('A'), 
2 => array('Jupiter'), 
3 => array('C'), 
4 => array('D'), 
5 => array('A'), 
6 => array('C'), 
7 => 'C', 
8 => 'C', 
9 => 'B', 
10 => array('A','B','C'));
$total = count($answers);
foreach($answers as $k => $v){
if(is_array($v)){
if(array_diff($qa[$k], $v) == array()){
$correct++;
}
} else if($qa[$k] === $v){
$correct++;
}
}
$grade= ($correct/count($answers))*100;
echo"<p>Score $grade%</p>";
}

MY LATEST TEST

if ($_SERVER['REQUEST_METHOD'] == 'POST') {
    $correct = 0;
    $answers = array(1 => array('A'), 
                 2 => array('Jupiter'), 
                 3 => array('C'), 
                 4 => array('D'), 
                 5 => array('A'), 
                 6 => array('C'), 
                 7 => 'C', 
                 8 => 'C', 
                 9 => 'B', 
                 10 => array('A','B','C'));
    $total = count($answers);
 
 foreach($answers as $num => $answer){
 
        $qa = 'q'.$num;
 
    if(is_array($answer)){
        if(array_diff($qa[$num], $answer) == array()){
            $correct++;
        }
    } else if($qa[$num] === $answer){
        $correct++;
    }
 }
 
    $grade= ($correct/count($answers))*100;
    $grade2= ($correct/count($answer))*100;
    echo"<p>Score $grade%</p>";
    echo"<p>Score2 $grade2%</p>";
    // echo $totalCorrect.' correct ('.$grade.'%)';
}

SOME HTML

<li id="q9">	
  <div class="Question">Scientists believe the universe is:</div>
  <div class="Answer">
    <label class="Wide" for="q9-A"><div class="Radio"><input type="radio" name="q9" id="q9-A" value="A" style="display: none;"> A. disappearing</div></label></div>
  <div class="Answer">
    <label class="Wide" for="q9-B"><div class="Radio"><input type="radio" name="q9" id="q9-B" value="B" style="display: none;"> B. expanding</div></label></div>
  <div class="Answer">
    <label class="Wide" for="q9-C"><div class="Radio"><input type="radio" name="q9" id="q9-C" value="C" style="display: none;"> C. contracting</div></label></div>
  <div class="Answer">
    <label class="Wide" for="q9-D"><div class="Radio"><input type="radio" name="q9" id="q9-D" value="D" style="display: none;"> D. becoming bipolar</div></label></div>
</li>

<li id="q10">
  <div class="Question">Check each item that can be found in our solar system.</div>	
  <div class="Answer" style="margin-top: 5px; background: #000; color: #fff; text-align: center;">
    <label for="q10-A"><input type="checkbox" name="q10[]" id="q10-A" value="A">planet</label>
    <label for="q10-B"><input type="checkbox" name="q10[]" id="q10-B" value="B">asteroid</label>
    <label for="q10-C"><input type="checkbox" name="q10[]" id="q10-C" value="C">comet</label>
    <label for="q10-D"><input type="checkbox" name="q10[]" id="q10-D" value="D">black hole</label>
    <label for="q10-E"><input type="checkbox" name="q10[]" id="q10-E" value="E">neutrino star</label>
    <label for="q10-F"><input type="checkbox" name="q10[]" id="q10-F" value="F">quasar</label>
  </div>
</li>
Edited by PHPBear
Link to comment
Share on other sites

P.S. It just occurred to me that I could be doing this backwards. Rather than try to adapt my original script to the new script, would it be better to just take the new array and plug it into the original script? Can someone show me how to rewrite the original script to accommodate this new array?

 

 

$answers = array(1 => array('A'), 
2 => array('Jupiter'), 
3 => array('C'), 
4 => array('D'), 
5 => array('A'), 
6 => array('C'), 
7 => 'C', 
8 => 'C', 
9 => 'B', 
10 => array('A','B','C'));
Link to comment
Share on other sites

You aren't getting your data from the form in your latest example.

Since you aren't setting up your form to match the answer array like my previous example try it like this

 

Change

foreach($answers as $num => $answer){
 
        $qa = 'q'.$num;
 
    if(is_array($answer)){
        if(array_diff($qa[$num], $answer) == array()){
            $correct++;
        }
    } else if($qa[$num] === $answer){
        $correct++;
    }

TO

foreach($answers as $num => $answer){
        $qa = $_POST['q'.$num.''];
 
    if(is_array($answer)){
        if(array_diff($qa, $answer) == array()){
            $correct++;
        }
    } else if($qa === $answer){
        $correct++;
    }

One note though, in this manner you will need to make all the id's in the form fields arrays even if they are fill in the blank or multiple choice radio buttons.

  • Like 1
Link to comment
Share on other sites


Thanks for the code. I made a few changes, but I'm still missing something. If I select all the correct answers, I get this result:

 


Warning:  array_diff(): Argument #1 is not an array in /pages/test.php on line 45
Score 10%
Warning:  array_diff(): Argument #1 is not an array in /pages/test.php on line 45
Score 20%
Warning:  array_diff(): Argument #1 is not an array in /pages/test.php on line 45
Score 30%
Warning:  array_diff(): Argument #1 is not an array in /pages/test.php on line 45
Score 40%
Warning:  array_diff(): Argument #1 is not an array in /pages/test.php on line 45
Score 50%
Warning:  array_diff(): Argument #1 is not an array in /pages/test.php on line 45
Score 60%
Score 70%
Score 80%
Score 90%
Score 100%
var_dump: array(12) {
  ["q1"]=> string(1) "A"
  ["q2"]=> string(7) "Jupiter"
  ["q3"]=> string(1) "C"
  ["q4"]=> string(1) "D"
  ["q5"]=> string(1) "A"
  ["q6"]=> string(1) "C"
  ["q7"]=> string(1) "C"
  ["q8"]=> string(1) "C"
  ["q9"]=> string(1) "B"
  ["q10"]=>
  array(3) {
    [0]=> string(1) "A"
    [1]=> string(1) "B"
    [2]=> string(1) "C"
  }
  ["PreviousURL"]=> string(25) "http://g1/test/gw-intro-1"
  ["user_token"]=> string(13) "54f112b3d1e77"
}

 

And if I select all the INCORRECT answers, I get the following result. Do you have any idea what I need to change?

 

Also, in your first reply you wrote, "Since you aren't setting up your form to match the answer array like my previous example try it like this." Do you mean I should be approaching this a different way? I concluded that there must be two ways to make it work - 1) adapt the script you gave me to work with my quiz, 2) just take the array from your script and figure out how to import it into my original script. Is one strategy better than the other? I've just been exploring all angles in an attempt to put together something that works.

 

Thanks.

 


Warning: array_diff(): Argument #1 is not an array in /pages/test.php on line 45
Score 10%
Warning: array_diff(): Argument #1 is not an array in /pages/test.php on line 45
Score 20%
Warning: array_diff(): Argument #1 is not an array in /pages/test.php on line 45
Score 30%
Warning: array_diff(): Argument #1 is not an array in /pages/test.php on line 45
Score 40%
Warning: array_diff(): Argument #1 is not an array in /pages/test.php on line 45
Score 50%
Warning: array_diff(): Argument #1 is not an array in /pages/test.php on line 45
Score 60%
Score 60%
Score 60%
Score 60%
Score 60%
var_dump: array(12) {
  ["q1"]=> string(1) "B"
  ["q2"]=> string(4) "Mars"
  ["q3"]=> string(1) "B"
  ["q4"]=> string(1) "A"
  ["q5"]=> string(1) "C"
  ["q6"]=> string(1) "B"
  ["q7"]=> string(1) "B"
  ["q8"]=> string(1) "A"
  ["q9"]=> string(1) "A"
  ["q10"]=>
  array(3) {
    [0]=> string(1) "D"
    [1]=> string(1) "E"
    [2]=> string(1) "F"
  }
  ["PreviousURL"]=> string(25) "http://g1/test/gw-intro-1"
  ["user_token"]=> string(13) "54f1141384866"
}

Edited by PHPBear
Link to comment
Share on other sites

Part of the problem may be the way I'm creating arrays. Should I put the array brackets after an element's ID or after its "name"? I've been trying both and getting mixed results.

 

 

<label for="q'.$QID.'-'.$Value.'"><input type="checkbox" name="q'.$QID.'[]" id="q'.$QID.'-'.$Value.'" value="'.$Value.'">'.$QA.'</label>
Link to comment
Share on other sites

 

 

 I made a few changes, but I'm still missing something

It would help to see what you changed because in my last example Arg 1 wouldn't be a string it would be an array so you shouldn't be getting the warning.

 

 

Do you mean I should be approaching this a different way? I concluded that there must be two ways to make it work 

There are probably a bunch of ways to make it work, the right way to me just depends on how you want it implemented to fit with how your site works.

 

post the code your working with now and we can maybe pinpoint where things got changed.

Link to comment
Share on other sites

Thanks. I've been playing with several variations, so I'm a little confused regarding my original code. But here's what I have right now.

 

This code is pasted FIRST, above my doctype:

 

 

if ($_SERVER['REQUEST_METHOD'] == 'POST') {
    $correct = 0;
    $answers = array(1 => array('A'), 
                 2 => array('Jupiter'), 
                 3 => array('C'), 
                 4 => array('D'), 
                 5 => array('A'), 
                 6 => array('C'), 
                 7 => 'C', 
                 8 => 'C', 
                 9 => 'B', 
                 10 => array('A','B','C'));
    $total = count($answers);
 
foreach($answers as $num => $answer){
        $qa = $_POST['q'.$num.''];
 
    if(is_array($answer)){
        if(array_diff($qa, $answer) == array()){
            $correct++;
        }
    } else if($qa === $answer){
        $correct++;
    }
 
    $grade= ($correct/count($answers))*100;
}
}
    echo '<div style="background: #ff0;">Score '.$grade.'%</div>';
// echo 'rPOST: ';
// r($_POST);
echo '<br>var_dump: ';
var_dump($_POST);

 

This code is included later:

 

 

<?php
$stmt = $pdo->prepare("SELECT T.URL, T.QA, T.Parent, T.ParentLong, T.QID, T.Type, T.TypeAnswer, T.AID, T.Value, T.Correct
FROM g1_tests10 T
WHERE T.URL = 'gw-intro-1'
ORDER BY T.N");
$stmt->execute(array(
 // 'MyURL'=>$MyURL
));
 
while ($row = $stmt->fetch()) {
 $URL = $row['URL'];
 $QA = $row['QA'];
 $Parent = $row['Parent'];
 $ParentLong = $row['ParentLong'];
 $QID = $row['QID'];
 $Type = $row['Type'];
 $TypeAnswer = $row['TypeAnswer'];
 $AID = $row['AID'];
 $Value = $row['Value'];
 $Correct = $row['Correct'];
 
 switch($Type)
 {
  case 'Q':
 
  // INNER SWITCH
   switch($TypeAnswer)
   {
    case 'CB':
  $QA = '    </li>
      <li id="q'.$QID.'">
        <div class="Question">'.$QA.'</div>
        <div class="Answer" style="margin-top: 5px; background: #000; color: #fff; text-align: center;">
  ';
    break;
    default:
  $QA = '    </li>
      <li id="q'.$QID.'">
        <div class="Question">'.$QA.'</div>
  ';
    break;
   }
  // END INNER SWITCH
 
  break;
 
  case 'A':
  case 'H':
   // INNER SWITCH
   switch($TypeAnswer)
   {
     // MC = Multiple-Choice questions.
case 'MC':
    $QA = '      <div class="Answer">
          <label class="Wide" for="q'.$QID.'-'.$Value.'"><div class="Radio"><input type="radio" name="q'.$QID.'" id="q'.$QID.'-'.$Value.'[]" value="'.$Value.'" style="display: none;"> '.$Value.'. '.$QA.'</div></label></div>
  ';
break;
 
case 'CB':
     // CB = Checkboxes
     // INNER SWITCH 2
     switch($QA)
{
 case '</div>':
 $QA = '    </div>
 ';
 break;
 default:
     $QA = '      <label for="q'.$QID.'-'.$Value.'"><input type="checkbox" name="q'.$QID.'" id="q'.$QID.'-'.$Value.'[]" value="'.$Value.'">'.$QA.'</label>
     ';
 break;
}
// END INNER SWITCH 2
    break;
 
case 'Txt':
// Txt = Fill-in-the-blank questions
  $QA = '      <div class="Answer" style="background: #ccc;">
          <label for="q'.$QID.'-'.$Value.'"><div class="Multiple-Choice" style="margin: 0;"><input type="text" name="q'.$QID.'" id="q'.$QID.'-'.$Value.'[]" value=""></div></label></div>
  ';
break;
 
default:
break;
}
   // END INNER SWITCH
  break;
 
  default:
  $QA = '';
  break;
 }
 
 $Base[] = ''.$QA.'';
}
 
$MyURL = 'gw-intro-1';
?>
 
<div id="quiz" rel="key">
  <form action="" method="post" id="quiz">
    <ol>
      <li style="display: none;">
<?php
echo join ($Base, '');
?>
    </li>
    </ol>
    <input type="hidden" name="PreviousURL" id="url" />
    <input type="hidden" name="user_token" value="<?php echo $_SESSION['user_token']; ?>" />
    <input type="submit" value="Submit Quiz" />
  </form>
</div><!-- quiz-container -->

 

And here's the HTML for three questions (multiple choice, fill-in-the-blank and checkboxes):

 

 

<li id="q1">
  <div class="Question"><img src="/images/sections/test/gw-intro-1/universe.png" alt="The Universe" style="width: 100px; float: right;"> No one knows if there’s just one universe or a series of universes, sometimes referred to as:</div>
  <div class="Answer">
    <label class="Wide" for="q1-A">
    <div class="Radio">
      <input type="radio" name="q1" id="q1-A[]" value="A" style="display: none;">A. a multiverse</div>
    </label>
  </div>
  <div class="Answer">
    <label class="Wide" for="q1-B">
    <div class="Radio">
      <input type="radio" name="q1" id="q1-B[]" value="B" style="display: none;">B. Area 51</div>
    </label>
  </div>
  <div class="Answer">
    <label class="Wide" for="q1-C">
    <div class="Radio">
      <input type="radio" name="q1" id="q1-C[]" value="C" style="display: none;">C. a constellation</div>
    </label>
  </div>
  <div class="Answer">
    <label class="Wide" for="q1-D">
    <div class="Radio">
      <input type="radio" name="q1" id="q1-D[]" value="D" style="display: none;">D. a black hole</div>
    </label>
  </div>
</li>
 
<li id="q2">
  <div class="Question">What’s the name of the biggest planet in our solar system? <img src="/images/sections/test/gw-intro-1/planets.jpg" alt="Planets" style="width: 100%;"></div>
  <div class="Answer" style="background: #ccc;">
    <label for="q2-">
    <div class="Multiple-Choice" style="margin: 0;">
      <input type="text" name="q2" id="q2-[]" value="">
    </div>
    </label>
  </div>
</li>
 
<li id="q10">
  <div class="Question">Check each item that can be found in our solar system.</div>
  <div class="Answer" style="margin-top: 5px; background: #000; color: #fff; text-align: center;">
    <label for="q10-A">
      <input type="checkbox" name="q10" id="q10-A[]" value="A">planet</label>
    <label for="q10-B">
      <input type="checkbox" name="q10" id="q10-B[]" value="B">asteroid</label>
    <label for="q10-C">
      <input type="checkbox" name="q10" id="q10-C[]" value="C">comet</label>
    <label for="q10-D">
      <input type="checkbox" name="q10" id="q10-D[]" value="D">black hole</label>
    <label for="q10-E">
      <input type="checkbox" name="q10" id="q10-E[]" value="E">neutrino star</label>
    <label for="q10-F">
      <input type="checkbox" name="q10" id="q10-F[]" value="F">quasar</label>
  </div>
</li>
Link to comment
Share on other sites

 

Part of the problem may be the way I'm creating arrays. Should I put the array brackets after an element's ID or after its "name"? I've been trying both and getting mixed results.

<label for="q'.$QID.'-'.$Value.'"><input type="checkbox" name="q'.$QID.'[]" id="q'.$QID.'-'.$Value.'" value="'.$Value.'">'.$QA.'</label>

Sorry missed this post

after the name...

Link to comment
Share on other sites

Thanks, I fixed it. But something still isn't working right.

 

If I get all ten questions right, I get a score of 70% instead of 100%, along with this output:

 

 

var_dump: array(12) { ["q1"]=> array(1) { [0]=> string(1) "A" } ["q2"]=> array(1) { [0]=> string(7) "Jupiter" } ["q3"]=> array(1) { [0]=> string(1) "C" } ["q4"]=> array(1) { [0]=> string(1) "D" } ["q5"]=> array(1) { [0]=> string(1) "A" } ["q6"]=> array(1) { [0]=> string(1) "C" } ["q7"]=> array(1) { [0]=> string(1) "C" } ["q8"]=> array(1) { [0]=> string(1) "C" } ["q9"]=> array(1) { [0]=> string(1) "B" } ["q10"]=> array(3) { [0]=> string(1) "A" [1]=> string(1) "B" [2]=> string(1) "C" } ["PreviousURL"]=> string(25) "http://g1/test/gw-intro-1" ["user_token"]=> string(13) "54f3cf7949955" }

 

The array is fine; those are the right answers. If I only get Question #10 right, it gives me a score of 60%.

 

Can you see a problem in my scoring script or do you think there's still a bug in my main code that I need to track down?

 

foreach($answers as $num => $answer){
        $qa = $_POST['q'.$num.''];
 
    if(is_array($answer)){
        if(array_diff($qa, $answer) == array()){
            $correct++;
        }
    } else if($qa === $answer){
        $correct++;
    }
 
    $grade= ($correct/count($answers))*100;
}
Link to comment
Share on other sites

I found one obvious mistake I made. For some reason, I didn't have 7-9 set up as arrays...

 

 

$answers = array(1 => array('A'), 
2 => array('Jupiter'), 
3 => array('C'), 
4 => array('D'), 
5 => array('A'), 
6 => array('C'), 
7 => 'C', 
8 => 'C', 
9 => 'B', 
10 => array('A','B','C'));

 

I fixed it, but the scoring is even more bizarre. If I get all 10 questions correct, I get 100%, but if I get just one correct, I get 90%.

 

Maybe I can isolate the problem by just displaying one type of question (e.g. multiple choice) at a time.

Link to comment
Share on other sites

Sorry for the multi-posting, but I just realized another mistake I'm making. When I said I got just one question right, I meant I didn't even answer the other nine. I just chose one answer out of ten to test the scoring. I think perhaps it interprets my answer as 1 out of 1 correct, or 100%. If I answer two questions and get just one correct, I think the score was 90%.

 

So maybe it's working after all - just as long as users answer all ten questions.

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.