Filter an array with PHP - php

I have this array:
Array
(
[0] => Array
(
[DEB_Date] => 2018-01-06
[DEB_Total] => 100.00
[DEB_Nb_Days] => 181
)
[1] => Array
(
[DEB_Date] => 2018-07-06
[DEB_Total] => 100.00
[DEB_Nb_Days] => 0
)
)
I want to have a sort of report depending the DEB_Nb_Days.
So my script is the following:
// Init the array
$arr['0_to_30']['DEB_Total'] = 0;
$arr['31_to_60']['DEB_Total'] = 0;
$arr['61_to_90']['DEB_Total'] = 0;
$arr['91_to_120']['DEB_Total'] = 0;
$arr['121_and_more']['DEB_Total'] = 0;
// Loop between the debtors
foreach($debtors as $debtor){
if($debtor['DEB_Nb_Days'] >= 0 || $debtor['DEB_Nb_Days'] <= 30) { $arr['0_to_30']['DEB_Total'] += $debtor['DEB_Total']; }
if($debtor['DEB_Nb_Days'] >= 31 || $debtor['PAY_Nb_Days'] <= 60) { $arr['31_to_60']['DEB_Total'] += $debtor['DEB_Total']; }
if($debtor['DEB_Nb_Days'] >= 61 || $debtor['PAY_Nb_Days'] <= 90) { $arr['61_to_90']['DEB_Total'] += $debtor['DEB_Total']; }
if($debtor['DEB_Nb_Days'] >= 91 || $debtor['PAY_Nb_Days'] <= 120) { $arr['91_to_120']['DEB_Total'] += $debtor['DEB_Total']; }
if($debtor['PAY_Nb_Days'] >= 121) { $arr['121_and_more']['DEB_Total'] += $debtor['DEB_Total']; }
}
I should have this:
$arr['0_to_30']['DEB_Total'] = 100;
$arr['31_to_60']['DEB_Total'] = 0;
$arr['61_to_90']['DEB_Total'] = 0;
$arr['91_to_120']['DEB_Total'] = 0;
$arr['121_and_more']['DEB_Total'] = 100;
But actually the result is:
$arr['0_to_30']['DEB_Total'] = 200;
$arr['31_to_60']['DEB_Total'] = 200;
$arr['61_to_90']['DEB_Total'] = 200;
$arr['91_to_120']['DEB_Total'] = 200;
$arr['121_and_more']['DEB_Total'] = 0;
What I'm missed here please ?
Thanks.

You could restructure the set of if conditions to look for the highest first and then use else to reduce the number of comparisons...
foreach ($debtors as $debtor) {
if ($debtor['DEB_Nb_Days'] >= 121) {
$arr['121_and_more']['DEB_Total'] += $debtor['DEB_Total'];
}
else if ($debtor['DEB_Nb_Days'] >= 91) {
$arr['91_to_120']['DEB_Total'] += $debtor['DEB_Total'];
}
else if ($debtor['DEB_Nb_Days'] >= 61) {
$arr['61_to_90']['DEB_Total'] += $debtor['DEB_Total'];
}
else if ($debtor['DEB_Nb_Days'] >= 31) {
$arr['31_to_60']['DEB_Total'] += $debtor['DEB_Total'];
}
else {
$arr['0_to_30']['DEB_Total'] += $debtor['DEB_Total'];
}
}
( This also corrects that at some points your using PAY_Nb_Days instead of DEB_Nb_Days ).

Related

Assigning a string value if input value falls within a specific range in Laravel 8

