public AddDescriptionMode(Controller controller, UndoMgr undoMgr, SelectionMgr selectionMgr, EventDB eventDB, SymbolDB symbolDB, CourseDesignator courseDesignator, DescriptionLine[] description, DescriptionKind kind)
 {
     this.controller = controller;
     this.undoMgr = undoMgr;
     this.selectionMgr = selectionMgr;
     this.symbolDB = symbolDB;
     this.eventDB = eventDB;
     this.courseDesignator = courseDesignator;
     this.description = description;
     this.kind = kind;
 }
Example #2
0
        // Get the number of parts that this course has.  A course with no map exchanges has 1 part, with one
        // map exchange has 2 parts, etc.
        public static int CountCourseParts(EventDB eventDB, CourseDesignator courseDesignator)
        {
            Debug.Assert(courseDesignator.AllParts);

            int currentPart = 0;

            foreach (Id<CourseControl> courseControlId in EnumCourseControlIds(eventDB, courseDesignator)) {
                if (eventDB.GetCourseControl(courseControlId).exchange)
                    ++currentPart;
            }

            return currentPart + 1;
        }
Example #3
0
        // Check the validate of the selected course view/selected object and update accordingly.
        void UpdateSelection()
        {
            // Check the selection validity.
            if (!activeCourseDesignator.IsAllControls && !eventDB.IsCoursePresent(activeCourseDesignator.CourseId)) {
                // Active course was deleted. Switch to all controls.
                activeCourseDesignator = CourseDesignator.AllControls;
                ClearSelection();
            }

            // Check that variation still exists.
            if (activeCourseDesignator.IsVariation && QueryEvent.HasVariations(eventDB, activeCourseDesignator.CourseId)) {
                IEnumerable<VariationInfo> variations = QueryEvent.GetAllVariations(eventDB, activeCourseDesignator.CourseId);
                if (!variations.Any(v => v.Equals(activeCourseDesignator.VariationInfo)))
                    activeCourseDesignator = activeCourseDesignator.WithAllVariations();
            }

            // Does the current part still exist?
            if (!activeCourseDesignator.IsAllControls && !activeCourseDesignator.AllParts && activeCourseDesignator.Part >= QueryEvent.CountCourseParts(eventDB, activeCourseDesignator.CourseId)) {
                // No part that large any more.
                int numberOfParts = QueryEvent.CountCourseParts(eventDB, activeCourseDesignator.CourseId);
                if (numberOfParts > 1)
                    activeCourseDesignator = new CourseDesignator(activeCourseDesignator.CourseId, numberOfParts - 1);
                else
                    activeCourseDesignator = new CourseDesignator(activeCourseDesignator.CourseId);
                ClearSelection();
            }

            if (selectedCourseControl.IsNotNone && !eventDB.IsCourseControlPresent(selectedCourseControl)) {
                // Selected course control is no longer there.
                selectedCourseControl = Id<CourseControl>.None;
                ClearSelection();
            }

            if (selectedCourseControl.IsNotNone && activeCourseDesignator.IsNotAllControls &&
                (!activeCourseDesignator.AllParts || activeCourseDesignator.IsVariation) &&
                !QueryEvent.IsCourseControlInPart(eventDB, activeCourseDesignator, selectedCourseControl)) {
                // Selected course control is not in active part.
                // Could be allowed if it's the finish.
                Id<ControlPoint> controlId = eventDB.GetCourseControl(selectedCourseControl).control;
                if (!(eventDB.IsControlPresent(controlId) &&
                      eventDB.GetControl(controlId).kind == ControlPointKind.Finish &&
                      QueryEvent.GetPartOptions(eventDB, activeCourseDesignator).ShowFinish))
                {
                    selectedCourseControl = Id<CourseControl>.None;
                    ClearSelection();
                }
            }

            if (selectedCourseControl2.IsNotNone && !eventDB.IsCourseControlPresent(selectedCourseControl2)) {
                // Selected course control 2 is no longer there.
                selectedCourseControl2 = Id<CourseControl>.None;
                ClearSelection();
            }

            if (selectedCourseControl2.IsNotNone && activeCourseDesignator.IsNotAllControls && !activeCourseDesignator.AllParts &&
                !QueryEvent.IsCourseControlInPart(eventDB, activeCourseDesignator, selectedCourseControl2)) {
                // Selected course control 2 is not in active part.
                selectedCourseControl2 = Id<CourseControl>.None;
                ClearSelection();
            }

            if (selectedControl.IsNotNone && !eventDB.IsControlPresent(selectedControl)) {
                // Selected control is no longer there.
                ClearSelection();
            }

            if (selectedSpecial.IsNotNone && !eventDB.IsSpecialPresent(selectedSpecial)) {
                // Selected special is no longer there.
                ClearSelection();
            }

            if (selectedSpecial.IsNotNone && !(activeCourseDesignator.IsAllControls || QueryEvent.CourseContainsSpecial(eventDB, activeCourseDesignator, selectedSpecial))) {
                // Selected special is not in current course
                ClearSelection();
            }
        }
