Calculating Vat Rates Based on some variables - php

The following function is working up to a point where I have to calculate the $vatamount based on some rules.
Ive got all my POST content from a script that fires my ajax request (code below is the code from the ajax URL).
The rules are - If the $bookingtype value is a "Corporate" booking or a "Groups" booking then the vat rate is calculated over the length of stay. 20% for anything up to 28 nights and 4% for anything over 28 nights.
However, if the $bookingtype value is a "Leisure" booking then the vat rate is 20% regardless of the length of stay.
I've got the function to return the right VAT percentage. But that last if statement just isn't working for me. Im a php newbish and i think I've done well to get this far with it. Just need some assistance completing this function. I think I've screwed my syntax in there somewhere lol
The last echo should echo the calculated vat amount.
Thanks in advance.
function implement_ajax_vat() {
if(isset($_POST['arrivaldate']))
{
//get the start and end dates
$startdate = ($_POST['arrivaldate']);
$enddate = ($_POST['leavingdate']);
$datetime1 = new DateTime($startdate);
$datetime2 = new DateTime($enddate);
$interval = $datetime1->diff($datetime2);
$numberofnights = $interval->format('%a nights');
//calculatge the VAT amount
$bookingtype = ($_POST['bookingtype']);
$rentalprice = ($_POST['rentalprice']);
//check numbr of nights
if($numberofnights >= 29){
$vatrate = "4";
} elseif ($numberofnights <= 28) {
$vatrate = "20";
}
//get the booking type and check if its a variable rate
if(($bookingtype = 'Corporate') || ($bookingtype = 'Groups')){
$vatamount = ($rentalprice / 100) * $vatrate;
} elseif ($bookingtype = 'Leisure') {
$vatamount = "20";
}
echo $vatamount;
die();
}
}

You are assigning values instead of comparing: use double equals sign ==:
if($bookingtype == 'Corporate' || $bookingtype == 'Groups'){
^ ^
$vatamount = ($rentalprice / 100) * $vatrate;
} elseif ($bookingtype == 'Leisure') {
^
$vatamount = 20;
}
That's why first statement yields true as you assign and return there non-empty string, so you never go to elseif section.

Related

How to display number in percentage

I wanted to know how I present a percentage, here is the code
//The number taken from the database
$minos = $ud['bnk']['gold'];
The number that is supposed to be in percent through the database (the database has a number and not a percentage for example 2)
$plus= $ud['bnk']['ent_level'];
And here is a simple calculation of X + 2% = Y
$sava = $minos + $plus;
I tried to do this, according to an internet guide, but it doesn't work for me, I want the number to be a percentage and not successful
function get_percentage($total, $number)
{
if ( $total > 0 ) {
return round($number / ($total / 100),$ud['bnk']['ent_level']);
} else {
return 0;
}
}
$minos = $ud['bnk']['gold'];
$plus = get_percentage(100,$ud['bnk']['ent_level']).'%';
$sava = $minos + $plus;
I solved the equation with what you gave me, thank you very much, the way is:
$minos = $ud['bnk']['gold'];
$plus = ($minos / 100) * $ud['bnk']['ent_level'];
$sava = $plus;
Thanks so much to everyone who helped

Php Calculate percentage difference between two numbers

I am trying to find the difference of two numbers in percentage. The actual scenario is iam getting a total value of user data for this week and for last week. Now i need to see the performance difference in percentage with this weeks data and last weeks data. Following is my code which i am trying. But at times either any of the data will be zero and am getting an error "Division by zero". How to handle that?
$this_week_cust=$row["cust_count_new"];
$last_week_cust=$row["cust_count_old"];
$percentChange = (1 - $last_week_cust / $this_week_cust) * 100;
You can check if $this_week_cust is zero and just set the change to 100%
$this_week_cust=$row["cust_count_new"];
$last_week_cust=$row["cust_count_old"];
if ( $this_week_cust == 0 ) {
$percentChange = -100;
}
else {
$percentChange = (1 - $last_week_cust / $this_week_cust) * 100;
}
Altough the change would be 0 if $last_week_cust was also 0, so perhaps
if ( $this_week_cust == 0 ) {
$percentChange = ($last_week_cust==0)?0:-100;
}
I think this will help you.
$original= 1000;
$current = 5;
$diff = $current - $original;
$more_less = $diff > 0 ? "More" : "Less";
$diff = abs($diff);
$percentChange = ($diff/$original)*100;
echo "$percentChange% $more_less agaist $original";
try this
if $this_week_cust!=0 that time only calculation will perform otherwise not do anything
$this_week_cust=$row["cust_count_new"];
$last_week_cust=$row["cust_count_old"];
if($this_week_cust!=0){
$percentChange = (1 - $last_week_cust / $this_week_cust) * 100;
}
You can get the desired result by checking $this_week_cust, if is it return zero, null or empty set $this_week_cust to 100;
$percentChange=100;

