Calculation error, help me find please? - php

I am running subscriptions on my website.
I have a 1,3,6 and 12 months of subscription, and I would like the user to be able to change that subscription whenever they feel like.
However, I need to calculate the amount of money the user had to pay had he or she signed up for the shorter term, rather the relatively cheap,longer one.
I made this function optimized_subscription_total($active_sub_time,$arr_sub_values) so that it returns that sum of money exactly.
<?php
function optimized_subscription_total($active_sub_time,$arr_sub_values)
{
// This function takes a row from the DB where prices for each period of time usage is listed. there are prices for 1 month, 3 months,6 and 12 months.
// when the user has subscribed for 12 months, and the user asks for a refund, after they used 9 months and 6 days for example, the system treats the refund as if they subscribed for (in months) COST_6 + COST_3 + (COST_1/30)*6
// the result of the function is then subtracted from the amount they actually paid and is considered the refund.
// $arr_sub_values is the associative row from the DB, containing the prices
// $active_sub_time is measured in months and is a double
$result=0;
while(($active_sub_time-12)>=0)
{
$active_sub_time-=12;
$result+=($arr_subscription_values['COST_12']);
}
while(($active_sub_time-6)>=0)
{
$active_sub_time-=6;
$result+=($arr_subscription_values['COST_6']);
}
while(($active_sub_time-3)>=0)
{
$active_sub_time-=3;
$result+=($arr_subscription_values['COST_3']);
}
while(($active_sub_time-1)>=0)
{
$active_sub_time-=1;
$result+=($arr_subscription_values['COST_1']);
}
if($active_sub_time>0)
$result+=($active_sub_time)*($arr_subscription_values['COST_1']);
return $result;
}
$datetime1 = date_create('2009-12-11');
$datetime2 = date_create('2010-11-09');
$interval = date_diff($datetime1, $datetime2);
$num_of_months = ($interval->format('%y'))*12+($interval->format('%m'))+($interval->format('%a'))/30;
echo "<br />";
$v = array('COST_1'=>'3.99','COST_3'=>'9.99','COST_6'=>'15.99','COST_12'=>'25.99');
echo "OPT value for $num_of_months months=" . optimized_subscription_total($num_of_months, $v);
?>
Strangely I get the bug appearing only after 7 to 10 times after refreshing this code.
So I got:
OPT value for 10 months=M.97
as a result here. I think I need to get a float number, no ?
I was expecting the result of the function that should be "OPT value for 10 months=29.97", as it should take COST_6 + COST_3 + COST_1... but I get that weird M.97, and sometimes things like POKHHHG.97

I would change the logic to the following and see if error is still produced. I think this is a little bit more clear and easy to debug. It is the same as your though just explained differently.
while($active_sub_time>=12)
{
$active_sub_time-=12;
$result+=($arr_subscription_values['COST_12']);
}
while($active_sub_time>=6)
{
$active_sub_time-=6;
$result+=($arr_subscription_values['COST_6']);
}
while($active_sub_time>=3)
{
$active_sub_time-=3;
$result+=($arr_subscription_values['COST_3']);
}
while($active_sub_time>=1)
{
$active_sub_time-=1;
$result+=($arr_subscription_values['COST_1']);
}
What I would also do is added debug cod at the top inside function.
echo "<br>$active_sub_time" // debug code include at the top
This will give you an idea, if any garbage being is being sent to the function itself.
Also I would add this test function in all while blocks if the above does not resolve the issue.
if (!is_numeric($result))
{
echo"<br> Bug occurred";break; // print other values if necessary
}

Related

Google Analytics Report Api start-time fail

i made simple PHP code to show uniquePageViews for my website. The main code was for 7days, but i want to make it lifetime and when i made start-date: "2017-10-5" it start shows me errors. But documentation says that i can place date in that type.
Work variant:
try {
$result = $service->data_ga->get( $GA_VIEW_ID, '100daysAgo', 'today','ga:uniquePageviews');
$count = $result->totalsForAllResults['ga:uniquePageviews'];
echo $count;
} catch(Exception $e) {
var_dump($e);
}
Fail variant:
try {
$result = $service->data_ga->get( $GA_VIEW_ID, '2017-10-5', 'today','ga:uniquePageviews');
$count = $result->totalsForAllResults['ga:uniquePageviews'];
echo $count;
} catch(Exception $e) {
var_dump($e);
}
From the documentation you linked (Emphasis mine) :
All Analytics data requests must specify a date range. If you do not include start-date and end-date parameters in the request, the server returns an error. Date values can be for a specific date by using the pattern YYYY-MM-DD or relative by using today, yesterday, or the NdaysAgo pattern. Values must match [0-9]{4}-[0-9]{2}-[0-9]{2}|today|yesterday|[0-9]+(daysAgo).
Which means your day must be displayed with two digits. Try 2017-10-05 as your start date.

Compare time difference

I want to compare the time between sent messages, so that i know how quick someone would respond.
message_sent is the unix timestamp when a message has been sent.
ID: 0000000005 is the start, ID: 0000000006 is a response on the message of ID: 0000000005.
With this data: 0000000006 sent a message on 1483021773. The original question was asked in 0000000005 on 1483021687. So the reaction time is 1483021773 - 1483021687. How should i approach this so i get an average response time?
The data
Assuming that a response time is defined by the time it takes for a user to respond to the last message of another user:
$response_times = array(); // array of response times
// let's define a variable to keep track of the person
// to which another person will respond. initially, variable will hold
// the first message
$initiator = array_shift($messages);
// now iterator through messages
foreach ($messages as $message) {
// if this message belongs to the initiator, just update the timestamp
if ($message['from_user_id'] == $initiator['from_user_id']) {
$initiator['message_sent'] = $message['message_sent'];
continue; // and go to the next message
}
// otherwise, calculate the time difference and put it in response times
array_push($response_times, $message['message_sent'] - $initiator['message_sent']);
// and update the initiator
$initiator = $message;
}
// finally, calculate average of response time
$avg_response_time = array_sum($response_times) / count($response_times);
Since i don't know the exact code here is some sudo code with an example:
$total_items = count($array_of_items);
$starting_time_total = "0";
// Some code here to do your message_sent - message_sent = $some_value;
// Do the following for every single item for the $total_items in array
$starting_time_total = $starting_time_total + $some_value;
//Now to get the average we do this
$average = $starting_time_total / $total_items;
So if you have 4 items in the array, with response times of 423, 395, 283, 583 respectively, you are left with an average response time of 421 which you can then convert to seconds of minutes or whatever.

time greater than another time

I am preparing a small php attendance script which will record the time and date of given user.
I am trying to display a message that if person is LATE after given time php to display a message you are late
$CURRENTTIME = new DateTime($data['current_time']);
$CURRENTTIME = $CURRENTTIME->format('H:i:s');
$OFFICETIME = new DateTime('10:20:00');
$OFFICETIME = $OFFICETIME->format('H:i:s');
var_dump($CURRENTTIME);
var_dump($OFFICETIME);
if ($CURRENTTIM > $OFFICETIME) {
echo 'you are late tody';
} else {
echo 'Thank you for being on time';
}
also i wanted to learn the code if i need a result in between time? let say i need to display result if employee is in between 10:00:00 - 10:30:00
DateTime objects are comparable so no need to compare their formatted strings. Just compare the objects themselves.
$CURRENTTIME = new DateTime($data['current_time']);
$OFFICETIME = new DateTime('10:20:00');
if ($CURRENTTIME > $OFFICETIME) {
echo 'you are late tody';
} else {
echo 'Thank you for being on time';
}
See this answer for how to see if a time is between two times. It's pretty much the same concept.
Sidenote: There was a typo in your code. $CURRENTTIM which should read as $CURRENTTIME.

Golf league payout to six finishing positions