Example #4
0
        // 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;
        }
Example #5
0
        // 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;
        }
Example #6
0
 // Create the course view for printing and OCAD export. If CourseId is 0, then the all controls view for printing.
 public static CourseView CreatePrintingCourseView(EventDB eventDB, CourseDesignator courseDesignator)
 {
     if (courseDesignator.IsAllControls)
         return CourseView.CreateFilteredAllControlsView(eventDB, null, ControlPointKind.None, true, true);
     else
         return CourseView.CreateCourseView(eventDB, courseDesignator, true, true);
 }
Example #7
0
        private float totalPoints; // total points.

        #endregion Fields

        #region Constructors

        private CourseView(EventDB eventDB, CourseDesignator courseDesignator)
        {
            this.eventDB = eventDB;
            this.courseDesignator = courseDesignator;
        }
Example #8
0
        // Add the appropriate specials for the given course to the course view.
        // If descriptionSpecialOnly is true, then only description sheet specials are added.
        private void AddSpecials(CourseDesignator courseDesignator, bool addNonDescriptionSpecials, bool addDescriptionSpecials)
        {
            bool multiPart = courseDesignator.IsNotAllControls && courseDesignator.AllParts && (QueryEvent.CountCourseParts(eventDB, courseDesignator.CourseId) > 1);

            foreach (Id<Special> specialId in eventDB.AllSpecialIds) {
                SpecialKind specialKind = eventDB.GetSpecial(specialId).kind;

                if (ShouldAddSpecial(specialKind, addNonDescriptionSpecials, addDescriptionSpecials)) {
                    if (specialKind == SpecialKind.Descriptions) {
                        // Descriptions are added differently. It's not entirely clear the best way to handle descriptions
                        // for all-parts of a multi-part course. For now, we don't put any descriptions on.
                        if (!multiPart) {
                            if (QueryEvent.CourseContainsSpecial(eventDB, courseDesignator, specialId))
                                descriptionViews.Add(new DescriptionView(specialId, courseDesignator));
                        }
                    }
                    else {
                        if (QueryEvent.CourseContainsSpecial(eventDB, courseDesignator, specialId))
                            specialIds.Add(specialId);
                    }
                }
            }
        }
Example #9
0
        public static IEnumerable<LegInfo> EnumLegs(EventDB eventDB, CourseDesignator courseDesignator)
        {
            if (courseDesignator.IsAllControls)
                yield break;

            Id<Course> courseId = courseDesignator.CourseId;

            // Score courses, by definition, have no legs.
            if (eventDB.GetCourse(courseId).kind == CourseKind.Score)
                yield break;

            bool first = true;
            foreach (Id<CourseControl> courseControlId in EnumCourseControlIds(eventDB, courseDesignator)) {
                CourseControl courseControl = eventDB.GetCourseControl(courseControlId);
                if (first || courseDesignator.AllParts || !courseControl.exchange) {
                    Id<CourseControl> nextCourseControlId = GetNextControl(eventDB, courseDesignator, courseControlId);
                    if (nextCourseControlId.IsNotNone) {
                        yield return new LegInfo(courseControlId, nextCourseControlId);
                    }
                }
                first = false;
            }
        }
