value ($age) returns unexpected result - php

Ideally what should happen is, based on the in-game date that the site is set to (currently its 3014-11-16) the site should calculate a characters current age and return that age. So if we set the Year to ignore year to 10 and a characters Date of Birth to 2, we would get an age of 8.
The current date is set to: 3014-11-16 (yyyy-mm-dd)
The date of birth for timber wolf is: 2998-01-12 (yyyy-mm-dd)
His age should display as 16, instead it displays as -55
If i set his DOB to: 3013-11-16, his age become -71
If i set his DOB to: 3012-11-16, his age come back -70
If i set his DOB to: 3005-11-16, his age comes back as -63 instead of 7
If i set his DOB to: 2998-11-16, his age comes back as -56 instead of 16
If i set his DOB to: 2945-11-16, his age come back as -3
If i set his DOB to: 2944-11-16, his age comes back as -1
If i set his DOB to: 2943-11-16, his age comes back as 0
If i set his DOB to: 2105-11-16, his age come back 837 instead of 909
I've tried to minimize the code by removing a lot of the key array and parts that are not related to the problem. If I set the $age at the very last line to $age=15, I get fifteen, so I know that I am trying to revise the value being returned to the $age variable, but I'm completely lost after many attempts.
I'm looking for a way to get the correct age of the character. Thats my goal, hopefully someone out there can see what i'm doing wrong.
Here is the relevant code:
require_once('../include/Application.php'); // The only class we need to include
$app = new Application(); // Create the initial application object
$app->connect(); // Connect to the mysql server
$sess = new Session(); // Start a new session
$current = new CurrentUser(FALSE);
if ($current->errors) {
$errors = $current->errors;
trigger_error(current($errors), E_USER_ERROR);
}
include ("../functions.php");
$id="";
$record=array();
approveVars(array("id"));
$PHP_SELF = $_SERVER["PHP_SELF"];
$errors = array();
// Get daytimes from db
$daytimes = new DaytimeList();
if ($daytimes->errors) {
$errors = $daytimes->errors;
trigger_error(current($errors), E_USER_ERROR);
}
// Get the current game from the db
require_once('../include/Game.php');
$cu_game = new Game();
$cu_game->selectCurrent();
if ($cu_game->errors) { // Query error
$errors = $cu_game->errors;
trigger_error(current($errors), E_USER_ERROR);
} elseif ($cu_game->id) { // We got the current game
list($gametime, $realtime, $daylength, $inittod) = array(htmlspecialchars($cu_game->gametime, ENT_QUOTES), htmlspecialchars($cu_game->realtime, ENT_QUOTES), $cu_game->daylength/604800, htmlspecialchars($daytimes->data[$cu_game->inittod], ENT_QUOTES));
}
/*
$gametimefile = "$basefile/gamedate/gamedate.txt";
$tempy = file($gametimefile);
$gametime = trim($tempy[0]);
$realtime = trim($tempy[1]);
*/
if ($id) {
// FORMULA FOR GAME TIME
// FROM_DAYS(TO_DAYS('$gametime') + FLOOR((TO_DAYS(NOW()) - TO_DAYS('$realtime')) /14))
if (!is_numeric($id)) {
$characterSQL = "SELECT *, DATE_FORMAT(lastmodified,'%b %e # %h:%i %p') AS modformat, TO_DAYS(NOW()) - TO_DAYS(lastmodified) as modage, IFNULL(FLOOR((TO_DAYS('$gametime') + FLOOR((TO_DAYS(NOW()) - TO_DAYS('$realtime')) / 14) - TO_DAYS(dateofbirth)) / 365.25) ,0) AS age, DATE_FORMAT(dateofbirth, '%b %e, %Y') AS dateofbirth, datecreated AS dateadded FROM cerebra where codename=\"". mysql_real_escape_string($id) . "\"";
} else {
$characterSQL = "SELECT *, DATE_FORMAT(lastmodified,'%b %e # %h:%i %p') AS modformat, TO_DAYS(NOW()) - TO_DAYS(lastmodified) as modage, IFNULL(FLOOR((TO_DAYS('$gametime') + FLOOR((TO_DAYS(NOW()) - TO_DAYS('$realtime')) / 14) - TO_DAYS(dateofbirth)) / 365.25) ,0) AS age, DATE_FORMAT(dateofbirth, '%b %e, %Y') AS dateofbirth, datecreated AS dateadded FROM cerebra where id=\"" . mysql_real_escape_string($id) . "\"";
} // end if'
$result=mysql_query($characterSQL, $db);
if (!mysql_num_rows($result)) { errorpage("There is no Cerebra record with that id number. Please check the link you used to access this page and try again, or check the <a href='/cerebra.php'>Cerebra main page</a> for the record you're looking for."); die; }
$record = mysql_fetch_assoc($result);
$id = $record["id"];
} else {
header("location: /cerebra.php");
die; } // end if ID
// "modelname","song","song_link"
//"Model", "Song", "Song Link",
$fields = array(
"Age"=>"age",
"Apparentage Age"=>"apparentage",
"Base Of Operations"=>"baseofoperations",
"Birthdate"=>"dateofbirth"
);
$patterns = array ("/\"/","/[\n\r\f]+/");
$replace = array (""","</p>\n<p>");
FOREACH ($fields as $label => $field) {
${$field} = preg_replace($patterns, $replace, trim($record[$field]));
${$field . "Name"} = $label;
} // end FOREACH
if ($age > "2000") { $age =""; }
//if i set $age = 15 here, then character age will appear as 15...

Related

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";
}
}

Query in a while loop fetching stale data

I am trying (and not succeeding) to run a while loop with a query that gets the last row in a table, uses that data then create a new row then selects the last row in the table again (which should be the row just created) then uses that data and creates a new row. This should repeat until the while loop is no longer true.
The problem I have is the while loop runs but always uses the row it selected the first time round. So the same row get inserted over and over until the while loop is false.
My question is how can I get the query to refresh when the while loop starts a new loop?
I have tried unset() but this did not work and am out of ideas. Here the while loop of my code (which is still in progress - still so much to add):-
while ($total_debt > 0) {
$get_dp_accounts_list_query = "SELECT account_id
FROM money_debt_planner
WHERE customer_id = '".$_SESSION['customer_id']."'
GROUP BY account_id";
$get_dp_accounts_list = $db->Execute($get_dp_accounts_list_query);
while (!$get_dp_accounts_list->EOF) {
$get_dp_accounts_listArray[] = array('account_id'=>$get_dp_accounts_list->fields['account_id']);
$get_dp_accounts_list->MoveNext();
}
foreach($get_dp_accounts_listArray as $acc_list) {
$get_last_dp_entry_query = "SELECT *
FROM money_debt_planner
WHERE customer_id = '".$_SESSION['customer_id']."'
AND account_id = '".$acc_list['account_id']."'
ORDER BY line_id DESC";
$get_last_dp_entry = $db->Execute($get_last_dp_entry_query);
if($get_last_dp_entry->fields['end_debt_balance'] <> 0) {
// calculate the interest this period
$accounts_balance = $get_last_dp_entry->fields['end_debt_balance'] + $get_last_dp_entry->fields['estimated_spending'];
$min_pay = $get_last_dp_entry->fields['min_pay_amount'];
$min_pay_rate = $get_last_dp_entry->fields['min_pay_rate'];
$interest_rate = $get_last_dp_entry->fields['interest_rate'];
$int_rate = $interest_rate /100;
$int_rate_a = $int_rate + 1;
$int_value_b = $accounts_balance ;
$int_value_c = ($int_rate_a * $int_value_b) - $int_value_b . ' ';
$int_value_d = $int_value_c / 12;
$statement_balance = $accounts_balance + $int_value_d;
$min_pay_rate = ($statement_balance) * $min_pay_rate / 100;
if($min_pay_rate < $min_pay) {
$new_bill_amount = $min_pay;
} else {
$new_bill_amount = $min_pay_rate;
}
if(($statement_balance) <= ($min_pay_rate) && ($statement_balance) <= $min_pay) {
$new_bill_amount = $statement_balance;
}
// next pay date
$next_due_day1 = date('d', strtotime ( $get_last_dp_entry->fields['date'] ));
$next_due_year_month1 = date('Y-m', strtotime ( $get_last_dp_entry->fields['date'] ));
$next_due_month_a_1 = strtotime ( "+ 1 month" , strtotime ( $next_due_year_month1 ) ) ;
$next_due_month_b_1 = date ( 'Y-m' , $next_due_month_a_1);
$total_days_in_this_month = date('t', strtotime($next_due_month_b_1) );
if($next_due_day1 >= $total_days_in_this_month) {
$next_due_date_a_1 = $total_days_in_this_month;
} else {
$next_due_date_a_1 = $next_due_day1;
}
$payment_date_from_account1 = $next_due_month_b_1 .'-' . $next_due_date_a_1;
$next_due1a = strtotime ( $payment_date_from_account1 ) ;
$next_due1 = date ( 'Y-m-d' , $next_due1a );
$dp_pay_date = $next_due1; // this will be 1 month from last entry
$interest_this_period = $int_value_d; // this will be interest on last end balance + est spending
$payment_this_period = $new_bill_amount; // this will be the min payment allowed including any over credit amount
$end_balance = ''; // this will be current open balance + spending + interest - payment
$sql = "INSERT INTO `money_debt_planner` (`customer_id`, `account_id`, `date`, `open_debt_balance`, `interest_rate`, `min_pay_rate`, `min_pay_amount`, `credit_limit`, `estimated_spending`, `interest_this_period`, `payment_this_period`, `end_debt_balance`)
VALUES ('".$_SESSION['customer_id']."', '".$acc_list['account_id']."', '".$dp_pay_date."', '".$get_last_dp_entry->fields['end_debt_balance']."', '".$get_last_dp_entry->fields['interest_rate']."', '".$get_last_dp_entry->fields['min_pay_rate']."', '".$get_last_dp_entry->fields['min_pay_amount']."', '".$get_last_dp_entry->fields['credit_limit']."', '".$get_last_dp_entry->fields['estimated_spending']."', '".$interest_this_period."', '".$payment_this_period."', '".$end_balance."')";
$db->Execute($sql);
} // end if balance zero
} // end account list
// to do this will be total debt balance utstanding
$total_debt = $total_debt - 1000;
}
Any help you can offer would be great :o)

Timestamp mktime php format

I have a php page listed below with events and I wish to order them by dates. No problem with this, but I want the date format was "15/Lug/1998" and not "15/Lug/1998:00:00:00 -0000". I post the code to fix this problem. Thanks in advance for your reply and help.
<?php
# For demo - some data that we will test with
$stuff = <<<COURSES
02 - - [15/Lug/1998:00:00:00 -0000] "Event01"
05 - - [21/Lug/1998:00:00:00 -0000] "Event02"
07 - - [16/Lug/1998:00:00:00 -0000] "Event03"
COURSES;
# Date in yukky format to Unix timestamp
function gdate($record) {
eregi('\[([0-9]{2})/([A-Z]{3})/([0-9]{4}):([0-9]{2}):([0-9]{2}):([0-9]{2})',
$record, $gotten);
$yikes = 1 + (strpos("GenFebMarAprMagGiuLugAgoSetOttNovDic",
$gotten[2]))/3; # Date "Alpha Triplet" to Month No.
$when = mktime($gotten[4],$gotten[5],$gotten[6],
$yikes,$gotten[1],$gotten[3]);
return $when;
}
function bydate($left,$right) {
$whenone = gdate($left);
$whentwo = gdate($right);
if ($whenone == $whentwo) return 0;
return (($whenone < $whentwo) ? -1 : +1);
}
$records = explode("\n",$stuff);
sort ($records);
$result = implode("<br />",$records);
print "<hr> Normal sort</br>$result";
usort ($records,bydate);
$result = implode("<br />",$records);
print "<hr> User defined sort - by date stamp</br>$result";
?>
Your timestamp is generated through below code
function gdate($record) {
eregi('\[([0-9]{2})/([A-Z]{3})/([0-9]{4}):([0-9]{2}):([0-9]{2}):([0-9]{2})',
$record, $gotten);
$yikes = 1 + (strpos("GenFebMarAprMagGiuLugAgoSetOttNovDic",
$gotten[2]))/3; # Date "Alpha Triplet" to Month No.
$when = mktime($gotten[4],$gotten[5],$gotten[6],
$yikes,$gotten[1],$gotten[3]);
return $when;
}
Modify it like below:
function gdate($record) {
eregi('\[([0-9]{2})/([A-Z]{3})/([0-9]{4}):([0-9]{2}):([0-9]{2}):([0-9]{2})',
$record, $gotten);
$yikes = 1 + (strpos("GenFebMarAprMagGiuLugAgoSetOttNovDic",
$gotten[2]))/3; # Date "Alpha Triplet" to Month No.
$time = mktime($gotten[4],$gotten[5],$gotten[6],
$yikes,$gotten[1],$gotten[3]);
$when = date('d/M/Y', $time); //this is solution one, recommended
$when = substr($time, 0, -15); //this is solution two
return $when;
}
EDIT:
Remain your previous code and modify below part:
$records = explode("\n",$stuff);
TO:
$rec = str_replace(":00:00:00 -0000", "", $stuff);
$records = explode("\n",$rec);
Second EDIT:
Change: (Change two places)
$result = implode("<br />",$records);
To:
$result = implode("<br />",str_replace(":00:00:00 -0000", "", $stuff));

Replacing redundant dates in DB query with symbol (MySQL/PHP)

I have a database query that displays a list of historic events in chronological order, like this:
(URL = MySite/Calendar/January_1)<br>
On this day in history...<br>
1968 - A volcano erupted.<br>
1968 - A country was invaded.<br>
1968 - Someone had a hit song.<br>
1970 - A famous person was born.
I'd like to know if there's a way to display a year just once, so the display looks like this:
1968 - A volcano erupted.<br>
• A country was invaded.<br>
• Someone had a hit song.<br>
1970 - A famous person was born.
Let's start with a database table (calendar_px) that lists the dates of various historic political events. The table has five fields -
1) N (a simple numerical key)
2) URL (values - such as May_1 - match page URL's)
3) Year (e.g. 1970, but the field type is INT, not Year, which only goes back to 1901)
4) Brief (some brief content)
5) Date (field type will be either date or datetime; I'm not actually using this field at the moment)
Here's what my code looks like (where $MyURL equals the page URL; e.g. January_1):
$stm = $pdo->prepare("SELECT Cal2.N, Cal2.URL, Cal2.Date, Cal2.Year, Cal2.Brief
FROM calendar_px Cal2
WHERE Cal2.URL = :MyURL
ORDER BY Cal2.Year");
$stm->execute(array(
'MyURL'=>$MyURL
));
while ($row = $stm->fetch())
{
$Year = $row['Year'];
$Brief[] = ''.$Year.' – '.$row['Brief'].'';
}
Then, I display a list of historic events like this...
echo join( $Brief, '<br>' );
I don't think it really changes anything, but I should mention that I have a similar set up on several websites; everything is the same except for the table names:
calendar_gw, calendar_gz, calendar_gs, calendar_px, calendar_sl
Accordingly, I've joined all five tables together with a UNION command. Here's a portion of the query:
$stm = $pdo->prepare("SELECT CGW.N, CGW.URL, CGW.Date, CGW.Year, CGW.Brief
FROM calendar_gw CGW
WHERE CGW.URL = :MyURL
UNION ALL
SELECT CGZ.N, CGZ.URL, CGZ.Date, CGZ.Year, CGZ.Brief
FROM calendar_gz CGZ
WHERE CGZ.URL = :MyURL
UNION ALL
SELECT CSL.N, CSL.URL, CSL.Date, CSL.Year, CSL.Brief
FROM calendar_sl CSL
WHERE CSL.URL = :MyURL
ORDER BY Year");
$stm->execute(array(
'MyURL'=>$MyURL
));
Anyway, my goal is the same; to replace redundant dates (years) with some sort of "dingbat" or symbol.
$prevYear = null;
while ($row = $stm->fetch())
{
$Year = $row['Year'];
if ($Year == $prevYear) {
$YearStr = '• ';
} else {
$YearStr = $Year . ' $#8211; ';
$prevYear = $Year;
}
$Brief[] = $YearStr.$row['Brief'];
}
P.S. You don't need to concatenate '' at each end of the string.
Looks like you need to group resultset before outputting:
$events = array();
while($row = $stm->fetch()){
$year = $row['Year']; // current year
if(!isset($events[$year]){ // if no such group
$events[$year] = array(); // create group
}
$events[$year][] = $row['Brief']; // add data to year group
}
// Output:
foreach($events as $year => $event){
echo $year, ':<br>'; // show year;
foreach($event as $data){
echo $data, '<br>'; // show row;
}
}
Also, you may change output to your model, easily:
foreach($events as $year => $event){
echo $year, ' • ', implode('<br>• ', $event);
}

Comparing missing numbers in an array. PHP

I got this script which looks up taken times in this table and then removes those times from these three arrays. The arrays are times 1-24.
The ultimate goal of this script is to compare all the missing times from these arrays and make one big array with only the available times.
The catch is it needs to check if a time is missing three times in a row. If it is, that time will not display in the final array.
For example:
<?php
include 'db-connect.php';
if (isset($_GET['month']) && isset($_GET['day']) && isset($_GET['year'])) {
$month = $_GET['month'];
$day = $_GET['day'];
$year = $_GET['year'];
//string together date
$date = $month."/".$day."/".$year;
//define the queries
$sql1 = mysql_query("SELECT start_time, server FROM classes WHERE date = '$date' AND server = '1'");
$sql2 = mysql_query("SELECT start_time, server FROM classes WHERE date = '$date' AND server = '2'");
$sql3 = mysql_query("SELECT start_time, server FROM classes WHERE date = '$date' AND server = '3'");
//define time lists for each server
$timelist1 = range(1, 24);
$timelist2 = range(1, 24);
$timelist3 = range(1, 24);
//unset the arrays with the taken times for server 1
while($query1 = mysql_fetch_array($sql1)) {
unset($timelist1[$query1['start_time'] - 1]);
}
//unset the arrays with the taken times for server 2
while($query2 = mysql_fetch_array($sql2)) {
unset($timelist2[$query2['start_time'] - 1]);
}
//unset the arrays with the taken times for server 3
while($query3 = mysql_fetch_array($sql3)) {
unset($timelist3[$query3['start_time'] - 1]);
}
//now see which times are missing three times in a row and make one final array of available times.
//code goes here...
}
?>
Instead of your current strategy you could just store the number of arrays each time is found in, like:
include 'db-connect.php';
if (isset($_GET['month']) && isset($_GET['day']) && isset($_GET['year'])) {
$month = $_GET['month'];
$day = $_GET['day'];
$year = $_GET['year'];
//string together date
$date = $month."/".$day."/".$year;
//define time list
$timelist = array_fill(1, 24, 0);
while($query1 = mysql_fetch_array($sql1)) {
$timelist[$query1['start_time']]++;
}
while($query2 = mysql_fetch_array($sql2)) {
$timelist[$query2['start_time']]++;
}
while($query3 = mysql_fetch_array($sql3)) {
$timelist[$query3['start_time']]++;
}
$timelist = array_keys(array_filter($timelist, 'equals3'));
function equals3($x){
return $x == 3;
}
Now $timelist is an array of times that were found in all three queries. If you want an array of times that were missing from at least one query use this instead of the last few lines:
$timelist = array_keys(array_filter($timelist, 'lessThan3'));
function lessThan3($x){
return $x < 3;
}
Edit for variable amount of servers.
// Here you can list the servers you want to include in the query
// In an array form so it can be filled easily
$servers = array(1,2,4,5);
$num_servers = count($servers);
// Convert servers into queryable format
$servers = '(\''.implode('\',\'', $servers).'\')';
$query = 'SELECT `start_time`, COUNT(*) as `count` FROM `classes`
WHERE `date` = \''.$date.'\' AND `server` IN '.$servers.'
GROUP BY `start_time`';
$result = mysql_query($query);
$timelist = array_fill(1, 24, 1);
while($row = mysql_fetch_row($result))
if($row[1] == $num_servers) // `start_time` is missing from at least one server
unset($timelist[$row[0]]);
$timelist = array_keys($timelist);
// Now $timelist is an array of times that are available on at least one server from the query
Please note that since your date variable comes from $_GET you should be very careful of MySQL Injection attacks. Someone could delete your whole database, or worse, if you don't have the right protection in place. Please read this: http://www.learnphponline.com/security/sql-injection-prevention-mysql-php

Categories