/**
*
* TrafficMitigation is a GUI application that runs multiple threads concurrently
* to display current time stamps in 1 second intervals and a real-time Traffic
* light display for three major intersections using multiple JFrame components
* and listeners
*/
//=========
//packages
//=========
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import java.util.concurrent.atomic.*;
//=================================
//start of class TrafficMitigation
//=================================
public class TrafficMitigation extends JFrame implements Runnable, ChangeListener {
private static final long serialVersionUID = 1L;
//==================
//JFrame components
//==================
public static JLabel currentTime = new JLabel();
public static JLabel trafficLight1 = new JLabel();
private static JLabel trafficLightLabel1;
public static JLabel trafficLight2 = new JLabel();
private static JLabel trafficLightLabel2;
public static JLabel trafficLight3 = new JLabel();
private static JLabel trafficLightLabel3;
private static JButton startButton;
private static JButton pauseButton;
private static JButton stopButton;
private static JComboBox<Integer> carsJComboBox;
private static JComboBox<Integer> intersectionJComboBox;
private static JLabel carBoxLabel;
private static JLabel intersectionBoxLabel;
private static JLabel header1;
private static JLabel header2;
private static JLabel timeLabel;
private static JSlider car1Slider;
private static JSlider car2Slider;
private static JSlider car3Slider;
//==========
//variables
//==========
private static boolean running;
private static Thread thread;
//=========
//invoking
//=========
private static final AtomicBoolean simIsRunning = new AtomicBoolean(false);
//=============================================
//invoking and each object gets its own thread
//=============================================
private Intersection intersection1 = new Intersection("Intersection 1 Thread", trafficLight1);
private Intersection intersection2 = new Intersection("Intersection 2 Thread", trafficLight2);
private Intersection intersection3 = new Intersection("Intersection 3 Thread", trafficLight3);
private Car car1 = new Car("Car 1 Thread", 1, 0);
private Car car2 = new Car("Car 2 Thread", 300, 0);
private Car car3 = new Car("Car 3 Thread", 700, 0);
//=======
//arrays
//=======
private Car[] carArray = {car1, car2, car3};
private Intersection[] intersectionArray = {intersection1, intersection2, intersection3};
private String[] tableColumnNames = {"Car", "X-Pos", "Y-Pos", "Speed km/h"};
//=========
//2D array
//=========
private Object[][] trafficData = {
{"Car 1", car1.getPosition(), 0, 0},
{"Car 2", car2.getPosition(), 0, 0},
{"Car 3", car3.getPosition(), 0, 0}
};
//============================
//JTable for all traffic data
//============================
private JTable dataTable = new JTable(trafficData, tableColumnNames);
//============================================
//displays GUI window to the user and passing
//it to class Thread. Also Giving the time
//its own thread
//============================================
public static void main(String args[]) {
TrafficMitigation gui = new TrafficMitigation();
gui.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
gui.setLocation(440, 100);
gui.setResizable(false);
gui.setSize(600, 700);
gui.setVisible(true);
thread = new Thread(gui);
Thread time = new Thread(new Time());
time.start();
}
//==================================
//initializes JFrame components and
//adds them to the GUI window
//==================================
public TrafficMitigation() {
super("Traffic Congestion Mitigation Company");
setLayout(new GridLayout(9, 1));
trafficLightLabel1 = new JLabel("Traffic Light 1 (1000)");
trafficLightLabel2 = new JLabel("Traffic Light 2 (2000)");
trafficLightLabel3 = new JLabel("Traffic Light 3 (3000)");
startButton = new JButton("Start");
pauseButton = new JButton("Pause");
stopButton = new JButton("Stop");
carsJComboBox = new JComboBox<>();
carsJComboBox.addItem(1);
carsJComboBox.addItem(2);
carsJComboBox.addItem(3);
carsJComboBox.addItem(4);
carsJComboBox.addItem(5);
intersectionJComboBox = new JComboBox<>();
intersectionJComboBox.addItem(1);
intersectionJComboBox.addItem(2);
intersectionJComboBox.addItem(3);
intersectionJComboBox.addItem(4);
intersectionJComboBox.addItem(5);
carBoxLabel = new JLabel("Number of Cars");
intersectionBoxLabel = new JLabel("Number of Intersections");
header1 = new JLabel("Welcome to the Traffic Congestion Mitigation Simulator", SwingConstants.CENTER);
header2 = new JLabel("\nClick the Start button to begin", SwingConstants.CENTER);
timeLabel = new JLabel("Current Time: ");
car1Slider = new JSlider(0, 3000);
car1Slider.setMajorTickSpacing(1000);
car1Slider.setPaintTicks(true);
car1Slider.setPaintLabels(true);
car2Slider = new JSlider(0, 3000);
car2Slider.setMajorTickSpacing(1000);
car2Slider.setPaintTicks(true);
car2Slider.setPaintLabels(true);
car3Slider = new JSlider(0, 3000);
car3Slider.setMajorTickSpacing(1000);
car3Slider.setPaintTicks(true);
car3Slider.setPaintLabels(true);
//=====================================
//JPanel's for headers, buttons, time,
//intersections, datatable
//=====================================
JPanel headerPanel = new JPanel();
headerPanel.setLayout(new GridLayout(2,1));
headerPanel.add(header1);
headerPanel.add(header2);
JPanel buttonPanel = new JPanel();
buttonPanel.add(startButton);
buttonPanel.add(pauseButton);
buttonPanel.add(stopButton);
JPanel timePanel = new JPanel();
timePanel.add(timeLabel);
timePanel.add(currentTime);
JPanel boxPanel = new JPanel();
boxPanel.add(carBoxLabel);
boxPanel.add(carsJComboBox);
boxPanel.add(intersectionBoxLabel);
boxPanel.add(intersectionJComboBox);
JPanel lightPanel = new JPanel();
lightPanel.add(trafficLightLabel1);
lightPanel.add(trafficLight1);
lightPanel.add(trafficLightLabel2);
lightPanel.add(trafficLight2);
lightPanel.add(trafficLightLabel3);
lightPanel.add(trafficLight3);
JScrollPane scrollPane = new JScrollPane(dataTable);
JPanel dataPanel = new JPanel();
dataPanel.add(scrollPane);
//================================
//add JPanels and JSliders to GUI
//================================
add(headerPanel);
add(timePanel);
add(boxPanel);
add(buttonPanel);
add(lightPanel);
add(car1Slider);
add(car2Slider);
add(car3Slider);
add(dataPanel);
//==============================================
//add ChangeListners and set Values to JSliders
//==============================================
car1Slider.addChangeListener(this);
car1Slider.setValue(car1.getPosition());
car2Slider.addChangeListener(this);
car2Slider.setValue(car2.getPosition());
car3Slider.addChangeListener(this);
car3Slider.setValue(car3.getPosition());
setButtons();
//=========================
//setting JTable Viewports
//=========================
dataTable.setPreferredScrollableViewportSize(new Dimension(400, 300));
dataTable.setFillsViewportHeight(true);
//===================
//run current thread
//===================
running = Thread.currentThread().isAlive();
}
//==================================
//handles all JButtons ActionEvents
//==================================
private void setButtons() {
//====================================
//handles "Start" buttton ActionEvent
//====================================
startButton.addActionListener((ActionEvent e) -> {
//=================================================================
//begin threads for cars and intersections when "Start" is clicked
//=================================================================
if(!simIsRunning.get()) {
System.out.println(Thread.currentThread().getName() + " calling start");
try {
intersection1.start();
intersection2.start();
intersection3.start();
car1.start();
car2.start();
car3.start();
thread.start(); /**Exception thrown here
*/
}
catch(IllegalThreadStateException itse) {
itse.printStackTrace();;
}
catch(NullPointerException npe) {
npe.printStackTrace();
}
}
simIsRunning.set(true);
});
//===================================
//handles "Pause" button ActionEvent
//===================================
pauseButton.addActionListener((ActionEvent e) -> {
if(simIsRunning.get()) {
//=====================================================
//loop through cars and intersections to call paused()
//=====================================================
for(Car i: carArray) {
i.paused();
System.out.println(Thread.currentThread().getName() + " calling pause");
}
//=======================================
//for loop to interrupt sleeping threads
//=======================================
for(Intersection i: intersectionArray) {
i.interrupt();
i.paused();
}
//=========================================
//-changes pause button text to "Continue"
//-sets simluation running to false
//=========================================
pauseButton.setText("Continue");
simIsRunning.set(false);
}
//=============================
//"Continue" button is clicked
//=============================
else {
//====================================
//for loop to resume threads for cars
//====================================
for(Car i:carArray) {
if(i.paused.get()) {
i.resume();
System.out.println(Thread.currentThread().getName() + " calling resume");
}
}
//=============================================
//for loop to resume threads for intersections
//=============================================
for(Intersection i: intersectionArray) {
i.resume();
}
//=========================================
//-changes continue button text to "Pause"
//-sets simluation running to true
//=========================================
pauseButton.setText("Pause");
simIsRunning.set(true);
}
});
//==================================
//handles "Stop" button ActionEvent
//==================================
stopButton.addActionListener((ActionEvent e) -> {
if(simIsRunning.get()) {
System.out.println(Thread.currentThread().getName() + " calling stop");
//=================================
//for loop to stop all car threads
//=================================
for(Car i: carArray) {
i.stop();
}
//==========================================
//for loop to stop all intersection threads
//==========================================
for(Intersection i: intersectionArray) {
i.stop();
}
simIsRunning.set(false);
}
});
}
//=========================================
//checks status of the intersection. Stops
//car threads for running the lights
//=========================================
private void getData() {
if(simIsRunning.get()) {
//======================================
//switch case for intersection 1 colors
//======================================
switch(intersection1.getColor()) {
case "Red":
//=====================================
//red light. Cars drive all the way up
//to 1st intersection and stop at 989
//=====================================
for(Car i: carArray) {
if(i.getPosition() > 989 && i.getPosition() < 1000) {
i.atStopLight.set(true);
}
}
break;
case "Green":
//==================================
//green light. Keep driving through
//==================================
for(Car i:carArray) {
if(i.atStopLight.get()) {
i.resume();
}
}
break;
}
//======================================
//switch case for intersection 2 colors
//======================================
switch(intersection2.getColor()) {
case "Red":
//=====================================
//red light. Cars drive all the way up
//to 2nd intersection and stop at 1989
//=====================================
for(Car i: carArray) {
if(i.getPosition() > 1989 && i.getPosition() < 2000) {
i.atStopLight.set(true);
}
}
break;
case "Green":
//==================================
//green light. Keep driving through
//==================================
for(Car i:carArray) {
if(i.atStopLight.get()) {
i.resume();
}
}
break;
}
//======================================
//switch case for intersection 3 colors
//======================================
switch(intersection3.getColor()) {
case "Red":
//=====================================
//red light. Cars drive all the way up
//to 2nd intersection and stop at 2989
//=====================================
for(Car i: carArray) {
if(i.getPosition() > 2989 && i.getPosition() < 3000) {
i.atStopLight.set(true);
}
}
break;
case "Green":
//===================================
//green light. Keep driving through.
//loops back to beginning of track
//===================================
for(Car i:carArray) {
if(i.atStopLight.get()) {
i.resume();
}
}
break;
}
}
}
//=============================================================
//adjusts JSlider values and car speeds as their states change
//=============================================================
@Override
public void stateChanged(ChangeEvent e) {
try {
trafficData[0][1] = car1Slider.getValue();
trafficData[1][1] = car2Slider.getValue();
trafficData[2][1] = car3Slider.getValue();
trafficData[0][3] = car1.getSpeed() + " km/h";
trafficData[1][3] = car2.getSpeed() + " km/h";
trafficData[2][3] = car3.getSpeed() + " km/h";
}
catch(NullPointerException npe) {
npe.printStackTrace();
}
dataTable.repaint();
}
//====================================
//constantly update JSliders position
//====================================
@Override
public void run() {
while(running) {
if(simIsRunning.get()) {
car1Slider.setValue(car1.getPosition());
car2Slider.setValue(car2.getPosition());
car3Slider.setValue(car3.getPosition());
getData();
}
}
}
}