diff --git a/Management.Test/Markdown/Quiz/QuizMarkdownTests.cs b/Management.Test/Markdown/Quiz/QuizMarkdownTests.cs index c2616e3..7ec7ce4 100644 --- a/Management.Test/Markdown/Quiz/QuizMarkdownTests.cs +++ b/Management.Test/Markdown/Quiz/QuizMarkdownTests.cs @@ -220,4 +220,52 @@ Which events are triggered when the user clicks on an input field? short_answer"; questionMarkdown.Should().Contain(expectedMarkdown); } + [Test] + public void NegativePoints_IsAllowed() + { + var rawMarkdownQuiz = @" +Name: Test Quiz +ShuffleAnswers: true +OneQuestionAtATime: false +DueAt: 2023-08-21T23:59:00 +LockAt: 2023-08-21T23:59:00 +AssignmentGroup: Assignments +AllowedAttempts: -1 +Description: this is the +multi line +description +--- +Points: -4 +Which events are triggered when the user clicks on an input field? +short answer +"; + + var quiz = LocalQuiz.ParseMarkdown(rawMarkdownQuiz); + var firstQuestion = quiz.Questions.First(); + firstQuestion.Points.Should().Be(-4); + } + [Test] + public void FloatingPointPoints_IsAllowed() + { + var rawMarkdownQuiz = @" +Name: Test Quiz +ShuffleAnswers: true +OneQuestionAtATime: false +DueAt: 2023-08-21T23:59:00 +LockAt: 2023-08-21T23:59:00 +AssignmentGroup: Assignments +AllowedAttempts: -1 +Description: this is the +multi line +description +--- +Points: 4.56 +Which events are triggered when the user clicks on an input field? +short answer +"; + + var quiz = LocalQuiz.ParseMarkdown(rawMarkdownQuiz); + var firstQuestion = quiz.Questions.First(); + firstQuestion.Points.Should().Be(4.56); + } } diff --git a/Management.Test/Markdown/RubricMarkdownTests.cs b/Management.Test/Markdown/RubricMarkdownTests.cs index bc2be99..542806c 100644 --- a/Management.Test/Markdown/RubricMarkdownTests.cs +++ b/Management.Test/Markdown/RubricMarkdownTests.cs @@ -68,4 +68,35 @@ public class RubricMarkdownTests rubric.First().IsExtraCredit.Should().BeTrue(); rubric.First().Label.Should().Be("(Extra Credit) this is the task"); } + + [Test] + public void TestCanParseFloatingPointNubmers() + { + var rawRubric = @" + - 1.5pt: this is the task + "; + + var rubric = LocalAssignment.ParseRubricMarkdown(rawRubric); + rubric.First().Points.Should().Be(1.5); + } + [Test] + public void TestCanParseNegativeNubmers() + { + var rawRubric = @" + - -2pt: this is the task + "; + + var rubric = LocalAssignment.ParseRubricMarkdown(rawRubric); + rubric.First().Points.Should().Be(-2.0); + } + [Test] + public void TestCanParseNegativeFloatingPointNubmers() + { + var rawRubric = @" + - -2895.00053pt: this is the task + "; + + var rubric = LocalAssignment.ParseRubricMarkdown(rawRubric); + rubric.First().Points.Should().Be(-2895.00053); + } } diff --git a/Management.Web/Pages/AssignmentForm/AssignmentMarkdownEditor.razor b/Management.Web/Pages/AssignmentForm/AssignmentMarkdownEditor.razor index 3c85e86..4c4adc2 100644 --- a/Management.Web/Pages/AssignmentForm/AssignmentMarkdownEditor.razor +++ b/Management.Web/Pages/AssignmentForm/AssignmentMarkdownEditor.razor @@ -61,9 +61,7 @@ private MarkupString preview { get { - var pipeline = new MarkdownPipelineBuilder() - .UsePipeTables().Build(); - return (MarkupString)Markdown.ToHtml(assignmentContext?.Assignment?.Description ?? "", pipeline); + return (MarkupString)MarkdownService.Render(assignmentContext?.Assignment?.Description ?? ""); } } private string HelpText() diff --git a/Management.Web/Pages/AssignmentForm/RubricDisplay.razor b/Management.Web/Pages/AssignmentForm/RubricDisplay.razor index fc41a17..cd6274d 100644 --- a/Management.Web/Pages/AssignmentForm/RubricDisplay.razor +++ b/Management.Web/Pages/AssignmentForm/RubricDisplay.razor @@ -22,8 +22,8 @@ assignmentContext.StateHasChanged -= reload; } - private int requiredPoints => assignmentContext?.Assignment?.Rubric.Where(r => !r.IsExtraCredit).Select(r => r.Points).Sum() ?? 0; - private int extraCreditPoints => assignmentContext?.Assignment?.Rubric.Where(r => r.IsExtraCredit).Select(r => r.Points).Sum() ?? 0; + private double requiredPoints => assignmentContext?.Assignment?.Rubric.Where(r => !r.IsExtraCredit).Select(r => r.Points).Sum() ?? 0; + private double extraCreditPoints => assignmentContext?.Assignment?.Rubric.Where(r => r.IsExtraCredit).Select(r => r.Points).Sum() ?? 0; } @if(assignmentContext != null) @@ -58,4 +58,4 @@ Extra Credit Points @extraCreditPoints -} \ No newline at end of file +} diff --git a/Management.Web/Pages/CoursePageForm/CoursePageMarkdownEditor.razor b/Management.Web/Pages/CoursePageForm/CoursePageMarkdownEditor.razor index 5f48a0b..87927a5 100644 --- a/Management.Web/Pages/CoursePageForm/CoursePageMarkdownEditor.razor +++ b/Management.Web/Pages/CoursePageForm/CoursePageMarkdownEditor.razor @@ -28,7 +28,7 @@ private string rawText { get; set; } = string.Empty; private string? error = null; - private MarkupString preview { get => (MarkupString)Markdown.ToHtml(pageContext?.Page?.Text ?? ""); } + private MarkupString preview { get => (MarkupString)MarkdownService.Render(pageContext?.Page?.Text ?? ""); } private void handleChange(string newRawPage) { diff --git a/Management.Web/Pages/QuizForm/QuizFormPage.razor b/Management.Web/Pages/QuizForm/QuizFormPage.razor index e2c1200..e6a7431 100644 --- a/Management.Web/Pages/QuizForm/QuizFormPage.razor +++ b/Management.Web/Pages/QuizForm/QuizFormPage.razor @@ -96,7 +96,7 @@ private string canvasQuizUrl => $"https://snow.instructure.com/courses/{planner.LocalCourse?.Settings.CanvasId}/quizzes/{quizInCanvas?.Id}"; - private int? quizPoints => quizContext.Quiz?.Questions.Sum(q => q.Points); + private double? quizPoints => quizContext.Quiz?.Questions.Sum(q => q.Points); private bool showHelp = false; private readonly static string exampleMarkdownQuestion = @"QUESTION REFERENCE diff --git a/Management/Models/Local/Assignment/LocalAssignment.cs b/Management/Models/Local/Assignment/LocalAssignment.cs index b931f97..d61c306 100644 --- a/Management/Models/Local/Assignment/LocalAssignment.cs +++ b/Management/Models/Local/Assignment/LocalAssignment.cs @@ -20,7 +20,7 @@ public record LocalAssignment : IModuleItem public string? LocalAssignmentGroupName { get; init; } public IEnumerable SubmissionTypes { get; init; } = Array.Empty(); public IEnumerable Rubric { get; init; } = Array.Empty(); - public int PointsPossible => Rubric.Sum(r => r.IsExtraCredit ? 0 : r.Points); + public double PointsPossible => Rubric.Sum(r => r.IsExtraCredit ? 0 : r.Points); public string GetDescriptionHtml() diff --git a/Management/Models/Local/Assignment/LocalAssignmentMarkdownParser.cs b/Management/Models/Local/Assignment/LocalAssignmentMarkdownParser.cs index 586e16b..7dec9a8 100644 --- a/Management/Models/Local/Assignment/LocalAssignmentMarkdownParser.cs +++ b/Management/Models/Local/Assignment/LocalAssignmentMarkdownParser.cs @@ -89,12 +89,12 @@ public static class LocalAssignmentMarkdownParser private static RubricItem parseIndividualRubricItemMarkdown(string rawMarkdown) { - var pointsPattern = @"\s*-\s*(\d+)\s*pt(s)?:"; + var pointsPattern = @"\s*-\s*(-?\d+(?:\.\d+)?)\s*pt(s)?:"; var match = Regex.Match(rawMarkdown, pointsPattern); if (!match.Success) throw new RubricMarkdownParseException($"points not found: {rawMarkdown}"); - var points = int.Parse(match.Groups[1].Value); + var points = double.Parse(match.Groups[1].Value); var label = string.Join(": ", rawMarkdown.Split(": ").Skip(1)); diff --git a/Management/Models/Local/Assignment/RubricItem.cs b/Management/Models/Local/Assignment/RubricItem.cs index a54dcd8..8bf2c52 100644 --- a/Management/Models/Local/Assignment/RubricItem.cs +++ b/Management/Models/Local/Assignment/RubricItem.cs @@ -4,6 +4,6 @@ public record RubricItem { public static readonly string extraCredit = "(Extra Credit) "; public required string Label { get; set; } - public required int Points { get; set; } + public required double Points { get; set; } public bool IsExtraCredit => Label.Contains(extraCredit.ToLower(), StringComparison.CurrentCultureIgnoreCase); } diff --git a/Management/Models/Local/Quiz/LocalQuizQuestion.cs b/Management/Models/Local/Quiz/LocalQuizQuestion.cs index 9474127..1efe8f4 100644 --- a/Management/Models/Local/Quiz/LocalQuizQuestion.cs +++ b/Management/Models/Local/Quiz/LocalQuizQuestion.cs @@ -8,7 +8,7 @@ public record LocalQuizQuestion public string Text { get; init; } = string.Empty; public string HtmlText => MarkdownService.Render(Text); public string QuestionType { get; init; } = string.Empty; - public int Points { get; init; } + public double Points { get; init; } public IEnumerable Answers { get; init; } = Enumerable.Empty(); public string ToMarkdown() @@ -59,9 +59,9 @@ public record LocalQuizQuestion var textHasPoints = lines.Length > 0 && lines.First().Contains(": ") && lines.First().Split(": ").Length > 1 - && int.TryParse(lines.First().Split(": ")[1], out _); + && double.TryParse(lines.First().Split(": ")[1], out _); - int points = firstLineIsPoints && textHasPoints ? int.Parse(lines.First().Split(": ")[1]) : 1; + double points = firstLineIsPoints && textHasPoints ? double.Parse(lines.First().Split(": ")[1]) : 1; var linesWithoutPoints = firstLineIsPoints ? lines[1..] : lines; diff --git a/docker-compose.yml b/docker-compose.yml index c5194df..6b00d75 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -19,24 +19,24 @@ services: - ~/projects/faculty/4620_Distributed/2024Spring/modules:/app/storage/distributed - ~/projects/faculty/3840_Telemetry/2024Spring_alex/modules:/app/storage/telemetry_and_operations - collector: - image: otel/opentelemetry-collector-contrib - volumes: - - ./canvas-development/otel-collector-config.yml:/etc/otelcol-contrib/config.yaml - ports: - - 1888:1888 # pprof extension - - 8888:8888 # Prometheus metrics exposed by the Collector - - 8889:8889 # Prometheus exporter metrics - - 13133:13133 # health_check extension - - 4317:4317 # OTLP gRPC receiver - - 4318:4318 # OTLP http receiver - - 55679:55679 # zpages extension + # collector: + # image: otel/opentelemetry-collector-contrib + # volumes: + # - ./canvas-development/otel-collector-config.yml:/etc/otelcol-contrib/config.yaml + # ports: + # - 1888:1888 # pprof extension + # - 8888:8888 # Prometheus metrics exposed by the Collector + # - 8889:8889 # Prometheus exporter metrics + # - 13133:13133 # health_check extension + # - 4317:4317 # OTLP gRPC receiver + # - 4318:4318 # OTLP http receiver + # - 55679:55679 # zpages extension - zipkin: - image: ghcr.io/openzipkin/zipkin-slim - # Environment settings are defined here https://github.com/openzipkin/zipkin/blob/master/zipkin-server/README.md#environment-variables - environment: - - STORAGE_TYPE=mem - ports: - - 9411:9411 - # command: --logging.level.zipkin2=DEBUG + # zipkin: + # image: ghcr.io/openzipkin/zipkin-slim + # # Environment settings are defined here https://github.com/openzipkin/zipkin/blob/master/zipkin-server/README.md#environment-variables + # environment: + # - STORAGE_TYPE=mem + # ports: + # - 9411:9411 + # # command: --logging.level.zipkin2=DEBUG