Punktesortierung bei Onlineliga

GreenBeret

Mitglied
hallo. ich arbeite an einer PHP-Online Liga für einen egoshooter.

bisher funktionierte es so, dass es eine tabelle für die user und eine für die matches gab. die user hatten standardgemäß 1000 punkte, und wenn einer ein match gewonnen hatte, wurde die usertabelle geupdated und dann stand in seiner usertabelle eben z.B. 1004 punkte. die rankingseite zu machen war dann unkompliziert, einfach die benötigten infos der "user"tabelle selektieren und "ORDER BY POINTS" machen.

ich möchte das system aber ändern, und zwar dass nun nicht mehr die nach jedem match neu fest gelegten punkte eingetragen werden sondern ich habe mir eine funktion gebaut, die in der matches tabelle nachschaut wieviele spiele der spieler gespielt hat, wieviele und wie hoch gewonnen hat und demnach die gesamtpunktzahl des spielers berechnet wird. Ich könnte problemlos eine funktion bauen die z.B. "get_playerpoints($userID)" heisst und für die userIDs die punkte ermittelt.

(ich mache das deshalb so, da evtl gespielte matches, die aber ungültig waren z.B. wegen cheatens gelöscht werden könnten, und der admin dann immer dem user manuell die beim match errungenen punkte abziehen müsste)

leider hätte ich dann das problem, dass ich bei der rankingsanzeige nicht mehr "order by points" angeben muss, da dieser wert eigentlich garnicht mehr existiert (und auch nicht mehr relevant ist). habt ihr eine idee wie man es trotzdem hinbekommen könnte ? das problem liegt ja darin dass erstmal für alle user der punktestand ermittelt werden muss, und dann eine sortierung erfolgen muss

um es gleich vorwegzunehmen: es ist leider nicht möglich über irgendwelche SQL Tricks, wie left join o.ä. dies hinzubekommen, das habe ich schon probiert und es hat nicht wirklich geklappt. ich möchte euch nun noch kurz ein paar felder in der tabelle matches aufzeigen:
- challenger_userid, challended_userid
- challenger(ed)_score_map1(2) => das sind einfach die mapergebnisse
- winner_id, loser_id
- challenger(ed)_points_difference - die anzahl der rankingpunkte die bei diesem match für den challenger/challenged spieler hinzugekommen sind.

die ranking-punkte werden nach dem ELO system berechnet (infos dazu findet man z.B. bei wikipedia). d.h. es kann auch sein dass man punkte erhält obwohl man das spiel verloren oder draw gespielt hat.

meine bisherige theoretische lösungsmethode sieht so aus:
- alle IDs aus der membertabelle holen. für jede ID mittels einer selbst gebauten funktion die gesamtpunktzahl errechnen. d.h. ich hole alle matches aus der matches tabelle bei denen userID = challenger_userid ist und addiere dann alle challenger_points_diff werte und mache dasselbe mit userID = challened_userid.
- das ganze funktioniert über while($fetch = mysql_fetch_array($sql))... - ich muss dann in dieser whileschleife, nachdem die punkte-funktion für jede ID die punkte herausgefunden hat diese auch irgendwie speichern, also z.B. in einem mehrdimensionalen array.
- dann muss z.B. das array sortiert werden, also nach den rankingpunkten - relevant ist aber dann letztendlich nicht nur der punktestand sondern v.a. auch die userid, ich muss also eine sortierung haben die mir sagt welche userID am meisten punkte hat, welche am zweitmeisten usw
- über eine foreach schleife verarbeitet die bereits sortierte userID-abfolge. es wird dann für jede ID der datensatrz geholt und die ergebnisse auf der seite angezeigt.

ist das soweit richtig ? wenn ja, dann bräuchte ich auf jeden fall hilfe wie das mit der erstellung und sortierung des mehrdimensionalen arrays gehen kann. ich habe gesehen dass es einige sort-funktionen gibt, aber diese löschen den index, der bei mir ja die userID wäre, und genau das kann ich nicht gebrauchen da der index (also die userID) das ist was ja entscheidend ist!

