From 4e47cd426f5b27f49678114b9a0e521b9bcf404b Mon Sep 17 00:00:00 2001 From: Andreas Svanberg <andreass@dsv.su.se> Date: Thu, 24 Oct 2024 13:53:21 +0200 Subject: [PATCH] Calculate grades using grade limits, if available. Grade can be any string rather than a limited set --- .../report/GradeCalculatorServiceImpl.java | 14 +++++++ .../su/dsv/scipro/report/GradingReport.java | 10 ++++- .../GradingReportTemplateGradeCalculator.java | 39 +++++++++++++++++++ .../grading/GradingReportPointsPanel.java | 2 +- .../grading/GradingReportPointsPanelTest.java | 2 +- 5 files changed, 63 insertions(+), 4 deletions(-) create mode 100644 core/src/main/java/se/su/dsv/scipro/report/GradingReportTemplateGradeCalculator.java diff --git a/core/src/main/java/se/su/dsv/scipro/report/GradeCalculatorServiceImpl.java b/core/src/main/java/se/su/dsv/scipro/report/GradeCalculatorServiceImpl.java index 569afb79b7..c2a6362c83 100644 --- a/core/src/main/java/se/su/dsv/scipro/report/GradeCalculatorServiceImpl.java +++ b/core/src/main/java/se/su/dsv/scipro/report/GradeCalculatorServiceImpl.java @@ -1,5 +1,6 @@ package se.su.dsv.scipro.report; +import jakarta.inject.Inject; import se.su.dsv.scipro.project.Project; import se.su.dsv.scipro.report.calculators.original.SupervisorBachelorGradeCalculator; import se.su.dsv.scipro.report.calculators.original.SupervisorMaster15GradeCalculator; @@ -8,8 +9,21 @@ import se.su.dsv.scipro.system.DegreeType; import se.su.dsv.scipro.system.ProjectType; public class GradeCalculatorServiceImpl implements GradeCalculatorService { + + private final GradingReportService gradingReportTemplateService; + + @Inject + public GradeCalculatorServiceImpl(GradingReportService gradingReportService) { + this.gradingReportTemplateService = gradingReportService; + } + @Override public GradeCalculator getSupervisorCalculator(final Project project) { + GradingReportTemplate template = gradingReportTemplateService.getTemplate(project); + if (!template.getGradeLimits().isEmpty()) { + return new GradingReportTemplateGradeCalculator(template); + } + DegreeType degreeType = project.getProjectType().getDegreeType(); if (degreeType == DegreeType.BACHELOR) { if (getYear(project) >= 2017) { diff --git a/core/src/main/java/se/su/dsv/scipro/report/GradingReport.java b/core/src/main/java/se/su/dsv/scipro/report/GradingReport.java index 4c4b70397c..0c036ede48 100644 --- a/core/src/main/java/se/su/dsv/scipro/report/GradingReport.java +++ b/core/src/main/java/se/su/dsv/scipro/report/GradingReport.java @@ -15,8 +15,14 @@ import java.util.stream.Collectors; @Entity public abstract class GradingReport extends Report { - public enum Grade { - A, B, C, D, E, F, FX + public record Grade(String name) { + public static final Grade A = new Grade("A"); + public static final Grade B = new Grade("B"); + public static final Grade C = new Grade("C"); + public static final Grade D = new Grade("D"); + public static final Grade E = new Grade("E"); + public static final Grade F = new Grade("F"); + public static final Grade FX = new Grade("FX"); } public enum State { INITIAL, REVIEWING, FINALIZED } diff --git a/core/src/main/java/se/su/dsv/scipro/report/GradingReportTemplateGradeCalculator.java b/core/src/main/java/se/su/dsv/scipro/report/GradingReportTemplateGradeCalculator.java new file mode 100644 index 0000000000..777770eb3b --- /dev/null +++ b/core/src/main/java/se/su/dsv/scipro/report/GradingReportTemplateGradeCalculator.java @@ -0,0 +1,39 @@ +package se.su.dsv.scipro.report; + +import java.util.Comparator; +import java.util.Objects; + +class GradingReportTemplateGradeCalculator implements GradeCalculator { + private final GradingReportTemplate template; + + GradingReportTemplateGradeCalculator(GradingReportTemplate template) { + this.template = template; + } + + @Override + public GradingReport.Grade getGrade(GradingReport gradingReport) { + for (GradingCriterion gradingCriterion : gradingReport.getGradingCriteria()) { + if (!gradingCriterion.meetsMinimumPointRequirement()) { + return new GradingReport.Grade(template.getFailingGrade()); + } + } + long points = getPoints(gradingReport); + String textualGrade = template.getGradeLimits() + .stream() + .filter(gradeLimit -> points >= gradeLimit.getLowerLimit()) + .max(Comparator.comparing(GradeLimit::getLowerLimit)) + .map(GradeLimit::getGrade) + .orElseGet(template::getFailingGrade); + return new GradingReport.Grade(textualGrade); + } + + @Override + public long getPoints(GradingReport gradingReport) { + return gradingReport.getGradingCriteria() + .stream() + .map(GradingCriterion::getPoints) + .filter(Objects::nonNull) + .mapToInt(Integer::intValue) + .sum(); + } +} diff --git a/view/src/main/java/se/su/dsv/scipro/grading/GradingReportPointsPanel.java b/view/src/main/java/se/su/dsv/scipro/grading/GradingReportPointsPanel.java index 6a0c6c6e71..ad4c49050d 100644 --- a/view/src/main/java/se/su/dsv/scipro/grading/GradingReportPointsPanel.java +++ b/view/src/main/java/se/su/dsv/scipro/grading/GradingReportPointsPanel.java @@ -24,7 +24,7 @@ public class GradingReportPointsPanel extends Panel { return gradingReportIModel.getObject().getGrade(gradeCalculator); } }; - final Label grade = new Label(GRADE, gradeModel) { + final Label grade = new Label(GRADE, gradeModel.map(GradingReport.Grade::name)) { @Override protected void onConfigure() { super.onConfigure(); diff --git a/view/src/test/java/se/su/dsv/scipro/grading/GradingReportPointsPanelTest.java b/view/src/test/java/se/su/dsv/scipro/grading/GradingReportPointsPanelTest.java index 6df3e73e79..cc0c6799df 100644 --- a/view/src/test/java/se/su/dsv/scipro/grading/GradingReportPointsPanelTest.java +++ b/view/src/test/java/se/su/dsv/scipro/grading/GradingReportPointsPanelTest.java @@ -45,7 +45,7 @@ public class GradingReportPointsPanelTest extends SciProTest { when(gradeCalculator.getGrade(any(GradingReport.class))).thenReturn(grade); startPanel(); - tester.assertLabel(path(panel, GRADE), grade.toString()); + tester.assertLabel(path(panel, GRADE), grade.name()); } @Test