saving work until i come back
This commit is contained in:
parent
167dea9451
commit
aa2b21e515
@ -1,19 +1,24 @@
|
|||||||
package dev.ksan.travelpathoptimizer.controller;
|
package dev.ksan.travelpathoptimizer.controller;
|
||||||
|
|
||||||
import dev.ksan.travelpathoptimizer.app.TransportDataGenerator;
|
import dev.ksan.travelpathoptimizer.app.TransportDataGenerator;
|
||||||
|
import dev.ksan.travelpathoptimizer.graph.Graph;
|
||||||
import dev.ksan.travelpathoptimizer.model.City;
|
import dev.ksan.travelpathoptimizer.model.City;
|
||||||
import dev.ksan.travelpathoptimizer.model.Departure;
|
import dev.ksan.travelpathoptimizer.model.Departure;
|
||||||
import dev.ksan.travelpathoptimizer.model.Location;
|
import dev.ksan.travelpathoptimizer.model.Location;
|
||||||
import dev.ksan.travelpathoptimizer.service.CityManager;
|
import dev.ksan.travelpathoptimizer.service.CityManager;
|
||||||
import dev.ksan.travelpathoptimizer.util.JsonParser;
|
import dev.ksan.travelpathoptimizer.util.JsonParser;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.time.LocalTime;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import javafx.fxml.FXML;
|
import javafx.fxml.FXML;
|
||||||
import javafx.scene.control.Button;
|
import javafx.scene.control.Button;
|
||||||
|
import javafx.scene.control.ChoiceBox;
|
||||||
import javafx.scene.control.Label;
|
import javafx.scene.control.Label;
|
||||||
import javafx.scene.control.TextField;
|
import javafx.scene.control.TextField;
|
||||||
import javafx.scene.layout.ColumnConstraints;
|
import javafx.scene.layout.ColumnConstraints;
|
||||||
import javafx.scene.layout.GridPane;
|
import javafx.scene.layout.GridPane;
|
||||||
|
import javafx.scene.layout.HBox;
|
||||||
import javafx.scene.layout.Priority;
|
import javafx.scene.layout.Priority;
|
||||||
import javafx.scene.layout.RowConstraints;
|
import javafx.scene.layout.RowConstraints;
|
||||||
import javafx.scene.layout.StackPane;
|
import javafx.scene.layout.StackPane;
|
||||||
@ -37,6 +42,7 @@ public class MainController {
|
|||||||
@FXML private Button startCityButton;
|
@FXML private Button startCityButton;
|
||||||
@FXML private Button endCityButton;
|
@FXML private Button endCityButton;
|
||||||
|
|
||||||
|
private Graph graph;
|
||||||
City[][] cities;
|
City[][] cities;
|
||||||
private File selectedFile;
|
private File selectedFile;
|
||||||
@FXML private Button openFileButton;
|
@FXML private Button openFileButton;
|
||||||
@ -45,12 +51,51 @@ public class MainController {
|
|||||||
@FXML private TextField departureTextField;
|
@FXML private TextField departureTextField;
|
||||||
@FXML private VBox randomSideBar;
|
@FXML private VBox randomSideBar;
|
||||||
@FXML private VBox mapSideBar;
|
@FXML private VBox mapSideBar;
|
||||||
|
@FXML private ChoiceBox categoryBox;
|
||||||
|
@FXML private Button startButton;
|
||||||
|
|
||||||
|
// routeView
|
||||||
|
@FXML private HBox routeView;
|
||||||
|
@FXML private Text totalTicketPriceText;
|
||||||
|
@FXML private Button buyButton;
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private void findTopPaths() {
|
||||||
|
graph.reset();
|
||||||
|
if (this.startCity != null && this.endCity != null) {
|
||||||
|
List<City> path = new ArrayList<>();
|
||||||
|
|
||||||
|
List<Integer> departuress = new ArrayList<>();
|
||||||
|
LocalTime currentTime = LocalTime.of(1, 0);
|
||||||
|
double totalCost = 0.0;
|
||||||
|
|
||||||
|
graph.calculateTopPaths(
|
||||||
|
this.startCity,
|
||||||
|
this.endCity,
|
||||||
|
path,
|
||||||
|
totalCost,
|
||||||
|
currentTime,
|
||||||
|
departuress,
|
||||||
|
categoryBox.getValue().toString());
|
||||||
|
System.out.println(graph.getTopPaths().size());
|
||||||
|
// Output the top 5 paths
|
||||||
|
graph.printTopPaths();
|
||||||
|
System.out.println(startCity.getName() + endCity.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
protected void onHelloButtonClick() {
|
protected void onHelloButtonClick() {
|
||||||
welcomeText.setText("Welcome to JavaFX Application!");
|
welcomeText.setText("Welcome to JavaFX Application!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private void showRouteView() {
|
||||||
|
boolean visible = routeView.isVisible();
|
||||||
|
routeView.setVisible(!visible);
|
||||||
|
routeView.setManaged(!visible);
|
||||||
|
}
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
void showRandomSideBar() {
|
void showRandomSideBar() {
|
||||||
boolean visible = randomSideBar.isVisible();
|
boolean visible = randomSideBar.isVisible();
|
||||||
@ -155,6 +200,10 @@ public class MainController {
|
|||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
public void initialize() {
|
public void initialize() {
|
||||||
|
|
||||||
|
categoryBox.getItems().addAll("time", "price", "hops");
|
||||||
|
categoryBox.setValue("time");
|
||||||
|
|
||||||
endCityText
|
endCityText
|
||||||
.textProperty()
|
.textProperty()
|
||||||
.addListener(
|
.addListener(
|
||||||
@ -164,6 +213,8 @@ public class MainController {
|
|||||||
endCityText.setStyle("-fx-text-fill: black;");
|
endCityText.setStyle("-fx-text-fill: black;");
|
||||||
} else {
|
} else {
|
||||||
City match = CityManager.getCityByName(newText.trim());
|
City match = CityManager.getCityByName(newText.trim());
|
||||||
|
|
||||||
|
System.out.println("Selected end: " + match.getName());
|
||||||
if (match != null) {
|
if (match != null) {
|
||||||
endCity = match;
|
endCity = match;
|
||||||
endCityText.setStyle("-fx-text-fill: green;");
|
endCityText.setStyle("-fx-text-fill: green;");
|
||||||
@ -184,6 +235,8 @@ public class MainController {
|
|||||||
startCityText.setStyle("-fx-text-fill: black;");
|
startCityText.setStyle("-fx-text-fill: black;");
|
||||||
} else {
|
} else {
|
||||||
City match = CityManager.getCityByName(newText.trim());
|
City match = CityManager.getCityByName(newText.trim());
|
||||||
|
|
||||||
|
System.out.println("Selected start: " + match.getName());
|
||||||
if (match != null) {
|
if (match != null) {
|
||||||
startCity = match;
|
startCity = match;
|
||||||
startCityText.setStyle("-fx-text-fill: green;");
|
startCityText.setStyle("-fx-text-fill: green;");
|
||||||
@ -217,17 +270,25 @@ public class MainController {
|
|||||||
|
|
||||||
private void getData() {
|
private void getData() {
|
||||||
CityManager.clear();
|
CityManager.clear();
|
||||||
List<City> cities = JsonParser.parseCities(selectedFile.toString(), "stations");
|
List<City> cities = JsonParser.parseCities("transport_data.json", "stations");
|
||||||
List<Departure> departures = JsonParser.getDeparturesList("transport_data.json", "departures");
|
List<Departure> departures = JsonParser.getDeparturesList("transport_data.json", "departures");
|
||||||
|
for (Departure dep : departures) {
|
||||||
|
for (City city : cities) {
|
||||||
|
if (dep.getTo().equals(city.getName())) {
|
||||||
|
dep.setToCity(city);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
cities = JsonParser.loadDepartures(cities, departures);
|
cities = JsonParser.loadDepartures(cities, departures);
|
||||||
City[][] map = JsonParser.loadMap("transport_data.json", "countryMap", cities);
|
City[][] map = JsonParser.loadMap("transport_data.json", "countryMap", cities);
|
||||||
|
|
||||||
cities = JsonParser.loadDepartures(cities, departures);
|
cities = JsonParser.loadDepartures(cities, departures);
|
||||||
for (City city : cities) {
|
for (City city : cities) {
|
||||||
System.out.println(city);
|
|
||||||
CityManager.addCity(city);
|
CityManager.addCity(city);
|
||||||
}
|
}
|
||||||
this.cities = map;
|
this.cities = map;
|
||||||
|
|
||||||
|
this.graph = new Graph(map);
|
||||||
}
|
}
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
|
@ -5,10 +5,9 @@ import dev.ksan.travelpathoptimizer.model.Departure;
|
|||||||
import dev.ksan.travelpathoptimizer.model.Location;
|
import dev.ksan.travelpathoptimizer.model.Location;
|
||||||
import dev.ksan.travelpathoptimizer.service.CityManager;
|
import dev.ksan.travelpathoptimizer.service.CityManager;
|
||||||
import dev.ksan.travelpathoptimizer.util.JsonParser;
|
import dev.ksan.travelpathoptimizer.util.JsonParser;
|
||||||
|
import java.time.Duration;
|
||||||
import java.time.LocalTime;
|
import java.time.LocalTime;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
public class Graph {
|
public class Graph {
|
||||||
private City[][] matrix;
|
private City[][] matrix;
|
||||||
@ -16,7 +15,9 @@ public class Graph {
|
|||||||
private int pathIdCounter = 1;
|
private int pathIdCounter = 1;
|
||||||
private static int nextid = 0;
|
private static int nextid = 0;
|
||||||
private static Set<String> visitedRoutes = new HashSet<>();
|
private static Set<String> visitedRoutes = new HashSet<>();
|
||||||
public static PriorityQueue<PathResult> topPaths = new PriorityQueue<>(5, Comparator.comparingDouble(PathResult::getCost).reversed());
|
public static PriorityQueue<PathResult> topPaths =
|
||||||
|
new PriorityQueue<>(5, Comparator.comparingDouble(PathResult::getCost).reversed());
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
List<City> cities = JsonParser.parseCities("transport_data.json", "stations");
|
List<City> cities = JsonParser.parseCities("transport_data.json", "stations");
|
||||||
List<Departure> departures = JsonParser.getDeparturesList("transport_data.json", "departures");
|
List<Departure> departures = JsonParser.getDeparturesList("transport_data.json", "departures");
|
||||||
@ -32,19 +33,16 @@ public class Graph {
|
|||||||
|
|
||||||
Graph graph = new Graph(map);
|
Graph graph = new Graph(map);
|
||||||
cities = JsonParser.loadDepartures(cities, departures);
|
cities = JsonParser.loadDepartures(cities, departures);
|
||||||
System.out.println(cities.getFirst().getName() + " do " + cities.getLast().getName());
|
|
||||||
for (City city : cities) {
|
for (City city : cities) {
|
||||||
CityManager.addCity(city);
|
CityManager.addCity(city);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
System.out.println(cities.getFirst().getName() + " do " + cities.getLast().getName());
|
||||||
Map<Location, Double> result =
|
Map<Location, Double> result =
|
||||||
graph.calculateShortestPath(cities.getFirst(), cities.getLast(), "time");
|
graph.calculateShortestPath(cities.getFirst(), cities.getLast(), "time");
|
||||||
System.out.println(
|
System.out.println(
|
||||||
cities.get(1).getName() + " = " + result.get(cities.getLast().getLocation()));
|
cities.get(1).getName() + " = " + result.get(cities.getLast().getLocation()));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
graph.calculateTopPaths(cities.getFirst(), cities.getLast());
|
graph.calculateTopPaths(cities.getFirst(), cities.getLast());
|
||||||
|
|
||||||
@ -70,15 +68,23 @@ public class Graph {
|
|||||||
|
|
||||||
List<City> path = new ArrayList<>();
|
List<City> path = new ArrayList<>();
|
||||||
List<Integer> departuress = new ArrayList<>();
|
List<Integer> departuress = new ArrayList<>();
|
||||||
LocalTime currentTime = LocalTime.of(1, 0); // Assume starting at 8:00 AM
|
LocalTime currentTime = LocalTime.of(1, 0);
|
||||||
double totalCost = 0.0;
|
double totalCost = 0.0;
|
||||||
|
|
||||||
calculateTopPaths(
|
calculateTopPaths(
|
||||||
cities.getFirst(), cities.getLast(), path, totalCost, currentTime, departuress);
|
cities.getFirst(), cities.getLast(), path, totalCost, currentTime, departuress, "time");
|
||||||
System.out.println(topPaths.size());
|
System.out.println(topPaths.size());
|
||||||
// Output the top 5 paths
|
// Output the top 5 paths
|
||||||
printTopPaths(); }
|
printTopPaths();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reset() {
|
||||||
|
topPaths.clear();
|
||||||
|
pathIdCounter = 1;
|
||||||
|
nextid = 0;
|
||||||
|
allPaths.clear();
|
||||||
|
visitedRoutes.clear();
|
||||||
|
}
|
||||||
|
|
||||||
public static void addToTopPaths(PathResult newPath) {
|
public static void addToTopPaths(PathResult newPath) {
|
||||||
String routeHash = generateRouteHash(newPath.getDeparturesUsed());
|
String routeHash = generateRouteHash(newPath.getDeparturesUsed());
|
||||||
@ -100,7 +106,6 @@ public class Graph {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static String generateRouteHash(List<Integer> departures) {
|
private static String generateRouteHash(List<Integer> departures) {
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
for (Integer depId : departures) {
|
for (Integer depId : departures) {
|
||||||
@ -108,20 +113,30 @@ public class Graph {
|
|||||||
}
|
}
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void calculateTopPaths(
|
public static void calculateTopPaths(
|
||||||
City currentCity,
|
City currentCity,
|
||||||
City endCity,
|
City endCity,
|
||||||
List<City> path,
|
List<City> path,
|
||||||
double totalCost,
|
double totalCost,
|
||||||
LocalTime currentTime,
|
LocalTime currentTime,
|
||||||
List<Integer> departures) {
|
List<Integer> departures,
|
||||||
|
String type) {
|
||||||
|
|
||||||
if (currentCity.getLocation().equals(endCity.getLocation())) {
|
if (currentCity.getLocation().equals(endCity.getLocation())) {
|
||||||
|
|
||||||
addToTopPaths(new PathResult(nextid++, new ArrayList<>(path), new ArrayList<>(departures), totalCost, currentTime));
|
addToTopPaths(
|
||||||
|
new PathResult(
|
||||||
|
nextid++,
|
||||||
|
new ArrayList<>(path),
|
||||||
|
new ArrayList<>(departures),
|
||||||
|
totalCost,
|
||||||
|
currentTime));
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Departure dep : currentCity.getDestinations()) {
|
for (Departure dep : currentCity.getDestinations()) {
|
||||||
|
double cost = 0.0;
|
||||||
if (dep.getDepartureTime().isBefore(currentTime)) continue;
|
if (dep.getDepartureTime().isBefore(currentTime)) continue;
|
||||||
City nextCity;
|
City nextCity;
|
||||||
if (path.contains(dep.getDestinationCity())) {
|
if (path.contains(dep.getDestinationCity())) {
|
||||||
@ -130,21 +145,41 @@ public class Graph {
|
|||||||
nextCity = dep.getDestinationCity();
|
nextCity = dep.getDestinationCity();
|
||||||
}
|
}
|
||||||
LocalTime arrivalTime = dep.getDepartureTime().plusMinutes(dep.getDuration());
|
LocalTime arrivalTime = dep.getDepartureTime().plusMinutes(dep.getDuration());
|
||||||
|
Duration duration = Duration.between(currentTime, arrivalTime);
|
||||||
|
duration = duration.abs();
|
||||||
|
|
||||||
if (topPaths.size() >= 5 && totalCost + dep.getDuration() > topPaths.peek().getCost()) {
|
if (type.equals("time")) {
|
||||||
|
// cost += dep.getDuration();
|
||||||
|
cost += duration.toMinutes();
|
||||||
|
} else if (type.equals("price")) {
|
||||||
|
cost += dep.getPrice();
|
||||||
|
} else if (type.equals("hops")) {
|
||||||
|
cost++;
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (topPaths.size() >= 5 && totalCost + cost > topPaths.peek().getCost()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
path.add(nextCity);
|
path.add(nextCity);
|
||||||
departures.add(dep.getIdCounter());
|
departures.add(dep.getIdCounter());
|
||||||
calculateTopPaths(
|
calculateTopPaths(nextCity, endCity, path, totalCost + cost, arrivalTime, departures, type);
|
||||||
nextCity, endCity, path, totalCost + dep.getDuration(), arrivalTime, departures);
|
|
||||||
|
|
||||||
departures.remove(departures.size() - 1);
|
departures.remove(departures.size() - 1);
|
||||||
path.remove(path.size() - 1);
|
path.remove(path.size() - 1);
|
||||||
|
if (type.equals("hops")) {
|
||||||
|
|
||||||
|
cost--;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void printTopPaths() {
|
public static void printTopPaths() {
|
||||||
|
if (topPaths.isEmpty()) {
|
||||||
|
System.out.println("No Paths");
|
||||||
|
return;
|
||||||
|
}
|
||||||
System.out.println("Top 5 Paths:");
|
System.out.println("Top 5 Paths:");
|
||||||
int rank = 5;
|
int rank = 5;
|
||||||
while (!topPaths.isEmpty()) {
|
while (!topPaths.isEmpty()) {
|
||||||
@ -158,138 +193,137 @@ public class Graph {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
private PriorityQueue<PathResult> topPaths =
|
private PriorityQueue<PathResult> topPaths =
|
||||||
new PriorityQueue<>(Comparator.comparingDouble(PathResult::getCost).reversed());
|
new PriorityQueue<>(Comparator.comparingDouble(PathResult::getCost).reversed());
|
||||||
private final AtomicInteger pathIdGenerator = new AtomicInteger(1); // Start from 1
|
private final AtomicInteger pathIdGenerator = new AtomicInteger(1); // Start from 1
|
||||||
private final Set<String> uniquePathKeys = new HashSet<>();
|
private final Set<String> uniquePathKeys = new HashSet<>();
|
||||||
|
|
||||||
private int makeDeparturePathHash(Set<Departure> departures) {
|
private int makeDeparturePathHash(Set<Departure> departures) {
|
||||||
// A simple approach: sum of hashes or use Objects.hash(...)
|
return departures.stream()
|
||||||
return departures.stream()
|
.mapToInt(
|
||||||
.mapToInt(
|
dep ->
|
||||||
dep ->
|
Objects.hash(
|
||||||
Objects.hash(
|
dep.getDepartureTime()
|
||||||
dep.getDepartureTime()
|
.toSecondOfDay(),
|
||||||
.toSecondOfDay(), // convert time to int seconds for consistency
|
dep.getDestinationCity()
|
||||||
dep.getDestinationCity()
|
.getLocation(),
|
||||||
.getLocation(), // assuming Location implements hashCode properly
|
Double.valueOf(dep.getDuration()).hashCode()))
|
||||||
Double.valueOf(dep.getDuration()).hashCode()))
|
.sorted()
|
||||||
.sorted() // sort to avoid order affecting hash
|
.reduce(1, (a, b) -> 31 * a + b);
|
||||||
.reduce(1, (a, b) -> 31 * a + b); // combine with a hash combiner
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private HashSet<Integer> uniquePathHashes = new HashSet<Integer>();
|
|
||||||
public void calculateTopPaths(City start, City end) {
|
|
||||||
topPaths.clear();
|
|
||||||
uniquePathKeys.clear();
|
|
||||||
pathIdGenerator.set(1);
|
|
||||||
|
|
||||||
for (Departure dep : start.getDestinations()) {
|
|
||||||
City next = dep.getDestinationCity();
|
|
||||||
double duration = dep.getDuration();
|
|
||||||
LocalTime depTime = dep.getDepartureTime();
|
|
||||||
LocalTime arrivalTime = depTime.plusMinutes((long) duration);
|
|
||||||
|
|
||||||
List<City> initialPath = new ArrayList<>();
|
|
||||||
Set<Departure> usedDepartures = new HashSet<>();
|
|
||||||
usedDepartures.add(dep);
|
|
||||||
|
|
||||||
initialPath.add(start); // include start
|
|
||||||
initialPath.add(next); // move to first destination
|
|
||||||
List<Integer> initialDepartures = new ArrayList<>();
|
|
||||||
initialDepartures.add(dep.getIdCounter());
|
|
||||||
Set<Location> visited = new HashSet<>();
|
|
||||||
visited.add(start.getLocation());
|
|
||||||
|
|
||||||
findPaths(
|
|
||||||
next,
|
|
||||||
end,
|
|
||||||
initialPath,
|
|
||||||
usedDepartures,
|
|
||||||
initialDepartures,
|
|
||||||
duration,
|
|
||||||
arrivalTime,
|
|
||||||
visited);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public void findPaths(
|
|
||||||
City current,
|
|
||||||
City end,
|
|
||||||
List<City> pathSoFar,
|
|
||||||
Set<Departure> usedDepartures,
|
|
||||||
List<Integer> departuresSoFar,
|
|
||||||
double totalCost,
|
|
||||||
LocalTime currentTime,
|
|
||||||
Set<Location> visitedCities
|
|
||||||
) {
|
|
||||||
if (visitedCities.contains(current.getLocation())) return;
|
|
||||||
|
|
||||||
visitedCities.add(current.getLocation());
|
|
||||||
|
|
||||||
if (current.getLocation().equals(end.getLocation())) {
|
|
||||||
int pathHash = makeDeparturePathHash(usedDepartures);
|
private HashSet<Integer> uniquePathHashes = new HashSet<Integer>();
|
||||||
if (uniquePathHashes.contains(pathHash)) {
|
public void calculateTopPaths(City start, City end) {
|
||||||
visitedCities.remove(current.getLocation());
|
topPaths.clear();
|
||||||
|
uniquePathKeys.clear();
|
||||||
|
pathIdGenerator.set(1);
|
||||||
|
|
||||||
|
for (Departure dep : start.getDestinations()) {
|
||||||
|
City next = dep.getDestinationCity();
|
||||||
|
double duration = dep.getDuration();
|
||||||
|
LocalTime depTime = dep.getDepartureTime();
|
||||||
|
LocalTime arrivalTime = depTime.plusMinutes((long) duration);
|
||||||
|
|
||||||
|
List<City> initialPath = new ArrayList<>();
|
||||||
|
Set<Departure> usedDepartures = new HashSet<>();
|
||||||
|
usedDepartures.add(dep);
|
||||||
|
|
||||||
|
initialPath.add(start);
|
||||||
|
initialPath.add(next);
|
||||||
|
List<Integer> initialDepartures = new ArrayList<>();
|
||||||
|
initialDepartures.add(dep.getIdCounter());
|
||||||
|
Set<Location> visited = new HashSet<>();
|
||||||
|
visited.add(start.getLocation());
|
||||||
|
|
||||||
|
findPaths(
|
||||||
|
next,
|
||||||
|
end,
|
||||||
|
initialPath,
|
||||||
|
usedDepartures,
|
||||||
|
initialDepartures,
|
||||||
|
duration,
|
||||||
|
arrivalTime,
|
||||||
|
visited);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void findPaths(
|
||||||
|
City current,
|
||||||
|
City end,
|
||||||
|
List<City> pathSoFar,
|
||||||
|
Set<Departure> usedDepartures,
|
||||||
|
List<Integer> departuresSoFar,
|
||||||
|
double totalCost,
|
||||||
|
LocalTime currentTime,
|
||||||
|
Set<Location> visitedCities
|
||||||
|
) {
|
||||||
|
if (visitedCities.contains(current.getLocation())) return;
|
||||||
|
|
||||||
|
visitedCities.add(current.getLocation());
|
||||||
|
|
||||||
|
if (current.getLocation().equals(end.getLocation())) {
|
||||||
|
int pathHash = makeDeparturePathHash(usedDepartures);
|
||||||
|
if (uniquePathHashes.contains(pathHash)) {
|
||||||
|
visitedCities.remove(current.getLocation());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uniquePathHashes.add(pathHash);
|
||||||
|
int pathId = pathIdGenerator.getAndIncrement();
|
||||||
|
topPaths.add(
|
||||||
|
new PathResult(
|
||||||
|
pathId,
|
||||||
|
new ArrayList<>(pathSoFar),
|
||||||
|
new ArrayList<>(departuresSoFar),
|
||||||
|
totalCost,
|
||||||
|
currentTime));
|
||||||
|
|
||||||
|
if (topPaths.size() > 5) topPaths.poll();
|
||||||
|
|
||||||
|
visitedCities.remove(current.getLocation()); // backtrack
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
uniquePathHashes.add(pathHash);
|
for (Departure dep : current.getDestinations()) {
|
||||||
int pathId = pathIdGenerator.getAndIncrement();
|
if (usedDepartures.contains(dep)) continue;
|
||||||
topPaths.add(
|
if (dep.getDepartureTime().isBefore(currentTime)) continue;
|
||||||
new PathResult(
|
|
||||||
pathId,
|
|
||||||
new ArrayList<>(pathSoFar),
|
|
||||||
new ArrayList<>(departuresSoFar),
|
|
||||||
totalCost,
|
|
||||||
currentTime));
|
|
||||||
|
|
||||||
if (topPaths.size() > 5) topPaths.poll();
|
City next = dep.getDestinationCity();
|
||||||
|
if (visitedCities.contains(next.getLocation())) continue; // skip if already visited
|
||||||
|
|
||||||
|
LocalTime arrivalTime = dep.getDepartureTime().plusMinutes((long) dep.getDuration());
|
||||||
|
|
||||||
|
usedDepartures.add(dep);
|
||||||
|
departuresSoFar.add(dep.getIdCounter());
|
||||||
|
pathSoFar.add(next);
|
||||||
|
if (!(topPaths.peek() == null)) {
|
||||||
|
if (totalCost + dep.getDuration() > topPaths.peek().getCost()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
findPaths(
|
||||||
|
next,
|
||||||
|
end,
|
||||||
|
pathSoFar,
|
||||||
|
usedDepartures,
|
||||||
|
departuresSoFar,
|
||||||
|
totalCost + dep.getDuration(),
|
||||||
|
arrivalTime,
|
||||||
|
visitedCities);
|
||||||
|
|
||||||
|
// backtrack
|
||||||
|
pathSoFar.remove(pathSoFar.size() - 1);
|
||||||
|
departuresSoFar.remove(departuresSoFar.size() - 1);
|
||||||
|
usedDepartures.remove(dep);
|
||||||
|
}
|
||||||
|
|
||||||
visitedCities.remove(current.getLocation()); // backtrack
|
visitedCities.remove(current.getLocation()); // backtrack
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
for (Departure dep : current.getDestinations()) {
|
|
||||||
if (usedDepartures.contains(dep)) continue;
|
|
||||||
if (dep.getDepartureTime().isBefore(currentTime)) continue;
|
|
||||||
|
|
||||||
City next = dep.getDestinationCity();
|
|
||||||
if (visitedCities.contains(next.getLocation())) continue; // skip if already visited
|
|
||||||
|
|
||||||
LocalTime arrivalTime = dep.getDepartureTime().plusMinutes((long) dep.getDuration());
|
|
||||||
|
|
||||||
usedDepartures.add(dep);
|
|
||||||
departuresSoFar.add(dep.getIdCounter());
|
|
||||||
pathSoFar.add(next);
|
|
||||||
if (!(topPaths.peek() == null)) {
|
|
||||||
if (totalCost + dep.getDuration() > topPaths.peek().getCost()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
findPaths(
|
|
||||||
next,
|
|
||||||
end,
|
|
||||||
pathSoFar,
|
|
||||||
usedDepartures,
|
|
||||||
departuresSoFar,
|
|
||||||
totalCost + dep.getDuration(),
|
|
||||||
arrivalTime,
|
|
||||||
visitedCities);
|
|
||||||
|
|
||||||
// backtrack
|
|
||||||
pathSoFar.remove(pathSoFar.size() - 1);
|
|
||||||
departuresSoFar.remove(departuresSoFar.size() - 1);
|
|
||||||
usedDepartures.remove(dep);
|
|
||||||
}
|
|
||||||
|
|
||||||
visitedCities.remove(current.getLocation()); // backtrack
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
public Map<Location, Double> calculateShortestPath(City startCity, City endCity, String type) {
|
public Map<Location, Double> calculateShortestPath(City startCity, City endCity, String type) {
|
||||||
int n = matrix.length;
|
int n = matrix.length;
|
||||||
int m = matrix[0].length;
|
int m = matrix[0].length;
|
||||||
@ -338,8 +372,6 @@ public class Graph {
|
|||||||
return distances;
|
return distances;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public List<PathResult> getAllPaths() {
|
public List<PathResult> getAllPaths() {
|
||||||
return allPaths;
|
return allPaths;
|
||||||
}
|
}
|
||||||
@ -359,4 +391,8 @@ public class Graph {
|
|||||||
public City getCity(Location loc) {
|
public City getCity(Location loc) {
|
||||||
return matrix[loc.getX()][loc.getY()];
|
return matrix[loc.getX()][loc.getY()];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static PriorityQueue<PathResult> getTopPaths() {
|
||||||
|
return topPaths;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,21 +1,41 @@
|
|||||||
module dev.ksan.travelpathoptimizer {
|
module dev.ksan.travelpathoptimizer {
|
||||||
requires javafx.controls;
|
requires javafx.controls;
|
||||||
requires javafx.fxml;
|
requires javafx.fxml;
|
||||||
requires java.desktop;
|
requires java.desktop;
|
||||||
|
requires javafx.graphics;
|
||||||
|
|
||||||
|
opens dev.ksan.travelpathoptimizer to
|
||||||
|
javafx.fxml;
|
||||||
|
|
||||||
|
exports dev.ksan.travelpathoptimizer;
|
||||||
|
exports dev.ksan.travelpathoptimizer.app;
|
||||||
|
|
||||||
|
opens dev.ksan.travelpathoptimizer.app to
|
||||||
|
javafx.fxml;
|
||||||
|
|
||||||
|
exports dev.ksan.travelpathoptimizer.controller;
|
||||||
|
|
||||||
|
opens dev.ksan.travelpathoptimizer.controller to
|
||||||
|
javafx.fxml;
|
||||||
|
|
||||||
|
exports dev.ksan.travelpathoptimizer.model;
|
||||||
|
|
||||||
|
opens dev.ksan.travelpathoptimizer.model to
|
||||||
|
javafx.fxml;
|
||||||
|
|
||||||
|
exports dev.ksan.travelpathoptimizer.util;
|
||||||
|
|
||||||
|
opens dev.ksan.travelpathoptimizer.util to
|
||||||
|
javafx.fxml;
|
||||||
|
|
||||||
|
exports dev.ksan.travelpathoptimizer.service;
|
||||||
|
|
||||||
|
opens dev.ksan.travelpathoptimizer.service to
|
||||||
|
javafx.fxml;
|
||||||
|
|
||||||
|
exports dev.ksan.travelpathoptimizer.graph;
|
||||||
|
|
||||||
|
opens dev.ksan.travelpathoptimizer.graph to
|
||||||
|
javafx.fxml;
|
||||||
|
}
|
||||||
|
|
||||||
opens dev.ksan.travelpathoptimizer to javafx.fxml;
|
|
||||||
exports dev.ksan.travelpathoptimizer;
|
|
||||||
exports dev.ksan.travelpathoptimizer.app;
|
|
||||||
opens dev.ksan.travelpathoptimizer.app to javafx.fxml;
|
|
||||||
exports dev.ksan.travelpathoptimizer.controller;
|
|
||||||
opens dev.ksan.travelpathoptimizer.controller to javafx.fxml;
|
|
||||||
exports dev.ksan.travelpathoptimizer.model;
|
|
||||||
opens dev.ksan.travelpathoptimizer.model to javafx.fxml;
|
|
||||||
exports dev.ksan.travelpathoptimizer.util;
|
|
||||||
opens dev.ksan.travelpathoptimizer.util to javafx.fxml;
|
|
||||||
exports dev.ksan.travelpathoptimizer.service;
|
|
||||||
opens dev.ksan.travelpathoptimizer.service to javafx.fxml;
|
|
||||||
exports dev.ksan.travelpathoptimizer.graph;
|
|
||||||
opens dev.ksan.travelpathoptimizer.graph to javafx.fxml;
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user