Example #10
0
        // Enumerate all the course controls ids for a particular course.
        public static IEnumerable<Id<CourseControl>> EnumCourseControlIds(EventDB eventDB, CourseDesignator courseDesignator)
        {
            Debug.Assert(courseDesignator.IsNotAllControls);

            Id<Course> courseId = courseDesignator.CourseId;
            int part = courseDesignator.Part;
            Id<CourseControl> firstCourseControlId = eventDB.GetCourse(courseId).firstCourseControl;
            int currentPart = 0;

            IEnumerable<Id<CourseControl>> variationChoices;
            if (! courseDesignator.IsVariation)
                variationChoices = null;
            else
                variationChoices = courseDesignator.VariationInfo.Path.Choices;

            return EnumCourseControlsToJoin(eventDB, courseDesignator, firstCourseControlId, Id<CourseControl>.None, variationChoices, false, currentPart);
        }
Example #11
0
        // Does courseControl1 precede courseControl2 in the given course.
        public static bool DoesCourseControlPrecede(EventDB eventDB, CourseDesignator courseDesignator, Id<CourseControl> courseControl1, Id<CourseControl> courseControl2)
        {
            bool sawFirst = false, sawSecond = false;

            foreach (Id<CourseControl> id in EnumCourseControlIds(eventDB, courseDesignator)) {
                if (id == courseControl1)
                    sawFirst = true;
                else if (sawFirst && id == courseControl2)
                    sawSecond = true;
            }

            return (sawFirst && sawSecond);
        }
Example #12
0
        // Get the full output file name. Uses the name of the course, removes bad characters,
        // checks for duplication of the map file name.
        // If courseDesignator is null, uses the event title insteand.
        public static string CreateOutputFileName(EventDB eventDB, CourseDesignator courseDesignator, string filePrefix, string fileSuffix, string extension)
        {
            string basename;

            // Get the course name.
            if (courseDesignator == null)
                basename = GetEventTitle(eventDB, " ");
            else if (courseDesignator.IsAllControls)
                basename = MiscText.AllControls;
            else
                basename = eventDB.GetCourse(courseDesignator.CourseId).name;

            // Add prefix, if requested.
            if (!string.IsNullOrEmpty(filePrefix))
                basename = filePrefix + "-" + basename;

            // Add variation.
            if (courseDesignator != null && courseDesignator.IsVariation) {
                basename = basename + " " + courseDesignator.VariationInfo.Name;
            }

            // Add part.
            if (courseDesignator != null && !courseDesignator.AllParts) {
                basename = basename + "-" + (courseDesignator.Part + 1).ToString();
            }

            if (!string.IsNullOrEmpty(fileSuffix))
                basename = basename + fileSuffix;

            // Remove bad characters.
            basename = Util.FilterInvalidPathChars(basename);
            basename += extension;      // add OCAD extension.

            return basename;
        }
Example #13
0
        // Return if a give course uses a given control.
        public static bool CourseUsesControl(EventDB eventDB, CourseDesignator courseDesignator, Id<ControlPoint> controlId)
        {
            eventDB.CheckControlId(controlId);

            foreach (Id<CourseControl> courseControlId in EnumCourseControlIds(eventDB, courseDesignator)) {
                if (eventDB.GetCourseControl(courseControlId).control == controlId)
                    return true;
            }

            return false;
        }
Example #14
0
        public static bool CourseIsForked(EventDB eventDB, CourseDesignator courseDesignator)
        {
            foreach (Id<CourseControl> courseControlId in EnumCourseControlIds(eventDB, courseDesignator)) {
                if (eventDB.GetCourseControl(courseControlId).split)
                    return true;
            }

            return false;
        }
Example #15
0
        // Does the given course (or all controls) contain the given special?
        public static bool CourseContainsSpecial(EventDB eventDB, CourseDesignator courseDesignator, Id<Special> specialId)
        {
            Special special = eventDB.GetSpecial(specialId);

            if (special.allCourses)
                return true;

            if (courseDesignator.AllParts)
                return special.courses.Any(cd => cd.CourseId == courseDesignator.CourseId);
            else
                return special.courses.Contains(courseDesignator) || special.courses.Contains(new CourseDesignator(courseDesignator.CourseId));
        }
