Escolar Documentos
Profissional Documentos
Cultura Documentos
Americana, SP
2011
ii
Americana, SP
2011
III
BANCA EXAMINADORA
IV
AGRADECIMENTOS
Sinto-me grato a todas as pessoas que auxiliaram na realizao deste
trabalho, direta ou indiretamente.
minha orientadora, por todo seu apoio durante o curso e pelas
oportunidades a mim oferecidas. Sem a sua ajuda este trabalho no teria sido
possvel.
Aos meus colegas de sala, que tornaram a convivncia diria em ambiente
escolar muito agradvel e ajudaram a manter o nimo e motivao.
Em especial minha colega Mayara, que me acompanhou durante todo o
curso, e sem o apoio da qual no teria concludo o presente trabalho da forma que
apresentado.
Aos meus pais, pelo apoio ao estudo desde minha criao, o que possibilitou
que eu conclua este trabalho.
RESUMO
Sistemas de filas so bastante comuns no mbito comercial, e tm impacto
financeiro direto nas empresas. O presente trabalho descreve o desenvolvimento de
uma ferramenta completa e verstil para simulao de sistemas de filas em
linguagem de programao Java, detalhando cada passo no desenvolvimento e sua
base terica.
Palavras Chave: Teoria de filas, Simulao, Clculo numrico
VI
ABSTRACT
Queuing systems are quite common in commerce, having direct financial impact on
companies. This paper describes the development of a complete and versatile tool
for queuing systems simulation in the Java programming language, detailing each
step of the development and its theoretical basis.
Keywords: Queuing theory, Simulation, Numerical calculation
VII
SUMRIO
INTRODUO.................................................................................................. 11
1.1
1.2
1.3
SIMULAO ................................................................................................................. 13
1.4
1.5
CLCULO NUMRICO................................................................................................ 15
1.6
2.1
2.2
2.3
2.1.1
2.1.2
2.1.3
2.1.4
2.2.2
2.2.3
2.3.2
2.3.3
2.3.4
3.1
3.2
DISTRIBUIES ................................................................................. 57
VIII
3.2.2
3.3
SIMULAO ................................................................................................................. 65
3.3.1
ATUALIZAO ................................................................................... 66
3.3.2
MTODOS DA TELA........................................................................... 73
3.3.3
CONCLUSO ................................................................................................... 78
Figura 1:
Figura 2:
Figura 3:
Figura 4:
Figura 5:
Figura 6:
Figura 7:
Figura 8:
Figura 9:
Figura 10:
Figura 11:
Figura 12:
Figura 13:
Figura 14:
Figura 15:
10
11
INTRODUO
1.1
TRABALHOS ANTERIORES
A modelagem e simulao de sistemas um recurso bastante verstil e til no
12
1.2
TEORIA DE FILAS
Segundo a teoria de filas, um sistema de filas um sistema onde entradas
David George Kendall foi um estatstico britnico, nascido dia 15 de janeiro de 1918, especialista em
probabilidade e anlise de dados. Faleceu dia 23 de outubro de 2007.
13
SIMULAO
A simulao consiste em aplicar formalizaes em computadores, como
A LINGUAGEM JAVA
A linguagem de programao Java foi criada em 1991 por James Gosling.
Agner Krarup Erlang foi um matemtico dinamarqus, nascido dia 1 de Janeiro de 1878, pioneiro em
diversos estudos relacionados telefonia. Faleceu dia 3 de Fevereiro de 1929.
14
James Gosling. Como j existia uma linguagem de programao com este nome, a
linguagem foi rebatizada para Java.
O termo Java utilizado, geralmente, como referncia linguagem de
programao orientada a objetos, ao ambiente de desenvolvimento composto pelo
compilador, interpretador e gerador de documentao ou ao ambiente de execuo
que pode ser qualquer mquina que possua Java Runtime Environment (JRE)
instalado.
A linguagem de programao Java uma linguagem de alto-nvel com as
seguintes caractersticas:
15
1.5
CLCULO NUMRICO
O clculo numrico um ramo da matemtica que estuda mtodos
ESCOPO DO TRABALHO
O presente trabalho detalha o desenvolvimento de uma ferramenta para
16
17
Figura 1:
18
2.1
Figura 2:
19
Figura 3:
20
O cdigo gerado pelo NetBeans ao montar a tela deve ser suficiente para que
a tela seja desenhada como na Figura 3, porm isso no ser o bastante para que a
interface com o usurio seja funcional.
A tabela criada ser usada pelo usurio para inserir dados na forma de
medio cronometrada, e ter o seguinte comportamento dinmico: assim que a
ltima linha da tabela estiver completa, uma nova linha criada para permitir que o
usurio insira mais registros; se algum valor de uma linha anterior ltima for
apagado, a linha em questo removida da tabela; a formatao das clulas deve
ser validada de acordo com seus padres; as linhas devem ser posicionadas
automaticamente para que fiquem ordenadas pelo horrio inicial.
Para a validao da tabela ser criado um mtodo no modo de visualizao
de cdigo. Este mtodo retornar true caso os dados na tabela sejam vlidos ou
false caso haja algum dado invlido. Segue o cdigo de tal mtodo:
private boolean validaTabelaMedicaoCronometrada() {
String horarioInicial =
(String)tblMedicaoCronometrada.getValueAt(tblMedicaoCronometrada.getRowCount() - 1, 0);
Double duracao =
(Double)tblMedicaoCronometrada.getValueAt(tblMedicaoCronometrada.getRowCount() - 1, 1);
Long numClientes =
(Long)tblMedicaoCronometrada.getValueAt(tblMedicaoCronometrada.getRowCount() - 1, 2);
if ((horarioInicial != null) &&
(duracao != null) &&
(numClientes != null)) {
((DefaultTableModel)tblMedicaoCronometrada.getModel()).addRow(new Object[]{null, null,
null});
}
for (int linha = 0; linha < tblMedicaoCronometrada.getRowCount() - 1; linha++) {
horarioInicial = (String)tblMedicaoCronometrada.getValueAt(linha, 0);
duracao = (Double)tblMedicaoCronometrada.getValueAt(linha, 1);
numClientes = (Long)tblMedicaoCronometrada.getValueAt(linha, 2);
if ((horarioInicial == null) ||
(duracao == null) ||
(numClientes == null)) {
((DefaultTableModel)tblMedicaoCronometrada.getModel()).removeRow(linha);
linha--;
} else {
if ((!tblMedicaoCronometrada.isEditing()) ||
(!tblMedicaoCronometrada.isColumnSelected(0)) ||
(!tblMedicaoCronometrada.isRowSelected(linha))) {
try {
String horarioInicialAux[] = horarioInicial.split(":");
Long.parseLong(horarioInicialAux[0]);
Double.parseDouble(horarioInicialAux[1].replace(",", "."));
} catch (Exception e) {
return false;
}
}
}
}
return true;
}
21
22
os limites superior e inferior do novo painel para que o mesmo fique na mesma
posio que o painel anterior, e tambm apagar os dois componentes internos, que
tambm foram copiados (a tabela e o painel da medio cronometrada).
A seguir, basta clicar com o boto direito do mouse no painel recm-criado
(usando o Inspetor do NetBeans, novamente) e usar a opo Desenhar este
recipiente, para facilitar sua edio.
Ser adicionado um componente de tabela, que ser a tabela de frequncia.
Esta tabela ter as colunas Nmero de clientes e Frequncia, como observado na
Figura 4.
Figura 4:
23
Para que o cdigo do evento seja inserido, basta clicar com o boto direito do
mouse
na
tabela
com
boto
esquerdo
do
mouse
em
Eventos,
24
Figura 5:
25
26
Figura 6:
27
28
2.2
usurio para a aba responsvel pela taxa de sada de clientes do sistema. Nesta aba
o usurio ir inserir dados referentes ao tempo de atendimento do sistema simulado,
o que implica na taxa de sada de clientes do sistema quando h demanda.
Para a taxa de sada de clientes do sistema no faria sentido se a taxa
variasse com o tempo, afinal pr-supe-se que o atendimento realizado o mesmo
independente do horrio. Portanto, no haver a medio cronometrada.
Deve-se, ento, copiar o painel de entrada e col-lo dentro do painel tabulado.
O Inspetor, novamente, facilitar esta tarefa. Isto criar outra aba. Para voltar a editar
o painel principal da ferramenta, ser necessrio clicar no mesmo com o boto
direito e escolher Desenhar este recipiente. O texto da nova aba dever ser
alterado para Sada, clicando na mesma e pressionando F2. O painel de medio
cronometrada deste novo painel de sada dever ser removido, bem como a opo
correspondente na caixa de combinao que controlar a forma de insero de
dados, ficando a aparncia da tela como na Figura 7.
29
Figura 7:
30
Figura 8:
O
campo
durao
dos
intervalos
ser
um
objeto
da
classe
Na tabela ser preciso validar todos os nmeros inseridos para que no sejam
negativos, da mesma forma que foi feito para a tabela de frequncia da taxa de
entrada de clientes no sistema. De forma anloga, ser criado um mtodo
responsvel pela validao dos dados, detalhado a seguir.
31
Note
que
objeto
da
tabela
de
frequncia
foi
nomeado
32
Figura 9:
33
O campo que guardar o valor fixo da taxa de sada de clientes do sistema foi
nomeado nmrValorFixoSaida.
2.2.3 AJUSTES FINAIS
Assim como na aba relacionada taxa de entrada de clientes no sistema, ser
preciso configurar o comportamento da caixa de combinao responsvel pela
escolha da forma de insero dos dados relacionados taxa de sada de clientes do
sistema, exibindo apenas os componentes relacionados forma selecionada.
Para isto ser usado o evento ActionPerformed novamente, e sero feitos os
filtros como est detalhado no cdigo a seguir.
private void cmbSaidaActionPerformed(java.awt.event.ActionEvent evt) {
final int TABELA_DE_FREQUENCIA = 0;
final int VALOR_FIXO = 1;
switch (cmbSaida.getSelectedIndex()) {
case TABELA_DE_FREQUENCIA:
pnlTabelaFrequenciaSaida.setVisible(true);
txtDuracaoIntervaloSaida.setVisible(true);
nmrDuracaoIntervaloSaida.setVisible(true);
pnlValorFixoSaida.setVisible(false);
break;
case VALOR_FIXO:
pnlValorFixoSaida.setVisible(true);
pnlTabelaFrequenciaSaida.setVisible(false);
txtDuracaoIntervaloSaida.setVisible(false);
nmrDuracaoIntervaloSaida.setVisible(false);
break;
}
}
34
combo. O construtor da tela dever ser alterado novamente, para que o mesmo
tambm chame o evento actionPerformed do combo de sada.
O construtor ficar, ento, como no cdigo a seguir.
public SimulacaoView(SingleFrameApplication app) {
super(app);
initComponents();
cmbEntradaActionPerformed(null);
cmbSaidaActionPerformed(null);
}
2.3
ABA DE SIMULAO
A ltima aba do sistema ser a aba que conter a representao visual da
simulao e suas variveis, bem como campos para configurar parmetros relativos
simulao.
Primeiramente ser criado um novo painel dentro do painel tabulado, para ser
a terceira e ltima aba do sistema, e seu texto ser mudado para Simulao. Para
facilitar esta tarefa ser usado o Inspetor, clicando com o boto direito do mouse
no painel tabulado, escolhendo Adicionar da paleta, Contineres Swing e Painel,
nesta ordem. Para alterar o texto basta clicar na aba e pressionar F2.
Dentro do novo painel campos devero ser adicionados para que o usurio
possa configurar os parmetros referentes simulao. O usurio poder determinar
o nmero de servidores, o nmero de filas, os horrios inicial e final e a velocidade
da simulao nesta aba. Tais campos (com exceo do horrio inicial da simulao)
podero ser alterados durante a simulao em tempo real.
Alm dos parmetros da simulao, nesta aba tambm ficaro a
representao visual da simulao, todas as informaes relevantes e dois grficos
que auxiliaro no entendimento.
2.3.1 PARMETROS DA SIMULAO
Para o parmetro referente ao nmero de servidores na simulao ser
adicionado um objeto da classe JSpinner, com seu modelo devidamente
35
configurado para permitir valor numrico inteiro, com valor inicial e mnimo 1. Para
fazer isto basta selecionar o campo e clicar em SpinnerModel frente de model
no painel de propriedades do NetBeans, que pode ser aberto pelo menu Janela, no
item Propriedades.
Para a escolha do nmero de filas sero adicionados dois botes de opo: o
primeiro representar apenas uma fila para todos os servidores e o segundo
representar uma fila para cada servidor. Como inicialmente o sistema estar
configurado para apenas um servidor, no faria sentido manter a segunda opo
ativa, portanto a mesma ser deixada inativa. Para fazer isto basta selecionar a
opo e desmarcar a caixa ao lado de enabled no painel de propriedades do
NetBeans.
Para a insero dos horrios inicial e final, sero adicionados dois objetos da
classe JTextField.
Finalmente, para a velocidade da simulao, ser usado um objeto da classe
JSlider, configurado para permitir valores entre 1 e 1000, e com valor inicial 871.
Tais configuraes podem ser feitas no painel de propriedades do NetBeans,
alterando
os
valores
das
propriedades minimum,
maximum e
value,
36
Figura 10:
Feito isto a aparncia dos parmetros da simulao deve estar concluda, mas
ainda ser preciso fazer algumas validaes para concluir os requisitos da interface
com o usurio.
Assim que o usurio alterar o nmero de servidores da simulao, a segunda
opo do nmero de filas dever ser ativada ou desativada, assim como seu texto
dever ser corrigido. Isto ser feito no evento stateChanged do campo de nmero
de servidores. Para se inserir cdigo no evento basta clicar com o boto direito no
campo e escolher Eventos, Change e stateChanged. O cdigo a seguir deve ser
suficiente.
private void numeroServidoresStateChanged(javax.swing.event.ChangeEvent evt) {
multiplasFilas.setText(numeroServidores.getValue().toString());
if (Integer.parseInt(numeroServidores.getValue().toString()) == 1) {
unicaFila.setSelected(true);
multiplasFilas.setEnabled(false);
} else {
multiplasFilas.setEnabled(true);
}
}
37
Nota-se que o mtodo responsvel por devolver o foco ao campo tem de ser
chamado de forma diferente. Isso necessrio pois enquanto o evento de perda de
foco no for concludo o foco continuar no campo, resultando que, ao clicar na
mensagem de erro, o evento de perda de foco invocado novamente. Se o retorno
do foco for registrado para depois do fim da execuo do evento este impasse
evitado.
38
39
40
41
import java.awt.Image;
import javax.swing.JPanel;
public class PainelGrafico extends JPanel {
public
public
public
public
public
public
public
public
Image
Image
Image
Image
int
int
int
double
imagemCliente;
imagemClienteRedimensionada;
imagemServidor;
imagemServidorRedimensionada;
numeroClientesFila[];
tamanhoMaiorFila;
numeroServidores;
alturaAnterior;
public PainelGrafico() {
imagemCliente = null;
imagemClienteRedimensionada = null;
imagemServidor = null;
imagemServidorRedimensionada = null;
numeroClientesFila = null;
tamanhoMaiorFila = 0;
numeroServidores = 0;
alturaAnterior = 0;
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if ((imagemCliente != null) && (imagemServidor != null)) {
double aspectoCliente = (double)(imagemCliente.getWidth(this)) /
imagemCliente.getHeight(this);
double aspectoServidor = (double)(imagemServidor.getWidth(this)) /
imagemServidor.getHeight(this);
double alturaMaxima = ((this.getHeight() - 80) / numeroServidores) * 0.95;
double larguraServidorPorClientes = 2 * aspectoServidor / aspectoCliente;
double numeroClientesHorizontal = 1.05 * tamanhoMaiorFila +
larguraServidorPorClientes + 0.05;
double larguraMaximaCliente = (this.getWidth() - 40) / numeroClientesHorizontal;
double larguraMaximaServidor = larguraMaximaCliente * larguraServidorPorClientes;
double alturaServidor = larguraMaximaServidor / aspectoServidor;
double larguraServidor;
if (alturaServidor <= alturaMaxima) {
larguraServidor = larguraMaximaServidor;
} else {
alturaServidor = alturaMaxima;
larguraServidor = alturaServidor * aspectoServidor;
}
double alturaCliente = alturaServidor / 2;
double larguraCliente = alturaCliente * aspectoCliente;
if (alturaServidor < 1) {
alturaServidor = 1;
}
if (larguraServidor < 1) {
larguraServidor = 1;
}
if (alturaCliente < 1) {
alturaCliente = 1;
}
if (larguraCliente < 1) {
larguraCliente = 1;
}
if (alturaServidor != alturaAnterior) {
alturaAnterior = alturaServidor;
imagemClienteRedimensionada = imagemCliente.getScaledInstance((int)
larguraCliente, (int) alturaCliente, Image.SCALE_SMOOTH);
imagemServidorRedimensionada = imagemServidor.getScaledInstance((int)
larguraServidor, (int) alturaServidor, Image.SCALE_SMOOTH);
}
Graphics2D g2D = (Graphics2D) g;
int margemDireita = this.getWidth() - 20 - (int) larguraServidor;
for (int i = 0; i < numeroServidores; i++) {
g2D.drawImage(imagemServidorRedimensionada, margemDireita, (int)(20 + i *
(alturaServidor * 1.05)), this);
}
for (int i = 0; i < numeroClientesFila.length; i++) {
for (int j = 0; j < numeroClientesFila[i]; j++) {
42
Figura 11:
43
Figura 12:
44
imagem escolhida. Estes campos devero ser adicionados para cliente e servidor,
portanto sero duas cpias de cada.
Feito isto a aparncia da tela ficar como mostrada na Figura 13.
Figura 13:
45
suportadas: GIF, JPG, PNG e TIF. Estes arquivos sero includos em um pacote
novo, chamado imagens.
O cdigo a seguir, levemente modificado de um exemplo chamado
FileChooserDemo2 (ORACLE), disponibilizado pela Oracle3 em seu site oficial, ser
suficiente para cumprir os requisitos do novo arquivo, que ser chamado
Imagem.java.
/*
* Copyright (c) 1995, 2008, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle or the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
import
import
import
import
import
import
import
import
import
import
import
import
import
java.awt.Component;
java.awt.Dimension;
java.awt.Graphics;
java.awt.Image;
java.beans.PropertyChangeEvent;
java.beans.PropertyChangeListener;
java.io.File;
javax.swing.Icon;
javax.swing.ImageIcon;
javax.swing.JComponent;
javax.swing.JFileChooser;
javax.swing.filechooser.FileFilter;
javax.swing.filechooser.FileView;
Oracle Corporation uma empresa multinacional de tecnologia e informtica dos Estados Unidos,
especializada no desenvolvimento e comercializao de hardware e software.
46
return null;
}
}
}
class ImagemFilter extends FileFilter {
@Override
public boolean accept(File f) {
if (f.isDirectory()) {
return true;
}
String extension = Utils.getExtension(f);
if (extension != null) {
if (extension.equals(Utils.tiff) ||
extension.equals(Utils.tif) ||
extension.equals(Utils.gif) ||
extension.equals(Utils.jpeg) ||
extension.equals(Utils.jpg) ||
extension.equals(Utils.png)) {
return true;
} else {
return false;
}
}
return false;
}
@Override
public String getDescription() {
return "Apenas imagens";
}
}
class ImagemFileView extends FileView {
ImageIcon jpgIcon = Utils.createImageIcon("JPG.png");
ImageIcon gifIcon = Utils.createImageIcon("GIF.png");
ImageIcon tiffIcon = Utils.createImageIcon("TIF.png");
ImageIcon pngIcon = Utils.createImageIcon("PNG.png");
@Override
public String getName(File f) {
return null;
}
@Override
public String getDescription(File f) {
return null;
}
@Override
public Boolean isTraversable(File f) {
return null;
}
@Override
public String getTypeDescription(File f) {
String extension = Utils.getExtension(f);
String type = null;
if (extension != null) {
if (extension.equals(Utils.jpeg) ||
extension.equals(Utils.jpg)) {
type = "Imagem JPEG";
} else if (extension.equals(Utils.gif)){
type = "Imagem GIF";
} else if (extension.equals(Utils.tiff) ||
extension.equals(Utils.tif)) {
type = "Imagem TIFF";
} else if (extension.equals(Utils.png)){
type = "Imagem PNG";
}
}
return type;
}
47
@Override
public Icon getIcon(File f) {
String extension = Utils.getExtension(f);
Icon icon = null;
if (extension != null) {
if (extension.equals(Utils.jpeg) ||
extension.equals(Utils.jpg)) {
icon = jpgIcon;
} else if (extension.equals(Utils.gif))
icon = gifIcon;
} else if (extension.equals(Utils.tiff)
extension.equals(Utils.tif))
icon = tiffIcon;
} else if (extension.equals(Utils.png))
icon = pngIcon;
}
}
return icon;
{
||
{
{
}
}
class ImagemPreview extends JComponent
implements PropertyChangeListener {
ImageIcon thumbnail = null;
File file = null;
public ImagemPreview(JFileChooser fc) {
setPreferredSize(new Dimension(100, 50));
fc.addPropertyChangeListener(this);
}
public void loadImage() {
if (file == null) {
thumbnail = null;
return;
}
ImageIcon tmpIcon = new ImageIcon(file.getPath());
if (tmpIcon != null) {
if (tmpIcon.getIconWidth() > 90) {
thumbnail = new ImageIcon(tmpIcon.getImage().
getScaledInstance(90, -1,
Image.SCALE_DEFAULT));
} else {
thumbnail = tmpIcon;
}
}
}
@Override
public void propertyChange(PropertyChangeEvent e) {
boolean update = false;
String prop = e.getPropertyName();
if (JFileChooser.DIRECTORY_CHANGED_PROPERTY.equals(prop)) {
file = null;
update = true;
} else if (JFileChooser.SELECTED_FILE_CHANGED_PROPERTY.equals(prop)) {
file = (File) e.getNewValue();
update = true;
}
if (update) {
thumbnail = null;
if (isShowing()) {
loadImage();
repaint();
}
}
}
@Override
protected void paintComponent(Graphics g) {
if (thumbnail == null) {
48
loadImage();
}
if (thumbnail != null) {
int x = getWidth()/2 - thumbnail.getIconWidth()/2;
int y = getHeight()/2 - thumbnail.getIconHeight()/2;
if (y < 0) {
y = 0;
}
if (x < 5) {
x = 5;
}
thumbnail.paintIcon(this, g, x, y);
}
}
}
class Utils {
public final
public final
public final
public final
public final
public final
static
static
static
static
static
static
String
String
String
String
String
String
jpeg = "jpeg";
jpg = "jpg";
gif = "gif";
tiff = "tiff";
tif = "tif";
png = "png";
49
edtImagemClientes,
botImagemClientes
imgImagemClientes,
50
}
}
}
51
Figura 14:
52
Figura 15:
53
Os
referidos
objetos
foram
txtTextoClientesSistema,
nomeados
txtNumeroClientesSistema,
txtNumeroClientesAtendidos
txtTextoClientesAtendidos.
3
DESENVOLVENDO AS FUNCIONALIDADES
Agora que a interface com o usurio est pronta resta apenas implementar as
uma das formas a medio cronometrada. Nesta forma o usurio insere todas as
medies realizadas, e a ferramenta deve gerar uma curva para a taxa de entrada
que melhor represente estes dados.
Para melhor compreender a gerao desta curva alguns pontos devem ser
esclarecidos. Os dados inseridos informaro o nmero de clientes que chegaram em
intervalos determinados. A curva que ser gerada, entretanto, da taxa de chegada,
que a uma funo contnua derivada do nmero de clientes no sistema.
A tarefa atual , ento, gerar uma curva cuja integral definida em cada
intervalo inserido seja to prxima quanto possvel do valor inserido pelo usurio.
Para isso ser usada uma biblioteca especfica para clculos cientficos
chamada JScience (JScience), em sua verso experimental (EDU-DEVELOPER).
Uma de suas classes, chamada DoubleCubicSplineInterpolator, implementa
interpolao de pontos em um plano, o que facilitar nossa tarefa de criar a curva.
O objeto da curva dever ser guardado, para que seja possvel utiliz-lo
futuramente na prpria simulao. Criar-se-, ento, um atributo na classe da tela
para guard-la, e se alterar o construtor para que o mesmo seja inicializado. O
cdigo a seguir demonstra como o incio do cdigo da classe ficar aps as
modificaes.
54
Sir Isaac Newton, nascido em 4 de janeiro de 1643, foi um cientista ingls. Ganhou renome por suas
contribuies fsica e matemtica, porm tambm estudou astronomia, alquimia, filosofia natural e
teologia. Faleceu em 31 de maro de 1727.
5
Roger Cotes, nascido em 10 de julho de 1682, foi um matemtico ingls conhecido por realizar
trabalhos em parceria com Isaac Newton. Faleceu em 5 de junho de 1716.
55
Por fim, para apresentar a curva para o usurio, ser gerado um grfico de
linha a partir do objeto da curva. Uma biblioteca Java chamada JFreeChart
(JFreeChart), especfica para esta tarefa, ser usada, e em seguida o grfico ser
adicionado ao painel reservado para o mesmo.
O cdigo criado anteriormente para o evento propertyChange da tabela de
medio de frequncia ser, ento, alterado para adicionar as funcionalidades
desejadas. O cdigo a seguir demonstra como o novo cdigo do evento ficar
contemplando todas estas funcionalidades.
private void tblMedicaoCronometradaPropertyChange(java.beans.PropertyChangeEvent evt) {
if (validaTabelaMedicaoCronometrada()) {
if (tblMedicaoCronometrada.getRowCount() > 1) {
for (int linha1 = 0; linha1 < tblMedicaoCronometrada.getRowCount() - 1; linha1++)
{
for (int linha2 = linha1 + 1; linha2 < tblMedicaoCronometrada.getRowCount() 1; linha2++) {
String aux[] = ((String)tblMedicaoCronometrada.getValueAt(linha1,
0)).split(":");
double valor1 = Long.parseLong(aux[0]) * 60 +
Double.parseDouble(aux[1].replace(",", "."));
aux = ((String)tblMedicaoCronometrada.getValueAt(linha2, 0)).split(":");
double valor2 = Long.parseLong(aux[0]) * 60 +
Double.parseDouble(aux[1].replace(",", "."));
if (valor2 < valor1) {
((DefaultTableModel)tblMedicaoCronometrada.getModel()).moveRow(linha1,
linha1, linha2);
}
}
}
56
57
clientes entraro e sairo do sistema. Para isso sero utilizados os dados das taxas
de entrada e sada. Para facilitar esta tarefa algumas funcionalidades devem ser
adicionadas ao cdigo.
3.2.1 DISTRIBUIES
Ao se utilizar tabelas de frequncia, entretanto, vrios valores so inseridos, e
um nico valor deve ser utilizado.
Na etapa de desenvolvimento da interface com o usurio foram adicionadas
caixas de combinao para permitir ao usurio a escolha da distribuio matemtica
utilizada ao interpretar os dados inseridos nas tabelas de frequncia.
O valor utilizado, quando baseado em uma tabela de frequncia, ser gerado
de forma aleatria, mas seguindo uma distribuio que regule as probabilidades para
que os valores sorteados representem com maior fidelidade os dados inseridos.
Ser permitido ao usurio a escolha entre as opes Observada e Poisson6.
Na distribuio observada, o valor a ser utilizado como taxa ser um dos
valores presentes na tabela, obtido atravs de um sorteio, porm com maior
58
Simon Denis Poisson, nascido em 21 de junho de 1781, foi um matemtico e fsico francs. Criador
da distribuio de Poisson, Faleceu em 25 de abril de 1840.
59
60
61
62
63
insero
de
dados,
portanto
tambm
sero
alterados
os
eventos
64
65
cont = 0;
while (cont < sort) {
cont += (Long) tblTabelaFrequenciaEntrada.getValueAt(j, 1);
j++;
}
return (Long) tblTabelaFrequenciaEntrada.getValueAt(j - 1, 0) /
Double.parseDouble(nmrDuracaoIntervaloEntrada.getText());
default:
return numeroSorteadoPoisson(numeroEsperadoEntrada) /
Double.parseDouble(nmrDuracaoIntervaloEntrada.getText());
}
default:
if (cmbDistribuicaoEntrada.getSelectedIndex() == DISTRIBUICAO_OBSERVADA) {
return Double.parseDouble(nmrValorFixoEntrada.getText());
} else {
return (double)
numeroSorteadoPoisson(Double.parseDouble(nmrValorFixoEntrada.getText()));
}
}
}
// [...]
public double pegarTaxaSaida() {
final int TABELA_FREQUENCIA = 0;
final int DISTRIBUICAO_OBSERVADA = 0;
switch (cmbSaida.getSelectedIndex()) {
case TABELA_FREQUENCIA:
switch (cmbDistribuicaoSaida.getSelectedIndex()) {
case DISTRIBUICAO_OBSERVADA:
int cont = 0;
for (int j = 0; j < tblTabelaFrequenciaSaida.getRowCount() - 1; j++) {
cont += (Long) tblTabelaFrequenciaSaida.getValueAt(j, 1);
}
long sort = Math.round(Math.random() * (cont + 1)) + 1;
int j = 0;
cont = 0;
while (cont < sort) {
cont += (Long) tblTabelaFrequenciaSaida.getValueAt(j, 1);
j++;
}
return (Long) tblTabelaFrequenciaSaida.getValueAt(j - 1, 0) /
Double.parseDouble(nmrDuracaoIntervaloSaida.getText());
default:
return numeroSorteadoPoisson(numeroEsperadoSaida) /
Double.parseDouble(nmrDuracaoIntervaloSaida.getText());
}
default:
if (cmbDistribuicaoSaida.getSelectedIndex() == DISTRIBUICAO_OBSERVADA) {
return Double.parseDouble(nmrValorFixoSaida.getText());
} else {
return (double)
numeroSorteadoPoisson(Double.parseDouble(nmrValorFixoSaida.getText()));
}
}
}
3.3
SIMULAO
Por fim, ser feita a codificao do que acontece aps o usurio apertar o
boto Simular.
66
3.3.1 ATUALIZAO
A simulao acontecer em tempo real, portanto dever ser atualizada
constantemente para que seja fluda, e o andamento da simulao dever ser
relativo ao tempo passado. A taxa de atualizao escolhida foi 60 atualizaes por
segundo.
As atualizaes estaro executando constantemente, portanto iro travar a
interface com o usurio se rodarem na mesma linha de execuo. As atualizaes
sero feitas, ento, em uma Thread, para que sejam executadas em uma linha de
execuo nova.
Para isso ser criada uma nova classe que herdar da classe Thread do
Java. Esta classe ter um mtodo chamado run, que ser executado em uma nova
linha de execuo quando o mtodo start da classe pai for chamado.
A nova classe dever conter atributos para armazenar referncias aos objetos
da tela e do painel grfico, pois ter contato direto com ambos. Tambm so
necessrios atributos para armazenar o tempo atual e final da simulao, o tempo
real restante, um valor booleano indicando se a simulao est pausada, a
velocidade da simulao, um vetor armazenando a ordem das filas, um vetor
armazenando listas com os tempos de entrada de todos os clientes no sistema, um
vetor armazenando o tempo em que os clientes entraram para ser atendidos em
cada fila, um valor booleano que indica se existe apenas uma fila, um vetor com
valores auxiliares de sada, que armazenar a taxa de sada que sobrou aps os
clientes do passo atual terem sado do sistema (utilizado no prximo passo), um
contador indicando quanto tempo j passou desde o incio da simulao e um valor
booleano que indica se as informaes da simulao esto sendo atualizadas.
Tambm sero necessrios atributos para armazenar as informaes
relevantes cujos valores sero inseridos nos campos da tela. Tais atributos devero
ser pblicos, pois sero acessados por um mtodo da classe da tela.
No mtodo run ser criado um lao de repetio que continuar at que a
simulao termine. Dentro deste lao sero controladas as atualizaes, limitando a
67
java.util.ArrayList;
java.util.List;
java.util.logging.Level;
java.util.logging.Logger;
68
double
double
double
double
double
boolean
boolean
mediaVarianciaClientesFilas;
mediaTempoSistema;
mediaVarianciaTempoSistema;
mediaTempoFila;
mediaVarianciaTempoFila;
estabilidadeMomentanea;
estabilidadeMedia;
69
} else {
painel.numeroClientesFila[ordemFilas[0]]++;
tempoEntrada[ordemFilas[0]].add(tempoAtualSimulacao);
}
auxiliarEntrada--;
numeroClientesEntrando++;
}
double miMedio = 0;
int numeroClientesSaindo = 0;
double tempoMedioSistema = 0;
double tempoMedioFila = 0;
for (int i = 0; i < painel.numeroServidores; i++) {
double mi = janela.pegarTaxaSaida();
miMedio += mi;
auxiliarSaida[i] += mi * tempoRealPassado * velocidade;
double auxTempoMedio = 0;
if (filaUnica) {
if (painel.numeroClientesFila[0] < (int) auxiliarSaida[i]) {
while (!tempoEntrada[0].isEmpty()) {
auxTempoMedio += tempoAtualSimulacao - tempoEntrada[0].get(0);
tempoEntrada[0].remove(0);
}
tempoMedioSistema += auxTempoMedio;
numeroClientesSaindo += painel.numeroClientesFila[0];
painel.numeroClientesFila[0] = 0;
} else {
for (int j = 0; j < (int) auxiliarSaida[i]; j++) {
auxTempoMedio += tempoAtualSimulacao - tempoEntrada[0].get(0);
tempoEntrada[0].remove(0);
}
tempoMedioSistema += auxTempoMedio;
numeroClientesSaindo += (int) auxiliarSaida[i];
painel.numeroClientesFila[0] -= (int) auxiliarSaida[i];
}
tempoMedioFila += auxTempoMedio - (tempoAtualSimulacao tempoAtendimento[0]);
tempoAtendimento[0] = tempoAtualSimulacao;
} else {
if (painel.numeroClientesFila[i] < (int) auxiliarSaida[i]) {
while (!tempoEntrada[i].isEmpty()) {
auxTempoMedio += tempoAtualSimulacao - tempoEntrada[i].get(0);
tempoEntrada[i].remove(0);
}
tempoMedioSistema += auxTempoMedio;
numeroClientesSaindo += painel.numeroClientesFila[i];
painel.numeroClientesFila[i] = 0;
} else {
for (int j = 0; j < (int) auxiliarSaida[i]; j++) {
auxTempoMedio += tempoAtualSimulacao - tempoEntrada[i].get(0);
tempoEntrada[i].remove(0);
}
tempoMedioSistema += auxTempoMedio;
numeroClientesSaindo += (int) auxiliarSaida[i];
painel.numeroClientesFila[i] -= (int) auxiliarSaida[i];
}
tempoMedioFila += auxTempoMedio - (tempoAtualSimulacao tempoAtendimento[i]);
tempoAtendimento[i] = tempoAtualSimulacao;
int j = 0;
while ((j < ordemFilas.length - 1) && (ordemFilas[j] != i)) {
j++;
}
while ((j < ordemFilas.length - 1) &&
(painel.numeroClientesFila[ordemFilas[j + 1]] < painel.numeroClientesFila[i])) {
ordemFilas[j] = ordemFilas[j + 1];
j++;
ordemFilas[j] = i;
}
}
auxiliarSaida[i] = auxiliarSaida[i] - (int) auxiliarSaida[i];
}
painel.tamanhoMaiorFila = painel.numeroClientesFila[ordemFilas[ordemFilas.length 1]];
if (numeroClientesSaindo > 0) {
tempoMedioSistema /= numeroClientesSaindo;
tempoMedioFila /= numeroClientesSaindo;
}
70
71
72
73
auxiliarFila[auxiliarOrdemFilas[0]]++;
auxiliarTempoEntrada[0].add(temposRemovidos.get(0));
}
temposRemovidos.remove(0);
clientesRemovidos--;
}
for (int i = 0; i < numeroServidores; i++) {
auxiliarTempoAtendimento[i] = tempoAtendimento[i];
}
}
painel.numeroClientesFila = auxiliarFila;
ordemFilas = auxiliarOrdemFilas;
tempoEntrada = auxiliarTempoEntrada;
tempoAtendimento = auxiliarTempoAtendimento;
}
painel.numeroServidores = numeroServidores;
}
}
}
Nota-se
que
os
mtodos
adicionarPontoGraficoClientesSistema,
mtodos
chamados
adicionarPontoGraficoClientesSistema
curva;
numeroEsperadoEntrada;
numeroEsperadoSaida;
graficoClientesSistema;
graficoTempoSistema;
74
txtNumeroClientesAtendidos.setVisible(false);
txtTextoClientesAtendidos.setVisible(false);
curva = null;
numeroEsperadoEntrada = 0;
numeroEsperadoSaida = 0;
graficoClientesSistema = null;
}
// [...]
curva;
numeroEsperadoEntrada;
numeroEsperadoSaida;
atualizacao;
graficoClientesSistema;
graficoTempoSistema;
75
Assim ser possvel obter os valores para inserir nos campos informativos do
objeto da classe Atualizacao. O cdigo do mtodo atualizarInformacoes est
apresentado a seguir.
public void atualizarInformacoes(int numeroClientesEntrando, int numeroClientesSaindo) {
if (atualizacao.estabilidadeMomentanea) {
txtEstabilidadeMomentanea.setForeground(Color.BLACK);
txtEstabilidadeMomentanea.setText("Estvel");
} else {
txtEstabilidadeMomentanea.setForeground(Color.RED);
txtEstabilidadeMomentanea.setText("Instvel");
}
if (atualizacao.estabilidadeMedia) {
txtEstabilidadeMedia.setForeground(Color.BLACK);
txtEstabilidadeMedia.setText("Estvel");
} else {
txtEstabilidadeMedia.setForeground(Color.RED);
txtEstabilidadeMedia.setText("Instvel");
}
double tempoRestante = (atualizacao.tempoFinalSimulacao - atualizacao.tempoAtualSimulacao)
/ (1000 * atualizacao.velocidade);
if (tempoRestante < 0) {
tempoRestante = 0;
}
dslVelocidade.setValue((int) (1001 - 50 * Math.sqrt(tempoRestante) / 3));
txtNumeroClientesSistema.setText("" +
(Integer.parseInt(txtNumeroClientesSistema.getText()) + numeroClientesEntrando));
if (numeroClientesSaindo < Integer.parseInt(txtNumeroClientesSistema.getText())) {
txtNumeroClientesSistema.setText("" +
(Integer.parseInt(txtNumeroClientesSistema.getText()) - numeroClientesSaindo));
txtNumeroClientesAtendidos.setText("" +
(Integer.parseInt(txtNumeroClientesAtendidos.getText()) + numeroClientesSaindo));
} else {
txtNumeroClientesAtendidos.setText("" +
(Integer.parseInt(txtNumeroClientesAtendidos.getText()) +
Integer.parseInt(txtNumeroClientesSistema.getText())));
txtNumeroClientesSistema.setText("0");
}
nmrIntensidadeTrafego.setValue(atualizacao.mediaRo);
nmrProbabilidadeZero.setValue(atualizacao.mediaProbabilidadeSistemaVazio);
nmrProbabilidadeEnfileiramento.setValue(atualizacao.mediaProbabilidadeEnfileiramento);
nmrClientesSistema.setValue(atualizacao.mediaClientesSistema);
nmrVarianciaClientesSistema.setValue(atualizacao.mediaVarianciaClientesSistema);
nmrClientesFila.setValue(atualizacao.mediaClientesFilas);
nmrVarianciaClientesFila.setValue(atualizacao.mediaVarianciaClientesFilas);
nmrTempoSistema.setValue(atualizacao.mediaTempoSistema);
nmrVarianciaTempoSistema.setValue(atualizacao.mediaVarianciaTempoSistema);
nmrTempoEspera.setValue(atualizacao.mediaTempoFila);
nmrVarianciaTempoEspera.setValue(atualizacao.mediaVarianciaTempoFila);
pnlAbas.setTitleAt(2, "Simulao (" + horarioExtenso((int)
atualizacao.tempoAtualSimulacao, 'M', true) + ")");
}
76
botSimular.setText("Pausar");
botReiniciar.setEnabled(true);
atualizacao.pausado = false;
if (graficoClientesSistema == null) {
graficoClientesSistema = new XYSeries("Numero de Clientes no Sistema");
XYSeriesCollection colecao = new XYSeriesCollection();
colecao.addSeries(graficoClientesSistema);
JFreeChart objeto = ChartFactory.createXYLineChart("Nmero de Clientes no
Sistema", "Tempo", "Nmero de Clientes", colecao, PlotOrientation.VERTICAL, false, true,
false);
objeto.setBackgroundPaint(pnlGraficoClientesSistema.getBackground());
ChartPanel painel = new ChartPanel(objeto, true);
pnlGraficoClientesSistema.removeAll();
pnlGraficoClientesSistema.add(painel);
graficoTempoSistema = new XYSeries("Tempo dos Clientes no Sistema");
colecao = new XYSeriesCollection();
colecao.addSeries(graficoTempoSistema);
objeto = ChartFactory.createXYLineChart("Tempo dos Clientes no Sistema",
"Tempo", "Tempo dos Clientes", colecao, PlotOrientation.VERTICAL, false, true, false);
objeto.setBackgroundPaint(pnlGraficoTempoSistema.getBackground());
painel = new ChartPanel(objeto, true);
pnlGraficoTempoSistema.removeAll();
pnlGraficoTempoSistema.add(painel);
}
pnlGraficoClientesSistema.validate();
pnlGraficoTempoSistema.validate();
try {
atualizacao.start();
} catch (Exception e) {
synchronized (atualizacao) {
atualizacao.notify();
}
}
txtNumeroClientesSistema.setVisible(true);
txtTextoClientesSistema.setVisible(true);
txtNumeroClientesAtendidos.setVisible(true);
txtTextoClientesAtendidos.setVisible(true);
}
} else if (botSimular.getText().equals("Pausar")) {
atualizacao.pausado = true;
botSimular.setText("Simular");
pnlAbas.setEnabled(true);
txtNumeroClientesSistema.setVisible(false);
txtTextoClientesSistema.setVisible(false);
txtNumeroClientesAtendidos.setVisible(false);
txtTextoClientesAtendidos.setVisible(false);
pnlAparencia.setVisible(true);
}
}
77
78
CONCLUSO
O presente trabalho demonstra que possvel (e vivel) o desenvolvimento
79
80
REFERNCIAS BIBLIOGRFICAS
81