Score system php-undefined function - php

I am working in a scoring system in php. When user chooses specific question, get extra points.
If anyone has a working PHP demo with code of a scoring system, he would be welcome. I mostly need a working "for" function:
"for question 1, if answer is abc, 5 points, else 0 points. for question 2, if aswer is bcd, 10 points, if answer is cft, 10 points, else 0 points", etc.
I would not want to have to fill my code with endless if statements.
For my current attempt, The error it displays:
Fatal error: Uncaught Error: Call to undefined function value() in C:\xampp\htdocs\score.php:18 Stack trace: #0 {main} thrown in C:\xampp\htdocs\score.php on line 18
Edit: I realized i might not have defined the "value" variable. It should give the value of "1 point" for now. How should i define it?
<?php
// Define questions and the correct answers
$questions = array(
'AB01' => 3, // correct answer to question AB01 is 3
'AB02' => 1, // correct answer to AB02 is code 1
'AB03' => 4, // correct answer to AB03 is hidden behind code 4
'AB04' => 2,
'AB05' => 1
// and so on
);
// Initialize counter variable
$points = 0;
// Check all questions in a loop
foreach ($questions as $variable=>$correct) {
// Call up participant's answer
$answer = value($variable);
// Check and count point if applicable
if ($answer == $correct) {
$points++; // synonymous with $points = $points + 1
}
}
// Show result ...
html('<p>You have scored'.$points.' points.</p>');
// ... or store in an internal variable
put('IV01_01', $points);
// ...
// Check all questions in a loop
foreach ($questions as $variable=>$correct) {
if (value($variable) == $correct) {
$points++;
}
}
// Show result or otherwise process
// ...
// Define questions and the values of possible answers
$questions = array(
'AB01' => array(1 => 2, 2 => 5, 3 => 3), // In question AB01, answer 1 has value 2, 2 has value 5, 3 has value 3
'AB02' => array(1 => 5, 2 => 4, 3 => 1), // In question AB02, values 5 (answer 1), 4 (2) und 1 (3) are assigned
'AB03' => array(1 => 0, 2 => 0, 3 => 5),
'AB04' => array(1 => 4, 2 => 0, 3 => 3),
'AB05' => array(1 => 2, 2 => 2, 3 => 5),
// u.s.w.
);
// Initialize counter variable
$points = 0;
// By using foreach you can just pass through the key-value pairs
foreach ($questions as $variable => $values) {
// Call up participant's answer
$answer = value($variable);
// Check if there is a value available for this answer (otherwise, do not award a point)
if (isset($values[$answer])) {
// Count the value
$points += $values[$answer];
}
}
// Show result or otherwise process
html('<p>You have scored'.$points.' points.</p>');
$points = valueSum('AB01');
// Show result or otherwise process
html('<p>You have scored '.$points.' points.</p>');
// Call up list of all items
$items = getItems('AB01');
// Initialize points variable
$points = 0;
// Pass through all items
foreach ($items as $item) {
// Question ID still has to be assembled
$id = 'AB01_'.sprintf('%02d', $item);
// Call up participant's answer
$answer = value($id);
// An error code may have been saved (e.g. -1 for "no response")
// Otherwise, count the answer
if ($answer > 0) {
$points += $answer;
}
}
// Show result or otherwise process
html('<p>You have scored '.$points.' points.</p>');
$points += $answer - 1;
// List of items - providing polarity in each case
$items = array(
'01' => +1,
'02' => -1,
'03' => +1,
'04' => +1,
'05' => -1
// and so on.
);
// Initialization of points variable
$points = 0;
// Pass through all items
foreach ($items as $item => $polarity) {
// Here the variable ID is built from the question and item IDs
$id = 'AB01_'.$item;
// Call up respondent's answer
$answer = value($id);
// Ignore if it is not a valid response
if ($answer < 1) {
// This means the rest are ignored in the FOR/FOREACH loop
continue;
}
// "Invert" answers
if ($polarity < 0) {
// In a 5-point scale, the inverted answer code has a value of 6
// the constant has to be adjusted for other differentations.
$answer = 6 - $answer;
}
// Add up
$points += $answer;
}
// Show result or otherwise process.
html('<p>You have scored'.$points.' points.</p>');
if (
(value('AB01_01') == 2) and
(value('AB01_02') == 2) and
(value('AB01_03') == 1) and
(value('AB01_04') == 1)
) {
// Count point, jump to a different part, or just display a message
html('<p>Correct</p>');
} else {
html('<p>Incorrect</p>');
}
// Define questions and their correct answers
// Only items are defined that will also be checked
$questions = array(
// In question AB01, 1 and 2 have to be checked, 3 and 4 must not be checked
'AB01' => array(1 => 2, 2 => 2, 3 => 1, 4 => 1),
// In question AB02, 2 and 3 have to be checked, 4 must not, and the value for 1 is irrelevant
'AB02' => array( 2 => 2, 3 => 2, 4 => 1),
// In AB03, all 4 have to be checked
'AB03' => array(1 => 2, 2 => 2, 3 => 2, 4 => 2),
// and so on.
'AB04' => array(1 => 1, 2 => 2, 3 => 1, 4 => 2),
'AB05' => array(1 => 2, 2 => 1, 3 => 2 )
);
// Initialize counter variable
$points = 0;
// Pass through all questions
foreach ($questions as $questionId => $answers) {
// Set the error counter for this question to 0
$error = 0;
foreach ($answers as $itemId => $default) {
// Assemble item ID
$id = $questionId.'_'.$itemId;
// Call up participant's answer
$answer = value($id);
// Verify answer is correct (actually: for falsehood)
if ($answer != $default) {
// In the event of any deviation, count as an error
$error++;
}
}
// Check if the question has been correctly answered
if ($error == 0) {
// Award a point
$points++;
}
}
// Show result or otherwise process
html('<p>You have scored '.$points.' points.</p>');
if ($points < 10) {
text('feedback1');
} elseif ($points < 20) {
text('feedback2');
} else {
text('feedback3');
}
$type = valueMean('AB01');
$use = valueMean('AB02');
if ($type < 1.5) {
text('typeA');
} elseif ($type <= 4.5) {
text('typeB');
} else {
text('typeC');
}
if ($use < 2.0) {
text('useA');
} elseif ($use < 4.0) {
text('useB');
} else {
text('useC');
}
?>

