Kirjautuminen

Haku

Tehtävät

Keskustelu: Nettisivujen teko: Taulukon järjestäminen monen kriteerin suhteen

Sivun loppuun

jideko [06.06.2006 19:50:11]

#

No johan oli otsikko.

Olen tekemässä futiksen MMkisoista sarjataulukkoa. Nyt kuitenkin tuli ongelma vastaan.

Nyt minulla on moniuloteinen taulukko joka koostuu näin:

scores---lohko A-----joukkue 1-------pelatut ottelut
		|		|			|--------voitot
		|		|			|--------tasapelit
		|		|			|--------häviöt
		|		|			|--------tehdyt maalit
		|		|			|--------päästetyt maalit
		|		|			|--------pisteet
		|		|
		|		|------joukkue 2--------pelatut ottelut
		|		|			.
		|		|			.
		|		|			|--------pisteet
		|		.
		.		------joukkue3
		.		.
		-lohko B
		.

Olen tehnyt jokaiselle lohkolle oman taulukon johon järjestän joukkueet pisteiden perusteella.
Mutta kun kahdella joukkueella on samat pisteet, niin niiden keskenäinen järjestys pitäisi saada keskinäisen ottelun tai maalieron perusteella.
Siinä vaiheessa mulla menee sormi suuhun.

Osaisiko joku ystävällisesti auttaa?


Laitetaanpa vielä tiedostot niin voi kokeilla käytännössä tuota.

standings.php

<?php
$countries=file("countries.txt");
$i=0;
while($countries[$i]!=""){
	$countries[$i]=str_replace("\n","",$countries[$i]);
	$countries[$i]=str_replace("\r","",$countries[$i]);
	$i++;
}
$scores=array();

$info=array("mp"=>0, "wins"=>0, "ties"=>0, "losses"=>0, "gf"=>0, "ga"=>0, "points"=>0);

for($i=0;$i<8;$i++) {
	$group=array( ($i*4+0) => $info,  ($i*4+1) => $info,  ($i*4+2) =>$info,  ($i*4+3) => $info);
	$scores[$i]=$group;
}


$games=file("games.txt");

$groups=array("a","b","c","d","e","f","g","h");


for($i=0;$i<count($games);$i++) {
	$osat=explode("|",$games[$i]);

	$scores[(ceil(($osat[0]+1)/4)-1)][$osat[0]]["mp"] +=1;
	$scores[(ceil(($osat[0]+1)/4)-1)][$osat[1]]["mp"] +=1;
	$scores[(ceil(($osat[0]+1)/4)-1)][$osat[0]]["gf"] +=$osat[2];
	$scores[(ceil(($osat[0]+1)/4)-1)][$osat[1]]["gf"] +=$osat[3];
	$scores[(ceil(($osat[0]+1)/4)-1)][$osat[0]]["ga"] +=$osat[3];
	$scores[(ceil(($osat[0]+1)/4)-1)][$osat[1]]["ga"] +=$osat[2];

	if(trim($osat[2])>trim($osat[3])){
		$scores[(ceil(($osat[0]+1)/4)-1)][$osat[0]]["points"] +=3;
		$scores[(ceil(($osat[0]+1)/4)-1)][$osat[0]]["wins"] +=1;
		$scores[(ceil(($osat[0]+1)/4)-1)][$osat[1]]["losses"] +=1;
	}
	elseif(trim($osat[2])<trim($osat[3])){
		$scores[(ceil(($osat[0]+1)/4)-1)][$osat[1]]["points"] +=3;
		$scores[(ceil(($osat[0]+1)/4)-1)][$osat[1]]["wins"] +=1;
		$scores[(ceil(($osat[0]+1)/4)-1)][$osat[0]]["losses"] +=1;

	}
	else {
		$scores[(ceil(($osat[0]+1)/4)-1)][$osat[1]]["points"] +=1;
		$scores[(ceil(($osat[0]+1)/4)-1)][$osat[0]]["points"] +=1;
		$scores[(ceil(($osat[0]+1)/4)-1)][$osat[1]]["ties"] +=1;
		$scores[(ceil(($osat[0]+1)/4)-1)][$osat[0]]["ties"] +=1;
	}
}


