// Return true if this leg should be included, false if not. private bool FilterLeg(CourseView.CourseViewKind kind, ControlPoint from, ControlPoint to, Leg leg) { if (leg == null) { return(false); } if (leg.flagging == FlaggingKind.None || leg.flagging == FlaggingKind.End) { return(false); } // Flagged legs that end at the finish or a map exchange are // included in the finish control. if (to.kind == ControlPointKind.Finish || to.kind == ControlPointKind.MapExchange) { return(false); } // Flagged legs that start at a map issue point are included in the map issue point. if (from.kind == ControlPointKind.MapIssue) { return(false); } return(true); }
// Return true if this control should be included, false if not. private bool FilterControl(CourseView.CourseViewKind kind, ControlPoint control, ControlPoint controlPrev, ControlPoint controlNext) { switch (kind) { case CourseView.CourseViewKind.AllControls: // All controls list shows all kinds. return(true); case CourseView.CourseViewKind.Normal: case CourseView.CourseViewKind.AllVariations: // Normal list shows all control kinds. // filter out duplicate crossing points. if (control.kind == ControlPointKind.CrossingPoint && controlPrev != null && controlPrev.kind == ControlPointKind.CrossingPoint) { return(false); } // Don't show map exchange that is the last control being shown. if (control.kind == ControlPointKind.MapExchange && controlNext == null) { return(false); } return(true); case CourseView.CourseViewKind.Score: // Score course shows start, normal controls. return(control.kind == ControlPointKind.Normal || control.kind == ControlPointKind.Start || control.kind == ControlPointKind.MapIssue); default: Debug.Fail("bad course view kind"); return(false); } }
// Create a set of description lines for a course. If "createKey" is true, then lines for a key are created based on any symbols // that have custom text. This is typically done only if text description are not already being printed. public DescriptionLine[] CreateDescription(bool createKey) { EventDB eventDB = courseView.EventDB; CourseView.CourseViewKind kind = courseView.Kind; int scoreColumn = courseView.ScoreColumn; List <DescriptionLine> list = new List <DescriptionLine>(courseView.ControlViews.Count + 4); string text; DescriptionLine line; DescriptionLine[] lines; Dictionary <string, string> descriptionKey = new Dictionary <string, string>(); // dictionary for any symbols encountered with custom text. // Get the first title line. text = GetTitleLine1(); Debug.Assert(text != null); lines = GetTitleLineFromText(DescriptionLineKind.Title, text); list.AddRange(lines); // Get the second title line. text = GetTitleLine2(); if (text != null) { lines = GetTitleLineFromText(DescriptionLineKind.SecondaryTitle, text); list.AddRange(lines); } // Get the header line, depending on the kind of course. switch (kind) { case CourseView.CourseViewKind.Normal: line = GetNormalHeaderLine(); break; case CourseView.CourseViewKind.AllControls: line = GetAllControlsHeaderLine(); break; case CourseView.CourseViewKind.Score: line = GetScoreHeaderLine(); break; case CourseView.CourseViewKind.AllVariations: line = GetAllVariationsHeaderLine(); break; default: Debug.Fail("unknown CourseViewKind"); line = null; break; } if (line != null) { list.Add(line); } // Do all the normal lines for (int iLine = 0; iLine < courseView.ControlViews.Count; ++iLine) { CourseView.ControlView controlView = courseView.ControlViews[iLine]; ControlPoint control = eventDB.GetControl(controlView.controlId); CourseControl courseControl = controlView.courseControlIds[0].IsNone ? null : eventDB.GetCourseControl(controlView.courseControlIds[0]); // CONSIDER: this might need to be updated for relay or split controls. ControlPoint controlPrev = (iLine > 0) ? eventDB.GetControl(courseView.ControlViews[iLine - 1].controlId) : null; ControlPoint controlNext = (iLine < courseView.ControlViews.Count - 1) ? eventDB.GetControl(courseView.ControlViews[iLine + 1].controlId) : null; //Id<CourseControl> courseControlIdNext = (iLine < courseView.ControlViews.Count - 1) ? courseView.ControlViews[iLine + 1].courseControlId : Id<CourseControl>.None; //CourseControl courseControlNext = courseControlIdNext.IsNotNone ? eventDB.GetCourseControl(coruseControlIdNext) : null; // Do the control.control if (FilterControl(kind, control, controlPrev, controlNext)) { // Text associated with the course or course control (before) AddTextLine(list, control.descTextBefore, controlView.courseControlIds[0], controlView.controlId, DescriptionLine.TextLineKind.BeforeControl); if (courseControl != null) { AddTextLine(list, courseControl.descTextBefore, controlView.courseControlIds[0], controlView.controlId, DescriptionLine.TextLineKind.BeforeCourseControl); } // The control itself. if (control.kind == ControlPointKind.Finish || control.kind == ControlPointKind.CrossingPoint || control.kind == ControlPointKind.MapIssue) { line = GetDirectiveLine(kind, controlView, iLine > 0 ? courseView.ControlViews[iLine - 1] : null); } else { line = GetRegularLine(kind, scoreColumn, controlView, descriptionKey); } Debug.Assert(line != null); list.Add(line); // Text associated with the course or course control (after) if (courseControl != null) { AddTextLine(list, courseControl.descTextAfter, controlView.courseControlIds[0], controlView.controlId, DescriptionLine.TextLineKind.AfterCourseControl); } AddTextLine(list, control.descTextAfter, controlView.courseControlIds[0], controlView.controlId, DescriptionLine.TextLineKind.AfterControl); } // Add any map exchange lines. if (courseView.Kind == CourseView.CourseViewKind.Normal || courseView.Kind == CourseView.CourseViewKind.AllVariations) { if (controlNext != null && controlNext.kind == ControlPointKind.MapExchange) { line = GetMapExchangeLine(controlView, courseView.ControlViews[controlView.legTo[0]]); list.Add(line); } else if (courseControl != null && courseControl.exchange && control.kind != ControlPointKind.MapExchange && controlPrev != null) { line = GetMapExchangeAtControlLine(controlView); list.Add(line); } } // Do the leg (if any). if (controlView.legTo != null && controlView.legTo.Length > 0) { Id <Leg> legId = controlView.legId[0]; Leg leg = (legId.IsNotNone) ? eventDB.GetLeg(legId) : null; if (FilterLeg(kind, control, controlNext, leg)) { line = GetMarkedRouteLine(controlView, courseView.ControlViews[controlView.legTo[0]], legId); Debug.Assert(line != null); list.Add(line); } } } // Add the key if desired. if (createKey) { foreach (string symbolId in descriptionKey.Keys) { line = new DescriptionLine(); line.kind = DescriptionLineKind.Key; line.boxes = new object[2]; line.boxes[0] = symbolDB[symbolId]; line.boxes[1] = descriptionKey[symbolId]; list.Add(line); } } // And we're done! return(list.ToArray()); }
// Get a directive line for a finish or crossingpoint. private DescriptionLine GetDirectiveLine(CourseView.CourseViewKind kind, CourseView.ControlView controlView, CourseView.ControlView controlViewPrev) { ControlPoint control = eventDB.GetControl(controlView.controlId); CourseControl courseControl; if (controlView.courseControlIds[0].IsNone) { courseControl = null; } else { courseControl = eventDB.GetCourseControl(controlView.courseControlIds[0]); } Debug.Assert(control.kind == ControlPointKind.Finish || control.kind == ControlPointKind.CrossingPoint || control.kind == ControlPointKind.MapIssue); DescriptionLine line = new DescriptionLine(); line.kind = DescriptionLineKind.Directive; line.boxes = new object[2]; // Figure out the distance in the directive, rounded to nearest 10m. float distance = float.NaN; string distanceText; if (control.kind == ControlPointKind.MapIssue) { if (controlView.legLength != null) { distance = controlView.legLength[0]; } } else { if (controlViewPrev != null && controlViewPrev.legLength != null) { distance = controlViewPrev.legLength[0]; } } if (!float.IsNaN(distance)) { distance = (float)(Math.Round(distance / 10.0) * 10.0); // round to nearest 10 m. distanceText = string.Format("{0} m", distance); } else { distanceText = ""; } // Box 1: directive graphics. string directiveId = control.symbolIds[0]; // Based on the leg flagging, we may modify the finish directive symbol. if (control.kind == ControlPointKind.Finish && (kind == CourseView.CourseViewKind.Normal || kind == CourseView.CourseViewKind.AllVariations)) { FlaggingKind flagging = FlaggingKind.None; if (controlView != null && controlViewPrev != null) { flagging = QueryEvent.GetLegFlagging(eventDB, controlViewPrev.controlId, controlView.controlId); } if (flagging == FlaggingKind.All) { directiveId = "14.1"; // If flagging is All, then finish id must be flagging to finish. } else if (flagging == FlaggingKind.End) { directiveId = "14.2"; // If flagging is Partial, then finish id must be flagging to funnel. } } line.boxes[0] = symbolDB[directiveId]; // Box 2: distance for the control, if any. if (control.kind == ControlPointKind.Finish || control.kind == ControlPointKind.MapIssue) { line.boxes[1] = distanceText; } // Get the text version of the control using the Textifier. Textifier textifier = new Textifier(eventDB, symbolDB, language); line.textual = textifier.CreateTextForDirective(directiveId, distanceText); // The course control ID, for use in coordinating the selection line.controlId = controlView.controlId; line.courseControlId = controlView.courseControlIds[0]; return(line); }
// Get a regular 8-box line for a start or regular control. private DescriptionLine GetRegularLine(CourseView.CourseViewKind kind, int scoreColumn, CourseView.ControlView controlView, Dictionary <string, string> descriptionKey) { Event ev = eventDB.GetEvent(); ControlPoint control = eventDB.GetControl(controlView.controlId); CourseControl courseControl; if (controlView.courseControlIds[0].IsNone) { courseControl = null; } else { courseControl = eventDB.GetCourseControl(controlView.courseControlIds[0]); } Debug.Assert(control.kind == ControlPointKind.Normal || control.kind == ControlPointKind.Start || control.kind == ControlPointKind.MapExchange); DescriptionLine line = new DescriptionLine(); line.kind = DescriptionLineKind.Normal; line.boxes = new object[8]; // Box A: ordinal or start triangle or points. if (control.kind == ControlPointKind.Start || control.kind == ControlPointKind.MapExchange) { line.boxes[0] = symbolDB["start"]; } else if (kind != CourseView.CourseViewKind.AllControls && controlView.ordinal > 0) { line.boxes[0] = Convert.ToString(controlView.ordinal); } else { line.boxes[0] = null; } // Box B: code of the control if (control.kind == ControlPointKind.Normal) { line.boxes[1] = Convert.ToString(control.code); } // Boxes C-H, from the symbols for (int i = 2; i < 8; ++i) { String symbolID = control.symbolIds[i - 2]; if (symbolID != null) { line.boxes[i] = symbolDB[control.symbolIds[i - 2]]; // See if we need to add this to the key. bool addToKey; if (ev.customSymbolKey.TryGetValue(symbolID, out addToKey) && addToKey && Symbol.ContainsLanguage(ev.customSymbolText[symbolID], language)) { descriptionKey[symbolID] = Symbol.GetBestSymbolText(symbolDB, ev.customSymbolText[symbolID], language, false, "", ""); } } } // Box F -- may be text instead of a symbol. if (control.columnFText != null) { Debug.Assert(line.boxes[5] == null); line.boxes[5] = control.columnFText; } // Put points in the score column, for a score course. if (control.kind == ControlPointKind.Normal && scoreColumn >= 0 && courseControl != null) { int points = courseControl.points; if (points > 0) { line.boxes[scoreColumn] = Convert.ToString(courseControl.points); } else { line.boxes[scoreColumn] = null; } } // Get the text version of the control using the Textifier. Textifier textifier = new Textifier(eventDB, symbolDB, language); line.textual = textifier.CreateTextForControl(controlView.controlId, ""); // The course control ID, for use in coordinating the selection line.controlId = controlView.controlId; line.courseControlId = controlView.courseControlIds[0]; return(line); }