Example #16
0
        // Get the mapping from split course control to letter.
        public static Dictionary<Id<CourseControl>, char> GetVariantCodeMapping(EventDB eventDB, CourseDesignator courseDesignator)
        {
            Debug.Assert(!courseDesignator.IsVariation);

            char nextLetter = 'A';
            Dictionary<Id<CourseControl>, char> result = new Dictionary<Id<CourseControl>, char>();

            foreach (Id<CourseControl> courseControlId in EnumCourseControlIds(eventDB, courseDesignator)) {
                CourseControl courseControl = eventDB.GetCourseControl(courseControlId);
                if (courseControl.split) {
                    foreach (Id<CourseControl> splitId in courseControl.splitCourseControls) {
                        // The loop escape path doesn't get a letter.
                        if (!(courseControl.loop && courseControl.splitCourseControls[0] == splitId)) {
                            if (!result.ContainsKey(splitId)) {
                                result.Add(splitId, nextLetter);
                                if (nextLetter == 'Z')
                                    nextLetter = 'a';
                                else
                                    ++nextLetter;
                            }
                        }
                    }
                }
            }

            return result;
        }
Example #17
0
        // 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;
        }
Example #18
0
        // Find the closest leg to a given point on a course. The leg might be None/None if the course has no legs.
        public static LegInfo FindClosestLeg(EventDB eventDB, CourseDesignator courseDesignator, PointF pt)
        {
            LegInfo closestLegSoFar = new LegInfo();
            float closestSoFar = 1E10F;

            foreach (LegInfo leg in EnumLegs(eventDB, courseDesignator)) {
                PointF temp;
                SymPath legPath = GetLegPath(eventDB, eventDB.GetCourseControl(leg.courseControlId1).control, eventDB.GetCourseControl(leg.courseControlId2).control);
                float distance = legPath.DistanceFromPoint(pt, out temp);
                if (distance < closestSoFar) {
                    closestSoFar = distance;
                    closestLegSoFar = leg;
                }
                else if (distance == closestSoFar) {
                    // Distances are equal. Use leg with the largest angle between the end points.
                    SymPath closestLegPath = GetLegPath(eventDB, eventDB.GetCourseControl(closestLegSoFar.courseControlId1).control, eventDB.GetCourseControl(closestLegSoFar.courseControlId2).control);
                    if (Geometry.Angle(legPath.FirstPoint, pt, legPath.LastPoint) >  Geometry.Angle(closestLegPath.FirstPoint, pt, closestLegPath.LastPoint)) {
                        closestSoFar = distance;
                        closestLegSoFar = leg;
                    }
                }
            }

            return closestLegSoFar;
        }
Example #19
0
 public DescriptionView(Id<Special> specialId, CourseDesignator courseDesignator)
 {
     this.SpecialId = specialId;
     this.CourseDesignator = courseDesignator;
 }
