Updating total price array when user submit - php

I have an array with nested array in it like below.
cart (
[total] => 98
[itemcount] => 3
[items] => Array ( [0] => 0 [1] => 3 [2] => 5 )
[itemprices] => Array ( [0] => 33.00 [3] => 32.00 [5] => 33 )
[itemqtys] => Array ( [0] => 1 [3] => 1 [5] => 1 )
[iteminfo] => Array ( [0] => Chemistry [3] => Additional Mathematics [5] => Physics )
)
And I have the code below in a switch when the user enter correct discount code, this function will trigger. I can get it work to display the discounted price.
$anewvalue = 16.50;
$physubject = "Physics";
$index = array_search($physubject , $cart->iteminfo);
if (false !== $index) {
$cart->itemprices[$index] = $anewvalue;}
Problem is that how do I update the total whenever the user key in a correct discount code and submit the form, so that the total price will always up to date, because now it doesn't do that.

You need to recalculate the total every time a correct discount is applied.
if (false !== $index) {
$cart->itemprices[$index] = $anewvalue;
//re-calculate the total
$total = 0;
foreach ($cart->itemprices as $key=>$itemprice) {
$total += $itemprice * $cart->itemqtys[$key];
}
$cart->total = $total
}

Related

How to set calculate items of loop in one array in PHP

Following is my array
(
[0] => Array
(
[items] => 10.4
[Total] => 10.4
)
[1] => Array
(
[items] => 10.5
[Total] => 10.5
)
[2] => Array
(
[items] => 4.5
[Total] => 15
)
[3] => Array
(
[items] => 15.2
[Total] => 15.2
)
[4] => Array
(
[items] => 8.4
[Total] => 8.4
)
)
Here each array has items & total , I want to check if total of each item is less then 20 then set items with total in a array and also not check already checked item.
For example there are 4 items in array 0 has item 10.4 & total 10.4 then check is less then 20 if not then plus second array item means (10.4 + 10.5) again check if is greater then 20 If yes then set last checked in array like array('item'=>10.4, 'total'=>10.4) , Now second time 10.4 item will skip & check with 10.5 + 4.5 etc...
I want output like.
(
[0] => Array
(
[items] => array([0]=>10.4),
[Total] => 10.4
)
[1] => Array
(
[items] => array(
[0] => 10.5,
[1] => 4.5
),
[Total] => 15
)
[2] => Array
(
[items] => array([0]=>15.2)
[Total] => 15.2
)
[3] => Array
(
[items] => array([0]=>8.4)
[Total] => 8.4
)
)
Following is my script.
$packageInfo = $ordercon->get_package_items_by_order_number($order_number); // Comes from model
// First calculate the total
foreach ($packageInfo as $key => $package) {
$packageInfo[$key]['total_weight'] = $package['quantity'] * $package['weight'];
$packageInfo[$key]['currnt_item'] = $package['quantity'] * $package['weight'];
}
// Then check count the packages ?
$packages = [];
$packageTotalWeight = 0;
$packageItemWeight = 0;
foreach ($packageInfo as $key => $package) {
if(($packageTotalWeight + $package['total_weight']) > 20){
$packages[]['final_total'] = $packageTotalWeight;
$packageTotalWeight = $package['total_weight'];
$data[] = array('items'=>$package['currnt_item'], 'Total'=>$packageTotalWeight); // For combine items
} else {
$packages[]['currntItem'] = $package['quantity'] * $package['weight'];
$packageTotalWeight += $package['total_weight'];
$data[] = array('items'=>$package['currnt_item'], 'Total'=>$packageTotalWeight);
}
}
echo "<pre>";print_r($data);
echo '<pre>packageInfo';print_r($packageInfo);

Sorting multiple subarrays based on a total count from all sub arrays

