// Remove a control from a course. Caller must ensure the current is actually in this course. // Returns a list of all control points that were deleted. This will include the one asked to remove, // but might also remove others if it starts a fork or loop. public static ICollection<Id<ControlPoint>> RemoveCourseControl(EventDB eventDB, Id<Course> courseId, Id<CourseControl> courseControlIdRemove) { Course course = eventDB.GetCourse(courseId); List<Id<CourseControl>> allCourseControls = QueryEvent.EnumCourseControlIds(eventDB, new CourseDesignator(courseId)).ToList(); // This the course control to change to. Could be None. CourseControl courseControlRemove = eventDB.GetCourseControl(courseControlIdRemove); Id<CourseControl> afterRemove = courseControlRemove.nextCourseControl; if (courseControlRemove.split && !courseControlRemove.loop) { // Change next to another one of the split controls. if (courseControlRemove.splitCourseControls[0] == courseControlIdRemove) afterRemove = courseControlRemove.splitCourseControls[1]; else afterRemove = courseControlRemove.splitCourseControls[0]; } // For each course control, go throught and change referecnes to the subsequent control. foreach (Id<CourseControl> courseControlId in allCourseControls) { bool changed = false; CourseControl courseControl = eventDB.GetCourseControl(courseControlId); CourseControl clone = (CourseControl)courseControl.Clone(); if (courseControl.nextCourseControl == courseControlIdRemove) { changed = true; clone.nextCourseControl = afterRemove; } if (courseControl.split && courseControl.splitEnd == courseControlIdRemove) { changed = true; clone.splitEnd = afterRemove; if (afterRemove.IsNone) { clone.split = false; // No join control means we remove the split entirely. clone.splitCourseControls = null; } } if (clone.split && clone.splitCourseControls.Contains(courseControlIdRemove)) { changed = true; clone.splitCourseControls = clone.splitCourseControls.Where(id => id != courseControlIdRemove).ToArray(); if (clone.splitCourseControls.Length < 2) { clone.split = false; clone.loop = false; clone.splitCourseControls = null; clone.splitEnd = Id<CourseControl>.None; } } if (changed) { eventDB.ReplaceCourseControl(courseControlId, clone); } } if (course.firstCourseControl == courseControlIdRemove) { // Special case -- remove the first course control. course = (Course) course.Clone(); course.firstCourseControl = afterRemove; eventDB.ReplaceCourse(courseId, course); } // Remove a split could orphan more than one control. Go through and find orphaned ones. HashSet<Id<CourseControl>> newCourseControls = new HashSet<Id<CourseControl>>(QueryEvent.EnumCourseControlIds(eventDB, new CourseDesignator(courseId))); List<Id<CourseControl>> removedCourseControls = new List<Id<CourseControl>>(); HashSet<Id<ControlPoint>> removedControls = new HashSet<Id<ControlPoint>>(); foreach (Id<CourseControl> courseControlId in allCourseControls) { if (!newCourseControls.Contains(courseControlId)) { removedControls.Add(eventDB.GetCourseControl(courseControlId).control); removedCourseControls.Add(courseControlId); eventDB.RemoveCourseControl(courseControlId); } } if (! removedCourseControls.Contains(courseControlIdRemove)) { Debug.Fail("Did not remove the course control we were removing."); } return removedControls; }
// Delete a course and all of its course controls. public static void DeleteCourse(EventDB eventDB, Id<Course> courseId) { // Remember the set of course controls. List<Id<CourseControl>> courseControls = new List<Id<CourseControl>>(QueryEvent.EnumCourseControlIds(eventDB, new CourseDesignator(courseId))); // Remove the course. eventDB.RemoveCourse(courseId); // Remove each of the course controls in that course foreach (Id<CourseControl> courseControlId in courseControls) { eventDB.RemoveCourseControl(courseControlId); } // Now check specials, and see which need to be modified List<Id<Special>> specialsToChange = new List<Id<Special>>(); foreach (Id<Special> specialId in eventDB.AllSpecialIds) { Special special = eventDB.GetSpecial(specialId); if (!special.allCourses && special.courses.Any(cd => cd.CourseId == courseId)) { // This special is not an all controls special, and is present on the course being deleted. Update it. specialsToChange.Add(specialId); } } // Update each of the specials. foreach (Id<Special> specialId in specialsToChange) { Special special = eventDB.GetSpecial(specialId); CourseDesignator[] newCourses = special.courses.Where(cd => cd.CourseId != courseId).ToArray(); if (newCourses.Length == 0) ChangeEvent.DeleteSpecial(eventDB, specialId); else { special = (Special) special.Clone(); special.courses = newCourses; eventDB.ReplaceSpecial(specialId, special); } } }