echo "<table>\n\t<tr>\n";
for($i=0;$i<8;$i++) {
	if($i==2 || $i==4 || $i==6) echo "\t</tr>\n\t<tr>\n";
	echo "\t\t<td valign=\"top\">\n";
	echo "\t\t\t<table>\n";
	echo "\t\t\t<tr><th class =\"country1\">". strtoupper($groups[$i]) ."</th><th>MP</th><th>W</th><th>D</th><th>L</th><th>GF</th><th>GA</th><th>Pts</th></tr>\n";

	@arsort($scores[$i]);
	@reset($scores[$i]);
	foreach ($scores[$i] as $country => $teaminfo){
		echo "\t\t\t\t<tr>\n\t\t\t\t\t";
		echo "<td class=\"country\">".$countries[$country]."</td>\n";
		echo "\t\t\t\t\t<td>".$teaminfo["mp"]."</td>\n";
		echo "\t\t\t\t\t<td>".$teaminfo["wins"]."</td>\n";
		echo "\t\t\t\t\t<td>".$teaminfo["ties"]."</td>\n";
		echo "\t\t\t\t\t<td>".$teaminfo["losses"]."</td>\n";
		echo "\t\t\t\t\t<td>".$teaminfo["gf"]."</td>\n";
		echo "\t\t\t\t\t<td>".$teaminfo["ga"]."</td>\n";
		echo "\t\t\t\t\t<td>".$teaminfo["points"]."</td>\n";
		echo "\t\t\t\t</tr>\n";
	}
	echo "\t\t\t</table>\n";
	echo"\t\t</td>\n";
}
echo "\t</tr>\n</table>\n";
?>

countries.txt

Costa Rica
Ecuador
Germany
Poland
England
Paraguay
Sweden
Trinidad and Tobago
Argentina
Côte d'Ivoire
Netherlands
Serbia and Montenegro
Angola
Iran
Mexico
Portugal
Czech Republic
Ghana
Italy
USA
Australia
Croatia
Brazil
Japan
France
Korea Republic
Switzerland
Togo
Saudi Arabia
Spain
Tunisia
Ukraine

games.txt esimerkki

3|2|1|4
1|2|1|2
18|19|3|1
0|3|2|2
16|17|3|3

Metabolix [06.06.2006 20:51:06]

#

Hitaasti mutta varmasti tuo onnistuu (ainakin teoriassa) sillä, että ensin järjestetään ne heikommalla perusteella ja vasta sitten pääasiallisella periaatteella. Käytännössä valmisfunktioiden kanssa tämä voi olla ongelma, eli oma lajittelufunktio tulisi tarpeeseen. PHP vielä mutkistaa asioita entisestään...

Nopeinta on kuitenkin etsiä ensimmäinen ja viimeinen saman pistemäärän omaava joukkue ja järjestää se väli uudestaan. Bubble Sort ja Insertion Sort voivat olla helpoimmin toteutettavat algoritmit, ja löytyypä tuolta koodivinkeistä muitakin. Pitää vain lajitella alkiot tietyltä väliltä.

Blaze [06.06.2006 21:16:53]

#

Minä tekisin tuollaisen oman sorttausfunktion, ja antaisin sen usort:lle parametriksi.

jideko [06.06.2006 22:24:13]

#

Huhhuh, menee kyllä mulle vähän vaikeaksi. Kun en mikään haka php:ssä ole, kuten noista koodeista näkyy, aika moista purkkaa paikoittain.

Pitää kyllä vielä yrittää lueskella tuota manuaalia oikeen ajan kanssa, kun äkkiä vilkasin niin näytti vähän hankalalta. Tai sitten toivoa ettei tule tasatuloksia.

Antti Laaksonen [06.06.2006 22:56:44]

#

Voisitko selostaa tarkemmin:
- järjestysperiaatteen
- tiedoston games.txt rakenteen

Näiden tietojen perusteella voin ehkä olla avuksi.

jideko [06.06.2006 23:38:30]

#

Jokaisella maalla on oma numeronsa(countries.txt:n rivinumero), games.txt:ssa yhdellä rivillä on yksi ottelu.
maa1|maa2|maa1:n maalit|maa2:n maalit. Eli 16|17|3|3 tarkoittaisi, että Tsekki ja Ghana olisi pelannut 3-3 tasapelin.
Ja nuo kaikki tiedot saan kyllä taulukkoon ihan oikein, mutta sitten järjestäminen tuottaa ongelmia.

EDIT:
Tarkistin viralliset säännöt ja nyt tämä taisi helpottua aika lailla.
Eli, järjestysperjaate:
Joukkue jolla on eniten pisteitä on ylimpänä listassa. Jos kuitenkin joillakin joukkueilla on yhtä paljon pisteitä, heidän välinen järjestys ratkeaa maalierolla(tehdyt maalit-päästetyt maalit). Jos maalierotkin on samat niin paremman sijoituksen saa joukkue jolla on enemmän tehtyjä maaleja.

Laitetaan nytten vielä virallista tekstiä kehiin.