I have some data which looks like this (reduced)
Array
(
[datasets] => Array
(
[0] => Array
(
[label] => NEW
[backgroundColor] => #37fdfd
[data] => Array
(
[0] => 0
[1] => 0
[2] => 5
[3] => 0
)
)
[1] => Array
(
[label] => Grade A
[backgroundColor] => #76ef76
[data] => Array
(
[0] => 8
[1] => 12
[2] => 11
[3] => 0
)
)
[2] => Array
(
[label] => Grade B
[backgroundColor] => #f9f96d
[data] => Array
(
[0] => 1
[1] => 6
[2] => 5
[3] => 3
)
)
[3] => Array
(
[label] => Grade C
[backgroundColor] => #f3ca36
[data] => Array
(
[0] => 3
[1] => 0
[2] => 1
[3] => 4
)
)
[4] => Array
(
[label] => Grade D
[backgroundColor] => #f3ca36
[data] => Array
(
[0] => 3
[1] => 0
[2] => 1
[3] => 0
)
)
)
[labels] => Array
(
[0] => User 0
[1] => User 1
[2] => User 2
[3] => User 3
)
)
Here is a JSON string of the data (not reduced, numbers may differ slightly)
{"datasets":[{"label":"NEW","backgroundColor":"#37fdfd","data":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]},{"label":"Grade A","backgroundColor":"#76ef76","data":[9,14,12,0,4,17,13,0,10,0,18,18,12,13,13,4]},{"label":"Grade B","backgroundColor":"#f9f96d","data":[1,6,5,0,6,5,2,0,1,0,2,1,4,3,1,15]},{"label":"Grade C","backgroundColor":"#f3ca36","data":[3,0,1,0,2,0,0,0,0,0,1,1,0,0,0,0]},{"label":"Grade C","backgroundColor":"#f3ca36","data":[3,0,1,0,2,0,0,0,0,0,1,1,0,0,0,0]}],"labels":["User 0","User 1","User 2","User 3","User 4","User 5","User 6","User 7","User 8","User 9","User 10","User 11","User 12","User 13","User 14","User 15"]}
Each dataset has an array of data which has keys that directly relates to a key in the labels array. This is currently sorted in alphabetical order by the label.
This data structure is the structure required for Chart.js, which I am using to display a stacked bar chart on my webpage.
Essentially what I need to accomplish is to sort the data array for every user in the labels array based on the sum of each data set for that user. I also need to sort the labels array to be in the same order.
My original idea on how to achieve this is to create a temporary array, loop through all the data sets and add them to this temporary array in the order necessary, but I got stuck after calculating the total for each user. Here is my attempt:
$return = [];
foreach($calculated['labels'] as $key => &$name) {
$total = 0;
foreach($calculated['datasets'] as $dataset) {
$total += $dataset['data'][$key];
}
echo "$name - $total<br>";
}
How can I sort my data and labels in descending order based on the total for each user from all datasets.
Here is my expected output for the reduced data above
Array
(
[datasets] => Array
(
[0] => Array
(
[label] => NEW
[backgroundColor] => #37fdfd
[data] => Array
(
[2] => 5
[1] => 0
[0] => 0
[3] => 0
)
)
[1] => Array
(
[label] => Grade A
[backgroundColor] => #76ef76
[data] => Array
(
[2] => 11
[1] => 12
[0] => 8
[3] => 0
)
)
[2] => Array
(
[label] => Grade B
[backgroundColor] => #f9f96d
[data] => Array
(
[2] => 5
[1] => 6
[0] => 1
[3] => 3
)
)
[3] => Array
(
[label] => Grade C
[backgroundColor] => #f3ca36
[data] => Array
(
[2] => 1
[1] => 0
[0] => 3
[3] => 4
)
)
[4] => Array
(
[label] => Grade D
[backgroundColor] => #f3ca36
[data] => Array
(
[2] => 1
[1] => 0
[0] => 3
[3] => 0
)
)
)
[labels] => Array
(
[2] => User 2 //23 total across all data sets
[1] => User 1 //18 total across all data sets
[0] => User 0 //15 total across all data sets
[3] => User 3 //7 total across all data sets
)
)
The key in the labels array acts as a unique identifier for each user in each dataset data array.
Notice how each set of data inside of each dataset is in the same order, as is the labels array. Each set should be ordered by the total amount from all sets for each user, not necessarily the highest number in each dataset.
For clarification, each set of data in each dataset contains a list of values, the key for each value is directly related to the key for each user in the labels array. So in my example, we have User 0 who has the key "0". This user has a total of 23 from adding up the values from each dataset with the key "0".
Complete solution:
// get array
$a = json_decode('{"datasets":[{"label":"NEW","backgroundColor":"#37fdfd","data":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]},{"label":"Grade A","backgroundColor":"#76ef76","data":[9,14,12,0,4,17,13,0,10,0,18,18,12,13,13,4]},{"label":"Grade B","backgroundColor":"#f9f96d","data":[1,6,5,0,6,5,2,0,1,0,2,1,4,3,1,15]},{"label":"Grade C","backgroundColor":"#f3ca36","data":[3,0,1,0,2,0,0,0,0,0,1,1,0,0,0,0]},{"label":"Grade C","backgroundColor":"#f3ca36","data":[3,0,1,0,2,0,0,0,0,0,1,1,0,0,0,0]}],"labels":["User 0","User 1","User 2","User 3","User 4","User 5","User 6","User 7","User 8","User 9","User 10","User 11","User 12","User 13","User 14","User 15"]}', true);
// get array of arrays with `data` key from each data set
$users = array_column($a['datasets'], 'data');
// tricky code to sum arrays
$sums = array_map('array_sum', array_map(null, ...$users));
// sort array with keeping keys
arsort($sums);
// we need flip so as `array_replace` will work as expected
$keys = array_flip(array_keys($sums));
// "sorting" `data` subarrays
foreach ($a['datasets'] as &$item) {
$item['data'] = array_replace($keys, $item['data']);
}
// "sorting" `labels` subarray
$a['labels'] = array_replace($keys, $a['labels']);
// see the result
print_r($a);
Fiddle here https://3v4l.org/a7rPL
I see this task as a perfect candidate for array_multisort(). Your synchronously sorted subarrays don't need to retain their initial keys like in u_mulder's output.
The first parameter must be the array of columnar sums, then the descending sort flag as the second parameter, then the labels subarray as a reference, then the dynamic number of data subarrays as references to the original array.
Code: (Demo)
$params = [[], SORT_DESC, &$array['labels']];
foreach ($array['datasets'] as ['data' => &$data]) {
foreach ($data as $i => $d) {
$params[0][$i] = ($params[0][$i] ?? 0) + $d;
}
$params[] = &$data;
}
array_multisort(...$params);
var_export($array);
This looks like a typical job for map(reduce).sort: map each element to an object with id, so you can preserve "which user this used to be" information, and total, the result of reducing data. Then sort with a custom sort function (a,b) => a.total - b.total.
E.g.
function map_total($user, $pos) {
return array(
"id" => $pos,
"total" => array_sum($user.data)
);
}
function cmp_total($a, $b) {
return $a["total"] - $b["total"];
}
$mapped = array_map("map_total", $thing.dataset, array_keys($thing.dataset));
$sorted = usort($mapped, "cmp_total");