I have a golf league of 40 individuals. We all throw money in a pot and pay out the first 6 places based on final score.
If there were no ties the pay out would be simple but often we have, for example, 2 people tied for first place, 3 people tied for second, 1 person alone in third, etc. The variations seem endless.
I've been trying to automate the calculated payouts for each place using PHP but have not been successful. Any suggestions, help, or pointing in the right direction would be much appreciated. I noticed that someone else tried to ask a similar question on this site but was not successful in framing the question. I'll try to do a better job.
Here is some data I've been playing around with:
$playerNumber=40;
$totalPoints=100;
Payouts:
$pointsFirst=0.6*$totalPoints;
$pointsSecond=0.2*$totalPoints;
$pointsThird=0.15*$totalPoints;
$pointsFourth=0.03*$totalPoints;
$pointsFifth=0.02*$totalPoints;
$pointsSixth=0.01*$totalPoints;
For the example given above and to pay out six places, we would calculate the payouts as follows:
If two people are tied for first place, we add first and second place points and divide by two.
If three people are tied for second place, we add third, fourth and fifth place points and divide by three.
If one person is alone in third, this person would win sixth place points.
I can count the number of players who are in or tied for a certain place.
$countFirst=2;
$countSecond=3;
$countThird=1;
$countFourth=2;
$countFifth=1;
$countSixth=2;
In this example the player scores would be 72, 72, 73, 73, 73, 74, 75, 75, 76, 77, 77.
At first I thought this was an application for nested arrays. Then I thought perhaps using arrays, array slice, etc, may be a way to go. Each time I end up in the woods. I'm not seeing the logic.
I have used conditional statements for paying out three places but to pay out six places with this method puts me deep in the woods.
Example of payout to three places using conditional statements:
$pointsFirst=0.5*$totalPoints;
$pointsSecond=0.3*$totalPoints;
$pointsThird=0.2*$totalPoints;
if($countFirst>2) {
$ptsA=round($totalPoints/$countFirst,2);
}
elseif($countFirst==2) {
$ptsA=round(($pointsFirst+$pointsSecond)/2,2);
if($countSecond>1) {
$ptsB=round($pointsThird/$countSecond,2);
}
elseif($countSecond==1) {
$ptsB=round($pointsThird,2);
}
}
elseif($countFirst==1) {
$ptsA=round($pointsFirst,2);
if($countSecond>1) {
$ptsB=round(($pointsSecond+$pointsThird)/2,2);
}
elseif($countSecond==1) {
$ptsB=round($pointsSecond,2);
if($countThird>1) {
$ptsC=round($pointsThird/$countThird,2);
}
elseif($countThird==1) {
$ptsC=round($pointsThird,2);
}
}
}
I hope I have been clear in my request. I'll be glad to clarify anything. If anyone has any ideas on how to efficiently automate a payout calculation to six places I will be eternally grateful. Thank-you! Mike
Per request:
$scores=array();
$scores[0]=72;
$scores[1]=72;
$scores[2]=73;
$scores[3]=73;
$scores[4]=73;
$scores[5]=74;
$scores[6]=75;
$scores[7]=75;
$scores[8]=76;
$scores[9]=77;
$scores[10]=77;
$payout=array();
$payout[0]=0.6*$totalPoints;
$payout[1]=0.2*$totalPoints;
$payout[2]=0.15*$totalPoints;
$payout[3]=0.03*$totalPoints;
$payout[4]=0.02*$totalPoints;
$payout[5]=0.01*$totalPoints;
$countScores=array();
$countScores[0]=$countFirst;
$countScores[1]=$countSecond;
$countScores[2]=$countThird;
$countScores[3]=$countFourth;
$countScores[4]=$countFifth;
$countScores[5]=$countSixth;
First, there is a problem with your Payouts. If you add them up you get 1.01 not 1
0.6 (1st) + 0.2 (2nd ) + 0.15 (3rd) + 0.03 (4th) + 0.02 (5th) + 0.01 (6th) = 1.01
Second, it is easier if you make your Payouts and Counts into arrays -
change these -
$pointsFirst=0.6*$totalPoints;
$pointsSecond=0.2*$totalPoints;
$pointsThird=0.15*$totalPoints;
$pointsFourth=0.03*$totalPoints;
$pointsFifth=0.02*$totalPoints;
$pointsSixth=0.01*$totalPoints;
$countFirst=2;
$countSecond=3;
$countThird=1;
$countFourth=2;
$countFifth=1;
$countSixth=2;
to these
$payout=array();
$payout[0]=0.6*$totalPoints;
$payout[1]=0.2*$totalPoints;
$payout[2]=0.15*$totalPoints;
$payout[3]=0.03*$totalPoints;
$payout[4]=0.02*$totalPoints;
$payout[5]=0.01*$totalPoints;
$count=array();
$count[0]=2;
$count[1]=3;
$count[2]=1;
$count[3]=2;
$count[4]=1;
$count[5]=2;
Here is the start of one way to do it. Although I would eventually change this into a function so that I can use it again with different payouts, and number of places (see phpfiddle examples below)
I see this in 4 steps-
Step 1
// Add together the payments if there are ties - ie. 2 tied for first $payout[0]+$payout[1], etc
$payout_groups = array(); // start a payout array
$payout_groups_key = 0; // array key count
$payout_groups_count = 0; // array counter, use to match the $count array values
for($w=0;$w<count($payout);$w++){ //
if(array_key_exists($payout_groups_key,$payout_groups)){
$payout_groups[$payout_groups_key] += $payout[$w]; // if there are ties, add them together
}
else{
$payout_groups[$payout_groups_key] = $payout[$w]; // else set a new payout level
}
$payout_groups_count++; // increase the counter
if($payout_groups_count == $count[$payout_groups_key]){ // if we merged all the ties, set a new array key and restart the counter
$payout_groups_key++;
$payout_groups_count = 0;
}
}
Step 2
// basic counter to get how many placers/winners. This makes it possible to have ties for 6th (last) place
$x = 0;
$y = 0;
while($y < count($payout)){
$y += $count[$x]; // the $count array values until we reach the amount of places/payouts
$x++;
}
Step 3
// Create array for winnings per placing
$winnings = array(); // start an array
$placings_count = 0; //
$placings_counter = 0;
for($z=0;$z<$y;$z++){
$winnings[$z] = $payout_groups[$placings_count]/$count[$placings_count];
$placings_counter++;
if($placings_counter == $count[$placings_count]){
$placings_count++;
$placings_counter = 0;
}
}
Step 4
// Assign winnings to scorecard
$scoreboard = array();
for($t=0;$t<count($winnings);$t++){
$scoreboard[$t]['score'] = $scores[$t];
$scoreboard[$t]['payout'] = $winnings[$t];
}
You can see this using your defined values at - http://phpfiddle.org/main/code/a1g-qu0
Using the same code above, I changed the payout amounts, and increased it to 7th places - http://phpfiddle.org/main/code/uxi-qgt

