Jump to content

[SOLVED] Foreach Loop Problem? I am not sure...


Glen

Recommended Posts

Hi Everyone,

 

I am having problems with this php script.  I have a script that gets a list of villages from a mysql database and all the villages are stored in the one field and separated with a semi-colon.  When I export the village list depending on the group the user selects the villages are exploded and a launch time is found out.

 

///////////////////////////////////////
//New stage
///////////////////////////////////////

if($stage == 2)
{

//create form

echo '<form action="index.php" method="get">
<input type="hidden" name="page" value="plan_attack" />
<input type="hidden" name="stage" value="3" />
';
//get enemy coords
$enemycoords = $_GET['ec'];

//get arrival time
$arrivaltime = $_GET['arrivaltime'];

//get arrival date
$arrivaldate = $_GET['arrivaldate'];

$groupid = $_GET['groupid'];

//get unit

$unit = $_GET['unit'];

//Display target information
echo "Target: $enemycoords<br>
      Arrival: $arrivaldate $arrivaltime<br>";

//set the user session
$user = $_SESSION['username'];

//connect to database
include("connect_attackplanner.php");

//Select the group name form the database where the id = the drop down id
$query = "SELECT * FROM `" . $user . "_group` where id = '$groupid'";

$result = mysql_query($query) or die(mysql_error());


//declare the function that works out the time distance
function int2time($time)
  { 
   
    $h=floor($time);
    $m=floor(($time*60)%60);
    $s=floor(($time*60*60)%60);
    return sprintf("%02d:%02d:%02d",$h,$m,$s);
  
  }
  
  
  
  //set the varibales
while($row = mysql_fetch_array($result))
{
$name = $row['group_name'];
$villages = $row['villages'];

//explode the villages
 $villages1 = explode(";", $villages);
 echo '<table border = "1">
	<tr><th>Attack From</th><th>Unit</th><th>Distance Unit</th><th>Duration</th><th>Launch at</th><th>EnemyCoords</th></tr>'; 
}


      





 //find out the arrival time of each village in the group
     foreach($villages1 as $attackcoords)
 {


	echo "<tr><td>$attackcoords</td><td>$unit</td>";


    
   $ax = substr($attackcoords,0,3);
   $ay = substr($attackcoords,4,3);

   
   $ex = substr($enemycoords,0,3);
   $ey = substr($enemycoords,4,3);
   
   $distance = sqrt((($ex - $ax)*($ex - $ax)) + (($ey - $ay)*($ey - $ay)));
   
   
   
   $distanceunit = $unit * $distance;
   
   echo "<td>$distanceunit</td>";
   
   



        //convert date to timestamp
	$arrivaldate1 = strtotime($arrivaldate);

        //convert arrival time to timestamp
	$arrivaltime1 = strtotime($arrivaltime);

	//add them together to get arrival date timestamp
	$arrival = $arrivaltime1 + $arrivaldate1;


	//get duration timestamp
	$duration = int2time($distanceunit/60);
	$duartion1 = strtotime($duration);

	 echo "<td>$duration1</td>";

	//take duration  away from arrival
	$newtime = $arrival - $duration1;

	//display launchtime
	$finaltime = date("m/d/y H:i:s",$newtime);
	echo "<td>$finaltime</td><td>$enemycoords</td></tr>";

        
}



 echo "</table>";
 echo "</form>";
}

 

Problems with the script are:

1)So the first village in the array gives me the correct launch time but after that it seems to display the wrong launch time for the rest of the villages.

 

2)The launch times now display that the attacks should be launched in the year 1913 which is wrong as some villages are only like 100 hours apart not 100 years :P

 

3)$duration1 seems to be empty as nothing is displayed when I echo it out.  I think if this problem is fixed then problem #2 will be fixed aswell.

 

I don't know if I explained that well  :P

 

Anyway if you know what's up help would be very much appreciated

 

Many Thanks

 

-Glen

Link to comment
Share on other sites

Does this line of code...

 

