import java.util.*;
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 i o n F r a m e
//Denne klasse sætter overordnet applet winduet op, samt står for at starte selve
//simulationen og vise de efterfølgende resultat,
public class CarSimulationFrame extends JApplet
{
//Følgende indlejrede klasse tager sig af at lytte på simulations knapper, og
//sætte simulationen igang. Herudover sørger den også for at vise resultaterne.
class SimulationButton extends JButton implements ActionListener
{
SimulationButton(String str) { super(str); addActionListener(this); }
public void actionPerformed(ActionEvent evt)
{
if(this.getText().equals("Start Calculation"))
{
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 );
int simulationTime = simulationResultPanel.getClock();
this.setText("Calculating please wait!");
simulationResultPanel.reset();
//Her sker det så endeligt.. Vis skal simulere nu! =>
SimulationData sd = carSimulation.newSimulationSession(meanArrival, diviasionArrival, payTime, nrOfQueues, simulationTime*60);
if(sd != null)
{
simulationResultPanel.setProcessedCars((int)sd.nrOfProcessedCars);
simulationResultPanel.setMeanWaitingTime((int)sd.meanWaitingTime);
simulationResultPanel.setMaximalWaitingTime((int)sd.maximalWaitingTime);
int spareTime= 0;
int waitingCars = 0;
int cars = 0;
for(int i = 0; i < sd.carQueues.length; i++)
{ queueOutput.append("Queue nr " + (i+1) + ": cars=" + sd.carQueues[i].getProcessedCars() +
" waiting=" + sd.carQueues[i].getWaitingCars() +
" spareTime=" + ClockConverter.sec2Time(sd.carQueues[i].getSpareTime()) + "\n");
cars += sd.carQueues[i].getProcessedCars();
waitingCars += sd.carQueues[i].getWaitingCars();
spareTime += sd.carQueues[i].getSpareTime();
}
queueOutput.append("Total: cars=" + cars + " waiting=" + waitingCars + " spareTime=" + ClockConverter.sec2Time(spareTime));
queueOutput.append("\n");
}
this.setText("Start Calculation");
}
}
}
private CarSimulation carSimulation = null;
SimulationResultPanel simulationResultPanel = new SimulationResultPanel();
SimulationControlePanel simulationControlePanel = new SimulationControlePanel();
SimulationButton simulationButton = new SimulationButton("Start Calculation");
JTextArea queueOutput = new JTextArea(8, 40);
JPanel[] panels = new JPanel[3];
Border etched = BorderFactory.createEtchedBorder();
Container pane = getContentPane();
GridLayout layout = new GridLayout(3, 1);
public void init()
{
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].setLayout(new BorderLayout());
JScrollPane sp = new JScrollPane(queueOutput);
panels[2].add(sp, BorderLayout.CENTER);
for(int i = 0; i < 3; i++)
pane.add(panels[i]);
carSimulation = new CarSimulation();
show();
}
public void start()
{
TitelPanel tp = (TitelPanel)panels[0];
tp.start();
}
}
//-----------------------------------------------------------------------------
//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 = "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 felter hvori brugeren kan sætte de betingelser som
//simulationen skal foregå under.! (antallet af køer, betalings tiden, gennemsnitlige ankomst
//og ankomst afvigelsen.
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 angiver resultaterne for selve simulationen, dvs gennemsnits vente tiden,
//den maximale ventetid osv. (Dog er der ikke inkluderet de enkelte boder)
//Herudover kan brugeren også indtaste simulationslængden i et felt.
class SimulationResultPanel extends JPanel
{
CombiLabel processedCarsLabel = new CombiLabel("Processed Cars:");
CombiLabel meanWaitingTimeLabel = new CombiLabel("Mean waitingtime:");
CombiLabel maximalWaitingTimeLabel = new CombiLabel("Maximal waitingtime:");
ValueLabel clockPanel = new ValueLabel("Simulation Time(min):", 5);
SimulationResultPanel()
{
setLayout(new GridLayout(4, 1));
setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), "Simulation result:"));
add(processedCarsLabel);
add(meanWaitingTimeLabel);
add(maximalWaitingTimeLabel);
clockPanel.setTextField("1");
add(clockPanel);
}
public void setProcessedCars(int nr)
{
processedCarsLabel.setDataLabel(nr);
}
public void setMeanWaitingTime(int time)
{
meanWaitingTimeLabel.setDataLabel(ClockConverter.sec2Time(time));
}
public void setMaximalWaitingTime(int time)
{
maximalWaitingTimeLabel.setDataLabel(ClockConverter.sec2Time(time));
}
public void setClock(int time) { clockPanel.setTextField(""+time); }
public int getClock()
{
String str = clockPanel.getTextField();
int value = -1;
try{ value = Integer.parseInt(str); }catch(Exception e) { return -1; }
return value;
}
public void reset()
{
processedCarsLabel.setDataLabel(0);
meanWaitingTimeLabel.setDataLabel(0);
maximalWaitingTimeLabel.setDataLabel(0);
}
}
//-----------------------------------------------------------------------------
//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); }
}
//-----------------------------------------------------------------------------
//C l o c k C o n v e r t e r
//Klassen kan lave et sekund antal om til en tilsvarende string opstillet tidsmæssigt
//som på et digitalt ur (dvs. timer:minutter:sekunder)
class ClockConverter
{
public static String sec2Time(long sec)
{
String time = "" + (int)(sec/3600);
sec -= ((int)(sec/3600)*3600);
time += ":";
if((int)(sec/60) < 10)
time +="0";
time += (""+ (int)(sec/60));
time += ":";
if(sec%60 < 10)
time += "0";
time += ("" + (int)(sec%60));
return time;
}
}
//-----------------------------------------------------------------------------