Determine Taker Price from Bid/Ask Order Book

I am working on a bitcoin trading script in PHP. To run paper trading on live data, I have to determine buy/sell price from order book i.e taker price.
Order book live json data looks like this
Order book has two main arrays - bids & asks. Each bid/ask array has price [0], quantity [1] and the third parameter [2] is irrelevant:
Bid/Ask Sample Array
[0] => Array
(
[0] => 8848.99
[1] => 9.89850469
[2] => 7
)
[1] => Array
(
[0] => 8848.2
[1] => 0.05
[2] => 1
)
[2] => Array
(
[0] => 8848.02
[1] => 0.274203
[2] => 1
)
[3] => Array
(
[0] => 8848.01
[1] => 0.0012
[2] => 1
)
[4] => Array
(
[0] => 8847.47
[1] => 0.5
[2] => 1
)
[5] => Array
(
[0] => 8846.99
[1] => 0.28345
[2] => 1
)
[6] => Array
(
[0] => 8846.81
[1] => 0.75
[2] => 1
)
[7] => Array
(
[0] => 8846
[1] => 0.75181214
[2] => 2
)
[8] => Array
(
[0] => 8845.99
[1] => 26.57694043
[2] => 28
)
From the above data, how to calculate average price for 15 or n number of coins in PHP? Considering that orders will be filled/taken from top to bottom as available.
I solved it with this Excel formula:
Avg. Cost = sumproduct(price series, qty series) / sum(qty series)
Here is the PHP code:
$order_book = json_decode($order_book, true);
$bids = ($order_book['bids']);
$ordered = 15; //n number of coins
$filled = 0;
$fill_array = array();
foreach ($bids as $PriceQty) {
$price = $PriceQty[0];
$qty = $PriceQty[1];
if ($ordered != $filled){
$required = $ordered - $filled;
if ($qty >= $required){
$fill_array[] = array($price,$required);
$filled = $filled + $required;
break;
}else{
$filled = $filled + $qty;
$fill_array[] = array($price,$qty);
}
}
}
$totalQty = 0;
$totalSum = 0;
foreach ($fill_array as $PriceQty) {
$totalSum = $totalSum + ($PriceQty[0] * $PriceQty[1]);
$totalQty = $totalQty + $PriceQty[1];
}
echo "$totalSum/$totalQty = ".($totalSum/$totalQty);
There might be simpler way of doing this, someone could improve this answer. For now it produces expected average.