//Select the group name form the database where the id = the drop down id
$query = "SELECT * FROM `" . $user . "_group` where id = '$groupid'";

... only select one row from the database? If it does you should consider using LIMIT 1, it might speed it up slightly. Also there is no need for the while loop.

 

//set the varibales
while($row = mysql_fetch_array($result)){
   $name = $row['group_name'];
   $villages = $row['villages'];
   
   //explode the villages
   $villages1 = explode(";", $villages);
   echo '<table border = "1"><tr><th>Attack From</th><th>Unit</th><th>Distance Unit</th><th>Duration</th><th>Launch at</th><th>EnemyCoords</th></tr>';
}

If only one item is fetched from the database there is no point with the while loop, remove the while and the brackets around it.

 

In order to make any more specific suggestions regarding the foreach loop, it would be very usefull to know what the contents of $attackcoords looks like.

Link to comment
Share on other sites

Hi

 

Can't see anything obvious. However I would wonder if the list of village coordinates might be seperated with a ; and a space.

 

Also, it is best not to use delimited fields. Best to split them onto a seperaet table with one row per delimited field.

 

All the best

 

Keith

Link to comment
Share on other sites

Does this line of code...

 

//Select the group name form the database where the id = the drop down id
$query = "SELECT * FROM `" . $user . "_group` where id = '$groupid'";

... only select one row from the database? If it does you should consider using LIMIT 1, it might speed it up slightly. Also there is no need for the while loop.

 

//set the varibales
while($row = mysql_fetch_array($result)){
   $name = $row['group_name'];
   $villages = $row['villages'];
   
   //explode the villages
   $villages1 = explode(";", $villages);
   echo '<table border = "1"><tr><th>Attack From</th><th>Unit</th><th>Distance Unit</th><th>Duration</th><th>Launch at</th><th>EnemyCoords</th></tr>';
}

If only one item is fetched from the database there is no point with the while loop, remove the while and the brackets around it.

 

In order to make any more specific suggestions regarding the foreach loop, it would be very usefull to know what the contents of $attackcoords looks like.

Hi cags,

 

Thanks for the reply.

 

Yeah it does only select one item so I removed the while loop, force of habit :D

 

The contents of $attackcoords is xxx|yyy.  So an example would be 123|453.

 

Hi

 

Can't see anything obvious. However I would wonder if the list of village coordinates might be seperated with a ; and a space.

 

Also, it is best not to use delimited fields. Best to split them onto a seperaet table with one row per delimited field.

 

All the best

 

Keith

 

Hi keith,

 

I changed the value in the database and it now does not contain a ; and a space, just a ;.  Though it never gave me the results I wanted. 

 

Having played about even more I have noticed that I the date I insert in the previous stage to carry on to this stage changes the launch time result dramatically.

 

I am inserting the time as hh/mm/ss and inserting the date as mm/dd/yy

 

Does that change anything?

 

Many Thanks

 

-Glen

 

Link to comment
Share on other sites

I think that could explain some of your problems. If you have...

 

//convert date to timestamp
$arrivaldate1 = strtotime($arrivaldate);
//convert arrival time to timestamp
$arrivaltime1 = strtotime($arrivaltime);

 

...and the 2 strings are in the format hh/mm/ss and mm/dd/yy, how is PHP supposed to determine that the first one is hour minute second and the second is month day year. For the time I'd suggest doing a str_replace("/", ":", $arrivaltime), to get it in the more 'standard' format'.

 

You may also have some issues with the date as mm/dd/yy as some versions of PHP seem to behave oddly with certain formats of year but I'm not certain on that one.

 

Edit: You can test it with the following, but judging by the order your date will be ok. You could also use mkdate instead of replacing the slashes with colons for the time.

 