Can't find the memory leak in this snippet

using PHP Version 5.3.5
I am going insane.
This piece of code is giving me hard time. After I refresh the page on Apache a few times, I get weird results. I think I have a memory leak here, but I can't find out why.
Please help !
<?php
function ost($active_sub_time,$arr_subscription_values)
{
$result=0;
while($active_sub_time>=12)
{
$active_sub_time-=12;
$result+=($arr_subscription_values['COST_12']);
}
while($active_sub_time>=6)
{
$active_sub_time-=6;
$result+=($arr_subscription_values['COST_6']);
}
while($active_sub_time>=3)
{
$active_sub_time-=3;
$result+=($arr_subscription_values['COST_3']);
}
while($active_sub_time>=1)
{
$active_sub_time-=1;
$result+=($arr_subscription_values['COST_1']);
}
if($active_sub_time>0)
$result+=($active_sub_time)*($arr_subscription_values['COST_1']);
if (!is_numeric($result))
{
echo"<br> Bug occurred";break; // print other values if necessary
}
return $result;
}
$datetime1 = date_create('2009-01-11');
$datetime2 = date_create('2001-11-09');
$interval = date_diff($datetime1, $datetime2);
$num_of_months = ($interval->y)*12 + ($interval->m) + ($interval->d)/(cal_days_in_month(CAL_GREGORIAN, $datetime2->format("m"), $datetime2->format("Y")));
$v = array('COST_1'=>'3.99','COST_3'=>'9.99','COST_6'=>'15.99','COST_12'=>'24.99');
echo "OPT value for $num_of_months months=".ost($num_of_months,$v);
?>
I do get this result at first:
OPT value for 86.066666666667 months=183.176
But after a few refreshes I get this :
OPT value for G.GMMMMMMMMMMMN months=183.176
Does anyone know why this is ?
Thanks
Cannot reproduce, I used your code exactly, and executed it multiple times. It displays the same result.
There may be an issue with your server, or mashing refresh over and over is causing some kind of problem or memory limit.
Check your php.ini and see if your memory limit is set too low, or max requests?

Categories