-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathOrders.java
More file actions
226 lines (203 loc) · 10.2 KB
/
Orders.java
File metadata and controls
226 lines (203 loc) · 10.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
package uk.ac.ed.inf;
import java.sql.Date;
import java.util.ArrayList;
import java.util.List;
import static uk.ac.ed.inf.App.APPLETONTOWER;
import static uk.ac.ed.inf.App.DISTANCEBEFORERETURNHOME;
/**
* Orders class provides a methods used for determining Delivery Classes based off of order numbers
*
*/
public class Orders {
private LongLat droneLocation;
private final Database database;
private final Website website;
private ArrayList<Delivery> moves;
/**
* Orders class constructor
* @param droneLocation : Drones starting location as a LongLat
* @param database : Database class with name and port
* @param website :Website class with name and port
*/
public Orders(LongLat droneLocation, Database database, Website website) {
this.droneLocation = droneLocation;
this.database = database;
this.website = website;
}
public LongLat getDroneLocation() {
return droneLocation;
}
public void setDroneLocation(LongLat droneLocation) {
this.droneLocation = droneLocation;
}
public Database getDatabase() {
return database;
}
public Website getWebsite() {
return website;
}
public ArrayList<Delivery> getMoves() {return moves;}
/**
* performs a greedy best first search to decide the route for the day
* @param date : for finding route on the given date
*/
public void setMoves(Date date) {
ArrayList<Delivery> deliveryDecisionFinal = new ArrayList<>();
ArrayList<String> allOrderNumbers = this.getDatabase().getOrderNos(date);
while (!allOrderNumbers.isEmpty()) {
long startTime = System.nanoTime();
ArrayList<Delivery> finalisedOptionalRoute = new ArrayList<>();
for (String orderNo : allOrderNumbers) { //creates temporary choice which is a ist of all the routes for the day with longlats
ArrayList<Delivery> optionalRoute = new ArrayList<>();
ArrayList<LongLat> longLats = this.getDatabase().getAllFlightLocations(this.getWebsite(), orderNo);
ArrayList<LongLat> finalStop = new ArrayList<>();
finalStop.add(longLats.get(longLats.size() - 1));
longLats.remove(longLats.size() - 1);
LongLat droneLocation = this.getDroneLocation();
while (!longLats.isEmpty()) { //while there are still longlats in the order number left to visit
Delivery optionalDelivery = getNextDistances(longLats, orderNo, droneLocation);
droneLocation = optionalDelivery.getLocations().get(optionalDelivery.getLocations().size() - 1);
optionalRoute.add(optionalDelivery);
for (LongLat lnglat : optionalDelivery.getLocations()) {
longLats.remove(lnglat);
}
}
droneLocation = (optionalRoute.get(optionalRoute.size() - 1).getLocations()).get((optionalRoute.get(optionalRoute.size() - 1)).getLocations().size() - 1);
optionalRoute.add(getNextDistances(finalStop, orderNo, droneLocation));
finalisedOptionalRoute.add(totalDistance(optionalRoute));
}
Delivery bestValueRoute = finalisedOptionalRoute.get(0);
int totCostInitial = getTotalCostofOrder(this.getDatabase(), this.getWebsite(), bestValueRoute.getOrderNo());
bestValueRoute.setCost(totCostInitial);
for (Delivery choice : finalisedOptionalRoute) {
double first = bestValueRoute.getDistance() / totCostInitial;
int totCostCompare = getTotalCostofOrder(this.getDatabase(), this.getWebsite(), choice.getOrderNo());
double compare = choice.getDistance() / totCostCompare;
if (first > compare) { //compares best ratio of distance over price
bestValueRoute = choice;
bestValueRoute.setCost(totCostCompare);
}
}
String w3w = this.getWebsite().getDeliveryLocation((bestValueRoute.getOrderNo()));
bestValueRoute.setW3w(w3w);
if (deliveryDecisionFinal.size() < 1) { //for first move
bestValueRoute.setStart(this.getDroneLocation());
deliveryDecisionFinal.add(bestValueRoute);
allOrderNumbers.remove(bestValueRoute.getOrderNo());
LongLat bestStart = bestValueRoute.getLocations().get(bestValueRoute.getLocations().size() - 1);
this.setDroneLocation(bestStart);
System.out.println(deliveryDecisionFinal);
long endTime = System.nanoTime();
long totalTime = (endTime - startTime)/1000;
System.out.println("Add one route to delivery: "+totalTime);
} else {
bestValueRoute.setStart(this.getDroneLocation());
deliveryDecisionFinal.add(bestValueRoute);
allOrderNumbers.remove(bestValueRoute.getOrderNo());
LongLat bestStart = bestValueRoute.getLocations().get(bestValueRoute.getLocations().size()-1);
this.setDroneLocation(bestStart);
long endTime = System.nanoTime();
long totalTime = (endTime - startTime)/1000;
System.out.println("Add one route to delivery: "+totalTime); // for checking runtime
}
}
ArrayList<Delivery> finalisedDayRoute = new ArrayList<>();
double distance = 0.;
for (Delivery i : deliveryDecisionFinal) {
if (distance < DISTANCEBEFORERETURNHOME) { //creates final list by removing values that make journey too long
distance += i.getDistance();
finalisedDayRoute.add(i);
}
}
ArrayList<LongLat> home = new ArrayList<>();
LongLat secondlast = finalisedDayRoute.get(finalisedDayRoute.size() - 1).getLocations().get(finalisedDayRoute.get(finalisedDayRoute.size() - 1).getLocations().size() - 1);
home.add(APPLETONTOWER);
Delivery finalmove = getNextDistances(home, "RETHOME", secondlast); //adds final move back to home
System.out.println(finalisedDayRoute.size());
finalisedDayRoute.add(finalmove);
System.out.println(distance);
this.moves = finalisedDayRoute;
}
/**
* Given an order number and a starting location and the places we should move to, it will produce the route towards
* this whilst utilising the landmarks to avoid no-fly zones. Returning the shortest possible route.
*
* @param destinations an array list of longlats to travel to
* @param orderNo hexadecimal unique ordernumber we wish to find the distance for
* @param start starting location from which we get the distance
* @return new delivery route that is the shortest that does not cross confin zone or through no-fly zone
*/
private Delivery getNextDistances(ArrayList<LongLat> destinations, String orderNo, LongLat start) {
ArrayList<Delivery> deliver = new ArrayList<>();
List<LongLat> allLandmarks = this.getWebsite().getLandmarks();
for (LongLat delivery : destinations) {
ArrayList<LongLat> firstMove = new ArrayList<>();
firstMove.add(delivery);
Line line = new Line(start, delivery);
if (line.canMakeMove(this.getWebsite()) && delivery.isConfined()) {
Delivery oneLoc = new Delivery(orderNo, firstMove, start);
oneLoc.setDistance(start.distanceTo(delivery));
deliver.add(oneLoc);
} else {
for (LongLat landMark : allLandmarks) {
ArrayList<LongLat> moveViaLandmark = new ArrayList<>();
moveViaLandmark.add(landMark);
moveViaLandmark.add(delivery);
Line line1 = new Line(start, landMark);
Line line2 = new Line(landMark, delivery);
if ((line1.canMakeMove(this.getWebsite())) && (line2.canMakeMove(this.getWebsite()) && delivery.isConfined())) {
Delivery twoLocs = new Delivery(orderNo, moveViaLandmark, start);
twoLocs.setDistance(landMark.distanceTo(delivery) + start.distanceTo(landMark));
deliver.add(twoLocs);
}
}
}
}
if (deliver.isEmpty()) {
System.err.println(start.longitude);
System.err.println(start.latitude);
}
Delivery smallest = deliver.get(0);
for (int i = 1; i < deliver.size(); i++) {
Double b = smallest.getDistance();
Double a = deliver.get(i).getDistance();
if (a < b) { // return shortest possible route
smallest = deliver.get(i);
}
}
return smallest;
}
/**
* Calculate the total distance of all the deliveries
* @param pathUntotaled list of deliveries with individual distances
* @return totalled distance moved
*/
private Delivery totalDistance(ArrayList<Delivery> pathUntotaled) {
Double totalDistance = 0.;
ArrayList<LongLat> allLongLats = new ArrayList<>();
for (Delivery move : pathUntotaled) {
totalDistance += move.getDistance();
allLongLats.addAll(move.getLocations());
}
LongLat start = pathUntotaled.get(0).getLocations().get(0);
Delivery delivery = new Delivery(pathUntotaled.get(0).getOrderNo(), allLongLats, start);
delivery.setDistance(totalDistance);
return delivery;
}
/**
* Calculates the total cost of items for a given ordernumber including delivery cost
* @param database : database class for accessing database values
* @param website :website class for accessing website values
* @param orderNo hexidecimal value unique representation order number
* @return integer value representing cost on pence of order total
*/
private int getTotalCostofOrder(Database database, Website website, String orderNo) {
ArrayList<String> ordersItems = database.getOrders(orderNo);
int totalCost = 0;
if (ordersItems != null) {
totalCost = website.getDeliveryCost();
return totalCost;
}
return totalCost;
}
}