Example #20
0
        // Finds where a new regular control would be inserted into an existing course. courseControl1 and courseControl2 can either or both be none, to identify
        // a leg to insert into, a control to insert after, or no information about where to insert. Updates courseControl1 and courseControl2 to identify exactly
        // where on the course the control should be inserted as follows:
        //     If inserting between two course controls -- these are denoted by courseControl1 and courseControl2
        //     If inserting as last course control -- courseControl1 is the current last control and courseControl2 is None  (only occurs when there is no finish)
        //     If inserting as first course control -- courseControl2 is None and courseControl2 is current first control (only occurs when there is no start)
        //     If inserting as only course control -- both are none (only occurs if course is currently empty)
        public static void FindControlInsertionPoint(EventDB eventDB, CourseDesignator courseDesignator, ref Id<CourseControl> courseControl1, ref Id<CourseControl> courseControl2)
        {
            Id<Course> courseId = courseDesignator.CourseId;

            if (courseControl1.IsNotNone && courseControl2.IsNotNone) {
                CourseControl cc1 = eventDB.GetCourseControl(courseControl1);
                CourseControl cc2 = eventDB.GetCourseControl(courseControl2);

                if (cc1.nextCourseControl != courseControl2) {
                    Debug.Assert(cc2.split && cc2.splitCourseControls.Contains(courseControl2));
                    courseControl2 = cc1.nextCourseControl;
                }

                return;
            }
            else {
                // Adding after courseControl1. If none, or a finish control, add at end, before the finish control if any.
                if (courseControl1.IsNone || eventDB.GetControl(eventDB.GetCourseControl(courseControl1).control).kind == ControlPointKind.Finish)
                    courseControl1 = QueryEvent.LastCourseControl(eventDB, courseId, true);

                if (courseControl1.IsNone) {
                    // Empty course or adding at start.
                    courseControl2 = eventDB.GetCourse(courseId).firstCourseControl;
                    return;
                }
                else {
                    // Adding after courseControl1.
                    CourseControl before = (CourseControl)eventDB.GetCourseControl(courseControl1);
                    courseControl2 = before.nextCourseControl;
                    return;
                }
            }
        }
Example #21
0
        // 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;
        }
Example #22
0
        // Get all the possible variations for a given course, based on the loops/forks. Returns a list of VariationInfo,
        // giving the code string, VariationPath, and name. Sorted by code string.
        public static IEnumerable<VariationInfo> GetAllVariations(EventDB eventDB, Id<Course> courseId)
        {
            HashSet<Id<CourseControl>> alreadyVisited = new HashSet<PurplePen.Id<PurplePen.CourseControl>>();

            CourseDesignator courseDesignator = new CourseDesignator(courseId);
            Dictionary<Id<CourseControl>, char> variationMapper = GetVariantCodeMapping(eventDB, courseDesignator);
            List<List<Id<CourseControl>>> variations = GetVariations(eventDB, courseDesignator, eventDB.GetCourse(courseId).firstCourseControl, alreadyVisited);

            List<VariationInfo> result = new List<VariationInfo>();

            // Check for no variations.
            if (variations.Count == 1 && variations[0].Count == 0)
                return result;

            foreach (var choices in variations) {
                string variationString = GetVariationString(eventDB, choices, variationMapper);
                VariationInfo.VariationPath variationPath = new VariationInfo.VariationPath(choices);
                result.Add(new VariationInfo(variationString, variationPath));
            }
            result.Sort((vi1, vi2) => string.Compare(vi1.CodeString, vi2.CodeString, StringComparison.OrdinalIgnoreCase));

            return result;
        }
Example #23
0
 // Create a course view for normal viewing.
 public static CourseView CreateViewingCourseView(EventDB eventDB, CourseDesignator courseDesignator)
 {
     if (courseDesignator.IsAllControls)
         return CourseView.CreateAllControlsView(eventDB);
     else
         return CourseView.CreateCourseView(eventDB, courseDesignator, true, true);
 }
Example #24
0
        // Find all the course controls for a particular control in a particular course. If the course
        // doesn't contain the given controlId, an empty array is returned.
        public static Id<CourseControl>[] GetCourseControlsInCourse(EventDB eventDB, CourseDesignator courseDesignator, Id<ControlPoint> controlId)
        {
            List<Id<CourseControl>> list = new List<Id<CourseControl>>();

            foreach (Id<CourseControl> courseControlId in EnumCourseControlIds(eventDB, courseDesignator)) {
                if (eventDB.GetCourseControl(courseControlId).control == controlId)
                    list.Add(courseControlId);
            }

            return list.ToArray();
        }
