Cleaned up some things.
This commit is contained in:
parent
f580857c14
commit
7207eeb6c2
23
README.md
23
README.md
|
@ -1,2 +1,25 @@
|
||||||
# HumanTaskDistributor
|
# HumanTaskDistributor
|
||||||
Simple command-line tool that helps automate the process of distributing sets of tasks to many people, including weighted preference and historical variation.
|
Simple command-line tool that helps automate the process of distributing sets of tasks to many people, including weighted preference and historical variation.
|
||||||
|
|
||||||
|
## Help
|
||||||
|
```
|
||||||
|
usage: HumanTaskDistributor
|
||||||
|
-hl,--humans-list <arg> Path to a CSV file containing list
|
||||||
|
of humans to distribute tasks to.
|
||||||
|
First column should be the name of
|
||||||
|
the person, and second column can
|
||||||
|
be empty, or contain a
|
||||||
|
floating-point weight.
|
||||||
|
-o,--output <arg> Output file to write CSV
|
||||||
|
distribution data to.
|
||||||
|
-prev,--previous-distributions <arg> One or more CSV files containing
|
||||||
|
previous task distribution
|
||||||
|
results, to aid in balancing
|
||||||
|
distribution over multiple
|
||||||
|
iterations. Each should be of the
|
||||||
|
form: person name, task name
|
||||||
|
-tl,--tasks-list <arg> Path to a CSV file containing list
|
||||||
|
of tasks that can be distributed
|
||||||
|
to humans. First column should be
|
||||||
|
unique task name.
|
||||||
|
```
|
||||||
|
|
|
@ -22,6 +22,7 @@ public class Distributor {
|
||||||
final float totalWeight = weightedHumans.values().stream().reduce(Float::sum).orElse(0.0f);
|
final float totalWeight = weightedHumans.values().stream().reduce(Float::sum).orElse(0.0f);
|
||||||
final float averageTasksPerHuman = unweightedAverageTasksPerHuman / (totalWeight / taskDistributions.size());
|
final float averageTasksPerHuman = unweightedAverageTasksPerHuman / (totalWeight / taskDistributions.size());
|
||||||
|
|
||||||
|
// Precompute the theoretical maximum number of tasks that each person should be assigned.
|
||||||
Map<Human, Float> maxTasksPerHuman = new HashMap<>();
|
Map<Human, Float> maxTasksPerHuman = new HashMap<>();
|
||||||
weightedHumans.forEach((h, w) -> maxTasksPerHuman.put(h, w * averageTasksPerHuman));
|
weightedHumans.forEach((h, w) -> maxTasksPerHuman.put(h, w * averageTasksPerHuman));
|
||||||
|
|
||||||
|
@ -30,6 +31,7 @@ public class Distributor {
|
||||||
taskStack.addAll(tasks);
|
taskStack.addAll(tasks);
|
||||||
Collections.shuffle(taskStack);
|
Collections.shuffle(taskStack);
|
||||||
|
|
||||||
|
// Iteratively pop and assign each task to a person.
|
||||||
while (!taskStack.empty()) {
|
while (!taskStack.empty()) {
|
||||||
Task t = taskStack.pop();
|
Task t = taskStack.pop();
|
||||||
Human h = this.chooseHumanForNextTask(
|
Human h = this.chooseHumanForNextTask(
|
||||||
|
|
|
@ -25,11 +25,18 @@ public class HumanTaskDistributor {
|
||||||
Map<Human, Float> nameWeightMap = fileParser.parseHumanList(cmd.getOptionValue("hl"));
|
Map<Human, Float> nameWeightMap = fileParser.parseHumanList(cmd.getOptionValue("hl"));
|
||||||
Set<Task> tasks = fileParser.parseTaskList(cmd.getOptionValue("tl"));
|
Set<Task> tasks = fileParser.parseTaskList(cmd.getOptionValue("tl"));
|
||||||
List<Map<Human, Set<Task>>> previousDistributions = fileParser.parsePreviousTaskDistributions(cmd.getOptionValues("prev"));
|
List<Map<Human, Set<Task>>> previousDistributions = fileParser.parsePreviousTaskDistributions(cmd.getOptionValues("prev"));
|
||||||
|
|
||||||
|
long start = System.currentTimeMillis();
|
||||||
Map<Human, Set<Task>> taskDistributions = new Distributor().generateDistribution(nameWeightMap, tasks, previousDistributions);
|
Map<Human, Set<Task>> taskDistributions = new Distributor().generateDistribution(nameWeightMap, tasks, previousDistributions);
|
||||||
taskDistributions.forEach((key, value) -> {
|
long durationMillis = System.currentTimeMillis() - start;
|
||||||
System.out.println("Task distribution for " + key + ", " + value.size() + " tasks:");
|
System.out.printf(
|
||||||
value.forEach(t -> System.out.println("\t" + t.getName()));
|
"Completed distribution of %d tasks to %d people in %d ms.%n",
|
||||||
});
|
tasks.size(),
|
||||||
|
taskDistributions.keySet().size(),
|
||||||
|
durationMillis
|
||||||
|
);
|
||||||
|
|
||||||
|
// Write to a file.
|
||||||
String filePath = cmd.hasOption("o") ? cmd.getOptionValue("o") : "distribution.csv";
|
String filePath = cmd.hasOption("o") ? cmd.getOptionValue("o") : "distribution.csv";
|
||||||
CSVPrinter printer = new CSVPrinter(Files.newBufferedWriter(Paths.get(filePath), StandardCharsets.UTF_8), CSV_FORMAT);
|
CSVPrinter printer = new CSVPrinter(Files.newBufferedWriter(Paths.get(filePath), StandardCharsets.UTF_8), CSV_FORMAT);
|
||||||
for (Map.Entry<Human, Set<Task>> entry : taskDistributions.entrySet()) {
|
for (Map.Entry<Human, Set<Task>> entry : taskDistributions.entrySet()) {
|
||||||
|
@ -41,6 +48,9 @@ public class HumanTaskDistributor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
printer.close(true);
|
printer.close(true);
|
||||||
|
|
||||||
|
System.out.println("Wrote task distribution data to " + filePath);
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
System.err.println("Error: " + e.getMessage());
|
System.err.println("Error: " + e.getMessage());
|
||||||
HelpFormatter hf = new HelpFormatter();
|
HelpFormatter hf = new HelpFormatter();
|
||||||
|
|
|
@ -1,32 +0,0 @@
|
||||||
package nl.andrewlalis.human_task_distributor;
|
|
||||||
|
|
||||||
import lombok.Getter;
|
|
||||||
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
public class TaskDistribution {
|
|
||||||
private final Human human;
|
|
||||||
private final float weight;
|
|
||||||
private final Set<Task> tasks;
|
|
||||||
|
|
||||||
public TaskDistribution(Human human, float weight, Set<Task> tasks) {
|
|
||||||
this.human = human;
|
|
||||||
this.weight = weight;
|
|
||||||
this.tasks = tasks;
|
|
||||||
}
|
|
||||||
|
|
||||||
public TaskDistribution(Human human, float weight) {
|
|
||||||
this(human, weight, new HashSet<>());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "TaskDistribution{" +
|
|
||||||
"human=" + human +
|
|
||||||
", weight=" + weight +
|
|
||||||
", tasks=" + tasks +
|
|
||||||
'}';
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue