Here are my thoughts based on what I have seen in real life.
But one thing I have seen in real life that we don't have here is: traffic lights at adjacent intersections working together.
In general there are 4 states that the intersection can be in, and we can cycle through them in order.
The states are:
A) vertical (top to bottom or bottom to top) traffic, including pedestrian traffic
B) left turn from horizontal to vertical (also allows horizontal U-turns)
C) horizontal traffic, including pedestrian traffic
D) left turn from vertical to horizontal (also allows vertical U-turns)
There are also intermediate states if we want to get more complicated. In state B we are allowing two left turns: left-to-up and right-to-down. We might decide to stop the left-to-up traffic (in order to allow right-to-left traffic) but keep the right-to-down traffic going. So this is a state between B and C.
How long to stay in each state? We need all of these criteria to be met in order to be done with the state:
We can leave state A when all the cars have gone through, and X seconds have passed*, and the pedestrian time has passed (only applies if a pedestrian pressed the button)
We can leave state B when all the cars have gone through
We can leave state C when all the cars have gone through, and Y seconds have passed*, and the pedestrian time has passed (only applies if a pedestrian pressed the button)
We can leave state D when all the cars have gone through
*Example X and Y calculations:
X = 60 seconds during rush hour, 20 seconds otherwise
Y = 10 seconds
We could also put a time limit on each state.
In my drawing I show the 4 states. Black = the main flow. Blue = right turn traffic that is always allowed. Brown lines = pedestrian traffic.
xxxxxxxxxx
public class Road {
private static HashMap<char[], Road> roadMap = new HashMap<char[], Road>();
protected static int yAccumulativePosition = 0;
protected static int xAccumulativePosition = 0;
protected char[] roadID = new char[4]; //The number for each street or avenue
/*
* first char of the road ID 1=entrance, 2=exit, 3=street, 4=avenue
*/
protected char roadType; //S=street, A=avenue
protected char roadDir; //direction of source of traffic
//protected int accumulativePosition;
protected int[] sectors = new int[3];
//These two are essentially used to show the start and end points of a road.
protected TrafficPoint entrancePoint = null;
protected TrafficPoint exitPoint = null;
//needed for car movement default Forward=2, Turning=1
protected int numberOfForwardLanes = 2;
protected int numberOfTurningLanes = 1;
public static boolean addRoads(int number, int MinBlockSide,
int MaxBlockSide, char type) {
if(number == 0 || MinBlockSide <= 0 || MaxBlockSide <= 0 ||
(type != 'S' || type != 'A')) {
int accPos = 0;
if(type == 'S')
accPos = yAccumulativePosition;
else if(type == 'A')
accPos = xAccumulativePosition;
char dir = 'D';
Road tempRoad;
for(int i=1; i<=number; i++) {
accPos += (int) (MinBlockSide+(MaxBlockSide-MinBlockSide)*Math.random());
if(type == 'S')
dir = (i%2==0)? 'E':'W';
else if(type == 'A')
dir = (i%2==0)? 'N':'S';
tempRoad = new Road(i, dir, type, accPos);
//middle coordinates for all lanes
tempRoad.sectors[0] = accPos - 1 - Frame.carWidth - Frame.Clearance;
tempRoad.sectors[1] = accPos;
tempRoad.sectors[2] = accPos + 1 + Frame.carWidth + Frame.Clearance;
roadMap.put(tempRoad.roadID, tempRoad);
}
accPos += (int) (MinBlockSide+(MaxBlockSide-MinBlockSide)*Math.random());
if(type == 'S')
yAccumulativePosition = accPos;
else if(type == 'A')
xAccumulativePosition = accPos;
return true;
} else {
System.out.println("Wrong passed parameters to addRoads() funtion");
return false;
}
}
https://github.com/Skullbash27/trafficemgmt/tree/master/Traffic%20Management