MfG
 
Ich find's ja klasse, dass Du Dein Problem so umfangreich beschreibst, aber wenn Du jetzt noch Gross- und Kleinschreibung korrigierst, dann kann man das sogar lesen ohne Hirnrindenkrebs zu bekommen. ;)
 
Also ich sag dir ganz ehrlich, so eine Onlineliga ist ja meist ein grösseres Ding, und da ist es von der Perfomance auf jeden Fall empfehlenswert, bei dem alten System zu bleiben. Zu dem Problem beim Löschen/Ungültig erklären eines Matches: Du wirst da ja bestimmt ein ACP haben, wo der Admin das machen kann – dann kannst du ja genausogut in die Datei, die das Match löscht (z. B. delete.php) noch einen zusätzlichen Query einbauen, der in der User-Tabelle bei den entsprechenden den Punktestand wieder ändert. Macht für mich mehr Sinn.

Aber wenn du es unbedingt so machen willst wie beschrieben, dann ok. Ich sehe jetzt ehrlich gesagt auch keine bessere Lösung als die von dir beschriebene. Muss dazu allerdings auch sagen, dass ich mich mit SQL nicht besonders gut auskenne, es könnte also durchaus sein, dass sich das über irgendeine komplizierte Anfrage lösen liesse (das wäre natürlich der Idealfall).

Hast du denn schon angefangen, die neuen Funktionen zu implementieren? Wenn ja, wo liegen konkret deine Probleme?
 
also, habe es letzendlich doch hinbekommen

ja, es ist richtig, eine Liga erfordert ein AdminPanel, und an diesem arbeite ich auch.

Hier die Funktion um die Punkte eines Spielers zu bekommen:
PHP:
function get_playerpoints ($userid)
{
	//get the rankingpoints by searching for all matches that the player did
	global $prefix;
	global $conn;
	$sql = "SELECT * FROM `".$prefix."matches` WHERE match_report_accepted!='0' AND challenger_userid=".$userid;
	$query = mysql_query($sql, $conn);
	$points = 1000; //standard points
	while ($fetch = @mysql_fetch_array($query))
	{
		$points = $points + $fetch['challenger_points_diff'];
	}
	$sql2 = "SELECT * FROM `".$prefix."matches` WHERE match_report_accepted!='0' AND challenged_userid=".$userid;
	$query2 = mysql_query($sql2, $conn);
	while ($fetch2 = @mysql_fetch_array($query2))
	{
		//echo $fetch['challenged_points_diff'];
		$points = $points + $fetch2['challenged_points_diff'];
	}
	return $points;
}

jetzt zum knackpunkt:
PHP:
$sql = "SELECT id FROM `".$prefix."members`";
$query = mysql_query($sql);
$users = array();
while ($fetch = @mysql_fetch_array($query))
{
	$points = get_playerpoints($fetch['id']);
	$users["$points"] = $fetch['id'];
}
function cmp($a, $b)
{
   if ($a == $b) {
       return 0;
   }
   return ($a > $b) ? -1 : 1;
}
uksort($users, "cmp");
foreach ($users as $key => $value) {
   $sql = "SELECT ID, username, points, country FROM ".$prefix."members WHERE id=".$value;
   $query = mysql_query($sql, $conn) or die(mysql_error());
   $data=mysql_fetch_array($query);
   ...
}
 
hmm, das Problem das mir jetzt geblieben ist, ist: wenn zwei Spieler die selbe Punktzahl haben, wird nur einer angezeigt, die anderen die die selbe Punktzahl haben, verschwinden =/
 
Problem gelöst

habe $users zu einem multidimensionalen Array gemacht. d.h. die User die dann gleichviel Punkte hatten waren dann jeweils in einem Array im Array $users. musste dann halt die foreach schleife etwas ändern, in:

PHP:
foreach ($users as $key => $value) {
	foreach ($users["$key"] AS $key => $value)
	{
	....
	}
}

MfG
 
Zurück