summaryrefslogtreecommitdiff
path: root/src/main/java/com/stileeducation/markr/service/TestResultsService.java
blob: 8d1b314f178416c7aecb073e50dd199d3d697feb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
package com.stileeducation.markr.service;

import com.stileeducation.markr.dto.AggregatedTestResultsDTO;
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;

import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

@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;
  }

}