summaryrefslogtreecommitdiff
path: root/src/main/java/com/stileeducation/markr/service/TestResultsService.java
blob: 95b42f30d84ae90fb699ac163052e732d4cec85a (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
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.apache.commons.math3.stat.descriptive.moment.StandardDeviation;
import org.apache.commons.math3.stat.descriptive.rank.Percentile;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Optional;

@Service
public class TestResultsService {

  public static final boolean IS_BIAS_CORRECTED = false;
  @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) {
    if (results.isEmpty()) {
      return 0.0;
    }
    double[] marks =
        results.stream()
            .mapToDouble(TestResult::getMarksAwarded)
            .toArray();

    StandardDeviation standardDeviation = new StandardDeviation(IS_BIAS_CORRECTED);
    return standardDeviation.evaluate(marks);
  }

  public double calculate25thPercentile(List<TestResult> results) {
    if (results.isEmpty()) {
      return 0.0;
    }
    double[] marks =
        results.stream()
            .mapToDouble(TestResult::getMarksAwarded)
            .toArray();
    return new Percentile().evaluate(marks, 25.0);
  }

  public double calculate50thPercentile(List<TestResult> results) {
    if (results.isEmpty()) {
      return 0.0;
    }
    double[] marks =
        results.stream()
            .mapToDouble(TestResult::getMarksAwarded)
            .toArray();
    return new Percentile().evaluate(marks, 50.0);
  }

  public double calculate75thPercentile(List<TestResult> results) {
    if (results.isEmpty()) {
      return 0.0;
    }
    double[] marks =
        results.stream()
            .mapToDouble(TestResult::getMarksAwarded)
            .toArray();
    return new Percentile().evaluate(marks, 75.0);
  }

  public AggregatedTestResultsDTO aggregateTestResults(String testId) {
    List<TestResult> testResults = findAllByTestId(testId);

    AggregatedTestResultsDTO results = new AggregatedTestResultsDTO();

    results.setMean(calculateMeanOfTestResults(testResults));
    results.setStddev(calculateStandardDeviationOfTestResults(testResults));
    results.setMin(calculateMinOfTestResults(testResults));
    results.setMax(calculateMaxOfTestResults(testResults));
    results.setP25(calculate25thPercentile(testResults));
    results.setP50(calculate50thPercentile(testResults));
    results.setP75(calculate75thPercentile(testResults));
    results.setCount(testResults.size());

    return results;
  }

}