Example #25
0
        //  -----------  Static methods to create a new CourseView.  -----------------
        // Create a normal course view -- the standard view in order, from start control to finish control. courseId may NOT be None.
        private static CourseView CreateCourseView(EventDB eventDB, CourseDesignator courseDesignator, bool addNonDescriptionSpecials, bool addDescriptionSpecials)
        {
            Debug.Assert(! courseDesignator.IsAllControls);

            Course course = eventDB.GetCourse(courseDesignator.CourseId);
            CourseView courseView;
            if (course.kind == CourseKind.Score)
                courseView = CreateScoreCourseView(eventDB, courseDesignator);
            else if (course.kind == CourseKind.Normal) {
                if (QueryEvent.HasVariations(eventDB, courseDesignator.CourseId) && !courseDesignator.IsVariation)
                    courseView = CreateAllVariationsCourseView(eventDB, courseDesignator);
                else
                    courseView = CreateStandardCourseView(eventDB, courseDesignator);
            }
            else {
                Debug.Fail("Bad course kind"); return null;
            }

            courseView.AddSpecials(courseDesignator, addNonDescriptionSpecials, addDescriptionSpecials);

            return courseView;
        }
Example #26
0
        // Get the start and end coursecontrols (inclusive on both ends) for a particular part of a course (parts separated by map exchanges).
        // If the given part doesn't exist, return false. If there are no map exchanges, then part 0 is the entire course.
        public static bool GetCoursePartBounds(EventDB eventDB, CourseDesignator courseDesignator, out Id<CourseControl> startCourseControlId, out Id<CourseControl> endCourseControlId)
        {
            Debug.Assert(courseDesignator.IsNotAllControls);

            startCourseControlId = endCourseControlId = Id<CourseControl>.None;

            bool startFound = false;      // did we find the beginning part of the course part?

            foreach (Id<CourseControl> courseControlId in EnumCourseControlIds(eventDB, courseDesignator)) {
                if (!startFound) {
                    startFound = true;
                    startCourseControlId = courseControlId;
                }
                endCourseControlId = courseControlId;
            }

            return startFound;
        }
Example #27
0
        // Select the course with the given id as the active tab, id==0 means all controls.
        public void SelectCourseView(CourseDesignator newDesignator)
        {
            UpdateState();
            if (activeCourseDesignator != newDesignator) {
                bool courseChanged = (activeCourseDesignator.CourseId != newDesignator.CourseId);
                ++selectionChangeNum;
                activeCourseDesignator = newDesignator;

                // For now, when switching tabs (but not parts) the selection is cleared.
                // CONSIDER: maybe change this later; e.g., keep the selected control if it is in common.
                if (courseChanged) {
                    ClearSelection();
                }

                // CONSIDER: record a non-persistant command with the Undo Manager.
            }
        }
Example #28
0
        // Get the part options for a specific course part. Returns null for all controls.
        public static PartOptions GetPartOptions(EventDB eventDB, CourseDesignator courseDesignator)
        {
            if (courseDesignator.IsAllControls)
                return null;

            Course course = eventDB.GetCourse(courseDesignator.CourseId);
            PartOptions partOptions;

            if (!course.partOptions.TryGetValue(courseDesignator.Part, out partOptions)) {
                partOptions = PartOptions.Default;
            }

            // Show Finish is always true for the last part of the course.
            if (courseDesignator.Part == QueryEvent.CountCourseParts(eventDB, courseDesignator.CourseId) - 1) {
                partOptions = partOptions.Clone();
                partOptions.ShowFinish = true;
            }

            return partOptions;
        }
Example #29
0
        CourseView topologyCourseView; // The active course view, but: null if all controls or score, plus always shows all variations and parts.

        #endregion Fields

        #region Constructors

        public SelectionMgr(EventDB eventDB, SymbolDB symbolDB, Controller controller)
        {
            this.eventDB = eventDB;
            this.symbolDB = symbolDB;
            this.controller = controller;
            this.activeCourseDesignator = CourseDesignator.AllControls;
        }
Example #30
0
        // Get the print area for a course, or for all controls if CourseId is none.
        public static PrintArea GetPrintArea(EventDB eventDB, CourseDesignator courseDesignator)
        {
            PrintArea printArea;

            if (courseDesignator.IsAllControls)
                printArea = eventDB.GetEvent().printArea;
            else {
                Course course = eventDB.GetCourse(courseDesignator.CourseId);
                printArea = course.printArea;
                if (!courseDesignator.AllParts && course.partPrintAreas.ContainsKey(courseDesignator.Part))
                    printArea = course.partPrintAreas[courseDesignator.Part];
            }

            return printArea;
        }