Enhance NetBuilderInteractive to support interactive node creation and connection management, updating input/output handling and adding unit tests for functionality
This commit is contained in:
@@ -1,20 +1,47 @@
|
||||
package net.berack.upo.valpre;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.util.Scanner;
|
||||
import java.util.function.Function;
|
||||
import net.berack.upo.valpre.rand.Distribution;
|
||||
import net.berack.upo.valpre.sim.Net;
|
||||
import net.berack.upo.valpre.sim.ServerNode;
|
||||
|
||||
/**
|
||||
* Interactive net builder. This class allows the user to build a net by adding
|
||||
* nodes and connections. The user can also save the net to a file.
|
||||
*/
|
||||
public class NetBuilderInteractive {
|
||||
|
||||
private final Net net = new Net();
|
||||
private final PrintStream out;
|
||||
private final Scanner scanner;
|
||||
|
||||
/**
|
||||
* Create a new interactive net builder. Uses System.in and System.out.
|
||||
*/
|
||||
public NetBuilderInteractive() {
|
||||
this(System.out, System.in);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new interactive net builder.
|
||||
*
|
||||
* @param out the output stream
|
||||
* @param in the input stream
|
||||
*/
|
||||
public NetBuilderInteractive(PrintStream out, InputStream in) {
|
||||
this.out = out;
|
||||
this.scanner = new Scanner(in);
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the interactive net builder.
|
||||
*
|
||||
* @param args the arguments
|
||||
*/
|
||||
public void run() {
|
||||
public Net run() {
|
||||
while (true) {
|
||||
try {
|
||||
var choice = choose("Choose the next step to do:",
|
||||
@@ -32,9 +59,12 @@ public class NetBuilderInteractive {
|
||||
var targetNode = this.net.getNode(target);
|
||||
this.net.addConnection(sourceNode, targetNode, weight);
|
||||
}
|
||||
case 3 -> this.printNodes();
|
||||
case 3 -> this.out.println(this.net);
|
||||
case 4 -> this.net.save(ask("Enter the filename: "));
|
||||
case 5 -> System.exit(0);
|
||||
default -> {
|
||||
this.scanner.close();
|
||||
return this.net;
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
@@ -42,34 +72,13 @@ public class NetBuilderInteractive {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Print the nodes in the net.
|
||||
*/
|
||||
private void printNodes() {
|
||||
var builder = new StringBuilder();
|
||||
builder.append("Nodes:\n");
|
||||
for (var i = 0; i < this.net.size(); i++) {
|
||||
var name = this.net.getNode(i).name;
|
||||
builder.append(name).append(" -> ");
|
||||
|
||||
for (var connection : this.net.getChildren(i)) {
|
||||
var child = this.net.getNode(connection.index);
|
||||
builder.append(child.name).append("(").append(connection.weight).append("), ");
|
||||
}
|
||||
|
||||
builder.delete(builder.length() - 2, builder.length());
|
||||
builder.append("\n");
|
||||
}
|
||||
System.out.print(builder.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a node.
|
||||
*
|
||||
* @return the node
|
||||
*/
|
||||
private ServerNode buildNode() {
|
||||
var choice = choose("Choose the type of node to create:", "Source", "Queue");
|
||||
var choice = choose("Choose the type of node to create:", "Source", "Queue", "Queue with unavailable time");
|
||||
var name = ask("Node name: ");
|
||||
var distribution = askDistribution("Service distribution");
|
||||
|
||||
@@ -81,6 +90,10 @@ public class NetBuilderInteractive {
|
||||
yield ServerNode.Builder.sourceLimited(name, limit, distribution);
|
||||
}
|
||||
case 2 -> {
|
||||
var servers = ask("Number of servers: ", Integer::parseInt, 1);
|
||||
yield ServerNode.Builder.queue(name, servers, distribution, null);
|
||||
}
|
||||
case 3 -> {
|
||||
var servers = ask("Number of servers: ", Integer::parseInt, 1);
|
||||
var unavailable = askDistribution("Unavailable distribution");
|
||||
yield ServerNode.Builder.queue(name, servers, distribution, unavailable);
|
||||
@@ -94,7 +107,7 @@ public class NetBuilderInteractive {
|
||||
*
|
||||
* @return the distribution
|
||||
*/
|
||||
public static Distribution askDistribution(String ask) {
|
||||
private Distribution askDistribution(String ask) {
|
||||
var choice = choose(ask + ":", "Exponential", "Uniform", "Erlang",
|
||||
"UnavailableTime", "Normal", "NormalBoxMuller", "None");
|
||||
|
||||
@@ -138,7 +151,7 @@ public class NetBuilderInteractive {
|
||||
* @param ask the question to ask
|
||||
* @return the answer
|
||||
*/
|
||||
private static String ask(String ask) {
|
||||
private String ask(String ask) {
|
||||
return ask(ask, Function.identity(), "");
|
||||
}
|
||||
|
||||
@@ -150,13 +163,13 @@ public class NetBuilderInteractive {
|
||||
* @param defaultValue the default value
|
||||
* @return the answer
|
||||
*/
|
||||
private static <T> T ask(String ask, Function<String, T> parser, T defaultValue) {
|
||||
System.out.print(ask);
|
||||
private <T> T ask(String ask, Function<String, T> parser, T defaultValue) {
|
||||
this.out.print(ask);
|
||||
try {
|
||||
var line = System.console().readLine();
|
||||
var line = this.scanner.nextLine();
|
||||
return parser.apply(line);
|
||||
} catch (Exception e) {
|
||||
System.out.println("Invalid input: " + e.getMessage());
|
||||
this.out.println("Invalid input: " + e.getMessage());
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
@@ -168,7 +181,7 @@ public class NetBuilderInteractive {
|
||||
* @param options the options to choose from
|
||||
* @return the choice
|
||||
*/
|
||||
private static int choose(String ask, String... options) {
|
||||
private int choose(String ask, String... options) {
|
||||
var builder = new StringBuilder();
|
||||
builder.append(ask).append("\n");
|
||||
for (int i = 0; i < options.length; i++) {
|
||||
|
||||
@@ -2,8 +2,14 @@ package net.berack.upo.valpre.sim;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import net.berack.upo.valpre.NetBuilderInteractive;
|
||||
import net.berack.upo.valpre.rand.Distribution;
|
||||
|
||||
public class TestInteractions {
|
||||
@@ -90,4 +96,66 @@ public class TestInteractions {
|
||||
+ other + " -\n",
|
||||
net.toString());
|
||||
}
|
||||
|
||||
@Test(timeout = 1000)
|
||||
public void netBuilderInteractive() {
|
||||
var out = new PrintStream(OutputStream.nullOutputStream());
|
||||
|
||||
var inputs = List.of("5");
|
||||
var bytes = String.join("\n", inputs).getBytes();
|
||||
var in = new ByteArrayInputStream(bytes);
|
||||
var net = new NetBuilderInteractive(out, in).run();
|
||||
assertEquals("", net.toString());
|
||||
|
||||
inputs = List.of("1", "1", "Source", "1", "1.0", "10000", "5");
|
||||
bytes = String.join("\n", inputs).getBytes();
|
||||
in = new ByteArrayInputStream("1\n1\nSource\n1\n1.0\n1000\n5\n".getBytes());
|
||||
net = new NetBuilderInteractive(out, in).run();
|
||||
assertEquals("Source[servers:1, queue:100, spawn:1000, Exponential(1.0)] -\n", net.toString());
|
||||
|
||||
inputs = List.of("1", "1", "Source", "1", "2.0", "500",
|
||||
"1", "2", "Queue", "5", "3.2", "0.6", "1",
|
||||
"5");
|
||||
bytes = String.join("\n", inputs).getBytes();
|
||||
in = new ByteArrayInputStream(bytes);
|
||||
net = new NetBuilderInteractive(out, in).run();
|
||||
assertEquals("Source[servers:1, queue:100, spawn:500, Exponential(2.0)] -\n"
|
||||
+ "Queue[servers:1, queue:100, spawn:0, Normal(3.2, 0.6)] -\n", net.toString());
|
||||
|
||||
inputs = List.of("1", "1", "Source", "1", "2.0", "500",
|
||||
"1", "2", "Queue", "5", "3.2", "0.6", "1",
|
||||
"2", "Source", "Queue", "1.0",
|
||||
"5");
|
||||
bytes = String.join("\n", inputs).getBytes();
|
||||
in = new ByteArrayInputStream(bytes);
|
||||
net = new NetBuilderInteractive(out, in).run();
|
||||
assertEquals("Source[servers:1, queue:100, spawn:500, Exponential(2.0)] -> Queue(1.0)\n"
|
||||
+ "Queue[servers:1, queue:100, spawn:0, Normal(3.2, 0.6)] -\n", net.toString());
|
||||
}
|
||||
|
||||
/*
|
||||
* An interaction example is like this:
|
||||
* 1. Add a node
|
||||
* - Choose the type of node to create:
|
||||
* - 1. Source
|
||||
* - 2. Queue
|
||||
* - 3. Queue with unavailable time
|
||||
* - Node name: Name
|
||||
* - Arrivals limit (0 for Int.Max) / Number of servers: 1
|
||||
* - Choose the type of service distribution:
|
||||
* - - 1. Exponential
|
||||
* - - 2. Uniform
|
||||
* - - 3. Erlang
|
||||
* - - 4. UnavailableTime
|
||||
* - - 5. Normal
|
||||
* - - 6. NormalBoxMuller
|
||||
* - - 7. None
|
||||
* 2. Add a connection
|
||||
* - Enter the source node: Source
|
||||
* - Enter the target node: Queue
|
||||
* - Enter the weight: 1.0
|
||||
* 3. Print Nodes
|
||||
* 4. Save the net
|
||||
* 5. Exit
|
||||
*/
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user