- <?php
- /** A groups tömbökön különböző műveletek végző függvények kódjai
- *
- * Itt azok a függvények találhatóak, amelyek a $groups tömbön végeznek
- * különféle műveleteket.
- *
- * @package koliportal
- * @author Karakó Miklós <palacsint_X_freemail.hu>
- * @copyright Copyright © 2005, Karakó Miklós
- */
-
- /** Első-első kívánságot nem tartalmazó csoportok kiszűrése
- *
- * Kiszűri azokat a csoportokat, amelyek 1-1-es jelölés esetén csak az
- * egyik hallgatót tartalmazzák.
- *
- * 1-1-es jelölés: két diák egymást jelölte meg első helyen a
- * kívánságlistájukban.
- *
- * ST_HETEROGEN esetén azokat a csoportokat is kiszűri, amelyekben egyforma
- * neműek vannak.
- *
- * @param array $groups A szűrendő csoportok
- * @param array $table Használt kívánságmátrix
- * @param array $students A kívánságmátrixban található hallgatói
- * azonosítók folytonosan indexelve
- * @param int $stype Fiú-Lány 1-1 kívánsot keresünk-e? Ha igen,
- * akkor ST_HETEROGEN, más esetben ettől eltérő értéke legyen.
- *
- * @return array Megszűrt csoportlista
- */
- function strip_not11_groups($groups, $table, $students, $stype)
- {
- $found_wrong = false; // ha találtunk legalább egy hibás csoportot, akkor true lesz
-
- // ellenőrzünk minden csoportot
- $gsize = count($groups);
- for ($i = 0; $i < $gsize; $i++)
- {
- $u = $groups[$i]["users"];
- sort($u);
-
- $wrong_group = false; // ha hibás a csoport, akkor true lesz
- if (ST_HETEROGEN == $stype)
- {
- if ((2 != count($u)) || (get_student_st($u[0]) == get_student_st($u[1])))
- {
- $found_wrong = $wrong_group = true;
- }
- }
-
- for ($j = 0; $j < count($u); $j++)
- {
- // $fw a $j. user 1 helyen jelölt kívánsága
- $fw = find_wish($table, $students, $u[$j], 1);
- if (($fw !== false) && ($wrong_group === false))
- {
- /*
- // ez is jó, de a másik szebb
- if (isset($table[$fw][$u[$j]]) && ($table[$fw][$u[$j]] == 1)
- && (array_search($fw, $u) === false))
- {
- debug_echo("Elrontott csoport: $fw, " . $u[$j] );
- //$wrong_group = true;
- //die();
-
- }
- */
- // most fordítva is
- $fw_first = find_wish($table, $students, $fw, 1);
- if (($fw_first == $u[$j]) && (array_search($fw, $u) === false))
- {
- $wrong_group = true;
- $found_wrong = true;
- break;
- }
- }
- }
-
- if ($wrong_group === true)
- {
- //debug_echo("\teltávolítva...");
- unset($groups[$i]);
- //$i--;
- //sort($groups);
- //reset($groups);
- }
- }
-
- // csak akkor szükséges, ha találtunk hibás csoportot (és töröltük ugye)
- if ($found_wrong)
- {
- sort($groups);
- reset($groups);
- }
-
- return $groups;
- }
-
- /** Kétfős csoportok kialakítása
- *
- * A megadott adatok alapján létrehoz egy tömböt, amelyek két fős csoportokat
- * tartalmaz. A csoportokat a $table tömb kölcsönös élei alapján rakja össze.
- * Egy csoport többször is szerepelhet a kimeneti tömbben, ezt később még
- * szűrni kell.
- *
- * @param array $table A kapcsolatokat tartalmazó táblázat
- * @param array $key A $table indexeihez tartozó valódi felhasználói azonosítók (users.sid)
- * @param int $stype A kapcsolat típusa. Jelenleg két részre van bonta: páros szoba és nem páros szoba
- * @return array A kétfős csoportokat tartalamzó tömb
- */
- function make_2groups($table, $keys, $stype)
- {
- $groups = array();
- $gindex = 1;
-
- sort($keys);
- $maxij = count($keys);
-
- for ($i = 0; $i < $maxij; $i++)
- {
- for ($j = 0; $j < $maxij; $j++)
- {
- $u1 = $keys[$i];
- $u2 = $keys[$j];
- if (isset($table[$u1][$u2]) &&
- isset($table[$u2][$u1])
- )
- {
- $r1 = $table[$u1][$u2];
- $r2 = $table[$u2][$u1];
-
- /* ez akkor lesz igaz:
- - ha nem páros csoportokat akarunk csinálni
- - vagy ha páros csoportot akarunk, és különböző neműek
- ha hamis, akkor ez nem ide való csoport
- */
- if ((ST_HETEROGEN != $stype) || (get_student_st($u1) != get_student_st($u2)))
- {
-
- $newgroup = array();
- $newgroup["users"][$u1] = $u1;
- $newgroup["users"][$u2] = $u2;
- /* ez még ráérne később, de nem jelent nagy plusz költséget */
- $newgroup["points"] = ($r1 + $r2);
-
- /* itt ellenőrizhetnénk, hogy van-e már ilyen csoport,
- de ahhoz mindig rendezgetni kellene a tömböket - a végén
- egy lépésben elvégezve jobb futásidőt kapunk */
- $groups[$gindex++] = $newgroup;
- }
- }
- }
- }
-
- sort($groups);
- reset($groups);
-
- return $groups;
- }
-
-
-
- /** 2-nél nagyobb létszámú csoportok létrehozása
- *
- * A megkapott, kétfős csoportokat próbálja meg kibővíteni mindig egy-egy
- * új hallgató hozzáadásával. Maximum $spacemax fős csoportokat hoz létre.
- *
- * @param array $groups Kiindulási csoportok
- * @param array $table Kívánságmátrix
- * @param array $students A kívánságmátrixban szereplő hallgatói azonosítók indexfolytonosan
- * @param int $spacemax Maximum ennyi fős csoportokat kell létrehozni
- */
-
- function make_ngroups($groups, $table, $students, $spacemax)
- {
-
- /* ilyenkor nincs mit csinálni */
- if ($spacemax == 2)
- {
- return $groups;
- }
-
- $maxij = count($students);
- for ($gi = 0; $gi < count($groups); $gi++)
- {
- /* minden user-t megpróbálunk hozzáadni a g1 csoporthoz */
- for ($i = 0; $i < $maxij; $i++)
- {
- $gc = $groups[$gi]; // ha új user került a csoportba, akkor is működjön ám!
- reset($gc);
- /* ha már bennevan az $i user a csoportban, akkor jöhet a következő
- optimalizálunk itt is, $spacemax-nál nagyobb csoportokra
- nincs szükség */
- if (!isset($gc["users"][$students[$i]]) && (count($gc["users"]) < $spacemax))
- {
- $sel_ok = true;
- /* kipróbáljuk, hogy létezik-e [g1user, $i] és [$i, $g1user] él a gráfban
- tehát hogy minden csoporttag bejelölte- az $i. diákot, mint leendő szobatárs
- ha nincs, akkor ez az ($i) user nem kerülhet be a csoportba */
- reset($gc["users"]);
- while (list(, $guser) = each($gc["users"]))
- {
- $k1 = $students[$i];
- $k2 = $guser;
-
- if (!isset($table[$k1][$k2]) || !isset($table[$k2][$k1]))
- {
- $sel_ok = false;
- /* innen breakelhetnénk is kifele */
- break;
- }
- }
- if ($sel_ok)
- {
- /* ilyenkor új csoportot csinálunk, mert:
- ABC és ABD is megjelölte egymást
- akkor először lesz AB, majd ABC, de ABD már nem lehet,
- ha BC nem jelölte meg egymást
- ezért lesz egy AB és egy ABC, amihez később még hozzájön
- egy ABD mindegyikre számolunk egy pontszámot,
- és majd kiderül melyik a nyerő
- */
- $end = count($groups); // csoportsorszám lesz
-
- $newgroup = array();
- $newgroup["users"] = $groups[$gi]["users"];
- $newgroup["users"][$students[$i]] = $students[$i];
- sort($newgroup["users"]);
-
- /* ezzel itt nagyon sokat lehet spórolni
- ha már van ilyen csoport, akkor ne adjuk hozzá */
- if (!is_group($groups, $newgroup))
- {
- $groups[$end] = $groups[$gi];
- $groups[$end]["users"][$students[$i]] = $students[$i];
- sort($groups);
- /* módosítani kelle a "points" -ot:
- *
- * ez még ráér később, mert lehetnek többszörös csoportokat,
- * amiket előbb kiszűrve csökkenthető a műveletek száma
- */
- }
- }
- }
- }
- }
-
- return $groups;
- }
-
- /** Többször jelenlévő csoportok törlése
- *
- * A függvény egy kivételével törli a $groups tömb azon elemeit,
- * amelyek ["users"] altömbjének azonos elemei vannak.
- * Folytonosan indexelt $groups tömb szükséges a helyes működéshez!
- *
- * @param array $groups Csoportlista
- * @return array Megszűrt csoportlista
- */
- function uniq_groups($groups)
- {
- for ($i = 0; $i < count($groups); $i++)
- {
- for ($j = $i + 1; $j < count($groups); $j++)
- {
- if (!array_diffp($groups[$i]["users"], $groups[$j]["users"]))
- {
- unset($groups[$j]);
- sort($groups);
- //debug_echo("groups $i == $j: true");
- $j--;
- } else {
- //debug_echo("groups $i == $j: false");
- }
- }
- //print_r($groups);
- }
- return $groups;
- }
-
-
- /* sorrendezi a csoportokat, a belső "users" altömbbel együtt */
- /** Csoportok sorrendezése
- *
- * Sorrendezi a csoportokat, folyonos indexeléssel látja el mind a főtömböt,
- * mind az egyes altömbök "users" tömbjét.
- *
- * @param array $groups Sorrendezni kívánt csoport tömbje
- * @return array Rendezett csoportlista
- */
- function sort_groups($groups)
- {
- sort($groups);
- for ($i = 0; $i < count($groups); $i++)
- {
- sort($groups[$i]["users"]);
- }
- sort($groups); // újrasorrendezzük mert muszáj az előző sort()-ok miatt
- reset($groups);
- return $groups;
- }
-
-
- /* összehasonlító funkció az usort()-hoz... két csoportot hasonlít össze
- * pontszám szerint
- */
- /** Két csoport összehasonlítása pontszám szerint
- *
- * Az usort() függvényhez szükséges segédfüggvény, amely két csoportot
- * hasonlít össze a pontszámuk szerint.
- *
- * @param array $a Az első csoport
- * @param array $b A második csoport
- * @return int Az usort() által várt 1, -1, vagy 0
- */
- function cmp_group_by_points($a, $b)
- {
- //var_dump($a);
- //var_dump($b);
- //die();
- if ($a["points"] > $b["points"])
- {
- return 1;
- }
- if ($a["points"] < $b["points"])
- {
- return -1;
- }
- if (count($a["users"]) > count($b["users"]))
- {
- return 1;
- }
- elseif (count($a["users"]) > count($b["users"]))
- {
- return -1;
- }
- else
- {
- return 0;
- }
- }
-
-
- /** Csoportok pontszámainak kiszámítása és sorrendezési
- *
- * Kiszámítja minden csoport pontszámát, majd a tömböt eszerint
- * sorba is rendezi. A pontszám jelenleg attól függ, hogy csoporttagok
- * hanyadik helyen jelölték meg egymás. A lista elejéhez közelebb eső
- * jelölések kevesebb pontot érnek, de növekvő sorrenbe lesznek rendezve
- * a csoportok a függvény végén, s majd a szobabeosztás is ez alapján fog
- * történni.
- *
- * @param array $groups Csoporttömb
- * @param array $table_full Kívánságmátrix
- * @return array Csoporttömb, pontszám szerint sorbarendezve
- */
- function calc_points($groups, $table_full)
- {
- // pontok kiszámítása minden csoporthoz!
- /* FIXME: ide kellene valami átlag is, amit figyelembe lehetne
- venni, ha egyébként azonos a pontszám. Például 100000-res szorzó
- mellett az átlagok összegét ki lehetne vonni a pontszámból.
- Még 6 fős csoportok esetén is (10000/6/(6-1) = 333) sem befolyásolná
- az értékét az átlag 10-szerese */
- for ($i = 0; $i < count($groups); $i++)
- {
- $p = 0;
- $avg = 0;
- $u1 = $u2 = $groups[$i]["users"];
- reset($u1);
- while (list(, $u1v) = each($u1))
- {
- reset($u2);
- while (list(, $u2v) = each($u2))
- {
- if ($u1v != $u2v)
- {
- $p += $table_full[$u1v][$u2v];
- }
- }
- $avg += get_average($u1v);
- }
-
- $c = count($groups[$i]["users"]);
- // eredeti:
- //$groups[$i]["points"] = $p * 1000 / $c / ($c - 1) ;
- $groups[$i]["points"] = $p * 1000 / $c - $avg ;
-
- }
-
-
- /* sorbarendezünk pontszám szerint */
- usort($groups, "cmp_group_by_points");
-
- return $groups;
- }
-
-
- /** Csoportellenőrzés
- *
- * A függvény leellenőrzi, hogy tényleg mindenki belevaló-e a csoportba,
- * mindenki bejelölt-e mindenkit a csoportból. Fejlesztői (?) funkció, az
- * csoportképző algoritmus helyességének vizsgálatára.
- *
- * @param array $groups Az ellenőrizni kívánt csoport
- * @param array $table_full Az ellenőrzéshez használt kívánságmátrix
- */
- function debug_groups_selftest($groups, $table_full)
- {
- for ($i = 0; $i < count($groups); $i++)
- {
- $u1 = $u2 = $groups[$i]["users"];
- reset($u1);
- // ide talán for jobb lenne egy sort() után
- while (list(, $u1v) = each($u1))
- {
- reset($u2);
- while (list(, $u2v) = each($u2))
- {
- if (($u1v != $u2v) && !isset($table_full[$u1v][$u2v]))
- {
- debug_echo("selftester: !isset[$u1v, $u2v]");
- }
- }
- }
- }
- //debug_echo("selftester end");
- }
-
-
- /** Csoport keresés csoportlistában
- *
- * Eldönti, hogy a megadott csoportlistában szerepel-e már valamilyen
- * csoport, benne van-e az adott csoporttömbben a $newg csoport.
- *
- * @param array $g A keresés alanya, csoporttöb
- * @param array $newg A keresett csoport
- * @return bool true, ha megtalálható a $g csoportömbben a $newg, egyébként false
- */
- function is_group($g, $newg)
- {
- sort($g);
- for ($i = 0; $i < count($g); $i++)
- {
- sort($g[$i]["users"]);
- }
- sort($g);
-
- $eq = false;
- for ($i = 0; $i < count($g); $i++)
- {
- if (!array_diffp($g[$i]["users"], $newg["users"]))
- {
- $eq = true;
- break; // igy gyorsabb, de ugye nem struktúrált... fene essen bele :)
- }
- }
-
- return $eq;
- }
-
- /** Csoport beosztása egy szobába
- *
- * Egy csoport minden tagját elhelyezi a megadott szobában.
- *
- * @param array $group A csoport, tömb a csoportba tartozó hallgatók azonosítóival
- * @param array $rd A szoba adatait tartalmazó tömb
- */
- function group_to_room($group, $rd)
- {
- global $database;
-
- if (room_freespace($rd["roomid"]) < count($group["users"]))
- {
- myerr("végzetes kivétel történt...");
- /* rosszul hívtuk meg a függvényt, biztos-ami-biztos alapon */
- }
-
- $log = sprintf("%s (%s):", $rd["rnum"], $rd["space"]);
-
- $roomid = $rd["roomid"];
- $u = $group["users"];
- reset($u);
- while (list(, $uid) = each($u))
- {
- szobaba_tesz($roomid, $uid);
- set_usedwish($uid);
- $log .= sprintf("%s; ", $uid);
- }
- debug_echo($log);
- }
-
- /** Azon csoportok kiszűrése, amelyekben szerepel a megadott felhasználó
- *
- * A megadott csoportokat tartalmazó tömbből meghagyja azokat, amelyek
- * nem tartalmazzák a $t tömbben lévő egyik felhasználói azonosítót sem.
- * Erre olyankor van szükség, amikor beosztottunk egy hallgatót, illetve
- * egy csoportot valamelyik szobába, de mivel egy hallgató több csoportban
- * is szerepelhet, ezért a többi olyan csoportot, amiben szerepel meg kell
- * szüntetni, hiszen egy embert csak egy szobába lehet beosztani.
- *
- * @param array $from A kezdeti csoportlista
- * @param int $t A törlendő hallgatói azonosító
- * @return array A megszűrt csoportlista
- */
- function drop_groupslike($from, $t)
- {
- sort($from);
- reset($from);
- for ($i = 0; $i < count($from); $i++)
- {
- $unset = false;
- reset($t);
- while (list(, $tid) = each($t))
- {
- if (array_search($tid, $from[$i]["users"]) !== false)
- {
- $unset = true;
- }
- }
- if ($unset)
- {
- unset($from[$i]);
- sort($from);
- $i--;
- }
- }
-
- return $from;
- }
-
- /** Csoportlista szűrése létszám alapján
- *
- * Kiszűri egy csoportlistából a megadott létszámú csoportokat.
- *
- * @param array $g A szűrendő csoport
- * @param int $space A keresett létszám
- */
- function groups_filter($g, $space)
- {
- $rg = array();
- reset($g);
- while (list(, $gdata) = each ($g))
- {
- if (count($gdata["users"]) == $space)
- {
- $rg[] = $gdata;
- }
-
- }
- return $rg;
- }
-
-
- ?>