private string CreateLearningObjectivesPart(ExerciseObjectTree exerciseObjectTree) { var conceptList = exerciseObjectTree.Exercises .SelectMany(ex => ex.Concepts) .Where(c => c.LearningObjectives.Count > 0) .OrderBy(c => c.Name) .Select(c => new { name = "`" + c.Name + "`", learningObjectives = "<ul><li>" + string.Join("<li>", c.LearningObjectives) }) .ToList(); if (conceptList.Count == 0) { return(string.Empty); } int longestConceptName = conceptList.Max(c => c.name.Length); int longestLearningObjectives = conceptList.Max(c => c.learningObjectives.Length); StringBuilder sb = new StringBuilder(); var format = "| {0,-" + longestConceptName + "} | {1,-" + longestLearningObjectives + "} |" + Environment.NewLine; sb.AppendLine(); sb.AppendLine("## Learning Objectives"); sb.AppendLine(); sb.AppendFormat(format, "Concept", "Learning Objectives"); sb.AppendFormat(format, new String('-', longestConceptName), new String('-', longestLearningObjectives)); foreach (var text in conceptList) { sb.AppendFormat(format, text.name, text.learningObjectives); } return(sb.ToString()); }
// distance from v3/languages/csharp/reference to v3/reference // for location of track neutral concepts README.md public string CreateReport(ExerciseObjectTree exerciseObjectTree) { var concepts = CreateConceptPart(exerciseObjectTree); var conceptDefiniitons = CreateLearningObjectivesPart(exerciseObjectTree); var linkReferences = CreateLinkReferences(exerciseObjectTree); return(concepts + conceptDefiniitons + linkReferences); }
private static List <Error> ValidateExercises(ExerciseObjectTree exerciseObjectTree) { var errors = exerciseObjectTree.Exercises.Select(ex => ValidateExercise(ex)) .Where(exo => !string.IsNullOrWhiteSpace(exo)) .Select(exo => new Error(ErrorSource.Exercise, Severity.Error, exo)) .ToList(); return(errors); }
public string ToString(ExerciseObjectTree exerciseObjectTree) { var options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true, WriteIndented = true, }; options.Converters.Add(new JsonStringEnumConverter(JsonNamingPolicy.CamelCase)); return(JsonSerializer.Serialize(exerciseObjectTree, options)); }
private void GetConcepts(StringBuilder sb, ExerciseObjectTree exerciseObjectTree, Level level) { var reportLines = exerciseObjectTree.Exercises .SelectMany(ex => ex.Concepts, (ex, c) => new { Exercise = ex, Concept = c }) .Where(p => p.Exercise.Level == level) .OrderBy(p => p.Concept.Name) .Select(p => FormatConceptReportLine(p.Exercise, p.Concept)).DefaultIfEmpty("None"); foreach (string reportLine in reportLines) { sb.AppendLine(reportLine); } }
private string CreateLinkReferences(ExerciseObjectTree exerciseObjectTree) { StringBuilder sb = new StringBuilder(); var issueRefs = exerciseObjectTree.Exercises .Where(ex => ex.CompletionStatus == CompletionStatus.NewExerciseIssueRaised) .OrderBy(ex => ex.Slug) .Select(ex => $"[issue-{ex.Slug}]: {ex.DocumentLink}"); sb.AppendLine(); foreach (string issueRef in issueRefs) { sb.AppendLine(issueRef); } var designRefs = exerciseObjectTree.Exercises .Where(ex => ex.CompletionStatus == CompletionStatus.Complete) .OrderBy(ex => ex.Slug) .Select(ex => $"[design-{ex.Slug}]: {Path.Combine(GetExerciseLocationLink(ex.Slug), PathNames.Default.DesignDocName)}"); sb.AppendLine(); foreach (string designRef in designRefs) { sb.AppendLine(designRef); } var exerciseLocations = exerciseObjectTree.Exercises .Where(ex => ex.CompletionStatus == CompletionStatus.Complete) .OrderBy(ex => ex.Slug) .Select(ex => $"[exercise-{ex.Slug}]: {GetExerciseLocationLink(ex.Slug)}"); sb.AppendLine(); foreach (string exerciseLocation in exerciseLocations) { sb.AppendLine(exerciseLocation); } var trackNeutralConcepts = exerciseObjectTree.Exercises .SelectMany(ex => ex.Concepts) .Where(c => !string.IsNullOrWhiteSpace(c.TrackNeutralConcept)) .OrderBy(c => c.Name) .Select(c => $"[tnc-{c.Name}]: {Path.Combine(Relativity, c.TrackNeutralConcept)}"); sb.AppendLine(); foreach (string trackNeutralConcept in trackNeutralConcepts) { sb.AppendLine(trackNeutralConcept); } return(sb.ToString()); }
private void MergeLearningObjectives(ExerciseObjectTree exerciseObjectTree, LearningObjectives learningObjectives) { var concepts = exerciseObjectTree.Exercises.SelectMany(ex => ex.Concepts); foreach (var concept in concepts) { var objectives = learningObjectives.GetObjectivesForConcept(concept.Name); if (objectives != null) { concept.LearningObjectives.Clear(); foreach (string objective in objectives) { concept.LearningObjectives.Add(objective); } } } }
private List <Error> ReportUnmatchedConcepts(ExerciseObjectTree exerciseObjectTree, LearningObjectives learningObjectives) { var exerciseMap = exerciseObjectTree.Exercises .SelectMany(ex => ex.Concepts) .Select(con => con.Name) .ToHashSet(); List <Error> errors = new List <Error>(); foreach ((string DocId, string ConceptName)conceptDetails in learningObjectives.ConceptsInclDesignDocId) { if (!exerciseMap.Contains(conceptDetails.ConceptName)) { errors.Add(new Error(ErrorSource.Merge, Severity.Error, $"Failed to find concept {conceptDetails.ConceptName}, from the {conceptDetails.DocId} {Constants.DesignMd}, in {Constants.ExercisesJson} file")); } } return(errors); }
private List <Error> ReportMissingLearningObjectives(ExerciseObjectTree exerciseObjectTree) { var errors = exerciseObjectTree.Exercises.Where(ex => ex.CompletionStatus == CompletionStatus.Complete) .SelectMany(ex => ex.Concepts, (Exercise, Concept) => (Exercise, Concept)) .Where(e_and_c => e_and_c.Concept.LearningObjectives.Count == 0) .Select(e_and_c => new Error(ErrorSource.MissingLearningObjective, Severity.Error, $"The {e_and_c.Concept.Name} concept has no learning objectives on the exercise report - update the {Constants.DesignMd} for the {e_and_c.Exercise.Slug} exercise") ).ToList(); if (errors.Count > maxErrors) { errors.Add( new Error(ErrorSource.MissingLearningObjective, Severity.Fatal, $"Too many concepts have no learning objectives - see {Constants.ExerciseErrorsJson}") ); } return(errors); }
private string CreateConceptPart(ExerciseObjectTree exerciseObjectTree) { StringBuilder sb = new StringBuilder(); sb.Append(GetResourceAsString(Constants.ExerciseReportIntroResource)); sb.AppendLine(); sb.AppendLine("### Introductory Concepts"); sb.AppendLine(); GetConcepts(sb, exerciseObjectTree, Level.Introductory); sb.AppendLine(); sb.AppendLine("### Essential Concepts"); sb.AppendLine(); GetConcepts(sb, exerciseObjectTree, Level.Essential); sb.AppendLine(); sb.AppendLine("### Advanced Concepts"); sb.AppendLine(); GetConcepts(sb, exerciseObjectTree, Level.Advanced); sb.AppendLine(); sb.AppendLine("### Unallocated Concepts"); sb.AppendLine(); GetConcepts(sb, exerciseObjectTree, Level.None); return(sb.ToString()); }