php loop array to get total

I am having some difficulty looping through an array and calculating fields. Here is the array $iroom:
Array
(
[num_rooms] => 2
[adults] => Array
(
[0] => 2
[1] => 2
)
[prices] => Array
(
[0] => 44.5
[1] => 44.5
)
[roomTotalPrice] => Array
(
[0] => 89
[1] => 89
)
[price] => 178
)
I want to (adults*prices)+(adults*$asup)+(chidern*$csup)+$ssup and pu the answer into the roomTotalPrice. So far the outer forloop sets the roomTotalPrice price but I cannot get the inner loops to calculate the price. The $sup are extra supplement prices.
The code I got so far:
foreach($iroom['roomTotalPrice'] as &$irt){
foreach($iroom['adults'] as $ira){
}
$irt = ;
}
CODE WRAPPED IN FUNCTION, TO HANDLE NEW ARRAY FORMAT
/*
Note that this function may not be 100% correct. I notice you have removed
the 'supp' key from the array, and that your current spec doesn't do anything
with the 'price' key. I suspect you may want the line
+ ((isset($array['supp'])) ? $array['supp'] : 0);
to read
+ ((isset($array['price'])) ? $array['price'] : 0);
*/
function calculateTotalPrices ($array, $asup = 10, $csup = 10) {
if (!is_array($array) || !isset($array['num_rooms']) || !$array['num_rooms']) return FALSE; // make sure data is valid
for ($i = 0; $i < $array['num_rooms']; $i++) { // Loop num_rooms times
$array['roomTotalPrice'][$i] =
((isset($array['adults'][$i],$array['prices'][$i])) ? ($array['adults'][$i] * $array['prices'][$i]) + ($array['adults'][$i] * $asup) : 0) // Calculate price for adults
+ ((isset($array['childern'][$i])) ? ($array['childern'][$i] * $csup) : 0) // Calculate price for children
+ ((isset($array['supp'])) ? $array['supp'] : 0); // Add the supplement
}
// Get a total price for adults + children + supplements for all rooms
$array['grandTotal'] = array_sum($array['roomTotalPrice']);
return $array;
}
$iroom = array (
'num_rooms' => 2,
'adults' => array (
0 => 2,
1 => 3
),
'childern' => array (
0 => 1,
1 => 2
),
'prices' => array (
0 => 44.5,
1 => 44.5
),
'price' => 178,
);
print_r(calculateTotalPrices($iroom));
/* With the above array, outputs
Array
(
[num_rooms] => 2
[adults] => Array
(
[0] => 2
[1] => 3
)
[childern] => Array
(
[0] => 1
[1] => 2
)
[prices] => Array
(
[0] => 44.5
[1] => 44.5
)
[price] => 178
[roomTotalPrice] => Array
(
[0] => 119
[1] => 183.5
)
[grandTotal] => 302.5
)
*/
print_r(calculateTotalPrices($iroom,20,25));
/* With your sample array, outputs
Array
(
[num_rooms] => 2
[adults] => Array
(
[0] => 2
[1] => 3
)
[childern] => Array
(
[0] => 1
[1] => 2
)
[prices] => Array
(
[0] => 44.5
[1] => 44.5
)
[price] => 178
[roomTotalPrice] => Array
(
[0] => 154
[1] => 243.5
)
[grandTotal] => 397.5
)
*/
CODE UPDATED WITH ADDITIONAL CHECKS
foreach ($iroom as $k1 => $v1) { // Loop outer array
if (is_array($v1)) { // Make sure element is an array
foreach ($v1 as $k2 => $v2) { // Loop inner array
if (is_array($v2)) { // Make sure element is an array
for ($i = 0; $i < $v2['num_rooms']; $i++) { // Loop num_rooms times
$iroom[$k1][$k2]['roomTotalPrice'][$i] =
((isset($v2['adults'][$i],$v2['prices'][$i])) ? ($v2['adults'][$i] * $v2['prices'][$i]) + ($v2['adults'][$i] * $asup) : 0) // Calculate price for adults
+ ((isset($v2['childern'][$i])) ? ($v2['childern'][$i] * $csup) : 0) // Calculate price for children
+ $v2['supp']; // Add the supplement
}
// Get a total price for adults + children + supplements for all rooms
$iroom[$k1][$k2]['grandTotal'] = array_sum($iroom[$k1][$k2]['roomTotalPrice']);
}
}
}
}
print_r($iroom);
EDIT
Using the exact code above, feeding in the array above, and setting $asup = $csup = 10; at the top, I get no errors, and this output:
Array
(
[10] => Array
(
[12] => Array
(
[num_rooms] => 2
[adults] => Array
(
[0] => 2
[1] => 3
)
[childern] => Array
(
[0] => 1
[1] => 2
)
[prices] => Array
(
[0] => 44.5
[1] => 44.5
)
[price] => 178
[supp] => 0
[roomTotalPrice] => Array
(
[0] => 119
[1] => 183.5
)
[grandTotal] => 302.5
)
)
)
Note that the first result comes out at 119, not 129 as you state in the comment above - this is because in your example array, supp is 0 and not 10, as you have used in your calculation.
I have also tested with more complex arrays (with more elements at the first and second levels) and it works fine.
I'm guessing if you are getting "invalid argument supplied for foreach" errors it's because in your actual array, you highest level has some non-array memebers. This can easily be overcome by changing
foreach ($v1 as $k2 => $v2) {
to
if (is_array($v1)) foreach ($v1 as $k2 => $v2) {

Drop Array Element and Sum Remaining Elements

I have an array that output's this:
Array (
[0] => Array ( [week] => 1 )
[1] => Array ( [user] => 1 )
[2] => Array ( [score] => 6 )
[3] => Array ( [week] => 1 )
[4] => Array ( [user] => 15 )
[5] => Array ( [score] => 6 )
[6] => Array ( [week] => 2 )
[7] => Array ( [user] => 1 )
[8] => Array ( [score] => 5 )
[9] => Array ( [week] => 2 )
[10] => Array ( [user] => 15 )
[11] => Array ( [score] => 7 )
How do I drop the lowest score for user 1 (which would be 5 taken in week 2) from the array? I only want to drop the lowest number from the array for user 1 and then want to do the same thing for user 15 (which would be 6 in week 1).
Then, how would I sum the remaining scores in the array by user? There will be more weeks data to follow and I always want to drop the lowest per user for any week.
So thus far the total score for User 1 would be 6 thru 2 weeks and the total score for User 15 would be 7 thru week 2. If week 3 has lower scores for both users then their totals would be: User 1 = 11 and User 15 = 13.
Thanks in advance!!
Assuming that all records are in groups of 3:
$array = array(/* your data */);
$count = count($array) / 3;
$lowest = 0;
$min = PHP_INT_MAX;
for($i = 0; $i < $count; $i++)
{
if($array[$i + 1]['user'] == 1)
{
if($array[$i + 2]['score'] < $min)
{
$min = $array[$i + 2]['score'];
$lowest = $i;
}
}
}
unset($array[$lowest]);
unset($array[$lowest + 1]);
unset($array[$lowest + 2]);
Should at least give you the idea.
Your array structure is bizarre. Why is every array element itself a singleton array? Something like the following would make more sense:
$array_better = array (
[0] => array (
['week'] => 1,
['user'] => 1,
['score'] => 6
),
[1] => array (
['week'] => 1,
['user'] => 15,
['score'] => 6
),
[2] => array (
['week'] => 2,
['user'] => 1,
['score'] => 5
),
[3] => array (
['week'] => 2,
['user'] => 15,
['score'] => 7
)
)
But for that matter, what would make still more sense would be a $array[$week][$user] structure, like this:
$array_wu = array (
[1] => array (
[1] => 6,
[15] => 6
),
[2] => array (
[1] => 5,
[15] => 7
)
)
(If you do not understand what I have done here, please ask me about it.)
Alternatively again, you could have a $array[$user][$week] structure:
$array_uw = array (
[1] => array (
[1] => 6,
[2] => 5
),
[15] => array (
[1] => 6,
[2] => 7
)
)
This in particular would make it very easy to do what you are trying to do - in fact it would take only one line of code statement:
$sum_excl_lowest = (array_key_exists(1, $array_uw) and count($array_uw[1])) ?
array_sum($array_uw[1]) - min($array_uw[1]) :
0;

Categories