SQL or PHP mistake? Distance calculation - php

I have a problem with my file. I'm making Travian Clone script and we went really far. Now we decided to add artefacts into game.
Goal is to show closest artefacts to the current village we are in. The code is:
function getDistance($coorx1, $coory1, $coorx2, $coory2) {
$max = 2 * WORLD_MAX + 1;
$x1 = intval($coorx1);
$y1 = intval($coory1);
$x2 = intval($coorx2);
$y2 = intval($coory2);
$distanceX = min(abs($x2 - $x1), $max - abs($x2 - $x1));
$distanceY = min(abs($y2 - $y1), $max - abs($y2 - $y1));
$dist = sqrt(pow($distanceX, 2) + pow($distanceY, 2));
return round($dist, 1);
}
unset($reqlvl);
unset($effect);
$arts = mysql_query("SELECT * FROM ".TB_PREFIX."artefacts WHERE id > 0");
$rows = array();
while($row = mysql_fetch_array($arts)) {
$query = mysql_query('SELECT * FROM `' . TB_PREFIX . 'wdata` WHERE `id` = ' . $row['vref']);
$coor2 = mysql_fetch_assoc($query);
$wref = $village->wid;
$coor = $database->getCoor($wref);
$dist = getDistance($coor['x'], $coor['y'], $coor2['x'], $coor2['y']);
$rows[$dist] = $row;
}
ksort($rows, SORT_ASC);
foreach($rows as $row) {
echo '<tr>';
echo '<td class="icon"><img class="artefact_icon_'.$row['type'].'" src="img/x.gif" alt="" title=""></td>';
echo '<td class="nam">';
echo ''.$row['name'].' <span class="bon">'.$row['effect'].'</span>';
echo '<div class="info">';
if($row['size'] == 1){
$reqlvl = 10;
$effect = "village";
}elseif($row['size'] == 2 OR $row['size'] == 3){
$reqlvl = 20;
$effect = "account";
}
echo '<div class="info">Treasury <b>'.$reqlvl.'</b>, Effect <b>'.$effect.'</b>';
echo '</div></td><td class="pla">'.$database->getUserField($row['owner'],"username",0).'</td>';
echo '<td class="dist">'.getDistance($coor['x'], $coor['y'], $coor2['x'], $coor2['y']).'</td>';
echo '</tr>';
}
?>
but the code seems to be wrong because its showing all same distances. 14.8 to me. I know i maybe have bad explanation but u will probably understand what I need.

I can't help with your current code I'm afraid but you could try using the Haversine Formula instead:
// Where:
// $l1 ==> latitude1
// $o1 ==> longitude1
// $l2 ==> latitude2
// $o2 ==> longitude2
function haversine ($l1, $o1, $l2, $o2) {
$l1 = deg2rad ($l1);
$sinl1 = sin ($l1);
$l2 = deg2rad ($l2);
$o1 = deg2rad ($o1);
$o2 = deg2rad ($o2);
$distance = (7926 - 26 * $sinl1) * asin (min (1, 0.707106781186548 * sqrt ((1 - (sin ($l2) * $sinl1) - cos ($l1) * cos ($l2) * cos ($o2 - $o1)))));
return round($distance, 2);
}
Credit goes to this post on go4expert.com, I've used this function in the past and found it works very well.

Related

Php - getting the distance between multiple points using lon, lat and alt

