Compare commits
No commits in common. "main" and "1.0-SNAPSHOT" have entirely different histories.
main
...
1.0-SNAPSH
|
@ -5,11 +5,8 @@ import org.apache.commons.csv.CSVRecord;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.regex.Matcher;
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
import static nl.andrewlalis.human_task_distributor.HumanTaskDistributor.CSV_FORMAT;
|
import static nl.andrewlalis.human_task_distributor.HumanTaskDistributor.CSV_FORMAT;
|
||||||
|
|
||||||
|
@ -77,20 +74,4 @@ public class FileParser {
|
||||||
}
|
}
|
||||||
return previousDistributions;
|
return previousDistributions;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set<Task> parseTaskList(String path, String regex) {
|
|
||||||
try {
|
|
||||||
String contents = String.join(" ", Files.readAllLines(Paths.get(path), StandardCharsets.UTF_8));
|
|
||||||
Pattern pattern = Pattern.compile(regex);
|
|
||||||
Matcher matcher = pattern.matcher(contents);
|
|
||||||
Set<Task> tasks = new HashSet<>();
|
|
||||||
while (matcher.find()) {
|
|
||||||
tasks.add(new Task(matcher.group()));
|
|
||||||
}
|
|
||||||
return tasks;
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
return new HashSet<>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,38 +0,0 @@
|
||||||
package nl.andrewlalis.human_task_distributor;
|
|
||||||
|
|
||||||
import org.apache.commons.csv.CSVPrinter;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.Paths;
|
|
||||||
import java.util.*;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import static nl.andrewlalis.human_task_distributor.HumanTaskDistributor.CSV_FORMAT;
|
|
||||||
|
|
||||||
public class FileWriter {
|
|
||||||
|
|
||||||
public void write(Map<Human, Set<Task>> taskDistributions, String filePath) throws IOException {
|
|
||||||
CSVPrinter printer = new CSVPrinter(Files.newBufferedWriter(Paths.get(filePath), StandardCharsets.UTF_8), CSV_FORMAT);
|
|
||||||
for (Map.Entry<Human, Set<Task>> entry : taskDistributions.entrySet()) {
|
|
||||||
Human human = entry.getKey();
|
|
||||||
Set<Task> assignedTasks = entry.getValue();
|
|
||||||
List<Task> sortedTasks = assignedTasks.stream().sorted(Comparator.comparing(Task::getName)).collect(Collectors.toList());
|
|
||||||
for (Task task : sortedTasks) {
|
|
||||||
printer.printRecord(human.getName(), task.getName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
printer.close(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void write(Set<Task> tasks, String filePath) throws IOException {
|
|
||||||
CSVPrinter printer = new CSVPrinter(Files.newBufferedWriter(Paths.get(filePath), StandardCharsets.UTF_8), CSV_FORMAT);
|
|
||||||
List<Task> orderedTasks = new ArrayList<>(tasks);
|
|
||||||
orderedTasks.sort(Task::compareTo);
|
|
||||||
for (Task t : orderedTasks) {
|
|
||||||
printer.printRecord(t.getName());
|
|
||||||
}
|
|
||||||
printer.close(true);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,9 +1,14 @@
|
||||||
package nl.andrewlalis.human_task_distributor;
|
package nl.andrewlalis.human_task_distributor;
|
||||||
|
|
||||||
import nl.andrewlalis.human_task_distributor.commands.DistributeTasks;
|
|
||||||
import nl.andrewlalis.human_task_distributor.commands.PrepareTasksList;
|
|
||||||
import org.apache.commons.cli.*;
|
import org.apache.commons.cli.*;
|
||||||
import org.apache.commons.csv.CSVFormat;
|
import org.apache.commons.csv.CSVFormat;
|
||||||
|
import org.apache.commons.csv.CSVPrinter;
|
||||||
|
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
public class HumanTaskDistributor {
|
public class HumanTaskDistributor {
|
||||||
public static final CSVFormat CSV_FORMAT = CSVFormat.RFC4180;
|
public static final CSVFormat CSV_FORMAT = CSVFormat.RFC4180;
|
||||||
|
@ -13,14 +18,41 @@ public class HumanTaskDistributor {
|
||||||
CommandLineParser cmdParser = new DefaultParser();
|
CommandLineParser cmdParser = new DefaultParser();
|
||||||
try {
|
try {
|
||||||
CommandLine cmd = cmdParser.parse(options, args);
|
CommandLine cmd = cmdParser.parse(options, args);
|
||||||
if (cmd.hasOption("ptl")) {
|
FileParser fileParser = new FileParser();
|
||||||
new PrepareTasksList().execute(cmd);
|
Map<Human, Float> nameWeightMap = fileParser.parseHumanList(cmd.getOptionValue("hl"));
|
||||||
} else if (cmd.hasOption("hl") && cmd.hasOption("tl")) {
|
Set<Task> tasks = fileParser.parseTaskList(cmd.getOptionValue("tl"));
|
||||||
new DistributeTasks().execute(cmd);
|
String[] previousDistributionPaths = cmd.getOptionValues("prev");
|
||||||
|
if (previousDistributionPaths == null) previousDistributionPaths = new String[0];
|
||||||
|
List<Map<Human, Set<Task>>> previousDistributions = fileParser.parsePreviousTaskDistributions(previousDistributionPaths);
|
||||||
|
|
||||||
|
long start = System.currentTimeMillis();
|
||||||
|
Map<Human, Set<Task>> taskDistributions = new Distributor().generateDistribution(nameWeightMap, tasks, previousDistributions);
|
||||||
|
long durationMillis = System.currentTimeMillis() - start;
|
||||||
|
System.out.printf(
|
||||||
|
"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";
|
||||||
|
CSVPrinter printer = new CSVPrinter(Files.newBufferedWriter(Paths.get(filePath), StandardCharsets.UTF_8), CSV_FORMAT);
|
||||||
|
for (Map.Entry<Human, Set<Task>> entry : taskDistributions.entrySet()) {
|
||||||
|
Human human = entry.getKey();
|
||||||
|
Set<Task> assignedTasks = entry.getValue();
|
||||||
|
List<Task> sortedTasks = assignedTasks.stream().sorted(Comparator.comparing(Task::getName)).collect(Collectors.toList());
|
||||||
|
for (Task task : sortedTasks) {
|
||||||
|
printer.printRecord(human.getName(), task.getName());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
throw new IllegalArgumentException("Invalid command.");
|
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());
|
||||||
|
e.printStackTrace();
|
||||||
HelpFormatter hf = new HelpFormatter();
|
HelpFormatter hf = new HelpFormatter();
|
||||||
hf.printHelp("HumanTaskDistributor", options);
|
hf.printHelp("HumanTaskDistributor", options);
|
||||||
System.exit(1);
|
System.exit(1);
|
||||||
|
@ -33,25 +65,16 @@ public class HumanTaskDistributor {
|
||||||
.longOpt("humans-list")
|
.longOpt("humans-list")
|
||||||
.hasArg(true)
|
.hasArg(true)
|
||||||
.desc("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.")
|
.desc("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.")
|
||||||
.required(false)
|
.required(true)
|
||||||
.numberOfArgs(1)
|
.numberOfArgs(1)
|
||||||
.type(String.class)
|
.type(String.class)
|
||||||
.build()
|
.build()
|
||||||
);
|
);
|
||||||
options.addOption(Option.builder("ptl")
|
|
||||||
.longOpt("prepare-tasks-list")
|
|
||||||
.desc("Prepares a tasks-list CSV from a TXT file with one task for each item that matches the given Regex.")
|
|
||||||
.required(false)
|
|
||||||
.numberOfArgs(2)
|
|
||||||
.valueSeparator(',')
|
|
||||||
.type(String.class)
|
|
||||||
.build()
|
|
||||||
);
|
|
||||||
options.addOption(Option.builder("tl")
|
options.addOption(Option.builder("tl")
|
||||||
.longOpt("tasks-list")
|
.longOpt("tasks-list")
|
||||||
.hasArg(true)
|
.hasArg(true)
|
||||||
.desc("Path to a CSV file containing list of tasks that can be distributed to humans. First column should be unique task name.")
|
.desc("Path to a CSV file containing list of tasks that can be distributed to humans. First column should be unique task name.")
|
||||||
.required(false)
|
.required(true)
|
||||||
.numberOfArgs(1)
|
.numberOfArgs(1)
|
||||||
.type(String.class)
|
.type(String.class)
|
||||||
.build()
|
.build()
|
||||||
|
|
|
@ -5,7 +5,7 @@ import lombok.Getter;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
public class Task implements Comparable<Task> {
|
public class Task {
|
||||||
private final String name;
|
private final String name;
|
||||||
|
|
||||||
public Task(String name) {
|
public Task(String name) {
|
||||||
|
@ -24,9 +24,4 @@ public class Task implements Comparable<Task> {
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return Objects.hash(getName());
|
return Objects.hash(getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public int compareTo(Task o) {
|
|
||||||
return this.getName().compareToIgnoreCase(o.getName());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
package nl.andrewlalis.human_task_distributor.commands;
|
|
||||||
|
|
||||||
import org.apache.commons.cli.CommandLine;
|
|
||||||
|
|
||||||
public interface Command {
|
|
||||||
|
|
||||||
void execute(CommandLine cmd);
|
|
||||||
}
|
|
|
@ -1,41 +0,0 @@
|
||||||
package nl.andrewlalis.human_task_distributor.commands;
|
|
||||||
|
|
||||||
import nl.andrewlalis.human_task_distributor.*;
|
|
||||||
import org.apache.commons.cli.CommandLine;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
public class DistributeTasks implements Command {
|
|
||||||
@Override
|
|
||||||
public void execute(CommandLine cmd) {
|
|
||||||
final FileParser fileParser = new FileParser();
|
|
||||||
final FileWriter fileWriter = new FileWriter();
|
|
||||||
Map<Human, Float> nameWeightMap = fileParser.parseHumanList(cmd.getOptionValue("hl"));
|
|
||||||
Set<Task> tasks = fileParser.parseTaskList(cmd.getOptionValue("tl"));
|
|
||||||
String[] previousDistributionPaths = cmd.getOptionValues("prev");
|
|
||||||
if (previousDistributionPaths == null) previousDistributionPaths = new String[0];
|
|
||||||
List<Map<Human, Set<Task>>> previousDistributions = fileParser.parsePreviousTaskDistributions(previousDistributionPaths);
|
|
||||||
|
|
||||||
long start = System.currentTimeMillis();
|
|
||||||
Map<Human, Set<Task>> taskDistributions = new Distributor().generateDistribution(nameWeightMap, tasks, previousDistributions);
|
|
||||||
long durationMillis = System.currentTimeMillis() - start;
|
|
||||||
System.out.printf(
|
|
||||||
"Created distribution of %d tasks to %d people in %d ms.%n",
|
|
||||||
tasks.size(),
|
|
||||||
taskDistributions.keySet().size(),
|
|
||||||
durationMillis
|
|
||||||
);
|
|
||||||
|
|
||||||
// Write to a file.
|
|
||||||
final String filePath = cmd.hasOption("o") ? cmd.getOptionValue("o") : "distribution.csv";
|
|
||||||
try {
|
|
||||||
fileWriter.write(taskDistributions, filePath);
|
|
||||||
System.out.println("Wrote task distribution data to " + filePath);
|
|
||||||
} catch (IOException e) {
|
|
||||||
System.err.println("Couldn't write to file: " + e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,31 +0,0 @@
|
||||||
package nl.andrewlalis.human_task_distributor.commands;
|
|
||||||
|
|
||||||
import nl.andrewlalis.human_task_distributor.FileParser;
|
|
||||||
import nl.andrewlalis.human_task_distributor.FileWriter;
|
|
||||||
import nl.andrewlalis.human_task_distributor.Task;
|
|
||||||
import org.apache.commons.cli.CommandLine;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
public class PrepareTasksList implements Command {
|
|
||||||
@Override
|
|
||||||
public void execute(CommandLine cmd) {
|
|
||||||
String[] values = cmd.getOptionValues("ptl");
|
|
||||||
if (values.length != 2) {
|
|
||||||
throw new IllegalArgumentException("Expected exactly 2 parameters for ptl arg.");
|
|
||||||
}
|
|
||||||
String filePath = values[0].trim();
|
|
||||||
String regex = values[1].trim();
|
|
||||||
Set<Task> tasks = new FileParser().parseTaskList(filePath, regex);
|
|
||||||
System.out.println("Read " + tasks.size() + " tasks from file.");
|
|
||||||
String outFilePath = filePath.replaceFirst("\\..*", ".csv");
|
|
||||||
try {
|
|
||||||
new FileWriter().write(tasks, outFilePath);
|
|
||||||
System.out.println("Wrote tasks to " + outFilePath);
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
System.err.println("Couldn't write output file.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue