CourseList.php

  1. 7.x classes/CourseList.php
  2. 6.x classes/CourseList.php
  3. 5.x custom/classes/CourseList.php

File

classes/CourseList.php
View source
  1. <?php
  2. require_once("ObjList.php");
  3. class CourseList extends ObjList
  4. {
  5. // This inherits most of its classes from ObjList,
  6. // but, it has to be able to do special functions
  7. // specific to Courses. Use parent:: to access
  8. // a parent function within ObjList.
  9. // Example: parent::indexOf();
  10. //public $arrayCourseIDList = array();
  11. /**
  12. * Used to cast a regular ObjList object into a CourseList.
  13. *
  14. * @param ObjList $obj
  15. *
  16. * @return CourseList
  17. */
  18. static public function cast(ObjList $obj)
  19. { // This can be used to cast a regular ObjList
  20. // into a CourseList object.
  21. // Use the syntax: CourseList::cast($x);
  22. $new_c_l = new CourseList();
  23. $new_c_l->array_list = $obj->array_list;
  24. $new_c_l->is_empty = $obj->is_empty;
  25. $new_c_l->reset_counter();
  26. return $new_c_l;
  27. }
  28. /**
  29. * Give every course in the list a minimum grade.
  30. *
  31. * @param string $min_grade
  32. */
  33. function assign_min_grade($min_grade)
  34. {
  35. // Go through the list and give every course the specified
  36. // min grade.
  37. $min_grade = strtoupper($min_grade);
  38. for ($t = 0; $t < $this->count; $t++)
  39. {
  40. $course = $this->array_list[$t];
  41. $course->min_grade = $min_grade;
  42. }
  43. }
  44. /**
  45. * Go through the list and find any course whose hours are greater
  46. * than $hours. Make that course "unselectable." Used in the groups.
  47. *
  48. * For example, if a student may only select 3 hours from a group, we don't
  49. * want to give them the option of selecting a 5 hour course. But we also
  50. * don't want to remove that course either. We want to display it so they
  51. * know it was an option (and possibly need to substitute or move things
  52. * around if they need it).
  53. *
  54. * Returns TRUE if anything got assigned, FALSE if nothing got assigned.
  55. *
  56. * @param int $hours
  57. *
  58. * @return bool
  59. */
  60. function assign_unselectable_courses_with_hours_greater_than($hours)
  61. {
  62. // Go through the list and assign bool_unselectable courses whose minHour
  63. // is greater than $hours.
  64. // Returns TRUE if it did assign something,
  65. // false if it didn't.
  66. $bool_assigned = false;
  67. for ($t = 0; $t < $this->count; $t++)
  68. {
  69. $course = $this->array_list[$t];
  70. if ($course->subject_id == "")
  71. {
  72. $course->load_descriptive_data();
  73. }
  74. if ($course->min_hours > $hours)
  75. {
  76. $course->bool_unselectable = true;
  77. $bool_assigned = true;
  78. }
  79. }
  80. return $bool_assigned;
  81. }
  82. /**
  83. * Find and return a specific course from the list.
  84. *
  85. * @param int $course_id
  86. * - The course_id to look for. Do not set if using
  87. * $use_course.
  88. *
  89. * @param int $term_id
  90. * - The term_id for the course to look for. Do not set if using
  91. * $use_course.
  92. *
  93. * @param bool $bool_transfer
  94. * - Is the course we are looking for a transfer course? Do not
  95. * use if using $use_course.
  96. *
  97. * @param bool $bool_exclude_substitutions
  98. * - If TRUE, we will not consider courses which have been used
  99. * in a substitution.
  100. *
  101. * @param Course $use_course
  102. * - Optional. If you already have a course object which can be used
  103. * as a template to search for, specify it here. Otherwise, set to
  104. * NULL. If using this, then $course_id, $term_id, and $bool_transfer
  105. * will be ignored.
  106. *
  107. * @param Int $sub_req_by_degree_id
  108. * - Optional. If set, we will only exclude substituted courses if they were substitutions made for this degree_id. Leave 0 if not sure
  109. * what to use.
  110. *
  111. *
  112. * @return Course
  113. */
  114. function find_specific_course($course_id = 0, $term_id = 0, $bool_transfer = false, $bool_exclude_substitutions = true, Course $use_course = null, $sub_req_by_degree_id = 0)
  115. {
  116. if ($use_course != null && is_object($use_course))
  117. {
  118. $course_id = $use_course->course_id;
  119. $term_id = $use_course->term_id;
  120. $bool_transfer = $use_course->bool_transfer;
  121. }
  122. // Look through the array for a course with this id, termId, and
  123. // transfer credit status.
  124. for ($t = 0; $t < $this->count; $t++)
  125. {
  126. $course = $this->array_list[$t];
  127. $check_course_id = $course->course_id;
  128. if ($bool_transfer == true && is_object($course->course_transfer))
  129. {
  130. $check_course_id = $course->course_transfer->course_id;
  131. }
  132. if ($check_course_id == $course_id && $course->term_id == $term_id && $course->bool_transfer == $bool_transfer)
  133. {
  134. if ($bool_exclude_substitutions == true)
  135. {
  136. if ($course->get_bool_substitution($sub_req_by_degree_id) == TRUE)
  137. {
  138. continue;
  139. }
  140. }
  141. return $course;
  142. }
  143. }
  144. return false;
  145. }
  146. /**
  147. * Call the $course->load_course_descriptive_data() on
  148. * every course in the list.
  149. *
  150. */
  151. function load_course_descriptive_data()
  152. {
  153. // Call the load_descriptive_data() method
  154. // for every course in the list.
  155. for ($t = 0; $t < $this->count; $t++)
  156. {
  157. $course = $this->array_list[$t];
  158. $course->load_descriptive_data();
  159. }
  160. }
  161. /**
  162. * Call the $course->load_descriptive_transfer_data() on
  163. * every course in the list. Meant for transfer courses.
  164. *
  165. */
  166. function load_descriptive_transfer_data($student_id = 0)
  167. {
  168. for ($t = 0; $t < $this->count; $t++)
  169. {
  170. $course = $this->array_list[$t];
  171. $course->load_descriptive_transfer_data($student_id);
  172. }
  173. }
  174. /**
  175. * Using the parent's function of find_all_matches, this
  176. * will return a CourseList of all courses which match
  177. * the Course object.
  178. *
  179. * @param Course $course_c
  180. * @return CourseList
  181. */
  182. function find_all_matches(stdClass $course_c)
  183. {
  184. if (!$list_matches = parent::find_all_matches($course_c))
  185. {
  186. return false;
  187. }
  188. $list_matches = CourseList::cast($list_matches);
  189. return $list_matches;
  190. }
  191. /**
  192. * Returns a match to the Course courseC which does
  193. * not have any courses fulfilling it. Usefull for finding
  194. * course requirement matches in a list which have not
  195. * yet been assigned.
  196. *
  197. * @param Course $course_c
  198. * @return Course
  199. */
  200. function find_first_unfulfilled_match(Course $course_c)
  201. {
  202. // Returns match to courseC which does not have
  203. // any courses fulfilling it. Useful for finding
  204. // course requirement matches in a list which have not
  205. // yet been assigned.
  206. for ($t = 0; $t < $this->count; $t++)
  207. {
  208. if ($this->array_list[$t]->equals($course_c) && $this->array_list[$t]->course_list_fulfilled_by->is_empty == true)
  209. {
  210. return $this->array_list[$t];
  211. }
  212. }
  213. return false;
  214. }
  215. /**
  216. * Returns a CourseList of courses with this specific grade.
  217. */
  218. function find_courses_with_grade($grade = 'C') {
  219. $rtn = new CourseList();
  220. for ($t = 0; $t < $this->count; $t++)
  221. {
  222. $course = $this->array_list[$t];
  223. if ($course->grade == $grade) {
  224. $rtn->add($course);
  225. }
  226. }
  227. return $rtn;
  228. }
  229. /**
  230. * Go through the list and set the $bool_exclude_repeat flag to TRUE
  231. * for all matches of $course in this list.
  232. *
  233. * Returns FALSE if no matches could be found.
  234. *
  235. * @param Course $course
  236. * @return bool
  237. */
  238. function mark_repeats_exclude(Course $course, $degree_id = 0, Course $except_for_course = NULL)
  239. {
  240. // Set the bool_exclude_repeat flag to TRUE for all
  241. // occurances of $course in THIS list.
  242. if (!$list_matches = parent::find_all_matches($course))
  243. {
  244. return false;
  245. }
  246. $list_matches = CourseList::cast($list_matches);
  247. $list_matches->reset_counter();
  248. while($list_matches->has_more())
  249. {
  250. $c = $list_matches->get_next();
  251. if ($except_for_course != NULL) {
  252. if ($c == $except_for_course) {
  253. // Skip it.
  254. continue;
  255. }
  256. }
  257. $c->set_bool_exclude_repeat($degree_id, TRUE);
  258. }
  259. return true;
  260. }
  261. /**
  262. * Find a list of matches to Course courseC, which fulfill
  263. * the min_grade requirement, ordered by most recently taken.
  264. *
  265. * Returns FALSE if no matches were found, else it will
  266. * return the matched Course object.
  267. *
  268. * @return Course
  269. */
  270. function find_most_recent_match(Course $course_c, $min_grade = "", $bool_mark_repeats_exclude = false, $degree_id = 0, $bool_skip_already_assigned_to_degree = TRUE, $bool_skip_subs = FALSE, $group_id = 0)
  271. {
  272. // Get a list of all matches to courseC, and
  273. // then order them by the most recently taken course
  274. // first.
  275. // We should, too, check for minimum grades here
  276. // as well.
  277. $min_grade = strtoupper($min_grade);
  278. if (!$list_matches = parent::find_all_matches($course_c))
  279. {
  280. return false;
  281. }
  282. $list_matches = CourseList::cast($list_matches);
  283. if ($list_matches->is_empty)
  284. {
  285. return false;
  286. }
  287. // If we are here, then we have at least one match.
  288. // Meaning, we have at least one class which might fit
  289. // into this course requirement.
  290. // Sort the courses into most recently taken first.
  291. $list_matches->sort_most_recent_first();
  292. $withdrew_grades = csv_to_array(variable_get_for_school("withdrew_grades", "W", $course_c->school_id));
  293. // So, now that it's sorted, we should look through the list,
  294. // checking the min grade requirements (if any). When we find
  295. // a good one, we will select it.
  296. $list_matches->reset_counter();
  297. while($list_matches->has_more())
  298. {
  299. $c = $list_matches->get_next();
  300. if ($c->get_bool_exclude_repeat($degree_id, TRUE))
  301. {
  302. continue;
  303. }
  304. if ($bool_skip_subs && $c->get_bool_substitution($degree_id) == TRUE) {
  305. // It is already being used in a substitution for this degree id, so we skip it.
  306. continue;
  307. }
  308. //////////////////////////////////////////
  309. /// Check for min grade, etc, here.
  310. if (!$c->meets_min_grade_requirement_of(null, $min_grade))
  311. {
  312. //if ($min_grade == "B-") fpm("[did not meet min grade requirement of $min_grade :: $c->subject_id $c->course_num $c->grade");
  313. if ($bool_mark_repeats_exclude == true)
  314. {
  315. // Since this course does not meet the min_grade,
  316. // check to see if it may be repeated. If it can't,
  317. // then we must mark ALL previous attempts at this
  318. // course as being excluded from further consideration.
  319. //
  320. // We don't do this consideration if they simply
  321. // withdrew from a course...
  322. if (in_array($c->grade, $withdrew_grades)) { continue; }
  323. if (floatval($c->min_hours) == 0 || $c->min_hours == "") {
  324. $c->load_descriptive_data(); // make sure we get hour data for this course.
  325. }
  326. if ($c->repeat_hours <= $c->min_hours)
  327. {
  328. // No repeats.
  329. $this->mark_repeats_exclude($c, $degree_id);
  330. return false;
  331. } else {
  332. // Repeats allowed, so just continue.
  333. continue;
  334. }
  335. } // if bool_mark_repeats_exclude == true
  336. else {
  337. // We did NOT meet the min_grade requirement!
  338. //if ($min_grade == "B-") fpm("[did not meet min grade requirement of $min_grade :: $c->subject_id $c->course_num $c->grade");
  339. $c = FALSE;
  340. continue;
  341. }
  342. } // course did NOT meet the min_grade requirement
  343. else {
  344. // The course DID meet the min grade requirement.
  345. // Are we supposed to exclude repeats?
  346. if ($bool_mark_repeats_exclude) {
  347. // Make sure the course isn't allowed to be repeated...
  348. if ($c->repeat_hours <= $c->min_hours) {
  349. // No repeats allowed.
  350. $this->mark_repeats_exclude($c, $degree_id, $c);
  351. }
  352. }
  353. }
  354. // Has the course already been assigned [to this degree]?
  355. if ($bool_skip_already_assigned_to_degree && $c->get_has_been_assigned_to_degree_id($degree_id)) {
  356. // Yes, it's been assigned, so we can just skip it.
  357. continue;
  358. }
  359. // At this point, we are going to invoke a hook, to give add-on modules
  360. // one last chance to "skip" the course or not.
  361. $bool_can_proceed = TRUE;
  362. $result = invoke_hook("courselist_find_match_allow_course", array($c, $course_c, $list_matches, $degree_id, $group_id));
  363. foreach ($result as $m => $val) {
  364. // If *any* module said FALSE, then we must skip this course and not assign it to this degree.
  365. if ($val === FALSE) $bool_can_proceed = $val;
  366. }
  367. if (!$bool_can_proceed) {
  368. continue;
  369. }
  370. return $c;
  371. }
  372. return FALSE;
  373. }
  374. /**
  375. * Find a list of matches to Course courseC, which fulfill
  376. * the min_grade requirement, ordered by most best grade first.
  377. *
  378. * Returns FALSE if no matches were found, else it will
  379. * return the matched Course object.
  380. *
  381. *
  382. * @return Course
  383. */
  384. function find_best_grade_match(Course $course_c, $min_grade = "", $bool_mark_repeats_exclude = false, $degree_id = 0, $bool_skip_already_assigned_to_degree = TRUE, $bool_skip_subs = FALSE, $group_id = 0)
  385. {
  386. $min_grade = strtoupper($min_grade);
  387. $list_matches = parent::find_all_matches($course_c);
  388. if (!$list_matches) {
  389. return false;
  390. }
  391. $list_matches = CourseList::cast($list_matches);
  392. //sort the courses into largest hours first, so equal grades will be sorted by hours
  393. $list_matches->sort_largest_hours_first();
  394. // Sort the courses into best grade first.
  395. $list_matches->sort_best_grade_first(NULL, $course_c->school_id);
  396. if (!$list_matches || $list_matches->is_empty)
  397. {
  398. return false;
  399. }
  400. // If we are here, then we have more than one match.
  401. // Meaning, we have more than one class which might fit
  402. // into this course requirement.
  403. $withdrew_grades = csv_to_array(variable_get_for_school("withdrew_grades", "W", $course_c->school_id));
  404. // So, now that it's sorted, we should look through the list,
  405. // checking the min grade requirements (if any). When we find
  406. // a good one, we will select it.
  407. $list_matches->reset_counter();
  408. while($list_matches->has_more())
  409. {
  410. $c = $list_matches->get_next();
  411. if ($c->get_bool_exclude_repeat($degree_id) == TRUE)
  412. {
  413. continue;
  414. }
  415. // Has the course already been assigned [to this degree]?
  416. if ($bool_skip_already_assigned_to_degree && $c->get_has_been_assigned_to_degree_id($degree_id)) {
  417. // Yes, it's been assigned, so we can just skip it.
  418. continue;
  419. }
  420. if ($bool_skip_subs && $c->get_bool_substitution($degree_id) == TRUE) {
  421. // It is already being used in a substitution for this degree id, so we skip it.
  422. continue;
  423. }
  424. //////////////////////////////////////////
  425. /// Check for min grade, etc, here.
  426. if (!$c->meets_min_grade_requirement_of(null, $min_grade))
  427. {
  428. if ($bool_mark_repeats_exclude == true)
  429. {
  430. // Since this course does not meet the min_grade,
  431. // check to see if it may be repeated. If it can't,
  432. // then we must mark ALL previous attempts at this
  433. // course as being excluded from further consideration.
  434. // (ULM policy on repeats).
  435. // We don't do this consideration if they simply
  436. // withdrew from a course...
  437. if (in_array($c->grade, $withdrew_grades)) { continue; }
  438. if (floatval($c->min_hours) == 0 || $c->min_hours == "") {
  439. $c->load_descriptive_data(); // make sure we get hour data for this course.
  440. }
  441. if ($c->repeat_hours <= $c->min_hours)
  442. {
  443. // No repeats.
  444. $this->mark_repeats_exclude($c, $degree_id);
  445. return false;
  446. } else {
  447. // Repeats allowed, so just continue.
  448. continue;
  449. }
  450. } // if bool_mark_repeats_exclude == true
  451. else {
  452. // We did NOT meet the min_grade requirement!
  453. $c = FALSE;
  454. continue;
  455. }
  456. } // course did NOT meet the min_grade requirement
  457. else {
  458. // The course DID meet the min grade requirement.
  459. // Are we supposed to exclude repeats?
  460. if ($bool_mark_repeats_exclude) {
  461. // Make sure the course isn't allowed to be repeated...
  462. if ($c->repeat_hours <= $c->min_hours) {
  463. // No repeats allowed.
  464. $this->mark_repeats_exclude($c, $degree_id, $c);
  465. }
  466. }
  467. }
  468. // At this point, we are going to invoke a hook, to give add-on modules
  469. // one last chance to "skip" the course or not.
  470. $bool_can_proceed = TRUE;
  471. $result = invoke_hook("courselist_find_match_allow_course", array($c, $course_c, $list_matches, $degree_id, $group_id));
  472. foreach ($result as $m => $val) {
  473. // If *any* module said FALSE, then we must skip this course and not assign it to this degree.
  474. if ($val === FALSE) $bool_can_proceed = $val;
  475. }
  476. if (!$bool_can_proceed) {
  477. continue;
  478. }
  479. return $c;
  480. } // while
  481. return FALSE;
  482. } // find_best_grade_match
  483. /**
  484. * Sorts best-grade-first, as defined by the setting "grade_order", which is a CSV of
  485. * grades, best-first. Ex: A, B, C, D, F
  486. *
  487. * If the student object is set to a student, we will use that's student's best grade for a course, rather
  488. * than the actual course's grade. Generally, this can be left as set to null. This is only for when we are
  489. * trying to organize a list of courses into the grade order, based on what a student has taken. For example, if we want
  490. * to order a Group's list of courses based on what the student has taken and the grades they made.
  491. *
  492. */
  493. function sort_best_grade_first(Student $student = NULL, $school_id = 0) {
  494. if ($student) {
  495. $school_id = $student->school_id;
  496. }
  497. $temp = csv_to_array(variable_get_for_school("grade_order", "AMID,BMID,CMID,DMID,FMID,A,B,C,D,F,W,I", $school_id));
  498. // We will use array_flip to get back an assoc array where the grades are the keys and the indexes are the values.
  499. $temp = array_flip($temp);
  500. // Go through the grades and convert the integers to strings, padd with zeros so that everything is at least 3 digits.
  501. $grades = array();
  502. foreach ($temp as $grade => $val) {
  503. $grades[$grade] = str_pad((string)$val, 3, "0", STR_PAD_LEFT);
  504. }
  505. // We now have our grades array just how we want it. Best grade has lowest value. Worst grade has highest value.
  506. $unknown_grade_value = 999; // sort to the very end, in other words.
  507. $student_grade_score = 0;
  508. // We are going to go through our courses and, based on the grade, assign them a value.
  509. $tarray = array();
  510. for ($t = 0; $t < $this->count; $t++) {
  511. // $t is the index for the array_list, keep in mind.
  512. $c = $this->array_list[$t];
  513. $use_grade = $c->grade;
  514. if ($student != null) {
  515. $use_grade = $student->get_best_grade_for_course($c);
  516. if (!$use_grade) $use_grade = "";
  517. }
  518. @$grade_value = $grades[$use_grade];
  519. if ($grade_value == "") {
  520. // Couldn't find this grade in our array, so give it the unknown value.
  521. $grade_value = $unknown_grade_value;
  522. }
  523. $student_grade_score += intval($grade_value);
  524. // Add to a string in array so we can sort easily using a normal sort operation.
  525. $tarray[$grade_value][] = $c;
  526. }
  527. // Sort best-grade-first:
  528. ksort($tarray,SORT_NUMERIC);
  529. // Okay, now go back through tarray and re-construct a new CourseList
  530. $new_list = new CourseList();
  531. foreach ($tarray as $per_grade_courses) {
  532. foreach ($per_grade_courses as $course) {
  533. $new_list->add($course);
  534. }
  535. }
  536. // Okay, now $new_list should contain the correct values.
  537. // We will transfer over the reference.
  538. $this->array_list = $new_list->array_list;
  539. // And we are done!
  540. if ($student != NULL) {
  541. // Return the "student grade score" for this list of courses.
  542. return $student_grade_score;
  543. }
  544. }
  545. /**
  546. * Remove courses from THIS list which appear in listCourses under
  547. * these conditions:
  548. * - the listCourses->"assigned_to_group_id" != $group_id
  549. * This function is being used primarily with $list_courses being the
  550. * list of courses that students have taken.
  551. * Also checking substitutions for courses substituted into groups.
  552. * @param CourseList $list_courses
  553. * @param int $group_id
  554. * @param bool $bool_keep_repeatable_courses
  555. * @param SubstitutionList $list_substitutions
  556. * @param $degree_id The degree id to look for. If it's -1, then ignore it. If it's 0, use the course's req_by_degree_id.
  557. */
  558. function remove_previously_fulfilled(CourseList $list_courses, $group_id, $bool_keep_repeatable_courses = true, $list_substitutions = NULL, $degree_id = 0)
  559. {
  560. $rtn_list = new CourseList();
  561. for ($t = 0; $t < $this->count; $t++)
  562. {
  563. $course = $this->array_list[$t];
  564. if ($bool_keep_repeatable_courses == true)
  565. { // We can always keep repeatable courses in the list.
  566. if ($course->repeat_hours > $course->min_hours)
  567. {
  568. $rtn_list->add($course);
  569. continue;
  570. }
  571. }
  572. // Has the course been substituted?
  573. if ($list_substitutions != NULL && $test_sub = $list_substitutions->find_requirement($course, false, -1))
  574. {
  575. // it WAS substituted, so we should NOT add it to our
  576. // rtnList.
  577. // We should only skip it if the test_sub's degree_id matches the one supplied...
  578. if ($degree_id >= 0) {
  579. if ($test_sub->assigned_to_degree_id == $degree_id) {
  580. continue;
  581. }
  582. }
  583. else if ($degree_id < 0) {
  584. // degree_id is -1, so we don't care what degree it was assigned to.
  585. continue;
  586. }
  587. }
  588. // Okay, now check if $course is anywhere in $list_courses
  589. //if ($test_course = $list_courses->find_match($course))
  590. // Instead of using simply find_match(), which does not allow for any hook interventions, switch to using find_best_match.
  591. // Thanks for Logan Buth for this.
  592. if ($test_course = $list_courses->find_best_match($course, '', FALSE, $degree_id, TRUE, FALSE, $group_id))
  593. {
  594. // Yes, it found a match.
  595. // I am taking out this part where I say if it is in
  596. // this group then we can keep it. I think that shouldn't
  597. // be in.
  598. // This course is in another group, so do nothing
  599. // and skip it.
  600. // perhaps the course is on the degreePlan in excess with a W
  601. // or F?
  602. if (!$test_course->meets_min_grade_requirement_of(null, "D"))
  603. {
  604. // Meaning, this was a failed attempt, so we can add
  605. // our original course back in.
  606. $rtn_list->add($course);
  607. continue;
  608. }
  609. // perhaps this course was purposefully excluded from
  610. // this list because it did not meet the min grade
  611. // requirements? If this is the case, $course should
  612. // still appear in THIS list.
  613. if (!$test_course->meets_min_grade_requirement_of($course))
  614. {
  615. // Meaning, this was attempt did not meet the
  616. // min grade of the original requirement, so we can add
  617. // our original requirement back in.
  618. $rtn_list->add($course);
  619. continue;
  620. }
  621. } else {
  622. // The course was NOT found in the courseList,
  623. // so its safe to add it back in.
  624. $rtn_list->add($course);
  625. }
  626. }
  627. $this->array_list = $rtn_list->array_list;
  628. $this->reset_counter();
  629. }
  630. /**
  631. * Return an array of all the course_id's in this course_list.
  632. */
  633. function get_course_id_array() {
  634. $rtn = array();
  635. for ($t = 0; $t < $this->count; $t++)
  636. {
  637. $course = $this->array_list[$t];
  638. $rtn[$course->course_id] = TRUE;
  639. }
  640. return $rtn;
  641. }
  642. /**
  643. * Returns an array containing the unique subject_id's of
  644. * the courses in this list. Its assumed to be ordered
  645. * already!
  646. *
  647. * @param bool $bool_ignore_excluded
  648. * @return array
  649. */
  650. function get_course_subjects($bool_ignore_excluded = true)
  651. {
  652. // returns an array containing the unique subject_id's
  653. // of the courses in this list.
  654. // IMPORTANT: The list is assumed to be ordered already! Either
  655. // alphabetically or reverse alphabetically.
  656. $old_subject_id = "";
  657. $rtn_array = array();
  658. for ($t = 0; $t < $this->count; $t++)
  659. {
  660. $course = $this->array_list[$t];
  661. if ($course->subject_id == "")
  662. {
  663. $course->load_descriptive_data();
  664. }
  665. // Go through all valid names for this course.
  666. for ($x = 0; $x < count($course->array_valid_names); $x++)
  667. {
  668. $temp = explode("~",$course->array_valid_names[$x]);
  669. $subj = strtoupper($temp[0]);
  670. if (in_array($subj, $rtn_array))
  671. { // skip ones with subjects we have already looked at.
  672. continue;
  673. }
  674. if (intval($course->db_exclude) === 1) {
  675. continue;
  676. }
  677. // probably because it was excluded.
  678. if ($subj != $course->subject_id) {
  679. continue;
  680. }
  681. // We have a new subject. Add it to the array.
  682. $rtn_array[] = $subj;
  683. }
  684. }
  685. return $rtn_array;
  686. }
  687. /**
  688. * Go through the courseList and take out any course
  689. * which does not have the $subject as its subject_id.
  690. *
  691. * @param string $subject
  692. * @param bool $bool_reassign_valid_name
  693. * - If set to TRUE, we will look at other possible valid names
  694. * for this course. If we find one, we will reassign the course's
  695. * subject_id and course_num to the new valid name.
  696. *
  697. */
  698. function exclude_all_subjects_except($subject, $bool_reassign_valid_name = true)
  699. {
  700. $new_course_list = new CourseList();
  701. for ($t = 0; $t < $this->count; $t++)
  702. {
  703. $course = $this->array_list[$t];
  704. if ($course->subject_id == $subject)
  705. {
  706. $new_course_list->add($course);
  707. continue;
  708. }
  709. // Not the right subject-- but perhaps the course has another
  710. // valid name with this subject? Ex: CSCI 373 and MATH 373.
  711. if ($bool_reassign_valid_name == true && count($course->array_valid_names) > 1)
  712. {
  713. for ($x = 0; $x < count($course->array_valid_names); $x++)
  714. {
  715. if (strstr($course->array_valid_names[$x], $subject))
  716. {
  717. $temp = explode("~",$course->array_valid_names[$x]);
  718. $course->subject_id = $temp[0];
  719. $course->course_num = $temp[1];
  720. $new_course_list->add($course);
  721. continue;
  722. }
  723. }
  724. }
  725. }
  726. // Now, transfer ownership of the arraylist.
  727. $this->array_list = $new_course_list->array_list;
  728. }
  729. /**
  730. * This re-sorts the CourseList so that fulfilled courses
  731. * are first, in alphabetical order, followed by
  732. * unfulfilled courses, in alphabetical order.
  733. * This is most useful for making the groups
  734. * show up correctly.
  735. *
  736. */
  737. function sort_fulfilled_first_alphabetical()
  738. {
  739. $tarray = array();
  740. for ($t = 0; $t < $this->count; $t++)
  741. {
  742. //if (!is_object($this->array_list[$t]->courseFulfilledBy))
  743. if ($this->array_list[$t]->course_list_fulfilled_by->is_empty == true)
  744. { // Skip if not fulfilled.
  745. continue;
  746. }
  747. $c = $this->array_list[$t];
  748. $str = "$c->subject_id ~~ $c->course_num ~~ $t";
  749. array_push($tarray,$str);
  750. }
  751. sort($tarray);
  752. $new_list = new CourseList();
  753. for($t = 0; $t < count($tarray); $t++)
  754. {
  755. $temp = explode(" ~~ ",$tarray[$t]);
  756. $i = $temp[2];
  757. $new_list->add($this->array_list[$i]);
  758. }
  759. // Alright, now we do it again, but with unfulfilled courses.
  760. $tarray = array();
  761. for ($t = 0; $t < $this->count; $t++)
  762. {
  763. //if (is_object($this->array_list[$t]->courseFulfilledBy))
  764. if ($this->array_list[$t]->course_list_fulfilled_by->is_empty != true)
  765. { // Skip if fulfilled.
  766. continue;
  767. }
  768. $c = $this->array_list[$t];
  769. $str = "$c->subject_id ~~ $c->course_num ~~ $t";
  770. array_push($tarray,$str);
  771. }
  772. sort($tarray);
  773. $new_list2 = new CourseList();
  774. for($t = 0; $t < count($tarray); $t++)
  775. {
  776. $temp = explode(" ~~ ",$tarray[$t]);
  777. $i = $temp[2];
  778. $new_list2->add($this->array_list[$i]);
  779. }
  780. // Now, combine the two lists.
  781. $new_list->add_list($new_list2);
  782. // And, transfer the newList into this list.
  783. $this->array_list = $new_list->array_list;
  784. }
  785. /**
  786. * This re-sorts the CourseList so that advised courses
  787. * are last, in alphabetical order, preceeded by
  788. * unfulfilled courses, in alphabetical order.
  789. *
  790. *
  791. */
  792. function sort_advised_last_alphabetical()
  793. {
  794. $tarray = array();
  795. for ($t = 0; $t < $this->count; $t++)
  796. {
  797. if ($this->array_list[$t]->bool_advised_to_take == true)
  798. { // Skip if not fulfilled.
  799. continue;
  800. }
  801. $c = $this->array_list[$t];
  802. $str = "$c->subject_id ~~ $c->course_num ~~ $t";
  803. array_push($tarray,$str);
  804. }
  805. sort($tarray);
  806. // Alright, now we do it again, but with advised courses.
  807. $t2array = array();
  808. for ($t = 0; $t < $this->count; $t++)
  809. {
  810. if ($this->array_list[$t]->bool_advised_to_take == false)
  811. { // Skip if not advised
  812. continue;
  813. }
  814. $c = $this->array_list[$t];
  815. $str = "$c->subject_id ~~ $c->course_num ~~ $t";
  816. array_push($t2array,$str);
  817. }
  818. sort($t2array);
  819. $t3array = array_merge($tarray, $t2array);
  820. $new_list = new CourseList();
  821. for($t = 0; $t < count($t3array); $t++)
  822. {
  823. $temp = explode(" ~~ ",$t3array[$t]);
  824. $i = $temp[2];
  825. $new_list->add($this->array_list[$i]);
  826. }
  827. // And, transfer the newList into this list.
  828. $this->array_list = $new_list->array_list;
  829. }
  830. /**
  831. * This function will resort this courselist for which a substitution
  832. * has been made in listSubstitutions.
  833. *
  834. * @param SubstitutionList $list_substitutions
  835. * @param int $group_id
  836. */
  837. function sort_substitutions_first($list_substitutions, $group_id = 0)
  838. {
  839. // This will sort courses in a list for which
  840. // a substitution has been made in listSubstitutions.
  841. // It will place those courses at the top of the list.
  842. $top_array = array();
  843. // Since I need the indexes, I will have to go through the array
  844. // myself...
  845. // array to keep track of all the substitutions that have been used for this list (Logan's change ticket 2291)
  846. $used_substitution_ids = array();
  847. for ($t = 0; $t < $this->count; $t++) {
  848. $c = $this->array_list[$t];
  849. // So-- does this course have a substitution somewhere in
  850. // the list (for the supplied groupID) ?
  851. // supply the list of used ids, so they are not reused in this list. (Logan's change ticket 2291)
  852. if ($substitution = $list_substitutions->find_requirement($c, true, $group_id,0,$used_substitution_ids))
  853. {
  854. // yes, there is a sub for this group (or bare degree plan)
  855. //mark the substitution so it doesn't get used again (Logan's change ticket 2291)
  856. $used_substitution_ids[] = $substitution->db_substitution_id;
  857. $top_array[] = $t;
  858. }
  859. }
  860. // Okay, we now have, in the topArray, a list of indexes which should
  861. // appear at the top.
  862. $new_list = new CourseList();
  863. for ($j = 0; $j < count($top_array); $j++)
  864. {
  865. $new_list->add($this->array_list[$top_array[$j]]);
  866. }
  867. // Now, add everything else in the array (except indecies
  868. // appearing in topArray)
  869. for ($t = 0; $t < $this->count; $t++)
  870. {
  871. if (in_array($t, $top_array))
  872. {
  873. continue;
  874. }
  875. $new_list->add($this->array_list[$t]);
  876. }
  877. $this->array_list = $new_list->array_list;
  878. $new_list->reset_counter();
  879. }
  880. /**
  881. * This will sort so that courses with the smallest hours
  882. * (first trying hours_awarded, then min_hours)
  883. * are at the top of the list. If the list contains more
  884. * than one course with a set of hours (like there are 30
  885. * courses all worth 3 hours) then it orders those as
  886. * most-recently-taken first.
  887. *
  888. */
  889. function sort_smallest_hours_first()
  890. {
  891. $tarray = array();
  892. // Since I need the indexes, I will have to go through the array
  893. // myself...
  894. for ($t = 0; $t < $this->count; $t++)
  895. {
  896. $c = $this->array_list[$t];
  897. $hours = $c->get_hours_awarded();
  898. if (floatval($hours) == 0)
  899. {
  900. $hours = $c->min_hours*1;
  901. }
  902. $str = "$hours ~~ $t";
  903. array_push($tarray,$str);
  904. }
  905. // Now, sort the array...
  906. //print_pre(print_r($tarray));
  907. sort($tarray);
  908. //print_pre(print_r($tarray));
  909. // Now, convert the array back into a list of courses.
  910. $new_list = new CourseList();
  911. for($t = 0; $t < count($tarray); $t++)
  912. {
  913. $temp = explode(" ~~ ",$tarray[$t]);
  914. $i = $temp[1];
  915. $new_list->add($this->array_list[$i]);
  916. }
  917. // Okay, now $new_list should contain the correct values.
  918. // We will transfer over the reference.
  919. $this->array_list = $new_list->array_list;
  920. } // sort_smallest_hours_first
  921. /*
  922. * Sort the courses of this list by number of hours descending.
  923. * Order of courses with the same number of hours is preserved.
  924. */
  925. function sort_largest_hours_first() {
  926. $sort_list = array();
  927. // go through the courses, creating an array keyed by hours.
  928. for ($t = 0; $t < count($this->array_list); $t++) {
  929. $hrs = $this->array_list[$t]->get_hours();
  930. if ($this->array_list[$t]->bool_ghost_hour) $hrs = 0;
  931. $hrs = "$hrs"; // force into a string so hours with decimals are preserved. Prevents warning in PHP 8
  932. $sort_list[$hrs][] = $this->array_list[$t];
  933. }
  934. //sort the array in order of hours descending
  935. krsort($sort_list,SORT_NUMERIC);
  936. //clear the internal array, then refill it with the now sorted courses.
  937. $this->array_list = array();
  938. foreach ($sort_list as $courses) {
  939. foreach ($courses as $course) {
  940. $this->array_list[] = $course;
  941. }
  942. }
  943. $this->reset_counter();
  944. }
  945. /**
  946. * This method will sort by the most recently taken
  947. * courses (determined by the term_id).
  948. * The easiest way I can think to do this is to temporarily
  949. * put their term_id's and index#'s into an array, and then
  950. * have PHP sort the array itself. PHP's sorting algorithm
  951. * is faster than anything I can program right now, anyway.
  952. *
  953. * @param bool $bool_maintain_alpha_order
  954. */
  955. function sort_most_recent_first($bool_maintain_alpha_order = true)
  956. {
  957. $tarray = array();
  958. // Since I need the indexes, I will have to go through the array
  959. // myself...
  960. for ($t = 0; $t < $this->count; $t++)
  961. {
  962. $c = $this->array_list[$t];
  963. $cn = "";
  964. if ($bool_maintain_alpha_order == true)
  965. {
  966. // We say 1000- the course number in order to give
  967. // us the complement of the number. That is so it will
  968. // reverse-sort in the correct order. Strange, but it fixes
  969. // a small display issue where PHYS 207 and PHYS 209, taken at
  970. // the same time, causes PHYS 209 to be displayed first.
  971. // We also reverse the subject_id, again, so that
  972. // MATH will be sorted above ZOOL, when taken at the same time.
  973. // This might not work at all, though...
  974. // TODO: The 1000 - course_num bit doesn't work (throws a warning) if the course_num
  975. // is non-numeric. Ex: 301A. Let's instead use the same strrev() function on course_num, but we put it in quotes
  976. // to guarantee it gets evaluated as a string.
  977. //$cn = strrev($c->subject_id) . "," . (1000 - $c->course_num);
  978. $cn = strrev($c->subject_id) . "," . strrev("$c->course_num");
  979. }
  980. $str = "$c->term_id ~~ $cn ~~ $t";
  981. array_push($tarray,$str);
  982. }
  983. // Now, sort the array...
  984. rsort($tarray);
  985. // Now, convert the array back into a list of courses.
  986. $new_list = new CourseList();
  987. for($t = 0; $t < count($tarray); $t++)
  988. {
  989. $temp = explode(" ~~ ",$tarray[$t]);
  990. $i = $temp[2];
  991. $new_list->add($this->array_list[$i]);
  992. }
  993. // Okay, now $new_list should contain the correct values.
  994. // We will transfer over the reference.
  995. $this->array_list = $new_list->array_list;
  996. }
  997. /**
  998. * Convienence function. It simply calls sort_alphabetical_order(), but
  999. * passes the boolean value to make it be reversed.
  1000. *
  1001. */
  1002. function sort_reverse_alphabetical_order()
  1003. {
  1004. $this->sort_alphabetical_order(true);
  1005. }
  1006. /**
  1007. * Sorts the courses based on their db_degree_requirement_id value
  1008. */
  1009. function sort_degree_requirement_id() {
  1010. $sort_list = array();
  1011. // go through the courses, creating an array keyed by db_degree_requirement_id.
  1012. for ($t = 0; $t < count($this->array_list); $t++) {
  1013. $id = intval($this->array_list[$t]->db_degree_requirement_id);
  1014. $sort_list[$id][] = $this->array_list[$t];
  1015. }
  1016. //sort the array in order ascending
  1017. ksort($sort_list,SORT_NUMERIC);
  1018. //clear the internal array, then refill it with the now sorted courses.
  1019. $this->array_list = array();
  1020. foreach ($sort_list as $courses) {
  1021. foreach ($courses as $course) {
  1022. $this->array_list[] = $course;
  1023. }
  1024. }
  1025. $this->reset_counter();
  1026. }
  1027. /**
  1028. * Sorts the courses based on their db_group_requirement_id value
  1029. */
  1030. function sort_group_requirement_id() {
  1031. $sort_list = array();
  1032. // go through the courses, creating an array keyed by db_degree_requirement_id.
  1033. for ($t = 0; $t < count($this->array_list); $t++) {
  1034. $id = (string) $this->array_list[$t]->db_group_requirement_id; // not necessarily an integer, don't cast as one.
  1035. // make sure that $id is at least 20 digits, padding 0's on the left, so that the sort works even if the id is a different
  1036. // number of digits.
  1037. $id = str_pad($id, 20, "0", STR_PAD_LEFT);
  1038. $sort_list[$id][] = $this->array_list[$t];
  1039. }
  1040. //sort the array in order ascending
  1041. ksort($sort_list);
  1042. //clear the internal array, then refill it with the now sorted courses.
  1043. $this->array_list = array();
  1044. foreach ($sort_list as $courses) {
  1045. foreach ($courses as $course) {
  1046. $this->array_list[] = $course;
  1047. }
  1048. }
  1049. $this->reset_counter();
  1050. }
  1051. /**
  1052. * Sorts the course list into alphabetical order. If load_descriptive_data()
  1053. * has not already been called for each course, it will call it.
  1054. *
  1055. * @param bool $bool_reverse_order
  1056. * - If set to TRUE, the list will be in reverse order.
  1057. *
  1058. * @param unknown_type $bool_only_transfers
  1059. * - Only sort the transfer courses.
  1060. *
  1061. * @param unknown_type $bool_set_array_index
  1062. * - If set to true, it will set the $course->array_index value
  1063. * to the index value in $this's array_list array.
  1064. * @param new_split_subs_higher_priority_in_degree_id
  1065. * - If the course is a split substitution for the supplied degree_id, then give it a higher "priority" so it will
  1066. * sort above courses with identical names.
  1067. *
  1068. */
  1069. function sort_alphabetical_order($bool_reverse_order = false, $bool_only_transfers = false, $bool_set_array_index = false, $subs_higher_prority_in_degree_id = 0, $bool_include_degree_sort = FALSE)
  1070. {
  1071. // Sort the list into alphabetical order, based
  1072. // on the subject_id and course_num.
  1073. $tarray = array();
  1074. // Since I need the indexes, I will have to go through the array
  1075. // myself...
  1076. for ($t = 0; $t < $this->count; $t++)
  1077. {
  1078. $c = NULL;
  1079. if (isset($this->array_list[$t])) {
  1080. $c = $this->array_list[$t];
  1081. }
  1082. if ($c == NULL) continue;
  1083. // If this is a transfer credit, make sure we load it's information
  1084. if ($c->bool_transfer == TRUE && is_object($c->course_transfer)) {
  1085. if ($c->course_transfer->subject_id == '') {
  1086. $c->course_transfer->load_descriptive_transfer_data();
  1087. }
  1088. if ($c->subject_id == '') {
  1089. $c->subject_id = $c->course_transfer->subject_id;
  1090. $c->course_num = $c->course_transfer->course_num;
  1091. }
  1092. }
  1093. if ($c->subject_id == "")
  1094. {
  1095. $c->load_descriptive_data();
  1096. }
  1097. $priority = 5; // default sort priority for courses with identical names.
  1098. if ($subs_higher_prority_in_degree_id > 0) {
  1099. if (@$c->details_by_degree_array[$subs_higher_prority_in_degree_id]["bool_substitution_new_from_split"] == TRUE
  1100. || @$c->details_by_degree_array[$subs_higher_prority_in_degree_id]["bool_substitution_split"] == TRUE
  1101. || @$c->details_by_degree_array[$subs_higher_prority_in_degree_id]["bool_substitution"] == TRUE) {
  1102. //fpm("here for $c->subject_id $c->course_num");
  1103. $priority = 3; // lower priority so it sorts higher in the list.
  1104. }
  1105. }
  1106. // Make $t at least 5 characters long, padded with zeroes on the left, so sorting works correctly. We are using it to
  1107. // find out our index later, but it is throwing off the sorting when courses have the same name. For example,
  1108. // if a course is from a split sub.
  1109. $tpad = str_pad("$t",5,"0",STR_PAD_LEFT);
  1110. $degree_title = "n"; // Default.
  1111. $degree_advising_weight = "0000";
  1112. if ($bool_include_degree_sort) {
  1113. // Find the actual degree title for this course.
  1114. if (intval($c->req_by_degree_id) > 0) {
  1115. // Get the degree title...
  1116. $dtitle = @$GLOBALS["fp_temp_degree_titles"][$c->req_by_degree_id];
  1117. $dweight = intval(@$GLOBALS["fp_temp_degree_advising_weights"][$c->req_by_degree_id]);
  1118. if ($dtitle == "" || $dweight == "" || $dweight == 0) {
  1119. $t_degree_plan = new DegreePlan($c->req_by_degree_id);
  1120. $t_degree_plan->load_descriptive_data();
  1121. $dtitle = $t_degree_plan->get_title2(TRUE, TRUE);
  1122. $dweight = $t_degree_plan->db_advising_weight;
  1123. $GLOBALS["fp_temp_degree_titles"][$c->req_by_degree_id] = $dtitle . " "; //save for next time.
  1124. $GLOBALS["fp_temp_degree_advising_weights"][$c->req_by_degree_id] = $dweight . " "; //save for next time.
  1125. }
  1126. $degree_title = fp_get_machine_readable($dtitle); // make it machine readable. No funny characters.
  1127. $degree_advising_weight = str_pad($dweight, 4, "0", STR_PAD_LEFT);
  1128. }
  1129. }
  1130. if ($bool_only_transfers == true)
  1131. {
  1132. // Rarer. We only want to sort the transfer credits. If the course doesn not
  1133. // have transfers, don't skip, just put in the original. Otherwise, we will be using
  1134. // the transfer credit's SI and CN.
  1135. if (is_object($c->course_transfer))
  1136. {
  1137. $str = $degree_advising_weight . " ~~ " . $degree_title . " ~~ " . $c->course_transfer->subject_id . " ~~ " . $c->course_transfer->course_num ." ~~ $priority ~~ $tpad";
  1138. } else {
  1139. // There was no transfer!
  1140. $str = "$degree_advising_weight ~~ $degree_title ~~ $c->subject_id ~~ $c->course_num ~~ $priority ~~ $tpad";
  1141. }
  1142. } else {
  1143. // This is the one which will be run most often. Just sort the list
  1144. // in alphabetical order.
  1145. $str = "$degree_advising_weight ~~ $degree_title ~~ $c->subject_id ~~ $c->course_num ~~ $priority ~~ $tpad";
  1146. }
  1147. array_push($tarray,$str);
  1148. }
  1149. // Now, sort the array...
  1150. //print_pre(print_r($tarray));
  1151. if ($bool_reverse_order == true)
  1152. {
  1153. rsort($tarray);
  1154. } else {
  1155. sort($tarray);
  1156. }
  1157. //print_pre(print_r($tarray));
  1158. // Now, convert the array back into a list of courses.
  1159. $new_list = new CourseList();
  1160. for($t = 0; $t < count($tarray); $t++)
  1161. {
  1162. $temp = explode(" ~~ ",$tarray[$t]);
  1163. $i = intval($temp[5]);
  1164. if ($bool_set_array_index == true)
  1165. {
  1166. $this->array_list[$i]->array_index = $i;
  1167. }
  1168. $new_list->add($this->array_list[$i]);
  1169. }
  1170. // Okay, now $new_list should contain the correct values.
  1171. // We will transfer over the reference.
  1172. $this->array_list = $new_list->array_list;
  1173. }
  1174. /**
  1175. * Returns an array of db_group_requirement_id's from the courses
  1176. * in this list.
  1177. *
  1178. * @return array
  1179. */
  1180. function get_group_requirement_id_array()
  1181. {
  1182. // Return an array of db_group_requirement_id's
  1183. // from the courses in this list, indexed by the
  1184. // id's.
  1185. $rtn_array = array();
  1186. for ($t = 0; $t < $this->count; $t++)
  1187. {
  1188. $course = $this->array_list[$t];
  1189. $rtn_array[$course->db_group_requirement_id] = true;
  1190. }
  1191. return $rtn_array;
  1192. }
  1193. /**
  1194. * Returns TRUE if this list has a course which contains
  1195. * $id for it's db_group_requirement_id property.
  1196. *
  1197. * @param int $id
  1198. * - This is the id to test for.
  1199. *
  1200. * @return bool
  1201. */
  1202. function contains_group_requirement_id($id)
  1203. {
  1204. // Returns true if the list has a course
  1205. // which contains $id for it's db_group_requirement_id.
  1206. // False if it cannot be found.
  1207. for ($t = 0; $t < $this->count; $t++)
  1208. {
  1209. $course = $this->array_list[$t];
  1210. if ($course->db_group_requirement_id == $id)
  1211. {
  1212. return true;
  1213. }
  1214. }
  1215. return false;
  1216. }
  1217. /**
  1218. * Returns the first course in the list
  1219. * which the user may select for advising. This
  1220. * method is used by the popup window to determine
  1221. * what exactly is the first element of the course list.
  1222. * (so it can make that radio button checked).
  1223. *
  1224. * Returns FALSE if it cannot find a selectable course.
  1225. *
  1226. * @return Course
  1227. */
  1228. function find_first_selectable()
  1229. {
  1230. /*
  1231. */
  1232. $temp_i = $this->i; // preserve the counter.
  1233. $this->reset_counter();
  1234. while($this->has_more())
  1235. {
  1236. $c = $this->get_next();
  1237. if ($c->bool_advised_to_take == true)
  1238. {
  1239. continue;
  1240. }
  1241. if (!$c->course_list_fulfilled_by->is_empty)
  1242. {
  1243. continue;
  1244. }
  1245. if ($c->bool_unselectable == true)
  1246. {
  1247. continue;
  1248. }
  1249. // $c is our valid course...
  1250. $this->i = $temp_i;
  1251. //print_pre($c->to_string());
  1252. return $c;
  1253. }
  1254. $this->i = $temp_i;
  1255. return false;
  1256. }
  1257. /**
  1258. * Returns TRUE if there is at least one course in this list which
  1259. * is selected (for advising).
  1260. *
  1261. * @return bool
  1262. */
  1263. function has_any_course_selected()
  1264. {
  1265. /*
  1266. Returns TRUE if there is at least one course
  1267. in this list which is "selected." FALSE, otherwise.
  1268. */
  1269. $temp_i = $this->i; // preserve the counter.
  1270. $this->reset_counter();
  1271. $rtn = false;
  1272. while($this->has_more())
  1273. {
  1274. $c = $this->get_next();
  1275. if ($c->bool_selected == true)
  1276. {
  1277. $rtn = true;
  1278. break;
  1279. }
  1280. }
  1281. $this->i = $temp_i;
  1282. return $rtn;
  1283. }
  1284. /**
  1285. * Mark every course in this list as bool_has_been_displayed = true.
  1286. * Used for making sure we don't display the same course twice on
  1287. * screen.
  1288. *
  1289. * Returns FALSE if we did not mark any courses.
  1290. *
  1291. * @param int $semester_num
  1292. * - If > -1, we will first make sure the course
  1293. * falls into this semesterNum. This way we can only
  1294. * perform this operation on a particular semester.
  1295. *
  1296. * @return bool
  1297. */
  1298. function mark_as_displayed($semester_num = -1)
  1299. {
  1300. $temp_i = $this->i; // preserve the counter.
  1301. $this->reset_counter();
  1302. $rtn = false;
  1303. while($this->has_more())
  1304. {
  1305. $c = $this->get_next();
  1306. if ($semester_num != -1)
  1307. { // A semesterNum was specified.
  1308. // Make sure the course is in the correct semester.
  1309. if ($c->assigned_to_semester_num != $semester_num)
  1310. {
  1311. continue;
  1312. }
  1313. }
  1314. $c->bool_has_been_displayed = true;
  1315. $rtn = true;
  1316. }
  1317. $this->i = $temp_i;
  1318. return $rtn;
  1319. }
  1320. /**
  1321. * Returns a CourseList of all the courses matching course_id
  1322. * that has bool_has_been_assigned == TRUE for the requested degree
  1323. *
  1324. * @param int $course_id
  1325. * @return CourseList
  1326. */
  1327. function get_previous_assignments($course_id, $degree_id = 0)
  1328. {
  1329. // Return a courseList of all the times a course matching
  1330. // course_id has the bool_has_been_assigned set to TRUE.
  1331. $rtn_list = new CourseList();
  1332. for ($t = 0; $t < $this->count; $t++)
  1333. {
  1334. $course = $this->array_list[$t];
  1335. if ($course->course_id == $course_id && $course->get_has_been_assigned_to_degree_id($degree_id) == true)
  1336. {
  1337. $rtn_list->add($course);
  1338. }
  1339. }
  1340. return $rtn_list;
  1341. }
  1342. /**
  1343. * Find the "best" match for this course, based on what
  1344. * the university considers a best match.
  1345. * This largely has to do with repeats.
  1346. * If the student has more than one credit, what is
  1347. * the "best" match?
  1348. *
  1349. * For example, at ULM we consider the best match to be the
  1350. * most recent that meets the minimum requirements.
  1351. * Other schools might simply take the best grade.
  1352. *
  1353. *
  1354. * @return Course
  1355. */
  1356. function find_best_match(Course $course_c, $min_grade = "", $bool_mark_repeats_exclude = false, $degree_id = 0, $bool_skip_already_assigned_to_degree = TRUE, $bool_skip_subs = FALSE, $group_id = 0)
  1357. {
  1358. $rtn = FALSE;
  1359. $min_grade = strtoupper($min_grade);
  1360. $school_id = $course_c->school_id;
  1361. // We will look at the course_repeat_policy to determine which type of search to do on this list.
  1362. $course_repeat_policy = variable_get_for_school("course_repeat_policy", "most_recent_exclude_previous", $school_id);
  1363. if ($course_repeat_policy == "best_grade_exclude_others") {
  1364. // Search for best grade, exclude other attempts.
  1365. $rtn = $this->find_best_grade_match($course_c, $min_grade, TRUE, $degree_id, $bool_skip_already_assigned_to_degree, $bool_skip_subs, $group_id);
  1366. }
  1367. else {
  1368. // Search for most recent first, possibly mark previous as excluded.
  1369. $rtn = $this->find_most_recent_match($course_c, $min_grade, $bool_mark_repeats_exclude, $degree_id, $bool_skip_already_assigned_to_degree, $bool_skip_subs, $group_id);
  1370. }
  1371. return $rtn;
  1372. }
  1373. /**
  1374. * Adds the supplied CourseList to the bottom of $this's list.
  1375. *
  1376. * @param CourseList $course_l
  1377. */
  1378. function add_list(CourseList $course_l) {
  1379. $c = count($course_l->array_list);
  1380. for ($t = 0; $t < $c; $t++)
  1381. {
  1382. $this->add($course_l->array_list[$t]);
  1383. }
  1384. }
  1385. /**
  1386. * Returns hour many hours are in $this CourseList.
  1387. *
  1388. * @param string $requirement_type
  1389. * - If specified, we will only count courses which match this
  1390. * requirement_type.
  1391. *
  1392. * @param bool $bool_use_ignore_list
  1393. * @return int
  1394. */
  1395. function count_hours($requirement_type = "", $bool_use_ignore_list = false, $bool_correct_ghost_hour = true, $bool_force_zero_hours_to_one_hour = false, $bool_exclude_all_transfer_credits = FALSE, $degree_id = 0)
  1396. {
  1397. // Returns how many hours are being represented in this courseList.
  1398. // A requirement type of "uc" is the same as "c"
  1399. // (university capstone is a core requirement)
  1400. $count = 0;
  1401. for ($t = 0; $t < $this->count; $t++)
  1402. {
  1403. $course = $this->array_list[$t];
  1404. // Does this course belong to the same degree we are interested in? If not, skip it.
  1405. if ($degree_id > 0) {
  1406. if ($course->req_by_degree_id != $degree_id && $course->get_has_been_assigned_to_degree_id($degree_id) != TRUE) continue;
  1407. }
  1408. $school_id = $course->school_id;
  1409. if ($bool_use_ignore_list == true)
  1410. {
  1411. // Do ignore some courses...
  1412. $temp_course_name = $course->subject_id . " " . $course->course_num;
  1413. // Check in our settings to see if we should ignore this course
  1414. // (configured in /custom/settings.php)
  1415. if (in_array($temp_course_name, csv_to_array(@variable_get_for_school("ignore_courses_from_hour_counts", "", $school_id)))) {
  1416. continue;
  1417. }
  1418. // Also, if the course's requirement_type is "x" it means we should ignore it.
  1419. if ($course->requirement_type == 'x') continue;
  1420. }
  1421. if ($course->get_bool_substitution_new_from_split($degree_id) == TRUE)
  1422. {
  1423. // Do not count the possible fragments that are created
  1424. // from a new substitution split. This is causing problems
  1425. // in getting accurate numbers on the pie charts.
  1426. // BUT-- only skip if this new fragment isn't also being
  1427. // substituted somewhere else!
  1428. if ($course->get_bool_substitution($degree_id) == FALSE)
  1429. { // not being used in another sub, so skip it.
  1430. continue;
  1431. }
  1432. }
  1433. $h_get_hours = $course->get_hours($degree_id);
  1434. if ($bool_correct_ghost_hour) {
  1435. // If this course has a ghosthour, then use the
  1436. // hours_awarded (probably 1). However, if it was substituted,
  1437. // then we actually want the 0 hour. Confusing, isn't it?
  1438. if ($course->bool_ghost_hour) {
  1439. $h_get_hours = $course->get_hours_awarded($degree_id);
  1440. }
  1441. }
  1442. if ($bool_force_zero_hours_to_one_hour) {
  1443. // We want to force anything with a 0 hour to be 1 hour.
  1444. // Helps when selecting 0 hour courses from groups.
  1445. if ($h_get_hours == 0) {
  1446. $h_get_hours = 1;
  1447. }
  1448. }
  1449. // Make sure we aren't trying to exclude any transfer credits.
  1450. if ($bool_exclude_all_transfer_credits) {
  1451. if ($course->bool_transfer) {
  1452. continue;
  1453. }
  1454. // Is this a requirement which has been fulfilled by a course? And if so, is THAT course a transfer?
  1455. if ($course->course_list_fulfilled_by->is_empty == false) {
  1456. $cc = $course->course_list_fulfilled_by->get_first();
  1457. if ($cc->bool_transfer) {
  1458. continue;
  1459. }
  1460. }
  1461. }
  1462. if ($requirement_type == "")
  1463. {
  1464. $count = $count + $h_get_hours;
  1465. }
  1466. else {
  1467. // Requirement Type not blank, so only count these hours
  1468. // if it has the set requirement type.
  1469. if ($course->requirement_type == $requirement_type)
  1470. {
  1471. $count = $count + $h_get_hours;
  1472. continue;
  1473. }
  1474. // For specifically "university capstone" courses (which have a 'u' in front)...
  1475. if ($course->requirement_type == "u" . $requirement_type)
  1476. {
  1477. $count = $count + $h_get_hours;
  1478. }
  1479. }
  1480. }
  1481. return $count;
  1482. }
  1483. /**
  1484. * Removes courses which have neither been fulfilled or advised.
  1485. *
  1486. */
  1487. function remove_unfulfilled_and_unadvised_courses()
  1488. {
  1489. // remove courses from THIS list
  1490. // which have not been fulfilled AND
  1491. // are not currently advised.
  1492. $rtn_list = new CourseList();
  1493. for ($t = 0; $t < $this->count; $t++)
  1494. {
  1495. $course = $this->array_list[$t];
  1496. if ($course->course_list_fulfilled_by->is_empty == false)
  1497. {
  1498. // something IS fulfilling it!
  1499. $rtn_list->add($course);
  1500. } else if ($course->bool_advised_to_take == true)
  1501. {
  1502. // Was not being fulfilled, but, it was advised
  1503. // to take.
  1504. $rtn_list->add($course);
  1505. }
  1506. }
  1507. $this->array_list = $rtn_list->array_list;
  1508. $this->reset_counter();
  1509. }
  1510. /**
  1511. * Removes courses from this list which have not been fulfilled
  1512. * (ther course_list_fulfilled_by is empty).
  1513. *
  1514. */
  1515. function remove_unfulfilled_courses()
  1516. {
  1517. // remove courses in THIS list
  1518. // which have nothing in their course_list_fulfilled_by
  1519. // object.
  1520. $rtn_list = new CourseList();
  1521. for ($t = 0; $t < $this->count; $t++)
  1522. {
  1523. $course = $this->array_list[$t];
  1524. if ($course->course_list_fulfilled_by->is_empty == false)
  1525. {
  1526. $rtn_list->add($course);
  1527. }
  1528. }
  1529. $this->array_list = $rtn_list->array_list;
  1530. $this->reset_counter();
  1531. }
  1532. /**
  1533. * Returns a clone CourseList of $this.
  1534. *
  1535. * @param bool $bool_return_new_courses
  1536. * - If set to TRUE, it will create new Course objects
  1537. * based on the course_id's of the ones in $this's list.
  1538. * If set to FALSE, this will add the exact same Course
  1539. * objects by reference to the new list.
  1540. *
  1541. * @return CourseList
  1542. */
  1543. function get_clone($bool_return_new_courses = FALSE)
  1544. {
  1545. // This will return a clone of this list.
  1546. // If boolReturnNewCourses is true, then it will
  1547. // return a new list of new instances of courses
  1548. // from this list.
  1549. $rtn_list = new CourseList();
  1550. for ($t = 0; $t < $this->count; $t++)
  1551. {
  1552. $course = $this->array_list[$t];
  1553. if ($bool_return_new_courses)
  1554. {
  1555. $new_course = new Course();
  1556. $new_course->course_id = $course->course_id;
  1557. $rtn_list->add($new_course);
  1558. } else {
  1559. $rtn_list->add($course);
  1560. }
  1561. }
  1562. return $rtn_list;
  1563. }
  1564. /**
  1565. * Returns a CourseList of all the fulfilled or advised courses
  1566. * in $this's list.
  1567. *
  1568. * @param bool $bool_return_new_courses
  1569. * - Works the same as get_clone()'s boolReturnNewCourses
  1570. * variable.
  1571. *
  1572. * @return Course
  1573. */
  1574. function get_fulfilled_or_advised($bool_return_new_courses = false)
  1575. {
  1576. $rtn_list = new CourseList();
  1577. for ($t = 0; $t < $this->count; $t++)
  1578. {
  1579. $course = $this->array_list[$t];
  1580. $add_course = $course;
  1581. if ($bool_return_new_courses == true)
  1582. {
  1583. $add_course = new Course();
  1584. $add_course->course_id = $course->course_id;
  1585. }
  1586. if ($course->bool_advised_to_take == true)
  1587. {
  1588. $rtn_list->add($add_course);
  1589. }
  1590. // Several ways to tell if a course is here by credit...
  1591. if (!$course->course_list_fulfilled_by->is_empty) {
  1592. $rtn_list->add($add_course);
  1593. }
  1594. else if ($course->grade != "") {
  1595. $rtn_list->add($add_course);
  1596. }
  1597. else if ($course->get_bool_substitution() == true) {
  1598. $rtn_list->add($add_course);
  1599. }
  1600. }
  1601. return $rtn_list;
  1602. }
  1603. /**
  1604. * Returns the number of courses in this list which have either
  1605. * been fulfilled or advised to take. It does not count hours,
  1606. * just the courses themselves.
  1607. *
  1608. * @return int
  1609. */
  1610. function count_fulfilled_or_advised()
  1611. {
  1612. // This function returns the number of courses in this
  1613. // courseList which is either fulfilled or has been advised
  1614. // to take. It does care about hours, just the number of
  1615. // courses themselves.
  1616. $count = 0;
  1617. for ($t = 0; $t < $this->count; $t++)
  1618. {
  1619. $course = $this->array_list[$t];
  1620. if ($course->bool_advised_to_take == true)
  1621. {
  1622. $count++;
  1623. }
  1624. // Several ways to tell if a course is here by credit...
  1625. if (!$course->course_list_fulfilled_by->is_empty)
  1626. {
  1627. $count++;
  1628. } else if ($course->grade != "") {
  1629. $count++;
  1630. } else if ($course->bool_substitution == true)
  1631. {
  1632. $count++;
  1633. }
  1634. }
  1635. return $count;
  1636. }
  1637. /**
  1638. * Returns a CourseList of courses which have bool_advised_to_take == true.
  1639. *
  1640. * @return CourseList
  1641. */
  1642. function get_advised_courses_list()
  1643. {
  1644. // Return a courseList object of courses in THIS
  1645. // list which have bool_advised_to_take == true.
  1646. $rtn_list = new CourseList();
  1647. for ($t = 0; $t < $this->count; $t++)
  1648. {
  1649. $course = $this->array_list[$t];
  1650. if ($course->bool_advised_to_take == true)
  1651. {
  1652. $rtn_list->add($course);
  1653. }
  1654. }
  1655. return $rtn_list;
  1656. }
  1657. /**
  1658. * Similar to count_hours, but this will only count courses
  1659. * which have been taken and have a grade.
  1660. *
  1661. * @param string $requirement_type
  1662. * - If set, we will only look for courses matching this requirement_type.
  1663. *
  1664. * @param bool $bool_use_ignore_list
  1665. * @param bool $bool_ignore_enrolled
  1666. * @return int
  1667. */
  1668. function count_credit_hours($requirement_type = "", $bool_use_ignore_list = false, $bool_ignore_enrolled = false, $bool_qpts_grades_only = FALSE, $bool_exclude_all_transfer_credits = FALSE, $degree_id = 0)
  1669. {
  1670. // Similar to count_hours, but this will only
  1671. // count courses which have been taken (have a grade).
  1672. $count = 0;
  1673. $qpts_grades = NULL;
  1674. $retake_grades = $enrolled_grades = NULL;
  1675. for ($t = 0; $t < $this->count; $t++)
  1676. {
  1677. $course = $this->array_list[$t];
  1678. // Does this course belong to the same degree we are interested in? If not, skip it.
  1679. if ($degree_id > 0) {
  1680. if ($course->req_by_degree_id != $degree_id && $course->get_has_been_assigned_to_degree_id($degree_id) != TRUE) continue;
  1681. }
  1682. $school_id = $course->school_id;
  1683. // Now that we have a school_id, let's figure out some variables....
  1684. if (!$retake_grades || !$enrolled_grades) {
  1685. $retake_grades = csv_to_array(variable_get_for_school("retake_grades", 'F,W,I', $school_id));
  1686. $enrolled_grades = csv_to_array(variable_get_for_school("enrolled_grades",'E', $school_id));
  1687. }
  1688. if (!$qpts_grades) {
  1689. $tlines = explode("\n", variable_get_for_school("quality_points_grades", "A ~ 4\nB ~ 3\nC ~ 2\nD ~ 1\nF ~ 0\nI ~ 0", $school_id));
  1690. foreach ($tlines as $tline) {
  1691. $temp = explode("~", trim($tline));
  1692. if (trim($temp[0]) != "") {
  1693. $qpts_grades[trim($temp[0])] = trim($temp[1]);
  1694. }
  1695. }
  1696. }
  1697. if ($bool_use_ignore_list == true)
  1698. {
  1699. // Do ignore some courses...
  1700. $temp_course_name = $course->subject_id . " " . $course->course_num;
  1701. // Check in our settings to see if we should ignore this course
  1702. // (configured in /custom/settings.php)
  1703. if (in_array($temp_course_name, csv_to_array(@variable_get_for_school("ignore_courses_from_hour_counts", "", $school_id)))) {
  1704. continue;
  1705. }
  1706. // Also, if the course's requirement_type is "x" it means we should ignore it.
  1707. if ($course->requirement_type == 'x') continue;
  1708. }
  1709. if ($bool_ignore_enrolled == true)
  1710. {
  1711. if (in_array($course->grade, $enrolled_grades)) {
  1712. continue;
  1713. }
  1714. }
  1715. // Only allowing grades which we have quality points for?
  1716. if ($bool_qpts_grades_only) {
  1717. if ($course->grade != "" && !isset($qpts_grades[$course->grade])) {
  1718. continue;
  1719. }
  1720. }
  1721. else {
  1722. // Is this grade a "retake" grade? If so, skip it.
  1723. if (in_array($course->grade, $retake_grades)) continue;
  1724. }
  1725. // Correct the course's requirement type, if needed (remove the "u")
  1726. $cr_type = $course->requirement_type;
  1727. $cr_type = str_replace("u", "", $cr_type);
  1728. if ($course->grade != "")// || !($course->course_list_fulfilled_by->is_empty))
  1729. {
  1730. // Make sure we aren't trying to exclude any transfer credits.
  1731. if ($bool_exclude_all_transfer_credits) {
  1732. if ($course->bool_transfer) {
  1733. continue;
  1734. }
  1735. // Is this a requirement which has been fulfilled by a course? And if so, is THAT course a transfer?
  1736. if ($course->course_list_fulfilled_by->is_empty == false) {
  1737. $cc = $course->course_list_fulfilled_by->get_first();
  1738. if ($cc->bool_transfer) {
  1739. continue;
  1740. }
  1741. }
  1742. }
  1743. // If we require the grade to be a qpts_grade, then check that now.
  1744. if ($bool_qpts_grades_only && !isset($qpts_grades[$course->grade])) {
  1745. continue;
  1746. }
  1747. // Do our requirement types match?
  1748. if ($requirement_type == "" || ($requirement_type != "" && $requirement_type == $cr_type))
  1749. {
  1750. $h = $course->get_hours();
  1751. $count = $count + $h;
  1752. }
  1753. }
  1754. else {
  1755. // maybe it's a substitution?
  1756. if ($requirement_type == "" || ($requirement_type != "" && $requirement_type == $cr_type))
  1757. {
  1758. if ($course->course_list_fulfilled_by->is_empty == false)
  1759. {
  1760. $cc = $course->course_list_fulfilled_by->get_first();
  1761. if ($cc->get_bool_substitution())
  1762. {
  1763. // If we require the grade to be a qpts_grade, then check that now.
  1764. if ($bool_qpts_grades_only && !isset($qpts_grades[$cc->grade])) {
  1765. continue;
  1766. }
  1767. // Make sure we aren't trying to exclude any transfer credits.
  1768. if ($bool_exclude_all_transfer_credits && $cc->bool_transfer) {
  1769. //fpm($requirement_type);
  1770. //fpm($cc);
  1771. continue;
  1772. }
  1773. $h = $cc->get_substitution_hours();
  1774. if ($cc->bool_ghost_hour) {
  1775. $h = 0;
  1776. }
  1777. $count = $count + $h;
  1778. }
  1779. }
  1780. }
  1781. }
  1782. }
  1783. return $count;
  1784. }
  1785. /**
  1786. * Similar to count_credit_hours, but this will only count courses
  1787. * which have been taken and have a grade. We will return back
  1788. * a sum of their quality points.
  1789. *
  1790. * @param string $requirement_type
  1791. * - If set, we will only look for courses matching this requirement_type.
  1792. *
  1793. * @param bool $bool_use_ignore_list
  1794. * @param bool $bool_ignore_enrolled
  1795. * @return int
  1796. */
  1797. function count_credit_quality_points($requirement_type = "", $bool_use_ignore_list = false, $bool_ignore_enrolled = false, $bool_exclude_all_transfer_credits = FALSE, $degree_id = 0)
  1798. {
  1799. $points = 0;
  1800. for ($t = 0; $t < $this->count; $t++)
  1801. {
  1802. $course = $this->array_list[$t];
  1803. // Does this course belong to the same degree we are interested in? If not, skip it.
  1804. if ($degree_id > 0) {
  1805. if ($course->req_by_degree_id != $degree_id && $course->get_has_been_assigned_to_degree_id($degree_id) != TRUE) continue;
  1806. }
  1807. $school_id = $course->school_id;
  1808. // Correct the course's requirement type, if needed (remove the "u")
  1809. $cr_type = $course->requirement_type;
  1810. $cr_type = str_replace("u", "", $cr_type);
  1811. if ($bool_use_ignore_list == true)
  1812. {
  1813. // Do ignore some courses...
  1814. $temp_course_name = $course->subject_id . " " . $course->course_num;
  1815. // Check in our settings to see if we should ignore this course
  1816. // (configured in /custom/settings.php)
  1817. if (in_array($temp_course_name, csv_to_array(@variable_get_for_school("ignore_courses_from_hour_counts", "", $school_id)))) {
  1818. continue;
  1819. }
  1820. // Also, if the course's requirement_type is "x" it means we should ignore it.
  1821. if ($course->requirement_type == 'x') continue;
  1822. }
  1823. if ($bool_ignore_enrolled == true)
  1824. {
  1825. if ($course->is_completed() == false)
  1826. {
  1827. if ($course->course_list_fulfilled_by->is_empty)
  1828. {
  1829. continue;
  1830. } else {
  1831. if ($course->course_list_fulfilled_by->get_first()->is_completed() == false)
  1832. {
  1833. continue;
  1834. }
  1835. }
  1836. }
  1837. }
  1838. if ($course->grade != "")
  1839. {
  1840. // Make sure we aren't trying to exclude any transfer credits.
  1841. if ($bool_exclude_all_transfer_credits) {
  1842. if ($course->bool_transfer) {
  1843. continue;
  1844. }
  1845. // Is this a requirement which has been fulfilled by a course? And if so, is THAT course a transfer?
  1846. if ($course->course_list_fulfilled_by->is_empty == false) {
  1847. $cc = $course->course_list_fulfilled_by->get_first();
  1848. if ($cc->bool_transfer) {
  1849. continue;
  1850. }
  1851. }
  1852. }
  1853. if ($requirement_type == "")
  1854. {
  1855. $p = $course->get_quality_points($degree_id);
  1856. $points = $points + $p;
  1857. } else {
  1858. if ($cr_type == $requirement_type)
  1859. {
  1860. $p = $course->get_quality_points($degree_id);
  1861. $points = $points + $p;
  1862. continue;
  1863. }
  1864. }
  1865. }
  1866. else {
  1867. // maybe it's a substitution?
  1868. if (($requirement_type == "") || ($requirement_type != "" && $requirement_type == $cr_type))
  1869. {
  1870. if ($course->course_list_fulfilled_by->is_empty == false)
  1871. {
  1872. $cc = $course->course_list_fulfilled_by->get_first();
  1873. if ($cc->get_bool_substitution($degree_id))
  1874. {
  1875. // Make sure we aren't trying to exclude any transfer credits.
  1876. if ($bool_exclude_all_transfer_credits) {
  1877. if ($cc->bool_transfer) {
  1878. //fpm($course);
  1879. continue;
  1880. }
  1881. }
  1882. //$h = $cc->substitution_hours;
  1883. //if ($cc->bool_ghost_hour) {
  1884. // $h = 0;
  1885. //}
  1886. // What are the quality points for this course?
  1887. $p = $cc->get_quality_points($degree_id);
  1888. $points = $points + $p;
  1889. }
  1890. }
  1891. }
  1892. }
  1893. }
  1894. return $points;
  1895. }
  1896. /**
  1897. * Assign a groupID to every course in the list.
  1898. *
  1899. * @param int $group_id
  1900. */
  1901. function assign_group_id($group_id)
  1902. {
  1903. for ($t = 0; $t < $this->count; $t++)
  1904. {
  1905. $course = $this->array_list[$t];
  1906. //$course->assigned_to_group_id = $group_id;
  1907. $course->assigned_to_group_ids_array[$group_id] = $group_id;
  1908. }
  1909. }
  1910. /**
  1911. * Assign a semesterNum to every course in the list.
  1912. *
  1913. * @param int $semester_num
  1914. */
  1915. function assign_semester_num($semester_num)
  1916. {
  1917. for ($t = 0; $t < $this->count; $t++)
  1918. {
  1919. $course = $this->array_list[$t];
  1920. $course->assigned_to_semester_num = $semester_num;
  1921. }
  1922. }
  1923. /**
  1924. * Sets the bool_has_been_assigned property of every course in
  1925. * the list.
  1926. *
  1927. * @param bool $bool_has_been_assigned
  1928. * - What to set each course's->boolhasBeenAssigned property
  1929. * to.
  1930. *
  1931. */
  1932. function set_has_been_assigned($bool_has_been_assigned = true)
  1933. {
  1934. // Set the bool_has_been_assigned for all items
  1935. // in this list.
  1936. for ($t = 0; $t < $this->count; $t++)
  1937. {
  1938. $course = $this->array_list[$t];
  1939. $course->bool_has_been_assigned = $bool_has_been_assigned;
  1940. }
  1941. }
  1942. /**
  1943. * Set's each course's bool_substitution value.
  1944. *
  1945. * @param bool $bool_s
  1946. * - What to set each course's bool_substitution value to.
  1947. */
  1948. function set_bool_substitution($degree_id = 0, $bool_s = true)
  1949. {
  1950. // Set the bool_substitution for all items
  1951. // in this list.
  1952. for ($t = 0; $t < $this->count; $t++)
  1953. {
  1954. $course = $this->array_list[$t];
  1955. $course->set_bool_substitution($degree_id, $bool_s);
  1956. }
  1957. }
  1958. /**
  1959. * Set all the courses in this list to have the same "req_by_degree_id" value.
  1960. */
  1961. function set_req_by_degree_id($degree_id = 0)
  1962. {
  1963. // Set the bool_substitution for all items
  1964. // in this list.
  1965. for ($t = 0; $t < $this->count; $t++)
  1966. {
  1967. $course = $this->array_list[$t];
  1968. $course->req_by_degree_id = $degree_id;
  1969. }
  1970. }
  1971. /**
  1972. * Set all the courses in this list to have the same "requirement_type" value.
  1973. */
  1974. function set_requirement_type($requirement_type = "")
  1975. {
  1976. // Set the bool_substitution for all items
  1977. // in this list.
  1978. for ($t = 0; $t < $this->count; $t++)
  1979. {
  1980. $course = $this->array_list[$t];
  1981. $course->requirement_type = $requirement_type;
  1982. }
  1983. }
  1984. /**
  1985. * Sets each course's $course_substitution value to the supplied
  1986. * Course object.
  1987. *
  1988. * @param Course $course_s
  1989. * @param string $sub_remarks
  1990. */
  1991. function set_course_substitution(Course $course_s, $sub_remarks = "", $degree_id = 0)
  1992. {
  1993. for ($t = 0; $t < $this->count; $t++)
  1994. {
  1995. $course = $this->array_list[$t];
  1996. $course->set_course_substitution($degree_id, $course_s);
  1997. $course->req_by_degree_id = $course_s->req_by_degree_id; // match it up to the degree its being subbed for
  1998. $course->sub_remarks = $sub_remarks;
  1999. }
  2000. }
  2001. /**
  2002. * Go through the list and decrement the specified_repeats
  2003. * value for all instances of Course $course.
  2004. *
  2005. * @param Course $course
  2006. */
  2007. function dec_specified_repeats(Course $course, $bool_ignore_infinite_repeats = TRUE) {
  2008. // Go through the list, and decrement the specified_repeats
  2009. // value for all instances of $course.
  2010. for ($t = 0; $t < $this->count; $t++)
  2011. {
  2012. $course2 = $this->array_list[$t];
  2013. if ($course2->course_id == $course->course_id)
  2014. {
  2015. if ($bool_ignore_infinite_repeats && $course2->specified_repeats == Group::GROUP_COURSE_INFINITE_REPEATS) continue;
  2016. $course2->specified_repeats--;
  2017. }
  2018. }
  2019. }
  2020. /**
  2021. * Go through the list and set the specified_repeats value to $num
  2022. * for all instances of $course.
  2023. *
  2024. * @param Course $course
  2025. * @param int $num
  2026. */
  2027. function set_specified_repeats(Course $course, $num)
  2028. {
  2029. for ($t = 0; $t < $this->count; $t++)
  2030. {
  2031. $course2 = $this->array_list[$t];
  2032. if ($course2->course_id == $course->course_id)
  2033. {
  2034. $course2->specified_repeats = $num;
  2035. $course2->bool_specified_repeats = true;
  2036. }
  2037. }
  2038. }
  2039. /**
  2040. * Removes excluded courses from the list (courses that
  2041. * have db_exclude == 1)
  2042. *
  2043. */
  2044. function remove_excluded()
  2045. {
  2046. // Removes courses from the list that have a db_exclude == 1.
  2047. $new_list = new CourseList();
  2048. // Do this by adding elements to an array.
  2049. // course_id => index in list.
  2050. for ($t = 0; $t < $this->count; $t++)
  2051. {
  2052. $course = $this->array_list[$t];
  2053. if ($course->subject_id == "")
  2054. { // load descriptive data (include exclude info)
  2055. $course->load_descriptive_data();
  2056. }
  2057. if ($course->db_exclude == 1)
  2058. {
  2059. continue;
  2060. }
  2061. $new_list->add($course);
  2062. }
  2063. $this->array_list = $new_list->array_list;
  2064. $this->reset_counter();
  2065. }
  2066. /**
  2067. * Remove occurances of the course in the course list.
  2068. *
  2069. * If a limit is higher than zero, we will STOP after that limit has been reached.
  2070. */
  2071. function remove_course_with_course_id($course_id, $limit = 0) {
  2072. // If the limit is 0, set it to an int's max, which is around 2 billion (32bit) or 9 quintillion (64 bit).
  2073. // Either way, it's effectively infinite for FlightPath in this purpose.
  2074. if ($limit == 0) $limit = PHP_INT_MAX;
  2075. $new_list = new CourseList();
  2076. $c = 0;
  2077. for ($t = 0; $t < $this->count; $t++)
  2078. {
  2079. $course = $this->array_list[$t];
  2080. if ($course == null)
  2081. {
  2082. continue;
  2083. }
  2084. if ($c < $limit && intval($course->course_id) == intval($course_id)) {
  2085. // We found the course. Since we do not want it to be part of the list,
  2086. // we will skip adding it to the new_list.
  2087. $c++;
  2088. continue;
  2089. }
  2090. // Otherwise, let's add it to the new_list.
  2091. $new_list->add($course);
  2092. }
  2093. // Switch over the reference.
  2094. $this->array_list = $new_list->array_list;
  2095. $this->reset_counter();
  2096. }
  2097. /**
  2098. * Removes all courses which are not assigned to this degree_id.
  2099. */
  2100. function remove_courses_not_in_degree($degree_id) {
  2101. $new_list = new CourseList();
  2102. for ($t = 0; $t < $this->count; $t++)
  2103. {
  2104. $course = $this->array_list[$t];
  2105. if ($course == null)
  2106. {
  2107. continue;
  2108. }
  2109. if ($course->req_by_degree_id != $degree_id) {
  2110. continue;
  2111. }
  2112. // Otherwise, let's add it to the new_list.
  2113. $new_list->add($course);
  2114. }
  2115. // Switch over the reference.
  2116. $this->array_list = $new_list->array_list;
  2117. $this->reset_counter();
  2118. }
  2119. /**
  2120. * Removes null's and duplicate courses from the list.
  2121. *
  2122. */
  2123. function remove_duplicates()
  2124. {
  2125. // Go through and remove duplicates from the list.
  2126. // Also remove null's
  2127. $tarray = array();
  2128. $new_list = new CourseList();
  2129. // Do this by adding elements to an array.
  2130. // course_id => index in list.
  2131. for ($t = 0; $t < $this->count; $t++)
  2132. {
  2133. $course = $this->array_list[$t];
  2134. if ($course == null)
  2135. {
  2136. continue;
  2137. }
  2138. $tarray[$course->course_id] = -1;
  2139. }
  2140. for ($t = 0; $t < $this->count; $t++)
  2141. {
  2142. $course = $this->array_list[$t];
  2143. if ($course == null)
  2144. {
  2145. continue;
  2146. }
  2147. //if (is_object($course->courseFulfilledBy))
  2148. if (!($course->course_list_fulfilled_by->is_empty))
  2149. {
  2150. $tarray[$course->course_id] = $t;
  2151. continue;
  2152. }
  2153. if ($tarray[$course->course_id]*1 < 0)
  2154. {
  2155. $tarray[$course->course_id] = $t;
  2156. }
  2157. }
  2158. // Now, go through tarray and rebuild the newList.
  2159. foreach($tarray as $course_id => $i)
  2160. {
  2161. $new_list->add($this->array_list[$i]);
  2162. }
  2163. // Switch over the reference.
  2164. $this->array_list = $new_list->array_list;
  2165. $this->reset_counter();
  2166. }
  2167. } // end class CourseList

Classes

Namesort descending Description
CourseList