Nantes Université

Skip to content
Extraits de code Groupes Projets
Valider cc2b9825 rédigé par Erwan BOUSSE's avatar Erwan BOUSSE
Parcourir les fichiers

First complete version

parent c83fe1e3
Branches
Aucune étiquette associée trouvée
Aucune requête de fusion associée trouvée
Affichage de
avec 497 ajouts et 39 suppressions
.idea .idea
*.iml *.iml
\ No newline at end of file target
\ No newline at end of file
package fr.univnantes; package fr.univnantes.trainreservation;
/** /**
* Represents a city with a train station. * Represents a city with a train station.
......
package fr.univnantes; package fr.univnantes.trainreservation;
/** /**
* Thrown when something wrong happens during a ticket reservation. * Thrown when something wrong happens during a ticket reservation.
......
package fr.univnantes; package fr.univnantes.trainreservation;
/** /**
* Represents a ticket booked for a trip by a customer. * Represents a ticket booked for a trip by a customer.
...@@ -26,7 +26,17 @@ public interface Ticket { ...@@ -26,7 +26,17 @@ public interface Ticket {
/** /**
* Cancels this ticket. Cannot be undone. * Cancels this ticket. Cannot be undone.
* Once a ticket has been cancelled, isCancelled() always returns true.
*/ */
void cancel(); void cancel();
/**
* Exchanges the ticket for a new ticket for a different trip.
* Once exchanged, a ticket becomes cancelled.
* It is only possible to exchange a ticket if the new trip has the same origin and the same destination,
* and if the new trip has not been cancelled, and if the new trip planned departure is after the ticket planned departure.
* @param trip The trip for the new ticket.
* @throws ReservationException If the trip does not satisfy the constraints.
* @return The new ticket
*/
Ticket exchangeTicket(Trip trip) throws ReservationException;
} }
package fr.univnantes; package fr.univnantes.trainreservation;
import java.time.Duration; import java.time.Duration;
import java.time.Instant; import java.time.Instant;
import java.time.LocalDate; import java.time.LocalDate;
import java.util.List; import java.util.List;
import java.util.Optional;
/** /**
* Represents a ticket reservation system. It can be used both to manage * Represents a ticket reservation system. It can be used both to manage
...@@ -12,27 +13,6 @@ import java.util.List; ...@@ -12,27 +13,6 @@ import java.util.List;
*/ */
public interface TicketReservationSystem { public interface TicketReservationSystem {
/**
* Creates a new Ticket for a given trip, and records the ticket in the trip.
* It is only possible to book a ticket if the trip had not already reached the maximum amount of passengers.
* @param trip The trip for which a ticket must be booked.
* @param passengerName The name of the passenger.
* @return The ticket that has been booked.
* @throws ReservationException If the trip has already reached the maximum amount of passengers.
*/
Ticket bookTicket(Trip trip, String passengerName) throws ReservationException;
/**
* Exchanges a ticket for a new ticket for a different trip.
* Once exchanged, a ticket becomes cancelled.
* It is only possible to exchange a ticket if the new trip has the same origin and the same destination,
* and if the new trip has not been cancelled, and if the new trip departure is after the ticket departure.
* @param ticket The ticket to exchange.
* @param trip The trip for the new ticket.
* @throws ReservationException If the trip does not satisfy the constraints.
* @return The new ticket
*/
Ticket exchangeTicket(Ticket ticket, Trip trip) throws ReservationException;
/** /**
* Retrieves the list of all booked tickets (not cancelled). * Retrieves the list of all booked tickets (not cancelled).
...@@ -49,7 +29,7 @@ public interface TicketReservationSystem { ...@@ -49,7 +29,7 @@ public interface TicketReservationSystem {
/** /**
* Finds all the trips eligible for an exchange against a ticket. * Finds all the trips eligible for an exchange against a ticket.
* A trip is eligible for an exchange if the trip has the same origin and the same destination as the ticket, * A trip is eligible for an exchange if the trip has the same origin and the same destination as the ticket,
* and if the trip has not been cancelled, and if the trip departure is after the ticket departure. * and if the trip has not been cancelled, and if the trip planned departure is after the ticket planned departure.
* @param ticket The ticket for which to find exchange possibilities. * @param ticket The ticket for which to find exchange possibilities.
* @return The list of all trips eligible for the exchange. * @return The list of all trips eligible for the exchange.
*/ */
...@@ -104,9 +84,9 @@ public interface TicketReservationSystem { ...@@ -104,9 +84,9 @@ public interface TicketReservationSystem {
/** /**
* Creates and registers a new trip in the system. * Creates and registers a new trip in the system.
* A trip can only be created if the following constraints are satisfied: * A trip can only be created if the following constraints are satisfied:
* - The train must not be already in another trip at the same time as the new trip. * - The train must not be already in another trip at the same time as the new trip (using real departure and arrival times).
* - The last destination of the train must be in the same city as the origin of the new trip. * - The last destination of the train must be in the same city as the origin of the new trip.
* - The last arrival of the train must be at least 10 minutes from the departure of the new trip. * - The last arrival of the train must be at least 10 minutes from the departure of the new trip (using real departure and arrival times)..
* - The arrival must come after the departure. * - The arrival must come after the departure.
* - The origin must be different from the destination. * - The origin must be different from the destination.
* @return The created registered trip. * @return The created registered trip.
...@@ -126,7 +106,7 @@ public interface TicketReservationSystem { ...@@ -126,7 +106,7 @@ public interface TicketReservationSystem {
* Also automatically adds an arrival delay of the same amount. * Also automatically adds an arrival delay of the same amount.
* @param delay The amount of delay to add. * @param delay The amount of delay to add.
*/ */
void addDepartureDelay(Trip trip, Duration delay); void delayTripDeparture(Trip trip, Duration delay);
/** /**
* Adds an arrival delay to a trip. * Adds an arrival delay to a trip.
...@@ -134,6 +114,33 @@ public interface TicketReservationSystem { ...@@ -134,6 +114,33 @@ public interface TicketReservationSystem {
* departure remains at least 10 minutes from the arrival time of the delayed trip. * departure remains at least 10 minutes from the arrival time of the delayed trip.
* @param delay The amount of delay to add. * @param delay The amount of delay to add.
*/ */
void addArrivalDelay(Trip trip, Duration delay); void delayTripArrival(Trip trip, Duration delay);
/**
* Finds the trip that follows an existing trip of a train.
* @param train The train.
* @param trip The trip.
* @return The trip following the given trip, for the train.
* @throws TripException if the trip's train is not the same
*/
Optional<Trip> findNextTripOfTrain(Train train, Trip trip) throws TripException;
/**
* Finds the trip that precedes an existing trip of a train.
* @param train The train.
* @param trip The trip.
* @return The trip preceding the given trip, for the train.
* @throws TripException if the trip's train is not the same
*/
Optional<Trip> findPreviousTripOfTrain(Train train, Trip trip) throws TripException;
/**
* Finds and orders all the trips of a given train.
* @param train The train.
* @return The ordered list of all trips for this train.
*/
List<Trip> findOrderedTripsOfTrain(Train train);
} }
package fr.univnantes; package fr.univnantes.trainreservation;
/** /**
* Represents a train available in the rail system. * Represents a train available in the rail system.
......
package fr.univnantes; package fr.univnantes.trainreservation;
import java.time.Duration; import java.time.Duration;
import java.time.Instant; import java.time.Instant;
...@@ -11,36 +11,49 @@ public interface Trip { ...@@ -11,36 +11,49 @@ public interface Trip {
/** /**
* Retrieves the origin city of the trip. * Retrieves the origin city of the trip.
*
* @return the origin city of the trip. * @return the origin city of the trip.
*/ */
City getOrigin(); City getOrigin();
/** /**
* Retrieves the destination city of the trip. * Retrieves the destination city of the trip.
*
* @return the destination city of the trip. * @return the destination city of the trip.
*/ */
City getDestination(); City getDestination();
/** /**
* Retrieves the train used for the trip. * Retrieves the train used for the trip.
*
* @return the train used for the trip. * @return the train used for the trip.
*/ */
Train getTrain(); Train getTrain();
/** /**
* Finds the duration of the trip. * Finds the planned duration of the trip.
* @return The duration of the trip (ie. the duration between departure and arrival). *
* @return The planned duration of the trip (ie. the duration between planned departure and arrival).
*/ */
Duration findDuration(); Duration findPlannedDuration();
/**
* Finds the real duration of the trip.
*
* @return The real duration of the trip (ie. the duration between real departure and arrival).
*/
Duration findRealDuration();
/** /**
* Retrieves whether the trip was cancelled or not. * Retrieves whether the trip was cancelled or not.
*
* @return true if the trip was cancelled, false otherwise. * @return true if the trip was cancelled, false otherwise.
*/ */
boolean isCancelled(); boolean isCancelled();
/** /**
* Retrieves whether the trip was delayed or not. * Retrieves whether the trip was delayed or not.
*
* @return true if the trip was delayed (ie. if the amount of delay it above zero), false otherwise. * @return true if the trip was delayed (ie. if the amount of delay it above zero), false otherwise.
*/ */
boolean isDelayed(); boolean isDelayed();
...@@ -48,54 +61,85 @@ public interface Trip { ...@@ -48,54 +61,85 @@ public interface Trip {
/** /**
* Cancels the trip. * Cancels the trip.
* This also automatically cancels all tickets for this trip. * This also automatically cancels all tickets for this trip.
*/ */
void cancel(); void cancel();
/** /**
* Get the initially planned departure time. * Get the initially planned departure time.
*
* @return the initially planned departure time. * @return the initially planned departure time.
*/ */
Instant getPlannedDepartureTime(); Instant getPlannedDepartureTime();
/** /**
* Get the initially planned arrival time. * Get the initially planned arrival time.
*
* @return the initially planned arrival time. * @return the initially planned arrival time.
*/ */
Instant getPlannedArrivalTime(); Instant getPlannedArrivalTime();
/** /**
* Finds the real departure time, considering delays. * Finds the real departure time, considering delays.
*
* @return the real departure time, considering delays. * @return the real departure time, considering delays.
*/ */
Instant findRealDepartureTime(); Instant findRealDepartureTime();
/** /**
* Finds the real arrival time, considering delays. * Finds the real arrival time, considering delays.
*
* @return the real arrival time, considering delays. * @return the real arrival time, considering delays.
*/ */
Instant findRealArrivalTime(); Instant findRealArrivalTime();
/** /**
* Retrieves the departure delay for this trip. * Retrieves the departure delay for this trip.
*
* @return the departure delay. * @return the departure delay.
*/ */
Duration getDepartureDelay(); Duration getDepartureDelay();
/** /**
* Retrieves the arrival delay for this trip. * Retrieves the arrival delay for this trip.
*
* @return the arrival delay. * @return the arrival delay.
*/ */
Duration getArrivalDelay(); Duration getArrivalDelay();
/** /**
* Retrieves the list of all (non-cancelled) booked tickets for this trip. * Retrieves the list of all (non-cancelled) booked tickets for this trip.
*
* @return the list of all (non-cancelled) booked tickets for this trip. * @return the list of all (non-cancelled) booked tickets for this trip.
*/ */
List<Ticket> getBookedTickets(); List<Ticket> getBookedTickets();
/** /**
* Retrieves the list of all cancelled tickets for this trip. * Retrieves the list of all cancelled tickets for this trip.
*
* @return the list of all cancelled tickets for this trip. * @return the list of all cancelled tickets for this trip.
*/ */
List<Ticket> getCancelledTickets(); List<Ticket> getCancelledTickets();
/**
* Creates a new Ticket for the trip, and records the ticket in the trip.
* It is only possible to book a ticket if the trip had not already reached the maximum amount of passengers.
* @param passengerName The name of the passenger.
* @return The ticket that has been booked.
* @throws ReservationException If the trip has already reached the maximum amount of passengers.
*/
Ticket bookTicket(String passengerName) throws ReservationException;
/**
* Adds a duration to the departure delay.
* @param delay The duration delay.
*/
void addDepartureDelay(Duration delay);
/**
* Adds a duration to the arrival delay.
* @param delay The duration delay.
*/
void addArrivalDelay(Duration delay);
} }
package fr.univnantes; package fr.univnantes.trainreservation;
/** /**
* Thrown when something wrong happens during a trip creation. * Thrown when something wrong happens during a trip creation.
......
package fr.univnantes.trainreservation.impl;
import fr.univnantes.trainreservation.City;
public class CityImpl implements City {
private final String name;
public CityImpl(String name) {
this.name = name;
}
@Override
public String getName() {
return this.name;
}
}
package fr.univnantes.trainreservation.impl;
import fr.univnantes.trainreservation.ReservationException;
import fr.univnantes.trainreservation.Ticket;
import fr.univnantes.trainreservation.Trip;
public class TicketImpl implements Ticket {
private boolean cancelled;
private String passengerName;
private Trip trip;
public TicketImpl(String passengerName, Trip trip) {
this.cancelled = false;
this.passengerName = passengerName;
this.trip = trip;
}
@Override
public boolean isCancelled() {
return this.cancelled;
}
@Override
public String getPassengerName() {
return this.passengerName;
}
@Override
public Trip getTrip() {
return this.trip;
}
@Override
public void cancel() {
this.cancelled = true;
}
@Override
public Ticket exchangeTicket(Trip trip) throws ReservationException {
if (this.getTrip().getOrigin() != trip.getOrigin()
|| this.getTrip().getDestination() != trip.getDestination()
|| this.getTrip().isCancelled()
|| this.getTrip().getPlannedDepartureTime().isBefore(trip.getPlannedDepartureTime())
) {
throw new ReservationException();
}
this.cancel();
return new TicketImpl(this.getPassengerName(), trip);
}
}
package fr.univnantes.trainreservation.impl;
import fr.univnantes.trainreservation.*;
import java.time.Duration;
import java.time.Instant;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.*;
import java.util.stream.Collectors;
public class TicketReservationSystemImpl implements TicketReservationSystem {
private List<Trip> trips;
private List<Trip> cancelledTrips;
private List<City> cities;
private List<Train> trains;
private ZoneId timeZone;
/**
* TODO
*
* @param timeZone
*/
public TicketReservationSystemImpl(ZoneId timeZone) {
this.trips = new ArrayList<>();
this.cancelledTrips = new ArrayList<>();
this.cities = new ArrayList<>();
this.trains = new ArrayList<>();
this.timeZone = timeZone;
}
@Override
public List<Ticket> getAllBookedTickets() {
return trips.stream().map(t -> t.getBookedTickets()).flatMap(Collection::stream).collect(Collectors.toList());
}
@Override
public List<Ticket> getAllCancelledTickets() {
return trips.stream().map(t -> t.getCancelledTickets()).flatMap(Collection::stream).collect(Collectors.toList());
}
@Override
public List<Trip> findPossibleExchanges(Ticket ticket) {
return trips.stream().filter(trip -> trip.getOrigin() == ticket.getTrip().getOrigin()
&& trip.getDestination() == ticket.getTrip().getDestination()
&& !trip.isCancelled()
&& trip.getPlannedDepartureTime().isAfter(ticket.getTrip().getPlannedDepartureTime())).collect(Collectors.toList());
}
@Override
public List<Trip> findAvailableTrips(City origin, LocalDate date) {
return trips.stream().filter(trip -> trip.getOrigin() == origin
&& trip.getPlannedDepartureTime().atZone(timeZone).toLocalDate().equals(date)).collect(Collectors.toList());
}
@Override
public List<Trip> findAvailableTrips(City origin, City destination, LocalDate date) {
return findAvailableTrips(origin, date).stream().filter(trip -> trip.getDestination() == destination).collect(Collectors.toList());
}
@Override
public List<City> getCities() {
return Collections.unmodifiableList(this.cities);
}
@Override
public List<Train> getAllTrains() {
return Collections.unmodifiableList(this.trains);
}
@Override
public List<Trip> getAllTrips() {
return Collections.unmodifiableList(this.trips);
}
@Override
public List<Trip> getAllCancelledTrips() {
return Collections.unmodifiableList(this.cancelledTrips);
}
@Override
public void addCity(City city) {
this.cities.add(city);
}
@Override
public Trip createTrip(City origin, City destination, Train train, Instant departure, Instant arrival) throws TripException {
List<Trip> trainTrips = this.findOrderedTripsOfTrain(train);
Optional<Trip> lastTrainTrip = Optional.ofNullable(trainTrips.isEmpty() ? null :
trainTrips.get(trainTrips.size() - 1));
boolean c1 = trainTrips.stream().allMatch(trip ->
!(trip.findRealDepartureTime().isAfter(departure)
&& trip.findRealDepartureTime().isBefore(arrival))
&& !(trip.findRealArrivalTime().isAfter(departure)
&& trip.findRealArrivalTime().isBefore(arrival)));
boolean c2 = lastTrainTrip.isEmpty() ||
lastTrainTrip.get().getDestination() == origin;
boolean c3 = lastTrainTrip.isEmpty() ||
Duration.between(lastTrainTrip.get().findRealArrivalTime(), departure)
.compareTo(Duration.ofMinutes(10)) == 1;
boolean c4 = arrival.isAfter(departure);
boolean c5 = origin != destination;
if (!(c1 && c2 && c3 && c4 && c5))
throw new TripException();
Trip trip = new TripImpl(origin, destination, train, departure, arrival);
trips.add(trip);
return trip;
}
@Override
public void cancelTrip(Trip trip) {
trip.cancel();
trips.remove(trip);
cancelledTrips.add(trip);
}
@Override
public void delayTripDeparture(Trip trip, Duration delay) {
trip.addDepartureDelay(delay);
this.delayTripArrival(trip, delay);
}
@Override
public void delayTripArrival(Trip trip, Duration delay) {
trip.addArrivalDelay(delay);
}
@Override
public Optional<Trip> findNextTripOfTrain(Train train, Trip trip) throws TripException {
if (trip.getTrain() != train) {
throw new TripException();
}
List<Trip> orderedTrips = findOrderedTripsOfTrain(train);
int nextTripIndex = orderedTrips.indexOf(trip) + 1;
Trip result = nextTripIndex < orderedTrips.size() ? orderedTrips.get(nextTripIndex) : null;
return Optional.ofNullable(result);
}
@Override
public Optional<Trip> findPreviousTripOfTrain(Train train, Trip trip) throws TripException {
if (trip.getTrain() != train) {
throw new TripException();
}
List<Trip> orderedTrips = findOrderedTripsOfTrain(train);
int previousTripIndex = orderedTrips.indexOf(trip) - 1;
Trip result = previousTripIndex >= 0 ? orderedTrips.get(previousTripIndex) : null;
return Optional.ofNullable(result);
}
@Override
public List<Trip> findOrderedTripsOfTrain(Train train) {
return trips.stream().sorted((t1, t2) -> t1.findRealArrivalTime().isBefore(t2.findRealDepartureTime()) ? -1 : 1).collect(Collectors.toList());
}
}
package fr.univnantes.trainreservation.impl;
import fr.univnantes.trainreservation.Train;
public class TrainImpl implements Train {
private final String name;
private final int maxPassengers;
public TrainImpl(String name, int maxPassengers) {
this.name = name;
this.maxPassengers = maxPassengers;
}
@Override
public String getName() {
return this.name;
}
@Override
public int getMaxPassengers() {
return this.maxPassengers;
}
}
package fr.univnantes.trainreservation.impl;
import fr.univnantes.trainreservation.*;
import java.time.Duration;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class TripImpl implements Trip {
private final City origin;
private final City destination;
private final Train train;
private boolean cancelled;
private final Instant departureTime;
private final Instant arrivalTime;
private Duration departureDelay;
private Duration arrivalDelay;
private final List<Ticket> bookedTickets;
private final List<Ticket> cancelledTickets;
public TripImpl(City origin, City destination, Train train, Instant departureTime, Instant arrivalTime) {
this.origin = origin;
this.destination = destination;
this.train = train;
this.departureTime = departureTime;
this.arrivalTime = arrivalTime;
this.bookedTickets = new ArrayList<>();
this.cancelledTickets = new ArrayList<>();
this.cancelled = false;
this.departureDelay = Duration.ZERO;
this.arrivalDelay = Duration.ZERO;
}
@Override
public City getOrigin() {
return this.origin;
}
@Override
public City getDestination() {
return this.destination;
}
@Override
public Train getTrain() {
return this.train;
}
@Override
public Duration findPlannedDuration() {
return Duration.between(this.departureTime, this.arrivalTime);
}
@Override
public Duration findRealDuration() {
return Duration.between(this.findRealDepartureTime(), this.findRealArrivalTime());
}
@Override
public boolean isCancelled() {
return this.cancelled;
}
@Override
public boolean isDelayed() {
return !this.getDepartureDelay().equals(Duration.ZERO) && !this.getArrivalDelay().equals(Duration.ZERO.isZero());
}
@Override
public void cancel() {
this.cancelled = true;
for (Ticket ticket: bookedTickets) {
ticket.cancel();
}
}
@Override
public Instant getPlannedDepartureTime() {
return departureTime;
}
@Override
public Instant getPlannedArrivalTime() {
return arrivalTime;
}
@Override
public Instant findRealDepartureTime() {
return departureTime.plus(departureDelay);
}
@Override
public Instant findRealArrivalTime() {
return arrivalTime.plus(arrivalDelay);
}
@Override
public Duration getDepartureDelay() {
return departureDelay;
}
@Override
public Duration getArrivalDelay() {
return arrivalDelay;
}
@Override
public List<Ticket> getBookedTickets() {
return Collections.unmodifiableList(bookedTickets);
}
@Override
public List<Ticket> getCancelledTickets() {
return Collections.unmodifiableList(cancelledTickets);
}
@Override
public Ticket bookTicket(String passengerName) throws ReservationException {
if (this.getBookedTickets().size() >= this.getTrain().getMaxPassengers()) {
throw new ReservationException();
}
Ticket ticket = new TicketImpl(passengerName, this);
this.bookedTickets.add(ticket);
return ticket;
}
@Override
public void addDepartureDelay(Duration delay) {
this.departureDelay = this.departureDelay.plus(delay);
}
@Override
public void addArrivalDelay(Duration delay) {
this.arrivalDelay = this.arrivalDelay.plus(delay);
}
}
0% Chargement en cours ou .
You are about to add 0 people to the discussion. Proceed with caution.
Veuillez vous inscrire ou vous pour commenter