Refactor CSV and Net loading to use InputStream for better flexibility
This commit is contained in:
@@ -3,31 +3,83 @@ package net.berack.upo.valpre;
|
||||
import java.io.File;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
|
||||
public class Main {
|
||||
public static void main(String[] args) throws Exception {
|
||||
public static void main(String[] args) {
|
||||
if (args.length == 0)
|
||||
exit();
|
||||
exit("No program specified!");
|
||||
|
||||
var subArgs = Arrays.copyOfRange(args, 1, args.length);
|
||||
switch (args[0]) {
|
||||
case "simulation":
|
||||
var sim = new Simulation(subArgs);
|
||||
sim.run();
|
||||
break;
|
||||
case "plot":
|
||||
var plot = new Plot(subArgs);
|
||||
plot.show();
|
||||
break;
|
||||
default:
|
||||
exit();
|
||||
try {
|
||||
var program = args[0];
|
||||
var subArgs = Arrays.copyOfRange(args, 1, args.length);
|
||||
var param = Main.getParameters(program, subArgs);
|
||||
switch (program) {
|
||||
case "simulation" -> {
|
||||
var net = param.get("net");
|
||||
var csv = param.get("csv");
|
||||
var runs = param.getOrDefault("runs", Integer::parseInt, 100);
|
||||
var seed = param.getOrDefault("seed", Long::parseLong, 2007539552L);
|
||||
var p = param.getOrDefault("p", Boolean::parseBoolean, false);
|
||||
|
||||
var sim = new Simulation(net, seed, runs, p, csv);
|
||||
sim.run();
|
||||
}
|
||||
case "plot" -> {
|
||||
var csv = param.get("csv");
|
||||
var plot = new Plot(csv);
|
||||
plot.show();
|
||||
}
|
||||
default -> exit("Invalid program!");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
exit(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public static void exit() throws URISyntaxException {
|
||||
var uri = Main.class.getProtectionDomain().getCodeSource().getLocation().toURI();
|
||||
var name = new File(uri).getName();
|
||||
System.out.println("Usage: java -jar " + name + ".jar [simulation|plot] [args]");
|
||||
System.exit(1);
|
||||
/**
|
||||
* Get the parameters from the arguments.
|
||||
*
|
||||
* @param program the program to run
|
||||
* @param args the arguments to parse
|
||||
* @return the parameters
|
||||
*/
|
||||
private static Parameters getParameters(String program, String[] args) {
|
||||
var arguments = new HashMap<String, Boolean>();
|
||||
arguments.put("p", false);
|
||||
arguments.put("seed", true);
|
||||
arguments.put("runs", true);
|
||||
arguments.put("net", true);
|
||||
arguments.put("csv", true);
|
||||
|
||||
var descriptions = new HashMap<String, String>();
|
||||
descriptions.put("p", "Add this if you want the simulation to use threads (one each run).");
|
||||
descriptions.put("seed", "The seed of the simulation.");
|
||||
descriptions.put("runs", "How many runs the simulator should run.");
|
||||
descriptions.put("net", "The file net to use. Use example1.net or example2.net for the provided ones.");
|
||||
|
||||
var csvDesc = switch (program) {
|
||||
case "simulation" -> "The filename for saving every run statistics.";
|
||||
case "plot" -> "The filename that contains the previous saved runs.";
|
||||
default -> "";
|
||||
};
|
||||
descriptions.put("csv", csvDesc);
|
||||
|
||||
return Parameters.getArgsOrHelper(args, "-", arguments, descriptions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Exit the program with an error message.
|
||||
*/
|
||||
public static void exit(String message) {
|
||||
try {
|
||||
var uri = Main.class.getProtectionDomain().getCodeSource().getLocation().toURI();
|
||||
var name = new File(uri).getName();
|
||||
System.out.println(message);
|
||||
System.out.println("Usage: java -jar " + name + ".jar [simulation|plot] [args]");
|
||||
System.exit(1);
|
||||
} catch (URISyntaxException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,11 @@
|
||||
package net.berack.upo.valpre;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.InputStream;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* Class that helps with parsing the parameters passed as input in the console.
|
||||
@@ -9,6 +13,7 @@ import java.util.Map;
|
||||
public class Parameters {
|
||||
private final Map<String, Boolean> arguments;
|
||||
private final String prefix;
|
||||
private Map<String, String> parameters;
|
||||
|
||||
/**
|
||||
* Constructs a new Parameters object with the specified prefix and arguments.
|
||||
@@ -27,6 +32,41 @@ public class Parameters {
|
||||
this.prefix = prefix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the size of the parameters.
|
||||
*
|
||||
* @return the size of the parameters
|
||||
*/
|
||||
public int size() {
|
||||
return this.parameters.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of the argument passed as input.
|
||||
*
|
||||
* @param key the key of the argument
|
||||
* @return the value of the argument
|
||||
*/
|
||||
public String get(String key) {
|
||||
if (this.parameters == null)
|
||||
return null;
|
||||
return this.parameters.get(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value from the arguments or the default value if it is not present.
|
||||
*
|
||||
* @param key The key to get the value from.
|
||||
* @param parse The function to parse the value.
|
||||
* @param value The default value if the key is not present.
|
||||
* @return The value from the arguments or the default value if it is not
|
||||
* present.
|
||||
*/
|
||||
public <T> T getOrDefault(String key, Function<String, T> parse, T value) {
|
||||
var arg = this.get(key);
|
||||
return arg != null ? parse.apply(arg) : value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a string with the standard <arggument> <description> spaced enough
|
||||
*
|
||||
@@ -68,20 +108,21 @@ public class Parameters {
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the arguments passed and returns a map of Argument --> Value that can
|
||||
* Parse the arguments passed and build a map of Argument --> Value that can
|
||||
* be used to retrieve the information. In the case that the arguments are not
|
||||
* in the correct format then an exception is thrown.
|
||||
* To get the arguments use the {@link #get(String)} method.
|
||||
*
|
||||
* @param args the arguments in input
|
||||
* @throws IllegalArgumentException if the arguments are not formatted correctly
|
||||
* or if there is an unknown argument
|
||||
* @return a map of the values
|
||||
* or if there is an unknown argument or there
|
||||
* are not arguments in the input
|
||||
*/
|
||||
public Map<String, String> parse(String[] args) {
|
||||
var result = new HashMap<String, String>();
|
||||
public void parse(String[] args) {
|
||||
if (args == null || args.length == 0)
|
||||
return result;
|
||||
throw new IllegalArgumentException("No arguments passed");
|
||||
|
||||
var result = new HashMap<String, String>();
|
||||
for (var i = 0; i < args.length; i += 1) {
|
||||
var current = args[i];
|
||||
var next = i + 1 < args.length ? args[i + 1] : null;
|
||||
@@ -91,7 +132,7 @@ public class Parameters {
|
||||
i += 1;
|
||||
}
|
||||
|
||||
return result;
|
||||
this.parameters = result;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -121,7 +162,7 @@ public class Parameters {
|
||||
result.put(current, "");
|
||||
|
||||
if (finalSize != result.size())
|
||||
throw new IllegalArgumentException("Argument unknown");
|
||||
throw new IllegalArgumentException("Unknown argument [" + current + "]");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -129,6 +170,7 @@ public class Parameters {
|
||||
* Parse the arguments passed and returns a map of Argument --> Value that can
|
||||
* be used to retrieve the information. In the case that the arguments are not
|
||||
* in the correct format then an exception is thrown and the helper is printed.
|
||||
* If the arguments passed are 0 then the helper is printed.
|
||||
*
|
||||
* @param args the arguments in input
|
||||
* @param prefix the prefix to be used
|
||||
@@ -139,12 +181,13 @@ public class Parameters {
|
||||
* or if there is an unknown argument
|
||||
* @return a map of the values
|
||||
*/
|
||||
public static Map<String, String> getArgsOrHelper(String[] args, String prefix, Map<String, Boolean> arguments,
|
||||
public static Parameters getArgsOrHelper(String[] args, String prefix, Map<String, Boolean> arguments,
|
||||
Map<String, String> descriptions) {
|
||||
|
||||
var param = new Parameters(prefix, arguments);
|
||||
try {
|
||||
return param.parse(args);
|
||||
param.parse(args);
|
||||
return param;
|
||||
} catch (IllegalArgumentException e) {
|
||||
System.out.println(e.getMessage());
|
||||
System.out.println(param.helper(descriptions));
|
||||
@@ -157,10 +200,17 @@ public class Parameters {
|
||||
*
|
||||
* @param file the file to get
|
||||
* @return the file or the example file
|
||||
* @throws FileNotFoundException if the file is not found
|
||||
*/
|
||||
public static String getFileOrExample(String file) {
|
||||
if (file.startsWith("example"))
|
||||
file = Main.class.getClassLoader().getResource(file).getPath();
|
||||
return file;
|
||||
public static InputStream getFileOrExample(String file) throws FileNotFoundException {
|
||||
if (file == null)
|
||||
return null;
|
||||
|
||||
if (file.startsWith("example")) {
|
||||
var resource = Parameters.class.getClassLoader().getResourceAsStream(file);
|
||||
if (resource != null)
|
||||
return resource;
|
||||
}
|
||||
return new FileInputStream(file);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,8 +3,6 @@ package net.berack.upo.valpre;
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Font;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.Box;
|
||||
@@ -42,13 +40,13 @@ public class Plot {
|
||||
* @param args the arguments to create the plot
|
||||
* @throws IOException if anything happens while reading the file
|
||||
*/
|
||||
public Plot(String[] args) throws IOException {
|
||||
var arguments = Plot.parseParameters(args);
|
||||
var file = Parameters.getFileOrExample(arguments.get("csv"));
|
||||
if (file == null)
|
||||
throw new IllegalArgumentException("CSV file needed! Use -csv <file>");
|
||||
public Plot(String csv) throws IOException {
|
||||
var stream = Parameters.getFileOrExample(csv);
|
||||
if (stream == null)
|
||||
throw new IllegalArgumentException("CSV file needed!");
|
||||
var results = CsvResult.loadResults(stream);
|
||||
stream.close();
|
||||
|
||||
var results = new CsvResult(file).loadResults();
|
||||
this.summary = new ResultSummary(results);
|
||||
|
||||
var nodes = this.summary.getNodes().toArray(new String[0]);
|
||||
@@ -157,22 +155,6 @@ public class Plot {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the arguments to get the CSV file.
|
||||
*
|
||||
* @param args the arguments to parse
|
||||
* @return a map with the arguments
|
||||
*/
|
||||
private static Map<String, String> parseParameters(String[] args) {
|
||||
var arguments = new HashMap<String, Boolean>();
|
||||
arguments.put("csv", true);
|
||||
|
||||
var descriptions = new HashMap<String, String>();
|
||||
descriptions.put("csv", "The filename that contains the previous saved runs.");
|
||||
|
||||
return Parameters.getArgsOrHelper(args, "-", arguments, descriptions);
|
||||
}
|
||||
|
||||
/**
|
||||
* This class is used to create a panel with a name and a value.
|
||||
* The name is on the left and the value is on the right.
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
package net.berack.upo.valpre;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.function.Function;
|
||||
|
||||
import com.esotericsoftware.kryo.KryoException;
|
||||
|
||||
import net.berack.upo.valpre.sim.Net;
|
||||
@@ -21,24 +18,32 @@ public class Simulation {
|
||||
public final int runs;
|
||||
public final long seed;
|
||||
public final boolean parallel;
|
||||
public final String file;
|
||||
public final Net net;
|
||||
|
||||
/**
|
||||
* Create a new simulation with the given arguments.
|
||||
*
|
||||
* @param args The arguments for the simulation.
|
||||
* @throws IOException if the file is has a problem
|
||||
*/
|
||||
public Simulation(String[] args) {
|
||||
// Evantually change the parameters
|
||||
var arguments = Simulation.parseParameters(args);
|
||||
this.runs = Simulation.getFromArguments(arguments, "runs", Integer::parseInt, 100);
|
||||
this.seed = Simulation.getFromArguments(arguments, "seed", Long::parseLong, 2007539552L);
|
||||
this.csv = arguments.getOrDefault("csv", null);
|
||||
this.parallel = arguments.containsKey("p");
|
||||
public Simulation(String netFile, long seed, int runs, boolean parallel, String csv) throws IOException {
|
||||
if (runs <= 0)
|
||||
throw new IllegalArgumentException("Runs must be greater than 0!");
|
||||
|
||||
this.file = Parameters.getFileOrExample(arguments.get("net"));
|
||||
if (this.file == null)
|
||||
throw new IllegalArgumentException("Net file needed! Use -net <file>");
|
||||
this.runs = runs;
|
||||
this.seed = seed;
|
||||
this.csv = csv;
|
||||
this.parallel = parallel;
|
||||
|
||||
try {
|
||||
var file = Parameters.getFileOrExample(netFile);
|
||||
this.net = Net.load(file);
|
||||
file.close();
|
||||
} catch (FileNotFoundException e) {
|
||||
throw new IllegalArgumentException("Net file needed!");
|
||||
} catch (KryoException e) {
|
||||
throw new IllegalArgumentException("Net file is not valid or corrupted!");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -51,9 +56,8 @@ public class Simulation {
|
||||
* @throws IOException If the simulation fails.
|
||||
*/
|
||||
public void run() throws InterruptedException, ExecutionException, KryoException, IOException {
|
||||
var net = Net.load(this.file);
|
||||
var nano = System.nanoTime();
|
||||
var sim = new SimulationMultiple(net);
|
||||
var sim = new SimulationMultiple(this.net);
|
||||
var summary = this.parallel ? sim.runParallel(this.seed, this.runs) : sim.run(this.seed, this.runs);
|
||||
nano = System.nanoTime() - nano;
|
||||
|
||||
@@ -65,45 +69,4 @@ public class Simulation {
|
||||
System.out.println("Data saved to " + this.csv);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value from the arguments or the default value if it is not present.
|
||||
*
|
||||
* @param args The arguments for the simulation.
|
||||
* @param key The key to get the value from.
|
||||
* @param parse The function to parse the value.
|
||||
* @param value The default value if the key is not present.
|
||||
* @return The value from the arguments or the default value if it is not
|
||||
* present.
|
||||
*/
|
||||
private static <T> T getFromArguments(Map<String, String> args, String key, Function<String, T> parse, T value) {
|
||||
if (args.containsKey(key))
|
||||
return parse.apply(args.get(key));
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the arguments for the simulation.
|
||||
*
|
||||
* @param args The arguments for the simulation.
|
||||
* @return The parsed arguments for the simulation.
|
||||
*/
|
||||
private static Map<String, String> parseParameters(String[] args) {
|
||||
var arguments = new HashMap<String, Boolean>();
|
||||
arguments.put("p", false);
|
||||
arguments.put("seed", true);
|
||||
arguments.put("runs", true);
|
||||
arguments.put("net", true);
|
||||
arguments.put("csv", true);
|
||||
|
||||
var descriptions = new HashMap<String, String>();
|
||||
descriptions.put("p", "Add this if you want the simulation to use threads (one each run).");
|
||||
descriptions.put("seed", "The seed of the simulation.");
|
||||
descriptions.put("runs", "How many runs the simulator should run.");
|
||||
descriptions.put("net",
|
||||
"The net to use. It should be a file. Use example1.net or example2.net for the provided ones.");
|
||||
descriptions.put("csv", "The filename for saving every run statistics.");
|
||||
|
||||
return Parameters.getArgsOrHelper(args, "-", arguments, descriptions);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,8 @@ package net.berack.upo.valpre.sim;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
@@ -250,15 +252,29 @@ public final class Net {
|
||||
*
|
||||
* @param file the file to load
|
||||
* @return a new Net object
|
||||
* @throws KryoException if the file saved is not a net
|
||||
* @throws FileNotFoundException if the file is not found
|
||||
* @throws KryoException if the file saved is not a net
|
||||
* @throws IOException if the file is not found
|
||||
*/
|
||||
public static Net load(String file) throws KryoException, FileNotFoundException {
|
||||
public static Net load(String file) throws KryoException, IOException {
|
||||
try (var stream = new FileInputStream(file)) {
|
||||
return Net.load(stream);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the net from the stream passed as input.
|
||||
* The net will be the same as the one saved.
|
||||
*
|
||||
* @param stream the input stream to read
|
||||
* @return a new Net object
|
||||
* @throws KryoException if the file saved is not a net
|
||||
*/
|
||||
public static Net load(InputStream stream) throws KryoException {
|
||||
var kryo = new Kryo();
|
||||
kryo.setRegistrationRequired(false);
|
||||
kryo.setInstantiatorStrategy(new StdInstantiatorStrategy());
|
||||
|
||||
try (var in = new Input(new FileInputStream(file))) {
|
||||
try (var in = new Input(stream)) {
|
||||
return (Net) kryo.readClassAndObject(in);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
package net.berack.upo.valpre.sim.stats;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
@@ -59,8 +60,20 @@ public class CsvResult {
|
||||
* @throws IOException if anything happens while reading the file
|
||||
*/
|
||||
public Result[] loadResults() throws IOException {
|
||||
try (var stream = new FileInputStream(this.file)) {
|
||||
return CsvResult.loadResults(stream);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the results from the CSV stream.
|
||||
*
|
||||
* @param input the input stream to read
|
||||
* @return the results loaded from the stream
|
||||
*/
|
||||
public static Result[] loadResults(InputStream input) {
|
||||
var results = new ArrayList<Result>();
|
||||
try (var scan = new Scanner(new File(this.file))) {
|
||||
try (var scan = new Scanner(input)) {
|
||||
var _ = scan.nextLine();
|
||||
|
||||
var nodes = new HashMap<String, Statistics>();
|
||||
|
||||
Reference in New Issue
Block a user