http://eur.i1.yimg.com/eur.yimg.com/i/eu/fifa/regen.pdf:

The ranking of each team in each group will be determined as
follows:
a) greatest number of points obtained in all group matches;
b) goal difference in all group matches;
c) greatest number of goals scored in all group matches.
If two or more teams are equal on the basis of the above three criteria,
their rankings will be determined as follows:
XVIII. TECHNICAL RULES FOR THE FINAL COMPETITION
41
d) greatest number of points obtained in the group matches between
the teams concerned;
e) goal difference resulting from the group matches between the
teams concerned;
f) greater number of goals scored in all group matches between the
teams concerned;
g) drawing of lots by the Organising Committee for the FIFA World
Cup™.

Antti Laaksonen [07.06.2006 00:04:00]

#

Tuo tosiaan helpottaa järjestelyä ratkaisevasti.

Nyt riittää Blazen mainitsema usort-funktio, jolle voi ilmoittaa juuri halutunlaisen järjestelytavan.

function vertailu($a, $b) {
    if ($a["points"] == $b["points"]) {
        if ($a["gf"] - $a["ga"] == $b["gf"] - $b["ga"]) {
            return $b["gf"] - $a["gf"];
        } else {
            return ($b["gf"] - $b["ga"]) - ($a["gf"] - $a["ga"]);
        }
    } else {
        return $b["points"] - $a["points"];
    }
}

// muutos alkuperäiseen koodiin:
@usort($scores[$i], "vertailu");

Ideana on siis se, että oma funktio vertailu saa parametreikseen kaksi taulukon alkiota, joita varsinainen järjestelyalgoritmi sillä hetkellä vertailee. Jos funktio palauttaa negatiivisen arvon, ensimmäinen parametri kuuluu järjestyksessä toisen edelle ja jos funktio palauttaa positiivisen arvon, toinen parametri kuuluu järjestyksessä ensimmäisen edelle. Nyt vertailussa voidaan ottaa huomioon samat arvot ja vertailla tilanteesta riippuen eri asioita.

muokkaus: Nuo kohdat d:stä eteenpäin ovat hankalampia. Nyt ei riitä pelkkä kahden joukkueen tietojen vertailu, vaan pitää erikseen ottaa huomioon, että käsittelyssä ovat vain tasaväkiset joukkueet. Tämän voi toteuttaa laskemalla ensimmäisen järjestelyn jälkeen erilliset tiedot tasaväkisistä joukkueista ja järjestelemällä joukkueet uudestaan laajennetulla vertailulla, mutta onkohan näin monimutkainen järjestely tarpeen omassa tapauksessasi?

jideko [07.06.2006 14:18:22]

#

Tuo toimii muuten paitsi maiden IDnumerot katoaa jonnekkin. Joten se tulostaa joka taulukkoon samat maat, ja niiden järjestys ei muutu.
Pisteiden järjestys näyttää kuitenkin olevan oikea.

Antti Laaksonen kirjoitti:

muokkaus: Nuo kohdat d:stä eteenpäin ovat hankalampia. Nyt ei riitä pelkkä kahden joukkueen tietojen vertailu, vaan pitää erikseen ottaa huomioon, että käsittelyssä ovat vain tasaväkiset joukkueet. Tämän voi toteuttaa laskemalla ensimmäisen järjestelyn jälkeen erilliset tiedot tasaväkisistä joukkueista ja järjestelemällä joukkueet uudestaan laajennetulla vertailulla, mutta onkohan näin monimutkainen järjestely tarpeen omassa tapauksessasi?

Epäilen että tämä riittää minulle. Täytyy sitten palata asiaan, jos tulee ongelmia.

Mutta jos tuohon joltakin vielä löytyisi neuvo, että miten saan maat takaisin ja vielä oikeaan järjestykseen.

Antti Laaksonen [07.06.2006 14:26:22]

#

Auttaisiko funktion uasort käyttö asiaan?

jideko [07.06.2006 14:40:00]

#

Nyt puolet maista katosi, mutta muut näkyy kyllä oikein.

Muutin vähän systeemin rakennetta. Laitoin joukkueiden pistelaskennan erilliseen tiedostoon, koska tarvitsen scorearrayta muuallakin.

Mulla on ollut peukalo suussa jo pidempään niin päätin vielä laittaa yritykseni tähän, ja kysyä että olenko laittanut tuon usort/uasort funktio jutun oikeen?

standings.php

<?php
include("scorearray.php");

$countries=file("countries.txt");
$groups=array("a","b","c","d","e","f","g","h");

