phpDocumentor koliportal
[ class tree: koliportal ] [ index: koliportal ] [ all elements ]

Source for file lib.groups.php

Documentation is available at lib.groups.php

  1. <?php
  2. /** A groups tömbökön különböző műveletek végző függvények kódjai
  3. *
  4. * Itt azok a függvények találhatóak, amelyek a $groups tömbön végeznek
  5. * különféle műveleteket.
  6. *
  7. * @package koliportal
  8. * @author Karakó Miklós <palacsint_X_freemail.hu>
  9. * @copyright Copyright &copy; 2005, Karakó Miklós
  10. */
  11. /** Első-első kívánságot nem tartalmazó csoportok kiszűrése
  12. *
  13. * Kiszűri azokat a csoportokat, amelyek 1-1-es jelölés esetén csak az
  14. * egyik hallgatót tartalmazzák.
  15. *
  16. * 1-1-es jelölés: két diák egymást jelölte meg első helyen a
  17. * kívánságlistájukban.
  18. *
  19. * ST_HETEROGEN esetén azokat a csoportokat is kiszűri, amelyekben egyforma
  20. * neműek vannak.
  21. *
  22. * @param array $groups A szűrendő csoportok
  23. * @param array $table Használt kívánságmátrix
  24. * @param array $students A kívánságmátrixban található hallgatói
  25. * azonosítók folytonosan indexelve
  26. * @param int $stype Fiú-Lány 1-1 kívánsot keresünk-e? Ha igen,
  27. * akkor ST_HETEROGEN, más esetben ettől eltérő értéke legyen.
  28. *
  29. * @return array Megszűrt csoportlista
  30. */
  31. function strip_not11_groups($groups, $table, $students, $stype)
  32. {
  33. $found_wrong = false; // ha találtunk legalább egy hibás csoportot, akkor true lesz
  34.  
  35. // ellenőrzünk minden csoportot
  36. $gsize = count($groups);
  37. for ($i = 0; $i < $gsize; $i++)
  38. {
  39. $u = $groups[$i]["users"];
  40. sort($u);
  41.  
  42. $wrong_group = false; // ha hibás a csoport, akkor true lesz
  43. if (ST_HETEROGEN == $stype)
  44. {
  45. if ((2 != count($u)) || (get_student_st($u[0]) == get_student_st($u[1])))
  46. {
  47. $found_wrong = $wrong_group = true;
  48. }
  49. }
  50. for ($j = 0; $j < count($u); $j++)
  51. {
  52. // $fw a $j. user 1 helyen jelölt kívánsága
  53. $fw = find_wish($table, $students, $u[$j], 1);
  54. if (($fw !== false) && ($wrong_group === false))
  55. {
  56. /*
  57. // ez is jó, de a másik szebb
  58. if (isset($table[$fw][$u[$j]]) && ($table[$fw][$u[$j]] == 1)
  59. && (array_search($fw, $u) === false))
  60. {
  61. debug_echo("Elrontott csoport: $fw, " . $u[$j] );
  62. //$wrong_group = true;
  63. //die();
  64. }
  65. */
  66. // most fordítva is
  67. $fw_first = find_wish($table, $students, $fw, 1);
  68. if (($fw_first == $u[$j]) && (array_search($fw, $u) === false))
  69. {
  70. $wrong_group = true;
  71. $found_wrong = true;
  72. break;
  73. }
  74. }
  75. }
  76. if ($wrong_group === true)
  77. {
  78. //debug_echo("\teltávolítva...");
  79. unset($groups[$i]);
  80. //$i--;
  81. //sort($groups);
  82. //reset($groups);
  83. }
  84. }
  85.  
  86. // csak akkor szükséges, ha találtunk hibás csoportot (és töröltük ugye)
  87. if ($found_wrong)
  88. {
  89. sort($groups);
  90. reset($groups);
  91. }
  92. return $groups;
  93. }
  94. /** Kétfős csoportok kialakítása
  95. *
  96. * A megadott adatok alapján létrehoz egy tömböt, amelyek két fős csoportokat
  97. * tartalmaz. A csoportokat a $table tömb kölcsönös élei alapján rakja össze.
  98. * Egy csoport többször is szerepelhet a kimeneti tömbben, ezt később még
  99. * szűrni kell.
  100. *
  101. * @param array $table A kapcsolatokat tartalmazó táblázat
  102. * @param array $key A $table indexeihez tartozó valódi felhasználói azonosítók (users.sid)
  103. * @param int $stype A kapcsolat típusa. Jelenleg két részre van bonta: páros szoba és nem páros szoba
  104. * @return array A kétfős csoportokat tartalamzó tömb
  105. */
  106. function make_2groups($table, $keys, $stype)
  107. {
  108. $groups = array();
  109. $gindex = 1;
  110.  
  111. sort($keys);
  112. $maxij = count($keys);
  113. for ($i = 0; $i < $maxij; $i++)
  114. {
  115. for ($j = 0; $j < $maxij; $j++)
  116. {
  117. $u1 = $keys[$i];
  118. $u2 = $keys[$j];
  119. if (isset($table[$u1][$u2]) &&
  120. isset($table[$u2][$u1])
  121. )
  122. {
  123. $r1 = $table[$u1][$u2];
  124. $r2 = $table[$u2][$u1];
  125.  
  126. /* ez akkor lesz igaz:
  127. - ha nem páros csoportokat akarunk csinálni
  128. - vagy ha páros csoportot akarunk, és különböző neműek
  129. ha hamis, akkor ez nem ide való csoport
  130. */
  131. if ((ST_HETEROGEN != $stype) || (get_student_st($u1) != get_student_st($u2)))
  132. {
  133. $newgroup = array();
  134. $newgroup["users"][$u1] = $u1;
  135. $newgroup["users"][$u2] = $u2;
  136. /* ez még ráérne később, de nem jelent nagy plusz költséget */
  137. $newgroup["points"] = ($r1 + $r2);
  138. /* itt ellenőrizhetnénk, hogy van-e már ilyen csoport,
  139. de ahhoz mindig rendezgetni kellene a tömböket - a végén
  140. egy lépésben elvégezve jobb futásidőt kapunk */
  141. $groups[$gindex++] = $newgroup;
  142. }
  143. }
  144. }
  145. }
  146. sort($groups);
  147. reset($groups);
  148.  
  149. return $groups;
  150. }
  151.  
  152. /** 2-nél nagyobb létszámú csoportok létrehozása
  153. *
  154. * A megkapott, kétfős csoportokat próbálja meg kibővíteni mindig egy-egy
  155. * új hallgató hozzáadásával. Maximum $spacemax fős csoportokat hoz létre.
  156. *
  157. * @param array $groups Kiindulási csoportok
  158. * @param array $table Kívánságmátrix
  159. * @param array $students A kívánságmátrixban szereplő hallgatói azonosítók indexfolytonosan
  160. * @param int $spacemax Maximum ennyi fős csoportokat kell létrehozni
  161. */
  162. function make_ngroups($groups, $table, $students, $spacemax)
  163. {
  164. /* ilyenkor nincs mit csinálni */
  165. if ($spacemax == 2)
  166. {
  167. return $groups;
  168. }
  169. $maxij = count($students);
  170. for ($gi = 0; $gi < count($groups); $gi++)
  171. {
  172. /* minden user-t megpróbálunk hozzáadni a g1 csoporthoz */
  173. for ($i = 0; $i < $maxij; $i++)
  174. {
  175. $gc = $groups[$gi]; // ha új user került a csoportba, akkor is működjön ám!
  176. reset($gc);
  177. /* ha már bennevan az $i user a csoportban, akkor jöhet a következő
  178. optimalizálunk itt is, $spacemax-nál nagyobb csoportokra
  179. nincs szükség */
  180. if (!isset($gc["users"][$students[$i]]) && (count($gc["users"]) < $spacemax))
  181. {
  182. $sel_ok = true;
  183. /* kipróbáljuk, hogy létezik-e [g1user, $i] és [$i, $g1user] él a gráfban
  184. tehát hogy minden csoporttag bejelölte- az $i. diákot, mint leendő szobatárs
  185. ha nincs, akkor ez az ($i) user nem kerülhet be a csoportba */
  186. reset($gc["users"]);
  187. while (list(, $guser) = each($gc["users"]))
  188. {
  189. $k1 = $students[$i];
  190. $k2 = $guser;
  191. if (!isset($table[$k1][$k2]) || !isset($table[$k2][$k1]))
  192. {
  193. $sel_ok = false;
  194. /* innen breakelhetnénk is kifele */
  195. break;
  196. }
  197. }
  198. if ($sel_ok)
  199. {
  200. /* ilyenkor új csoportot csinálunk, mert:
  201. ABC és ABD is megjelölte egymást
  202. akkor először lesz AB, majd ABC, de ABD már nem lehet,
  203. ha BC nem jelölte meg egymást
  204. ezért lesz egy AB és egy ABC, amihez később még hozzájön
  205. egy ABD mindegyikre számolunk egy pontszámot,
  206. és majd kiderül melyik a nyerő
  207. */
  208. $end = count($groups); // csoportsorszám lesz
  209. $newgroup = array();
  210. $newgroup["users"] = $groups[$gi]["users"];
  211. $newgroup["users"][$students[$i]] = $students[$i];
  212. sort($newgroup["users"]);
  213. /* ezzel itt nagyon sokat lehet spórolni
  214. ha már van ilyen csoport, akkor ne adjuk hozzá */
  215. if (!is_group($groups, $newgroup))
  216. {
  217. $groups[$end] = $groups[$gi];
  218. $groups[$end]["users"][$students[$i]] = $students[$i];
  219. sort($groups);
  220. /* módosítani kelle a "points" -ot:
  221. *
  222. * ez még ráér később, mert lehetnek többszörös csoportokat,
  223. * amiket előbb kiszűrve csökkenthető a műveletek száma
  224. */
  225. }
  226. }
  227. }
  228. }
  229. }
  230. return $groups;
  231. }
  232. /** Többször jelenlévő csoportok törlése
  233. *
  234. * A függvény egy kivételével törli a $groups tömb azon elemeit,
  235. * amelyek ["users"] altömbjének azonos elemei vannak.
  236. * Folytonosan indexelt $groups tömb szükséges a helyes működéshez!
  237. *
  238. * @param array $groups Csoportlista
  239. * @return array Megszűrt csoportlista
  240. */
  241. function uniq_groups($groups)
  242. {
  243. for ($i = 0; $i < count($groups); $i++)
  244. {
  245. for ($j = $i + 1; $j < count($groups); $j++)
  246. {
  247. if (!array_diffp($groups[$i]["users"], $groups[$j]["users"]))
  248. {
  249. unset($groups[$j]);
  250. sort($groups);
  251. //debug_echo("groups $i == $j: true");
  252. $j--;
  253. } else {
  254. //debug_echo("groups $i == $j: false");
  255. }
  256. }
  257. //print_r($groups);
  258. }
  259. return $groups;
  260. }
  261.  
  262. /* sorrendezi a csoportokat, a belső "users" altömbbel együtt */
  263. /** Csoportok sorrendezése
  264. *
  265. * Sorrendezi a csoportokat, folyonos indexeléssel látja el mind a főtömböt,
  266. * mind az egyes altömbök "users" tömbjét.
  267. *
  268. * @param array $groups Sorrendezni kívánt csoport tömbje
  269. * @return array Rendezett csoportlista
  270. */
  271. function sort_groups($groups)
  272. {
  273. sort($groups);
  274. for ($i = 0; $i < count($groups); $i++)
  275. {
  276. sort($groups[$i]["users"]);
  277. }
  278. sort($groups); // újrasorrendezzük mert muszáj az előző sort()-ok miatt
  279. reset($groups);
  280. return $groups;
  281. }
  282.  
  283. /* összehasonlító funkció az usort()-hoz... két csoportot hasonlít össze
  284. * pontszám szerint
  285. */
  286. /** Két csoport összehasonlítása pontszám szerint
  287. *
  288. * Az usort() függvényhez szükséges segédfüggvény, amely két csoportot
  289. * hasonlít össze a pontszámuk szerint.
  290. *
  291. * @param array $a Az első csoport
  292. * @param array $b A második csoport
  293. * @return int Az usort() által várt 1, -1, vagy 0
  294. */
  295. function cmp_group_by_points($a, $b)
  296. {
  297. //var_dump($a);
  298. //var_dump($b);
  299. //die();
  300. if ($a["points"] > $b["points"])
  301. {
  302. return 1;
  303. }
  304. if ($a["points"] < $b["points"])
  305. {
  306. return -1;
  307. }
  308. if (count($a["users"]) > count($b["users"]))
  309. {
  310. return 1;
  311. }
  312. elseif (count($a["users"]) > count($b["users"]))
  313. {
  314. return -1;
  315. }
  316. else
  317. {
  318. return 0;
  319. }
  320. }
  321. /** Csoportok pontszámainak kiszámítása és sorrendezési
  322. *
  323. * Kiszámítja minden csoport pontszámát, majd a tömböt eszerint
  324. * sorba is rendezi. A pontszám jelenleg attól függ, hogy csoporttagok
  325. * hanyadik helyen jelölték meg egymás. A lista elejéhez közelebb eső
  326. * jelölések kevesebb pontot érnek, de növekvő sorrenbe lesznek rendezve
  327. * a csoportok a függvény végén, s majd a szobabeosztás is ez alapján fog
  328. * történni.
  329. *
  330. * @param array $groups Csoporttömb
  331. * @param array $table_full Kívánságmátrix
  332. * @return array Csoporttömb, pontszám szerint sorbarendezve
  333. */
  334. function calc_points($groups, $table_full)
  335. {
  336. // pontok kiszámítása minden csoporthoz!
  337. /* FIXME: ide kellene valami átlag is, amit figyelembe lehetne
  338. venni, ha egyébként azonos a pontszám. Például 100000-res szorzó
  339. mellett az átlagok összegét ki lehetne vonni a pontszámból.
  340. Még 6 fős csoportok esetén is (10000/6/(6-1) = 333) sem befolyásolná
  341. az értékét az átlag 10-szerese */
  342. for ($i = 0; $i < count($groups); $i++)
  343. {
  344. $p = 0;
  345. $avg = 0;
  346. $u1 = $u2 = $groups[$i]["users"];
  347. reset($u1);
  348. while (list(, $u1v) = each($u1))
  349. {
  350. reset($u2);
  351. while (list(, $u2v) = each($u2))
  352. {
  353. if ($u1v != $u2v)
  354. {
  355. $p += $table_full[$u1v][$u2v];
  356. }
  357. }
  358. $avg += get_average($u1v);
  359. }
  360. $c = count($groups[$i]["users"]);
  361. // eredeti:
  362. //$groups[$i]["points"] = $p * 1000 / $c / ($c - 1) ;
  363. $groups[$i]["points"] = $p * 1000 / $c - $avg ;
  364. }
  365. /* sorbarendezünk pontszám szerint */
  366. usort($groups, "cmp_group_by_points");
  367.  
  368. return $groups;
  369. }
  370. /** Csoportellenőrzés
  371. *
  372. * A függvény leellenőrzi, hogy tényleg mindenki belevaló-e a csoportba,
  373. * mindenki bejelölt-e mindenkit a csoportból. Fejlesztői (?) funkció, az
  374. * csoportképző algoritmus helyességének vizsgálatára.
  375. *
  376. * @param array $groups Az ellenőrizni kívánt csoport
  377. * @param array $table_full Az ellenőrzéshez használt kívánságmátrix
  378. */
  379. function debug_groups_selftest($groups, $table_full)
  380. {
  381. for ($i = 0; $i < count($groups); $i++)
  382. {
  383. $u1 = $u2 = $groups[$i]["users"];
  384. reset($u1);
  385. // ide talán for jobb lenne egy sort() után
  386. while (list(, $u1v) = each($u1))
  387. {
  388. reset($u2);
  389. while (list(, $u2v) = each($u2))
  390. {
  391. if (($u1v != $u2v) && !isset($table_full[$u1v][$u2v]))
  392. {
  393. debug_echo("selftester: !isset[$u1v, $u2v]");
  394. }
  395. }
  396. }
  397. }
  398. //debug_echo("selftester end");
  399. }
  400. /** Csoport keresés csoportlistában
  401. *
  402. * Eldönti, hogy a megadott csoportlistában szerepel-e már valamilyen
  403. * csoport, benne van-e az adott csoporttömbben a $newg csoport.
  404. *
  405. * @param array $g A keresés alanya, csoporttöb
  406. * @param array $newg A keresett csoport
  407. * @return bool true, ha megtalálható a $g csoportömbben a $newg, egyébként false
  408. */
  409. function is_group($g, $newg)
  410. {
  411. sort($g);
  412. for ($i = 0; $i < count($g); $i++)
  413. {
  414. sort($g[$i]["users"]);
  415. }
  416. sort($g);
  417. $eq = false;
  418. for ($i = 0; $i < count($g); $i++)
  419. {
  420. if (!array_diffp($g[$i]["users"], $newg["users"]))
  421. {
  422. $eq = true;
  423. break; // igy gyorsabb, de ugye nem struktúrált... fene essen bele :)
  424. }
  425. }
  426. return $eq;
  427. }
  428.  
  429. /** Csoport beosztása egy szobába
  430. *
  431. * Egy csoport minden tagját elhelyezi a megadott szobában.
  432. *
  433. * @param array $group A csoport, tömb a csoportba tartozó hallgatók azonosítóival
  434. * @param array $rd A szoba adatait tartalmazó tömb
  435. */
  436. function group_to_room($group, $rd)
  437. {
  438. global $database;
  439. if (room_freespace($rd["roomid"]) < count($group["users"]))
  440. {
  441. myerr("végzetes kivétel történt...");
  442. /* rosszul hívtuk meg a függvényt, biztos-ami-biztos alapon */
  443. }
  444. $log = sprintf("%s (%s):", $rd["rnum"], $rd["space"]);
  445. $roomid = $rd["roomid"];
  446. $u = $group["users"];
  447. reset($u);
  448. while (list(, $uid) = each($u))
  449. {
  450. szobaba_tesz($roomid, $uid);
  451. set_usedwish($uid);
  452. $log .= sprintf("%s; ", $uid);
  453. }
  454. debug_echo($log);
  455. }
  456.  
  457. /** Azon csoportok kiszűrése, amelyekben szerepel a megadott felhasználó
  458. *
  459. * A megadott csoportokat tartalmazó tömbből meghagyja azokat, amelyek
  460. * nem tartalmazzák a $t tömbben lévő egyik felhasználói azonosítót sem.
  461. * Erre olyankor van szükség, amikor beosztottunk egy hallgatót, illetve
  462. * egy csoportot valamelyik szobába, de mivel egy hallgató több csoportban
  463. * is szerepelhet, ezért a többi olyan csoportot, amiben szerepel meg kell
  464. * szüntetni, hiszen egy embert csak egy szobába lehet beosztani.
  465. *
  466. * @param array $from A kezdeti csoportlista
  467. * @param int $t A törlendő hallgatói azonosító
  468. * @return array A megszűrt csoportlista
  469. */
  470. function drop_groupslike($from, $t)
  471. {
  472. sort($from);
  473. reset($from);
  474. for ($i = 0; $i < count($from); $i++)
  475. {
  476. $unset = false;
  477. reset($t);
  478. while (list(, $tid) = each($t))
  479. {
  480. if (array_search($tid, $from[$i]["users"]) !== false)
  481. {
  482. $unset = true;
  483. }
  484. }
  485. if ($unset)
  486. {
  487. unset($from[$i]);
  488. sort($from);
  489. $i--;
  490. }
  491. }
  492. return $from;
  493. }
  494. /** Csoportlista szűrése létszám alapján
  495. *
  496. * Kiszűri egy csoportlistából a megadott létszámú csoportokat.
  497. *
  498. * @param array $g A szűrendő csoport
  499. * @param int $space A keresett létszám
  500. */
  501. function groups_filter($g, $space)
  502. {
  503. $rg = array();
  504. reset($g);
  505. while (list(, $gdata) = each ($g))
  506. {
  507. if (count($gdata["users"]) == $space)
  508. {
  509. $rg[] = $gdata;
  510. }
  511. }
  512. return $rg;
  513. }
  514. ?>

Documentation generated on Wed, 18 May 2005 19:24:35 +0200 by phpDocumentor 1.3.0RC3