DragonPrime - LoGD Resource Community
Welcome Guest
  • Good evening, Guest.
    Please log in, or register.
  • May 19, 2013, 10:19:25 PM
Home Forums News Links Downloads Login Register Advanced Search
* * *
DragonPrime Menu
Login
 
 
Resource Pages
IRC Channels
Search

Pages: [1]   Go Down
  Print  
Author Topic: Endless loop  (Read 455 times)
0 Members and 1 Guest are viewing this topic.
Anharat
Captain of the Guard
***
Offline Offline

Posts: 191


View Profile WWW
« on: June 20, 2011, 10:49:40 AM »

Hey,

I'm currently working on a tournament module, in which a player battles against an other over rounds.
The contest information is saved in a array. Due the contest might be rather long I want "older" information not to be shown, so players dont have to scroll down so far, but I also dont want so completely remove this infos because I want to display them in a hidden field which can be expandet if players want to check older informations.

So I wrote this function, but I'm running into an endless loop while removeing the old date, writeing it into an other array.
Function is part of an class!

Code:
<?php
protected $output = array();
protected 
$oldoutput = array();

public function 
update_output($string$id=false)
{
static $keep 10// lines to keep

$i count($this->output);
$j $i $keep;

if($i $keep)
{
while($i $j || $this->output[$i][1] != "`2`bNext Round:`b`0`n")
$i--;

for($k 0$k $i$k++) // Here i'm runnin into an endless loop
{
$this->oldoutput[] = $this->output[$k];
unset($this->output[$k]);
}

$newarray = array();
foreach($this->output AS $i => $v)
$newarray[] = $v;
$this->output $newarray;
}

if($id === false)
$this->output[] = array("all",$string);
else
$this->output[] = array($id$string);
}

So a little explenation. Within the while loop I'm first going to the point of the lines I wish to keep (10 atm) then it checks for the next string "next round" because I dont want the rounds be cut in halfes... would only look bad and confusing. Like batteling, allways having new rounds after erveryones action. If the right amount of lines to keep is found then all values before those lines should be removed and be stored in an other array. At the end a new line is added, but this works well enough.
The strings are saved in a extra array with an ID as first param for infos that should only be displayed to one player.

I'm not sure what I'm doing wrong. Tested some different modifications but allays keep running into "Fatal error: Maximum execution time of 90 seconds exceeded in...\LotgD\lib\settings.php on line 55" which seems like the result of an endless loop to me.

Hope someone can enlighten me about this, due I'm kinda confused.

~ Anharat
« Last Edit: June 20, 2011, 11:21:07 AM by Anharat » Logged

In a World of Compromise, we don't!
Boris735
Mod God
*****
Offline Offline

Posts: 532


View Profile
« Reply #1 on: June 20, 2011, 05:26:56 PM »

I would suggest that you provide some sample data for the output array that this is exhibiting the bad behaviour on.  The while loop, for instance, could be infinitely looping if the first item in the array isn't the sentinel.  (I know you said this was not where it was happening, but still worth ruling out.)

EDITED to add: For instance, the sentinel being used is "Next Round"... which may well not be present for the first round.

A variant to try:

Code:
protected $output = array();
protected $oldoutput = array();

public function update_output($string, $id="all")
{
  static $keep = 10; // lines to keep
  static $sentinel = "`2`bNext Round:`b`0`n";

  $olen = count($this->output);
  if ($olen > $keep)
  {
    $splitpos = $olen - $keep;
    while ($splitpos >= 0 && $this->output[$splitpos][1] != $sentinel)
      --$splitpos;

    if ($splitpos < 0)
    {
      // add error reporting here to taste
      debug("Sentinel missing on output array, or of unexpected format");
      $splitpos = 0;
    }

    $this->oldoutput = array_slice($this->output, 0, $splitpos);
    $this->output = array_slice($this->output, $splitpos, $olen - $splitpos);
  }

  $this->output[] = array($id, $string);
}
« Last Edit: June 20, 2011, 05:29:47 PM by Boris735 » Logged
Anharat
Captain of the Guard
***
Offline Offline

Posts: 191


View Profile WWW
« Reply #2 on: June 21, 2011, 01:39:58 AM »

The output array could look like this. There might be more than two players acting and more information be shown thats why static numbers would not work.