I compare an input value to multiple range of values to determine the string value for another variable. The below code works, but I am wondering if there is a more elegant solution?
...
if ($totalPoints >= 0 && $totalPoints <= 249) {
$carClass = 'CC01';
} elseif ($totalPoints >= 250 && $totalPoints <= 299) {
$carClass = 'CC02';
} elseif ($totalPoints >= 300 && $totalPoints <= 349) {
$carClass = 'CC03';
} elseif ($totalPoints >= 350 && $totalPoints <= 399) {
$carClass = 'CC04';
} elseif ($totalPoints >= 400 && $totalPoints <= 449) {
$carClass = 'CC05';
} elseif ($totalPoints >= 450 && $totalPoints <= 499) {
$carClass = 'CC06';
} elseif ($totalPoints >= 500 && $totalPoints <= 549) {
$carClass = 'CC07';
} elseif ($totalPoints >= 550 && $totalPoints <= 599) {
$carClass = 'CC08';
} elseif ($totalPoints >= 600 && $totalPoints <= 649) {
$carClass = 'CC09';
} elseif ($totalPoints >= 650 && $totalPoints <= 699) {
$carClass = 'CC10';
} elseif ($totalPoints >= 700 && $totalPoints <= 749) {
$carClass = 'CC11';
} elseif ($totalPoints >= 750 && $totalPoints <= 824) {
$carClass = 'CC12';
} elseif ($totalPoints >= 825 && $totalPoints <= 899) {
$carClass = 'CC13';
} elseif ($totalPoints >= 900 && $totalPoints <= 974) {
$carClass = 'CC14';
} elseif ($totalPoints >= 975 && $totalPoints <= 1049) {
$carClass = 'CC15';
} elseif ($totalPoints >= 1050 && $totalPoints <= 1149) {
$carClass = 'CC16';
} elseif ($totalPoints >= 1150 && $totalPoints <= 1249) {
$carClass = 'CC17';
} elseif ($totalPoints >= 1250) {
$carClass = 'CC18';
}
...
This might be a more compact solution:
function findInRange($number, $array)
{
foreach ($array as $key => $value) {
list($min, $max) = explode('-', $key);
if (
$number >= $min && $number <= $max) {
return $value;
}
}
return null;
}
$totalPoints = 1300;
$carClassArray = [
"0-249" => 'CC01',
"250-299" => 'CC02',
"300-349" => 'CC03',
"250-399" => 'CC04',
"400-449" => 'CC05',
"450-499" => 'CC06',
"500-549" => 'CC07',
"550-599" => 'CC08',
"600-649" => 'CC09',
"650-699" => 'CC10',
"749-1000000" => 'CC11',
];
$carClass = findInRange($totalPoints, $carClassArray);
echo $carClass;
Based on your code I think that the $carClass always has the format CCXX where XX is two digits number and starts from 0 to the ranges count.
So you can use the 2nd value for each range and add them to the array and get the index of the desired value after sorting the array
$totalPoints = 290;
// -1 to get CC01 for 0 value
$breaks = [-1, 249, 299, 349, 399, 449]; // add all the 2nd values
$breaks[] = $totalPoints;
asort($breaks);
$breaks = array_values($breaks);
$index = array_search($totalPoints, $breaks);
$carClass = 'CC' . str_pad($index, 2, '0', STR_PAD_LEFT);
echo $carClass; // CC02
This can be a way:
$totalPoints = 399;
$rangeArray = [
[0, 249, 'CC01'],
[250, 299, 'CC02'],
[300, 349, 'CC03'],
[350, 399, 'CC04'],
/* .... More range */
[12520, null, 'CC18']
];
foreach($rangeArray as $range){
if( ($totalPoints >= $range[0]) && ($range[1] ? ($totalPoints <= $range[1]) : true) ){
$carClass = $range[2];
break;
}
}
echo $carClass;// CC04

PHP - Find turning points in array data (high and low) based on range

