diff --git a/src/main/java/dev/ksan/travelpathoptimizer/controller/MainController.java b/src/main/java/dev/ksan/travelpathoptimizer/controller/MainController.java index 0cb63f7..3faee6b 100644 --- a/src/main/java/dev/ksan/travelpathoptimizer/controller/MainController.java +++ b/src/main/java/dev/ksan/travelpathoptimizer/controller/MainController.java @@ -10,7 +10,6 @@ import dev.ksan.travelpathoptimizer.service.CityManager; import dev.ksan.travelpathoptimizer.util.JsonParser; import dev.ksan.travelpathoptimizer.util.TicketPrinter; import dev.ksan.travelpathoptimizer.visualize.GraphVisualizer; - import java.io.File; import java.time.LocalTime; import java.util.ArrayList; @@ -42,11 +41,9 @@ import javafx.stage.FileChooser; import javafx.stage.Stage; import org.graphstream.graph.Graph; import org.graphstream.graph.implementations.MultiGraph; -import org.graphstream.graph.implementations.SingleGraph; public class MainController { - @FXML private HBox graphPane; @FXML private GridPane map; @FXML private Label welcomeText; @@ -84,67 +81,80 @@ public class MainController { @FXML private TableColumn tabCostCol; @FXML private ChoiceBox pathChoiceBox; - private Graph graph = new MultiGraph("map"); + private GraphVisualizer visualizer; + private List tempDepartureList = new ArrayList<>(); - -@FXML -void showGraph() { + @FXML + void showGraph() { graph.clear(); if (map.isVisible()) { - map.setVisible(false); - map.setManaged(false); - graphPane.setVisible(true); - graphPane.setManaged(true); + map.setVisible(false); + map.setManaged(false); + graphPane.setVisible(true); + graphPane.setManaged(true); } else { graphPane.setManaged(false); - graphPane.setVisible(false); + graphPane.setVisible(false); - map.setManaged(true); + map.setManaged(true); map.setVisible(true); } for (City[] row : cities) { - for (City city : row) { - if (city != null) { - graph.addNode(city.getName()); - } + for (City city : row) { + if (city != null) { + graph.addNode(city.getName()); } + } } for (City[] row : cities) { - for (City city : row) { - if (city != null) { - for (Departure dep : city.getDestinations()) { - City destinationCity = dep.getDestinationCity(); - if (destinationCity != null) { - if (!city.getName().equals(destinationCity.getName())) { - String edgeId = city.getName() + "-" + destinationCity.getName() + "-" + dep.getIdCounter(); - - if (graph.getEdge(edgeId) != null) { - System.out.println("Edge already exists: " + edgeId); - System.out.println("skip"); - } else { - try { - graph.addEdge(edgeId, city.getName(), destinationCity.getName(), true); - System.out.println("Added directed edge: " + edgeId + " from " + city.getName() + " to " + destinationCity.getName()); - } catch (org.graphstream.graph.EdgeRejectedException e) { - System.out.println("Edge rejected: " + edgeId + " from " + city.getName() + " to " + destinationCity.getName()); - e.printStackTrace(); - } - } - } - } + for (City city : row) { + if (city != null) { + for (Departure dep : city.getDestinations()) { + City destinationCity = dep.getDestinationCity(); + if (destinationCity != null) { + if (!city.getName().equals(destinationCity.getName())) { + String edgeId = + city.getName() + "-" + destinationCity.getName() + "-" + dep.getIdCounter(); + + if (graph.getEdge(edgeId) != null) { + System.out.println("Edge already exists: " + edgeId); + System.out.println("skip"); + } else { + try { + graph.addEdge(edgeId, city.getName(), destinationCity.getName(), true); + System.out.println( + "Added directed edge: " + + edgeId + + " from " + + city.getName() + + " to " + + destinationCity.getName()); + } catch (org.graphstream.graph.EdgeRejectedException e) { + System.out.println( + "Edge rejected: " + + edgeId + + " from " + + city.getName() + + " to " + + destinationCity.getName()); + e.printStackTrace(); + } } + } } + } } + } } - - GraphVisualizer.showGraph(graph,graphPane); - + visualizer.showGraph(); + visualizer.highlightPath(tempDepartureList); } + @FXML private void buyTicket() { @@ -194,7 +204,8 @@ void showGraph() { pathChoiceBox.getItems().add("Route: " + String.valueOf(pathResult.getId())); } pathChoiceBox.setValue( - "Route: " + String.valueOf(graphSimulation.getSortedPaths().getFirst().getId())); + "Route: " + + String.valueOf(graphSimulation.getSortedPaths().getFirst().getId())); updateUiGetList(); }); } @@ -254,8 +265,10 @@ void showGraph() { System.out.println("No matching PathResult found."); } } - System.out.println(departureList.size()); + // System.out.println(departureList.size()); resultTable.setItems(departureList); + tempDepartureList.clear(); + tempDepartureList = departureList; resultTable.refresh(); double totalTicketPrice = calculateTotalCost(departureList); @@ -382,9 +395,16 @@ void showGraph() { @FXML public void initialize() { + visualizer = new GraphVisualizer(graph, graphPane); pathChoiceBox.setOnAction( event -> { updateUiGetList(); + + Platform.runLater( + () -> { + visualizer.highlightPath(tempDepartureList); + }); + // visualizer.highlightPath(tempDepartureList); }); categoryBox.getItems().addAll("time", "price", "hops"); diff --git a/src/main/java/dev/ksan/travelpathoptimizer/graphSimulation/GraphSimulation.java b/src/main/java/dev/ksan/travelpathoptimizer/graphSimulation/GraphSimulation.java index bf37170..43f407e 100644 --- a/src/main/java/dev/ksan/travelpathoptimizer/graphSimulation/GraphSimulation.java +++ b/src/main/java/dev/ksan/travelpathoptimizer/graphSimulation/GraphSimulation.java @@ -17,7 +17,7 @@ public class GraphSimulation { private static Set visitedRoutes = new HashSet<>(); public static PriorityQueue topPaths = new PriorityQueue<>(5, Comparator.comparingDouble(PathResult::getCost).reversed()); - +/* public static void main(String[] args) { List cities = JsonParser.parseCities("transport_data.json", "stations"); List departures = JsonParser.getDeparturesList("transport_data.json", "departures"); @@ -64,7 +64,7 @@ public class GraphSimulation { System.out.println("--------------------------------------------------"); } - */ + *\/ List path = new ArrayList<>(); List departuress = new ArrayList<>(); @@ -77,12 +77,13 @@ public class GraphSimulation { // Output the top 5 paths printTopPaths(); } - - public List getSortedPaths(){ +*/ + public List getSortedPaths() { List pathList = new ArrayList<>(topPaths); pathList.sort(Comparator.comparingDouble(PathResult::getCost)); return pathList; } + public void reset() { topPaths.clear(); pathIdCounter = 1; @@ -156,11 +157,12 @@ public class GraphSimulation { if (type.equals("time")) { // cost += dep.getDuration(); cost += duration.toMinutes(); + cost += dep.getMinTransferTime(); } else if (type.equals("price")) { cost += dep.getPrice(); } else if (type.equals("hops")) { cost++; - if(!topPaths.isEmpty() && totalCost + cost >= topPaths.peek().getCost()) continue; + if (!topPaths.isEmpty() && totalCost + cost >= topPaths.peek().getCost()) continue; } else { return; } diff --git a/src/main/java/dev/ksan/travelpathoptimizer/visualize/GraphVisualizer.java b/src/main/java/dev/ksan/travelpathoptimizer/visualize/GraphVisualizer.java index 3592cb2..ecd3f5a 100644 --- a/src/main/java/dev/ksan/travelpathoptimizer/visualize/GraphVisualizer.java +++ b/src/main/java/dev/ksan/travelpathoptimizer/visualize/GraphVisualizer.java @@ -1,32 +1,86 @@ package dev.ksan.travelpathoptimizer.visualize; +import dev.ksan.travelpathoptimizer.model.Departure; import java.io.File; - +import java.util.ArrayList; +import java.util.List; import javafx.scene.layout.HBox; +import org.graphstream.graph.Edge; import org.graphstream.graph.Graph; +import org.graphstream.graph.Node; import org.graphstream.ui.fx_viewer.FxDefaultView; import org.graphstream.ui.fx_viewer.FxViewer; import org.graphstream.ui.view.Viewer; -public class GraphVisualizer { +public class GraphVisualizer { static File cssFile = new File("src/main/resources/dev/ksan/travelpathoptimizer/app/graph.css"); + private Graph graph; + private HBox container; - public static void showGraph(Graph graph, HBox container) { + public GraphVisualizer(Graph graph, HBox container) { + this.graph = graph; + this.container = container; + } + + public void showGraph() { graph.setAttribute("ui.stylesheet", "url('" + cssFile + "')"); + for (Node node : graph) { + node.setAttribute("ui.label", node.getId()); + } Viewer viewer = new FxViewer(graph, FxViewer.ThreadingModel.GRAPH_IN_GUI_THREAD); viewer.enableAutoLayout(); FxDefaultView view = (FxDefaultView) viewer.addDefaultView(false); - container.getChildren().clear(); container.getChildren().add(view); } + public synchronized void highlightPath(List departures) { + List nodes = new ArrayList(); + List edges = new ArrayList<>(); + for (Node node : graph) { + node.removeAttribute("ui.class"); + } + for (int i = 0; i < graph.getEdgeCount(); i++) { + Edge edge = graph.getEdge(i); + edge.removeAttribute("ui.class"); + } + for (Departure dep : departures) { + String from = dep.getFrom(); + from = from.replaceAll("[A-Z]", "G"); + if (!nodes.contains(from)) nodes.add(from); + if (!nodes.contains(dep.getTo())) nodes.add(dep.getTo()); + edges.add(from + "-" + dep.getTo() + "-" + dep.getIdCounter()); + } + for (String s : nodes) { + System.out.println(s); + } + + for (String nodeId : nodes) { + Node node = graph.getNode(nodeId); + if (node != null) { + node.setAttribute("ui.class", "highlighted"); + } + } + for (int i = 0; i < edges.size(); i++) { + String from = nodes.get(i); + String to = nodes.get(i + 1); + + Edge edge = graph.getEdge(edges.get(i)); + + if (edge != null) { + edge.setAttribute("ui.class", "highlighted"); + } else { + System.out.println("Edge not found between " + from + " and " + to); + } + } + System.out.println(); + } } diff --git a/src/main/resources/dev/ksan/travelpathoptimizer/app/graph.css b/src/main/resources/dev/ksan/travelpathoptimizer/app/graph.css index b2d6ad4..cd189f6 100644 --- a/src/main/resources/dev/ksan/travelpathoptimizer/app/graph.css +++ b/src/main/resources/dev/ksan/travelpathoptimizer/app/graph.css @@ -14,3 +14,11 @@ edge { fill-color: #979797; arrow-shape: none; } + +edge.highlighted { + fill-color: green; + size: 3px; +} +node.highlighted { + fill-color: green; +} \ No newline at end of file diff --git a/src/main/resources/dev/ksan/travelpathoptimizer/app/main.fxml b/src/main/resources/dev/ksan/travelpathoptimizer/app/main.fxml index d042d31..6953cda 100644 --- a/src/main/resources/dev/ksan/travelpathoptimizer/app/main.fxml +++ b/src/main/resources/dev/ksan/travelpathoptimizer/app/main.fxml @@ -41,9 +41,9 @@