package mtsar.processors.task;

import mtsar.api.Process;
import mtsar.api.Task;
import mtsar.api.TaskAllocation;
import mtsar.api.Worker;
import mtsar.api.sql.AnswerDAO;
import mtsar.api.sql.TaskDAO;
import mtsar.processors.TaskAllocator;

import javax.inject.Inject;
import javax.inject.Provider;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;

public class InverseCountAllocator implements TaskAllocator {
    public static final Comparator<Task> RANDOM_COMPARATOR = Comparator.comparing(t -> Math.random());

    protected final Provider<Process> process;
    protected final TaskDAO taskDAO;
    protected final AnswerDAO answerDAO;

    @Inject
    public InverseCountAllocator(Provider<Process> processProvider, TaskDAO taskDAO, AnswerDAO answerDAO) {
        this.process = processProvider;
        this.taskDAO = taskDAO;
        this.answerDAO = answerDAO;
    }

    @Override
    public Optional<TaskAllocation> allocate(Worker worker) {
        final Comparator<Task> comparator = getComparator(answerDAO).thenComparing(RANDOM_COMPARATOR);
        final List<Task> tasks = taskDAO.listForProcess(process.get().getId());
        final Optional<Task> task = tasks.stream().sorted(comparator).findFirst();
        if (!task.isPresent()) return Optional.empty();
        return Optional.of(new TaskAllocation(worker, task.get()));
    }

    private Comparator<Task> getComparator(AnswerDAO answerDAO) {
        return Comparator.comparing(task -> answerDAO.listForTask(task.getId(), process.get().getId()).size());
    }
}

@@ -309,26 +309,69 @@
 va.util.
-Comparator
+List;%0Aimport java.util.Map;%0Aimport java.util.Optional
 ;%0Aimport
@@ -373,36 +373,49 @@
 mport java.util.
-List
+function.Function
 ;%0Aimport java.ut
@@ -417,24 +417,33 @@
 va.util.
-Optional
+stream.Collectors
 ;%0A%0Apubli
@@ -503,112 +503,8 @@
 r %7B%0A
-    public static final Comparator%3CTask%3E RANDOM_COMPARATOR = Comparator.comparing(t -%3E Math.random());%0A%0A
     
@@ -948,460 +948,566 @@
     
-final Comparator%3CTask%3E comparator = getComparator(answerDAO).thenComparing(RANDOM_COMPARATOR);%0A        final List%3CTask%3E tasks = taskDAO.listForProcess(process.get().getId());%0A        final Optional%3CTask%3E task = tasks.stream().sorted(comparator).findFirst();%0A        if (!task.isPresent()) return Optional.empty();%0A        return Optional.of(new TaskAllocation(worker, task
+List%3CTask%3E tasks = taskDAO.listForProcess(process.get().getId());%0A        if (tasks.isEmpty()) return Optional.empty();%0A%0A        final Map%3CTask, Integer%3E counts = tasks.parallelStream().collect(%0A                Collectors.toMap(Function.identity(), t -%3E answerDAO.listForTask(t.getId(), process.get().getId()).size())%0A        );%0A%0A        tasks.sort((t1, t2) -%3E %7B%0A            final int countsComparison = counts.get(t1).compareTo(counts
 .get(
+t2
 ))
-)
 ;%0A    
-%7D%0A%0A    private Comparator%3CTask%3E getComparator(AnswerDAO answerDAO)
+        if (countsComparison == 0) %7B%0A                return Math.random() %3E 0.5 ? 1 : -1;%0A            %7D else
  %7B%0A 
@@ -1517,108 +1517,134 @@
     
+ 
-return Comparator.comparing(task -%3E answerDAO.listForTask(task.getId(), process.get().getId()).size(
+       return countsComparison;%0A            %7D%0A        %7D);%0A%0A        return Optional.of(new TaskAllocation(worker, tasks.get(0)
 ));%0A

Optimize InverseCountAllocator