PHP Auto Aging Task for MyBB

So, I was wondering if anybody would mind checking over this task and correcting it? I'm very sure I've muddled Python in with what little PHP I know, and that there are open tags.
Basically, there'll be a field where the nasty decimal age goes ($age, which will later be replaced by the appropriate field id). Our site works in months for juveniles and then years and seasons for adults. Using the nasty age, I'm trying to calculate the rounded age values and then store them as a string value which will then be set as the value of the field that will display the age ($displayagefid, will be replaced later with the appropriate field id). Only certain usergroups will be updated (the list is huge, so I left it out).
I also have no idea how to set a variable as a string using both string and the value of another variable.
Please know that I'm a complete newbie to PHP.
This is intended to run as a task on a self-hosted MyBB forum.
Thank you in advance!
<?php
function task_age($task)
{
global $mybb, $db;
$increment = 0.04167
$age = $age + $increment
floor($age*4) = $seasons
floor($age) = $years
floor($age*12) = $months
if ($year < 1) {
$display_age = $months, "mnths"
}
elseif ( ! filter_var($year, FILTER_VALIDATE_INT) ){
$display_age = $year, "yrs"
}
else {
$display age = $display_age = $years, "yrs", $seasons, "s"
};
$query = $db->query("
UPDATE mybb_userfields userfields
for ($usergroup = a || b || d || all that other crap) {
SET $dispalyagefid = $display_age;
};
");
add_task_log($task, "The age characters task successfully ran.");
I had a cursory look over your code and the first thing which sticks out is you have some of your variable assignments back to front:
$increment = 0.04167
$age = $age + $increment
floor($age*4) = $seasons
floor($age) = $years
floor($age*12) = $months
Whatever is on the left gets set to whatever is on the right, so your first two are OK but the last three need switching around.
Having said that it seems to me you are not approaching this correctly. I enter my decimal age into your site but how are you going to work out seasons? It might be my birthday tomorrow, it might have been my birthday yesterday.
You would be better off having the user enter a date of birth, from that calculate their age.
$birthday=date_create("2013-03-15");
$today=date_create('now');
$diff=date_diff($birthday,$today);
Now in the $diff variable you can check all the elements of a PHP date. So first check if they are under 18:
if ($diff->format("%y") < 18) {
$ageInMonths = ($diff->format("%y") * 12) + $diff->format("%m");
$age = "$ageInMonths months";
}
If they are over 18 you want age in years, then calculate seasons from the remaining months.
else {
$ageInYears = $diff->format("%y");
$ageInSeasons = floor($diff->format("%m") / 4);
if ($ageInSeasons > 0) {
$age = "$ageInYears years and $ageInSeasons seasons";
} else {
$age = "$ageInYears years";
}
}

Optimal way of cycling through 1000's of values

I need to find the value of x where the variance of two results (which take x into account) is the closest to 0. The problem is, the only way to do this is to cycle through all possible values of x. The equation uses currency, so I have to check in increments of 1 cent.
This might make it easier:
$previous_var = null;
$high_amount = 50;
for ($i = 0.01; $i <= $high_amount; $i += 0.01) {
$val1 = find_out_1($i);
$val2 = find_out_2();
$var = variance($val1, $val2);
if ($previous_var == null) {
$previous_var = $var;
}
// If this variance is larger, it means the previous one was the closest to
// 0 as the variance has now started increasing
if ($var > $previous_var) {
$l_s -= 0.01;
break;
}
}
$optimal_monetary_value = $i;
I feel like there is a mathematical formula that would make the "cycling through every cent" more optimal? It works fine for small values, but if you start using 1000's as the $high_amount it takes quite a few seconds to calculate.
Based on the comment in your code, it sounds like you want something similar to bisection search, but a little bit different:
function calculate_variance($i) {
$val1 = find_out_1($i);
$val2 = find_out_2();
return variance($val1, $val2);
}
function search($lo, $loVar, $hi, $hiVar) {
// find the midpoint between the hi and lo values
$mid = round($lo + ($hi - $lo) / 2, 2);
if ($mid == $hi || $mid == $lo) {
// we have converged, so pick the better value and be done
return ($hiVar > $loVar) ? $lo : $hi;
}
$midVar = calculate_variance($mid);
if ($midVar >= $loVar) {
// the optimal point must be in the lower interval
return search($lo, $loVar, $mid, $midVar);
} elseif ($midVar >= $hiVar) {
// the optimal point must be in the higher interval
return search($mid, $midVar, $hi, $hiVar);
} else {
// we don't know where the optimal point is for sure, so check
// the lower interval first
$loBest = search($lo, $loVar, $mid, $midVar);
if ($loBest == $mid) {
// we can't be sure this is the best answer, so check the hi
// interval to be sure
return search($mid, $midVar, $hi, $hiVar);
} else {
// we know this is the best answer
return $loBest;
}
}
}
$optimal_monetary_value = search(0.01, calculate_variance(0.01), 50.0, calculate_variance(50.0));
This assumes that the variance is monotonically increasing when moving away from the optimal point. In other words, if the optimal value is O, then for all X < Y < O, calculate_variance(X) >= calculate_variance(Y) >= calculate_variance(O) (and the same with all > and < flipped). The comment in your code and the way have you have it written make it seem like this is true. If this isn't true, then you can't really do much better than what you have.
Be aware that this is not as good as bisection search. There are some pathological inputs that will make it take linear time instead of logarithmic time (e.g., if the variance is the same for all values). If you can improve the requirement that calculate_variance(X) >= calculate_variance(Y) >= calculate_variance(O) to be calculate_variance(X) > calculate_variance(Y) > calculate_variance(O), you can improve this to be logarithmic in all cases by checking to see how the variance for $mid compares the the variance for $mid + 0.01 and using that to decide which interval to check.
Also, you may want to be careful about doing math with currency. You probably either want to use integers (i.e., do all math in cents instead of dollars) or use exact precision numbers.
If you known nothing at all about the behavior of the objective function, there is no other way than trying all possible values.
On the opposite if you have a guarantee that the minimum is unique, the Golden section method will converge very quickly. This is a variant of the Fibonacci search, which is known to be optimal (require the minimum number of function evaluations).
Your function may have different properties which call for other algorithms.
Why not implementing binary search ?
<?php
$high_amount = 50;
// computed val2 is placed outside the loop
// no need te recalculate it each time
$val2 = find_out_2();
$previous_var = variance(find_out_1(0.01), $val2);
$start = 0;
$end = $high_amount * 100;
$closest_variance = NULL;
while ($start <= $end) {
$section = intval(($start + $end)/2);
$cursor = $section / 100;
$val1 = find_out_1($cursor);
$variance = variance($val1, $val2);
if ($variance <= $previous_var) {
$start = $section;
}
else {
$closest_variance = $cursor;
$end = $section;
}
}
if (!is_null($closest_variance)) {
$closest_variance -= 0.01;
}

Why does this simple subtraction does not work?

So this will be very specific question, but I am losing my sanity as I was staring at this for the better part of the day. So here I wrote this function to calculate the price dependent commission:
function commision($amount, $commision_arg = 0){
// $temp_amount = 0;
// $commision = 0;
if($amount > 999){
$temp_amount = $amount - 999;
$commision_arg += $temp_amount/100*1;
return commision(999, $commision_arg);
}else if($amount>249&&$amount<=999){
$temp_amount = $amount - 249;
$commision_arg += $temp_amount/100*3;
return commision(249, $commision_arg);
}else if($amount>49 && $amount<=249){
$temp_amount = $amount - 49;
$commision_arg += $temp_amount/100*5;
return commision(49, $commision_arg);
}else if($amount <= 49){
return number_format($commision_arg + 3.5, 2);
}
}
Basically if $amount is less then 49 then it is just flat 3.5 rate, if $amount is 49 to 249 then it is flat rate 3.5 + 5% of anything in 49-249 range.
I am not sure if this is good way to do this or not, but it works. However there is issue with another method that uses this function:
public function amountPayable(){
$amount = $this->uri->segment(3);
echo $amount - commision($amount);
}
This is just a function in codeigniter controller, that is called by AJAX request, and it should be returning the amount payable by the customer, which is then injected into DOM.
And this is where the problem lies.
Basically if I pass the $amount that equal to 100.000, what I get back from amountPayable is 99.999, whereas it should be: 98973.9. if I change echo $amount - commision($amount); to echo commision($amount); then I get back 1026.1. So the commision() function returns the correct number. But for some reason $amount - commision($amount); (where $amount = 100000) evaluates to 1.
How can this be?

Categories