You will need to define a "value" function.
<?php
//Define it anywhere within the <?php tag
function value($arg){
// Your code logic here
}

Related

Use values that are in all arrays and skip the rest

I have an array with 3 sub arrays like:
$array = array(
width => array(
0 => 1,
1 => 2,
2 => 3,
3 => 4,
4 => 5
),
height => array(
0 => 1,
1 => 2,
2 => 7,
3 => 8
),
color => array(
0 => 2,
1 => 7,
2 => 8
)
);
The count is in this case 3 as I have 3 arrays. This can be sometimes more or less, that's why I have a count.
Now I want to find out which number is in all 3 arrays and only use those. in above example the only returned number should be 2 as it's present in all 3 sub arrays.
I was trying something like below, but am really stuck what's the best approach...
$i = count($array); // gives me back the count of 3 which is correct
$n = 0;
foreach($array as $key=>values) {
foreach($values as $value) {
// do not how to proceed :(
}
}
You can call array_intersect with all the sub-arrays as arguments.
$common_values = call_user_func_array('array_intersect', $array);
Maybe you can affect your rows in some var and make what you want to do in your foreach
Like :
<?php
$width = 0;
$height = 0;
$color = 0 ;
$arrayBundleWidth = array();
$arrayBundleHeight = array();
$arrayBundleColor = array();
foreach ($array as $arrayRow){
$arrayBundleWidth = $arrayRow['width'];
$arrayBundleColor = $arrayRow['color'];
$arrayBundleHeight = $arrayRow['height'];
foreach ($arrayBundleWidth as $arrayBundleWidthtRow) {
# code...
#you got each index of your width array here
}
foreach ($arrayBundleHeight as $arrayBundleHeightRow) {
# code...
#you got each index of your height array here
}
foreach ($arrayBundleColor as $arrayBundleColorRow) {
# code...
#you got each index of your color array here
}
}
?>
Try it and tell me ? Is it what you want ?
Not sure if it's what you wanted to do !

Static Algorithm for giving response after user input

