user_data_generator.class.php 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418
  1. <?php
  2. /* For licensing terms, see /license.txt */
  3. /**
  4. * Class UserDataGenerator
  5. * Class to select, sort and transform object data into array data,
  6. * used for a student's general view
  7. * @author Bert Steppé
  8. * @package chamilo.gradebook
  9. */
  10. class UserDataGenerator
  11. {
  12. // Sorting types constants
  13. const UDG_SORT_TYPE = 1;
  14. const UDG_SORT_NAME = 2;
  15. const UDG_SORT_COURSE = 4;
  16. const UDG_SORT_CATEGORY = 8;
  17. const UDG_SORT_AVERAGE = 16;
  18. const UDG_SORT_SCORE = 32;
  19. const UDG_SORT_MASK = 64;
  20. const UDG_SORT_ASC = 128;
  21. const UDG_SORT_DESC = 256;
  22. private $items;
  23. private $userid;
  24. private $coursecodecache;
  25. private $categorycache;
  26. private $scorecache;
  27. private $avgcache;
  28. /**
  29. * UserDataGenerator constructor.
  30. * @param int $userid
  31. * @param array $evals
  32. * @param array $links
  33. */
  34. public function __construct($userid, $evals = array(), $links = array())
  35. {
  36. $this->userid = $userid;
  37. $result = array();
  38. foreach ($evals as $eval) {
  39. $toadd = true;
  40. $coursecode = $eval->get_course_code();
  41. if (isset($coursecode)) {
  42. $result = Result::load(null, $userid, $eval->get_id());
  43. if (count($result) == 0) {
  44. $toadd = false;
  45. }
  46. }
  47. if ($toadd) {
  48. $evals_filtered_copy = $evals;
  49. }
  50. }
  51. if (count($result) == 0) {
  52. $evals_filtered = $evals;
  53. } else {
  54. $evals_filtered = $evals_filtered_copy;
  55. }
  56. $this->items = array_merge($evals_filtered, $links);
  57. $this->coursecodecache = array();
  58. $this->categorycache = array();
  59. $this->scorecache = null;
  60. $this->avgcache = null;
  61. }
  62. /**
  63. * Get total number of items (rows)
  64. */
  65. public function get_total_items_count()
  66. {
  67. return count($this->items);
  68. }
  69. /**
  70. * Get actual array data
  71. * @return array 2-dimensional array - each array contains the elements:
  72. * 0: eval/link object
  73. * 1: item name
  74. * 2: course name
  75. * 3: category name
  76. * 4: average score
  77. * 5: student's score
  78. * 6: student's score as custom display (only if custom scoring enabled)
  79. */
  80. public function get_data(
  81. $sorting = 0,
  82. $start = 0,
  83. $count = null,
  84. $ignore_score_color = false
  85. ) {
  86. // do some checks on count, redefine if invalid value
  87. if (!isset($count)) {
  88. $count = count($this->items) - $start;
  89. }
  90. if ($count < 0) {
  91. $count = 0;
  92. }
  93. $allitems = $this->items;
  94. // sort users array
  95. if ($sorting & self::UDG_SORT_TYPE) {
  96. usort($allitems, array('UserDataGenerator', 'sort_by_type'));
  97. } elseif ($sorting & self::UDG_SORT_NAME) {
  98. usort($allitems, array('UserDataGenerator', 'sort_by_name'));
  99. } elseif ($sorting & self::UDG_SORT_COURSE) {
  100. usort($allitems, array('UserDataGenerator', 'sort_by_course'));
  101. } elseif ($sorting & self::UDG_SORT_CATEGORY) {
  102. usort($allitems, array('UserDataGenerator', 'sort_by_category'));
  103. } elseif ($sorting & self::UDG_SORT_AVERAGE) {
  104. // if user sorts on average scores, first calculate them and cache them
  105. foreach ($allitems as $item) {
  106. $this->avgcache[$item->get_item_type().$item->get_id()] = $item->calc_score();
  107. }
  108. usort($allitems, array('UserDataGenerator', 'sort_by_average'));
  109. } elseif ($sorting & self::UDG_SORT_SCORE) {
  110. // if user sorts on student's scores, first calculate them and cache them
  111. foreach ($allitems as $item) {
  112. $this->scorecache[$item->get_item_type().$item->get_id()]
  113. = $item->calc_score($this->userid);
  114. }
  115. usort($allitems, array('UserDataGenerator', 'sort_by_score'));
  116. } elseif ($sorting & self::UDG_SORT_MASK) {
  117. // if user sorts on student's masks, first calculate scores and cache them
  118. foreach ($allitems as $item) {
  119. $this->scorecache[$item->get_item_type().$item->get_id()]
  120. = $item->calc_score($this->userid);
  121. }
  122. usort($allitems, array('UserDataGenerator', 'sort_by_mask'));
  123. }
  124. if ($sorting & self::UDG_SORT_DESC) {
  125. $allitems = array_reverse($allitems);
  126. }
  127. // select the items we have to display
  128. $visibleitems = array_slice($allitems, $start, $count);
  129. // fill score cache if not done yet
  130. if (!isset($this->scorecache)) {
  131. foreach ($visibleitems as $item) {
  132. $this->scorecache[$item->get_item_type().$item->get_id()]
  133. = $item->calc_score($this->userid);
  134. }
  135. }
  136. // generate the data to display
  137. $scoredisplay = ScoreDisplay::instance();
  138. $data = array();
  139. foreach ($visibleitems as $item) {
  140. $row = array();
  141. $row[] = $item;
  142. $row[] = $item->get_name();
  143. $row[] = $this->build_course_name($item);
  144. $row[] = $this->build_category_name($item);
  145. $row[] = $this->build_average_column($item, $ignore_score_color);
  146. $row[] = $this->build_result_column($item, $ignore_score_color);
  147. if ($scoredisplay->is_custom()) {
  148. $row[] = $this->build_mask_column($item, $ignore_score_color);
  149. }
  150. $data[] = $row;
  151. }
  152. return $data;
  153. }
  154. /**
  155. * @param $item1
  156. * @param $item2
  157. * @return int
  158. */
  159. public function sort_by_type($item1, $item2)
  160. {
  161. if ($item1->get_item_type() == $item2->get_item_type()) {
  162. return $this->sort_by_name($item1, $item2);
  163. } else {
  164. return ($item1->get_item_type() < $item2->get_item_type() ? -1 : 1);
  165. }
  166. }
  167. /**
  168. * @param $item1
  169. * @param $item2
  170. * @return int
  171. */
  172. public function sort_by_course($item1, $item2)
  173. {
  174. $name1 = api_strtolower(
  175. $this->get_course_name_from_code_cached($item1->get_course_code())
  176. );
  177. $name2 = api_strtolower(
  178. $this->get_course_name_from_code_cached($item2->get_course_code())
  179. );
  180. return api_strnatcmp($name1, $name2);
  181. }
  182. /**
  183. * @param $item1
  184. * @param $item2
  185. * @return int
  186. */
  187. public function sort_by_category($item1, $item2)
  188. {
  189. $cat1 = $this->get_category_cached($item1->get_category_id());
  190. $cat2 = $this->get_category_cached($item2->get_category_id());
  191. $name1 = api_strtolower($this->get_category_name_to_display($cat1));
  192. $name2 = api_strtolower($this->get_category_name_to_display($cat2));
  193. return api_strnatcmp($name1, $name2);
  194. }
  195. /**
  196. * @param $item1
  197. * @param $item2
  198. * @return int
  199. */
  200. public function sort_by_name($item1, $item2)
  201. {
  202. return api_strnatcmp($item1->get_name(), $item2->get_name());
  203. }
  204. /**
  205. * @param $item1
  206. * @param $item2
  207. * @return int
  208. */
  209. public function sort_by_average($item1, $item2)
  210. {
  211. $score1 = $this->avgcache[$item1->get_item_type().$item1->get_id()];
  212. $score2 = $this->avgcache[$item2->get_item_type().$item2->get_id()];
  213. return $this->compare_scores($score1, $score2);
  214. }
  215. /**
  216. * @param $item1
  217. * @param $item2
  218. * @return int
  219. */
  220. public function sort_by_score($item1, $item2)
  221. {
  222. $score1 = $this->scorecache[$item1->get_item_type().$item1->get_id()];
  223. $score2 = $this->scorecache[$item2->get_item_type().$item2->get_id()];
  224. return $this->compare_scores($score1, $score2);
  225. }
  226. /**
  227. * @param $item1
  228. * @param $item2
  229. * @return int
  230. */
  231. public function sort_by_mask($item1, $item2)
  232. {
  233. $score1 = $this->scorecache[$item1->get_item_type().$item1->get_id()];
  234. $score2 = $this->scorecache[$item2->get_item_type().$item2->get_id()];
  235. return ScoreDisplay::compare_scores_by_custom_display($score1, $score2);
  236. }
  237. /**
  238. * @param $score1
  239. * @param $score2
  240. * @return int
  241. */
  242. public function compare_scores($score1, $score2)
  243. {
  244. if (!isset($score1)) {
  245. return (isset($score2) ? 1 : 0);
  246. } elseif (!isset($score2)) {
  247. return -1;
  248. } elseif (($score1[0] / $score1[1]) == ($score2[0] / $score2[1])) {
  249. return 0;
  250. } else {
  251. return (($score1[0] / $score1[1]) < ($score2[0] / $score2[1]) ? -1 : 1);
  252. }
  253. }
  254. /**
  255. * @param $item
  256. * @return mixed
  257. */
  258. private function build_course_name($item)
  259. {
  260. return $this->get_course_name_from_code_cached($item->get_course_code());
  261. }
  262. /**
  263. * @param $item
  264. * @return string
  265. */
  266. private function build_category_name($item)
  267. {
  268. $cat = $this->get_category_cached($item->get_category_id());
  269. return $this->get_category_name_to_display($cat);
  270. }
  271. /**
  272. * @param $item
  273. * @param $ignore_score_color
  274. * @return string
  275. */
  276. private function build_average_column($item, $ignore_score_color)
  277. {
  278. if (isset($this->avgcache)) {
  279. $avgscore = $this->avgcache[$item->get_item_type().$item->get_id()];
  280. } else {
  281. $avgscore = $item->calc_score();
  282. }
  283. $scoredisplay = ScoreDisplay::instance();
  284. $displaytype = SCORE_AVERAGE;
  285. /*if ($ignore_score_color)
  286. $displaytype |= SCORE_IGNORE_SPLIT;
  287. */
  288. return $scoredisplay->display_score($avgscore, $displaytype);
  289. }
  290. /**
  291. * @param $item
  292. * @param $ignore_score_color
  293. * @return string
  294. */
  295. private function build_result_column($item, $ignore_score_color)
  296. {
  297. $studscore = $this->scorecache[$item->get_item_type().$item->get_id()];
  298. $scoredisplay = ScoreDisplay::instance();
  299. $displaytype = SCORE_DIV_PERCENT;
  300. if ($ignore_score_color) {
  301. $displaytype |= SCORE_IGNORE_SPLIT;
  302. }
  303. return $scoredisplay->display_score(
  304. $studscore,
  305. $displaytype,
  306. SCORE_ONLY_DEFAULT
  307. );
  308. }
  309. /**
  310. * @param $item
  311. * @param $ignore_score_color
  312. * @return string
  313. */
  314. private function build_mask_column($item, $ignore_score_color)
  315. {
  316. $studscore = $this->scorecache[$item->get_item_type().$item->get_id()];
  317. $scoredisplay = ScoreDisplay::instance();
  318. $displaytype = SCORE_DIV_PERCENT;
  319. if ($ignore_score_color) {
  320. $displaytype |= SCORE_IGNORE_SPLIT;
  321. }
  322. return $scoredisplay->display_score(
  323. $studscore,
  324. $displaytype,
  325. SCORE_ONLY_CUSTOM
  326. );
  327. }
  328. /**
  329. * @param $coursecode
  330. * @return mixed
  331. */
  332. private function get_course_name_from_code_cached($coursecode)
  333. {
  334. if (isset($this->coursecodecache) &&
  335. isset($this->coursecodecache[$coursecode])
  336. ) {
  337. return $this->coursecodecache[$coursecode];
  338. } else {
  339. $name = CourseManager::getCourseNameFromCode($coursecode);
  340. $this->coursecodecache[$coursecode] = $name;
  341. return $name;
  342. }
  343. }
  344. /**
  345. * @param $category_id
  346. * @return null
  347. */
  348. private function get_category_cached($category_id)
  349. {
  350. if (isset($this->categorycache) &&
  351. isset($this->categorycache[$category_id])
  352. ) {
  353. return $this->categorycache[$category_id];
  354. } else {
  355. $cat = Category::load($category_id);
  356. if (isset($cat)) {
  357. $this->categorycache[$category_id] = $cat[0];
  358. return $cat[0];
  359. } else {
  360. return null;
  361. }
  362. }
  363. }
  364. /**
  365. * @param $cat
  366. * @return string
  367. */
  368. private function get_category_name_to_display($cat)
  369. {
  370. if (isset($cat)) {
  371. if ($cat->get_parent_id() == '0' || $cat->get_parent_id() == null) {
  372. return '';
  373. } else {
  374. return $cat->get_name();
  375. }
  376. } else {
  377. return '';
  378. }
  379. }
  380. }