$data = array(5,0,15,20,22,14,13,15,12,22,40,25);
Hi , i want to traverse the data points above and find the turning points based on a range.
The way i'm tackling it so far is simply taking the $array[$i] - $array[$i-1] , and if the absolute difference is greater than the range - i'm taking it as a turning point . however - the logic is flawed as if it moved slightly up and then back down - it breaks the cycle.
The 3 down values should have been enough to make X , a turning point downwards , but because they individually do not meet the range - they are discarded .
Any solutions ?
if($diff >= 0)
{
$diff_up = $diff_up + $diff;
}
else
{
$diff_down = $diff_down + abs($diff);
}
if((($diff_up-$diff_down) >=$range) && ($pivot_type != "UP"))
{
echo "Pivot UP at : ".$current;
break;
}
else if((($diff_down-$diff_up) >$range) && ($pivot_type != "DOWN"))
{
echo "Pivot DOWN at : ".$current;
break;
}
What you are looking for is all local minima and maxima, This is a good article.
I made this (with inspiration from:
get extremes from list of numbers):
<?php
$data = array(5,0,15,20,22,14,13,15,12,22,40,25);
function minima_and_maxima(array $array){
$maxima = [];
$minima = [];
$maxima[] = $array[0];
for($i = 1; $i < count($array) - 1; $i++){
$more_than_last = $array[$i] > $array[$i-1];
$more_than_next = $array[$i] > $array[$i+1];
$next_is_equal = $array[$i] == $array[$i+1];
if($next_is_equal) {
continue;
}
if ($i == 0) {
if ($more_than_next) {
$maxima[] = $array[$i];
} else {
$minima[] = $array[$i];
}
} elseif ($i == count($array)-1) {
if ($more_than_last) {
$maxima[] = $array[$i];
} else {
$minima[] = $array[$i];
}
} else {
if ($more_than_last && $more_than_next) {
$maxima[] = $array[$i];
} elseif (!$more_than_last && !$more_than_next) {
$minima[] = $array[$i];
}
}
}
for ($i = 0; $i < count($maxima); $i++) {
$current_maxima = $maxima[$i];
$next_maxima = $maxima[$i+1];
if ($current_maxima > $next_maxima) {
unset($maxima[$i+1]);
}
}
for ($i = 0; $i < count($minima); $i++) {
$current_minima = $minima[$i];
$next_minima = $minima[$i+1];
if ($next_minima < $current_minima) {
unset($minima[$i]);
}
}
return [
'maxima' => array_values($maxima),
'minima' => array_values($minima),
];
}
function get_turning_points($data)
{
$mins_and_maxs = minima_and_maxima($data);
$turning_points = [];
for ($i = 0; $i < count($mins_and_maxs['maxima']) - 1; $i++) {
$turning_points[] = $mins_and_maxs['maxima'][$i];
$turning_points[] = $mins_and_maxs['minima'][$i];
}
$turning_points[] = $mins_and_maxs['maxima'][count($mins_and_maxs['maxima'])-1];
return $turning_points;
}
print_r(get_turning_points($data));
This gives you:
Array
(
[0] => 5
[1] => 0
[2] => 22
[3] => 12
[4] => 40
)
Demo: https://eval.in/832708
Hope this helps :)

HTML PHP Math : Fill a progress bar using rank values

I got a progress bar to be filled showing remaining rank points to next level.
Ex: got 25 points and next rank is at 50 points so the bar must to be filled at 50%, if i got 40 point must to be 75% filled etc.
<div class="progress-bar" role="progressbar" aria-valuenow="<?php print $rank; ?>" aria-valuemin="0" aria-valuemax="100" style="width: <?php print get_rank($rank) * next_rank($level) / 2; ?>%;">
The get_rank() function take Rank points and convert to remain points minus $rank value, then I'd pass the $rank value to level() function in order to retrieve the level and finally next_rank() function get the level and return the remaining points.
So the used math is (get_rank($rank) * next_rank($level) / 2) / 10.
Using this return the remaining value ( eg. 19 * 20 / 2 = 500 / 10 = 19% ) print in the width 0.25%, how i can reverse the result to get 99.75% instead of 0.25?
For completeness will paste the complete functions:
<?php
function get_rank($rank) {
if ( $rank >= 5 ) { $rem_point = 20 - $rank; }
if ( $rank >= 20 ) { $rem_point = 50 - $rank; }
if ( $rank >= 50 ) { $rem_point = 100 - $rank; }
if ( $rank >= 100 ) { $rem_point = 500 - $rank; }
if ( $rank >= 500 ) { $rem_point = 1000 - $rank; }
if ( $rank >= 1000 ) { $rem_point = 2500 - $rank; }
if ( $rank >= 2500 ) { $rem_point = 5000 - $rank; }
return $rem_point;
}
function level($rank) {
if ( $rank <= 5 ) { $level = 1; }
elseif ( $rank <= 20 ) { $level = 2; }
elseif ( $rank <= 50 ) { $level = 3; }
elseif ( $rank <= 100 ) { $level = 4; }
elseif ( $rank <= 500 ) { $level = 5; }
elseif ( $rank <= 1000 ) { $level = 6; }
elseif ( $rank <= 2500 ) { $level = 7; }
elseif ( $rank <= 5000 ) { $level = 8; }
return $level;
}
function next_rank($level) {
if ( $level = 1 ) { $next_r = 5; }
elseif ( $level = 2 ) { $next_r = 20; }
elseif ( $level = 3 ) { $next_r = 50; }
elseif ( $level = 4 ) { $next_r = 100; }
elseif ( $level = 5 ) { $next_r = 500; }
elseif ( $level = 6 ) { $next_r = 1000; }
elseif ( $level = 7 ) { $next_r = 2500; }
elseif ( $level = 8 ) { $next_r = 5000; }
return $next_r;
}
?>
Thanks to all who can help.
Replace <?php print get_rank($rank) * next_rank($level) / 2; ?>
by <?php print_r(($rank*100)/(get_rank($rank)+$rank)); ?> should do the job you want.
For function level($rank) if i input level(10) output will be 10 as you are returning $rank without any calculation.