I have 2 arrays: F of length 4 and S of length 25
User can select any no of these elements from the above two arrays For eg selecting any 2 from F and 10 from S.Based on what user selected i have give a response to the user from my another array R of length 100.
I tried making if else but was exhausted after creating
100s of them.
So is there any better approach for this ?
My goal is to give user one of the index from array R.
PS. There is no AI(Artificial Intelligence) involved.
EDIT
Currently what i have done is :
if(in_array(1,$F) && in_array(12,$S)){
return $R[3];
}else if(in_array(1,$F) && in_array(17,$s)){
return $R[91];
}else if(in_array(2,$F) && in_array(1,$F) && in_array(21,$S) && in_array(25,$S)){
return $R[23];
}else if(in_array(3,$F) && in_array(21,$S) && in_array(7,$S)){
return $R[17];
}..........
Something like this? Creating map like #zerkms mentioned.
function getRKey(array $f, array $s)
{
// values map by order
$map_r_array = [
3 => ['f' => [1], 's' => [12]],
91 => ['f' => [1], 's' => [17]],
23 => ['f' => [1, 2], 's' => [21, 25]],
17 => ['f' => [3], 's' => [7, 21]],
];
foreach ($map_r_array as $key => $check)
{
// check one by one.
if (!array_diff($check['f'], $f) && !array_diff($check['s'], $s))
{
return $key;
}
}
return null;
}
$f = [1, 2, 3];
$s = [7, 21];
var_dump(getRKey($f, $s)); // int(17)

PHP algorithm to find between values in varying distance

I'm trying to create an algorithm that returns a price depending on number of hours. But the distance between the number of hours are varying. For example I have an array:
$set = [
1 => 0.5,
2 => 1,
3 => 1.5,
4 => 2,
5 => 2.5,
12 => 4
];
$value = 3;
end($set);
$limit = (int)key($set);
foreach($set as $v => $k) {
// WRONG, doesn't account for varying distance
if($value >= $v && $value <= $v) {
if($value <= $limit) {
return $k;
} else {
return false;
}
}
}
The trouble is, the distance between 5 and 12 register as null. I might as well use $value == $v instead as the line I've marked as incorrect does anyway.
So I was wondering if there was a better way to round up to the next index in that array and return the value for it?
Cheers in advance!
Try this:
$set = array(1 => 0.5, 2 => 1, 3 => 1.5, 4 => 2, 5 => 2.5, 12 => 4);
function whatever(idx, ary){
if(in_array(idx, array_keys(ary))){
return ary[idx];
}
else{
foreach(ary as $i => $v){
if($i > idx){
return $v;
}
}
}
return false;
}
echo whatever(7, $set);
The problem is that $v is a single value, so $value >= $v && $value <= $v is equivalent to $value == $v.
Instead, consider that if the loop hasn't ended, then the cutoff hasn't been reached yet - and a current "best price" is recorded. This requires that the keys are iterated in a well-ordered manner that can be stepped, but the logic can be updated for a descending order as well.
$price_chart = [
1 => 0.5,
2 => 1,
3 => 1.5,
4 => 2,
5 => 2.5,
12 => 4
];
function get_price ($hours) {
global $price_chart;
$best_price = 0;
foreach($price_chart as $min_hours => $price) {
if($hours >= $min_hours) {
// continue to next higher bracket, but remember the best price
// which is issued for this time bracket
$best_price = $price;
continue;
} else {
// "before" the next time cut-off, $hours < $min_hours
return $best_price;
}
}
// $hours > all $min_hours
return $best_price;
}
See the ideone demo. This code could also be updated to "fill in" the $price_chart, such that a price could be found simply by $price_chart[$hours] - but such is left as an exercise.

How can I determine a specific level in a parent/child-array?

I am looping over an array of groups, each element containing a parent id.
$currentparent = $group['grpId']; //$group is the current element in a loop wrapped around this piece of code
$currentlevel = 0;
foreach($groups as $grp)
{
$parent = $grp['grpParentId'];
if($parent != $currentparent && $currentlevel != 6)
{
//adding layer
$currentlevel++;
//changing parent
$currentparent = $grp['grpParentId'];
}
if($currentlevel == 6)
{
//call a special function
}
else
{
//call the regular function
}
}
This works fine on a array like this:
group
-group
--group
---group
----group
----- group <- the only group on the 5th layer
but not with an array which has multiple groups on the 5th level:
group
-group
--group
--group
---group
----group
-----group <- 5th layer
----group
-----group <- 5th layer too, but diff parent
How can I resolve this to get the special function called, even when there are multiple groups with multiple parents on the fifth level in the array?
I hope that I formulated my question clear enough.
Try iterating trough the the groups always searching for groups whose level can be determinated by its parent level. Something like this:
// example input
$groups = array(
array('grpParentId' => 0, 'grpId' => 1, ),
array('grpParentId' => 1, 'grpId' => 2, ),
array('grpParentId' => 2, 'grpId' => 3, ),
array('grpParentId' => 3, 'grpId' => 4, ),
array('grpParentId' => 4, 'grpId' => 5, ),
array('grpParentId' => 5, 'grpId' => 6, ),
array('grpParentId' => 6, 'grpId' => 7, ),
array('grpParentId' => 5, 'grpId' => 8, ),
array('grpParentId' => 8, 'grpId' => 9, ),
);
shuffle($groups); // just for testing the logic does in fact tolerate randomly ordered input
$rootId = 1; // set to the rootnode's id
$grouplevels = array();
// find the rootnode first
foreach($groups as $i => $grp) {
if ($rootId == $grp['grpId']) {
$grouplevels[$rootId] = 1;
unset($groups[$i]);
break;
}
}
// figure out childgroup levels
do {
$old_count = count($groups);
foreach($groups as $i => $grp) {
if (in_array($grp['grpParentId'], array_keys($grouplevels))) {
// the current node's parent's level was determinated previously, we can tell this group's level as well
$grouplevels[$grp['grpId']] = $level = $grouplevels[$grp['grpParentId']]+1;
if ($level == 6) {
print $grp['grpId']."\n";
}
// remove from the "we dont know yet" list
unset($groups[$i]);
}
}
} while (count($groups) < $old_count); // run while we can sort out at least one group's level in the current iteration
// handle the case when not every group's level could been determinated!
if (!empty($groups)) {
print "inconsitency ahead!";
}
It can be solved by using a recursive pattern. The following code should do the trick. It can probably be optimized.
$currentparent = $group['grpId']; //$group is the current element in a loop wrapped around
$this piece of code
$currentlevel = 0;
// Initialize
foreach($groups as $grp)
{
$grp['children'] = array();
}
foreach($groups as $grp)
{
$parent = $grp['grpParentId'];
$parent['children'][] = $grp;
}
foreach($groups as $grp)
{
if(empty($parent['children'])) $root = $grp; // Alternatively check if parent is null or something.
}
function recursive_count($root, $lvl = 0)
{
if($currentlevel == 6)
{
//call a special function
}
else
{
//call the regular function
}
foreach($root['children'] as $children)
{
recursive_count($children, $lvl++);
}
}
recursive_count($root);
Update: If memory consumption is a problem references can be used when adding a group to the children array.
Update II: Even though the algorithm has 4 foreach and a recursive structure the running time is still O(n) where n is the size of the graph.

PHP: Get two nearest neighbors from array?

I found this thread about picking the closest/nearest value from an array based upon a known value. What about if one wants to pick the two nearest values from an array looking at the same say?
$rebates = array(
1 => 0,
3 => 10,
5 => 25,
10 => 35)
$rebates = array(
1 => 0,
3 => 10,
5 => 25,
10 => 35);
function getArrayNeighborsByKey($array, $findKey) {
if ( ! array_key_exists($array, $findKey)) {
return FALSE;
}
$select = $prevous = $next = NULL;
foreach($array as $key => $value) {
$thisValue = array($key => $value);
if ($key === $findKey) {
$select = $thisValue;
continue;
}
if ($select !== NULL) {
$next = $thisValue;
break;
}
$previous = $thisValue;
}
return array(
'prev' => $previous,
'current' => $select,
'next' => $next
);
}
See it!
By "two nearest" you mean the two smaller than or equal to the value of $items?
Anyway, starting from the answer to that other thread, which is
$percent = $rebates[max(array_intersect(array_keys($rebates),range(0,$items)))];
You can go to
$two_nearest = array_slice(array_intersect(array_keys($rebates),range(0,$items)), -2);
$most_near = $rebates[$two_nearest[1]];
$less_near = $rebates[$two_nearest[0]];
This can probably be reduced to an one-liner using array_map, but I think it's overdone already.
$rebates = array(
1 => 0,
3 => 10,
5 => 25,
10 => 35)
$distances = array();
foreach($rebates as $key=>$item) {
if ($key == 5) continue;
$distances = abs($rebates[5] - $item);
}
sort($distances, SORT_NUMERIC)
Now you have an array with all the items in the array with their distance to $rebates[5] sorted. So you can get the two closest ones.
Or three closest ones. Whatever.
Just keep in mind that 2 items can have the same distance.

Categories