package simulation;
import classes.Constants;
import helpers.MultipleTripExpander;
import helpers.RandomNumberProvider;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import roadnetwork.Edge;
import trafficdefinition.School;
/**
* Class representing an adult in a virtual area. This class is used when
* creating traffic based on demographic data.
*/
public class Adult extends Person {
/**
* Flag to know if the adult can drive
*/
private boolean canDrive;
/**
* A list of the children that the adult has to pick up from school
*/
private List<Child> childrenToPickupFromSchool = null;
/**
* A list of the children that the adult has to take to school
*/
private List<Child> childrenToTakeToSchool = null;
/**
* Flag to know if the adult has a job
*/
private boolean hasJob;
/**
* The adult's virtual house
*/
private House home = null;
/**
* The adult's job type
*/
private JobType job;
/**
* The street on which the adult's job is located
*/
private Edge jobLocation = null;
/**
* The vehicle that the adult owns
*/
private VehicleType vehicle = null;
/**
* Class constructor
*
* @param house
* the adult's virtual house
* @param possibilityAdultIsDriver
* the possibility that the adult is a driver
* @param possibilityAdultHasJob
* the possibility that the adult is working
*/
public Adult(House house, float possibilityAdultIsDriver, float possibilityAdultHasJob) {
super();
Random r = RandomNumberProvider.getRandom();
// Set the driver property based on the possibility
if (r.nextFloat() <= possibilityAdultIsDriver) {
canDrive = true;
} else {
canDrive = false;
}
// Set the worker property based on the possibility
if (r.nextFloat() <= possibilityAdultHasJob) {
hasJob = true;
} else {
hasJob = false;
}
home = house;
}
/**
* Returns whether the adult can drive
*
* @return
*/
public boolean canDrive() {
return canDrive;
}
/**
* Checks to see if the adult can pickup the children from the specified
* school.
*
* @param school
* @return
*/
public boolean canPickupChildFromSchool(School school) {
// If the adult doesn't own a car then return false
if (vehicle == null) {
return false;
}
// If the driver is already responsible for picking up other children
// from school return false
if (childrenToPickupFromSchool != null) {
return false;
}
// If the adult doesn't have a job then she is always available
if (!hasJob) {
return true;
} else {
// Try to estimate the distance between the school and the job
float distanceToTravel = school.getClosestEdge().DistanceFrom(jobLocation);
// Estimate the time needed to cover this distance
int estimatedTravelTime = Math.round(distanceToTravel / Constants.averageSpeed);
// If the adult can make it on time from work to school then she
// can pickup the kid to school
if (job.getEndingTime() + estimatedTravelTime <= school.getTimeClosing() + school.amountOfTimeChildCanWaitAfterSchool()) {
return true;
} else {
return false;
}
}
}
/**
* Checks to see if the adult can take the children to the specified school
*
* @param school
* the school to take the children to
* @param amountOfTimeAdultAllowedToBeLate
* the number of seconds that the adult is allowed to be late to
* work
* @return
*/
public boolean canTakeChildToSchool(School school, int amountOfTimeAdultAllowedToBeLate) {
// If the adult doesn't have a vehicle then return false
if (vehicle == null) {
return false;
}
// If the adult is already responsible for taking other children to
// school then return false
if (childrenToTakeToSchool != null) {
return false;
}
// If the adult is not working then he can take the children to school
if (!hasJob) {
return true;
} else {
if (school.getTimeOpening() < job.getStartingTime()) {
// Try to estimate the distance between the school and the job
float distanceToTravel = school.getClosestEdge().DistanceFrom(jobLocation);
// Estimate the time needed to cover this distance
int estimatedTravelTime = Math.round(distanceToTravel / Constants.averageSpeed);
// If the adult can make it on time from the school to work then
// she can take the kid to school
if (school.getTimeOpening() + estimatedTravelTime <= job.getStartingTime() + amountOfTimeAdultAllowedToBeLate) {
return true;
}
}
}
// Else the adult can not take the children to school
return false;
}
/**
* Creates the adult's vehicle routes for 24 hours based on the adult's
* properties and whether the adult will take to or pick up children from
* school
*
* @param color
* the color that will be used for the routes
* @param tripsList
* List to place the generated trips into
* @param routesList
* List to place the generated routes into
* @param counter
* variable used to assign unique ids to trips and routes
* @throws Exception
* if anything goes wrong
*/
public void createTrips(String color, SUMOInstructionList<Trip> tripsList, SUMOInstructionList<Route> routesList, int counter) throws Exception {
// If the adult does not own a vehicle then no trips will be generated
if (vehicle == null) {
return;
}
// If the adult has a job and she has to take children to school
if (hasJob && (childrenToTakeToSchool != null)) {
// Get the children's school
School school = childrenToTakeToSchool.get(0).getSchool();
// Estimate distance between home->school and home->work
float distanceHomeSchool = home.getAddress().DistanceFrom(school.getClosestEdge());
float distanceHomeWork = home.getAddress().DistanceFrom(jobLocation);
// Estimate the time needed to travel from school->home->work,
// school->home and home->work
int estimatedTravelTimeSchoolHomeWork = Math.round((distanceHomeSchool + distanceHomeWork) / Constants.averageSpeed);
int estimatedTravelTimeHomeSchool = Math.round(distanceHomeSchool / Constants.averageSpeed);
int estimatedTravelTimeHomeWork = Math.round(distanceHomeWork / Constants.averageSpeed);
int timeBetweenSchoolOpeningAndJobStarting = job.getStartingTime() - school.getTimeOpening();
// Calculate the time to leave the house so that the child will
// be at school on time
int timeOfDepartureFromHouseToSchool = Math.max(0, school.getTimeOpening() - estimatedTravelTimeHomeSchool);
// If the adult cannot go from school back home, stay for 20 minutes
// and then go to work, then go straight from school to work
if ((estimatedTravelTimeSchoolHomeWork + 20 * 60) > timeBetweenSchoolOpeningAndJobStarting) {
// Create route for home->school->work
List<Edge> tripEdges = new ArrayList<Edge>();
tripEdges.add(home.getAddress());
tripEdges.add(school.getClosestEdge());
tripEdges.add(jobLocation);
String route = MultipleTripExpander.ExpandTrips(tripEdges);
// Write the route
routesList.add(new Route(timeOfDepartureFromHouseToSchool, "<vehicle id=\"home-school-work-" + String.valueOf(home.getId()) + "-" + String.valueOf(counter) + "\" type=\"" + vehicle.getName() + "\" depart=\"" + String.valueOf(timeOfDepartureFromHouseToSchool) + "\" color=\"" + color + "\">" + "<route color=\"" + color + "\">" + route + "</route>" + "</vehicle>"));
}
// If there is enough time go back home and later go to work
else {
// Create route for home->school->home
List<Edge> tripEdges = new ArrayList<Edge>();
tripEdges.add(home.getAddress());
tripEdges.add(school.getClosestEdge());
tripEdges.add(home.getAddress());
String route = MultipleTripExpander.ExpandTrips(tripEdges);
// Write the route
routesList.add(new Route(timeOfDepartureFromHouseToSchool, "<vehicle id=\"home-school-home-" + String.valueOf(home.getId()) + "-" + String.valueOf(counter) + "\" type=\"" + vehicle.getName() + "\" depart=\"" + String.valueOf(timeOfDepartureFromHouseToSchool) + "\" color=\"" + color + "\">" + "<route color=\"" + color + "\">" + route + "</route>" + "</vehicle>"));
// Estimate what time the adult has to leave home to be at work
// on time
int timeOfDepartureFromHouseToWork = Math.max(0, job.getStartingTime() - estimatedTravelTimeHomeWork);
// Write the trip home->work
tripsList.add(new Trip(timeOfDepartureFromHouseToWork,"<trip id=\"house-work-" + String.valueOf(home.getId()) + "-" + String.valueOf(counter) + "\" depart=\"" + String.valueOf(timeOfDepartureFromHouseToWork) + "\" from=\"" + home.getAddress().getId() + "\" to=\"" + jobLocation.getId() + "\" color=\"" + color + "\" type=\"" + vehicle.getName() + "\" />\n"));
}
}
// If the adult has a job but doesn't have to take children to school
else if (hasJob && (childrenToTakeToSchool == null)) {
// Just go to work
// Try to estimate the distance between home and work
float distanceToTravel = home.getAddress().DistanceFrom(jobLocation);
// Estimate the time needed to cover this distance
int estimatedTravelTime = Math.round(distanceToTravel / Constants.averageSpeed);
// Calculate the time to leave the house so that the adult will be
// at work on time
int timeOfDepartureFromHouse = Math.max(0, job.getStartingTime() - estimatedTravelTime);
// Create route from house to work
tripsList.add(new Trip(timeOfDepartureFromHouse,"<trip id=\"house-work-" + String.valueOf(home.getId()) + "-" + String.valueOf(counter) + "\" depart=\"" + String.valueOf(timeOfDepartureFromHouse) + "\" from=\"" + home.getAddress().getId() + "\" to=\"" + jobLocation.getId() + "\" color=\"" + color + "\" type=\"" + vehicle.getName() + "\" />\n"));
}
// If the adult is unemployeed and has to take children to school
else if (!hasJob && (childrenToTakeToSchool != null)) {
// Get the children's school
School school = childrenToTakeToSchool.get(0).getSchool();
// Try to estimate the distance that the vehicle will need to
// travel
float distanceHomeSchool = home.getAddress().DistanceFrom(school.getClosestEdge());
// Estimate the time needed to go from school to home
int estimatedTravelTimeHomeSchool = Math.round(distanceHomeSchool / Constants.averageSpeed);
// Calculate the time to leave the house
int timeOfDepartureFromHouse = Math.max(0, school.getTimeOpening() - estimatedTravelTimeHomeSchool);
// Go from home to school and back
List<Edge> tripEdges = new ArrayList<Edge>();
tripEdges.add(home.getAddress());
tripEdges.add(school.getClosestEdge());
tripEdges.add(home.getAddress());
String route = MultipleTripExpander.ExpandTrips(tripEdges);
// Write the route
routesList.add(new Route(timeOfDepartureFromHouse,"<vehicle id=\"home-school-home-" + String.valueOf(home.getId()) + "-" + String.valueOf(counter) + "\" type=\"" + vehicle.getName() + "\" depart=\"" + String.valueOf(timeOfDepartureFromHouse) + "\" color=\"" + color + "\">"+"<route color=\"" + color + "\">" + route + "</route>"+"</vehicle>"));
}
// If the adult has a job and she doesn't have to pick up kids from
// school
if (hasJob && (childrenToPickupFromSchool == null)) {
// Create route from work to home
tripsList.add(new Trip(job.getEndingTime(),"<trip id=\"work-house-" + String.valueOf(home.getId()) + "-" + String.valueOf(counter) + "\" depart=\"" + String.valueOf(job.getEndingTime()) + "\" from=\"" + jobLocation.getId() + "\" to=\"" + home.getAddress().getId() + "\" color=\"" + color + "\" type=\"" + vehicle.getName() + "\" />\n"));
}
// If the adult has a job and she has to pickup kids from school
else if (hasJob && (childrenToPickupFromSchool != null)) {
// Get the children's school
School school = childrenToPickupFromSchool.get(0).getSchool();
// Estimate distance between home-school and school-work
float distanceHomeSchool = home.getAddress().DistanceFrom(school.getClosestEdge());
float distanceHomeWork = home.getAddress().DistanceFrom(jobLocation);
// Estimate the time needed to go from work to school and then from
// school to home
int estimatedTravelTimeWorkSchoolHome = Math.round((distanceHomeSchool + distanceHomeWork) / Constants.averageSpeed);
int timeBetweenJobEndingAndSchoolClosing = school.getTimeClosing() - job.getEndingTime();
// If the adult doesn't have enough time after work to go home for
// 20 minutes
if ((estimatedTravelTimeWorkSchoolHome + 20 * 60) > timeBetweenJobEndingAndSchoolClosing) {
// Go straight from work to school and then home
List<Edge> tripEdges = new ArrayList<Edge>();
tripEdges.add(jobLocation);
tripEdges.add(school.getClosestEdge());
tripEdges.add(home.getAddress());
// Build the route
String route = MultipleTripExpander.ExpandTrips(tripEdges);
routesList.add(new Route(job.getEndingTime(),"<vehicle id=\"work-school-home-" + String.valueOf(home.getId()) + "-" + String.valueOf(counter) + "\" type=\"" + vehicle.getName() + "\" depart=\"" + String.valueOf(job.getEndingTime()) + "\" color=\"" + color + "\">"+"<route color=\"" + color + "\">" + route + "</route>"+"</vehicle>"));
}
// If the adult has enough time to go home after work
else {
// Go from work to home and from home to school and from school
// to home
// Create route from work to home
tripsList.add(new Trip(job.getEndingTime(),"<trip id=\"work-house-" + String.valueOf(home.getId()) + "-" + String.valueOf(counter) + "\" depart=\"" + String.valueOf(job.getEndingTime()) + "\" from=\"" + jobLocation.getId() + "\" to=\"" + home.getAddress().getId() + "\" color=\"" + color + "\" type=\"" + vehicle.getName() + "\" />\n"));
// Estimate the time needed to cover the distance from home to
// school
int estimatedTravelTime = (int) Math.round(distanceHomeSchool / Constants.averageSpeed);
// Calculate the time to leave the house so that the adult will
// be at school on time
int timeOfDepartureFromHouse = Math.max(0, school.getTimeClosing() - estimatedTravelTime);
// Build the route
List<Edge> tripEdges = new ArrayList<Edge>();
tripEdges.add(home.getAddress());
tripEdges.add(school.getClosestEdge());
tripEdges.add(home.getAddress());
String route = MultipleTripExpander.ExpandTrips(tripEdges);
routesList.add(new Route(timeOfDepartureFromHouse,"<vehicle id=\"home-school-home-" + String.valueOf(home.getId()) + "-" + String.valueOf(counter) + "\" type=\"" + vehicle.getName() + "\" depart=\"" + String.valueOf(timeOfDepartureFromHouse) + "\" color=\"" + color + "\">"+"<route color=\"" + color + "\">" + route + "</route>"+"</vehicle>"));
}
}
// If the adult has no job and has children to pick up
else if (!hasJob && (childrenToPickupFromSchool != null)) {
School school = childrenToPickupFromSchool.get(0).getSchool();
// Try to estimate the distance between home and school
float distanceToTravel = home.getAddress().DistanceFrom(school.getClosestEdge());
// Estimate the time needed to cover this distance
int estimatedTravelTime = (int) Math.round(distanceToTravel / Constants.averageSpeed);
// Calculate the time to leave the house so that the adult will be
// at school on time
int timeOfDepartureFromHouse = Math.max(0, school.getTimeClosing() - estimatedTravelTime);
// Create route from house to school and back
List<Edge> tripEdges = new ArrayList<Edge>();
tripEdges.add(home.getAddress());
tripEdges.add(school.getClosestEdge());
tripEdges.add(home.getAddress());
String route = MultipleTripExpander.ExpandTrips(tripEdges);
routesList.add(new Route(timeOfDepartureFromHouse, "<vehicle id=\"home-school-home-" + String.valueOf(home.getId()) + "-" + String.valueOf(counter) + "\" type=\"" + vehicle.getName() + "\" depart=\"" + String.valueOf(timeOfDepartureFromHouse) + "\" color=\"" + color + "\">"+"<route color=\"" + color + "\">" + route + "</route>"+"</vehicle>"));
}
}
/**
* @return the job
* @uml.property name="job"
*/
public JobType getJob() {
return job;
}
/**
* @return the jobLocation
* @uml.property name="jobLocation"
*/
public Edge getJobLocation() {
return jobLocation;
}
public boolean hasJob() {
return hasJob;
}
/**
* Assigns the specified children to the adult so that she will take them to
* school
*
* @param children
*/
public void pickupChildrenFromSchool(List<Child> children) {
childrenToPickupFromSchool = children;
}
/**
* @param hasJob
* the hasJob to set
* @uml.property name="hasJob"
*/
public void setHasJob(boolean hasJob) {
this.hasJob = hasJob;
}
/**
* Sets the specified job to the adult
*
* @param job
* the adult's job type
* @param jobLocation
* the job location
*/
public void setJobLocation(JobType job, Edge jobLocation) {
this.jobLocation = jobLocation;
this.job = job;
}
/**
* @param vehicle
* the vehicle to set
* @uml.property name="vehicle"
*/
public void setVehicle(VehicleType vehicle) {
this.vehicle = vehicle;
}
/**
* Assigns the specified children to the adult so that she will pick them up
* from school
*
* @param children
*/
public void takeChildrenToSchool(List<Child> children) {
childrenToTakeToSchool = children;
}
/**
* @return the vehicle
* @uml.property name="vehicle"
*/
public VehicleType getVehicle() {
return vehicle;
}
}