package trafficdefinition;
import enums.MotionRestriction;
import enums.SchoolType;
import helpers.TimeConverter;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.geom.Point2D;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import roadnetwork.Edge;
import shapes.Point2DExt;
import shapes.Rectangle2DExt;
/**
* Class representing a school. This is used when creating traffic based on demographic data.
*/
public class School extends TrafficDefinitionElement implements Serializable {
private static final long serialVersionUID = 1L;
/**
* The closest edge to the school
*/
private Edge closestEdge = null;
/**
* The school's location
*/
private Point2DExt location;
/**
* The school's type
*/
private SchoolType schoolType;
/**
* The shape used to draw the school
*/
private Rectangle2DExt shape;
/**
* The time the school is closing
*/
private int timeClosing;
/**
* The time the school is opening
*/
private int timeOpening;
/**
* The total number of children that the school is able to accomodate
*/
private int capacity;
/**
* The available capacity of the school (used during schoool assignemnt)
*/
private int availableCapacity;
/**
* Default constructor.
*
* @param location
* the school's location
*/
public School(Point2D.Double location) {
super();
name = "School " + String.valueOf(increment++);
// Create the school's shape
shape = new Rectangle2DExt();
shape.setFrameFromCenter(location.x, location.y, location.x + 15, location.y + 15);
this.location = new Point2DExt(location);
// Create the handle
List<Handle> handles = new ArrayList<Handle>();
handles.add(new Handle(location, "location", MotionRestriction.None));
addHandles(handles);
// Set default values to school times
timeOpening = TimeConverter.toSeconds(7, 30);
timeClosing = TimeConverter.toSeconds(13, 30);
schoolType = SchoolType.Kindergarden;
capacity = 800;
// Set the default value to true to export the school shape to SUMO
exportPolygon = true;
}
/**
* Class constructor that creates a new school as a copy of the specified
* school
*
* @param source
*/
public School(School source) {
super(source);
closestEdge = source.closestEdge;
location = new Point2DExt(source.location);
shape = new Rectangle2DExt(source.shape);
schoolType = source.schoolType;
capacity = source.capacity;
timeClosing = source.timeClosing;
timeOpening = source.timeOpening;
}
@Override
public void Draw(Graphics2D g, double zoomFactor, boolean isDeleted, boolean isSelected) {
// Save the previous color to restore it later
Color prev = g.getColor();
if (!isSelected) {
g.setColor(Color.ORANGE);
}
if (isSelected) {
g.setColor(Color.GREEN);
}
if (shape != null) {
g.fill(shape);
}
super.Draw(g, zoomFactor, isDeleted, isSelected);
g.setColor(prev);
}
public Rectangle2DExt getBounds() {
return shape;
}
/**
* Returns the closest edge to the school
* @return
* @uml.property name="closestEdge"
*/
public Edge getClosestEdge() {
return closestEdge;
}
/**
* Returns the school's location
* @return
* @uml.property name="location"
*/
public Point2D.Double getLocation() {
return location;
}
/**
* Returns how much time (in seconds) a child can wait after school to be
* picked up by its parent
*
* @return
*/
public int amountOfTimeChildCanWaitAfterSchool() {
int result = 0;
switch (schoolType) {
case Kindergarden:
result = 0;
break;
case Elementary:
result = 10 * 60;
break;
case Middle:
result = 20 * 60;
break;
case High:
result = 30 * 60;
break;
}
return result;
}
/**
* Returns the priority that the school will have when assigning children to
* adults to take them to school
*
* @return
*/
public int getPriority() {
int result = 0;
switch (schoolType) {
case Kindergarden:
result = 4;
break;
case Elementary:
result = 3;
break;
case Middle:
result = 2;
break;
case High:
result = 1;
break;
}
return result;
}
/**
* Helper class used for sorting a list of schools based on their priority
*
*/
public static class SchoolPriorityComparator implements Comparator<School>{
public int compare(School school1, School school2) {
return school1.getPriority()-school2.getPriority();
}
}
/**
* @return the schoolType
* @uml.property name="schoolType"
*/
public SchoolType getSchoolType() {
return schoolType;
}
/**
* @return the capacity
* @uml.property name="capacity"
*/
public int getCapacity() {
return capacity;
}
/**
* @param capacity the capacity to set
* @uml.property name="capacity"
*/
public void setCapacity(int capacity) {
this.capacity = capacity;
}
/**
* @return the availableCapacity
* @uml.property name="availableCapacity"
*/
public int getAvailableCapacity() {
return availableCapacity;
}
/**
* @param availableCapacity the availableCapacity to set
* @uml.property name="availableCapacity"
*/
public void setAvailableCapacity(int availableCapacity) {
this.availableCapacity = availableCapacity;
}
/**
* @return the timeClosing
* @uml.property name="timeClosing"
*/
public int getTimeClosing() {
return timeClosing;
}
/**
* @return the timeOpening
* @uml.property name="timeOpening"
*/
public int getTimeOpening() {
return timeOpening;
}
@Override
public String getToolTip() {
return "<html>" + "<b>School</b> " + name + "<br>" + "<b>Type:</b> " + schoolType.name() + "<br>" + "<b>Time opening:</b> " + TimeConverter.toString(timeOpening) + "<br>" + "<b>Time closing:</b> " + TimeConverter.toString(timeClosing) + "<br>" + "<b>Capacity:</b> " + String.valueOf(capacity) + "</html>";
}
public void handleLocationChanged(Handle h) {
if (h.getName().equals("location")) {
location = new Point2DExt(h.getLocation());
shape.setFrameFromCenter(location.x, location.y, location.x + 15, location.y + 15);
}
}
@Override
public boolean Hit(Point p) {
if (shape.getBounds2D().contains(p.x, p.y)) {
if (shape.contains(p.x, p.y)) {
return true;
}
}
return false;
}
@Override
public boolean Hit(Rectangle transformedRectangle) {
return shape.intersects(transformedRectangle);
}
/**
* @param closestEdge the closestEdge to set
* @uml.property name="closestEdge"
*/
public void setClosestEdge(Edge closestEdge) {
this.closestEdge = closestEdge;
}
/**
* @param schoolType the schoolType to set
* @uml.property name="schoolType"
*/
public void setSchoolType(SchoolType schoolType) {
this.schoolType = schoolType;
}
/**
* @param timeClosing the timeClosing to set
* @uml.property name="timeClosing"
*/
public void setTimeClosing(int timeClosing) {
this.timeClosing = timeClosing;
}
/**
* @param timeOpening the timeOpening to set
* @uml.property name="timeOpening"
*/
public void setTimeOpening(int timeOpening) {
this.timeOpening = timeOpening;
}
@Override
public TrafficDefinitionElement elementClone() {
return new School(this);
}
/* (non-Javadoc)
* @see trafficdefinition.TrafficDefinitionElement#getGeometryXML()
*/
@Override
public String getGeometryXML() {
StringBuilder polyBuilder = new StringBuilder();
polyBuilder.append("<poly id=\"" + schoolType.name() + " School " + name + "\" type=\"School\" color=\"1,0,0\" fill=\"true\" layer=\"-1\">");
polyBuilder.append(String.valueOf(shape.getMinX()) + "," + String.valueOf(shape.getMinY()));
polyBuilder.append(" " + String.valueOf(shape.getMinX()) + "," + String.valueOf(shape.getMaxY()));
polyBuilder.append(" " + String.valueOf(shape.getMaxX()) + "," + String.valueOf(shape.getMaxY()));
polyBuilder.append(" " + String.valueOf(shape.getMaxX()) + "," + String.valueOf(shape.getMinY()));
polyBuilder.append("</poly>\n");
return polyBuilder.toString();
}
@Override
public String toXML() {
StringBuilder sb=new StringBuilder();
sb.append("<school name=\""+name+"\" openingTime=\""+String.valueOf(timeOpening)+"\" closingTime=\""+String.valueOf(timeClosing)+"\" level=\""+schoolType.name()+"\" capacity=\"" + String.valueOf(capacity) + "\" location=\""+String.valueOf(location.x)+","+String.valueOf(location.y)+"\" />\n");
return sb.toString();
}
}