So i want to load a gpx file and get all the cordinates and calculate the total distance traveled, but im stuck with this code:
<?php
$xml = simplexml_load_file("data/example.gpx");
echo $xml->metadata->author->name;
echo "</br>";
echo "</br>";
echo "</br>";
$lon1=0;
$lat1=0;
$lon2=0;
$lat2=0;
$alt1=0;
$alt2=0;
$dist=0;
$brr = count($xml->trk->trkseg);
$brf = 0;
for($i = 0; $i<$brr; $i++){
$br = count($xml->trk->trkseg[$i]->trkpt);
$brf= $brf + $br;
for($j = 0; $j<$br;$j++){
$lat2= (float) $xml->trk->trkseg[$i]->trkpt[$j]['lat'];
$lon2= (float) $xml->trk->trkseg[$i]->trkpt[$j]['lon'];
$alt2= (float) $xml->trk->trkseg[$i]->trkpt[$j]->ele;
$lon2 = $alt2 * cos($lat2) * sin($lon2);
$lat2 = $alt2 * sin($lat2);
$alt2 = $alt2 * cos($lat2) * cos($lon2);
if ($j==0){ //this is just for the first time because first points are not set
$lat1=$lat2;
$lon1=$lon2;
$alt1= $alt2;
}
$cdist = sqrt(pow(($lat2-$lat1),2) + pow(($lon2-$lon1),2) + pow(($alt2-$alt1),2));
$dist = $dist + $cdist;
$lat1=$lat2;
$lon1=$lon2;
$alt1=$alt2;
}
}
echo 'Distance = '.$dist;
echo '</br>';
echo 'number of coordinates = '.$brf;
?>
as result for distance i get the number 4592.6244157763 instead of 4.10km (~~4100), but coordinates are good, it goes through all coordinates. (also, the gpx file is from endomondo if it matters)
Fixed the code, in case anyone needs it, here it is:
<?php
$xml = simplexml_load_file("data/vladantd.gpx");
echo $xml->metadata->author->name;
echo "</br>";
echo "</br>";
echo "</br>";
$lon1=0;
$lat1=0;
$lon2=0;
$lat2=0;
$alt1=0;
$alt2=0;
$dist=0;
$brr = count($xml->trk->trkseg);
$brf = 0;
for($i = 0; $i<$brr; $i++){
$br = count($xml->trk->trkseg[$i]->trkpt);
$brf= $brf + $br;
for($j = 0; $j<$br;$j++){
if($j==0)
{
$j=1;
$g=1;
}
$lat2= (float) $xml->trk->trkseg[$i]->trkpt[$j]['lat'];
$lon2= (float) $xml->trk->trkseg[$i]->trkpt[$j]['lon'];
$alt2= (float) $xml->trk->trkseg[$i]->trkpt[$j]->ele;
$lon2 = $alt2 * cos($lat2) * sin($lon2);
$lat2 = $alt2 * sin($lat2);
$alt2 = $alt2 * cos($lat2) * cos($lon2);
if ($g==1){
$lat1=$lat2;
$lon1=$lon2;
$alt1= $alt2;
$j=0;
$g=0;
}
$cdist = sqrt(pow(($lat2-$lat1),2) + pow(($lon2-$lon1),2) + pow(($alt2-$alt1),2));
$dist = $dist + $cdist;
$lat1=$lat2;
$lon1=$lon2;
$alt1=$alt2;
}
}
echo 'Distance = '.$dist;
echo '</br>';
echo 'number of coordinates = '.$brf;
?>
okay, so the files that i use, every first trkpt in every trkseg doesnt have an altitude, so if j==0 then set j to 1, so it skips that first point (it sets points 1 time every few seconds so it shouldnt make a big difference (in my case) and at the same time i've set another variable g to 1, so that we can at the end of this current loop, return j back to 0 so the j++ increases it to 1 instead of skipping the point and increasing it to 2, rest should be clear, if you have any questions, just ask ^^
EDIT:
The code isnt working good. The longer the distance, the bigger the mistake it makes, for 8.1km it shows 9km, tested it out on a few gpx files and noticed. Sorry, if someone has a solution, would mean a lot!

Set color shade based on variable number with PHP

Ok, I don't even know where to start with this one! I'll try and explain what I want to achieve, and we'll go from there....
I have a list of dates each with an associated number, say from 20-100. What I want to do is to output the date in a shade which represents the associated number. So 20 would display in a light blue and 100 in a dark blue. My code so far looks like this...
dateArray = Array('2001-01-01'=>30, '2001-02-01'=>40, '2001-03-01'=>50, '2001-04-01'=>60, '2001-05-01'=>70, '2001-06-01'=>80, '2001-07-01'=>90, '2001-08-01'=>90, '2001-09-01'=>80, '2001-10-01'=>70, '2001-11-01'=>60, '2001-12-01'=>50)
$maxNum = max($dateArray);
$minNum = min($dateArray);
foreach($dateArray AS $date => $num){
$lightest = 'rgb(204,204,255)';
$darkest = 'rgb(0, 0, 179)';
///magic that converts $num into $shade goes here///
echo "<span style='color:$shade'>$date</span><br>"
}
Any ideas? Thanks
I would do something like that :
$dateArray = Array('2001-01-01'=>30, '2001-02-01'=>40, '2001-03-01'=>50, '2001-04-01'=>60, '2001-05-01'=>70, '2001-06-01'=>80, '2001-07-01'=>90, '2001-08-01'=>90, '2001-09-01'=>80, '2001-10-01'=>70, '2001-11-01'=>60, '2001-12-01'=>50)
// get max and min values
$maxNum = max($dateArray);
$minNum = min($dateArray);
// set rgb values for max and min
$lightest = array(204, 204, 255);
$darkest = array(0, 0, 179);
foreach($dateArray AS $date => $num)
{
// get a "delta" where the current num value is
$delta = ($num / $maxNum) - $minNum;
// get a pro-rata values thanks to $delta
$shadesNum = array(
$delta * ($lightest[0] - $darkest[0]) + $darkest[0],
$delta * ($lightest[1] - $darkest[1]) + $darkest[1],
$delta * ($lightest[2] - $darkest[2]) + $darkest[2]
);
echo "<span style='rgb(".implode(',', $shadesNum).")'>$date</span><br>";
}
Some languages have a "lerp" function - linear interpolation. Quite useful.
My suggestion:
for ($x1=20; $x1<=100; $x1+=10)
echo $x1 . ": " . getshade($x1) . "<br />\n";
function getshade($num) {
$rlight = 204;
$glight = 204;
$blight = 255;
$rdark = 0;
$gdark = 0;
$bdark = 179;
$lightnum = 20;
$darknum = 100;
$k01 = ($num-$lightnum)/($darknum-$lightnum); // 0 to 1
$rshade = ilerp($rlight, $rdark, $k01);
$gshade = ilerp($glight, $gdark, $k01);
$bshade = ilerp($blight, $bdark, $k01);
return "rgb($rshade,$gshade,$bshade)"; }
function lerp($start, $end, $k01) { // linear interpolation
return $k01*$end + (1.0-$k01)*$start; }
function ilerp($start, $end, $k01) { // integer lerp
return intval($k01*$end + (1.0-$k01)*$start); }
EDIT: Same thing but better:
$rgblight = [204,204,255];
$rgbdark = [0,0,179];
$numlight = 20;
$numdark = 100;
for ($x1=20; $x1<=100; $x1+=10)
echo $x1 . ": " . getshade2($x1, $numlight, $numdark, $rgblight, $rgbdark) . "<br />\n";
function getshade2($num, $numlight, $numdark, $rgblight, $rgbdark) {
$k01 = ($num-$numlight)/($numdark-$numlight);
for ($i1=0; $i1<3; $i1+=1)
$rgb[$i1] = ilerp($rgblight[$i1], $rgbdark[$i1], $k01);
return "rgb({$rgb[0]},{$rgb[1]},{$rgb[2]})"; }

MySQL always takes wrong ID in a loop

I have a problem with my while loop. Hard to explain but the count function always returns 1, also when it should return 0...
Here's my code:
$query = mysql_query("select SongID, Songtitel, artwork, duration, Upvote, SCID from tMusic order by Songtitel ASC") or die(mysql_error());
$activeUserID = $_SESSION["user_id"];
while ($temp = mysql_fetch_array($query)) {
if (strlen($temp['Songtitel']) >= 47) {
$ifToLong = "...";
} else {
$ifToLong = "";
}
$activeSongID = $temp['SongID'];
$fistquery = mysql_query("select * from tMusicFists where SongID = ".$activeSongID." and UserID = ".$activeUserID."") or die(mysql_error());
echo '<div class="songdiv" onclick="StreamStart('.$temp['SCID'].'); playTrack(); changeSongtitle('.$temp['Songtitel'].');">';
echo '<div class="songimgdiv"><img class="songimg" src="'.$temp['artwork'].'" alt=""></div>';
echo '<div class="songinfodiv">';
echo '<div class="songtitleinfodiv"><p class="songtitleinfo">'.$activeSongID.' '.$activeUserID.' '.count($fistquery).'</p></div>';
echo '<div class="songdurationdiv"><p class="durationcount">';
$input = $temp[duration];
$uSec = $input % 1000;
$input = floor($input / 1000);
$seconds = $input % 60;
$input = floor($input / 60);
$minutes = $input % 60;
$input = floor($input / 60);
echo $minutes.':'.$seconds;
echo '</p></div>';
if(count($fistquery) > 0) {
echo '<div class="songratingdiv"><img class="thumbupimg" src="../images/likebrofist.png" alt=""><p class="thumbupnumber">'.$temp['Upvote'].'</p></div>';
} else {
echo '<div class="songratingdiv"><img class="thumbupimg" src="../images/brofist.png" alt=""><p class="thumbupnumber">'.$temp['Upvote'].'</p></div>';
}
echo '</div>';
echo '</div>';
}
mysql_close();
I know i shouldn't use the mysql functions, but I must try it like that...
Thank you
$fistquery = mysql_query("select * from tMusicFists where SongID = ".$activeSongID." and UserID = ".$activeUserID."") or die(mysql_error());
count($fistquery);
Its not okay.... Try use mysql_num_rows($firstquery);
You need to use mysql_num_rows instead of count
Please use following script
$num_rows = mysql_num_rows($fistquery);
if($num_rows > 0) {
instead of
if(count($fistquery) > 0) {
mysql_query returns either a resource or some boolean value.
Anyway, count of resource or boolean is 1.
If you need number of rows - use mysql_num_rows.

PHP generate a random minus or plus percentage of a given value

I have a value, lets say its 1000.
Now I have to generate a random minus or plus percentage of 1000.
In particular I have to generate or a -20% of 1000 or a +20% of 1000 randomly.
I tried using rand() and abs() but with no success..
Is there a way in PHP to achieve the above?
A bit of basic mathematics
$number = 1000;
$below = -20;
$above = 20;
$random = mt_rand(
(integer) $number - ($number * (abs($below) / 100)),
(integer) $number + ($number * ($above / 100))
);
rand(0, 1) seems to work fine for me. Maybe you should make sure your percentage is in decimal format.
<?php
$val = 10000;
$pc = 0.2;
$result = $val * $pc;
if(rand(0, 1)) echo $result; else echo -$result;
if(rand(0, 1)) echo $result; else echo -$result;
if(rand(0, 1)) echo $result; else echo -$result;
if(rand(0, 1)) echo $result; else echo -$result;
if(rand(0, 1)) echo $result; else echo -$result;
?>
$number = 10000;
$percent = $number*0.20;
$result = (rand(0,$percent)*(rand(0,1)*2-1));
echo $result;
Or if you want some sort of running balance type thing....
function plusminus($bank){
$percent = $bank*0.20;
$random = (rand(0,$percent)*(rand(0,1)*2-1));
return $bank + $random;
}
$new = plusminus(10000);
$new = plusminus($new);
echo $new."<br>";
$new = plusminus($new);
echo $new."<br>";
$new = plusminus($new);
echo $new."<br>";
$new = plusminus($new);
echo $new."<br>";
$new = plusminus($new);
echo $new."<br>";
$new = plusminus($new);
I know this is really old now but stumbled across it looking for something similar where I needed a random sign (+ or -) so opted for a random boolean:
<?php $sign = (rand(0,1) == 1) ? '+' : '-'; ?>
Thanks to this this answer.
So I would opt for a solution like this:
<?php
// Alter these as needed
$number = 1000;
$percentage = 20;
// Calculate the change
$change_by = $number * ($percentage / 100);
// Set a boolean at random
$random_boolean = rand(0,1) == 1;
// Calculate the result where we are using plus if true or minus if false
$result = ($random_boolean) ? $number + $change_by : $number - $change_by;
// Will output either 1200 or 800 using these numbers as an example
echo $result;
?>

Welle's Wilder Accumulative Swing Index PHP calculation - Cannot return proper value

I am trying to get the accumulative swing index for an aapl stock chart. I am using this calculation for reference.
http://www.barchart.com/education/std_studies.php?what=int_swing&hideheader=true#study
This is what I have written so far. This should return 252.09 but I cannot get it to work.
$asi[0] = -78.75
$ht = 584; // High today
$lt = 574.25; // low
$ct = 584.00; // close
$ot = 578; // open
$hy = 574; // High yesterday
$ly = 565.61;
$cy = 569.05;
$oy = 571.67;
$k = max(($hy-$ct),($ly-$ct));
$abc = array(($ht-$cy), ($lt-$cy), ($ht-$lt));
$max = max($abc);
$r = 0;
if($max == $abc[0]){
$r = ($ht-$cy)-.5*($lt-$cy)+.25*($cy-$oy);
}elseif($max == $abc[1]){
$r = ($lt-$cy)-.5*($ht-$cy)+.25*($cy-$oy);
}elseif($max == $abc[2]){
$r = ($ht-$lt)+.25*($cy-$oy);
}else{
echo "Error in welles accumulative swing index";
exit;
}
$l = 3 //period;
$val = 50 * (($cy - $ct) + .5 *($cy - $oy) + .25*($ct-$ot)) / $r * $k / $l;
$asi[] = $asi[$i-1] + $val;
Any help would be greatly appreciated.
I have tried to implement this index newly symbol-by-symbol and have get different result (swing: -248.7032967033 ).
May be your control value wrong?
That is my code:
class Swing
{
public function calculate($high_price, $low_price, $close_price, $open_price, $t)
{
// (Ct-1 - Ct)
$summand0 = ($close_price[$t-1] - $close_price[$t]);
// 0.5(Ct-1 - Ot-1)
$summand1 = 0.5 * ($close_price[$t-1] - $open_price[$t-1]);
// 0.25(Ct - Ot)
$summand2 = 0.25 * ($close_price[$t] - $open_price[$t]);
$limit_move_default = 3.0;
$r = $this->get_r_value($high_price, $low_price, $close_price, $open_price, $t);
$k = $this->get_k_value($high_price, $low_price, $close_price, $t);
$factor0 = 50.0 * ($summand0 + $summand1 + $summand2) / $r;
$factor1 = $k / $limit_move_default;
// SWING = 50 * ((Ct-1 - Ct)+ 0.5(Ct-1 - Ot-1)+ 0.25(Ct - Ot))/ R * K / M
return $factor0 * $factor1;
}
public function get_k_value($high_price, $low_price, $close_price, $t)
{
// K= MAX(| Ht-Ct-1|, | Lt-Ct-1|)
return max(
abs($high_price[$t] - $close_price[$t-1]),
abs($low_price[$t] - $close_price[$t-1]));
}
public function get_r_value($high_price, $low_price, $close_price, $open_price, $t)
{
// A. |Ht-Ct-1|
$a = abs($high_price[$t] - $close_price[$t-1]);
// B. |Lt-Ct-1|
$b = abs($low_price[$t] - $close_price[$t-1]);
// C. |Ht-Lt|
$c = abs($high_price[$t] - $low_price[$t]);
$max_value = max($a, $b, $c);
$d = abs($high_price[$t] - $low_price[$t]);
if($a == $max_value)
// R= (| Ht-Ct-1|)-.5(| Lt-Ct-1|)+.25(| Ct-1-Ot-1|)
return $a - 0.5 * $b + 0.25 * $d;
if($b == $max_value)
// R= (| Lt-Ct-1|)-.5(| Ht-Ct-1|)+.25(| Ct-1-Ot-1|)
return $b - 0.5 * $a + 0.25 * $d;
if($c == $max_value)
// R= (| Ht-Lt|)+.25(| Ct-1-Ot-1|)
return $c + 0.25 * $d;
}
};
$swing = new Swing();
$high_price = array(574.0, 584.0);
$low_price = array(565.61, 574.25);
$close_price = array(569.05, 584.0);
$open_price = array(571.67, 578.0);
$value = $swing->calculate($high_price, $low_price, $close_price, $open_price, 1);
echo("swing: $value \n");
$d looks wrong.
It should be abs($close_price[$t-1] - $open_price[$t-1]);

Categories