// Create the normal view onto a score course private static CourseView CreateScoreCourseView(EventDB eventDB, CourseDesignator courseDesignator) { Course course = eventDB.GetCourse(courseDesignator.CourseId); CourseView courseView = new CourseView(eventDB, courseDesignator); Id<CourseControl> courseControlId; courseView.courseName = course.name; courseView.scoreColumn = course.scoreColumn; courseControlId = course.firstCourseControl; while (courseControlId.IsNotNone) { ControlView controlView = new ControlView(); CourseControl courseControl = eventDB.GetCourseControl(courseControlId); controlView.courseControlIds = new[] { courseControlId }; controlView.controlId = courseControl.control; // Ordinals assigned after sorting. controlView.ordinal = -1; controlView.joinIndex = -1; // Move to the next control. courseView.controlViews.Add(controlView); courseControlId = courseControl.nextCourseControl; } // Sort the control views: first by kind, then by score, then by code. courseView.controlViews.Sort(delegate(ControlView view1, ControlView view2) { ControlPoint control1 = eventDB.GetControl(view1.controlId); ControlPoint control2 = eventDB.GetControl(view2.controlId); CourseControl courseControl1 = eventDB.GetCourseControl(view1.courseControlIds[0]); CourseControl courseControl2 = eventDB.GetCourseControl(view2.courseControlIds[0]); if (control1.kind < control2.kind) return -1; else if (control1.kind > control2.kind) return 1; if (courseControl1.points != courseControl2.points) return courseControl1.points.CompareTo(courseControl2.points); int result = Util.CompareCodes(control1.code, control2.code); if (result != 0) return result; return view1.controlId.id.CompareTo(view2.controlId.id); }); // Assign ordinals, if applicable. If scores in column A, then no ordinals will be assigned. if (courseView.scoreColumn != 0) { int ordinal = course.firstControlOrdinal; foreach (ControlView control in courseView.controlViews) { if (eventDB.GetControl(control.controlId).kind == ControlPointKind.Normal) control.ordinal = ordinal++; } } courseView.Finish(); return courseView; }
// Create an filtered All Controls view -- show controls from the control collection, but only includes some. // excludedCourses contains an array of course ids to excluded from the contgrols. // kindFilter, if non-null, limits the controls to this kind of controls. public static CourseView CreateFilteredAllControlsView(EventDB eventDB, CourseDesignator[] excludedCourses, ControlPointKind kindFilter, bool addSpecials, bool addDescription) { CourseView courseView = new CourseView(eventDB, CourseDesignator.AllControls); courseView.courseName = MiscText.AllControls; courseView.scoreColumn = -1; // Add every control to the course view, subject to the filters. foreach (Id<ControlPoint> controlId in eventDB.AllControlPointIds) { ControlPoint control = eventDB.GetControl(controlId); // Check if the control is filtered out. if (excludedCourses != null) { // Filter excluded courses. foreach (CourseDesignator excludedCourseDesignator in excludedCourses) { if (QueryEvent.CourseUsesControl(eventDB, excludedCourseDesignator, controlId)) goto SKIP; } } if (kindFilter != ControlPointKind.None) { // Filter on control type. if (control.kind != kindFilter) goto SKIP; } // We are going to include this control in the collection. ControlView controlView = new ControlView(); controlView.courseControlIds = new[] { Id<CourseControl>.None }; controlView.controlId = controlId; // All controls doesn't have ordinals. controlView.ordinal = -1; controlView.joinIndex = -1; courseView.controlViews.Add(controlView); SKIP: ; } // Sort the control views: first by kind, then by code. courseView.controlViews.Sort((view1, view2) => QueryEvent.CompareControlIds(eventDB, view1.controlId, view2.controlId)); courseView.Finish(); if (addSpecials) { // Add every special, regardless of courses it is on, except for descriptions. Descriptions are added to all // controls only if they appear in all courses (or specifically for the all controls view), and if "addDescription" is true foreach (Id<Special> specialId in eventDB.AllSpecialIds) { Special special = eventDB.GetSpecial(specialId); if (special.kind == SpecialKind.Descriptions) { if (addDescription && QueryEvent.CourseContainsSpecial(eventDB, CourseDesignator.AllControls, specialId)) courseView.descriptionViews.Add(new DescriptionView(specialId, CourseDesignator.AllControls)); } else courseView.specialIds.Add(specialId); } } return courseView; }
// Create the view of all variations of a course with variations. Cannot be a single part of a multi-part course. // Does not contain ordinals. private static CourseView CreateAllVariationsCourseView(EventDB eventDB, CourseDesignator courseDesignator) { Course course = eventDB.GetCourse(courseDesignator.CourseId); if (!courseDesignator.AllParts) throw new ApplicationException("Cannot create all variations of a single part"); CourseView courseView = new CourseView(eventDB, courseDesignator); courseView.courseName = course.name; courseView.scoreColumn = -1; // To get the ordinals correct, we get the course control ids for all parts. List<Id<CourseControl>> courseControls = QueryEvent.EnumCourseControlIds(eventDB, courseDesignator).ToList(); for (int index = 0; index < courseControls.Count; ++index) { Id<CourseControl> courseControlId = courseControls[index]; CourseControl courseControl = eventDB.GetCourseControl(courseControlId); // We add each split control only once, even though it has multiple variations. Check to see if we have already // handled it. bool alreadyHandled = false; if (courseControl.split) { foreach (ControlView cv in courseView.controlViews) { if (cv.courseControlIds.Contains(courseControlId)) alreadyHandled = true; } } if (!alreadyHandled) { ControlView controlView = new ControlView(); controlView.controlId = courseControl.control; // Set the ordinal number. All variations does not include an ordinal. controlView.ordinal = -1; // Set all course control ids associated with split control, or a single one for a non-split control. // Set the legTo array with the next courseControlID(s). This is later updated // to the indices. if (courseControl.split) { controlView.courseControlIds = QueryEvent.AllVariationsOfCourseControl(eventDB, courseControlId).ToArray(); if (courseControl.nextCourseControl.IsNotNone) { controlView.legTo = new int[controlView.courseControlIds.Length]; for (int i = 0; i < controlView.legTo.Length; ++i) { controlView.legTo[i] = eventDB.GetCourseControl(controlView.courseControlIds[i]).nextCourseControl.id; } } if (courseControl.loop) controlView.joinIndex = courseControlId.id; else controlView.joinIndex = courseControl.splitEnd.id; } else { controlView.courseControlIds = new[] { courseControlId }; if (courseControl.nextCourseControl.IsNotNone) controlView.legTo = new int[1] { courseControl.nextCourseControl.id }; // legTo initially holds course control ids, later changed. controlView.joinIndex = -1; } // Add the controlview. courseView.controlViews.Add(controlView); } } courseView.Finish(); return courseView; }
// Create the standard view onto a regular course, or a single variation of a variation course. private static CourseView CreateStandardCourseView(EventDB eventDB, CourseDesignator courseDesignator) { Course course = eventDB.GetCourse(courseDesignator.CourseId); if (QueryEvent.HasVariations(eventDB, courseDesignator.CourseId) && courseDesignator.VariationInfo == null) throw new ApplicationException("Cannot create course view without specifying which variation"); // Get sub-part of the course. firstCourseControls is the first control to process, lastCourseControl is the last one to // process, or None if process to the end of the course. Id<CourseControl> firstCourseControl, lastCourseControl; if (courseDesignator.AllParts) { firstCourseControl = course.firstCourseControl; lastCourseControl = Id<CourseControl>.None; } else { QueryEvent.GetCoursePartBounds(eventDB, courseDesignator, out firstCourseControl, out lastCourseControl); } CourseView courseView = new CourseView(eventDB, courseDesignator); int ordinal; courseView.courseName = course.name; courseView.scoreColumn = -1; ordinal = 1; ordinal = course.firstControlOrdinal; // To get the ordinals correct, we get the course control ids for all parts. List<Id<CourseControl>> courseControls = QueryEvent.EnumCourseControlIds(eventDB, courseDesignator.WithAllParts()).ToList(); int index = 0; // Increase the ordinal value for each normal control before the first one we're considering. while (index < courseControls.Count && courseControls[index] != firstCourseControl) { CourseControl courseControl = eventDB.GetCourseControl(courseControls[index]); ControlPoint control = eventDB.GetControl(courseControl.control); if (control.kind == ControlPointKind.Normal) ++ordinal; ++index; } for (; index < courseControls.Count; ++index) { Id<CourseControl> courseControlId = courseControls[index]; ControlView controlView = new ControlView(); CourseControl courseControl = eventDB.GetCourseControl(courseControlId); ControlPoint control = eventDB.GetControl(courseControl.control); controlView.courseControlIds = new[] { courseControlId }; controlView.controlId = courseControl.control; // Set the ordinal number. if (control.kind == ControlPointKind.Normal) controlView.ordinal = ordinal++; else if (control.kind == ControlPointKind.Start || control.kind == ControlPointKind.MapExchange) controlView.ordinal = 0; else controlView.ordinal = -1; controlView.joinIndex = -1; // Don't show the map exchange for the next part at the end of this part. if (courseControlId == lastCourseControl && !courseDesignator.AllParts && control.kind == ControlPointKind.MapExchange) { controlView.hiddenControl = true; } // Set the legTo array with the next courseControlID. This is later updated // to the indices. if (index < courseControls.Count - 1 && courseControlId != lastCourseControl) { Id<CourseControl> nextCourseControl = courseControls[index + 1]; controlView.legTo = new int[1] { nextCourseControl.id }; // legTo initially holds course control ids, later changed. } // Add the controlview. courseView.controlViews.Add(controlView); if (courseControlId == lastCourseControl) break; } // If this is a part that should also have the finish on it, and it isn't the last part, then // add the finish. if (courseDesignator.IsNotAllControls && !courseDesignator.AllParts && courseDesignator.Part != QueryEvent.CountCourseParts(eventDB, courseDesignator.CourseId) - 1 && QueryEvent.GetPartOptions(eventDB, courseDesignator).ShowFinish) { if (QueryEvent.HasFinishControl(eventDB, courseDesignator.CourseId)) courseView.extraCourseControls.Add(QueryEvent.LastCourseControl(eventDB, courseDesignator.CourseId, false)); } courseView.Finish(); return courseView; }