echo "<table>\n\t<tr>\n";
for($i=0;$i<8;$i++) {
	if($i==2 || $i==4 || $i==6) echo "\t</tr>\n\t<tr>\n";
	echo "\t\t<td valign=\"top\">\n";
	echo "\t\t\t<table>\n";
	echo "\t\t\t<tr><th class =\"country1\">".strtoupper($groups[$i])."</th><th>MP</th><th>W</th><th>D</th><th>L</th><th>GF</th><th>GA</th><th>Pts</th></tr>\n";

	@uasort($scores[$i], "vertailu");
	@reset($scores[$i]);
	foreach ($scores[$i] as $country => $teaminfo){
		echo "\t\t\t\t<tr>\n\t\t\t\t\t";
		echo "<td class=\"country\">".$countries[(4*$i+$country)]."</td>\n";
		echo "\t\t\t\t\t<td>".$teaminfo["mp"]."</td>\n";
		echo "\t\t\t\t\t<td>".$teaminfo["wins"]."</td>\n";
		echo "\t\t\t\t\t<td>".$teaminfo["ties"]."</td>\n";
		echo "\t\t\t\t\t<td>".$teaminfo["losses"]."</td>\n";
		echo "\t\t\t\t\t<td>".$teaminfo["gf"]."</td>\n";
		echo "\t\t\t\t\t<td>".$teaminfo["ga"]."</td>\n";
		echo "\t\t\t\t\t<td>".$teaminfo["points"]."</td>\n";
		echo "\t\t\t\t</tr>\n";
	}
	echo "\t\t\t</table>\n";
	echo"\t\t</td>\n";
}
echo "\t</tr>\n</table>\n";
?>

scorearray.php

<?php
$scores=array();

$info=array("mp"=>0, "wins"=>0, "ties"=>0, "losses"=>0, "gf"=>0, "ga"=>0, "points"=>0);

for($i=0;$i<8;$i++) {
	$group=array( ($i*4+0) => $info,  ($i*4+1) => $info,  ($i*4+2) =>$info,  ($i*4+3) => $info);
	$scores[$i]=$group;
}

$games=file("games.txt");

for($i=0;$i<count($games);$i++) {
	$osat=explode("|",$games[$i]);

	$scores[(ceil(($osat[0]+1)/4)-1)][$osat[0]]["mp"] +=1;
	$scores[(ceil(($osat[0]+1)/4)-1)][$osat[1]]["mp"] +=1;
	$scores[(ceil(($osat[0]+1)/4)-1)][$osat[0]]["gf"] +=$osat[2];
	$scores[(ceil(($osat[0]+1)/4)-1)][$osat[1]]["gf"] +=$osat[3];
	$scores[(ceil(($osat[0]+1)/4)-1)][$osat[0]]["ga"] +=$osat[3];
	$scores[(ceil(($osat[0]+1)/4)-1)][$osat[1]]["ga"] +=$osat[2];

	if(trim($osat[2])>trim($osat[3])){
		$scores[(ceil(($osat[0]+1)/4)-1)][$osat[0]]["points"] +=3;
		$scores[(ceil(($osat[0]+1)/4)-1)][$osat[0]]["wins"] +=1;
		$scores[(ceil(($osat[0]+1)/4)-1)][$osat[1]]["losses"] +=1;
	}
	elseif(trim($osat[2])<trim($osat[3])){
		$scores[(ceil(($osat[0]+1)/4)-1)][$osat[1]]["points"] +=3;
		$scores[(ceil(($osat[0]+1)/4)-1)][$osat[1]]["wins"] +=1;
		$scores[(ceil(($osat[0]+1)/4)-1)][$osat[0]]["losses"] +=1;

	}
	else {
		$scores[(ceil(($osat[0]+1)/4)-1)][$osat[1]]["points"] +=1;
		$scores[(ceil(($osat[0]+1)/4)-1)][$osat[0]]["points"] +=1;
		$scores[(ceil(($osat[0]+1)/4)-1)][$osat[1]]["ties"] +=1;
		$scores[(ceil(($osat[0]+1)/4)-1)][$osat[0]]["ties"] +=1;
	}
}

function vertailu($a, $b) {
	if ($a["points"] == $b["points"]) {
		if ($a["gf"] - $a["ga"] == $b["gf"] - $b["ga"]) {
			return $b["gf"] - $a["gf"];
		} else {
			return ($b["gf"] - $b["ga"]) - ($a["gf"] - $a["ga"]);
		}
	} else {
		return $b["points"] - $a["points"];
	}
}
?>

games.txt

19|17|4|1
0|1|3|1
19|18|2|1
18|17|5|1
2|3|2|1
3|0|5|1

Sivun alkuun

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta