PHPBear Posted February 27, 2015 Share Posted February 27, 2015 (edited) 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 February 27, 2015 by PHPBear Quote Link to comment Share on other sites More sharing options...
PHPBear Posted February 27, 2015 Author Share Posted February 27, 2015 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')); Quote Link to comment Share on other sites More sharing options...
tryingtolearn Posted February 27, 2015 Share Posted February 27, 2015 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. 1 Quote Link to comment Share on other sites More sharing options...
PHPBear Posted February 28, 2015 Author Share Posted February 28, 2015 (edited) 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 February 28, 2015 by PHPBear Quote Link to comment Share on other sites More sharing options...
PHPBear Posted February 28, 2015 Author Share Posted February 28, 2015 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> Quote Link to comment Share on other sites More sharing options...
tryingtolearn Posted February 28, 2015 Share Posted February 28, 2015 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. Quote Link to comment Share on other sites More sharing options...
PHPBear Posted March 1, 2015 Author Share Posted March 1, 2015 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> Quote Link to comment Share on other sites More sharing options...
tryingtolearn Posted March 1, 2015 Share Posted March 1, 2015 You have to pass the form name as the array not the id. Instead of name="q'.$QID.'" id="q'.$QID.'-'.$Value.'[]" try name="q'.$QID.'[]" id="q'.$QID.'-'.$Value.'" on your form elements. Quote Link to comment Share on other sites More sharing options...
tryingtolearn Posted March 1, 2015 Share Posted March 1, 2015 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... Quote Link to comment Share on other sites More sharing options...
PHPBear Posted March 2, 2015 Author Share Posted March 2, 2015 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; } Quote Link to comment Share on other sites More sharing options...
PHPBear Posted March 2, 2015 Author Share Posted March 2, 2015 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. Quote Link to comment Share on other sites More sharing options...
PHPBear Posted March 2, 2015 Author Share Posted March 2, 2015 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. Quote Link to comment Share on other sites More sharing options...
tryingtolearn Posted March 2, 2015 Share Posted March 2, 2015 change if(is_array($answer)){ if(array_diff($qa, $answer) == array()){ $correct++; } } else if($qa === $answer){ $correct++; } to if(is_array($answer)){ if($qa === $answers[$num]){ $correct++; } } else if($qa === $answers[$num]){ $correct++; } 1 Quote Link to comment Share on other sites More sharing options...
PHPBear Posted March 3, 2015 Author Share Posted March 3, 2015 Perfect. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.