Here's my code that returns a mark based on average score of tests done by a person.
public Map<Person, String> defineMarks(Stream<CourseResult> results) {
return results.collect(Collectors.toMap(CourseResult::getPerson,x->{
double avg=x.getTaskResults().values().stream().collect(Collectors.summarizingInt(Integer::intValue)).getAverage();
if(avg > 90) return "A";
if(avg >= 83) return "B";
if(avg >= 75) return "C";
if(avg >= 68) return "D";
if(avg >= 60) return "E";
else return "F";
}));
}
For reference here's CourseResult class
public class CourseResult {
private final Person person;
private final Map<String, Integer> taskResults;
public CourseResult(final Person person, final Map<String, Integer> taskResults) {
this.person = person;
this.taskResults = taskResults;
}
public Person getPerson() {
return person;
}
public Map<String, Integer> getTaskResults() {
return taskResults;
}
}
and 2 methods that generates test scores. historyResults
private final String[] practicalHistoryTasks = {"Shieldwalling", "Phalanxing", "Wedging", "Tercioing"};
private Stream<CourseResult> historyResults(final Random random) {
int n = random.nextInt(names.length);
int l = random.nextInt(lastNames.length);
AtomicInteger t = new AtomicInteger(practicalHistoryTasks.length);
return IntStream.iterate(0, i -> i + 1)
.limit(3)
.mapToObj(i -> new Person(
names[(n + i) % names.length],
lastNames[(l + i) % lastNames.length],
18 + random.nextInt(20)))
.map(p -> new CourseResult(p,
IntStream.iterate(t.getAndIncrement(), i -> t.getAndIncrement())
.map(i -> i % practicalHistoryTasks.length)
.mapToObj(i -> practicalHistoryTasks[i])
.limit(3)
.collect(toMap(
task -> task,
task -> random.nextInt(51) + 50))));
}
and programmingResults
private final String[] programTasks = {"Lab 1. Figures", "Lab 2. War and Peace", "Lab 3. File Tree"};
private Stream<CourseResult> programmingResults(final Random random) {
int n = random.nextInt(names.length);
int l = random.nextInt(lastNames.length);
return IntStream.iterate(0, i -> i + 1)
.limit(3)
.mapToObj(i -> new Person(
names[(n + i) % names.length],
lastNames[(l + i) % lastNames.length],
18 + random.nextInt(20)))
.map(p -> new CourseResult(p, Arrays.stream(programTasks).collect(toMap(
task -> task,
task -> random.nextInt(51) + 50))));
}
So there are 3 test scores for each person. If I generate scores using programmingResults its fine because there are only 3 programming tests but if I generate scores using historyResults I also get 3 test scores per person but I should treat it as if the 4th test was not attempted at all which means 0 points for it. How can I make my defineMarks method get an average of collected test scores and in the case of historyResults get an average of collected test scores and a score of 0.
If my question is unclear please instruct me how to make it better :D