$date = explode("/", $arrivaldate);
echo date("Y/m/d", mktime(0, 0, 0, $date[0], $date[1], $date[2]);
echo date("Y/m/d", strtotime("{$date[0]}/{$date[1]}/{$date[2]}"));

Link to comment
Share on other sites

I think that could explain some of your problems. If you have...

 

//convert date to timestamp
$arrivaldate1 = strtotime($arrivaldate);
//convert arrival time to timestamp
$arrivaltime1 = strtotime($arrivaltime);

 

...and the 2 strings are in the format hh/mm/ss and mm/dd/yy, how is PHP supposed to determine that the first one is hour minute second and the second is month day year. For the time I'd suggest doing a str_replace("/", ":", $arrivaltime), to get it in the more 'standard' format'.

 

You may also have some issues with the date as mm/dd/yy as some versions of PHP seem to behave oddly with certain formats of year but I'm not certain on that one.

 

Edit: You can test it with the following, but judging by the order your date will be ok. You could also use mkdate instead of replacing the slashes with colons for the time.

 

$date = explode("/", $arrivaldate);
echo date("Y/m/d", mktime(0, 0, 0, $date[0], $date[1], $date[2]);
echo date("Y/m/d", strtotime("{$date[0]}/{$date[1]}/{$date[2]}"));

 

Sorry the arrival time format is hh:mm:ss, my bad.

 

So would you recommend I use dd/mm/yy instead of mm/dd/yy?

 

Many Thanks

 

-Glen

Link to comment
Share on other sites

I would definately recommend using a method similar to this...

 

$date = explode("/", $arrivaldate);
echo date("Y/m/d", mktime(0, 0, 0, $date[0], $date[1], $date[2]);
echo date("Y/m/d", strtotime("{$date[0]}/{$date[1]}/{$date[2]}"));

 

... to test that you get the same result for the method your using and the mktime() method. Since you know for certain mktime will parse the time correctly.

Link to comment
Share on other sites

Hi

 

As you will want to combine the time and the date into something that you can manipulate, probably best to use something like mktime to format your date / time formats into a unix time stamp

 

$Ts = explode('/',"$arrivaldate/$arrivaltime");

$ArrivalTimeStamp = mktime($Ts[3],$Ts[4],$Ts[5],$Ts[0],$Ts[1],$Ts[2]);

 

Do the same for the other date times and then you can just subtract one from the other.

 

All the best

 

Keith

Link to comment
Share on other sites

Thanks keith, still no success yet.

 

Here is the current code...

if($stage == 2)
{

//create form

echo '<form action="index.php" method="get">
<input type="hidden" name="page" value="plan_attack" />
<input type="hidden" name="stage" value="3" />
';
//get enemy coords
$enemycoords = $_GET['ec'];

//get arrival time
$arrivaltime = $_GET['arrivaltime'];

//get arrival date
$arrivaldate = $_GET['arrivaldate'];

$groupid = $_GET['groupid'];

//get unit

$unit = $_GET['unit'];

//Display target information
echo "Target: $enemycoords<br>
      Arrival: $arrivaldate $arrivaltime<br>";

//set the user session
$user = $_SESSION['username'];

//connect to database
include("connect_attackplanner.php");

//Select the group name form the database where the id = the drop down id
$query = "SELECT * FROM `" . $user . "_group` where id = '$groupid'";

$result = mysql_query($query) or die(mysql_error());


//declare the function that works out the time distance
function int2time($time)
  { 
   
    $h=floor($time);
    $m=floor(($time*60)%60);
    $s=floor(($time*60*60)%60);
    return sprintf("%02d:%02d:%02d",$h,$m,$s);
  
  }
  
  
  
  //set the varibales
$row = mysql_fetch_array($result);

$name = $row['group_name'];
$villages = $row['villages'];

//explode the villages
 $villages1 = explode(";", $villages);
 echo '<table border = "1">
	<tr><th>Attack From</th><th>Unit</th><th>Distance Unit</th><th>Duration</th><th>Launch at</th><th>EnemyCoords</th></tr>'; 



      





 //find out the arrival time of each village in the group
     foreach($villages1 as $attackcoords)
 {


	echo "<tr><td>$attackcoords</td><td>$unit</td>";
    
   $ax = substr($attackcoords,0,3);
   $ay = substr($attackcoords,4,3);

   
   $ex = substr($enemycoords,0,3);
   $ey = substr($enemycoords,4,3);
   
   $distance = sqrt((($ex - $ax)*($ex - $ax)) + (($ey - $ay)*($ey - $ay)));
   
   
   
   $distanceunit = $unit * $distance;
   
   echo "<td>$distanceunit</td>";
   
   



    
	 $Ts = explode('/',"$arrivaldate/$arrivaltime");
         $arrival = mktime($Ts[3],$Ts[4],$Ts[5],$Ts[0],$Ts[1],$Ts[2]);


	//get duration timestamp
	$duration = int2time($distanceunit/60);

	$Ts1 = explode(":",$duration);
	$duration1 = mktime($Ts1[0],$Ts1[1],$Ts1[2]);

	 echo "<td>$duration</td>";

	//take duration  away from arrival
	$newtime = $arrival - $duration1;

	//display launchtime
	$finaltime = date("d/m/Y H:i:s",$newtime);
	echo "<td>$finaltime</td><td>$enemycoords</td></tr>";

        

        
}



 echo "</table>";
 echo "</form>";
}

 

Many Thanks

 

-Glen

Link to comment
Share on other sites

Hi

 

Quick hack around and something like this:-

 

if($stage == 2)
{

//create form

echo '<form action="index.php" method="get">
<input type="hidden" name="page" value="plan_attack" />
<input type="hidden" name="stage" value="3" />
';
//get enemy coords
$enemycoords = $_GET['ec'];

//get arrival time
$arrivaltime = $_GET['arrivaltime'];

//get arrival date
$arrivaldate = $_GET['arrivaldate'];

$groupid = $_GET['groupid'];

//get unit

$unit = $_GET['unit'];

//Display target information
echo "Target: $enemycoords<br>
Arrival: $arrivaldate $arrivaltime<br>";

$Ts = explode('/',"$arrivaldate/$arrivaltime");
$arrival = mktime($Ts[3],$Ts[4],$Ts[5],$Ts[0],$Ts[1],$Ts[2]);

//set the user session
$user = $_SESSION['username'];

//connect to database
include("connect_attackplanner.php");

//Select the group name form the database where the id = the drop down id
$query = "SELECT * FROM `" . $user . "_group` where id = '$groupid'";

$result = mysql_query($query) or die(mysql_error());

$ex = substr($enemycoords,0,3);
$ey = substr($enemycoords,4,3);

//set the varibales
$row = mysql_fetch_array($result);

$name = $row['group_name'];
$villages = $row['villages'];

//explode the villages
$villages1 = explode(";", $villages);
echo '<table border = "1">
<tr><th>Attack From</th><th>Unit</th><th>Distance Unit</th><th>Duration</th><th>Launch at</th><th>EnemyCoords</th></tr>'; 

//find out the arrival time of each village in the group
foreach($villages1 as $attackcoords)
{
	echo "<tr><td>$attackcoords</td><td>$unit</td>";

	$ax = substr($attackcoords,0,3);
	$ay = substr($attackcoords,4,3);

	$distance = sqrt((($ex - $ax)*($ex - $ax)) + (($ey - $ay)*($ey - $ay)));

	$distanceunit = $unit * $distance;

	echo "<td>$distanceunit</td>";

	echo "<td>$duration</td>";

	//take duration  away from arrival
	$newtime = $arrival - ($distanceunit*60*60);

	//display launchtime
	$finaltime = date("d/m/Y H:i:s",$newtime);
	echo "<td>$finaltime</td><td>$enemycoords</td></tr>";

}

echo "</table>";
echo "</form>";
}

 

I am not sure you need the function. However you need the time of the voyage in seconds. I have just assumed that $distanceunit is the time in decimal hours. However would need to know more of what $unit and $distance are, and exactly what you want to calculate and display.

 

All the best

 

Keith

Link to comment
Share on other sites

Hi

 

Quick hack around and something like this:-

 

if($stage == 2)
{

//create form

echo '<form action="index.php" method="get">
<input type="hidden" name="page" value="plan_attack" />
<input type="hidden" name="stage" value="3" />
';
//get enemy coords
$enemycoords = $_GET['ec'];

//get arrival time
$arrivaltime = $_GET['arrivaltime'];

//get arrival date
$arrivaldate = $_GET['arrivaldate'];

$groupid = $_GET['groupid'];

//get unit

$unit = $_GET['unit'];

//Display target information
echo "Target: $enemycoords<br>
Arrival: $arrivaldate $arrivaltime<br>";

$Ts = explode('/',"$arrivaldate/$arrivaltime");
$arrival = mktime($Ts[3],$Ts[4],$Ts[5],$Ts[0],$Ts[1],$Ts[2]);

//set the user session
$user = $_SESSION['username'];

//connect to database
include("connect_attackplanner.php");

//Select the group name form the database where the id = the drop down id
$query = "SELECT * FROM `" . $user . "_group` where id = '$groupid'";

$result = mysql_query($query) or die(mysql_error());

$ex = substr($enemycoords,0,3);
$ey = substr($enemycoords,4,3);

//set the varibales
$row = mysql_fetch_array($result);

$name = $row['group_name'];
$villages = $row['villages'];

//explode the villages
$villages1 = explode(";", $villages);
echo '<table border = "1">
<tr><th>Attack From</th><th>Unit</th><th>Distance Unit</th><th>Duration</th><th>Launch at</th><th>EnemyCoords</th></tr>'; 

//find out the arrival time of each village in the group
foreach($villages1 as $attackcoords)
{
	echo "<tr><td>$attackcoords</td><td>$unit</td>";

	$ax = substr($attackcoords,0,3);
	$ay = substr($attackcoords,4,3);

	$distance = sqrt((($ex - $ax)*($ex - $ax)) + (($ey - $ay)*($ey - $ay)));

	$distanceunit = $unit * $distance;

	echo "<td>$distanceunit</td>";

	echo "<td>$duration</td>";

	//take duration  away from arrival
	$newtime = $arrival - ($distanceunit*60*60);

	//display launchtime
	$finaltime = date("d/m/Y H:i:s",$newtime);
	echo "<td>$finaltime</td><td>$enemycoords</td></tr>";

}

echo "</table>";
echo "</form>";
}

 

I am not sure you need the function. However you need the time of the voyage in seconds. I have just assumed that $distanceunit is the time in decimal hours. However would need to know more of what $unit and $distance are, and exactly what you want to calculate and display.

 

All the best

 

Keith

 

Hi Keith,

 

$unit will be a range from 9 to 35 depending on what the user selects on the previous stage.

 

$distance was the distance between the two villages and is worked out using Pythagoras to give you a decimal value. 

 

So say the two villages were 4 fields apart(One from the array and the one selected as enemy coords) and the unit I select travels a 1 field every 9 mins. 

 

So $distanceunit would be 4 * 9 = 36mins.

 

Though most of the time it can end as a floating point(I am not sure that is the correct term).  An example would be 4.5632657 fields apart.

 

 

So Say I want to coordinate a strike and I set an arrival time 18/10/09 23:00:00 it would be 18/10/09 23:00:00 minus 36 mins = 18/10/09 22:24:00 and that's when I launch the attack so that it lands at that time.

 

So I want to find launch time from each village in the array to the enemy coord as to do in my head it would take me hours.

 

I use the function to display the duration in hh:mm:ss to the user.

 

Many Thanks

 

-Glen

Link to comment
Share on other sites

Hi

 

Think I almost got it then. Just got an extra *60 in there.

 

Change:-

 

$newtime = $arrival - ($distanceunit*60*60);

 

to

 

$newtime = $arrival - ($distanceunit*60);

 

All the best

 

Keith

 

Hi Keith,

 

That's it it seems to be working correctly now.  You're help has been very much appreciated.

 

Thanks again.

 

-Glen

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.