Ghost Players

garrensilverwing

New Member
Messages
148
Reaction score
0
Points
0
This guy and I are creating a ranking system for this game we play. The game automatically generates game reports and posts them on a webserver: server.war2.ru/reports. The guy wrote a short php function that parses the game reports and then separates important information out, including winner's name, loser's name, etc... Now in some cases the function will parse a game and give us either a blank winner, or a blank loser. We have no idea what is causing this and was hoping you could help us out a little. Here is a link to a game report that creates a ghost player: http://server.war2.ru/reports/gr_20091201223149_025853, in this case the player should be vanwilder but it is coming as blank. If anyone has an idea of how to fix this I will give them rep and whatever else I can! Here is the function:

Code:
  <?php
     function insertLadderGame($GameID, $map, $Winner, $Loser)
     {
        $wresult = mysql_query("select * from standings where Player = '$Winner'");
        $lresult = mysql_query("select * from standings where Player = '$Loser'");
        if (mysql_num_rows($wresult) == 0 || mysql_num_rows($lresult) == 0)
        {
             if (mysql_num_rows($wresult) == 0)
             {
                $result = mysql_query("SELECT * FROM standings order by Rank desc limit 1") or die(mysql_error());
                while($row = mysql_fetch_array($result)){$highestRank = $row['Rank'];}
                $WOldRank = $WNewRank = $highestRank + 1;
                mysql_query("INSERT INTO standings (Player,Rank,Wins,Losses,HighRank,Streak)                VALUES('$Winner','$WNewRank','1','0','$WNewRank','1');") or die(mysql_error());
             }
             else
             {
                $result = mysql_query("SELECT * FROM standings where Player = '$Winner'") or die(mysql_error());
                while($row = mysql_fetch_array($result))
                {$WOldRank = $WNewRank = $row['Rank']; $Wins = $row['Wins']; $wStreak = $row['Streak'];}
                if ($wStreak > 0) $wStreak++;
                else $wStreak = 1;
                mysql_query("UPDate standings SET Wins='$Wins+1', Streak='$wStreak' where Player = '$Winner'") or die(mysql_error());
             }
             if (mysql_num_rows($lresult) == 0)
             {
                $result = mysql_query("SELECT * FROM standings order by Rank desc limit 1") or die(mysql_error());
                while($row = mysql_fetch_array($result))
                {$highestRank = $row['Rank'];}
                $LOldRank = $LNewRank = $highestRank + 1;
                mysql_query("INSERT INTO standings (Player,Rank,Wins,Losses,HighRank,Streak)
                VALUES('$Loser','$LNewRank','0','1','$LNewRank','-1');") or die(mysql_error());
             }
             else
             {
                $result = mysql_query("SELECT * FROM standings where Player = '$Winner'") or die(mysql_error());
                while($row = mysql_fetch_array($result))
                {$LOldRank = $LNewRank = $row['Rank'];$Losses = $row['Losses'];$lStreak = $row['Streak'];}
                if ($lStreak < 0) $lStreak--;
                else $lStreak = -1;
                mysql_query("UPDate standings SET Losses='$Losses+1', Streak='$lStreak' where Player = '$Loser'") or die(mysql_error());
             }
             $DateT = substr($GameID, 4, 14);
             mysql_query("INSERT INTO checkedgames (GameID,Winner,Loser,WOldRank,WNewRank,LOldRank,LNewRank,Map,DateT)
             VALUES('$GameID', '$Winner','$Loser','$WOldRank','$WNewRank','$LOldRank','$LNewRank','$map','$DateT' );") or die(mysql_error());
             return 0;
        }
// If neither player is new
        $result = mysql_query("SELECT * FROM standings where Player='$Winner'") or die(mysql_error());
        while($row = mysql_fetch_array($result))
        {$highrank = $row['HighRank'];$WOldRank = $row['rank'];$Wins = $row['Wins'];$WStreak = $row['Streak'];$WSeries = $row['series'];}
        $Wins++;
        if ($wstreak > 0) $wstreak++;
        else $wstreak = 1;
        $result = mysql_query("SELECT * FROM standings where Player='$Loser'") or die(mysql_error());
        while($row = mysql_fetch_array($result))
        {$LOldrank = $row['Rank'];$Losses = $row['Losses'];$LStreak = $row['Streak'];}
        $Losses++;
        if ($LStreak < 0) $LStreak--;
        else $LStreak = -1;
        if ($LOldRank + $WOldRank == 3) $WSeries++;
        if ($WSeries > 0)
        {
             mysql_query("UPDATE standings SET series='$WSeries' where Player = '$Winner'") or die(mysql_error());
             if ($WSeries == 3)
             {$counter = 3; while($counter > 2 && $counter < 11) {$newrank = $counter-1; mysql_query("UPDATE standings SET rank ='$newrank' where Rank = '$counter'"); $counter = $counter+1;}
                  mysql_query("UPDATE standings SET series='0', rank='1' where Player = '$Winner'") or die(mysql_error());
                  mysql_query("UPDATE standings SET series='0', rank='10' where Player = '$Loser'") or die(mysql_error());

             }
        }
        if ($WOldRank > $LOldRank && $WSeries == 0)
        {
             $WNewRank = ($WOldRank + $LOldRank)/2;
             $WNewRank = intval($WNewRank);
             $n = $WOldRank-1;
             if ($WNewRank == 2)
             {
                  mysql_query("UPDATE standings SET series='0', rank='2' where player = '$Loser'") or die(mysql_error());
                  $result = mysql_query("SELECT * FROM standings where rank = '1'") or die(mysql_error());
                  while($row = mysql_fetch_array($result)) $TopPlayer = $row['Player'];
                  mysql_query("UPDATE standings SET series='0' where Player = '$TopPlayer'") or die(mysql_error());
             }
             
             while ($n >= $WNewRank)
             {
                  $result = mysql_query("SELECT * FROM standings where rank = '$n'") or die(mysql_error());
                  while($row = mysql_fetch_array($result)) $passedPlayer = $row['player'];
                  $m = $n+1;
                  mysql_query("UPDATE standings SET rank='$m' where player = '$passedPlayer'") or die(mysql_error());
                  $n--;
             }
        }
        else $wnewrank = $woldrank;
        if ($wnewrank < $highrank) $highrank = $wnewrank;
        if ($wnewrank == $loldrank) $lnewrank = $loldrank + 1;
        else $lnewrank = $loldrank;
        mysql_query("UPDATE standings SET rank='$wnewrank', wins='$wins', streak='$wstreak', highrank='$highrank' where player = '$winner'");
        mysql_query("UPDATE standings SET losses='$losses', streak='$lstreak' where player = '$loser'");
        mysql_query("INSERT INTO checkedgames (gameID,loser,winner,woldrank,wnewrank,loldrank,lnewrank,map,datet)
        VALUES('$gameID', '$loser','$winner','$woldrank','$wnewrank','$loldrank','$lnewrank','$map','now()' );")
        or die(mysql_error());
        return 0;
     }

     function insertGameID($GameID)
     {
        mysql_query("INSERT INTO checkedgames (GameID,Loser,Winner,WOldRank,WNewRank,LOldRank,LNewRank,Map)
        VALUES('$GameID', 'none','none','none','none','none','none','none');") or die(mysql_error());
     }

     function  parseGameInfo($GameID)
     {
        set_time_limit(8000);
        $war2gameinfo = file('http://server.war2.ru/reports/'.$GameID);
        $war2gameinfotxt = implode('',$war2gameinfo);

        if (preg_match('/mapauth=\"Self-Made\"/', $war2gameinfotxt) == 0 && preg_match('/DRAW/', $war2gameinfotxt) == 0
        && preg_match('/DISCONNECT/', $war2gameinfotxt) == 0)
        {
             if (preg_match('/  LOSS/', $war2gameinfotxt) == 0)
             {
                  return 0;
             }
             if (preg_match('/  WIN/', $war2gameinfotxt) == 0)
             {
                  return 0;
             }
             $startHere = strstr($war2gameinfotxt,'joins=');
             $line = explode("\n", $startHere);
             $joinCount = substr($startHere, 6, 1);
             $englishCount = preg_match_all('/ and played for/', $startHere, $matches);
             if ($englishCount < $joinCount)
             {          
                  return 0;
             }
             $watcherCount = preg_match_all('/ 1 for Units/', $startHere, $matches);
             $PlayerCount = $joinCount - $watcherCount;
             if ($PlayerCount == 2)
             {
                   preg_match('/mapfile=\".+\.pud\"/', $war2gameinfotxt, $mapmatch);
                   $map = substr($mapmatch[0], 9, -5);
                   $throwAway = preg_match_all('/\d+ for Units/', $startHere, $matches);
                  /* While loop: creates a variable Player1 first time through, Player2 second time through.
                     Sets Player1[0] to the first Player's name, [1] to the result, [2] to his units.
                     Sets Player2[0] to the second Player's name, etc.
                     If Player's units are more than 1, and he lost or disconnected, his name is set to $Loser.
                     If Player's units are more than 1, and he won, his name is set to $Winner.
                  */
                   $n = 0;
                    while ($n < $PlayerCount)
                    {${'Player'.($n+1)} = preg_split("/\s+/", $line[3+$n]);${'Player'.($n+1)}[2] = $matches[0][$n]; if (${'Player'.($n+1)}[2] > 1 && ${'Player'.($n+1)}[1] == 'LOSS') $Loser = ${'Player'.($n+1)}[0]; if (${'Player'.($n+1)}[2] > 1 && ${'Player'.($n+1)}[1] == 'WIN')
                          $Winner = ${'Player'.($n+1)}[0];
                        $n++;
                    }
                }

             else
             {
                  return 0;
             }

        }
        else
        {
            return 0;
        }
        if($Winner == "" OR $Loser == ""){
            echo "<li style=\"color: red\">$GameID</li>";
        }
        else {
        insertLadderGame($GameID, $map, $Winner, $Loser);
        }
        return 0;
    }
?>
 

misson

Community Paragon
Community Support
Messages
2,572
Reaction score
72
Points
48
Here is a link to a game report that creates a ghost player: http://server.war2.ru/reports/gr_20091201223149_025853, in this case the player should be vanwilder but it is coming as blank.
On that page, there is no "vanwilder". There's an "Equinox" who is listed with a loss and "BiBiFox[iS]" and "VaRioLa-" with wins--are you referring to one of them? If so, which one?

In some places in the code, names used mixed case. In others, the same names are lower case. You should always write code that will work whether the language is case sensitive or insensitive. Otherwise you'll find yourself doing the wrong thing at some point and introducing a bug. I see it happen.

Much of the code, especially in insertLadderGame, could be clarified by refactoring it into other functions, such as insertWinner(...), updateLoser(...) &c.

PHP:
  <?php
function insertLadderGame($GameID, $map, $Winner, $Loser) {
   $wresult = mysql_query("select * from standings where Player = '$Winner'");
   $lresult = mysql_query("select * from standings where Player = '$Loser'");
"SELECT *" is wasteful and causes more work should you change the table schema. Better to fetch only the columns you care about.

PHP:
   if (mysql_num_rows($wresult) == 0 || mysql_num_rows($lresult) == 0)
   {
        if (mysql_num_rows($wresult) == 0) {
           $result = mysql_query("SELECT * FROM standings order by Rank desc limit 1") or die(mysql_error());
           while($row = mysql_fetch_array($result)){$highestRank = $row['Rank'];}
$result will have at most one row; no need for a while loop. This applies in a couple places.

Don't use "or die", throw an exception. I'll keep saying it until people listen.

PHP:
        } else {
           $result = mysql_query("SELECT * FROM standings where Player = '$Winner'") or die(mysql_error());
You just ran this query. It's still in $wresult.

PHP:
           while($row = mysql_fetch_array($result))
           {$WOldRank = $WNewRank = $row['Rank']; $Wins = $row['Wins']; $wStreak = $row['Streak'];}
Assuming there should be at most one row in `standings` for each player, there's no need for a while loop. Even if there were more than one, the loop would be the wrong thing to do.

PHP:
           if ($wStreak > 0) $wStreak++;
           else $wStreak = 1;
           mysql_query("UPDate standings SET Wins='$Wins+1', Streak='$wStreak' where Player = '$Winner'") or die(mysql_error());
"'$Wins+1'" won't perform addition. Either remove the single quotes or perform addition in PHP. The same thing happens later in the loser update branch.

PHP:
        } else {
           $result = mysql_query("SELECT * FROM standings where Player = '$Winner'") or die(mysql_error());
Here, you're updating the loser, but fetching the standings for the winner. Also, the result of the same query is in $lresult.


Instead of the code above, you could create a few functions and have:
PHP:
class DBException extends RuntimeException {}

function insertNewPlayer($player, $win) {
    $result = mysql_query("SELECT Rank FROM standings ORDER BY Rank DESC LIMIT 1") 
        or die(mysql_error());
    $row = mysql_fetch_array($result);
    ++$row['Rank'];
    $standing = array('oldRank' => $row['Rank'], 'newRank' => $row['Rank'], 'Player' => $player);
    if ($win) {
        $standing['Streak'] = $standing['Wins'] = 1;
        $standing['Losses'] = 0;
    } else {
        $standing['Streak'] = -1;
        $standing['Wins'] = 0;
        $standing['Losses'] = 1;
    }
    
    if (! mysql_query("INSERT INTO standings (Player,Rank,Wins,Losses,HighRank,Streak)
                 VALUES('$player','$standing[newRank]',$standing[Wins],$standing[Losses],'$standing[newRank]','$standing[Streak]');")) 
    {
        throw new DBException(mysql_error(), mysql_errno());
    }
    return $standing;
}

function insertWinner($player) {
    return insertNewPlayer($player, True);
}
function insertLoser($player) {
    return insertNewPlayer($player, False);
}

function updateWinner($player, $result) {
    $standing = mysql_fetch_array($result);
    ++$standing['Wins'];
    if ($standing['Streak'] > 0) ++$standing['Streak'];
    else $standing['Streak'] = 1;
    if (! mysql_query("UPDATE standings SET Wins='$standing[Wins]', Streak='$standing[Streak]' WHERE Player = '$player'")) {
        throw new DBException(mysql_error(), mysql_errno());
    }
    $standing['oldRank'] = $standing['newRank'] = $standing['Rank'];
    return $standing;
}
function updateLoser($player, $result) {
    $standing = mysql_fetch_array($result);
    ++$standing['Losses'];
    if ($standing['Streak'] < 0) --$standing['Streak'];
    else $standing['Streak'] = -1;
    if (!mysql_query("UPDate standings SET Losses='$standing[Losses]', Streak='$standing[Streak]' WHERE Player = '$player'")) {
        throw new DBException(mysql_error(), mysql_errno());
    }
    $standing['oldRank'] = $standing['newRank'] = $standing['Rank'];
    return $standing;
}

function insertLadderGame($GameID, $map, $Winner, $Loser) {
    $wresult = mysql_query("select Wins, Streak, Rank, HighRank, Series from standings where Player = '$Winner'");
    $lresult = mysql_query("select Losses, Streak, Rank from standings where Player = '$Loser'");
    if (mysql_num_rows($wresult) == 0 || mysql_num_rows($lresult) == 0) {
        if (mysql_num_rows($wresult) == 0) {
            // winner is not in standings, unknown about loser
            $winnersStanding = insertWinner($Winner);
        } else {
            $winnersStanding = updateWinner($Winner, $wresult);
        }
        if (mysql_num_rows($lresult) == 0) {
            $losersStanding = insertLoser($Loser);
        } else {
            $losersStanding = updateLoser($Loser, $lresult);
        }
        $DateT = substr($GameID, 4, 14);
        mysql_query("INSERT INTO checkedgames (GameID,Winner,Loser,WOldRank,WNewRank,LOldRank,LNewRank,Map,DateT)
             VALUES('$GameID', '$Winner','$Loser','$winnersStanding[oldRank]','$winnersStanding[newRank]','$losersStanding[oldRank]','$losersStanding[newRank]','$map','$DateT' );") 
            or throw new DBException(mysql_error(), mysql_errno());
        return 0;
    }
    ....

Back to the original code.
PHP:
// If neither player is new
        $result = mysql_query("SELECT * FROM standings where Player='$Winner'") or die(mysql_error());
        while($row = mysql_fetch_array($result))
        ...
        $result = mysql_query("SELECT * FROM standings where Player='$Loser'") or die(mysql_error());
        while($row = mysql_fetch_array($result))
Again, unnecessary queries, columns and loops.

PHP:
             if ($WSeries == 3)
             {$counter = 3; while($counter > 2 && $counter < 11) {$newrank = $counter-1; mysql_query("UPDATE standings SET rank ='$newrank' where Rank = '$counter'"); $counter = $counter+1;}
This can be done in a single query:
Code:
UPDATE standings SET Rank=Rank-1 WHERE Rank BETWEEN 3 AND 10
If it couldn't, a for loop would better match the intent. Also, are you sure that's the correct thing to do?

PHP:
        if ($WOldRank > $LOldRank && $WSeries == 0)
        {
             $WNewRank = ($WOldRank + $LOldRank)/2;
             $WNewRank = intval($WNewRank);
You can combine the last two lines into "$WNewRank = (int)(($WOldRank + $LOldRank)/2)".

PHP:
             $n = $WOldRank-1;
             if ($WNewRank == 2)
             {
                  mysql_query("UPDATE standings SET series='0', rank='2' where player = '$Loser'") or die(mysql_error());
                  $result = mysql_query("SELECT * FROM standings where rank = '1'") or die(mysql_error());
                  while($row = mysql_fetch_array($result)) $TopPlayer = $row['Player'];
                  mysql_query("UPDATE standings SET series='0' where Player = '$TopPlayer'") or die(mysql_error());
             }
You can combine the last two queries into:
Code:
UPDATE standings SET series='0' WHERE Rank=1

PHP:
             while ($n >= $WNewRank) {
                  $result = mysql_query("SELECT * FROM standings where rank = '$n'") or die(mysql_error());
                  while($row = mysql_fetch_array($result)) $passedPlayer = $row['player'];
                  $m = $n+1;
                  mysql_query("UPDATE standings SET rank='$m' where player = '$passedPlayer'") or die(mysql_error());
                  $n--;
             }
Equivalent single query:
Code:
UPDATE standings SET Rank=Rank+1 WHERE Rank BETWEEN $WNewRank AND $WOldRank-1

More to follow.
 
Last edited:

misson

Community Paragon
Community Support
Messages
2,572
Reaction score
72
Points
48
Whoops... forgot about this for a bit.

PHP:
function  parseGameInfo($GameID) {
   set_time_limit(8000);
   $war2gameinfo = file('http://server.war2.ru/reports/'.$GameID);
   $war2gameinfotxt = implode('',$war2gameinfo);
Use file_get_contents rather than file+implode.

PHP:
   if (preg_match('/mapauth=\"Self-Made\"/', $war2gameinfotxt) == 0 && preg_match('/DRAW/', $war2gameinfotxt) == 0
   && preg_match('/DISCONNECT/', $war2gameinfotxt) == 0)
   {
        if (preg_match('/  LOSS/', $war2gameinfotxt) == 0) {
             return 0;
        }
        if (preg_match('/  WIN/', $war2gameinfotxt) == 0) {
             return 0;
        }
"\s" is safer than a plain space character because "\s" will also match tabs.

PHP:
        $startHere = strstr($war2gameinfotxt,'joins=');
        $line = explode("\n", $startHere);
Since you never go through most of the lines, this is wasteful. Since you only seem to be using it to look for "LOSS" and "WIN", I'd use a regexp.

PHP:
            preg_match('/mapfile=\".+\.pud\"/', $war2gameinfotxt, $mapmatch);
            $map = substr($mapmatch[0], 9, -5);
No need for the call to substr, just use grouping:
PHP:
            preg_match('/mapfile=\"(.+)\.pud\"/', $war2gameinfotxt, $mapmatch);
            $map = $mapmatch[1];
PHP:
            $throwAway = preg_match_all('/\d+ for Units/', $startHere, $matches);
            $n = 0;
            while ($n < $PlayerCount)
            {${'Player'.($n+1)} = preg_split("/\s+/", $line[3+$n]);${'Player'.($n+1)}[2] = $matches[0][$n]; if (${'Player'.($n+1)}[2] > 1 && ${'Player'.($n+1)}[1] == 'LOSS') $Loser = ${'Player'.($n+1)}[0]; if (${'Player'.($n+1)}[2] > 1 && ${'Player'.($n+1)}[1] == 'WIN')
                   $Winner = ${'Player'.($n+1)}[0];
                $n++;
            }
        }
I was meaning to say this earlier, but all those statements on one line isn't very readable.

$matches is an array of strings, so $matches holds a string like "330 for Units". Change the regexp to use grouping (/(\d+) for Units/) and reference $matches[1][$n].

Multi-dimensional arrays are a little neater than variable variables:
PHP:
	        $Players=array();
            for ($n=0; $n < $PlayerCount; ++$n) {
                $Players[$n] = preg_split("/\s+/", $line[3+$n]);
                $Players[$n]['unitScore'] = $matches[0][$n]; 
                if ($Players[$n]['unitScore'] > 1 && $Players[$n][1] == 'LOSS') 
                    $Loser = $Players[$n][0];
                if ($Players[$n]['unitScore'] > 1 && $Players[$n][1] == 'WIN')
                    $Winner = $Players[$n][0];
            }
or (using a regexp rather than $line):
PHP:
	        preg_match_all('/^\s*(\S*)\s+(LOSS|WIN)\s*$/m', $startHere, $Players, PREG_SET_ORDER);
            foreach ($Players as $n => &$Player) {
                $Player['unitScore'] = $matches[0][$n]; 
                if ($Player['unitScore'] > 1 && $Player[2] == 'LOSS') 
                    $Loser = $Player[1];
                if ($Player['unitScore'] > 1 && $Player[2] == 'WIN')
                    $Winner = $Player[1];
            }

PHP:
        else {
            return 0;
        }
    } else {
        return 0;
    }
Can you tell what these cases cover at this point? Either add a comment explaining each case, or change the conditions and switch the if and else blocks so that the short case immediately follows the if.
 
Last edited:

garrensilverwing

New Member
Messages
148
Reaction score
0
Points
0
sorry for the mixed cases, i was in the middle of changing them all when i decided to post on here, i thought the example game was vanwilder but i guess its bibifock[is] instead...i'll go through all your suggestions and clean it up, this was originally coded by my friend so its still confusing to me haha thanks a bunch misson!

as far as the if/else statement blocks go, i had to reduce the number of characters in the post so i took the comments out, sorry for the confusion

here are a list of games that actually produce ghost players:

http://server.war2.ru/reports/gr_20091201193149_025685
http://server.war2.ru/reports/gr_20091201203339_025726
http://server.war2.ru/reports/gr_20091201223149_025853
http://server.war2.ru/reports/gr_20091201224435_025884
http://server.war2.ru/reports/gr_20091201233500_025964
http://server.war2.ru/reports/gr_20091202003142_026062
http://server.war2.ru/reports/gr_20091202004918_026086
http://server.war2.ru/reports/gr_20091202050006_000016
Edit:
I worked all day on fixing all the problems the code has, including changing a lot of what you said misson, but i'm still having a problem with the ghost games :( here is the new code, and just above this is a list of game reports that produce ghost players:

Code:
function  parseGameInfo($GameID)
		{
			set_time_limit(8000);
			$DateT = substr($GameID, 3, 14);
			$war2gameinfotxt = file_get_contents('http://server.war2.ru/reports/'.$GameID);
			if (preg_match('/mapauth=\"Self-Made\"/', $war2gameinfotxt) == 0 && preg_match('/DRAW/', $war2gameinfotxt) == 0
			&& preg_match('/DISCONNECT/', $war2gameinfotxt) == 0)
				{
					if (preg_match('/\sLOSS/', $war2gameinfotxt) == 0)
					{
						return 0;
					}
					if (preg_match('/\sWIN/', $war2gameinfotxt) == 0)
					{
						return 0;
					}
					$startHere = strstr($war2gameinfotxt,'joins=');
					$line = explode("\n", $startHere);
					$joinCount = substr($startHere, 6, 1);
					$englishCount = preg_match_all('/\sand played for/', $startHere, $matches);
					if ($englishCount < $joinCount)
						{		  
							return 0;
						}
					$watcherCount = preg_match_all('/\s1 for Units/', $startHere, $matches);
					$PlayerCount = $joinCount - $watcherCount;
					if ($PlayerCount == 2)
						{
							preg_match('/mapfile=\"(.+)\.pud\"/', $war2gameinfotxt, $mapmatch);
							$map = $mapmatch[1];  
							$throwAway = preg_match_all('/\d+ for Units/', $startHere, $matches);
							$n = 0;
							/* While loop: creates a variable Player1 first time through, Player2 second time through.
								Sets Player1[0] to the first Player's name, [1] to the result, [2] to his units.
								Sets Player2[0] to the second Player's name, etc.
								If Player's units are more than 1, and he lost or disconnected, his name is set to $Loser.
								If Player's units are more than 1, and he won, his name is set to $Winner.
							*/
					preg_match_all('/^(.*)\s+(LOSS)$/', $startHere, $Players, PREG_SET_ORDER);
					$Players=array();
					for ($n=0; $n < $PlayerCount; ++$n) 
						{
						$Players[$n] = preg_split("/\s+/", $line[3+$n]);
						$Players[$n]['unitScore'] = $matches[0][$n]; 
						if ($Players[$n]['unitScore'] > 1 && $Players[$n][1] == 'LOSS') 
							$Loser = $Players[$n][0];
						if ($Players[$n]['unitScore'] > 1 && $Players[$n][1] == 'WIN')
							$Winner = $Players[$n][0];
						}  
					}
					 else		//If there are more than two players (non-watchers)
					 {
						  return 0;
					 }
				}
				else		//If a player (non-watcher) was disconnected
					{
						return 0;
					}
			if($Winner == "" OR $Loser == "")
				{
					echo "\n<li><a href=\"http://server.war2.ru/reports/$GameID\">http://server.war2.ru/reports/$GameID</a></li>";
					mysql_query("INSERT INTO ghostgames (GameID) VALUES('$GameID');");
				}
			else 
				{
					insertLadderGame($GameID, $map, $Winner, $Loser, $DateT);
				}
			return 0;
		}
 
Last edited:

misson

Community Paragon
Community Support
Messages
2,572
Reaction score
72
Points
48
Try the
PHP:
 tags rather than [code] when posting PHP. It will colorize your code, making it easier to read and spot certain errors.

One area to focus on when cleaning up is the ranking logic. See if you can write a more logical breakdown, reworking it into higher-level tasks that will be implemented as functions. That section is ripe for logic errors.

As for the missing players, look to:
[quote="garrensilverwing, post: 608888"][php]
function  parseGameInfo($GameID) {
    ...
            preg_match_all('/^(.*)\s+(LOSS)$/', $startHere, $Players, PREG_SET_ORDER);
            $Players=array();
            for ($n=0; $n < $PlayerCount; ++$n) {
                $Players[$n] = preg_split("/\s+/", $line[3+$n]);
                $Players[$n]['unitScore'] = $matches[0][$n]; 
                var_dump($Players[$n]);
                if ($Players[$n]['unitScore'] > 1 && $Players[$n][1] == 'LOSS') 
                    $Loser = $Players[$n][0];
                if ($Players[$n]['unitScore'] > 1 && $Players[$n][1] == 'WIN')
                    $Winner = $Players[$n][0];
            }
[/QUOTE]
This loops over the number of players, rather than the number of joined people. With two players and four people (two watchers), only the first two people are considered. You could loop over $joinCount, but I recommend replacing the loop (and deleting the explode of $startHere into $lines) with preg_match_all as I showed in the last post. Here it is again:
PHP:
			preg_match_all('/^\s*(\S+)\s+(LOSS|WIN)\s*$/m', $startHere, $Players, PREG_SET_ORDER);
			var_dump($Players);
            foreach ($Players as $n => &$Player) {
                $Player['unitScore'] = $matches[0][$n]; 
                if ($Player['unitScore'] > 1 && $Player[2] == 'LOSS') 
                    $Loser = $Player[1];
                if ($Player['unitScore'] > 1 && $Player[2] == 'WIN')
                    $Winner = $Player[1];
            }
 

garrensilverwing

New Member
Messages
148
Reaction score
0
Points
0
i made the change to the code as you suggested and it certainly seems to have cut back on the number of ghost games, there used to be roughly 18% ghost games and now only 4%, a huge decrease. if you want to see how everything is working, go to http://war2ladder.x10hosting.com. if you have any ideas on what could still be causing the 4% ghost game problem, it would be hugely appreciated. there are some logic errors or something in the ranking system but i'll open a new topic for that
 

misson

Community Paragon
Community Support
Messages
2,572
Reaction score
72
Points
48
Post another set of URIs for problem games and the current code, and I'll take a look.
 

garrensilverwing

New Member
Messages
148
Reaction score
0
Points
0
http://server.war2.ru/reports/gr_20091202224058_000869
http://server.war2.ru/reports/gr_20091207063748_003914
http://server.war2.ru/reports/gr_20091207062354_003887
http://server.war2.ru/reports/gr_20091207061558_003901
http://server.war2.ru/reports/gr_20091207061022_003881
http://server.war2.ru/reports/gr_20091207055250_003852
http://server.war2.ru/reports/gr_20091206072941_002253
http://server.war2.ru/reports/gr_20091206071344_002226
http://server.war2.ru/reports/gr_20091206061809_002136
http://server.war2.ru/reports/gr_20091206055702_002117
http://server.war2.ru/reports/gr_20091206053854_002082
http://server.war2.ru/reports/gr_20091206053044_002090
http://server.war2.ru/reports/gr_20091206014511_001723
http://server.war2.ru/reports/gr_20091205121152_000859
http://server.war2.ru/reports/gr_20091204235407_003890
http://server.war2.ru/reports/gr_20091204233118_003856
http://server.war2.ru/reports/gr_20091204072849_003055
http://server.war2.ru/reports/gr_20091203072839_001582
http://server.war2.ru/reports/gr_20091202231005_000886

PHP:
     function  parseGameInfo($GameID)
        {
            set_time_limit(8000);
            $DateT = substr($GameID, 3, 14);
            $war2gameinfotxt = file_get_contents('http://server.war2.ru/reports/'.$GameID);
            if (preg_match('/mapauth=\"Self-Made\"/', $war2gameinfotxt) == 0 && preg_match('/DRAW/', $war2gameinfotxt) == 0
            && preg_match('/DISCONNECT/', $war2gameinfotxt) == 0)
                {
                    if (preg_match('/\sLOSS/', $war2gameinfotxt) == 0)
                    {
                        return 0;
                    }
                    if (preg_match('/\sWIN/', $war2gameinfotxt) == 0)
                    {
                        return 0;
                    }
                    $startHere = strstr($war2gameinfotxt,'joins=');
                    $line = explode("\n", $startHere);
                    $joinCount = substr($startHere, 6, 1);
                    $englishCount = preg_match_all('/\sand played for/', $startHere, $matches);
                    if ($englishCount < $joinCount)
                        {          
                            return 0;
                        }
                    $watcherCount = preg_match_all('/\s1 for Units/', $startHere, $matches);
                    $PlayerCount = $joinCount - $watcherCount;
                    if ($PlayerCount == 2)
                        {
                            preg_match('/mapfile=\"(.+)\.pud\"/', $war2gameinfotxt, $mapmatch);
                            $map = $mapmatch[1];  
                            $throwAway = preg_match_all('/\d+ for Units/', $startHere, $matches);
                            $n = 0;
                            /* While loop: creates a variable Player1 first time through, Player2 second time through.
                                Sets Player1[0] to the first Player's name, [1] to the result, [2] to his units.
                                Sets Player2[0] to the second Player's name, etc.
                                If Player's units are more than 1, and he lost or disconnected, his name is set to $Loser.
                                If Player's units are more than 1, and he won, his name is set to $Winner.
                            */
                            preg_match_all('/^\s*(\S+)\s+(LOSS|WIN)\s*$/m', $startHere, $Players, PREG_SET_ORDER);
                            var_dump($Players);
                            foreach ($Players as $n => &$Player) 
                                {
                                    $Player['unitScore'] = $matches[0][$n]; 
                                    if ($Player['unitScore'] > 1 && $Player[2] == 'LOSS') 
                                        $Loser = $Player[1];
                                    if ($Player['unitScore'] > 1 && $Player[2] == 'WIN')
                                        $Winner = $Player[1];
                                }  
                        }
                     else        //If there are more than two players (non-watchers)
                     {
                          return 0;
                     }
                }
                else        //If a player (non-watcher) was disconnected
                    {
                        return 0;
                    }
            if($Winner == "" OR $Loser == "")
                {
                    mysql_query("INSERT INTO ghostgames (GameID) VALUES('$GameID');");
                }
            else 
                {
                    insertLadderGame($GameID, $map, $Winner, $Loser, $DateT);
                    return 0;
                }
            return 0;
        }
 
Last edited:

descalzo

Grim Squeaker
Community Support
Messages
9,373
Reaction score
326
Points
83
Code:
preg_match_all('/^\s*(\S+)\s+(LOSS|WIN)\s*$/m',
    $startHere, $Players, PREG_SET_ORDER);

Will not match lines like ....

Code:
NINJA_STRYKE     LOSS     rating=895 [#00000]  prob=35.3%  K=50  adj=-17
ArRoW            WIN      rating=1000 [#00000]  prob=64.7%  K=50  adj=+17

The rating=895 [#00000] prob=35.3% K=50 adj=-17 part makes it a no-match.

I think that covers a lot of the problem files.
 

garrensilverwing

New Member
Messages
148
Reaction score
0
Points
0
yeah actually me and the other guy noticed that too, but there are a couple files that are still problematic that don't have those extra lines
 

descalzo

Grim Squeaker
Community Support
Messages
9,373
Reaction score
326
Points
83
Well, let us know which problem files are left.
 

garrensilverwing

New Member
Messages
148
Reaction score
0
Points
0
the other two are actually a problem with the game mechanics that we cant really fix: if there is at least 1 watcher, and that watcher leaves the game or is killed it counts as a loss for them and then the two players agree they can end the game with a victory each...

as far as the games with the ladder information, how can i change the regular expressions to fix that? NEVERMIND!! we got it fixed
 
Last edited:
Top