diff options
Diffstat (limited to 'src')
5 files changed, 255 insertions, 36 deletions
diff --git a/src/main/java/com/stileeducation/markr/controller/TestResultsController.java b/src/main/java/com/stileeducation/markr/controller/TestResultsController.java index 5667027..c69492d 100644 --- a/src/main/java/com/stileeducation/markr/controller/TestResultsController.java +++ b/src/main/java/com/stileeducation/markr/controller/TestResultsController.java @@ -1,8 +1,17 @@ package com.stileeducation.markr.controller; import com.stileeducation.markr.dto.AggregatedTestResultsDTO; +import com.stileeducation.markr.dto.MCQTestResultDTO; 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.TestRepository; +import com.stileeducation.markr.repository.TestResultRepository; +import com.stileeducation.markr.service.StudentService; import com.stileeducation.markr.service.TestResultsService; +import com.stileeducation.markr.service.TestService; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; @@ -14,7 +23,20 @@ public class TestResultsController { public static final String IMPORT_ENDPOINT = "/import"; public static final String AGGREGATE_ENDPOINT = "/results/{test-id}/aggregate"; - private final TestResultsService testResultsService; + @Autowired + private StudentService studentService; + + @Autowired + private TestService testService; + + @Autowired + private TestResultsService testResultsService; + + @Autowired + private TestRepository testRepository; + + @Autowired + private TestResultRepository testResultRepository; public TestResultsController(TestResultsService testResultsService) { this.testResultsService = testResultsService; @@ -23,7 +45,39 @@ public class TestResultsController { // TODO consider return value @PostMapping(value = IMPORT_ENDPOINT, consumes = "text/xml+markr", produces = "application/json") public ResponseEntity<Void> handleXmlRequest(@RequestBody MCQTestResultsDTO testResults) { - testResultsService.importTestResults(testResults); + + for (MCQTestResultDTO mcqTestResult : testResults.getMcqTestResults()) { + Student student = studentService + .findOrCreateStudent( + mcqTestResult.getFirstName(), + mcqTestResult.getLastName(), + mcqTestResult.getStudentNumber()); + + Test test = testService + .findOrCreateTest( + mcqTestResult.getTestId(), + mcqTestResult.getSummaryMarks().getAvailable()); + + if (test.getMarksAvailable() < mcqTestResult.getSummaryMarks().getAvailable()) { + test.setMarksAvailable(mcqTestResult.getSummaryMarks().getAvailable()); + testRepository.save(test); + } + + // Some edge cases to consider + // obtained is higher than available (assumption?) + + TestResult testResult = testResultsService + .findOrCreateTestResult( + student.getId(), + test.getId(), + mcqTestResult.getSummaryMarks().getObtained()); + + if (testResult.getMarksAwarded() < mcqTestResult.getSummaryMarks().getObtained()) { + testResult.setMarksAwarded(mcqTestResult.getSummaryMarks().getObtained()); + testResultRepository.save(testResult); + } + } + return new ResponseEntity<>(HttpStatus.NO_CONTENT); } diff --git a/src/main/java/com/stileeducation/markr/service/StudentService.java b/src/main/java/com/stileeducation/markr/service/StudentService.java new file mode 100644 index 0000000..4af4d63 --- /dev/null +++ b/src/main/java/com/stileeducation/markr/service/StudentService.java @@ -0,0 +1,28 @@ +package com.stileeducation.markr.service; + +import com.stileeducation.markr.entity.Student; +import com.stileeducation.markr.repository.StudentRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.Optional; + +@Service +public class StudentService { + + @Autowired + private StudentRepository studentRepository; + + public Student findOrCreateStudent(String firstName, String lastName, String studentNumber) { + Optional<Student> optionalStudent = studentRepository.findByStudentNumber(studentNumber); + if (optionalStudent.isPresent()) { + return optionalStudent.get(); + } else { + Student student = new Student(); + student.setFirstName(firstName); + student.setLastName(lastName); + student.setStudentNumber(studentNumber); + return studentRepository.save(student); + } + } +} 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 diff --git a/src/main/java/com/stileeducation/markr/service/TestResultsServiceImpl.java b/src/main/java/com/stileeducation/markr/service/TestResultsServiceImpl.java deleted file mode 100644 index abb7f18..0000000 --- a/src/main/java/com/stileeducation/markr/service/TestResultsServiceImpl.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.stileeducation.markr.service; - -import com.stileeducation.markr.dto.AggregatedTestResultsDTO; -import com.stileeducation.markr.dto.MCQTestResultsDTO; -import org.springframework.stereotype.Service; - -@Service -public class TestResultsServiceImpl implements TestResultsService { - - @Override - public MCQTestResultsDTO importTestResults(MCQTestResultsDTO testResults) { - return testResults; - } - - @Override - public AggregatedTestResultsDTO aggregateTestResults(String testId) { - AggregatedTestResultsDTO results = new AggregatedTestResultsDTO(); - results.setMean(65.0); - results.setStddev(0.0); - results.setMin(65.0); - results.setMax(65.0); - results.setP25(65.0); - results.setP50(65.0); - results.setP75(65.0); - results.setCount(1); - return results; - } - -}
\ No newline at end of file diff --git a/src/main/java/com/stileeducation/markr/service/TestService.java b/src/main/java/com/stileeducation/markr/service/TestService.java new file mode 100644 index 0000000..f3ba98c --- /dev/null +++ b/src/main/java/com/stileeducation/markr/service/TestService.java @@ -0,0 +1,28 @@ +package com.stileeducation.markr.service; + +import com.stileeducation.markr.entity.Test; +import com.stileeducation.markr.repository.TestRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.Optional; + +@Service +public class TestService { + + @Autowired + TestRepository testRepository; + + public Test findOrCreateTest(String testId, Integer marksAvailable) { + Optional<Test> optionalTest = testRepository.findByTestId(testId); + if (optionalTest.isPresent()) { + return optionalTest.get(); + } else { + Test test = new Test(); + test.setTestId(testId); + test.setMarksAvailable(marksAvailable); + return testRepository.save(test); + } + } + +} |
