Skip to content
Snippets Groups Projects
Commit c03948f3 authored by Ruben Backx's avatar Ruben Backx :coffee:
Browse files

Merge branch...

Merge branch '116-average-number-of-submissions-before-passing-per-assignment-whole-course' into 'development'

Resolve "Average number of submissions before passing per assignment (whole course)"

Closes #116

See merge request !211
parents ec9736af af472480
No related branches found
No related tags found
2 merge requests!222Security release 2.2.0,!211Resolve "Average number of submissions before passing per assignment (whole course)"
...@@ -16,6 +16,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ...@@ -16,6 +16,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Ability to add file(s) for an assignment (@dsavvidi) - Ability to add file(s) for an assignment (@dsavvidi)
- Add "Enrol in a new edition" button in "Your courses" page (@dsavvidi) - Add "Enrol in a new edition" button in "Your courses" page (@dsavvidi)
- Module level grade export features (@dsavvidi) - Module level grade export features (@dsavvidi)
- New statistic: Average number of submissions before passing per assignment (@dsavvidi)
### Changed ### Changed
- Group joining is now restricted to groups with no submissions (@dsavvidi) - Group joining is now restricted to groups with no submissions (@dsavvidi)
- Reduced number of buttons needed to access script feedback (@dsavvidi) - Reduced number of buttons needed to access script feedback (@dsavvidi)
......
...@@ -43,6 +43,8 @@ public class AssignmentStatisticsDTO { ...@@ -43,6 +43,8 @@ public class AssignmentStatisticsDTO {
private Double medianScore; private Double medianScore;
private Double avgSubmissionsToPass;
private Integer[] scoreDistribution; private Integer[] scoreDistribution;
private Integer[] passFailDistribution; private Integer[] passFailDistribution;
......
...@@ -360,12 +360,25 @@ public class StatisticsService { ...@@ -360,12 +360,25 @@ public class StatisticsService {
.totalGroups(groups.size()) .totalGroups(groups.size())
.totalStudents(totalStudents) .totalStudents(totalStudents)
.totalSubmissions(totalSubmissions) .totalSubmissions(totalSubmissions)
.avgSubmissionsToPass(calculateAvgSubmissionsToPass(submissions, grades, gradeType,
assignment.getModule().getEdition().getId()))
.scoreDistribution(getScoreDistribution(grades, gradeType)) .scoreDistribution(getScoreDistribution(grades, gradeType))
.passFailDistribution(getPassFailDistribution(grades, gradeType, .passFailDistribution(getPassFailDistribution(grades, gradeType,
assignment.getModule().getEdition().getId(), totalStudents)) assignment.getModule().getEdition().getId(), totalStudents))
.build(); .build();
} }
private Double calculateAvgSubmissionsToPass(
Map<StudentGroupSummaryDTO, List<SubmissionDetailsDTO>> groupSubmissions,
Map<StudentGroupSummaryDTO, GradeSummaryDTO> grades, GradeScheme gradeType, Long editionId) {
int passingScore = getPassingScore(gradeType, editionId);
return groupSubmissions.keySet().stream()
.filter(group -> grades.get(group).getScore() >= passingScore)
.mapToLong(group -> groupSubmissions.get(group).size())
.average()
.orElse(0.0);
}
private SortedMap<Long, SubmitSubmissionViewDTO> getAssignmentSubmissionsForModule( private SortedMap<Long, SubmitSubmissionViewDTO> getAssignmentSubmissionsForModule(
ModuleDetailsDTO module, ModuleDetailsDTO module,
Map<StudentGroupSummaryDTO, List<SubmissionDetailsDTO>> submissions, Map<StudentGroupSummaryDTO, List<SubmissionDetailsDTO>> submissions,
...@@ -435,9 +448,7 @@ public class StatisticsService { ...@@ -435,9 +448,7 @@ public class StatisticsService {
private Integer[] getPassFailDistribution(List<? extends CalculatedScore> grades, private Integer[] getPassFailDistribution(List<? extends CalculatedScore> grades,
GradeScheme gradeType, Long editionId, int totalStudents) { GradeScheme gradeType, Long editionId, int totalStudents) {
int passingScore = gradeType == GradeScheme.PASS_FAIL ? 1 int passingScore = getPassingScore(gradeType, editionId);
: editionService.getSubmitEdition(editionId).map(SubmitEdition::getPassingScore).orElse(0.0)
.intValue();
Integer[] distribution = { 0, 0, 0 }; Integer[] distribution = { 0, 0, 0 };
grades.forEach(score -> { grades.forEach(score -> {
if (score.getScore() >= passingScore) { if (score.getScore() >= passingScore) {
...@@ -452,9 +463,7 @@ public class StatisticsService { ...@@ -452,9 +463,7 @@ public class StatisticsService {
private Integer[] getPassFailDistribution(Map<StudentGroupSummaryDTO, GradeSummaryDTO> grades, private Integer[] getPassFailDistribution(Map<StudentGroupSummaryDTO, GradeSummaryDTO> grades,
GradeScheme gradeType, Long editionId, int totalStudents) { GradeScheme gradeType, Long editionId, int totalStudents) {
int passingScore = gradeType == GradeScheme.PASS_FAIL ? 1 int passingScore = getPassingScore(gradeType, editionId);
: editionService.getSubmitEdition(editionId).map(SubmitEdition::getPassingScore).orElse(0.0)
.intValue();
Integer[] distribution = { 0, 0, 0, 0, 0 }; Integer[] distribution = { 0, 0, 0, 0, 0 };
grades.forEach((group, score) -> { grades.forEach((group, score) -> {
int index = score.getScore() >= passingScore ? 0 : 2; int index = score.getScore() >= passingScore ? 0 : 2;
...@@ -555,4 +564,12 @@ public class StatisticsService { ...@@ -555,4 +564,12 @@ public class StatisticsService {
})); }));
} }
private int getPassingScore(GradeScheme gradeType, Long editionId) {
return gradeType == GradeScheme.PASS_FAIL ? 1
: editionService.getSubmitEdition(editionId)
.map(SubmitEdition::getPassingScore)
.orElse(0.0)
.intValue();
}
} }
...@@ -296,6 +296,7 @@ grading.type.unlimited = Unbounded score ...@@ -296,6 +296,7 @@ grading.type.unlimited = Unbounded score
statistics.total_students = Total students statistics.total_students = Total students
statistics.total_groups = Total groups statistics.total_groups = Total groups
statistics.total_submissions = Total submissions statistics.total_submissions = Total submissions
statistics.avgSubmissionsToPass = Average submissions to pass (per group)
statistics.average_score = Average score statistics.average_score = Average score
statistics.median_score = Median score statistics.median_score = Median score
statistics.pass_fail = Pass/Fail statistics.pass_fail = Pass/Fail
......
...@@ -47,6 +47,10 @@ ...@@ -47,6 +47,10 @@
<span th:text="#{statistics.total_submissions}"></span> <span th:text="#{statistics.total_submissions}"></span>
<span th:text="${statistics.totalSubmissions}"></span> <span th:text="${statistics.totalSubmissions}"></span>
</div> </div>
<div class="flex space-between underlined pil-3">
<span th:text="#{statistics.avgSubmissionsToPass}"></span>
<span th:text="${statistics.avgSubmissionsToPass}"></span>
</div>
</div> </div>
<th:block <th:block
th:if="${statistics.averageScore != null or statistics.medianScore != null}"> th:if="${statistics.averageScore != null or statistics.medianScore != null}">
......
...@@ -410,6 +410,7 @@ class StatisticsServiceTest { ...@@ -410,6 +410,7 @@ class StatisticsServiceTest {
.totalSubmissions(2) .totalSubmissions(2)
.averageScore(1.0) .averageScore(1.0)
.medianScore(1.0) .medianScore(1.0)
.avgSubmissionsToPass(2.0)
.scoreDistribution(new Integer[] { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 }) .scoreDistribution(new Integer[] { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 })
.passFailDistribution(new Integer[] { 1, 0, 0, 0, 1 }) .passFailDistribution(new Integer[] { 1, 0, 0, 0, 1 })
.build()); .build());
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please to comment