i want to sum all digit in a number

i want to add all digit in a number and if it is 11,22 then i want to display only 11 or 22 else i want to make it a single digit.
example 30=3+0=3
28=2+8=10=1+0=1
i just made a codebut it have an error
please help.
<?php
$day = 17;
$month = 8;
$year = 1993;
function sumday($day)
{
if ($day == 11)
{
$sday = 11;
}
elseif ($day == 22)
{
$sday = 22;
}
elseif ($day == 29)
{
$sday = 11;
}
else
{
do {
$nday = $day . "";
$sday = 0;
for ($i = 0; $i < strlen($nday); ++$i)
{
$sday += $nday[$i];
}
while ($sday <=9);
}
return $sday;
}
First of all I would suggest you to learn to separate the tasks that a function do.
You ask to sum up the digits of a number, you may first create a function called sum_digits
<?php
function sum_digits($num) {
if ($num < 10)
return $num;
return $num % 10 + sum_digits(floor($num/10));
}
and then via conditional do whatever you need to do.
please refer to unnikked's answer, that's a good answer.
And here's the full code, combined with unnikked's answer
<?php
$day = 17;
$month = 8;
$year = 1993;
function sumday($day)
{
if ($day == 11)
{
$sday = 11;
}
elseif ($day == 22)
{
$sday = 22;
}
elseif ($day == 29)
{
$sday = 11;
}
else{
$sday = $day;
do {
$sday = $sday % 10 + floor($sday/10);
} while ($sday >= 10);
}
return $sday;
}
?>
EDIT: If you want to return the sum if it's 11,22,33 in the while loop, then put the conditions in the while loop rather than using if else condition, it's much simpler tho :)
function sumday($day)
{
$sday = $day;
while ($sday >= 10 && $sday != 11 && $sday != 22 && $sday != 29){
$sday = $sday % 10 + floor($sday/10);
}
return $sday;
}
EDIT: here's the logic that can split the day and sum them
function sumday($day)
{
$sday = $day;
$arrday = str_split($sday); // split the day into array
$sumarrday = 0;
for($i = 0; $i < strlen((string)$sday); $i++){
$sumarrday = $sumarrday + $arrday[$i]; // sum the day from the array
}
$sday = $sumarrday;
// here you can modify the condition of while statement for your needs
// for example, if you want to return 29 when 29 shows up, add this to your condition, && $sday != 29
while ($sday >= 10){
$sday = $sday % 10 + floor($sday/10);
}
return $sday;
}
Try this:
else {
$nday = $day . ""; //moved out wrom loop
do {
$sday = 0;
for ($i = 0; $i < strlen($nday); ++$i)
{
$sday += $nday[$i];
}
$nday = $sday . ""; // you forget this line
while ($sday <=9);
}

PHP Switch case & if statement not returning correct values

I'm kind of new to PHP and I'm trying to write a script that counts points after a user inputs values.
Here's the code:
<?php
$pla = $_GET['players'];
$plu = $_GET['plugins'];
$type = $_GET['type'];
$location = $_GET['location'];
totalPoints();
function typePoints($type) { //Returns points depending on server type
switch (strtolower($type)) { //Switch the type of server between all types and see how many points to return :)
case "standard minecraft": return 1;
break;
case "snapshot": return 2;
break;
case "craftbukkit": return 2;
break;
case "bungeecord": return 1;
break;
case "spigot": return 2;
break;
case "paperspigot": return 2;
break;
case "feed the beast": return 3;
break;
case "technic": return 3;
break;
case "pixelmon": return 3;
break;
default: echo 'Incorrect Server Type!';
exit;
break;
}
}
function playerPoints($players) { //Returns points depending on amount o players
if ($players >= 2 && $players <= 5) {
return 2;
} elseif ($players >= 6 && $players <= 10) {
return 4;
} //Between 6-10, return 4 points... AND SO ON...
elseif ($players >= 11 && $players <= 16) {
return 8;
} elseif ($players >= 17 && $players <= 25) {
return 12;
} elseif ($players >= 26 && $players <= 30) {
return 16;
} elseif ($players >= 31 && $players <= 36) {
return 18;
} elseif ($players >= 37 && $players <= 45) {
return 20;
} elseif ($players >= 46 && $players <= 50) {
return 22;
} elseif ($players >= 51 && $players <= 56) {
return 24;
} elseif ($players >= 57 && $players <= 65) {
return 26;
} elseif ($players >= 66 && $players <= 70) {
return 28;
} elseif ($players >= 71 && $players <= 76) {
return 30;
} elseif ($players >= 77 && $players <= 85) {
return 32;
} elseif ($players >= 86 && $players <= 90) {
return 34;
} elseif ($players >= 91 && $players <= 96) {
return 36;
} elseif ($players >= 97 && $players <= 105) {
return 38;
} elseif ($players >= 106 && $players <= 110) {
return 40;
} elseif ($players > 110) {
return 44;
}
}
function pluginPoints($plugins) {
if ($plugins == 0) {
return 0;
} elseif ($plugins >= 1 && $plugins <= 3) {
return 2;
} //Between 1-3, return 2 points.... AND SO ON...
elseif ($plugins >= 4 && $plugins <= 15) {
return 6;
} elseif ($plugins >= 16 && $plugins <= 30) {
return 10;
} elseif ($plugins >= 31 && $plugins <= 40) {
return 14;
} elseif ($plugins >= 41 && $plugins <= 50) {
return 20;
} elseif ($plugins > 50) {
return 24;
}
}
function locationPoints($location) {
switch (strtolower($location)) { //Switch between locations, easy to add a new one later in the future. :)
case "montreal": return 1;
break;
case "france": return 1;
break;
default: echo "Incorrect Location!";
exit;
break;
}
}
function totalPoints() { //Call this function to get the amount of points finally.
$totalPoints = typePoints($type) + playerPoints($pla) + pluginPoints($plu) + locationPoints($location);
echo 'Total points: ' . $totalPoints;
}
?>
The problem is the switch statement in function typePoints($type) always returns the default: echo 'Incorrect Server Type!'; exit; break;.
Also, function playerPoints($players) returns 0 even though I put in a number like 37.
I used this:
http://website.com/planpicker.php?players=121&location=france&plugins=80&type=technic
Can anyone tell me why?
This is not a duplicate question, the "marked duplicate" talks about different files, but this is within the same file.
The 4 variables are not accessible from totalPoints function. You should pass those parameters to function. You should call function as :
totalPoints($type,$pla,$plu,$location);
And define the function as
function totalPoints($type,$pla,$plu,$location)
It's because you call your functions in another function without passing the values in parameter.
The totalPoints function is not aware of the value of $type or $pla for example as they are not GLOBALS.
You have to pass the variables to the function you want to call :
function totalPoints($type, $pla, $plu, $location) //Call this function to get the amount of points finally.
{
$totalPoints = typePoints($type) + playerPoints($pla) + pluginPoints($plu) + locationPoints($location);
echo 'Total points: '.$totalPoints;
}
And then call the function like this :
totalPoints($type,$pla,$plu,$location);
The variables that were decared outside of the functions need to be made accessible to the totalPoints function. The easiest way is to use global
function totalPoints() {
global $pla;
global $plu;
global $type;
global $location;
$totalPoints = typePoints($type) + playerPoints($pla) + pluginPoints($plu) + locationPoints($location);
echo 'Total points: '.$totalPoints;
}

Categories