summaryrefslogtreecommitdiff
path: root/src/main/java/com/stileeducation/markr/service/TestResultsService.java
diff options
context:
space:
mode:
authorSzymon Szukalski <szymon@skas.io>2024-07-23 23:23:45 +1000
committerSzymon Szukalski <szymon@skas.io>2024-07-23 23:23:45 +1000
commitf08b2fa7e6a977a18d6b9f14fb73c18ec73ec5df (patch)
tree48ce214bc609130748b9630c2017000cafd29c2b /src/main/java/com/stileeducation/markr/service/TestResultsService.java
parentfa34f76ad8ebccb96012b45a4207532846cfa03f (diff)
Implement domain services
Implement core business logic for working with Student, Test, and TestResult.
Diffstat (limited to 'src/main/java/com/stileeducation/markr/service/TestResultsService.java')
-rw-r--r--src/main/java/com/stileeducation/markr/service/TestResultsService.java148
1 files changed, 143 insertions, 5 deletions
diff --git a/src/main/java/com/stileeducation/markr/service/TestResultsService.java b/src/main/java/com/stileeducation/markr/service/TestResultsService.java
index 2740e50..8d1b314 100644
--- a/src/main/java/com/stileeducation/markr/service/TestResultsService.java
+++ b/src/main/java/com/stileeducation/markr/service/TestResultsService.java
@@ -1,10 +1,148 @@
package com.stileeducation.markr.service;
import com.stileeducation.markr.dto.AggregatedTestResultsDTO;
-import com.stileeducation.markr.dto.MCQTestResultsDTO;
+import com.stileeducation.markr.entity.Student;
+import com.stileeducation.markr.entity.Test;
+import com.stileeducation.markr.entity.TestResult;
+import com.stileeducation.markr.repository.StudentRepository;
+import com.stileeducation.markr.repository.TestRepository;
+import com.stileeducation.markr.repository.TestResultRepository;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
-public interface TestResultsService {
- MCQTestResultsDTO importTestResults(MCQTestResultsDTO mcqTestResults);
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Collectors;
- AggregatedTestResultsDTO aggregateTestResults(String testId);
-}
+@Service
+public class TestResultsService {
+
+ @Autowired
+ private TestResultRepository testResultRepository;
+
+ @Autowired
+ private StudentRepository studentRepository;
+
+ @Autowired
+ private TestRepository testRepository;
+
+ public TestResult findOrCreateTestResult(Long studentId, Long testId, Integer marksAwarded) {
+ Student student = studentRepository.findById(studentId).orElseThrow(() -> new RuntimeException("Student not found"));
+ Test test = testRepository.findById(testId).orElseThrow(() -> new RuntimeException("Test not found"));
+
+ Optional<TestResult> optionalTestResult = testResultRepository.findByStudentAndTest(student, test);
+ if (optionalTestResult.isPresent()) {
+ return optionalTestResult.get();
+ } else {
+ TestResult testResult = new TestResult();
+ testResult.setStudent(student);
+ testResult.setTest(test);
+ testResult.setMarksAwarded(marksAwarded);
+ return testResultRepository.save(testResult);
+ }
+ }
+
+ public List<TestResult> findAllByTestId(String testId) {
+ return testResultRepository.findAllByTestId(testId);
+ }
+
+ public double calculateMeanOfTestResults(List<TestResult> results) {
+ if (results.isEmpty()) {
+ return 0.0;
+ }
+ return results.stream()
+ .mapToInt(TestResult::getMarksAwarded)
+ .average()
+ .orElse(0.0);
+ }
+
+ public double calculateMinOfTestResults(List<TestResult> results) {
+ if (results.isEmpty()) {
+ return 0.0;
+ }
+ return results
+ .stream()
+ .mapToDouble(TestResult::getMarksAwarded)
+ .min()
+ .orElse(0.0);
+ }
+
+ public double calculateMaxOfTestResults(List<TestResult> results) {
+ if (results.isEmpty()) {
+ return 0.0;
+ }
+ return results
+ .stream()
+ .mapToDouble(TestResult::getMarksAwarded)
+ .max()
+ .orElse(0.0);
+ }
+
+ public double calculateStandardDeviationOfTestResults(List<TestResult> results, double mean) {
+ if (results.isEmpty()) {
+ return 0.0; // or throw an exception if no results are found
+ }
+
+ // Calculate the variance
+ double variance = results.stream()
+ .mapToDouble(result -> Math.pow(result.getMarksAwarded() - mean, 2))
+ .average()
+ .orElse(0.0);
+
+ // Return the standard deviation
+ return Math.sqrt(variance);
+ }
+
+ public double calculatePercentile(List<Integer> sortedMarks, double percentile) {
+ if (sortedMarks.isEmpty()) {
+ return 0.0;
+ }
+ int index = (int) Math.floor(percentile / 100.0 * sortedMarks.size()) - 1;
+ return sortedMarks.get(Math.min(index, sortedMarks.size() - 1));
+ }
+
+ public List<Integer> getSortedMarks(List<TestResult> testResults) {
+ return testResults.stream()
+ .map(TestResult::getMarksAwarded)
+ .sorted()
+ .collect(Collectors.toList());
+ }
+
+ public double calculate25thPercentile(List<Integer> sortedMarks) {
+ return calculatePercentile(sortedMarks, 25.0);
+ }
+
+ public double calculate50thPercentile(List<Integer> sortedMarks) {
+ return calculatePercentile(sortedMarks, 50.0);
+ }
+
+ public double calculate75thPercentile(List<Integer> sortedMarks) {
+ return calculatePercentile(sortedMarks, 75.0);
+ }
+
+ public AggregatedTestResultsDTO aggregateTestResults(String testId) {
+ List<TestResult> testResults = findAllByTestId(testId);
+ List<Integer> sortedMarks = getSortedMarks(testResults);
+
+ AggregatedTestResultsDTO results = new AggregatedTestResultsDTO();
+
+ results.setMean(calculateMeanOfTestResults(testResults));
+
+ results.setStddev(calculateStandardDeviationOfTestResults(testResults, results.getMean()));
+
+ results.setMin(calculateMinOfTestResults(testResults));
+
+ results.setMax(calculateMaxOfTestResults(testResults));
+
+ results.setP25(calculate25thPercentile(sortedMarks));
+
+ results.setP50(calculate50thPercentile(sortedMarks));
+
+ results.setP75(calculate75thPercentile(sortedMarks));
+
+ results.setCount(testResults.size());
+
+ return results;
+ }
+
+} \ No newline at end of file