function FlightPath::assign_courses_to_list
Search API
7.x FlightPath.php | FlightPath::assign_courses_to_list(ObjList $list_requirements, Student $student, $bool_perform_assignment = true, Group $group = null, $bool_check_significant_courses = false, $assign_to_semester_num = -1) |
6.x FlightPath.php | FlightPath::assign_courses_to_list(ObjList $list_requirements, Student $student, $bool_perform_assignment = true, Group $group = null, $bool_check_significant_courses = false, $assign_to_semester_num = -1) |
3 calls to FlightPath::assign_courses_to_list()
- FlightPath::assign_courses_to_groups in classes/
FlightPath.php - FlightPath::assign_courses_to_semesters in classes/
FlightPath.php - FlightPath::get_count_of_matches in classes/
FlightPath.php
File
- classes/
FlightPath.php, line 657
Class
Code
function assign_courses_to_list(ObjList $list_requirements, Student $student, $bool_perform_assignment = true, Group $group = null, $bool_check_significant_courses = false, $assign_to_semester_num = -1)
{
$count = 0;
$school_id = 0;
if ($student) {
$school_id = $student->school_id;
}
if ($group == null)
{
$group = new Group();
$group->group_id = 0;
}
else if ($group->min_grade != "") {
$group->assign_min_grade($group->min_grade); // If this is a group with a min grade value, let's make sure we assign all the courses in it to this min grade.
}
$sort_policy = variable_get_for_school("initial_student_course_sort_policy", "alpha", $school_id); // will either be "alpha" or "grade"
$bool_disallow_graduate_credits = (variable_get_for_school("disallow_graduate_credits", "yes", $school_id) == "yes") ? TRUE : FALSE;
$graduate_level_codes_array = csv_to_array(variable_get_for_school("graduate_level_codes", "GR", $school_id));
// Get the course repeat policy.
$course_repeat_policy = variable_get_for_school("course_repeat_policy", "most_recent_exclude_previous", $school_id);
// Set the $bool_mark_repeats_exclude variable based on the course_repeat_policy.
$bool_mark_repeats_exclude = ($course_repeat_policy == "most_recent_exclude_previous" || $course_repeat_policy == "best_grade_exclude_others");
$group_id = $group->group_id;
// If the group_id == 0, we may be talking about the bare degree plan.
$hours_required = $group->hours_required * 1;
$hours_assigned = $group->hours_assigned;
$meet_min_hours = 999999; // effectively infinite by default, to make logic easier later on.
// If the group has min_hours, then we should allow the user to get at least the min hours before we stop trying to fill.
if ($group->has_min_hours_allowed() && variable_get_for_school("group_full_at_min_hours", "yes", $school_id) == "yes") {
$meet_min_hours = $group->min_hours_allowed;
}
if ($hours_required <= 0 || $hours_required == "")
{
$hours_required = 999999;
}
$list_requirements->sort_smallest_hours_first();
// sort the requirement list by the best grades that the student has made? Similar to the substitutions?
if ($sort_policy == "grade") {
$list_requirements->sort_best_grade_first($student);
}
else if ($sort_policy == "alpha") {
$list_requirements->sort_alphabetical_order();
}
$list_requirements->sort_substitutions_first($student->list_substitutions, $group_id);
$list_requirements->reset_counter();
while ($list_requirements->has_more())
{
$course_requirement = $list_requirements->get_next();
$req_by_degree_id = $course_requirement->req_by_degree_id; // what degree is requiring this course?
// If we're dealing with a group, use it's required by degree id.
if ($group->group_id != "" && $group->req_by_degree_id > 0) {
$req_by_degree_id = $group->req_by_degree_id;
}
if ($bool_check_significant_courses == true)
{
// Only look for the course_requirement if it is in the student's
// array_significant_courses array.
if (isset($student->array_significant_courses [$course_requirement->course_id]) && $student->array_significant_courses [$course_requirement->course_id] != true)
{ // course was not in there, so skip!
continue;
}
}
if ($course_requirement->bool_specified_repeat == true)
{
// Since this requirement has specified repeats, we want
// to make all of the student's taken courses (for this course)
// also have specified repeats.
$student->list_courses_taken->set_specified_repeats($course_requirement, $course_requirement->specified_repeats);
}
//if ($course_requirement->course_id == '101092') {
//fpm($course_requirement);
//}
// Does the student have any substitutions for this requirement?
if ($substitution = $student->list_substitutions->find_requirement($course_requirement, true, $group_id, $req_by_degree_id))
{
// Since the substitution was made, I don't really care about
// min grades or the like. Let's just put it in.
if ($bool_perform_assignment == TRUE)
{
// Check to see if this course requirement has "infinite repeats". If it does, then we want to
// clone it and add it back into our list of requirements.
if ($course_requirement->specified_repeats == Group::GROUP_COURSE_INFINITE_REPEATS) {
$temp_ds = $course_requirement->to_data_string();
$new_course = new Course();
$new_course->load_course_from_data_string_for_requirement_clone($temp_ds);
$new_course->min_grade = $course_requirement->min_grade;
if ($assign_to_semester_num !== -1) {
$new_course->assigned_to_semester_num = $assign_to_semester_num;
}
$list_requirements->add($new_course);
}
// Make sure this isn't a group addition and we are *currently*
// NOT looking at the group it is being added to. This is to
// correct a bug.
if ($substitution->bool_group_addition == true)
{
if ($substitution->course_requirement->get_first_assigned_to_group_id() != $group_id)
{
continue;
}
}
// If the course_requirement's min_hours are greater than
// the substitution's hours, then we have to split the
// coureRequirement into 2 pieces, and add the second piece just
// after this one in the list.
$course_sub = $substitution->course_list_substitutions->get_first();
if (floatval($course_requirement->min_hours) > floatval($course_sub->get_hours_awarded($req_by_degree_id)))
{
// Because float math can create some very strange results, we must
// perform some rounding. We will round to 6 decimal places, which should
// provide us the accuracy w/o losing precision (since we can only represent a max
// of 4 decimals in the database anyway.
$remaining_hours = round($course_requirement->min_hours - $course_sub->get_hours_awarded($req_by_degree_id), 6);
$new_course_string = $course_requirement->to_data_string();
$new_course = new Course();
$new_course->load_course_from_data_string($new_course_string);
$new_course->min_hours = $new_course->max_hours = $remaining_hours;
$new_course->set_bool_substitution_split($req_by_degree_id, TRUE);
$new_course->set_bool_substitution_new_from_split($req_by_degree_id, TRUE);
$new_course->requirement_type = $course_requirement->requirement_type;
$new_course->min_grade = $course_requirement->min_grade;
$new_course->req_by_degree_id = $req_by_degree_id;
$new_course->assigned_to_degree_ids_array [$req_by_degree_id] = $req_by_degree_id;
$new_course->db_degree_requirement_id = floatval($course_requirement->db_degree_requirement_id . ".1");
if ($assign_to_semester_num !== -1) {
$new_course->assigned_to_semester_num = $assign_to_semester_num;
}
$course_requirement->set_bool_substitution_split($req_by_degree_id, TRUE);
// I am commenting this out-- if we split up a sub multiple times, then we shouldn't
// set the old course requirement to say it WASN'T from a split. This was causing a bug
// where the pie charts got weird if you did more than 1 split. Was counting total
// hours as more, in CourseList->count_hours().
//$course_requirement->bool_substitution_new_from_split = false;
// Only do this if we are NOT in a group! This is to correct a bug where split additions to groups wound up
// being displayed like available selections in the group. It was like, weird man.
if ($group_id == 0) {
// Now, add this into the list, right after the course_requirement.
$current_i = $list_requirements->i;
$list_requirements->insert_after_index($current_i, $new_course);
}
} // if min_hours > sub's awarded hours
$course_requirement->course_list_fulfilled_by = $substitution->course_list_substitutions;
$substitution->course_list_substitutions->assign_group_id($group_id);
$substitution->course_list_substitutions->set_has_been_assigned(true);
$substitution->course_list_substitutions->set_bool_substitution($req_by_degree_id, TRUE);
$course_requirement->db_substitution_id_array [] = $substitution->db_substitution_id;
$substitution->course_list_substitutions->set_course_substitution($course_requirement, $substitution->remarks, $req_by_degree_id);
$substitution->bool_has_been_applied = TRUE;
if ($group_id != "" && intval($group_id) > 0) {
// We are going to add the course_sub's hours in as being assigned to this list, if this is for a group.
// I am surprised this wasn't already here. This fixes a bug with groups that allow min hours.
$hours_assigned += $course_sub->get_hours_awarded($req_by_degree_id);
}
}
$count++;
continue;
} // if student has any substitutions for this requirement
// Has the student taken this course requirement?
if ($c = $student->list_courses_taken->find_best_match($course_requirement, $course_requirement->min_grade, $bool_mark_repeats_exclude, $req_by_degree_id, TRUE, TRUE, $group_id))
{
$h_get_hours = $c->get_hours();
if ($c->bool_ghost_hour) {
// If this is a ghost hour, then $h_get_hours would == 0 right now,
// instead, use the the adjusted value (probably 1).
$h_get_hours = $c->get_hours_awarded($req_by_degree_id);
}
// Can we assign any more hours to this group? Are we
// out of hours, and should stop?
if ($hours_assigned >= $hours_required || $hours_assigned >= $meet_min_hours)
{
continue;
}
$c_hours_awarded = $c->get_hours_awarded($req_by_degree_id);
// Will the hours of this course put us over the hours_required limit? NOTE: We don't care if it puts us over the min_hours, in fact, we want that.
if ($hours_assigned + $c_hours_awarded > $hours_required)
{
continue;
}
// Do not apply substitution new_from_split courses to anything automatically. (from any degree!)
// They must be applied by substitutions.
if ($c->get_bool_substitution_new_from_split() == TRUE)
{
continue;
}
// Make sure the course meets min grade requirements.
if (!$c->meets_min_grade_requirement_of($course_requirement))
{
continue;
}
// Has the course been unassigned from this group?
if ($c->group_list_unassigned->find_match_with_degree_id($group, $req_by_degree_id))
{
continue;
}
// Make sure $c is not being used in a substitution (for this degree)
if ($c->get_bool_substitution($req_by_degree_id) == TRUE) {
continue;
}
// If this is a graduate level course, and we are not allowing grad credits, then skip!
if ($c->level_code != "" && in_array($c->level_code, $graduate_level_codes_array)) {
if ($bool_disallow_graduate_credits) {
continue;
}
}
// Check hooks to see if this course is allowed to be assigned to the GROUP in question.
if ($group_id != "" && $group_id != 0) {
$bool_can_proceed = TRUE;
$result = invoke_hook("flightpath_can_assign_course_to_group", array($group, $c));
foreach ($result as $m => $val) {
// If *any* module said FALSE, then we must skip this course and not assign it to this degree.
if ($val === FALSE) {
$bool_can_proceed = $val;
}
}
if (!$bool_can_proceed) {
continue; // don't assign!
}
} // if group_id != ""
// We want to see if this course has already been assigned to THIS degree...
if (!in_array($req_by_degree_id, $c->assigned_to_degree_ids_array))
{ //Don't count courses which have already been placed in other groups.
// Check hooks to see if this course is allowed to be assigned to the degree in question.
$bool_can_proceed = TRUE;
$result = invoke_hook("flightpath_can_assign_course_to_degree_id", array($req_by_degree_id, $c));
foreach ($result as $m => $val) {
// If *any* module said FALSE, then we must skip this course and not assign it to this degree.
if ($val === FALSE) {
$bool_can_proceed = $val;
}
}
if (!$bool_can_proceed) {
continue; // don't assign!
}
// Has another version of this course already been
// assigned? And if so, are repeats allowed for this
// course? And if so, then how many hours of the
// repeat_hours have I used up? If I cannot do any more
// repeats, then quit. Otherwise, let it continue...
$course_list_repeats = $student->list_courses_taken->get_previous_assignments($c->course_id);
if ($course_list_repeats->get_size() > 0)
{
// So, a copy of this course has been assigned more than once...
// Get the total number of hours taken up by this course.
$cc = $course_list_repeats->count_hours();
// have we exceeded the number of available repeat_hours
// for this course?
if ($course_requirement->repeat_hours <= 0)
{
$course_requirement->load_descriptive_data();
}
if (($course_requirement->bool_ghost_hour != TRUE || $c->bool_ghost_hour != TRUE)
&& $cc + $h_get_hours > $course_requirement->repeat_hours * 1)
{
// Do not allow the repeat, unless we are talking about courses worth zero hours.
// meaning, they have a ghost hour. In which case, allow it.
continue;
}
}
// Basically--- if the most recent attempt fails
// a min grade check, then tag all attempts as "unuseable"
// so that they can't be used in other groups. --
// unless they are able to be repeated. BARF!
// Inc hours_assigned, even if we aren't actually
// performing an assignment. This helps us accurately
// calculate the count.
$hours_assigned = $hours_assigned + $h_get_hours;
if ($bool_perform_assignment == TRUE)
{
// If this course has an "infinite" number of specified repeats, then
// let's actually clone the course and insert it as a new requirement, to replace
// the one we're about to use.
if ($course_requirement->specified_repeats == Group::GROUP_COURSE_INFINITE_REPEATS) {
$temp_ds = $course_requirement->to_data_string();
$new_course = new Course();
$new_course->load_course_from_data_string_for_requirement_clone($temp_ds);
$new_course->min_grade = $course_requirement->min_grade;
if ($assign_to_semester_num !== -1) {
$new_course->assigned_to_semester_num = $assign_to_semester_num;
$new_course->appears_in_semester_nums [] = $assign_to_semester_num; // for combo-degrees
}
$list_requirements->add($new_course);
} // infinite repeats?
// Which degree is this coming from?
//$req_by_degree_id = $course_requirement->req_by_degree_id;
$c->assigned_to_degree_ids_array [$req_by_degree_id] = $req_by_degree_id;
// Go ahead and state that the requirement was fulfilled.
$course_requirement->course_list_fulfilled_by->add($c);
$course_requirement->grade = $c->grade;
$course_requirement->set_hours_awarded($req_by_degree_id, $c->get_hours_awarded($req_by_degree_id));
$course_requirement->bool_ghost_hour = $c->bool_ghost_hour;
if ($course_requirement->extra_attribs != "") {
$c->extra_attribs = $course_requirement->extra_attribs;
}
// No longer using... using the assigned_to_degree_ids_array instead. // $c->bool_has_been_assigned = true;
//$c->requirement_type = $course_requirement->requirement_type;
if ($c->requirement_type == "") {
// No requirement type given? Perhaps we are part of a group. If so, use that.
//$c->requirement_type = $group->requirement_type;
//$course_requirement->requirement_type = $group->requirement_type;
}
if ($assign_to_semester_num !== -1) {
$c->assigned_to_semester_num = $assign_to_semester_num;
$c->appears_in_semester_nums [] = $assign_to_semester_num; // for combo-degrees
}
// Check what groups it has been assigned to already.
//$c->assigned_to_group_id = $group_id;
if ($group_id != '') {
$c->assigned_to_group_ids_array [$group_id . "_" . $req_by_degree_id] = $group_id;
}
$group->hours_assigned = $hours_assigned;
// Should check for:
// Can it be assigned, based on the number of allowed course repeats?
if ($course_requirement->bool_specified_repeat == true)
{
// $c is what they actually took.
$c->bool_specified_repeat = true;
$c->specified_repeats = $course_requirement->specified_repeats;
$list_requirements->dec_specified_repeats($c);
}
} // bool_perform_assignment == true
$count++;
}
}
}
return $count;
}