import java.applet.*;
import java.awt.*;
import java.awt.font.*;
import java.awt.geom.*;
import javax.swing.*;
import javax.swing.border.*;
import java.awt.event.*;
//-----------------------------------------------------------------------------
//C a r S i m u l a t o r F r a m e
//Klassen indeholder selve applet vinduet, som den sætter op, samt søger for
//at starte og stoppe simulationen.
public class CarSimulatorFrame extends JApplet
{
//Indlejret klasse til at håndtere simulations knappen.
class SimulationButton extends JButton implements ActionListener
{
SimulationButton(String str) { super(str); addActionListener(this); }
public void actionPerformed(ActionEvent evt)
{
if(this.getText().equals("Start Simulation"))
{
int nrOfQueues = simulationControlePanel.getField(SimulationControlePanel.NR_OF_QUEUES);
int payTime = simulationControlePanel.getField(SimulationControlePanel.PAY_TIME);
int meanArrival = simulationControlePanel.getField(SimulationControlePanel.MEAN_ARRIVAL);
int diviasionArrival = simulationControlePanel.getField(SimulationControlePanel.DIVIASION_ARRIVAL );
for(int i = 0; i < MAX_CARQUEUES; i++)
carQueuePanels[i].reset();
if(carSimulator.newSimulationSession(meanArrival, diviasionArrival, payTime, nrOfQueues))
{
simulationResultPanel.startClock();
simulationResultPanel.reset();
this.setText("Stop Simulation");
}
}
else
{
carSimulator.stopSimulation();
simulationResultPanel.stopClock();
this.setText("Start Simulation");
}
}
}
final int MAX_CARQUEUES = 5;
CarSimulator carSimulator = null;
CarQueuePanel[] carQueuePanels = new CarQueuePanel[MAX_CARQUEUES];
SimulationResultPanel simulationResultPanel = new SimulationResultPanel();
SimulationControlePanel simulationControlePanel = new SimulationControlePanel();
SimulationButton simulationButton = new SimulationButton("Start Simulation");
JPanel[] panels = new JPanel[3];
Border etched = BorderFactory.createEtchedBorder();
Container pane = getContentPane();
GridLayout layout = new GridLayout(3, 1);
public void init()
{
//setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//setTitle("Øresunds-bridge car simulation system v1.0");
//setSize(600, 420);
pane.setLayout(layout);
panels[0] = new TitelPanel();;
panels[0].setBorder(etched);
panels[1] = new JPanel();
panels[1].setBorder(etched);
panels[1].setLayout(new BorderLayout());
JPanel skod = new JPanel();
skod.setLayout(new GridLayout(1, 2));
skod.add(simulationResultPanel);
skod.add(simulationControlePanel);
panels[1].add(skod, BorderLayout.CENTER);
panels[1].add(simulationButton, BorderLayout.SOUTH);
panels[2] = new JPanel();
panels[2].setBorder(BorderFactory.createTitledBorder(etched, "Car queue information:"));
panels[2].setLayout(new GridLayout(1, 5));
for(int i = 0; i < MAX_CARQUEUES; i++)
{
carQueuePanels[i] = new CarQueuePanel(i+1);
carQueuePanels[i].setBorder(etched);
panels[2].add(carQueuePanels[i]);
}
for(int i = 0; i < 3; i++)
pane.add(panels[i]);
carSimulator = new CarSimulator(carQueuePanels, simulationResultPanel);
}
public void start() { ((TitelPanel)panels[0]).start(); }
public void stop()
{ carSimulator.stopSimulation();
simulationResultPanel.stopClock();
simulationButton.setText("Start Simulation");
}
}
//-----------------------------------------------------------------------------
//T i t e l P a n e l
//Denne klasse laver et panel hvorpå program overskriften bliver skrevet.
//Herudover scrolles navnet samt programmørens navn ind fra hver sin side, når
//man trykker på musen over panelet.
class TitelPanel extends JPanel implements Runnable
{
//Indlejret klase til at tage sig af museklikket (starter en scroller tråd)
class MouseStuff extends MouseAdapter
{
public void mousePressed(MouseEvent evt) { start(); }
}
Thread runner = null;
float x1 = 0;
float y1 = 30;
float x2 = 600;
float y2 = 60;
String message1 = "Realtime Bridge Simulation";
String message2 = "by Mads Lenskjær";
int strWidth1, strWidth2, strHeight1, strHeight2;
Font font1, font2;
boolean finishedScrolling = false;
TitelPanel()
{
super();
addMouseListener(new MouseStuff());
}
//Funktionen sætter grafikken op for overskriften, dvs måler størrelsen og bredten
//således at teksterne kan blive scrollet korrekt ind på midten. Herefter sparker
//den en tråd igang som gør flytte arbejdet.
public void start()
{
if(runner != null)
return;
runner = new Thread(this);
finishedScrolling = false;
Graphics2D g2D = null;
while((g2D = (Graphics2D)getGraphics()) == null) ;
font1 = new Font("arial", Font.PLAIN, 30);
g2D.setFont(font1);
FontRenderContext context = g2D.getFontRenderContext();
Rectangle2D bounds = font1.getStringBounds(message1, context);
strWidth1 = (int)bounds.getWidth();
strHeight1 = (int)bounds.getHeight();
y1 = strHeight1 + 20;
x1 = -strWidth1;
font2 = new Font("arial", Font.PLAIN+Font.ITALIC, 22);
g2D.setFont(font2);
context = g2D.getFontRenderContext();
bounds = font2.getStringBounds(message2, context);
strWidth2 = (int)bounds.getWidth();
strHeight2 = (int)bounds.getHeight();
y2 = y1+ strHeight2+20;
x2 = getWidth();
runner.start();
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2D = (Graphics2D)g;
g2D.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
g2D.setFont(font1);
if(finishedScrolling)
{ x1 = (int)((getWidth()/2)-(strWidth1/2));
x2 = (int)((getWidth()/2));
}
g2D.drawString(message1,x1,y1);
g2D.setFont(font2);
g2D.drawString(message2, x2,y2);
}
public void run()
{
boolean finished1 = false;
boolean finished2 = false;
int n = 0;
int midtPoint;
try
{ while(!finished1 && !runner.interrupted() || !finished2 && !runner.interrupted())
{
repaint();
midtPoint = (int)((getWidth()/2)-(strWidth1/2));
if(x1 < (int)(midtPoint))
x1 += (0.0006*(n*n));
else
finished1 = true;
midtPoint = (int)((getWidth()/2));
if(x2 > midtPoint)
x2 -= (0.0006*(n*n));
else
finished2 = true;
n++;
runner.sleep(1);
}
}catch(InterruptedException e) {}
finishedScrolling = true;
runner = null;
}
}
//-----------------------------------------------------------------------------
//S i m u l a t i o n C o n t r o l e P a n e l
//Klassen indeholder de kontrol parametre som simulationen udføres på baggrund af
class SimulationControlePanel extends JPanel
{
ValueLabel nrOfQueuesPanel = new ValueLabel("Open queues:", 5);
ValueLabel payTimePanel = new ValueLabel("Pay time (sec): ", 5);
ValueLabel meanArrivalTimePanel = new ValueLabel("Mean Arrival Time(sec): ", 5);
ValueLabel diviasionArrivalTimePanel = new ValueLabel("Diviation arrival Time(sec): ", 5);
static final int NR_OF_QUEUES = 0;
static final int PAY_TIME = 1;
static final int MEAN_ARRIVAL = 2;
static final int DIVIASION_ARRIVAL = 3;
SimulationControlePanel()
{
setLayout(new GridLayout(4, 1));
setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), "Simulation settings:"));
add(nrOfQueuesPanel);
add(payTimePanel);
add(meanArrivalTimePanel);
add(diviasionArrivalTimePanel);
nrOfQueuesPanel.setTextField("5");
payTimePanel.setTextField("20");
meanArrivalTimePanel.setTextField("4");
diviasionArrivalTimePanel.setTextField("2");
}
public int getField(int type)
{
String str = "";
int Value = -1;
try
{
switch(type)
{ case NR_OF_QUEUES: str = nrOfQueuesPanel.getTextField(); break;
case PAY_TIME: str = payTimePanel.getTextField(); break;
case MEAN_ARRIVAL: str = meanArrivalTimePanel.getTextField(); break;
case DIVIASION_ARRIVAL: str = diviasionArrivalTimePanel.getTextField(); break;
}
Value = Integer.parseInt(str);
}catch(Exception e) { return -1; }
return Value;
}
}
//-----------------------------------------------------------------------------
//S i m u l a t i o n R e s u l t P a n e l
//Klassen indeholder de vigtigste simulations resultater som løbende bliver opdateret
class SimulationResultPanel extends JPanel
{
CombiLabel processedCarsLabel = new CombiLabel("Processed Cars:");
CombiLabel meanWaitingTimeLabel = new CombiLabel("Mean waitingtime:");
CombiLabel maximalWaitingTimeLabel = new CombiLabel("Maximal waitingtime:");
ClockPanel clockPanel = new ClockPanel("Simulation Time:");
SimulationResultPanel()
{
setLayout(new GridLayout(4, 1));
setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), "Simulation result:"));
add(processedCarsLabel);
add(meanWaitingTimeLabel);
add(maximalWaitingTimeLabel);
add(clockPanel);
}
public void setProcessedCars(int nr) { processedCarsLabel.setDataLabel(nr); }
public void setMeanWaitingTime(int time)
{ meanWaitingTimeLabel.setDataLabel(ClockPanel.sec2Time(time));
}
public void setMaximalWaitingTime(int time)
{ maximalWaitingTimeLabel.setDataLabel(ClockPanel.sec2Time(time));
}
public void startClock() { clockPanel.startClock(); }
public void stopClock() { clockPanel.stopClock(); }
public void reset()
{ processedCarsLabel.setDataLabel(0);
meanWaitingTimeLabel.setDataLabel(0);
maximalWaitingTimeLabel.setDataLabel(0);
}
}
//-----------------------------------------------------------------------------
//C a r Q u e u e P a n e l
//Klassen sætter grafikken op tilhørende en bil kø. Der indeholder den felter
//angivende antallet af ventende biler, antallet af færdige biler, samt
//bodens resttide
class CarQueuePanel extends JPanel
{
JLabel queueLabel = new JLabel("", JLabel.CENTER);
CombiLabel nrOfCarsLabel = new CombiLabel("Waiting:");
CombiLabel nrOfMyProcessedCarsLabel = new CombiLabel("Finished:");
CombiLabel freeTimeLabel = new CombiLabel("Spare time:");
CarQueuePanel(int n)
{
Font font = new Font("arial", Font.PLAIN+Font.BOLD,12);
queueLabel.setFont(font);
queueLabel.setText("Queue nr " + n);
setLayout(new GridLayout(4, 1, 0,3));
add(queueLabel);
add(nrOfCarsLabel);
add(nrOfMyProcessedCarsLabel);
add(freeTimeLabel);
}
public void setWaitingCars(int nr) { nrOfCarsLabel.setDataLabel(nr); }
public void setFinishedCars(int nr) { nrOfMyProcessedCarsLabel.setDataLabel(nr); }
public void setFreeTime(int time) { freeTimeLabel.setDataLabel(ClockPanel.sec2Time(time)); }
public void reset()
{ nrOfCarsLabel.setDataLabel(0);
nrOfMyProcessedCarsLabel.setDataLabel(0);
freeTimeLabel.setDataLabel(0);
}
}
//-----------------------------------------------------------------------------
//C l o c k P a n e l
//Klassen indeholder 2 labels hvorpå det sidste kan angive klokken, som et
//digital ur (timer:min:sec). Herudover implementere klassen også en tråd
//der tæller uret op sekundtvis!
class ClockPanel extends JPanel implements Runnable
{
Thread runner = null;
long startTime = 0;
JLabel clockNameLabel = new JLabel("", SwingConstants.LEFT);
JLabel clockLabel = new JLabel("0", SwingConstants.RIGHT);
Font font = new Font("arial", Font.PLAIN,12);
ClockPanel(String str)
{
setLayout(new BorderLayout());
clockNameLabel.setFont(font);
clockLabel.setFont(font);
clockNameLabel.setText(str);
setBorder(BorderFactory.createEtchedBorder());
add(clockNameLabel,BorderLayout.WEST);
add(clockLabel,BorderLayout.EAST);
}
public static String sec2Time(int sec)
{
String time = (""+ (int)(sec/60));
time += ":";
if(sec%60 < 10)
time += "0";
time += ("" + (int)(sec%60));
return time;
}
public void startClock()
{ runner = new Thread(this);
startTime = System.currentTimeMillis();
runner.start();
}
public void stopClock()
{ runner.interrupt();
runner = null;
}
public void run()
{ try
{ while(!runner.interrupted())
{
Thread.sleep(1000);
clockLabel.setText(sec2Time((int)((System.currentTimeMillis() - startTime)/1000)));
}
}catch(InterruptedException e) {}
}
}
//-----------------------------------------------------------------------------
//V a l u e L a b e l
//Klassen laver et panel hvorpå der er et label(data overskrift) og et text felt hvori
//brugeren kan skrive indputs til programmet.!
class ValueLabel extends JPanel
{
JLabel textLabel = new JLabel("", SwingConstants.LEFT);
JTextField textField = null;
Font font = new Font("arial", Font.PLAIN,12);
ValueLabel(String text, int characters)
{
textField = new JTextField(characters);
setLayout(new BorderLayout());
textLabel.setFont(font);
textField.setFont(font);
textLabel.setText(text);
textField = new JTextField(characters);
add(textLabel, BorderLayout.WEST);
add(textField, BorderLayout.EAST);
setBorder(BorderFactory.createEtchedBorder());
}
public void setTextField(String value) { textField.setText(value); }
public String getTextField() { return textField.getText(); }
}
//-----------------------------------------------------------------------------
//C o m b i L a b e l
//Klassen laver et panel hvorpå der er 2 labels, hvor den første benyttes som overskrift
//og den anden som en slags data værdi felt til display for en variabel..
class CombiLabel extends JPanel
{
JLabel strLabel = new JLabel("", SwingConstants.LEFT);
JLabel dataLabel = new JLabel("0", SwingConstants.RIGHT);
Font font = new Font("arial", Font.PLAIN, 12);
CombiLabel(String str)
{
setLayout(new BorderLayout());
strLabel.setFont(font);
dataLabel.setFont(font);
strLabel.setText(str);
setBorder(BorderFactory.createEtchedBorder());
add(strLabel, BorderLayout.WEST);
add(dataLabel, BorderLayout.EAST);
}
public void setDataLabel(int data) { dataLabel.setText(""+data); }
public void setDataLabel(double data) { dataLabel.setText(""+data); }
public void setDataLabel(String data) { dataLabel.setText(data); }
}
//-----------------------------------------------------------------------------