Code:
array(4) {
  '0' = 'array(2) {
    '0' = 'all'
    '1' = 'Round beginns:'
  }'
  '1' = 'array(2) {
    '0' = 'all'
    '1' = 'Player 1 does this action.'
  }'
  '2' = 'array(2) {
    '0' = 'all'
    '1' = 'Player 2 does that action'
  }'
  '3' = 'array(2) {
    '0' = 'all'
    '1' = 'Next Round:'
  }'
}

I did a little testing on your function. Handling the output like this works very well, but the oldoutput is overwritten all the time so old data isn't saved. Did a little change to the function, appending values to the oldoutput, seems to work fine now.

Code:
<?php
public function update_output($string$id "all")
{
static $keep 10// lines to keep
static $sentinel "`2`bNext Round:`b`0`n";

$this->output[] = array($id$string);
//debug($this->output);

$olen count($this->output);
if ($olen $keep)
{
$splitpos $olen $keep;
while ($splitpos >= && $this->output[$splitpos][1] != $sentinel)
$splitpos--;

if ($splitpos 0)
{
// add error reporting here to taste
debug("Sentinel missing on output array, or of unexpected format");
$splitpos 0;
}

$this->oldoutput array_merge($this->oldoutputarray_slice($this->output0$splitpos));
$this->output array_slice($this->output$splitpos$olen $splitpos);
}
}

Thanks a lot for your help, would probaly been sittin' on the for a quite a while to only finding a worse solution. ^^
Logged

In a World of Compromise, we don't!
Boris735
Mod God
*****
Offline Offline

Posts: 532


View Profile
« Reply #3 on: June 21, 2011, 03:14:16 AM »

Ah, apologies, I'd overlooked that the old output was always to be concatenated to.  Careless of me.

Glad that this is working for you, although I'm still curious as to the cause of the original issue, which is why I asked (or intended to ask) about actual data that showed the infinite loop, not a mock-up of something similar.  As far as I can see, the only plausible infinite loop location is the one I mentioned before, when the sentinel is not present at the start.

(Actually, I see that your sample demonstrates this... if $keep were as little as 2, an infinite loop would arise.)

A modification that handles the need for more than one sentinel (adjust the first round message as appropriate, of course):

Code:
public function update_output($string, $id = "all")
{
static $keep = 10; // lines to keep
static $sentinels = array(
"`2`bFirst Round:`b`0`b" => 1,
"`2`bNext Round:`b`0`n" => 1,
);

$this->output[] = array($id, $string);
//debug($this->output);

$olen = count($this->output);
if ($olen > $keep)
{
$splitpos = $olen - $keep;
while ($splitpos >= 0 && !array_key_exists($this->output[$splitpos][1], $sentinels))
$splitpos--;

if ($splitpos < 0)
{
// add error reporting here to taste
debug("Sentinel missing on output array, or of unexpected format");
$splitpos = 0;
}

$this->oldoutput = array_merge($this->oldoutput, array_slice($this->output, 0, $splitpos));
$this->output = array_slice($this->output, $splitpos, $olen - $splitpos);
}
}
Logged
Anharat
Captain of the Guard
***
Offline Offline

Posts: 191


View Profile WWW
« Reply #4 on: June 21, 2011, 04:20:34 AM »

Glad that this is working for you, although I'm still curious as to the cause of the original issue, which is why I asked (or intended to ask) about actual data that showed the infinite loop, not a mock-up of something similar.  As far as I can see, the only plausible infinite loop location is the one I mentioned before, when the sentinel is not present at the start.

(Actually, I see that your sample demonstrates this... if $keep were as little as 2, an infinite loop would arise.)
Yeah, seems like the right reason. Although this confuses me because it worked with out the forloop serveral times. Well, good enough now, I guess. ^^
I didn't really get the data because I was running into an fatal error and I didn't checked the code with a debugger or something likewise. Bad habits don't change, huh?

New code is implemented and doesn't give any trouble so far.  Smiley

Thanks!!
« Last Edit: June 21, 2011, 04:26:32 AM by Anharat » Logged

In a World of Compromise, we don't!
Pages: [1]   Go Up
  Print  
 
Jump to:  


*
DragonPrime Notices
Please take the time to read the FAQ and browse the DragonPedia

Support Us
$100 raised this year
Your help is greatly appreciated!
Who's Online
25 Guests, 0 Users
DragonPrime LoGD
Recent Topics
Home Forums News Links Downloads Login Register Advanced Search