Relatório da Disciplica de Sistemas Periciais Engenharia Electrotécnica e de Computadores FEUP 1997/98 Trabalho realizado por: Fernando Jorge Rufino Ferreira Ivo Jorge Pinto Ramos Docentes: Prof. Eugénio de Oliveira Eng. Rui Camacho pág. 1 WEB Agenda- Sistemas Periciais Índice 1. Objectivos …………………………………………………………… Pág. 2 2. Motivação e Resumo do Trabalho…………………………………. Pág. 3 3. Descrição do Trabalho……………………………………………… Pág. 4 Pág. 4 Pág. 5 Pág. 6 Pág. 7 Pág. 7 Pág. 7 Pág. 8 Pág. 8 3.1 3.2 3.3 3.4 Funcionalidades………………………………………………………. Estrutura do Programa……………………………………………….. Esquemas de Representação do Conhecimento……………………. Implementação dos Esquemas de Representação de Conhecimento 3.5 3.6 Explicação dos Esquemas de Comunicação……………………….. Explicação do Algoritmo…………………………………………….. 3.4.1 3.4.2 3.4.3 Conhecimento das Agendas………………………………………………… Conhecimento das Reuniões……………………………………………….. Conhecimento sobre os Utilizadores………………………………………. Algoritmo do Coordenador…………………………………………………. Algoritmo do Cliente………………………………………………………… Análise da complexidade dos Algoritmos…………………………… Pág. 12 Pág. 12 Pág. 14 Pág. 15 4. Ambiente de Desenvolvimento…………………………………….. Pág. 15 5. Avaliação do Programa……………………………………………… Pág. 16 6. Resultados Experimentais………………………………………….. Pág. 16 7. Dificuldades Encontradas………………………………………….. Pág. 19 3.6.1 3.6.2 3.7 8. Conclusões…………………………………………………………… Pág. 20 9. Melhoramentos……………………………………………………… Pág. 20 10. Bibliografia…………………………………………………………... Pág. 21 Apêndices………………………………………………………………... Pág. 22 1. Manual do Utilizador……………………………………………….. Pág. 23 2. Listagem do Programa……………………………………………… Pág. 31 WEB Agenda- Sistemas Periciais pág. 2 1. Objectivos Este sistema insere-se no âmbito dos agentes distribuidos. Cada um dos agentes representa uma pessoa que defende a sua agenda existindo um agente coordenador que coordena toda a marcação. O sistema tem como principais objectivos: Criar uma agenda que permita ao utilizador da mesma organizar o seu trabalho diário. Representar a disponibilidade de cada pessoa utilizando um ficheiro de agenda válido por uma semana. Mediante pedido de marcação o agente coordenador entra em conversação com os outros agentes, cada um com a sua agenda, de maneira a conseguir um consenso que permite marcar uma reunião com as pessoas necessárias. Os agentes, durante toda a conversação, não conhecem a agenda dos outros mas apenas pontualmente as disponibilidades deles. Manter um ficheiro de todos os utilizadores do sistema. Permitir vários tipos de solução consoante os objectivos do utilizador. Permitir uma funcionalidade do sistema também como sistema de apoio à decisão em vários tipos de solução aonde o utilizador tem a última palavra. Facilidade de utilização através de um servidor http disponibilizando o serviço através da WEB. WEB Agenda- Sistemas Periciais pág. 3 2. Motivação e Resumo do Trabalho Como parte integrante da disciplina de Sistemas Periciais foram apresentados vários trabalhos com o intuito de ser feita uma escolha para futura implementação. Desde cedo os trabalhos inseridos na WEB nos despertaram interesse e, mediante a explicação deste trabalho, por parte do Prof. Eugénio de Oliveira ficamos entusiamados com o trabalho e começamos logo a pensar nele. Por outro lado este trabalho envolvia um domínio muito extenso pois para além da WEB, o trabalho envolve a utilização de Multi-agentes, utilização de uma nova linguagem como é o JAVA e utilização de mecanismos de comunicação. Com a execução deste trabalho poderíamos aprender a linguagem que nos parece que vai ditar o futuro no ambiente WEB e está a começar a impôr-se. Antes de optarmos pelo trabalho tivemos ainda a possibilidade de observar uma trabalho com um objectivo semelhante realizado por uma aluna do Prof. Eugénio, trabalho este realizado em TCL/TK. Verificamos que o trabalho era interessante, no entanto um pouco lento e ainda com poucas funcionalidades e a partir daí nasceu a nossa motivação para realizar um sistema como nós idealizávamos. O JAVA está ainda pouco explorado daí a dificuldade de tratar alguns problemas, que foram surgindo, por isso tivemos que recorrer à INTERNET e à nossa imaginação para conseguir resolver a maioria desses problemas. Inicialmente começamos por construir um trabalho dirigido para ambiente Windows, completamente dentro dos requisitos do trabalho, e apenas depois adaptamo-lo para a sua utilização em página de WEB. O trabalho não tem apenas um interesse meramente académico, bem pelo contrário. A nossa vontade era poder instalar o sistema na Faculdade e disponibilizar o serviço para os professores. Pensamos que o sistema é de facto de grande utilidade, pois a manutenção e gestão do tempo é importante no mundo do trabalho. Como projecto de final de curso estamos a trabalhar nos Sistemas de Informação da Faculdade e por achamos que um sistema deste tipo seria bastante útil para todos os docentes da mesma. Embora fazer a integração no Sistema de Informação não seja um exercício muito fácil devido à estrutura já existente. Tendo um semestre para executar o trabalho, e outras preocupações relativas ao curso, não nos foi possível nem fazer tudo o que tínhamos em vista. Em geral, achámos que o objectivo do trabalho foi atingido, tendo sido uma boa experiência tanto em termos de aquisição de conhecimentos, bem como experiência sobre comunicação entre multi-agentes, em que se aprendeu a WEB Agenda- Sistemas Periciais pág. 4 importância de boas definições de objectivos, divisão de tarefas, discussões de grupo e integração de resultados parcelares. Nas páginas seguintes indicamos em pormenor vários pontos relativos ao trabalho. 3. Descrição do Trabalho 3.1 Funcionalidades O sistema implementado proporciona um leque variado de funcionalidades, que apresentamos de seguida: Segurança: O sistema possui uma entrada em que é feita a verificação do utilizador que está a tentar aceder ao sistema. É pedido o utilizador e a respectiva password e através a entrada deste campos o sistema validará ou não o utilizador de acordo com a informação que possui. Ficheiro de Utilizadores: O adminstrador do sistema (super-utilizador) tem a possibilidade de acrescentar utilizadores a este ficheiro. Aqui é guardado o username, a password, o primeiro nome e o último do utilizador, a porta pelo qual o seu agente se vai ligar, o seu email e o URL da sua directiria de CGI's. Criação de Agendas: Cada utilizador tem a possibilidade de criar a sua própria agenda semanal podendo definir para cada dia se está livre, ocupado, ou condicionado. No caso de estar condicionado pode ainda especificar se tem preferência da parte da manhã ou da parte da tarde. Visualização da Agenda: Cada utilizador pode utilizar o sistema apenas para visualizar a sua agenda. Neste estado o utilizador poderá identificar as reuniões que foram marcadas e para cada reunião qual o assunto que vai ser tratado assim como quantas pessoas vão estar presentes e ausentes. Refinação dos Utilizadores: Antes do processo de marcação é possível fazer uma selecção de quais dos utilizadores do sistema queremos contactar para marcar uma reunião. Opções: Antes do início do processo de conversação entre os agentes é possível definir o intervalo temporal no qual a reunião pode ser marcada, o número de iterações que o processo deve fazer, qual o padrão final de disponibilidade dos utlizadores que aceitaram a reunião perante o dia e a hora em que foi marcada, o número de pessoas que podem faltar para além do tipo de solução que pretendemos. Três tipos de solução: O primeiro consiste numa solução em que queremos obter uma disponibilidade global máxima respeitando o número de faltas máxima e o sucesso mínimo que impusemos. O segundo preocupa-se em reduzir o número de faltas ao mínimo possível podendo a solução descer abaixo do nível que estipulamos para o grau de sucesso. O terceiro consiste WEB Agenda- Sistemas Periciais pág. 5 em procurar uma solução que se preocupa em maximizar o grau do sucesso podendo violar o número de faltas máximo imposto garantido pelo menos metade deste. Sistema de apoio à decisão: O sistema permite ainda apresentar os 3 tipos de solução e deixar o utilizador ter a última palavra a dizer. Actualização das agendas: No caso do utilizador que solicitou a marcação da reunião ficar satisfeito com a solução o sistema actualiza automaticamente as agendas de cada uma das pessoas que puderem estar presentes na reunião transmitindo o assunto e o número de pessoas presentes e ausentes. 3.2 Estrutura do Programa O trabalho está dividido em vários módulos que executam uma tarefa bem definida e que interagem entre si através de passagem de parâmetros. No nosso programa podemos então identificar os seguintes módulos: Tratamento dos ficheiros dos utilizadores: Este módulo preocupa-se em ler o ficheiro de Passwords, escrever no ficheiro de Passwords e verificar a veracidade do utilizador que pretende entrar no sistema. Este módulo recebe dados do “user interface” e depois de validar o utilizador transmite dados para o módulo de entrada do Sistema. Módulo de entrada do sistema: Este recebe informação do módulo anterior sobre qual o utilizador que entrou no sistema e uma lista das informações de todos os utilizadores presentes no sistema. Consoante a opção escolhida neste módulo ele pode comunicar com o ficheiro de utilizadores para acrescentar passwords (apenas é possível para o super-utilizador), pode comunicar com o módulo da agenda pessoal ou com o módulo de escolha de utilizadores. Módulo da agenda pessoal: Este módulo recebe informação sobre o utilizador actual e comunicando directamente com os módulos dos ficheiros de agenda e de reuniões lança resultados para o ecrán. A partir deste módulo é possível editar a agenda, e daí comunicar com o módulo de criação de agenda, ou marcar uma reunião e aí comunicar com o módulo de refinação de utilizadores. Módulo de gestão de ficheiros de agenda: Este módulo tem como funções ler e escrever sobre os ficheiros de agenda recebendo dados da criação de agenda e retribuindo dados ao módulo de visualização da agenda pessoal. Módulo de gestão de ficheiros de reunião: Este módulo permite ler e escrever sobre os ficheiros de reunião recebendo dados do módulo de marcação da reunião (Assunto da reunião, número de pessoas presentes e número de pessoas ausentes) e fornecendo dados ao ficheiro de visualização da agenda. WEB Agenda- Sistemas Periciais pág. 6 Módulo de criação da agenda: Este módulo é responsável pela criação da agenda de cada utilizador recebendo dados a partir do “user interface” e enviando os dados para o módulo de gestão de ficheiros de agenda. Módulo de escolha de utilizadores: Neste módulo o utilizador pode escolher os utilizadores que pretende para a marcação da reunião a partir de uma lista, esta é fornecida pelo módulo de entrada enviando depois uma lista dos utilizadores escolhidos para o módulo de marcação da reunião. Módulo de marcação de reunião: Este módulo recebe uma lista de utilizadores do módulo de escolha de utilizadores, recebe dados e um conjuntos de opções definidas pelo utilizador através do “user interface” e comunica com o módulo do servidor, com o módulo de comunicação e com o módulo de gestão de ficheiros. Para o módulo do servidor é enviado uma lista de portas para o qual ele deve comunicar. Para o módulo de comunicação são enviados os URLs onde se encontram os clientes que devem ser “acordados”. O módulo de gestão de ficheiros retribui para este módulo a lista de preferências do utilizador actual. Módulo de servidor: Este módulo recebe uma lista de agentes para os quais deve ser criado um socket. Módulo de comunicação: Este módulo é feito em Perl e recebe uma lista de URL’s e o Ip Adress do servidor. O que ele faz é acordá-los pondo cada agente a correr em background na máquina em que reside. Módulo do agente: Este módulo é acordado pelo módulo de comunicação, e comunica com o módulo de cliente e com o módulo de gestão de ficheiros de onde recebe a informação da sua agenda. Módulo de cliente: Este módulo é despertado pelo módulo do agente e permite aceitar o socket proposto pelo módulo Servidor. 3.3 Esquemas de Representação do Conhecimento O nosso trabalho insere-se na área de Sistemas Multi-Agente e daí não termos utilizado esquemas de representação de conhecimento muito complexos. Basicamente o conhecimento dos agentes traduz-se em 2 objectos: Conhecimento da agenda: O conteúdo da agenda de cada agente encontra-se armazenado num ficheiro de agenda. Neste ficheiro encontramos a disponibilidade do agente traduzida quantitativamente numa escala de 0.0 a 1.0, que representam indisponibilidade e disponibilidade total, respectivamente. Este ficheiro representa a base de conhecimento do nosso agente durante o processo de negociação, isto é, o agente cada vez que recebe uma proposta analisa-a recorrendo à base de conhecimento permitindo assim aceitar ou rejeitar a proposta para além de formular uma contraproposta. Este conhecimento é dinámico (não monótono) já que perante a marcação de WEB Agenda- Sistemas Periciais pág. 7 uma reunião num dia e a determinada hora dá origem a que a disponibilidade existente mude para indisponibilidade total. Conhecimento sobre as reuniões: Cada agente tem também o conhecimento sobre as reuniões que tem agendadas. Embore este conhecimento não tenha aplicação no processo de negociação, é utilizado sempre que o utilizador consulta a sua agenda. Este conhecimento é armazenado em ficheiro e carregado sempre que o utilizador consultar a sua a agenda. O conhecimento das reuniões é também uma informação dinâmica já que cada vez que marcamos uma reunião actualizamos a base de conhecimento com o assunto que vai ser tratado assim como o número de pessoas presentes e ausentes. Conhecimento sobre os utilizadores: O sistema possui um ficheiro de passwords que permite constituir para além de segurança, uma base de conhecimento sobre os utilizadores (O primeiro e último nomes, o email, o porta pelo qual ele comunica e URL para a sua directoria de cgi’s), 3.4 Implementação dos Esquemas de Representação de Conhecimento 3.4.1 Conhecimento das Agendas Este tipo de conhecimento está, como já dissemos, armazenado num ficheiro segundo um conjunto de Objectos a que nós chamamos “Instance” e que possui 3 argumentos: Day Hour Preference Quando o agente é acordado vai buscar esta informação ao ficheiro e coloca essa informação sobre 2 tipos de estruturas de dados: Matriz de Preferências: É traduzida por um array de 2 dimensões com objectos do tipo “Instance” Lista de Preferências: Conjunto de objectos “Instance” que são colocados por ordem descrescente de preferências e apenas aqueles que têm preferência não nula. 3.4.2 Conhecimento das Reuniões: À semelhança do anterior este tipo de conhecimento encontra-se também armazenado num ficheiro que é constituído por um conjunto de objectos “Reunion” que possuiem 3 tipos de argumentos: TalkAbout Ausent WEB Agenda- Sistemas Periciais pág. 8 Success Este conhecimento é adquirido quando um utilizador necessita de visualizar a sua agenda e essa informação é colocada numa: Matriz de Reuniões: Conjunto de objectos “Reunion” que são colocados num array de 2 dimensões. 3.4.3 Conhecimento sobre os Utilizadores: À semelhança dos tipos de conhecimento anteriores este está armazenado num ficheiro. Este conhecimento é carregado sempre que entramos no sistema e colocado 7 estruturas de dados: Array de Utilizadores: Todos os utilizadores do sistema. Array de Passwords: Passwords respectivas aos utilizadores. Array de Firstnames: Primeiro nome de cada Utilizador. Array de Lastnames: Último nome de cada Utilizador. Array de Emails: Correio electrónico referente a cada utilizador. Array de Ports: Porta de comunicação referente a cada utilizador. Array de URLs: URL da directoria de CGI´s respeitante a cada utilizador do sistema. 3.5 Explicação dos Esquemas de Comunicação Neste trabalho está envolvido um leque elevado de comunicações quer via Sockets, quer através de "URL connections". No caso da comunicação por Sockets foi importante a utilização de um protocolo capaz de efectuar uma comunicação ente o agente coordenador e os agentes clientes eficiente.Vamos passar agora a explicar os vários esquemas de comunicação. As operações que envolvem comunicação são as seguintes: Leitura de Ficheiros: A leitura de ficheiros é efectuada através de uma ligação URL ao ficheiro seguida da abertura de uma Stream para leitura, sendo esta efectuada linha a linha (através de um "readline"). pág. 9 WEB Agenda- Sistemas Periciais Stream de Stream de Leitura Leitura Servidor Local do Cliente 1 Stream de Leitura Agente Coordenador Servidor do Sistema Servidor Local do Cliente 2 Figura 1 Escrita de Ficheiros: A escrita de ficheiros é efectuada através de uma ligação URL a um CGI (Common Gateway Interface) chamado "escreve.pl" onde são passados como parâmetros o Username e o conteúdo a escrever. http://jinks.fe.up.pt/cgi-bin/fjorgecgi/escreve.pl?username+conteúdo escreve.pl Servidor do Sistema Figura 2 Apenas o Sistema faz alterações nos ficheiros de todos os utilizador para facilitar o problema. Ou seja, depois do fim da marcação quem se encarrega da actualização dos ficheiros de agenda e de reunião é o próprio sistema e daí a razão de todos estes ficheiros estarem no mesmo servidor. WEB Agenda- Sistemas Periciais pág. 10 Leitura de Imagens: A leitura de uma imagem é efectuada também através de uma ligação URL através da qual é obtido um objecto do tipo "Image" que permite fazer um "DrawImage", isto é, desenhá-la no ecrã. Negociação entre o Coordenador e os Clientes: A troca de mensagens entre o Agente Coordenador e os Agentes Clientes é feita através de Sockets. O Agente Coordenador sabendo quantos Clientes foram escolhidos para a marcação da reunião envia a sua proposta a todos eles utilizando para isso uma porta. Por seu lado cada Agente tem a sua própria porta para comunicar, e perante a proposta do Coordenador, vai analisá-la e construir uma contraproposta no caso de não aceitar ou uma segunda alternativa no caso de haver aceitação. De seguida envia a mensagem construída ao Coordenador. Tipos de Mensagens enviadas pelo coordenador: • 01 0 0 1.0 true - mensagem de envio de dados. 01- Código que indica que é uma mensagem de envio de dados. 0-Indica o dia da semana de 0 a 4 (Segunda a Sexta). 0-Indica a hora do dia de 0 a 9 (Das 8h00m-11h00m e das 14h00m-19h00m) 1.0-Mede a disponibilidade do coordenador face à proposta lançada (De 0.0 a 1.0) true-Indica que a comunicação ainda não vai terminar. No caso de ser false indica aos agentes para terminar. • 00 1 1 - mensagem para apagar dados. 00 - Código que indica que é uma mensagem para apagar dados. 1 1 - Indica que a proposta Terça às 9h00m não deve ser mais proposta por nenhum dos restantes clientes porque constitui uma indisponibilidade para o Coordenador (permite poupar tempo de processamento). • 02 - Aviso de última mensagem. Tipos de Mensagens enviadas pelos Clientes: • 0.7 0 0 1.0 true - mensagem de envio de contraproposta. 0.7- Indica o grau de preferência deste cliente em relação à proposta enviada pelo coordenador. 0 0 - Indica que a contraproposta é Segunda às 8h00m. 1.0 - Indica que nessa contraproposta o cliente apresenta uma preferência de 1.0. true - Indica que a ligação ainda se vai manter. WEB Agenda- Sistemas Periciais pág. 11 "Despertar" os Clientes: Quando o Agente Coordenador recebe ordens do utilizador para começar a marcação da reunião, este tenta estabelecer um Socket com cada um dos Clientes e de seguida efectua uma ligação URL para cada um dos Cliente para um CGI chamado "acorda.pl". É de notar que este CGI se encontra na mesma máquina do Sistema já que o JAVA não permite fazer ligações URL para máquinas diferentes. Para resolver este problema, o nosso "acorda.pl" através de uma biblioteca de Perl faz um "get" isto é uma ligação URL para outro CGI chamado "executa.pl" que pode estar no mesmo servidor ou noutro qualquer dependendo da máquina onde o Cliente tiver o seu agente. Este CGI chamado "executa.pl", já na máquina onde o agente do cliente se encontra, executa um programa em JAVA chamado "agent1.class". Este programa em JAVA faz o "accept" do Socket proposta pelo Coordenador está então estabelecida a comunicação. pág. 12 WEB Agenda- Sistemas Periciais Servidor do Cliente 1 executa.pl agent1 Servidor do Cliente 2 acorda.pl Servidor do Sistema executa.pl agent1 Figura 4 3.6 Explicação do Algoritmo O algoritmo utilizado neste sistema foi por nós concebido sofrendo sucessivos melhoramentos. Depois de estabelecida a comunicação entre os agentes e estarem prontos a trocar informação, como anteriormente explicamos, é necessária a utilização de um algoritmo capaz de avaliar a qualidade das propostas e capaz de lançar uma contra-proposta se necessário. O algoritmo que corre no Coordenador e o que corre nos Clientes são muito semelhantes. Vamos passar a explicar cada um deles. 3.6.1 Algoritmo do Coordenador O esquema do algoritmo é apresentado na figura 5 através de um fluxograma. O Coordenador envia uma proposta. De seguida recebe o grau de preferência de cada Cliente à proposta que enviou assim como uma contraproposta ou uma segunda alternativa. Conforme o tipo de solução que o utilizador pretende o sistema vai actuar de 4 maneiras diferentes, isto é: Tipo de Solução 1: Neste tipo de solução o sistema preocupa-se em tentar conseguir o máximo sucesso possível respeitando o número de falhas e o sucesso introduzido pelo utilizador. Nesse caso o sistema calcula a função heurística para todas as preferências diferentes de zero e conta o número de zeros. Se o número de zeros for melhor do que a escolha , o sucesso maior do que o escolhido e a solução for melhor então esta passa a ser a nova solução. Se WEB Agenda- Sistemas Periciais pág. 13 a solução apresenta o mesmo sucesso que a anterior, mas apresenta um número de falhas inferior então esta passa a ser a nova solução. Tipo de Solução 2: Aqui o sistema preocupa-se em obter uma solução que tem como prioridade a diminuição máxima do número de zeros. Depois de guardar todas as disponibilidade referentes à proposta enviada e as contrapropostas, verifica se o número de zeros é inferior à solução anterior e se é menor do que o valor especificado pelo utilizador. Se sim, então guarda. Se não, verifica se o número de zeros é igual, sendo esta a situação, verifica o valor do sucesso obtido; se não sai. Tipo de Solução 3: Com esta opção o sistema preocupa-se em conseguir obter o maior sucesso possível, isto é, a maior disponibilidade possível entre todos os presentes, mesmo que para isso tenha mais falhas do que as especificadas. De qualquer modo, garante que pelo menos metade das pessoas escolhidas estarão presentes. Depois de recebidas as disponibilidades referentes à proposta enviada e todas as contrapropostas o sistema algoritmo calcula através da função heurística o valor do sucesso. Se for melhor guarda. Se igual, mas o número de zeros inferior então guarda. Tipo de Solução 4: Esta solução não está apresentada na figura porque não é nada mais do que calcular as três soluções e deixar o utilizador escolher entre elas. Digamos que é uma espécie de Sistema de Apoio à Decisão. Depois de armazenar a solução o Sistema tem de escolher a próxima proposta a enviar. Assim verifica se existem contrapropostas ou alternativas enviadas pelos clientes para as quais ele possa estar presente. Se não existirem vai à sua lista, tira a melhor para si e envia. No caso da sua lista estar vazia notifica os Clientes para acabar a comunicação. Se sim, escolhe a melhor contraproposta e envia. pág. 14 WEB Agenda- Sistemas Periciais Figura 5 3.6.2 Algoritmo do Cliente O esquema do algoritmo é apresentado na figura 6 através de um fluxograma. O Coordenador envia uma proposta. De seguida o Cliente vai à sua matriz de preferências é vê qual é a sua disponibilidade no dia e à hora da proposta. Depois consulta a sua lista ordenada de preferências e lê o primeiro elemento da lista. Se as disponibilidades forem iguais então aceita a proposta e envia uma segunda alternativa. Se não, não aceita, retira da lista de preferências o primeiro elemento e este é a sua contraproposta. Este mecanismo mantém-se até ser anunciada por parte do Coordenador o fim da negociação ou então o Cliente esgotar as suas disponibilidades. Neste último caso este notifica o Coordenador. pág. 15 WEB Agenda- Sistemas Periciais Figura 6 3.7 Análise da complexidade dos Algoritmos A complexidade dos algoritmos do nosso sistema atinge ordem máxima igual a n. Isto porque não utilizamos ciclos encadeados, nem chamadas recursivas. O maior ciclo variável não é encadeado e o número de iterações do ciclo depende do número de utilizadores e do número de iterações, no entanto é apenas de ordem n. Isto quer significar que com o aumento de utilizadores a velocidade decresce de uma forma linear, no entanto, sem afectar demasiado o desempenho do sistema. 4. Ambiente de Desenvolvimento Como foi referido anteriormente, foram feitas duas versões desta aplicação. A primeira (não integrada na WEB) foi basicamente toda desenvolvida em PCs, no ambiente Windows95 e NT4.0, com o ambiente de programação de Java “Visual Age for Java” da IBM. A segunda, dada a sua complexidade, foi implementada em vários sistemas. Foi usado, além do Windows (95 e NT4.0), Unix e Linux, novamente em PCs e num alfa (tom.fe.up.pt da FEUPnet). Continuámos a usar o Java no ambiente de desenvolvimento da IBM e, desta vez, também com o JDK (Java Developers Kit) da Sun. WEB Agenda- Sistemas Periciais pág. 16 Devido aos problemas, de restrições, de escrita e leitura em disco através de Applets, em Java, foi necessário o recurso a CGIs em Perl. Para o efeito usamos uma biblioteca retirada da WEB que permite ao Perl executar URLs. Esta biblioteca permitiu-nos implementar um verdadeiro protocolo para ultrapassar as restrições referidas acima e pôr os agentes dos "clientes" a correr em background, em máquinas remotas. 5. Avaliação do Programa Para escolher uma aplicação deste género, entre várias, seriam de tomar em consideração os seguintes critérios: Facilidade de utilização: Um programa deve ser "user friendly" de maneira a que haja facilidade de utilização, por parte do utilizador, e que permita detectar e evitar a maioria dos erros. Acesso ao serviço: Se for acessível por WEB, qualquer pessoa inscrita no serviço, pode consultar a sua agenda e marcar uma possível reunião, em qualquer ponto do mundo com acesso à rede. Velocidade: É do interesse do utilizador ter um programa que consiga convergir para uma solução rapidamente. Qualidade: Apesar de ser pretendido um algoritmo rápido é também necessário que este produza bons resultados. Novos utilizadores: Com que facilidade se pode acrescentar novos utilizadores no sistema. 6. Resultados Experimentais Uma vez que a linguagem JAVA é orientada por objectos utilizamos testes direccionados para as linguagens orientadas por objectos. Estas linguagens permitem a concepção de objectos bem definidos e que realizam uma operação perfeitamente bem definida, o que facilita os testes de defeitos. As fases dos nossos testes foram as seguintes: Teste de Unidade: Nesta fase preocupamo-nos em testar cada um dos componentes do sistema independentemente e detectar os erros encontrados. Ex: Nesta fase testámos separadamente a leitura e escrita de ficheiros . Teste dos Módulos: Na fase seguinte ligados os componentes dependentes do sistema e fizemos o teste de cada um dos módulos com o intuito de encontrar algum erro. Ex: Aqui juntámos todos os componentes respeitantes à gestão de ficheiros e fizemos o teste deste módulo. WEB Agenda- Sistemas Periciais pág. 17 Teste do Sistema: Foram unidos todos os módulos e feito o teste a todo o sistema. Nas várias fases foram utilizadas 2 estratégias de teste que são respectivamente: Teste de Stress: Consiste em "esforçar" o sistema à máxima carga para que foi concebido. Este teste é eficiente porque causa, na maioria dos casos, o aparecimento de defeitos. Este tipo de teste é muito utilizado em sistemas distribuidos. Ex: No teste do módulo de marcação impôr o maior número de restrições possíveis (sucesso, faltas, intervalos temporais restritos, número máximo de iterações) e pedir ao sistema para enviar os 3 tipos de solução utilizando ainda para cada cliente agendas bastante apertadas. Teste "Back-to-Back": No nosso caso foi preciso realizar várias versões do sistema, devido a algumas dificuldades, pelo que tínhamos em nossa posse um conjunto de versões do sistema. Esta estratégia consiste na realização do mesmo teste a várias versões do programa e verificar as saídas do sistema. Saídas diferentes implicam potenciais problemas. Nas várias fases dos teste o tipo de teste utilizada foi o Teste Estrutural. Este tem como objectivo executar todo o código do programa pelo menos 1 vez. Não implica, no entanto, todas as combinações dos caminhos possíveis. Para além de defeitos preocupámo-nos em testar a qualidade das soluções que o sistema retribui. Neste campo foi utilizada inspecção directa sobre as soluções e verificação visual sobre a agenda de cada um, se a solução enviada pelo sistema é de facto a melhor alternativa possível de acordo com o objectivo de cada solução. De seguida apresentamos um exemplo do resultado de um dos teste em que pedimos um sucesso de 40%, e admitimos 1 falha, com um intervalo temporal entre Segunda e Sexta com o número máximo de iterações. O objectivo deste teste era, para além de fazer com que o sistema elaborasse os 3 tipos de soluções, testar o seu comportamento perante agendas muito restritas. Neste caso obtivemos a mesma solução nas 3 situações já que não é possível obter nenhuma solução com 0 faltas e com sucesso superior a 83%. pág. 18 WEB Agenda- Sistemas Periciais Figura 7 - Escolhas Efectuadas Figura 8 - Soluções Obtidas WEB Agenda- Sistemas Periciais pág. 19 Outro cuidado que existiu foi verificar qual a adaptabilidade do sistema, isto é, qual o seu comportamento perante situações inesperadas tais como: Não preenchimento de algum campo Tomada de decisão errada por parte do utilizador 7. Dificuldades Encontradas Uma das maiores dificuldades residiu pelo facto do JAVA ser uma linguagem nova o que origina o conhecimento de novos truques para resolução de problemas assim como a necessidade de muitas configurações e restrições de fundo sobre as quais poucas pessoas têm conhecimento e daí a dificuldade de encontrar soluções para muitos problemas que foram aparecendo durante a implementação do sistema. O maior problema que tivemos de "combater" foi o facto de o JAVA quando implementado como Applet não deixar escrever em disco mesmo sendo Servidor lançando excepções de segurança. Lançados para a resolução do problemas tentamos falar directamente através da WEB com a SUN (criadores do JAVA), no entanto, sem sucesso; falamos também com um dos responsáveis pelo CIUP que nos deu algumas ideias mas dizendo que não passavam disso porque nunca tinha feita nada do género. Fomos tentando ideias sucessivas sem grande sucesso até que resolvemos o problemas com a utilização de CGI's cuja implementação foi um pouco complicada. Depois de resolvido este problema surgiu um novo. Já pensávamos ter resolvido todos os problemas quando descobrimos que dentro de um Applet não é possível a realização de ligações URL para uma máquina diferente da que estamos a correr o Applet. Este problema foi resolvido através de uma ligação URL para a mesma máquina que chamava um CGI, que através de uma biblioteca de Perl fazia uma ligação URL para outra máquina. Por outras palavras, utilizamos o servidor de HTTP através de CGI's. Outro dos problemas encontradas foi a necessidade que criar um processo paralelo responsável pelo refrescamento do ecrã já que durante o estabelecimento de ligação o JAVA lançava o refrescamento para uma prioridade muito baixa o que originava o não refrescamento do ecrã. Um outro problema foi a dificuldade de "acordar" os clientes aquando do início do processo de comunicação. O que acontece neste caso é que o sistema lança ligações URL responsáveis por executar um programa em Java situado em cada Servidor onde o Cliente se encontra. Aqui o problema prende-se pelo facto de uma ligação URL quando entra num outro Servidor ter como dono o utilizador "Nobody". Daí ser necessário definir todas as variáveis de ambiente para correr o JAVA tais como PATH (indica onde se encontra o JAVA), SETCLASSPATH (indica onde se encontram os programas de JAVA a serem executados), SYSNAME (informa o JAVA sobre o nome do sistema). WEB Agenda- Sistemas Periciais pág. 20 Para finalizar foi necessário debatermo-nos com a criação de um algoritmo de negociação pois não encontramos grande bibliografia sobre o assunto. Houveram ainda mais dificuldades a nível de pormenores dos problemas citados anteriormente mas que não têm grande necessidade de serem descritos pois seria entrar em detalhe excessivo. 8. Conclusões O grupo atingiu todos os objectivos por ele estabelecidos. Conseguiu criar uma agenda que permite ao utilizador da mesma organizar o seu trabalho diário (com algumas limitações). Em ambas as versões implementadas o algoritmo, por nós idealizado, mostrou-se capaz de, na arquitectura utilizada (processamento distribuído através de agentes), fornecer rapidamente soluções próximas do ideal ou mesmo óptimas (o mais frequente). Foi também possível, na segunda versão desta aplicação, disponibilizar o serviço através da WEB. Esta versão ainda tem alguns problemas devido ao nosso não conhecimento completo da linguagem JAVA o que implica ainda alguns problemas ao nível do Windows NT (ou então algum bug do Internet Explorer 4.0 para o NT) e instalação dependente da máquina onde é necessário colocar o agente do utilizador específico. 9. Melhoramentos Este trabalho é bastante vasto o que proporciona uma grande quantidade de melhorias a serem levadas em consideração. Assim tivemos algumas ideias que poderiam ser implementadas e que descrevemos de seguida: Haver a possibilidade de, embora só existindo um janela temporal de 1 semana, o sistema ter conhecimento que existe uma semana a seguir à semana presente. Ou seja, ser possível, por exemplo, pedir-se para marcar numa Sexta e ter percepção de que a reunião poderia ir “parar” na semana seguinte. Disponibilizar um sistema de mail que depois da marcação notificasse convenientemente cada uma das pessoas com a informação referente a essa reunião (dia, hora, assunto, local, número de pessoas presentes e ausentes). Possibilidade de manutenção de uma Base de Dados utilizando o JDBC o que permitiria aumentar a eficiência do sistema distribuído. Implementar um sistema multi-utilizador tendo em conta que seria sempre possível a existência de uma marcação a decorrer em paralelo, podendo dar origem no final a um resultado que era inconsistente (dependo da conversação que acabasse em primeiro lugar). Aumentar a segurança do Sistema. WEB Agenda- Sistemas Periciais pág. 21 10. Bibliografia 1. Java-How to Program H.M. Deitel (Deitel & Associates, Inc.) P.J. Deitel (Deitel & Assiciates, Inc.) Prentice Hall 2. Java 1.1 Unleashed third edition Michael Morrison, et al. Sams net 3. Perl 5 - Quick Reference Mícheál Ó Foghlú QUE 4. JavaScript - The Defenitive Guide David Flanagan O'Reilly & Associates, Inc. 5. http://www.javaworld.com - Este site apesar de não nos ter fornecido nenhuma solução directa, permitiu-nos ver alguns "scripts" e tirar algumas ideias valiosas para a resolução dos nossos problemas. 6. http://www.sun.com e http://java.sun.com - Os sites dos "inventores" do JAVA (relacionados com o mesmo). Também este permitiu encontrar algumas soluções. 7. http://www.ibm.com/java/ - Foi aqui que conseguimos obter o ambiente de programação "Visual Age for JAVA" que usamos durante basicamente todo o trabalho. 8. http://jinks.fe.up.pt/~mentor/perl/ - Esta página é basicamente um manual de Perl (Quick Reference) de um colega nosso da licenciatura de Minas. pág. 22 WEB Agenda- Sistemas Periciais Apêndices pág. 23 WEB Agenda- Sistemas Periciais 1. Manual do Utilizador Para aceder a este serviço (após ter um username) basta aceder à página web onde este se encontra instalado (neste momento a sua localização é http://jinks.fe.up.pt/~fjorge/capa.html). Nesta página, carregando sobre o logotipo (do trabalho) “arranca-se o serviço”, este começa com o ecrã de segurança (figura 9) onde se introduz o username e a respectiva password. Figura 9 Sendo um utilizador autorizado aparece o menu de boas-vindas (figura10). Figura 10 Aqui pode-se ter acesso à agenda pessoal (figura 12), marcar uma reunião ou editar o ficheiro de utilizadores (só disponível para os gestores do sistema). pág. 24 WEB Agenda- Sistemas Periciais Visto que se entrou no sistema como super-utilizador pode-se ver já a opção de “Ficheiro de Passwords” (figura 11). Figura 11 Os campos Username e Port Number são inseridos automaticamente pelo programa (e não podem ser alterados). O gestor apenas necessita de preencher as informações do novo utilizador - a password, primeiro e último nome, email e localização onde se vão encontrar os CGIs referentes ao agente do utilizador. Para formalizar a inserção do utilizador, basta pressionar o botão “Adicionar” com os campos todos preenchidos. Volta-se agora ao ecrã de boas-vindas. Se quisermos ver ou alterar a nossa agenda carregamos no botão “Agenda Pessoal” o qual abre um ecrã (figura 12) com a mesma. Figura 12 pág. 25 WEB Agenda- Sistemas Periciais Aqui podemos (além de consultar a agenda) também editá-la e marcar uma reunião. Com vista à edição, carrega-se em “Editar”. Este abre uma janela (figura 13) com a possibilidade de alterar as suas disponibilidades diárias. Figura 13 No horário pode-se escolher entre três opções - livre, ocupado ou indiferente. Livre e ocupado indicam disponibilidade ou não total. Os indiferentes ainda podem ser refinados sendo afectados pelas preferências de tarde ou de manhã. Ou seja, posso dizer “...para mim todo o dia, de Segunda-feira, é-me indiferente mas prefiro de manhã…” (não é o caso ilustrado na figura). Após serem feitas as alterações pode-se ou não gravar. pág. 26 WEB Agenda- Sistemas Periciais Voltando ao quadro de agenda pessoal (figura 12) pode-se também marcar uma reunião. Assim basta carregar em “Marcar” que um novo ecrã (figura 14) se apresenta. Figura 14 Aqui podemos seleccionar as pessoas com quem queremos marcar a reunião. Após feita a selecção referida pressionamos o botão “Continuar” que nos retorna para o ecrã da agenda pessoal e aí pressionando “Marcar” passamos a ter o ecrã Figura 15 pág. 27 WEB Agenda- Sistemas Periciais de conversação (figura 16a). Figura 16a pág. 28 WEB Agenda- Sistemas Periciais Neste ecrã, antes de solicitarmos a marcação, temos de editar as opções. Esta operação abre uma nova janela (figura 15) com as opções disponíveis. Temos o intervalo temporal que nos permite configurar o intervalo de tempo em que a reunião tem significado. Podemos definir o sucesso que indica a média geométrica mínima exigida na solução, o número de iterações pretendido e o número de ausências permitidas. Aqui é possível seleccionar o tipo de solução pretendido (ou deixar essa decisão para o fim). Após a escolha da configuração para a reunião pretendida, retorna-se ao ecrã de marcação, onde está agora o botão de iniciar a conversação “ligado”. Pode-se ainda editar o campo “Assunto” para haver uma indicação, para os utilizadores, sobre o que é que a reunião trata. Carregando em “Iniciar” a conversação é iniciada e pode-se ver a mesma a decorrer nos campos de mensagens. Figura 16 pág. 29 WEB Agenda- Sistemas Periciais Quando a conversação chega a uma conclusão, é nos apresentado uma nova janela com o resultado da discussão. Aqui podemos escolher a solução que mais nos agrada (figura 17) se pedimos para deixar a escolha do tipo de solução para depois, ou se já foi escolhido aparece um ecrã (figura 18) só a confirmar se aceitamos ou não a solução alcançada. Figura 17 Figura 18 WEB Agenda- Sistemas Periciais pág. 30 Após a indicação para marcar as alterações são gravadas e pode-se sair do sistema. Se no ecrã de boas-vindas (figura 10) for pedido imediatamente para marcar uma reunião, o sistema abre primeiro o ecrã de escolha (figura 14), das pessoas com quem se quer marcar a reunião, e depois o da agenda pessoal (figura 12 - caso seja preciso vê-la antes de marcar uma reunião) a partir daí todo o procedimento é igual ao descrito acima. WEB Agenda- Sistemas Periciais pág. 31 2. Listagem do Programa Nesta secção vamos apresentar todos os componentes do sistema, descrevendo todas as suas funções e apresentando para cada um deles uma listagem devidamente comentada. Começamos então pelo programa em JAVA. 2.1 Classe Panel1 Esta classe é um Applet sobre o qual se vão sucedendo os interfaces do nosso sistema. A necessidade de um Applet deste tipo surgiu da dificuldade de comunicação entre 2 Applets que se encontram em página da WEB diferentes. Este Applet apresenta um layout que no JAVA chamamos de CardLayout. Este não é mais do que um baralho de cartas em que cada carta representa um Interface. Este layout permite como operações, adicionar cartas, eliminar cartas, colocar uma carta no cimo de baralho e retirar uma carta do cimo do baralho. Assim sendo, por exemplo, quando introduzimos a password e carregamos em submeter, este ecran desaparece e aparece o ecrán principal se a password estiver correcta. Isto não é mais do que retirar o 1º interface de cima do baralho, cria a nova carta e colocá-la no cimo do baralho. Cada interface representa no que se chama em JAVA de um Panel. Um Panel representa uma superficie de uma janela existente, isto é, uma superfície onde podemos desenhar componentes. Segue-se a listagem deste componente : // Importe das Bibliotecas de Applets e de Componentes do Java import java.applet.*; import java.awt.*; public class Panel1 extends Applet { // Declaração das Variáveis que representam os vários interfaces private Panel ivjPanel1 = null; private CardLayout cardManager; private Password password; private Entry begin; private ReadRandFile user=null; private Tabela2 tabela21; private Tabela table; private WriteRandFile alterar; private Tabela2 tabela2; private Marcacao marcacao; // Método que se encarrega de tratar todos os eventos deste applet (Ex :click nos botões) public boolean action (Event e,Object o ) { // Se for carregado um Botão if (e.target instanceof Button) { pág. 32 WEB Agenda- Sistemas Periciais // Trata dos Eventos do Ecran Password System.out.println(e.toString()+" /"+o.toString()); // Botão Submeter if (e.target==password.pajButton1) { showStatus("Espere...Validando a Password"); if (password.password_Validation()) { showStatus("Password Validada"); begin=new Entry(true,password.user); ivjPanel1.add("begin",begin); cardManager.show(ivjPanel1,"begin"); showStatus(""); } return true; } // Botão Cancelar if (e.target==password.pajButton11) { System.out.println("carreguei em cancelar"); System.exit(0); return true; } // Eventos do objecto Menu Principal // Botão Agenda Pessoal if (e.target==begin.etjButton13) { showStatus("Espere...Carregando a Agenda"); // Lê o ficheiro de Agenda Pessoal do Utilizador correspondente ReadSeqFile file; file=new ReadSeqFile(); file.open_file(begin.actual_user); file.readRecord(); file.cleanup(); // Cria a agenda tabela21=new Tabela2(file.records,begin.actual_user); ivjPanel1.add("tabela21",tabela21); cardManager.show(ivjPanel1,"tabela21"); showStatus("Agenda Carregada"); return true; } // Botão entrar if (e.target==begin.etjButton1) { // Se este interface ainda não se encontra criado if (user==null) { // Carrega a lista de utilizadores showStatus("Espere...Carregando Escolha de Utilizadores."); user=new ReadRandFile(begin.actual_user); ivjPanel1.add("user",user); cardManager.show(ivjPanel1,"user"); showStatus("Escolha de Utilizadores carregado."); } // Se o interface já se encontra criado apenas o mostra else pág. 33 WEB Agenda- Sistemas Periciais showStatus("Espere...Carregando Escolha de Utilizadores."); cardManager.show(ivjPanel1,"user"); showStatus("Escolha de Utilizadores carregado."); return true; } // Botão Ficheiro de Passwords if (e.target==begin.etjButton11) { // Abre o ficheiro de Passwords showStatus("Espere... Carregando Edição de Passwords."); alterar =new WriteRandFile(); ivjPanel1.add("alterar",alterar); cardManager.show(ivjPanel1,"alterar"); showStatus("Edição de Passwords carregado"); return true; } // Botão Sair if (e.target==begin.etjButton12) { // Sai do Sistema System.out.println("Ecran de Saída"); showStatus("Espere...Abandonando o Sistema."); System.exit(0); return true; } // Eventos da tabela21 // Botão Marcar if (tabela21!=null) { showStatus("Espere...Carregando Escolha de Utilizadores."); System.out.println("Entrei"); if (e.target==tabela21.ta2Button[0]) { System.out.println("Entrei"); if (user==null) { user=new ReadRandFile(tabela21.actual_user); IvjPanel1.add("user",user); cardManager.show(ivjPanel1,"user"); showStatus("Escolha de Utilizadores carregado."); } else cardManager.show(ivjPanel1,"user"); showStatus("Escolha de Utilizadores carregado."); return true; } // Botão Editar if (e.target==tabela21.ta2Button[1]) { showStatus("Espere...Carregando Criação da Agenda"); // Se a edição de agenda ainda não está carregada então cria-a if (table==null) { table=new Tabela(tabela21.actual_user); ivjPanel1.add("table",table); cardManager.show(ivjPanel1,"table"); showStatus("Criação da Agenda carregada."); WEB Agenda- Sistemas Periciais } // Senão apenas a coloca no ecran else cardManager.show(ivjPanel1,"table"); showStatus("Criação da Agenda carregada."); return true; } // Botão cancelar if (e.target==tabela21.ta2Button[2]) { // Ignora as alterações e volta ao menu principal showStatus("Espere...Carregando Menu de Entrada"); System.out.println("Finalizar a partir de Tabela 21"); cardManager.show(ivjPanel1,"begin"); showStatus("Menu de Entrada"); return true; } } // Eventos do WriteRandFile // Botão Gravar // Se este objecto já está criado if (alterar!=null) { // Se foi carregado o botão para gravar as alterações if (e.target==alterar.wrfButton11) { showStatus("Espere...Adicionando Utilizador"); alterar.addRecord(); cardManager.show(ivjPanel1,"begin"); showStatus("Utilizador Adicionado"); return true; } // Botão cancelar if (e.target==alterar.wrfButton1) { // Se for carregado ignora as alterações e volta ao menu principal showStatus("Espere...Saindo do Ficheiro de Passwords"); System.out.println("Sair do WriteRandFile"); cardManager.show(ivjPanel1,"begin"); showStatus("Menu de Entrada"); return true; } } // Eventos do Tabela // Botão Gravar // Apenas se já existe if (table!=null) { // Se foi carregado o botão gravar if (e.target==table.ta1Button[0]) { showStatus("Espere...Gravando a Tabela"); pág. 34 WEB Agenda- Sistemas Periciais pág. 35 // Grava table.save(); cardManager.show(ivjPanel1,"begin"); showStatus("Tabela Gravada"); return true; } // Se foi carregado em cancelar volta ao menu principal if (e.target==table.ta1Button[1]) { showStatus("Espere...Saindo da Criação da Tabela"); System.out.println("Saiu de Tabela"); cardManager.show(ivjPanel1,"begin"); showStatus("Menu Principal"); return true; } } // Eventos do ReadRandFile // Botão Seleccionar todos // Selecciona todos os utilizadores if (e.target==user.rrfButton1) { System.out.println("Cheguei"); for (int i=0;i<user.number_of_users;i++) user.rrfList1.select(i); showStatus("Seleccionou todos os Utilizadores"); return true; } // Deselecciona todos os utilizadores if (e.target==user.rrfButton11) { for (int i=0;i<user.number_of_users;i++) user.rrfList1.deselect(i); showStatus("Desactivou todos os Utilizadores"); return true; } // Carregou em continuar if (e.target==user.rrfButton12) { showStatus("Espere...Carregando a sua Agenda"); // Conta o nº de utilizadores seleccionados user.number_item_selected=user.rrfList1.getSelectedIndexes(); // Cria uma lista de utilizadores seleccionados user.names_selected=user.rrfList1.getSelectedItems(); // Cria uma lista dos Portos de comunicação user.ports_selected=new int[user.number_item_selected.length]; // Cria uma lista dos Emails seleccionados user.ipadresses_selected=new String[user.number_item_selected.length]; // Cria uma lista dos URL seleccionados user.emails_selected=new String[user.number_item_selected.length]; Integer number; number=new Integer(user.actual_user.substring(4,8)); for (int i=0;i<user.number_item_selected.length;i++) { if (i<number.intValue()) { user.ports_selected[i]=user.ports[user.number_item_selected[i]]; user.ipadresses_selected[i]=new String (user.ipadresses[user.number_item_selected[i]]); user.emails_selected[i]=new String (user.emails[user.number_item_selected[i]]); pág. 36 WEB Agenda- Sistemas Periciais } else { user.ports_selected[i]=user.ports[user.number_item_selected[i]+1]; user.ipadresses_selected[i]=new String (user.ipadresses[user.number_item_selected[i]+1]); user.emails_selected[i]=new String (user.emails[user.number_item_selected[i]+1]); } } // Lê o ficheiro de agenda ReadSeqFile file; file=new ReadSeqFile(); file.open_file(user.actual_user); file.readRecord(); file.cleanup(); // Mostra a agenda tabela2=new Tabela2(file.records,user.names_selected,user.ipadresses_selected, user.emails_selected,user.ports_selected,user.number_item_selected,user.actual_user); ivjPanel1.add("tabela2",tabela2); cardManager.show(ivjPanel1,"tabela2"); return true; } // Carregou em cancelar if (e.target==user.rrfButton13) { // Volta ao Menu principal showStatus("Voltando ao Menu de Entrada"); System.out.println("Sai do ReadRandFile"); cardManager.show(ivjPanel1,"begin"); showStatus("Menu de Entrada"); return true; } // Eventos da Tabela 2 // Botão Marcar if (e.target==tabela2.ta2Button[0]) { // Cria o Ecran de Marcação showStatus("Espere...Carregando o Ecran de Marcação de Reunião"); marcacao=new Marcacao(tabela2.registers,tabela2.names_selected, tabela2.ipadresses_selected,tabela2.emails_selected,tabela2.ports_selected, tabela2.number_item_selected,tabela2.actual_user); ivjPanel1.add("marcacao",marcacao); cardManager.show(ivjPanel1,"marcacao"); showStatus("Ecran de Marcação de Reunião carregado"); return true; } // Botão Editar pág. 37 WEB Agenda- Sistemas Periciais if (e.target==tabela2.ta2Button[1]) { showStatus("Espere...Carregando Criação da Agenda"); // Se a tabela de edição ainda não existe cria-a if (table==null) { table=new Tabela(tabela2.actual_user); ivjPanel1.add("table",table); cardManager.show(ivjPanel1,"table"); showStatus("Criação da Agenda carregada"); } // Se já existe, mostra existente else cardManager.show(ivjPanel1,"table"); showStatus("Criação da Agenda carregada"); return true; } // Futuro menu de Ajuda if (e.target==tabela2.ta2Button[2]) { showStatus("Espere... Carregando a ajuda"); System.out.println("Botão de Ajuda"); showStatus("Ajuda carregada"); return true; } // Carregou em Cancelar if (e.target==tabela2.ta2Button[3]) { // Volta ao Ecran de Entrada showStatus("Espere...Voltando ao Menu de Entrada"); System.out.println("Saí de Tabela2"); cardManager.show(ivjPanel1,"begin"); showStatus("Menu de Entrada"); return true; } // Eventos de Marcação //Botão iniciar int j=0; if (e.target==marcacao.mcjButton[0]) { // Desactiva os 3 botões marcacao.mcjButton[0].disable(); marcacao.mcjButton[1].disable(); marcacao.mcjButton[2].disable(); showStatus("Espere...Estabelecendo a Comunicação"); // Converte os espaços do Campo Assunto em "_" marcacao.talk=""; marcacao.talkaux=marcacao.ivjTextField.getText(); for (int i=1;i<=marcacao.talkaux.length();i++) { if (!marcacao.talkaux.substring(j,i).equals(null)) { if (marcacao.talkaux.substring(j,i).equals(" ")) marcacao.talk+="_"; else marcacao.talk+=marcacao.talkaux.substring(j,i); j=i; } } // Início da comunicação marcacao.initiation(); WEB Agenda- Sistemas Periciais showStatus("Fim da Comunicação"); // Activa o Botão fechar depois de terminada a comunicação marcacao.mcjButton[2].enable(); return true; } // Botão opções if (e.target==marcacao.mcjButton[1]) { showStatus("Espere...Abrindo opções"); // Carrega uma Frame de Opções marcacao.choose=new Options(); // Activa o botão de iniciar marcacao.mcjButton[0].enable(); showStatus("Menu de Opções"); return true; } // Botão Fechar if (e.target==marcacao.mcjButton[2]) { showStatus("Espere...Fechando o sistema e guardando Informação"); // Faz as alterações nos Ficheiros de cada utilizador try { marcacao.finish(); } catch( NullPointerException h) { System.out.println("Aconteceu um Excepção em Marcação"); System.exit(0); } System.exit(0); return true; } } return true; } // Método que permite definir as propriedades do Panel private Panel getPanel1() { if (ivjPanel1 == null) { // Fundo Branco, tamanho,altura,localização (x,y) try { ivjPanel1 = new java.awt.Panel(); ivjPanel1.setName("Panel1"); ivjPanel1.setBackground(java.awt.Color.white); ivjPanel1.setBounds(0, 0, 600, 600); } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); } }; return ivjPanel1; } pág. 38 WEB Agenda- Sistemas Periciais pág. 39 // Método que trata das excepções dos componentes do Ecran private void handleException(Throwable exception) { System.out.println("--------- UNCAUGHT EXCEPTION ---------"); } // Método que faz as inicializações do Applet public void init() { super.init(); begin=null; try { setName("Panel1"); setLayout(null); setSize(635, 613); // Cria o interface password e junta-o ao "baralho" password=new Password(); cardManager=new CardLayout(); // Cria o Panel getPanel1(); ivjPanel1.setLayout(cardManager); ivjPanel1.add("password",password); add(ivjPanel1); cardManager.show(ivjPanel1,"password"); } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); } } } 2.2 Classe Password Esta classe apresenta um ecrán de entrada de login e password e tem como função verificar a validade do username e da password introduzida. Se a password for verdadeira chama o menu principal; senão lança para o ecrã uma mensagem de erro. import java.awt.*; import java.io.*; import java.net.*; import java.applet.Applet; public class Password extends Panel{ // Declaração das variáveis java.awt.Button pajButton1 = null; java.awt.Button pajButton11 = null; private java.awt.Label ivjLabel1 = null; private java.awt.Label ivjLabel11 = null; private java.awt.Panel ivjPanel1 = null; private java.awt.ScrollPane ivjScrollPane1 = null; private java.awt.TextField ivjTextField1 = null; private java.awt.TextField ivjTextField11 = null; WEB Agenda- Sistemas Periciais private java.awt.Canvas ivjCanvas1; private Image animation; private Graphics g; Record data; RandomAccessFile input; boolean moreRecords; String user,pass; // Constructor public Password() { URL url; url=null; // Cria um URL para a imagem try { url=new URL("http://jinks.fe.up.pt/~fjorge/aluquete.jpg"); } catch (MalformedURLException e) { System.out.println("Imagem não encontrada"); } // Carrega a imagem animation=Toolkit.getDefaultToolkit().getImage(url); initialize(); } // Definição das características do botão 1 private java.awt.Button getButton1() { if (pajButton1 == null) { try { pajButton1 = new java.awt.Button(); pajButton1.setName("Button1"); pajButton1.setFont(new java.awt.Font("dialog", 0, 11)); pajButton1.setBounds(376, 265, 80, 22); pajButton1.setLabel("Submeter"); } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); } }; return pajButton1; } // Definição das características do botão 2 private java.awt.Button getButton11() { if (pajButton11 == null) { try { pajButton11 = new java.awt.Button(); pajButton11.setName("Button11"); pajButton11.setBounds(376, 315, 80, 22); pajButton11.setFont(new java.awt.Font("dialog", 0, 11)); pajButton11.setLabel("Cancelar"); } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); } }; return pajButton11; pág. 40 WEB Agenda- Sistemas Periciais } // Definição das características do Panel e adição dos Componentes gráficos ao Ecran private void getFrame1() { setLayout(null); setBounds(37, 100, 10, 10); add(getButton1(), getButton1().getName()); add(getButton11(), getButton11().getName()); } // Definição das características do label 1(Username) private java.awt.Label getLabel1() { if (ivjLabel1 == null) { try { ivjLabel1 = new java.awt.Label(); ivjLabel1.setName("Label1"); ivjLabel1.setFont(new java.awt.Font("dialog", 1, 12)); ivjLabel1.setText("Username"); ivjLabel1.reshape(140, 265, 76, 29); } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); } }; return ivjLabel1; } // Definição das características do label2(Password) private java.awt.Label getLabel11() { if (ivjLabel11 == null) { try { ivjLabel11 = new java.awt.Label(); ivjLabel11.setName("Label11"); ivjLabel11.setFont(new java.awt.Font("dialog", 1, 12)); ivjLabel11.setText("Password"); ivjLabel11.reshape(142, 315, 76, 29); } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); } }; return ivjLabel11; } // Definição das características do campo de introdução de Username private java.awt.TextField getTextField1() { if (ivjTextField1 == null) { try { ivjTextField1 = new java.awt.TextField(); ivjTextField1.setName("TextField1"); ivjTextField1.setBackground(java.awt.SystemColor.activeCaptionText); ivjTextField1.reshape(229, 265, 107, 24); } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); } }; return ivjTextField1; } pág. 41 WEB Agenda- Sistemas Periciais // Definição das características do campo de Introdução de Password private java.awt.TextField getTextField11() { if (ivjTextField11 == null) { try { ivjTextField11 = new java.awt.TextField(); ivjTextField11.setName("TextField11"); ivjTextField11.setBackground(java.awt.SystemColor.activeCaptionText); ivjTextField11.reshape(229,315, 107, 24); ivjTextField11.setEchoCharacter('*'); } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); } }; return ivjTextField11; } private void handleException(Throwable exception) { System.out.println("--------- UNCAUGHT EXCEPTION ---------"); } // Método de Inicialização public void init() { initialize(); } private void initialize() { getFrame1(); // Adição ao Ecrán das Label e dos Campos de Introdução de Dados add(getLabel1(), getLabel1().getName()); add(getTextField1(), getTextField1().getName()); add(getLabel11(), getLabel11().getName()); add(getTextField11(), getTextField11().getName()); repaint(); } // Desenho da imagem no Ecrán public void paint( Graphics t) { t.drawImage(animation,137,160,this); } // Método que permite a validação da Password public boolean password_Validation( ) { // Declaração das Variáveis int aux; Integer pointer; DataInputStream input; URL url; pág. 42 WEB Agenda- Sistemas Periciais pág. 43 url=null; boolean result; result=false; String text; String pa; input=null; text=""; pass=""; try { try { // Abre o ficheiro de Passwords user=""; try { url=new URL("http://jinks.fe.up.pt/~fjorge/password.dat"); } catch (MalformedURLException e) { System.out.println("Erro no URL"); } try { // Abre uma Stream de Leitura para o ficheiro de passwords InputStream j=url.openStream(); input=new DataInputStream(j); // Lê o username e a password introduzida pelo utilizador user=ivjTextField1.getText(); pass=ivjTextField11.getText(); } catch (IOException e) { System.err.println("O ficheiro não foi aberto correctamente\n"+e.toString()); } // Posiciona o apontador do ficheiro para o campo pretendido // Se o tamanho do username é 8 então continua senão diz que é inválido if (user.length()==8) { pointer=new Integer(user.substring(4,8)); try{ for (int i=0;i<=pointer.intValue();i++) text=input.readLine(); } catch (IOException e) { System.err.println("O ficheiro não foi aberto correctamente\n"+e.toString()); } // Lê o registo do ficheiro // Separa os campos da linha lida detectando os "+" aux=text.indexOf("+",9); WEB Agenda- Sistemas Periciais pág. 44 // Se a password daquele username está correcta retorna verdadeiro if (text.substring(9,aux).equals(pass)) result=true; // Senão diz que a password não está correcta else { Error_handler error; error=new Error_handler("A Password não está correcta.","Introduza a Password correcta!"); } } catch (NullPointerException e) { Error_handler error; error=new Error_handler("O Username introduzido não é válido","Introduza o Username correcto!"); } } // Se o username não está correcto lança mensagem de erro para o ecran else { Error_handler error; error=new Error_handler("O Username introduzido não é válido","Introduza o Username correcto!"); } } catch (StringIndexOutOfBoundsException e) { Error_handler error; error=new Error_handler("O Username introduzido não é válido","Introduza o Username correcto!"); } } catch (NumberFormatException e) { Error_handler error; error=new Error_handler("O Username introduzido não é válido","Introduza o Username correcto!"); } // Retorna a validade da Password return result; } } 2.3 Classe Entry Esta classe representa o menu de entrada do sistema onde podemos aceder à agenda pessoal, ou marcar uma reunião, ou alterar o ficheiro de passwords no caso de ser o superutilizador. Como entradas recebe o username do utilizador WEB Agenda- Sistemas Periciais pág. 45 actual e a informação se este é ou não o superutilizador. Segue-se a listagem deste objecto. import java.awt.*; import java.net.*; public class Entry extends Panel{ // declaração das variáveis java.awt.Button etjButton1 = null; java.awt.Button etjButton11 = null; java.awt.Button etjButton12 = null; java.awt.Button etjButton13; private java.awt.Panel ivjPanel1 = null; private Image animationB; private Image animationE; private Image animationM; private Image animationV; private Image animationI; private Image animationN; private Image animationD; private Image animationO; private Graphics g; boolean superuser=false; String actual_user; // Constructor public Entry(boolean su,String us) { super(); URL b,e,m,v,i,n,d,o; b=e=m=v=i=n=d=o=null; // Criação dos URL's onde se encontram as figuras try { b=new URL("http://jinks.fe.up.pt/~fjorge/b.gif"); e=new URL("http://jinks.fe.up.pt/~fjorge/e.gif"); m=new URL("http://jinks.fe.up.pt/~fjorge/m.gif"); v=new URL("http://jinks.fe.up.pt/~fjorge/v.gif"); i=new URL("http://jinks.fe.up.pt/~fjorge/i.gif"); n=new URL("http://jinks.fe.up.pt/~fjorge/n.gif"); d=new URL("http://jinks.fe.up.pt/~fjorge/d.gif"); o=new URL("http://jinks.fe.up.pt/~fjorge/o.gif"); } catch (MalformedURLException g) { System.out.println("Imagem não encontrada"); } // Carrega as imagens animationB=Toolkit.getDefaultToolkit().getImage(b); animationE=Toolkit.getDefaultToolkit().getImage(e); animationM=Toolkit.getDefaultToolkit().getImage(m); animationV=Toolkit.getDefaultToolkit().getImage(v); animationI=Toolkit.getDefaultToolkit().getImage(i); animationN=Toolkit.getDefaultToolkit().getImage(n); animationD=Toolkit.getDefaultToolkit().getImage(d); animationO=Toolkit.getDefaultToolkit().getImage(o); superuser=su; WEB Agenda- Sistemas Periciais actual_user=us; // Chama a inicialização initialize(); } // Método que define as características do botão 1 private java.awt.Button getButton1() { if (etjButton1 == null) { try { etjButton1 = new java.awt.Button(); etjButton1.setName("Button1"); etjButton1.setFont(new java.awt.Font("dialog", 0, 11)); etjButton1.setBounds(420, 237, 112, 25); etjButton1.setLabel("Entrar"); } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); } }; return etjButton1; } // Método que define as características do botão 2 private java.awt.Button getButton11() { if (etjButton11 == null) { try { etjButton11 = new java.awt.Button(); etjButton11.setName("Button11"); etjButton11.setFont(new java.awt.Font("dialog", 0, 11)); etjButton11.setBounds(420, 274, 113, 25); // Se for o utilizador faz a activação do botão if (!superuser) etjButton11.disable(); etjButton11.setLabel("Ficheiro Passwords"); } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); } }; return etjButton11; } // Método que define as características do botão 3 private java.awt.Button getButton12() { if (etjButton12 == null) { try { etjButton12 = new java.awt.Button(); etjButton12.setName("Button12"); etjButton12.setFont(new java.awt.Font("dialog", 0, 11)); etjButton12.setBounds(420, 310, 113, 24); etjButton12.setLabel("Sair"); } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); } }; return etjButton12; } // Método que define as características do Panel private void getFrame1() { pág. 46 WEB Agenda- Sistemas Periciais pág. 47 setLayout(null); setBounds(0, 0, 430, 240); // Adiciona os botões ao Panel add(getButton1(), getButton1().getName()); add(getButton11(), getButton11().getName()); add(getButton12(), getButton12().getName()); } // Método que trata as Excepções dos Componentes do Ecran private void handleException(Throwable exception) { System.out.println("--------- UNCAUGHT EXCEPTION ---------"); } // Inicialização private void initialize() { // Chama a definição do Panel getFrame1(); // Acrescenta o botão 3 etjButton13 = new java.awt.Button(); etjButton13.setName("Button13"); etjButton13.setFont(new java.awt.Font("dialog", 0, 11)); etjButton13.setBounds(420, 200, 112, 25); etjButton13.setLabel("Agenda Pessoal"); add(etjButton13); show(); } // Desenha as imagens no Ecrán public void paint( Graphics t) { t.drawImage(animationB,120,160,this); t.drawImage(animationE,190,160,this); t.drawImage(animationM,255,160,this); t.drawImage(animationV,70,255,this); t.drawImage(animationI,135,255,this); t.drawImage(animationN,187,255,this); t.drawImage(animationD,255,255,this); t.drawImage(animationO,320,255,this); } } 2.4 Classe Tabela 2 Este objecto encarrega-se de colocar a agenda pessoal no ecrã. Este objecto tem 2 constructores. O primeiro é chamado quando do menu principal escolhemos a opção "Agenda Pessoal". O segundo é chamado depois da escolha de utilizadores e antes da marcação. Este possui mais um botão de ajuda. Ambos recebem como parâmetros de entrada uma lista de preferências do respectivo utilizador, o username do utilizador, uma lista com os nomes dos outro utilizadores, uma lista com os emails dos utilizadores, uma lista com os portos dos utilizadores, uma lista com os URL's dos utilizadores e uma lista com os números dos utilizadores. Segue-se a listagem desta classe. import java.applet.Applet; WEB Agenda- Sistemas Periciais pág. 48 import java.awt.*; import java.awt.event.*; public class Tabela2 extends Panel{ // Declaração das Variáveis private Label title; private Special_Label ivjLabel[][]; private TextField ivjField[] ; Button ta2Button[]; private Panel ivjPanel[]; private Canvas ivjCanvas,ivjCanvas2; private String week_days[]={"Segunda"," Terça"," Quarta"," Quinta"," Sexta"}; private String hours[]={" 8h00m"," 9h00m"," 10h00m"," 11h00m"," 14h00m"," 15h00m"," 16h00m"," 17h00m"," 18h00m"," 19h00m"}; private ReadSeqFile file; private double preferences[][]; private LinkedList list; private Tabela table; private Marcacao table1; Instance registers[][]; Window ivjWindow1; private java.awt.Button Button1 = null; private java.awt.Frame Frame1 = null; String ipadresses_selected[]; String names_selected[]; String emails_selected[]; int ports_selected[]; int number_item_selected[]; ActionListener al; ReadSeqFile1 read_reunion; String actual_user; // Constructor 1 public Tabela2(Instance regist[][],String ns[],String ips[],String ems[],int ps[],int ins[],String us) { super(); ipadresses_selected=ips; names_selected=ns; emails_selected=ems; ports_selected=ps; number_item_selected=ins; actual_user=us; // inicialização de assuntos de reunião read_reunion=new ReadSeqFile1(); read_reunion.open_file(actual_user); read_reunion.readRecord(); ReadSeqFile file1; file1=new ReadSeqFile(); // Características do Panel setName("Teste"); setLayout(null); setSize(600, 516); // Criação de algumas variáveis ivjLabel=new Special_Label[5][10]; pág. 49 WEB Agenda- Sistemas Periciais ivjField=new TextField[15]; ivjPanel=new Panel[2]; ta2Button=new Button[4]; preferences=new double[5][10]; list=new LinkedList(); registers=regist; //Colocagco das Labels for (int i=0;i<5;i++) { for (int j=0;j<10;j++) { // Criação de labels especiais para permitir visualização de assunto ivjLabel[i][j] = new Special_Label(read_reunion.records); ivjLabel[i][j].setFont(new java.awt.Font("sansserif", 1, 13)); ivjLabel[i][j].setAlignment(java.awt.Label.CENTER); ivjLabel[i][j].setText(String.valueOf(registers[i][j].getdisp())); // Inserção das preferências na lista list.insert(registers[i][j]); // Se não existe reunião no dia I à hora j a cor da label é azul claro if (read_reunion.records[i][j].talkabout.equals("0")) ivjLabel[i][j].setBackground(new java.awt.Color(157, 208, 255)); // Se existe é azul escuro else ivjLabel[i][j].setBackground(new java.awt.Color(000, 100, 255)); ivjLabel[i][j].setBounds(93+i*73, 139+j*26, 70, 25); add(ivjLabel[i][j]); } } // Definição do título title = new java.awt.Label(); title.setName("Label1"); title.setAlignment(java.awt.Label.CENTER); title.setFont(new java.awt.Font("dialog",0, 14)); title.setText("Agenda de Preferências(classificadas entre 0 e 1)"); title.setBounds(73, 410, 402, 24); add(title); //Colocação das dias for (int i=0;i<5;i++) { ivjField[i] = new java.awt.TextField(); ivjField[i].setFont(new java.awt.Font("helvetica", 0, 13)); ivjField[i].setText(week_days[i]); ivjField[i].setBackground(new java.awt.Color(255, 255, 218)); ivjField[i].setBounds(93+i*73, 114, 70, 25); add(ivjField[i]); } // Colocação dos dias for (int i=5;i<15;i++) { ivjField[i] = new java.awt.TextField(); ivjField[i].setEditable(false); ivjField[i].setFont(new java.awt.Font("helvetica", 0, 13)); WEB Agenda- Sistemas Periciais ivjField[i].setText(hours[i-5]); ivjField[i].setBackground(new java.awt.Color(255, 255, 218)); ivjField[i].setBounds(23, 139+(i-5)*26, 70, 25); add(ivjField[i]); } // Colocação dos Botões //Botão 1 ta2Button[0] = new java.awt.Button(); ta2Button[0].setName("Button1"); ta2Button[0].setBounds(495, 200, 73, 25); ta2Button[0].setLabel("Marcar"); add(ta2Button[0]); // Botão 2 ta2Button[1] = new java.awt.Button(); ta2Button[1].setName("Button1"); ta2Button[1].setBounds(495, 235, 73, 25); ta2Button[1].setLabel("Editar"); add(ta2Button[1]); // Botão 3 ta2Button[2] = new java.awt.Button(); ta2Button[2].setName("Button1"); ta2Button[2].setBounds(495, 270, 73, 25); ta2Button[2].setLabel("Ajuda"); add(ta2Button[2]); // Botão 4 ta2Button[3] = new java.awt.Button(); ta2Button[3].setName("Button1"); ta2Button[3].setBounds(495,305, 73, 25); ta2Button[3].setLabel("Fechar"); add(ta2Button[3]); show(); } // Constructor 2 public Tabela2(Instance r[][],String us) { super(); actual_user=us; // inicialização de assuntos de reunião read_reunion=new ReadSeqFile1(); read_reunion.open_file(actual_user); read_reunion.readRecord(); pág. 50 pág. 51 WEB Agenda- Sistemas Periciais // Definição das caracteristicas do Panel setName("Teste"); setLayout(null); setSize(600, 516); // Criação de Variáveis ivjLabel=new Special_Label[5][10]; ivjField=new TextField[15]; ta2Button=new Button[3]; preferences=new double[5][10]; list=new LinkedList(); registers=r; //Colocação das Labels for (int i=0;i<5;i++) { for (int j=0;j<10;j++) { // Colocação de Labels especiais que permitem visualizar o assunto ivjLabel[i][j] = new Special_Label(read_reunion.records); ivjLabel[i][j].setFont(new java.awt.Font("sansserif", 1, 13)); ivjLabel[i][j].setAlignment(java.awt.Label.CENTER); ivjLabel[i][j].setText(String.valueOf(registers[i][j].getdisp())); list.insert(registers[i][j]); // Se não existe uma reunião no dia i à hora j então fundo azul claro if (read_reunion.records[i][j].talkabout.equals("0")) ivjLabel[i][j].setBackground(new java.awt.Color(157, 208, 255)); // Se existe o fundo é azul escuro else ivjLabel[i][j].setBackground(new java.awt.Color(000, 100, 255)); ivjLabel[i][j].setBounds(93+i*73, 139+j*26, 70, 25); add(ivjLabel[i][j]); } } // Definição do título title = new java.awt.Label(); title.setName("Label1"); title.setAlignment(java.awt.Label.CENTER); title.setFont(new java.awt.Font("dialog",0, 14)); title.setText("Agenda de Preferências(classificadas entre 0 e 1)"); title.setBounds(76, 410, 402, 24); add(title); //Colocação dos dias for (int i=0;i<5;i++) { ivjField[i] = new java.awt.TextField(); ivjField[i].setFont(new java.awt.Font("helvetica", 0, 13)); ivjField[i].setText(week_days[i]); ivjField[i].setBackground(new java.awt.Color(255, 255, 218)); ivjField[i].setBounds(93+i*73, 114, 70, 25); add(ivjField[i]); WEB Agenda- Sistemas Periciais pág. 52 } // Colocação das horas for (int i=5;i<15;i++) { ivjField[i] = new java.awt.TextField(); ivjField[i].setEditable(false); ivjField[i].setFont(new java.awt.Font("helvetica", 0, 13)); ivjField[i].setText(hours[i-5]); ivjField[i].setBackground(new java.awt.Color(255, 255, 218)); ivjField[i].setBounds(23, 139+(i-5)*26, 70, 25); add(ivjField[i]); } // Colocação dos Botões //Botão 1 ta2Button[0] = new java.awt.Button(); ta2Button[0].setName("Button1"); ta2Button[0].setBounds(495, 204, 73, 25); ta2Button[0].setLabel("Marcar"); add(ta2Button[0]); // Botão 2 ta2Button[1] = new java.awt.Button(); ta2Button[1].setName("Button1"); ta2Button[1].setBounds(495, 253, 73, 25); ta2Button[1].setLabel("Editar"); add(ta2Button[1]); // Botão 3 ta2Button[2] = new java.awt.Button(); ta2Button[2].setName("Button1"); ta2Button[2].setBounds(495, 301, 73, 25); ta2Button[2].setLabel("Cancelar"); add(ta2Button[2]); } // Colocação do fundo public void paint (Graphics g ) { g.setColor(new java.awt.Color(000, 100, 255)); g.fill3DRect(488,194,86,142,true); } } 2.5 Classe Tabela Esta classe tem como objectivo permitir ao utilizador criar a sua agenda, ou seja, quando o utilizador carrega em editar a agenda na classe Tabela 2, vem parar WEB Agenda- Sistemas Periciais pág. 53 nesta classe. Esta recebe como parâmetros o utilizador actual. Segue-se a listagem do código desta classe. import java.applet.*; import java.awt.*; import java.lang.Exception; public class Tabela extends Panel { // Declaração das variáveis private Label person; Button ta1Button[]; private Checkbox ivjCheckbox[][]; private Choice ivjChoice[][]; private Canvas ivjCanvas1; private Label ivjLabel[]; private CreateSeqFile file; private String preferences[]={"Segunda de Manhã","Terça de Manhã", "Quarta de Manhã","Quinta de Manhã", "Sexta de Manhã","Segunda de Tarde", "Terça de Tarde","Quarta de Tarde", "Quinta de Tarde","Sexta de Tarde"}; private String week_days[]={"Segunda","Terça","Quarta","Quinta", "Sexta"}; private String hours[]={"8h00m","9h00m","10h00m","11h00m","14h00m", "15h00m","16h00m","17h00m","18h00m","19h00m"}; private CreateSeqFile file1; String actual_user; // Constructor de Tabela public Tabela(String us) { super(); // Inicialização das variáveis actual_user=us; int count=0; ta1Button=new Button[2]; ivjCheckbox=new Checkbox[2][5]; ivjChoice=new Choice[5][10]; ivjLabel=new Label[15]; Instance color[][]; file=new CreateSeqFile(); file1=new CreateSeqFile(); color=new Instance[5][10]; setLayout(null); setSize(600, 520); //Colocação das CheckBoxes for (int i=0;i<2;i++) { for (int j=0;j<5;j++) { ivjCheckbox[i][j] = new java.awt.Checkbox(); ivjCheckbox[i][j].setFont(new java.awt.Font("Dialog", 0, 12)); ivjCheckbox[i][j].setBackground(new java.awt.Color(254, 254, 216)); ivjCheckbox[i][j].setBounds(93+i*164, 376+j*27, 125, 30); // Colocação do Texto referente a cada uma das Checkboxes ivjCheckbox[i][j].setLabel(preferences[count]); add(ivjCheckbox[i][j]); count+=1; } } WEB Agenda- Sistemas Periciais // Colocação dos Botões // Botão 1 ta1Button[0] = new java.awt.Button(); ta1Button[0].setBounds(434, 398, 77, 27); ta1Button[0].setLabel("Gravar"); add(ta1Button[0]); // Botão 2 ta1Button[1] = new java.awt.Button(); ta1Button[1].setBounds(434, 455, 77, 27); ta1Button[1].setLabel("Cancelar"); add(ta1Button[1]); // Colocação dos Componentes de Escolha for (int i=0;i<5;i++) { for (int j=0;j<10;j++) { ivjChoice[i][j] = new java.awt.Choice(); ivjChoice[i][j].setBackground(new java.awt.Color(154, 205, 252)); ivjChoice[i][j].setBounds(118+i*86, 81+j*23, 85, 26); ivjChoice[i][j].add("Livre"); ivjChoice[i][j].add("Indiferente"); ivjChoice[i][j].add("Ocupado"); add(ivjChoice[i][j]); } } // Colocação das Labels person = new java.awt.Label(); person.setName("Label1"); person.setAlignment(java.awt.Label.CENTER); person.setFont(new java.awt.Font("dialog", 1, 13)); person.setText("Seleccione as suas Preferências para Personalizar: "); person.setBackground(new Color(254, 254, 216)); person.setBounds(73, 345, 370, 24); add(person); // Colocação dos dias for (int i=0;i<5;i++) { ivjLabel[i] = new java.awt.Label(); ivjLabel[i].setFont(new java.awt.Font("helvetica", 1, 12)); ivjLabel[i].setAlignment(java.awt.Label.CENTER); ivjLabel[i].setText(week_days[i]); ivjLabel[i].setBounds(118+i*88, 51, 81, 30); add(ivjLabel[i]); } // Colocação das horas for (int i=5;i<15;i++) { ivjLabel[i] = new java.awt.Label(); ivjLabel[i].setFont(new java.awt.Font("helvetica", 1, 12)); pág. 54 pág. 55 WEB Agenda- Sistemas Periciais ivjLabel[i].setAlignment(java.awt.Label.CENTER); ivjLabel[i].setText(hours[i-5]); ivjLabel[i].setBounds(37, 76+(i-5)*23, 81, 30); add(ivjLabel[i]); } show(); } // Colocação do Fundo public void paint (Graphics g ) { g.setColor(new Color(254, 254, 216)); g.fill3DRect(55,339,489,180,true); } // Método que efectua a gravação da agenda public void save( ) { // Declaração das variáveis Instance days[][]; boolean r[]; days=new Instance[5][10]; r=new boolean[10]; int k=0; // Lê o estado das Checkboxes for (int j=0;j<5;j++) { for(int i=0;i<2;i++) { r[k]=ivjCheckbox[i][j].getState(); k+=1; } } // Cálculo das preferências associadas for (int i=0; i<5;i++) { for (int j=0; j<10; j++){ // Se encontrar livre a preferência é 1.0 if (ivjChoice[i][j].getSelectedItem().equals("Livre")) days[i][j]=new Instance(i,j,1); // Se encontrar ocupado a preferência é 0.0 if (ivjChoice[i][j].getSelectedItem().equals("Ocupado")) days[i][j]=new Instance(i,j,0); // Se encontrar indiferente a preferência pode ser 0.3 ou .07 if (ivjChoice[i][j].getSelectedItem().equals("Indiferente")) { switch (i) { case 0 : // No caso de segunda-feira // Se escolheu preferência de manhã if (r[0] & j<4) // a preferência é 0.7 e estamos // a avaliar até às 11h00 days[i][j]=new Instance(i,j,0.7); pág. 56 WEB Agenda- Sistemas Periciais // Se escolheu preferência de tarde else if (r[1] & j>=4) // a preferência é 0.7 e estamos // a avaliar a partir das 14h00 days[i][j]=new Instance(i,j,0.7); // Senão a preferência é 0.3 else days[i][j]=new Instance(i,j,0.3); break; case 1 : // No caso de terça-feira // Se escolheu preferência de manhã if (r[2] & j<4) // a preferência é 0.7 e estamos // a avaliar até às 11h00 days[i][j]=new Instance(i,j,0.7); // Se escolheu preferência de tarde else if (r[3] & j>=4) // a preferência é 0.7 e estamos // a avaliar a partir das 14h00 days[i][j]=new Instance(i,j,0.7); // Senão a preferência é 0.3 else days[i][j]=new Instance(i,j,0.3); break; case 2 : // No caso de quarta-feira // Se escolheu preferência de manhã if (r[4] & j<4) // a preferência é 0.7 e estamos // a avaliar até às 11h00 days[i][j]=new Instance(i,j,0.7); // Se escolheu preferência de tarde else if (r[5] & j>=4) days[i][j]=new Instance(i,j,0.7); // a preferência é 0.7 e estamos // a avaliar a partir das 14h00 // Senão a preferência é 0.3 else days[i][j]=new Instance(i,j,0.3); break; case 3 : // No caso de quinta-feira // Se escolheu preferência de manhã if (r[6] & j<4) // a preferência é 0.7 e estamos // a avaliar até às 11h00 days[i][j]=new Instance(i,j,0.7); // Se escolheu preferência de tarde else if (r[7] & j>=4) // a preferência é 0.7 e estamos // a avaliar a partir das 14h00 days[i][j]=new Instance(i,j,0.7); // Senão a preferência é 0.3 else days[i][j]=new Instance(i,j,0.3); break; case 4 : // No caso de sexta-feira pág. 57 WEB Agenda- Sistemas Periciais // Se escolheu preferência de manhã if (r[8] & j<4) // a preferência é 0.7 e estamos // a avaliar até às 11h00 days[i][j]=new Instance(i,j,0.7); // Se escolheu preferência de tarde else if (r[9] & j>=4) // a preferência é 0.7 e estamos // a avaliar a partir das 14h00 days[i][j]=new Instance(i,j,0.7); // Senão a preferência é 0.3 else days[i][j]=new Instance(i,j,0.3); break; } } } } // Gravar o registo file.addRecord(days,actual_user); } } 2.6 Classe WriteRandFile Esta classe tem como função acrescentar um novo utilizador ao ficheiro de passwords. Apenas pode ter acesso a esta classe o superutilizador (user0000). A classe lê os valores introduzidos pelo superutilizador e grava no ficheiro de passwords. Segue-se a listagem de código referente a esta classe. import java.awt.*; import java.io.*; import java.net.*; public class WriteRandFile extends Panel{ // Declaração das variáveis Button wrfButton1 = null; Button wrfButton11 = null; Integer p; private Label ivjLabel1 = null; private Label ivjLabel11 = null; private Label ivjLabel12 = null; private Label ivjLabel13 = null; private Label ivjLabel14 = null; private Label ivjLabel15 = null; private Label ivjLabel16 = null; private TextField ivjTextField1 = null; private TextField ivjTextField11 = null; private TextField ivjTextField12 = null; private TextField ivjTextField13 = null; private TextField ivjTextField14 = null; private TextField ivjTextField15 = null; private TextField ivjTextField16 = null; WEB Agenda- Sistemas Periciais Integer count; String us; // Constructor public WriteRandFile() { super(); int aux; // Vai ao ficheiro de passwords e encontra o último que foi introduzido us=findlast(); // Se já existe algum if (!us.equals("")) { // encontra o nº do utilizador count=new Integer(us.substring(4,8)); // Obtém o nº do novo utilizador aux=count.intValue()+1; us=String.valueOf(aux); // Constroi o novo username switch ( us.length() ) { // se o nº do novo utilizador é <10 case 1 : us="user000"+String.valueOf(aux); count=new Integer(aux); break; case 2 : // se o nº do novo utilizador é >10 e <100 us="user00"+String.valueOf(aux); count=new Integer(aux); break; case 3 : // se o nº do novo utilizador é >100 e <999 us="user0"+String.valueOf(aux); count=new Integer(aux); break; case 4: // se o nº do novo utilizador é >999 us="user"+String.valueOf(aux); count=new Integer(aux); break; } } // Senão cria o 1º utilizador (user0000) else { us="user0000"; count=new Integer("0"); } // Cria butão 1 wrfButton1 = new Button(); wrfButton1.setFont(new java.awt.Font("dialog", 0, 11)); wrfButton1.setBounds(199, 381, 85, 22); wrfButton1.setLabel("Acabar"); add(wrfButton1); // Cria botão 2 pág. 58 WEB Agenda- Sistemas Periciais pág. 59 wrfButton11 = new Button(); wrfButton11.setFont(new java.awt.Font("dialog", 0, 11)); wrfButton11.setBounds(357, 381, 85, 22); wrfButton11.setLabel("Adicionar"); add(wrfButton11); // Chama a inicialização initialize(); } // Método que permite adicionar o novo registo ao ficheiro public void addRecord ( ) { // Declaração de variáveis int aux; String usaux,pa,fi,la,ip,po,em; usaux=""; Integer number; URL url; InputStream input; DataInputStream dataInput; url=null; Instance temp[][]; temp=new Instance[5][10]; Reunion temp1[][]; temp1=new Reunion[5][10]; try { try { // lê o username us=ivjTextField1.getText(); // calcula o nº do utilizador number=new Integer(us.substring(4,8)); //lê a password pa=ivjTextField13.getText(); pa.substring(0,2); //lê o primeiro nome fi=ivjTextField11.getText(); fi.substring(0,2); //lê o último nome la=ivjTextField14.getText(); la.substring(0,2); //lê o email ip=ivjTextField12.getText(); ip.substring(0,2); // lê o porto po=ivjTextField15.getText(); p=new Integer(po); // lê o URL em=ivjTextField16.getText(); em.substring(0,2); // Cria um URL para o CGI de escrita try { url=new URL("http://jinks.fe.up.pt/cgi-bin/fjorge-cgi/password.pl?"+usaux+"+"+pa+"+"+fi+" + "+la+" +"+po+"+"+ip+"+"+em); } catch (MalformedURLException e) { System.out.println("Surgiu excepção no URL"); } WEB Agenda- Sistemas Periciais pág. 60 // Executa o CGI try { input=url.openStream(); dataInput=new DataInputStream(input); dataInput.close(); } catch(IOException e) { System.out.println("Ocorreu excepção na abertura da Stream"); } // É criado um ficheiro de agenda com todas as preferências a 1.0 para o novo utilizador for (int i=0;i<5;i++) { for (int j=0;j<10;j++) { temp[i][j]=new Instance(i,j,1.0); } } CreateSeqFile file; file=new CreateSeqFile(); file.addRecord(temp,usaux); // É criado um ficheiro de reuniões com todos os dias em branco para o novo utilizador for (int i=0;i<5;i++) { for (int j=0;j<10;j++) temp1[i][j]=new Reunion("0","0","0"); } CreateSeqFile1 file_create=new CreateSeqFile1(); file_create.addRecord(temp1,usaux); } // No caso de algum campo não estar preenchido manda uma mensagem de erro catch (StringIndexOutOfBoundsException e) { Error_handler error; error=new Error_handler("Um ou mais campos não estão preenchidos","É necessário preenchê-los!"); } } // No caso de algum dos campos ter tamanho excessivo manda uma mensagem de erro catch (ArrayIndexOutOfBoundsException e) { Error_handler error; error=new Error_handler("Um ou mais campos têm tamanho excessivo.","Retire alguns caracteres!"); } } // Método da classe que permite encontrar o último utilizador a ser introduzido public String findlast( ) { // Declaração de variáveis String text,textaux; text=""; textaux=""; WEB Agenda- Sistemas Periciais pág. 61 URL url; URL urlaux; url=null; int count; DataInputStream input; urlaux=null; // Criação de um URL para o ficheiro de passwords e para um URL para no caso de não existir // o ficheiro criar um try { url=new URL("http://jinks.fe.up.pt/~fjorge/password.dat"); urlaux=new URL ("http://jinks.fe.up.pt/cgi-bin/fjorge-cgi/touching.pl"); } catch (MalformedURLException e) { System.out.println("Erro no URL"); } try { // Execução do CGI de touching InputStream i=urlaux.openStream(); input=new DataInputStream(i); input.close(); // Abertura de uma Stream de leitura do ficheiro de passwords InputStream in=url.openStream(); input=new DataInputStream(in); // Leitura até encontrar o fim do ficheiro while ((text=input.readLine())!=null) textaux=text; input.close(); } catch (IOException e) { System.err.println("O ficheiro não foi aberto correctamente\n"+e.toString()); } // Se existe um utilizador envia o último try { us=textaux.substring(0,8); } // Senão envia uma string vazia catch (StringIndexOutOfBoundsException e) { us=""; } return us; } // Definição das características do Panel private void getFrame1() { setLayout(null); setBounds(256, 131, 484, 309); WEB Agenda- Sistemas Periciais // Adição das Labels e dos Campos add(getLabel1(), getLabel1().getName()); add(getLabel11(), getLabel11().getName()); add(getLabel12(), getLabel12().getName()); add(getLabel13(), getLabel13().getName()); add(getLabel14(), getLabel14().getName()); add(getLabel15(), getLabel15().getName()); add(getTextField1(), getTextField1().getName()); add(getTextField11(), getTextField11().getName()); add(getTextField12(), getTextField12().getName()); add(getTextField13(), getTextField13().getName()); add(getTextField14(), getTextField14().getName()); add(getTextField15(), getTextField15().getName()); add(getLabel16(), getLabel16().getName()); add(getTextField16(), getTextField16().getName()); } // Definição das características da Label 1 private Label getLabel1() { if (ivjLabel1 == null) { try { ivjLabel1 = new java.awt.Label(); ivjLabel1.setName("Label1"); ivjLabel1.setBackground(new Color(209,244,254)); ivjLabel1.setFont(new java.awt.Font("dialog", 0, 11)); ivjLabel1.setText("Username"); ivjLabel1.setBounds(99,174, 65, 26); } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); } }; return ivjLabel1; } // Definição das características da Label 2 private Label getLabel11() { if (ivjLabel11 == null) { try { ivjLabel11 = new java.awt.Label(); ivjLabel11.setName("Label11"); ivjLabel11.setBackground(new Color(209,244,254)); ivjLabel11.setFont(new java.awt.Font("dialog", 0, 11)); ivjLabel11.setText("Firstname"); ivjLabel11.setBounds(99, 224, 65, 26); } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); } }; return ivjLabel11; } // Definição das características da Label 3 private Label getLabel12() { if (ivjLabel12 == null) { try { ivjLabel12 = new java.awt.Label(); ivjLabel12.setName("Label12"); ivjLabel12.setBackground(new Color(209,244,254)); ivjLabel12.setFont(new java.awt.Font("dialog", 0, 11)); ivjLabel12.setText("Email"); ivjLabel12.setBounds(99, 274, 65, 26); pág. 62 WEB Agenda- Sistemas Periciais } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); } }; return ivjLabel12; } // Definição das características da Label 4 private Label getLabel13() { if (ivjLabel13 == null) { try { ivjLabel13 = new java.awt.Label(); ivjLabel13.setName("Label13"); ivjLabel13.setBackground(new Color(209,244,254)); ivjLabel13.setFont(new java.awt.Font("dialog", 0, 11)); ivjLabel13.setText("Password"); ivjLabel13.setBounds(329,174, 86, 26); } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); } }; return ivjLabel13; } // Definição das características da Label 5 private Label getLabel14() { if (ivjLabel14 == null) { try { ivjLabel14 = new java.awt.Label(); ivjLabel14.setName("Label14"); ivjLabel14.setBackground(new Color(209,244,254)); ivjLabel14.setFont(new java.awt.Font("dialog", 0, 11)); ivjLabel14.setText("Lastname"); ivjLabel14.setBounds(329, 224, 86, 26); } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); } }; return ivjLabel14; } // Definição das características da Label 6 private Label getLabel15() { if (ivjLabel15 == null) { try { ivjLabel15 = new java.awt.Label(); ivjLabel15.setName("Label15"); ivjLabel15.setBackground(new Color(209,244,254)); ivjLabel15.setFont(new java.awt.Font("dialog", 0, 11)); ivjLabel15.setText("Port Number"); ivjLabel15.setBounds(329, 274, 86, 26); } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); } }; return ivjLabel15; } // Definição das características da Label 7 pág. 63 WEB Agenda- Sistemas Periciais private Label getLabel16() { if (ivjLabel16 == null) { try { ivjLabel16 = new java.awt.Label(); ivjLabel16.setName("Label16"); ivjLabel16.setBackground(new Color(209,244,254)); ivjLabel16.setFont(new java.awt.Font("dialog", 0, 11)); ivjLabel16.setText("URL(cgi)"); ivjLabel16.setBounds(99, 324, 65, 26); } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); } }; return ivjLabel16; } // Definição das características do campo Username private TextField getTextField1() { if (ivjTextField1 == null) { try { ivjTextField1 = new java.awt.TextField(); ivjTextField1.setName("TextField1"); ivjTextField1.setText(us); ivjTextField1.setEditable(false); ivjTextField1.setBackground(java.awt.Color.white); ivjTextField1.setBounds(176,177, 103, 23); } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); } }; return ivjTextField1; } // Definição das características do campo Password private TextField getTextField11() { if (ivjTextField11 == null) { try { ivjTextField11 = new java.awt.TextField(); ivjTextField11.setName("TextField11"); ivjTextField11.setBackground(java.awt.Color.white); ivjTextField11.setBounds(176, 227, 103, 23); } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); } }; return ivjTextField11; } // Definição das características do campo Firstname private TextField getTextField12() { if (ivjTextField12 == null) { try { ivjTextField12 = new java.awt.TextField(); ivjTextField12.setName("TextField12"); ivjTextField12.setBackground(java.awt.Color.white); ivjTextField12.setBounds(176, 277, 103, 23); } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); pág. 64 WEB Agenda- Sistemas Periciais } }; return ivjTextField12; } // Definição das características do campo Lastname private TextField getTextField13() { if (ivjTextField13 == null) { try { ivjTextField13 = new java.awt.TextField(); ivjTextField13.setName("TextField13"); ivjTextField13.setEchoCharacter('*'); ivjTextField13.setBackground(java.awt.Color.white); ivjTextField13.setBounds(416, 177, 103, 23); } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); } }; return ivjTextField13; } // Definição das características do campo Email private TextField getTextField14() { if (ivjTextField14 == null) { try { ivjTextField14 = new java.awt.TextField(); ivjTextField14.setName("TextField14"); ivjTextField14.setBackground(java.awt.Color.white); ivjTextField14.setBounds(416, 227, 103, 23); } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); } }; return ivjTextField14; } // Definição das características do campo Port private TextField getTextField15() { if (ivjTextField15 == null) { try { ivjTextField15 = new java.awt.TextField(); ivjTextField15.setName("TextField15"); ivjTextField15.setText(String.valueOf(5001+count.intValue())); ivjTextField15.setEditable(false); ivjTextField15.setBackground(java.awt.Color.white); ivjTextField15.setBounds(416, 277, 103, 23); } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); } }; return ivjTextField15; } // Definição das características do campo URL(cgi) private TextField getTextField16() { if (ivjTextField16 == null) { try { ivjTextField16 = new java.awt.TextField(); pág. 65 WEB Agenda- Sistemas Periciais pág. 66 ivjTextField16.setName("TextField16"); ivjTextField16.setBackground(java.awt.Color.white); ivjTextField16.setBounds(176, 327, 343, 23); } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); } }; return ivjTextField16; } // Tratamento das excepções dos componentes private void handleException(Throwable exception) { System.out.println("--------- UNCAUGHT EXCEPTION ---------"); } // Inicialização private void initialize() { setLayout(null); setSize(426, 240); // Chama o método de definição do Panel getFrame1(); show(); } // Colocação do fundo no Ecran public void paint (Graphics g ) { g.setColor(new Color(209,244,254)); g.fill3DRect(63,132,489,309,true); } } 2.7 Classe ReadRandFile Esta classe encarrega-se de ler o ficheiro de utilizadores e colocá-los numa lista permitindo ao utilizador escolher aqueles com os quais pretende marcar a reunião. O constructor desta classe recebe como parâmetro de entrada o utilizador actual permitindo assim filtrar esse utilizador de modo a não aparecer na lista. Segue-se o código correspondente a esta classe. import java.io.*; import java.awt.*; import java.net.*; public class ReadRandFile extends Panel { // Declaração das variáveis java.awt.Button rrfButton1 = null; java.awt.Button rrfButton11 = null; Button rrfButton12; Button rrfButton13; private java.awt.Label ivjLabel1 = null; java.awt.List rrfList1 = null; String actual_user; String firstnames[]; String lastnames[]; String users[]; WEB Agenda- Sistemas Periciais String ipadresses[]; String passwords[]; int ports_selected[]; String emails_selected[]; String ipadresses_selected[]; String names_selected[]; int number_item_selected[]; int ports[]; String emails[]; RandomAccessFile input; Record data; boolean morepasswords=true; int number_of_users; private Image animation; private Graphics g; //Constructor public ReadRandFile(String us) { super(); // Criação dos objectos users=new String[200]; firstnames=new String[200]; lastnames=new String[200]; passwords=new String[200]; ipadresses=new String[200]; ports=new int[200]; emails=new String[200]; actual_user=us; // Chamar a inicialização initialize(); } // Permite fechar o ficheiro public void cleanup( ) { try { input.close(); } catch (IOException e) { System.err.println(e.toString()); System.exit(1); } } //Coloca os utilizadores na lista public void display_Users( ) { //Declaração das variáveis String aux,aux1; int length1,length2; length1=0; length2=0; //Colocação dos users na lista for (int i=0;i<(number_of_users);i++){ length1=0; length2=0; aux=firstnames[i]+" "+lastnames[i]; System.out.println(aux); if (!users[i].equals(actual_user)) rrfList1.addItem(aux); pág. 67 WEB Agenda- Sistemas Periciais } show(); } // Definição das características do botão 1 private java.awt.Button getButton1() { if (rrfButton1 == null) { try { rrfButton1 = new java.awt.Button(); rrfButton1.setName("Button1"); rrfButton1.setFont(new java.awt.Font("dialog", 0, 11)); rrfButton1.setBounds(372, 432, 114, 21); rrfButton1.setLabel("Seleccionar Todos"); } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); } }; return rrfButton1; } // Definição das características do botão 2 private java.awt.Button getButton11() { if (rrfButton11 == null) { try { rrfButton11 = new java.awt.Button(); rrfButton11.setName("Button11"); rrfButton11.setFont(new java.awt.Font("dialog", 0, 11)); rrfButton11.setBounds(372, 466, 114, 21); rrfButton11.setLabel("Desactivar Todos"); } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); } }; return rrfButton11; } // Definição das características do Panel private void getFrame1() { setName("Frame1"); setLayout(null); setBounds(28, 42, 501, 404); // Colocação dos botões, das labels e da lista add(getLabel1(), getLabel1().getName()); add(getButton1(), getButton1().getName()); add(getButton11(), getButton11().getName()); add(getList1(),getList1().getName()); } // Definição das características da Label private java.awt.Label getLabel1() { if (ivjLabel1 == null) { pág. 68 WEB Agenda- Sistemas Periciais try { ivjLabel1 = new java.awt.Label(); ivjLabel1.setName("Label1"); ivjLabel1.setBackground(new Color(209,244,254)); ivjLabel1.setFont(new java.awt.Font("dialog", 1, 12)); ivjLabel1.setText("Lista de Utilizadores"); ivjLabel1.setBounds(371, 101, 125, 30); } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); } }; return ivjLabel1; } // Definição das características da Lista private java.awt.List getList1() { if (rrfList1 == null) { try { rrfList1 = new java.awt.List(40,true); rrfList1.setName("List1"); rrfList1.setBackground(java.awt.Color.white); rrfList1.setBounds(341, 131, 174, 290); } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); } }; return rrfList1; } // Método que se encarrega de tratar das excepções dos componentes private void handleException(Throwable exception) { System.out.println("--------- UNCAUGHT EXCEPTION ---------"); } // Inicialização private void initialize() { //Chamar o método de definição do Panel getFrame1(); // Colocação de mais 2 botões // Botão 3 rrfButton12 = new java.awt.Button(); rrfButton12.setFont(new java.awt.Font("dialog", 0, 11)); rrfButton12.setBounds(92, 432, 75, 21); rrfButton12.setLabel("Continuar"); add(rrfButton12); // Botão 4 rrfButton13 = new java.awt.Button(); rrfButton13.setFont(new java.awt.Font("dialog", 0, 11)); rrfButton13.setBounds(222, 432, 75, 21); rrfButton13.setLabel("Cancelar"); add(rrfButton13); // Chama o método para ler o ficheiro de passwords e colocar as propriedades nos arrays put_properties_in_array(); // Chama o método para colocar o 1º e último nome na lista pág. 69 WEB Agenda- Sistemas Periciais display_Users(); show(); } // Colocar o fundo no ecran public void paint( Graphics t) { t.setColor(new Color(209,244,254)); t.fill3DRect(53,97, 501, 404,true); } public void put_properties_in_array ( ) { // Declaração das variáveis int i=0; DataInputStream input; URL url; url=null; String text; text=""; input=null; // Criação do URL para leitura do ficheiro try { url=new URL("http://jinks.fe.up.pt/~fjorge/password.dat"); } catch (MalformedURLException e) { System.out.println("Erro no URL"); } // Abertura de uma Stream de Leitura para o ficheiro de passwords try { InputStream j=url.openStream(); input=new DataInputStream(j); } catch (IOException e) { System.err.println("O ficheiro não foi aberto correctamente\n"+e.toString()); } Integer p; // Leitura do ficheiro de passwords linha a linha try { while ((text=input.readLine())!=null) { // Separação das várias características que estão juntas por "+" int index1=text.indexOf("+"); users[i]=text.substring(0,index1); int index2=text.indexOf("+",index1+1); passwords[i]=text.substring(index1+1,index2); index1=text.indexOf("+",index2+1); firstnames[i]=text.substring(index2+1,index1); index2=text.indexOf("+",index1+1); lastnames[i]=text.substring(index1+1,index2); pág. 70 WEB Agenda- Sistemas Periciais index1=text.indexOf("+",index2+1); p=new Integer(text.substring(index2+1,index1)); ports[i]=p.intValue(); index2=text.indexOf("+",index1+1); ipadresses[i]=text.substring(index1+1,index2); index1=text.indexOf("&"); emails[i]=text.substring(index2+1,index1); i++; number_of_users=i; } input.close(); } catch (IOException e) { System.err.println("O ficheiro não foi aberto correctamente\n"+e.toString()); } } } 2.8 Class Marcação import java.awt.*; import java.io.*; import java.net.*; public class Marcacao extends Panel implements Runnable{ // Declaração das Variáveis Instance t1[][]; String talk,talkaux; Reunion reunion[][]; CreateSeqFile agend_files_write; CreateSeqFile1 reunion_files_write; ReadSeqFile agend_files_read; ReadSeqFile1 reunion_files_read; String mess2[]; Sender socket; Solution best_solution1,best_solution2,best_solution3; int day_,hour_,mark,mark1,zeros,countaux,fails; double success; String person[]={"Ivo Jorge","Fernando"}; Button mcjButton[]; private TextArea ivjArea[]; private Choice ivjChoice[]; private Panel ivjPanel1; private ScrollPane ivjScrollPane1; private ScrollPane ivjScrollPane2; private ScrollPane ivjScrollPane21; TextField ivjTextField; private Label ivjLabel[]; private String options[]; private Instance table_pref[][]; private Integer count; private int cod; private ReadSeqFile1 read_reunion; private CreateSeqFile1 create_reunion; private String week_days[]={"Segunda","Terça","Quarta","Quinta", "Sexta"}; private String percents[]={"10%","20%","30%","40%","50%","60%", "70%","80%","90%","100%"}; pág. 71 WEB Agenda- Sistemas Periciais private String hours[]={"8h00m","9h00m","10h00m","11h00m","14h00m", "15h00m","16h00m","17h00m","18h00m","19h00m"}; private LinkedList listpref; private Preferences_Matrix matrixpref; private Boolean_Matrix matrixbool; int number_of_users; Options choose; int number_of_solution; int save_solution; Display_3_Solution solution3; Display_Solution solution; boolean wait; String ipadresses_selected[]; String names_selected[]; String emails_selected[]; int ports_selected[]; int number_item_selected[]; int number_of_the_fails[]; String fails_name[]; String actual_user; // Constructor public Marcacao(Instance t[][],String ns[],String ips[],String ems[],int ps[],int ins[],String us) { super(); // Inicialização das variáveis t1=t; ipadresses_selected=ips; names_selected=ns; emails_selected=ems; ports_selected=ps; number_item_selected=ins; number_of_users=number_item_selected.length; actual_user=us; setLayout(null); setBounds(41, 1, 503, 630); options=new String[6]; mcjButton=new Button[3]; count=new Integer("0"); ivjArea=new TextArea[2]; ivjChoice=new Choice[5]; ivjLabel=new Label[6]; listpref=new LinkedList(); matrixpref=new Preferences_Matrix(); matrixbool=new Boolean_Matrix(); table_pref=t; // Colocação dos Botões //Botão 1 mcjButton[0] = new java.awt.Button(); mcjButton[0].setName("Button1"); mcjButton[0].setFont(new java.awt.Font("dialog", 0, 11)); pág. 72 WEB Agenda- Sistemas Periciais mcjButton[0].setBounds(441, 30, 95, 22); mcjButton[0].setLabel("Iniciar"); mcjButton[0].disable(); add(mcjButton[0]); //Botão 2 mcjButton[1] = new java.awt.Button(); mcjButton[1].setName("Button11"); mcjButton[1].setFont(new java.awt.Font("dialog", 0, 11)); mcjButton[1].setBounds(441, 70, 95, 22); mcjButton[1].setLabel("Opções"); add(mcjButton[1]); //Botão 3 mcjButton[2] = new java.awt.Button(); mcjButton[2].setName("Button12"); mcjButton[2].setFont(new java.awt.Font("dialog", 0, 11)); mcjButton[2].setBounds(441, 111, 95, 22); mcjButton[2].setLabel("Fechar"); add(mcjButton[2]); //Colocação das caixas de Escolha //Choice 1 ivjChoice[0] = new java.awt.Choice(); ivjChoice[0].setName("Choice1"); ivjChoice[0].setBackground(java.awt.Color.white); ivjChoice[0].setBounds(196, 45, 100, 26); // Colocação dos dias na Choice 1 for (int i=0;i<5;i++) ivjChoice[0].add(week_days[i]); //Choice 2 ivjChoice[1] = new java.awt.Choice(); ivjChoice[1].setName("Choice11"); ivjChoice[1].setBackground(java.awt.Color.white); ivjChoice[1].setBounds(196, 79, 100, 26); // Colocação das horas na Choice 2 for (int i=0;i<10;i++) ivjChoice[1].add(hours[i]); // Colocação das Áreas de Texto onde aparecem as mensagens // TextArea 1 ivjArea[0] = new java.awt.TextArea(); ivjArea[0].setName("TextArea1"); ivjArea[0].setBackground(new java.awt.Color(254, 254, 236)); ivjArea[0].setBounds(110, 195, 413, 171); add(ivjArea[0]); //TextArea 2 ivjArea[1] = new java.awt.TextArea(); ivjArea[1].setName("TextArea11"); pág. 73 WEB Agenda- Sistemas Periciais ivjArea[1].setBackground(new java.awt.Color(254, 254, 236)); ivjArea[1].setBounds(110, 404, 412, 171); add(ivjArea[1]); // Colocação das Labels //Label 1 ivjLabel[0] = new java.awt.Label(); ivjLabel[0].setName("Label1"); ivjLabel[0].setBackground(new Color(191, 223, 253)); ivjLabel[0].setFont(new java.awt.Font("dialog", 1, 12)); ivjLabel[0].setText("Seleccione o dia e hora de marcação:"); ivjLabel[0].setBounds(90, 11, 220, 28); //Label 2 ivjLabel[1] = new java.awt.Label(); ivjLabel[1].setName("Label11"); ivjLabel[1].setBackground(new Color(191, 223, 253)); ivjLabel[1].setFont(new java.awt.Font("dialog", 0, 12)); ivjLabel[1].setText("Dia da Semana"); ivjLabel[1].setBounds(91, 41, 93, 29); //Label 3 ivjLabel[2] = new java.awt.Label(); ivjLabel[2].setName("Label12"); ivjLabel[2].setBackground(new Color(191, 223, 253)); ivjLabel[2].setFont(new java.awt.Font("dialog", 0, 12)); ivjLabel[2].setText("Hora da Reunião"); ivjLabel[2].setBounds(91, 75, 95, 29); //Label 4 ivjLabel[3] = new java.awt.Label(); ivjLabel[3].setName("Label13"); ivjLabel[3].setFont(new java.awt.Font("dialog", 0, 12)); ivjLabel[3].setAlignment(java.awt.Label.CENTER); ivjLabel[3].setText("Mensagens enviadas pelo Servidor"); ivjLabel[3].setBounds(0, -15, 221, 31); //Label 5 ivjLabel[4] = new java.awt.Label(); ivjLabel[4].setName("Label14"); ivjLabel[4].setFont(new java.awt.Font("dialog", 0, 12)); ivjLabel[4].setAlignment(java.awt.Label.CENTER); ivjLabel[4].setText("Mensagens enviadas pelos Clientes"); ivjLabel[4].setBounds(0, -3, 220, 31); // Label 6 ivjLabel[5] = new java.awt.Label(); ivjLabel[5].setFont(new java.awt.Font("dialog", 0, 12)); ivjLabel[5].setBackground(new Color(191, 223, 253)); ivjLabel[5].setAlignment(java.awt.Label.CENTER); ivjLabel[5].setText("Assunto"); ivjLabel[5].setBounds(76, 109, 77, 31); // Colocação do campo de texto (Assunto) ivjTextField = new java.awt.TextField(); ivjTextField.setName("TextField1"); ivjTextField.setBackground(java.awt.Color.white); ivjTextField.setBounds(153, 114, 142, 24); pág. 74 WEB Agenda- Sistemas Periciais // Adição ao Ecran das labels, do campo e das choices add(ivjLabel[0]); add(ivjLabel[1]); add(ivjLabel[5]); add(ivjChoice[0]); add(ivjLabel[2]); add(ivjChoice[1]); add(ivjTextField); // Colocação do Panel com relevo 1 ivjScrollPane2 = new java.awt.ScrollPane(java.awt.ScrollPane.SCROLLBARS_NEVER); ivjScrollPane2.setName("ScrollPane2"); ivjScrollPane2.setBackground(new Color(254, 254, 216)); ivjScrollPane2.setBounds(168, 166, 297, 23); ivjScrollPane2.add(ivjLabel[3]); add(ivjScrollPane2); // Colocação do Panel com relevo 2 ivjScrollPane21 = new java.awt.ScrollPane(java.awt.ScrollPane.SCROLLBARS_NEVER); ivjScrollPane21.setName("ScrollPane21"); ivjScrollPane21.setBackground(new Color(254, 254, 216)); ivjScrollPane21.setBounds(168, 375, 297, 23); ivjScrollPane21.add(ivjLabel[4]); add(ivjScrollPane21); show(); } // Método chamado para finalizar a Marcação (Executa tarefas como a actualização das agendas // e actualização dos ficheiros de reunião public void finish() { String mess; // Se foi escolhido o tipo de solução 1,2 ou 3 if (number_of_solution<4) { // Se existir solução 1 e se foi escolhida a solução 1 if (number_of_solution==1 & solution.solution_option) { // actualiza os ficheiros com a solução 1 updateFiles(best_solution1); } // Se existir solução 2 e se foi escolhida a solução 2 else if (number_of_solution==2 & solution.solution_option) { // actualiza os ficheiros com a solução 2 updateFiles(best_solution2); } // Se existir solução 3 e se foi escolhida a solução 3 else if (number_of_solution==3 & solution.solution_option) { // actualiza os ficheiros com a solução 3 updateFiles(best_solution3); pág. 75 WEB Agenda- Sistemas Periciais } } // Se foi escolhida a solução 4 (Isto é, soluções 1,2,3 para depois o utilizador escolher) else if (number_of_solution==4) { // Se for escolhida a solução 1 if (solution3.solution_option==1) { // actualiza os ficheiros com a solução 1 updateFiles(best_solution1); } // Se for escolhida a solução 2 else if (solution3.solution_option==2) { // actualiza os ficheiros com a solução 2 updateFiles(best_solution2); } // Se for escolhida a solução 2 else if (solution3.solution_option==3) { // actualiza os ficheiros com a solução 3 updateFiles(best_solution3); } } } // Inicialização public void initiation () { // Declaração das variáveis number_of_solution=0; success=0; mark=0; mark1=0; // Determina qual o tipo de solução que quer number_of_solution=choose.op; // Determina o dia até à qual é feito o reset da matriz mark=choose.mark; // Determina o dia a partir da qual é feito o reset da matriz mark1=choose.mark1; // Determina a coluna referente ao dia seleccionado pelo utilizador for (int i=0;i<5;i++) { pág. 76 WEB Agenda- Sistemas Periciais if (ivjChoice[0].getSelectedItem().equalsIgnoreCase(week_days[i])) { day_=i; break; } } // Encontra a linha referente à hora escolhida pelo utilizador for (int i=0;i<10;i++) { if (ivjChoice[1].getSelectedItem().equalsIgnoreCase(hours[i])) { hour_=i; break; } } // Encontra o grau de Sucesso a atingir success=choose.success; // Inicializa o nº de falhas admitidas fails=choose.fails; // Inicialização da matriz Booleana e de Preferências for (int i=0;i<mark;i++) { for (int j=0;j<10;j++) { matrixbool.setvalue(i,j,false); matrixpref.putpreference(i,j,0.0); } } for (int i=mark1+1;i<5;i++) { for (int j=0;j<10;j++) { matrixbool.setvalue(i,j,false); matrixpref.putpreference(i,j,0.0); } } for (int i=mark;i<=mark1;i++) { for (int j=0;j<10;j++) matrixpref.putpreference(i,j,table_pref[i][j].getdisp()); } // Inicialização da lista ligada for (int i=0;i<5;i++) { for (int j=0;j<10;j++) { pág. 77 pág. 78 WEB Agenda- Sistemas Periciais if (matrixpref.getpreference(i,j) !=0) listpref.insert(table_pref[i][j]) ; } } // lança um processo (thread) que se vai encarregar das comunicações new Thread(this).start(); // Chama o método que se vai encarregar de acordar os clientes waking_up(); } // Desenha o fundo do ecrán public void paint(Graphics g ) { g.setColor(new Color(191, 223, 253)); g.fill3DRect(61, 1, 503, 595,true); } // Método que corre o algoritmo de negociação public void run() { // Declaração das variáveis String mess4,mess5; boolean last=false; int position,count,initial_day,initial_hour; Instance item; Integer day[],hour[]; Double preference[]; Double antpreference[]; double best,result=1.0,result_propost=1.0,drm,hrm,peso1,peso2; boolean connection[]; number_of_the_fails=new int[200]; fails_name=new String[200]; boolean end,find; end=false; socket=new Sender(number_of_users); int type=0; LinkedList stack; stack=new LinkedList(); Instance zeropref; wait=true; String mess,mess1; String code[]; preference=new Double[number_of_users]; antpreference=new Double[number_of_users]; connection=new boolean[number_of_users]; code=new String[number_of_users]; day=new Integer[number_of_users]; hour=new Integer[number_of_users]; String mess3="Não concordo."; mess4="Concordo."; mess5=""; mess1=""; int counting; peso1=0.4; peso2=0.1; initial_day=day_; initial_hour=hour_; save_solution=0; WEB Agenda- Sistemas Periciais pág. 79 reunion=new Reunion[5][10]; // Inicialização das reuniões read_reunion=new ReadSeqFile1(); read_reunion.open_file(actual_user); read_reunion.readRecord(); read_reunion.cleanup(); reunion=read_reunion.records; // Inicialização das soluções best_solution1=new Solution(null,8,9,0.0,200,null); best_solution2=new Solution(null,10,10,0.0,200,null); best_solution3=new Solution(null,10,10,0.0,200,null); //Proposta de um Socket com os clientes mess1=socket.createsocket(ports_selected); counting=0; // Conta o nº de Iterações item=null; // Enquanto não for declarado o fim da negociação while (end==false) { zeros=0; counting++; // Marca a proposta que vai ser enviada para assegurar que não volta ser proposta matrixbool.setvalue(day_,hour_,false); // Construção da mensagem de proposta mess="01"+String.valueOf(day_)+String.valueOf(hour_)+ String.valueOf(matrixpref.getpreference(day_,hour_))+String.valueOf(end)+"\n"; // Manda mensagem mess1=socket.sendmessage(mess); // Escreve a proposta no ecran ivjArea[0].appendText("Proposta: "+week_days[day_]+" às "+hours[hour_]+ "\n"); // Espera pela resposta mess2=socket.receivemessage(); // Guarda valores e conta o número de zeros for (int i=0;i<number_of_users;i++) { // dia day[i]=new Integer(mess2[i].substring(3,4)); //hora hour[i]=new Integer(mess2[i].substring(4,5)); //preferência da contraproposta preference[i]=new Double(mess2[i].substring(5,8)); //preferência da proposta antpreference[i]=new Double(mess2[i].substring(0,3)); //conta o nº de zeros if (antpreference[i].doubleValue()==0.0) { number_of_the_fails[zeros]=i; zeros+=1; } pág. 80 WEB Agenda- Sistemas Periciais //lê qual o código da trama (true <=> ligação continua # false <=> ligação vai ser fechada) if (mess2[i].charAt(4)=='t') connection[i]=true; else connection[i]=false; } //Envio de mensagens para o display dos clientes for (int i=0;i<number_of_users;i++) { // Se proposta apresenta um valor diferente de ocupado if (preference[i].doubleValue()!=0.0) { // Se a contraproposta tem um valor superior à disp. da proposta anterior if (preference[i].doubleValue()>antpreference[i].doubleValue()) ivjArea[1].appendText("Agente"+String.valueOf(i+1)+":"+mess3+ "Prefiro"+week_days[day[i].intValue()]+"às"+hours[hour[i].intValue()] +".\n"); // Se a contraproposta tem um valor inferior à disp. da proposta anterior else ivjArea[1].appendText("Agente "+String.valueOf(i+1)+" : "+mess4+ " Outra possibilidade seria "+week_days[day[i].intValue()]+ " às "+hours[hour[i].intValue()]+".\n"); } // Se a proposta apresenta um valor equivalente a ocupado else ivjArea[1].appendText("Agente "+String.valueOf(i+1)+" : "+"Esgotei todas as alternativas"+".\n"); } // No caso de existirem contrapropostas que correspondam a indisponibilidade para o //coordenador este envia uma mensagem aos cliente para eliminarem este dia da lista for (int i=0;i<number_of_users;i++) { // Se a contraproposta constitui indisponibilidade para o coordenador if (matrixpref.getpreference(day[i].intValue(),hour[i].intValue())==0) { // Constroi mensagem mess="Apagar"+String.valueOf(day[i].intValue())+ String.valueOf(hour[i].intValue())+"\n"; // Envia mensagem mess1=socket.sendmessage(mess); // Espera um ok de resposta mess2=socket.receivemessage(); } } find=false; // Vê se encontrou alguma contraproposta !=0 best=0.0; // Valor inicial da primeira contraproposta result=1; // Valor da solução actual drm=Math.abs(initial_day-day_); hrm=Math.abs(initial_hour-hour_); pág. 81 WEB Agenda- Sistemas Periciais //multiplica todas as preferencias != de zero e extrai a raiz do mesmo grau result=result*matrixpref.getpreference(day_,hour_); // Cálculo da função heurística result_propost=result_propost*matrixpref.getpreference(day_,hour_)*(1.0-drm*peso1/8.0hrm*peso2/18.0); for (int i=0;i<number_of_users;i++) { // Apenas para disponibilidade diferentes de zero if (antpreference[i].doubleValue()!=0.0) { result=antpreference[i].doubleValue()*result; result_propost=result_propost*antpreference[i].doubleValue()* (1.0-drm*peso1/8.0-hrm*peso2/18.0); } } // Cálculo do sucesso result=Math.pow(result,Math.pow(number_of_users+1-zeros,-1)); result_propost=Math.pow(result_propost,Math.pow(number_of_users+1-zeros,-1)); // Solução do tipo 3 if (best_solution3.getvalue()<result || ((best_solution3.getvalue()==result best_solution3.getzeros()>zeros) & zeros<(number_of_users/2+1))){ for (int i=0;i<zeros;i++) fails_name[i]=names_selected[number_of_the_fails[i]]; best_solution3=new Solution(antpreference,day_,hour_,result,zeros,fails_name); } // Solução tipo 1 result=1; result_propost=1; result_propost=result_propost*matrixpref.getpreference(day_,hour_)*(1.0-drm*peso1/8.0hrm*peso2/18.0); result=result*matrixpref.getpreference(day_,hour_); for (int i=0;i<number_of_users;i++) { if (antpreference[i].doubleValue()!=0.0) { result=result*antpreference[i].doubleValue(); result_propost=result_propost*antpreference[i].doubleValue()*(1.0drm*peso1/8.0-hrm*peso2/18.0); } } // Cálculo do sucesso result=Math.pow(result,Math.pow(number_of_users+1-zeros,-1)); result_propost=Math.pow(result_propost,Math.pow(number_of_users+1-zeros,-1)); // Avaliação da Solução tipo 1 // Caso em que tem o mesmo result propost mas menos zeros & pág. 82 WEB Agenda- Sistemas Periciais if (best_solution1.getvalue()==result & zeros<best_solution1.getzeros() & zeros<=fails & success<=result){ for (int i=0;i<zeros;i++) fails_name[i]=names_selected[number_of_the_fails[i]]; best_solution1=new Solution(antpreference,day_,hour_,result,zeros,fails_name); } // Caso em que tem mais zeros mas o result_propost é melhor else if ((best_solution1.getvalue()<result & zeros<=fails & success<=result) || (best_solution1.getvalue()<result_propost & zeros<=best_solution1.getzeros() & zeros<=fails & success<=result)){ for (int i=0;i<zeros;i++) fails_name[i]=names_selected[number_of_the_fails[i]]; best_solution1=new Solution(antpreference,day_,hour_,result,zeros,fails_name); } // Cálculo da Solução tipo 2 if ((zeros<=fails & zeros<best_solution2.getzeros()) || (zeros<=fails zeros==best_solution2.getzeros() & best_solution2.getvalue()<result)) { for (int i=0;i<zeros;i++) fails_name[i]=names_selected[number_of_the_fails[i]]; best_solution2=new Solution(antpreference,day_,hour_,result,zeros,fails_name); } // Vê qual é a melhor contraproposta guarda em best for (int i=0;i<number_of_users;i++) { drm=Math.abs(initial_day-day[i].intValue()); hrm=Math.abs(initial_hour-hour[i].intValue()); if (best<preference[i].doubleValue()*(1.0-drm*peso1/8.0-hrm*peso2/18.0) & matrixpref.getpreference(day[i].intValue(),hour[i].intValue())!=0.0) { best=preference[i].doubleValue()*(1.0-drm*peso1/8.0-hrm*peso2/18.0); day_=day[i].intValue(); hour_=hour[i].intValue(); find=true; } } // Se nenhuma satisfez então busca a melhor da lista do coordenador while(find==false & end!=true) { if (listpref.isEmpty()) { end=true; ivjArea[0].appendText("Ficou true..."); } else { item=listpref.getbest(initial_day,initial_hour); listpref.removepropost(item.getday(),item.gethour()); if (listpref.isEmpty()) { last=true; ivjArea[0].appendText("Ficou true o last..."); } } if (matrixbool.getvalue(item.getday(),item.gethour()) & end!=true) { & pág. 83 WEB Agenda- Sistemas Periciais find=true; day_=item.getday(); hour_=item.gethour(); end=false; } } } // Construção da mensagem de finalização mess="02"+String.valueOf(day_)+String.valueOf(hour_)+ String.valueOf(matrixpref.getpreference(day_,hour_))+String.valueOf(end)+"\n"; // Manda mensagem socket.sendmessage(mess); // Se foi a primeira solução escolhida if (number_of_solution==1) { try { solution=new Display_Solution(week_days[best_solution1.getday()], hours[best_solution1.gethour()], best_solution1.getvalue(),best_solution1.getzeros(),best_solution1.getfails()); } catch (ArrayIndexOutOfBoundsException e) { ivjArea[0].appendText("Não foi possível obter uma solução to tipo 1"); number_of_solution=5; } } // Se foi a segunda solução escolhida if (number_of_solution==2) { try { solution=new Display_Solution(week_days[best_solution2.getday()], hours[best_solution2.gethour()], best_solution2.getvalue(),best_solution2.getzeros(),best_solution2.getfails()); } catch (ArrayIndexOutOfBoundsException e) { ivjArea[0].appendText("Não foi possível obter uma solução do tipo 2"); number_of_solution=5; } } // Se foi a terceira solução escolhida if (number_of_solution==3) { pág. 84 WEB Agenda- Sistemas Periciais try { solution=new Display_Solution(week_days[best_solution3.getday()], hours[best_solution3.gethour()], best_solution3.getvalue(),best_solution3.getzeros(),best_solution3.getfails()); } catch (ArrayIndexOutOfBoundsException e) { ivjArea[0].appendText("Não foi possível obter uma solução do tipo 3"); number_of_solution=5; } } // Se foi a terceira solução escolhida if (number_of_solution==4) { solution3=new Display_3_Solution(best_solution1,best_solution2,best_solution3); } // Fecho da comunicação mess="01Lecao#3/6#0.0\n"; socket.sendmessage(mess); mess2=socket.receivemessage(); ivjArea[0].appendText(mess2[0]); if (mess2[0].substring(0,3).equals("bye")) { socket.closesocket(); } } // Método que permite a alteração de ficheiros de agenda e de reunião public void updateFiles(Solution s ) { // Declaração das Variáveis int num=0; CreateSeqFile1 file1_create; Instance recs[][]; Reunion reun[][]; CreateSeqFile file_create; ReadSeqFile file_read; ReadSeqFile1 file1_read; file_create=new CreateSeqFile(); file1_create=new CreateSeqFile1(); file_read=new ReadSeqFile(); file1_read=new ReadSeqFile1(); int ports[]; String fails[]; // Alteração do ficheiro de agenda do Coordenador t1[s.getday()][s.gethour()]=new Instance(s.getday(),s.gethour(),0.0); file_create.addRecord(t1,actual_user); WEB Agenda- Sistemas Periciais pág. 85 // Alteração do ficheiro de reunião do Coordenador reunion[s.getday()][s.gethour()]= new Reunion(talk,String.valueOf(s.getzeros())+"/"+ String.valueOf(number_of_users),String.valueOf(s.getvalue())); file1_create.addRecord(reunion,actual_user); // Determinação do nº dos utilizadores que vão estar presentes ports=new int[number_of_users-s.getzeros()]; fails=s.getfails(); boolean fi; for (int i=0;i<ports_selected.length;i++) { fi=false; for (int j=0;j<s.getzeros();j++) { // Se o nome dos utilizadores seleccionados coincide com o nome de um utilizador //que não vai estar presente então na o põe na lista de alterações if (names_selected[i].equals(fails[j])) { fi=true; break; } } // SE encontra um utilizador que não vai estar presente não o põe na lista de alterações if (!fi) { ports[num]=ports_selected[i]; num ++; } } for (int i=0;i<ports.length;i++) // Leitura e Alteração dos Ficheiros for (int i=0;i<ports.length;i++) { file_read=new ReadSeqFile(); file_read.open_file("user0"+String.valueOf(ports[i]-1).substring(1,4)); file_read.readRecord(); file_read.cleanup(); recs=file_read.records; // Colocação da preferência do dia e hora a que foi marcada a reunião em 0.0 recs[s.getday()][s.gethour()]=new Instance(s.getday(),s.gethour(),0.0); // Alteração do ficheiro de agenda file_create=new CreateSeqFile(); file_create.addRecord(recs,"user0"+String.valueOf(ports[i]-1).substring(1,4)); } // leitura e alteração dos ficheiros de Reunião for (int i=0;i<ports.length;i++) { // Leitura do ficheiro WEB Agenda- Sistemas Periciais pág. 86 file1_read=new ReadSeqFile1(); file1_read.open_file("user0"+String.valueOf(ports[i]-1).substring(1,4)); file1_read.readRecord(); // Alteração do registo file1_read.records[s.getday()][s.gethour()]= new Reunion(talk,String.valueOf(s.getzeros())+"/"+ String.valueOf(number_of_users),String.valueOf(s.getvalue())); // Escrita do registo no ficheiro de Reuniões file1_create=new CreateSeqFile1(); file1_create.addRecord(file1_read.records,"user0"+String.valueOf(ports[i]1).substring(1,4)); } } // Método responsável por acordar os clientes public void waking_up ( ) { // Declaração das variáveis URL location; InputStream input; DataInputStream datastream; location=null; for (int i=0;i<emails_selected.length;i++) { // Criação do URL para acordar o cliente try { location=new URL ("http://jinks.fe.up.pt/cgi-bin/fjorge-cgi/acorda.pl?"+ emails_selected[i]+"/executa.pl"+"+" +InetAddress.getLocalHost().getHostAddress()); } catch (MalformedURLException e) { System.out.println("URL mal formado"); } catch (UnknownHostException e) { System.out.println("Falhou a leitura do Host"); } // Execução do CGI que acorda o cliente try { input=location.openStream(); datastream=new DataInputStream(input); datastream.close(); } catch (IOException e) { System.out.println("Erro na abertura da Stream"); } } WEB Agenda- Sistemas Periciais pág. 87 } } 2.9 Class CreateSeqFile Esta classe é responsável pela criação e escrita de ficheiros de agenda. O seu constructor recebe como parâmetros o utilizador para o qual a agenda vai ser criada e o conjunto de registos com a preferência em cada dia e hora da agenda. Segue-se a listagem do código correspondente a esta classe: import java.lang.Exception; import java.awt.*; import java.io.*; import java.applet.Applet; import java.net.*; public class CreateSeqFile { // Declaração das variáveis DataOutputStream output; public void addRecord(Instance s[][],String us){ // Declaração das variáveis InputStream input; DataInputStream dataInput; createFile(us); String record; record=""; URL url; url=null; System.out.println("Tudo fixe 2"); for (int i=0;i<5;i++) { for (int j=0;j<10;j++) { // Coloca o registo a envia para o CGI na forma d1+h1+pref1++d2+h2+pref2… if (i==0 & j==0) record=String.valueOf(s[i][j].getday()); else record+=String.valueOf("++"+String.valueOf(s[i][j].getday())); record+=String.valueOf("+"+String.valueOf(s[i][j].gethour())); record+=String.valueOf("+"+String.valueOf(s[i][j].getdisp())); } } // Cria um URL para o CGI escreve.pl try { url=newURL("http://jinks.fe.up.pt/cgi-bin/fjorge-cgi/escreve.pl?"+us.substring(4,8)+ "++"+record); } WEB Agenda- Sistemas Periciais pág. 88 catch (MalformedURLException e) { System.out.println("Surgiu excepção no URL"); } // Executa o CGI escreve.pl try { input=url.openStream(); dataInput=new DataInputStream(input); System.out.println("Tentou abrir Stream"); dataInput.close(); } catch(IOException e) { System.out.println("Ocorreu excepção na abertura da Stream"); } } 2.10 Classe ReadSeqFile Esta classe é responsável pela leitura dos ficheiros de agenda. Recebe como parâmetros de entrada o nome do utilizador para o qual queremos abrir a agenda. Segue-se a listagem de código referente a esta classe. import java.io.*; import java.awt.*; import java.net.*; public class ReadSeqFile extends Frame{ // Declaração das Variáveis DataInputStream input; Instance records[][]; boolean radiobuttons[]; String actual_user; // Método responsável pelo fecho da Stream de Leitura public void cleanup ( ) { try { input.close(); } catch (IOException e) { System.err.println("O ficheiro não foi fechado correctamente\n"+e.toString()); System.exit(1); } } // Método responsável pela abertura do ficheiro public void open_file (String f ) { // Declaração das variáveis URL url; url=null; actual_user=f; // Criação do URL para o ficheiro de agenda respectivo try { pág. 89 WEB Agenda- Sistemas Periciais url=new URL("http://jinks.fe.up.pt/~fjorge/agenda"+f.substring(4,8)); } catch (MalformedURLException e) { System.out.println("Erro no URL"); } // Abre uma Stream de Leitura para o ficheiro de agenda respectivo try { InputStream i=url.openStream(); input=new DataInputStream(i); } catch (IOException e) { // Se não existe um ficheiro para este utilizador cria um por defeito com todas as // preferências a 1.0 System.err.println("O ficheiro não foi aberto correctamente\n"+e.toString()); Instance temp[][]; temp=new Instance[5][10]; // Criação do registo a escrever no ficheiro de agenda for (int i=0;i<5;i++) { for (int j=0;j<10;j++) { temp[i][j]=new Instance(i,j,1.0); } } // Criação e escrita no ficheiro CreateSeqFile file; file=new CreateSeqFile(); file.addRecord(temp,actual_user); } } // Este método encarrega-se da leitura da Stream public void readRecord( ) { // Declaração das variáveis String aux,text; int day,hour; Integer dayaux,houraux; Double choiceaux; double choice; CreateSeqFile file; file=new CreateSeqFile(); Instance rec[][]; rec=new Instance[5][10]; records=new Instance[5][10]; radiobuttons=new boolean[10]; text=""; aux=""; boolean not_end_file=true; try { for (int i=0;i<5;i++) { for (int j=0;j<10;j++) { // leitura de uma linha do ficheiro text=input.readLine(); pág. 90 WEB Agenda- Sistemas Periciais // Separação da linha em dia… dayaux=new Integer(text.substring(0,1)); //…em hora houraux=new Integer(text.substring(2,3)); // e em preferência choiceaux=new Double(text.substring(4,7)); records[i][j]=new Instance(dayaux.intValue(),houraux.intValue(),choiceaux.doubleValue()); } } input.close(); } // Trata da Excepção de fim de ficheiro catch(EOFException eof) { not_end_file=false; } catch (IOException e) { System.err.println("Erro durante a leitura do ficheiro\n"+e.toString()) ; System.exit(1); } } } 2.11 Classe CreateSeqFile1 Esta classe encarrega-se de criar e escrever no ficheiro de reuniões do utilizador respectivo. Recebe como parâmetros de entrada o utilizador para o qual queremos escrever o ficheiro de reuniões. Segue-se a listagem do código respectivo a esta classe. import java.lang.Exception; import java.awt.*; import java.io.*; import java.applet.Applet; import java.net.*; public class CreateSeqFile1 { // Declaração das variáveis DataOutputStream output; // Método responsável por escrever o registo no ficheiro public void addRecord(Reunion s[][],String us){ // Declaração das variáveis createFile(us); String record; record=""; URL url; WEB Agenda- Sistemas Periciais pág. 91 url=null; InputStream input; DataInputStream dataInput; for (int i=0;i<5;i++) { for (int j=0;j<10;j++) { //Formação de uma frase do tipo Assunto1+Nºausentes1+Sucesso1++Assunto2+ //Nºausentes2+Sucesso2 if (i==0 & j==0) record+=s[i][j].talkabout; else record+="++"+s[i][j].talkabout; record+="+"+s[i][j].present; record+="+"+s[i][j].success; } } // Criação de um URL responsável por chamar o CGI escreve1.pl try { url=newURL("http://jinks.fe.up.pt/cgi-bin/fjorge-cgi/escreve1.pl?"+us.substring(4,8)+ "++"+record); } catch (MalformedURLException e) { System.out.println("Surgiu excepção no URL"); } // Execução do CGI escreve1.pl try { input=url.openStream(); dataInput=new DataInputStream(input); dataInput.close(); } catch(IOException e) { System.out.println("Ocorreu excepção na abertura da Stream"); } } } 2.12 Classe ReadSeqFile1 Classe responsável pela leitura do ficheiro de Reuniões de um utilizador respectivo. Esta classe recebe como parâmetros de entrada o utilizador para o qual queremos escrever no ficheiro de reuniões. import java.io.*; import java.aw;.*; import java.net.*; public class ReadSeqFile1 extends Frame{ // Declaração das variáveis DataInputStream input; Reunion records[][]; String actual_user; // Método responsável pelo fecho da Stream pág. 92 WEB Agenda- Sistemas Periciais public void cleanup ( ) { try { input.close(); } catch (IOException e) { System.err.println("O ficheiro não foi fechado correctamente\n"+e.toString()); System.exit(1); } } public void open_file (String f ) { // Declaração das variáveis URL url; url=null; actual_user=f; // Criação do URL para o ficheiro de reuniões respectivo try { url=new URL("http://jinks.fe.up.pt/~fjorge/reunion"+f.substring(4,8)); } catch (MalformedURLException e) { System.out.println("Erro no URL"); } try { // Criação de uma Stream de leitura para o ficheiro de reuniões respectivo InputStream i=url.openStream(); input=new DataInputStream(i); } catch (IOException g) { System.err.println("O ficheiro não foi aberto correctamente\n"+g.toString()); // Se não existir ficheiro cria um por defeito com os campos todos a 0 records=new Reunion[5][10]; // Criação do registo por defeito for (int i=0;i<5;i++) { for (int j=0;j<10;j++) records[i][j]=new Reunion("0","0","0"); } // Criação e escrita no ficheiro CreateSeqFile1 file_create=new CreateSeqFile1(); file_create.addRecord(records,actual_user); } } // Método responsável pela leitura do Ficheiro public void readRecord( ) { // Declaração das variáveis records=new Reunion[5][10]; String ta,p,s; boolean not_end_file=true; String text,aux; pág. 93 WEB Agenda- Sistemas Periciais int index,index1; try { for (int i=0;i<5;i++) { for (int j=0;j<10;j++) { // leitura de uma linha text=input.readLine(); index=text.indexOf('+'); // identificação do assunto na linha ta=text.substring(0,index); index1=text.indexOf('+',index+1); // identificação do nº de pessoas ausentes na linha p=text.substring(index+1,index1); // identificação do sucesso na linha s=text.substring(index1+1,text.indexOf('&')); records[i][j]=new Reunion(ta,p,s); } } input.close(); } // Trata da excepção de final do ficheiro catch(EOFException eof) { not_end_file=false; } catch (IOException e) { System.err.println("Erro durante a leitura do ficheiro\n"+e.toString()) ; System.exit(1); } } } 2.13 Classe Sender Este classe é responsável pelo estabelecimento de um Socket servidor que corresponde ao Coordenador que permite enviar mensagens e receber mensagens dos Clientes. Esta classe recebe como parâmetros de entrada o nº de clientes que vão estar em jogo na negociação. Segue-se a listagem do código referente a esta classe. import java.io.*; import java.net.*; import java.awt.*; public class Sender { // Declaração das variáveis String message; boolean done; boolean notcontinue=true; ServerSocket server[]; Socket connection[]; OutputStream output[]; WEB Agenda- Sistemas Periciais pág. 94 InputStream input[]; int number_of_users; int ports[]; // Constructor public Sender(int nu) { // Declaração das variáveis number_of_users=nu; server=new ServerSocket[200]; connection=new Socket[200]; output=new OutputStream[200]; input=new InputStream[200]; } // Método responsável pelo fecho do Socket public String closesocket ( ) { // Declaração das variáveis String mess; mess=""; // Fecha todos os sockets estabelecidos try { for (int i=0;i<number_of_users;i++) connection[i].close(); mess="Ligação Terminada...\n"; } catch (IOException e) { e.printStackTrace(); } return mess; } // Método responsável pelo estabelecimento de um Socket com cada Cliente public String createsocket (int p[] ) { // Declaração das variáveis String mess; ports=p; mess=""; try { // Cria um socket for (int i=0;i<number_of_users;i++) server[i]=new ServerSocket(ports[i],number_of_users); // Pergunta aceitação do socket for (int i=0;i<number_of_users;i++) connection[i]=server[i].accept(); // Se todos os sockets são aceites envia mensagem de estabelecimento de ligação mess="Ligação recebida...\n Enviando Dados...\n"; } catch (IOException e) { e.printStackTrace(); } return mess; } // Método responsável pela leitura de Mensagem public String[] receivemessage ( ) { // Declaração de variáveis String mess[]; mess=new String[200]; mess[0]=""; mess[1]=""; mess[2]=""; pág. 95 WEB Agenda- Sistemas Periciais try { // Lê a Stream de dados enviada por cada cliente for (int i=0;i<number_of_users;i++) input[i]=connection[i].getInputStream(); char c; // Converte a Stream de Entrada de cada cliente numa String for (int i=0;i<number_of_users;i++) { while ( (c=(char) input[i].read())!='\n') mess[i]+=String.valueOf(c); } } catch (IOException e) { e.printStackTrace(); } return mess; } // Este método é responsável pelo envio de mensagens aos Clientes public String sendmessage(String message ) { // Declaração de variáveis String mess; mess=""; try { // Cria uma Stream de saída para cada cliente for (int i=0;i<number_of_users;i++) { output[i]=connection[i].getOutputStream(); // Envia a mensagem para cada cliente for (int j=0;j<message.length();j++) output[i].write( (int) message.charAt(j)); } mess="Trasmissão completada.\n"; } catch (IOException e) { e.printStackTrace(); } return mess; } } 2.14 Classe Options Esta classe é responsável pela criação da janela de opções relativas à marcação de reuniões. Este objecto é do tipo Frame representa em JAVA uma janela do Windows. import java.awt.*; import java.awt.event.*; public class Options extends Frame implements ActionListener,WindowListener{ // Declaração das variáveis private java.awt.Button opjButton1 = null; private java.awt.Button opjButton11 = null; private java.awt.Button opjButton2 = null; WEB Agenda- Sistemas Periciais private java.awt.Checkbox ivjCheckbox1 = null; private java.awt.Checkbox ivjCheckbox11 = null; private java.awt.Checkbox ivjCheckbox12 = null; private java.awt.Checkbox ivjCheckbox13 = null; private java.awt.CheckboxGroup ivjCheckboxGroup1 = null; private Choice ivjChoice1 = null; private Choice ivjChoice11 = null; private Choice ivjChoice12 = null; private Choice ivjChoice13 = null; private java.awt.Label ivjLabel1 = null; private java.awt.Label ivjLabel11 = null; private java.awt.Label ivjLabel12 = null; private java.awt.Label ivjLabel13 = null; private java.awt.Label ivjLabel14 = null; private java.awt.Label ivjLabel15 = null; private java.awt.Label ivjLabel16 = null; private java.awt.TextField ivjTextField1 = null; private String week_days[]={"Segunda","Terça","Quarta","Quinta","Sexta"}; private String percents[]={"10%","20%","30%","40%","50%","60%", "70%","80%","90%","100%"}; private String iterations[]={"5","10","15","20","25","30","Máximo"}; Integer count; int countaux,mark,mark1,it,fails,op; double success; // Constructor public Options() { super("Opções de Marcação"); // Cria um atendedor de eventos para a Janela addWindowListener(this); count=new Integer("0"); // Chama a inicialização initialize(); } // Este método é responsável pelo tratamento dos eventos dos botões public void actionPerformed(ActionEvent e) { String buttonCommand=e.getActionCommand(); // Incremento do nº de falhas admitidas if (buttonCommand.equals("+")) { count=new Integer(ivjTextField1.getText()); countaux=count.intValue()+1; ivjTextField1.setText(String.valueOf(countaux)); } // Decremento do nº de falhas admitidas if (buttonCommand.equals("-")) { count=new Integer(ivjTextField1.getText()); countaux=count.intValue()-1; if (countaux<0) countaux=0; ivjTextField1.setText(String.valueOf(countaux)); } // Botão continuar if (buttonCommand.equals("Continuar")) { // Esconda a janela e liberta a memória por ela alocada hide(); dispose(); pág. 96 pág. 97 WEB Agenda- Sistemas Periciais // Inicialização das variáveis success=0; mark=0; mark1=0; //Determina a coluna até à qual é feito do reset da Matriz Booleana for (int i=0;i<5;i++) { if (ivjChoice1.getSelectedItem().equalsIgnoreCase(week_days[i])) { mark=i; break; } } //Determina a coluna a partir da qual é feito o reset à Matriz Boolean for (int i=0;i<5;i++) { if (ivjChoice11.getSelectedItem().equalsIgnoreCase(week_days[i])) { mark1=i; break; } } //Determina o nº de Iterações for (int i=5;i<40;i+=5) { if (ivjChoice13.getSelectedItem().equals(String.valueOf(i))) { it=i; break; } else if (i==35) { it=200; break; } } // Encontra o grau de Sucesso a atingir for (int i=0;i<10;i++) { if (!ivjChoice12.getSelectedItem().equalsIgnoreCase(percents[i])) { success+=0.1; } else { success+=0.1; break; } } // Inicializa o nº de falhas admitidas count=new Integer(ivjTextField1.getText()); fails=count.intValue(); // Vê qual a opção tomada quanto ao tipo de solução if (ivjCheckbox1.getState()==true) op=1; else if (ivjCheckbox11.getState()==true) op=2; WEB Agenda- Sistemas Periciais else if (ivjCheckbox12.getState()==true) op=3; else if (ivjCheckbox13.getState()==true) op=4; } } // Definição das características do Botão 1 private java.awt.Button getButton1() { if (opjButton1 == null) { try { opjButton1 = new java.awt.Button(); opjButton1.setName("Button1"); opjButton1.setFont(new java.awt.Font("dialog", 0, 11)); opjButton1.setBounds(454, 122, 15, 9); opjButton1.setLabel("+"); opjButton1.addActionListener(this); } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); } }; return opjButton1; } // Definição das características do Botão 2 private java.awt.Button getButton11() { if (opjButton11 == null) { try { opjButton11 = new java.awt.Button(); opjButton11.setName("Button11"); opjButton11.setFont(new java.awt.Font("dialog", 0, 11)); opjButton11.setBounds(454, 133, 15, 9); opjButton11.setLabel("-"); opjButton11.addActionListener(this); } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); } }; return opjButton11; } // Definição das características do Botão 3 private java.awt.Button getButton2() { if (opjButton2 == null) { try { opjButton2 = new java.awt.Button(); opjButton2.setName("Button2"); opjButton2.setFont(new java.awt.Font("dialog", 0, 11)); opjButton2.setBounds(205, 310, 93, 25); opjButton2.setLabel("Continuar"); opjButton2.addActionListener(this); } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); } }; return opjButton2; } // Definição das características da Checkbox1(Escolha da Solução) private java.awt.Checkbox getCheckbox1() { if (ivjCheckbox1 == null) { try { pág. 98 WEB Agenda- Sistemas Periciais pág. 99 ivjCheckbox1 = new java.awt.Checkbox(); ivjCheckbox1.setName("Checkbox1"); ivjCheckbox1.setCheckboxGroup(getCheckboxGroup1()); ivjCheckbox1.setBounds(28, 187, 463, 27); ivjCheckbox1.setLabel("Solução com melhor resultado respeitando o nº de falhas e o grau de sucesso."); ivjCheckbox1.setState(true); } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); } }; return ivjCheckbox1; } // Definição das características da Checkbox 2(Escolha da Solução) private java.awt.Checkbox getCheckbox11() { if (ivjCheckbox11 == null) { try { ivjCheckbox11 = new java.awt.Checkbox(); ivjCheckbox11.setName("Checkbox11"); ivjCheckbox11.setCheckboxGroup(getCheckboxGroup1()); ivjCheckbox11.setBounds(28, 216, 463, 27); ivjCheckbox11.setLabel("Solução com o menor número de faltas ignorando o grau de sucesso."); ivjCheckbox11.setState(false); } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); } }; return ivjCheckbox11; } // Definição das características da Checkbox 3(Escolha da Solução) private java.awt.Checkbox getCheckbox12() { if (ivjCheckbox12 == null) { try { ivjCheckbox12 = new java.awt.Checkbox(); ivjCheckbox12.setName("Checkbox12"); ivjCheckbox12.setCheckboxGroup(getCheckboxGroup1()); ivjCheckbox12.setBounds(28, 244, 463, 27); ivjCheckbox12.setLabel("Solução com o melhor sucesso possível ignorando o nº de faltas."); ivjCheckbox12.setState(false); } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); } }; return ivjCheckbox12; } // Definição das características da Checkbox4(Escolha da Solução) private java.awt.Checkbox getCheckbox13() { if (ivjCheckbox13 == null) { try { ivjCheckbox13 = new java.awt.Checkbox(); ivjCheckbox13.setName("Checkbox13"); ivjCheckbox13.setCheckboxGroup(getCheckboxGroup1()); ivjCheckbox13.setBounds(28, 269, 463, 27); ivjCheckbox13.setLabel("Esboçar os três tipos de soluções para depois decidir."); ivjCheckbox13.setState(false); WEB Agenda- Sistemas Periciais } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); } }; return ivjCheckbox13; } // Definição das características do Grupo de Checkboxes private java.awt.CheckboxGroup getCheckboxGroup1() { if (ivjCheckboxGroup1 == null) { try { ivjCheckboxGroup1 = new java.awt.CheckboxGroup(); } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); } }; return ivjCheckboxGroup1; } // Definição das características da Choice 1 (Escolha dos dias-inicio do intervalo) private java.awt.Choice getChoice1() { if (ivjChoice1 == null) { try { ivjChoice1 = new Choice(); ivjChoice1.setName("Choice1"); ivjChoice1.setBackground(java.awt.Color.white); ivjChoice1.setBounds(173, 79, 101, 22); for (int i=0;i<5;i++) ivjChoice1.add(week_days[i]); } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); } }; return ivjChoice1; } // Definição das características da Choice 2 (Escolha dos dias-fim do intervalo) private java.awt.Choice getChoice11() { if (ivjChoice11 == null) { try { ivjChoice11 = new Choice(); ivjChoice11.setName("Choice11"); ivjChoice11.setBackground(java.awt.Color.white); ivjChoice11.setBounds(368, 79, 101, 22); for (int i=0;i<5;i++) ivjChoice11.add(week_days[i]); } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); } }; return ivjChoice11; } // Definição das características da Choice 3 (Escolha do sucesso) private java.awt.Choice getChoice12() { if (ivjChoice12 == null) { try { ivjChoice12 = new Choice(); ivjChoice12.setName("Choice12"); ivjChoice12.setBackground(java.awt.Color.white); pág. 100 WEB Agenda- Sistemas Periciais ivjChoice12.setBounds(90, 121, 57, 23); for (int i=0;i<10;i++) ivjChoice12.add(percents[i]); // user code begin {1} // user code end } catch (java.lang.Throwable ivjExc) { // user code begin {2} // user code end handleException(ivjExc); } }; return ivjChoice12; } // Definição das características da Frame private void getFrame1() { setResizable(false); setLayout(null); setBackground(new Color(191, 223, 253)); setFont(new java.awt.Font("Dialog", 0, 12)); setBounds(162, 12, 500, 362); setTitle("Opções"); // Adição dos componentes à Frame add(getChoice1(), getChoice1().getName()); add(getLabel1(), getLabel1().getName()); add(getLabel11(), getLabel11().getName()); add(getLabel12(), getLabel12().getName()); add(getChoice11(), getChoice11().getName()); add(getLabel13(), getLabel13().getName()); add(getChoice12(), getChoice12().getName()); add(getTextField1(), getTextField1().getName()); add(getLabel14(), getLabel14().getName()); add(getButton1(), getButton1().getName()); add(getButton11(), getButton11().getName()); add(getLabel15(), getLabel15().getName()); add(getCheckbox1(), getCheckbox1().getName()); add(getCheckbox11(), getCheckbox11().getName()); add(getCheckbox12(), getCheckbox12().getName()); add(getCheckbox13(), getCheckbox13().getName()); add(getButton2(), getButton2().getName()); } // Definição das características da Label 1 private java.awt.Label getLabel1() { if (ivjLabel1 == null) { try { ivjLabel1 = new java.awt.Label(); ivjLabel1.setName("Label1"); ivjLabel1.setFont(new java.awt.Font("dialog", 0, 13)); ivjLabel1.setText("Seleccione as opções de refinamento da solução:"); ivjLabel1.setBounds(28, 28, 364, 26); } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); } }; return ivjLabel1; } // Definição das características da Label 2 private java.awt.Label getLabel11() { if (ivjLabel11 == null) { try { ivjLabel11 = new java.awt.Label(); ivjLabel11.setName("Label11"); ivjLabel11.setBackground(new Color(191, 223, 253)); pág. 101 WEB Agenda- Sistemas Periciais ivjLabel11.setFont(new java.awt.Font("dialog", 1, 12)); ivjLabel11.setText("Intervalo Temporal:"); ivjLabel11.setBounds(28, 76, 110, 27); } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); } }; return ivjLabel11; } // Definição das características da Label 3 private java.awt.Label getLabel12() { if (ivjLabel12 == null) { try { ivjLabel12 = new java.awt.Label(); ivjLabel12.setName("Label12"); ivjLabel12.setBackground(new Color(191, 223, 253)); ivjLabel12.setFont(new java.awt.Font("dialog", 1, 12)); ivjLabel12.setText("Até"); ivjLabel12.setBounds(309, 76, 25, 27); } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); } }; return ivjLabel12; } // Definição das características da Label 4 private java.awt.Label getLabel13() { if (ivjLabel13 == null) { try { ivjLabel13 = new java.awt.Label(); ivjLabel13.setName("Label13"); ivjLabel13.setFont(new java.awt.Font("dialog", 1, 12)); ivjLabel13.setText("Sucesso"); ivjLabel13.setBackground(new Color(191, 223, 253)); ivjLabel13.setBounds(28, 118, 62, 26); } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); } }; return ivjLabel13; } // Definição das características da Label 5 private java.awt.Label getLabel14() { if (ivjLabel14 == null) { try { ivjLabel14 = new java.awt.Label(); ivjLabel14.setName("Label14"); ivjLabel14.setBackground(new Color(191, 223, 253)); ivjLabel14.setFont(new java.awt.Font("dialog", 1, 12)); ivjLabel14.setText("Nº Ausências"); ivjLabel14.setBounds(325, 121,85, 23); } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); } }; return ivjLabel14; pág. 102 WEB Agenda- Sistemas Periciais } // Definição das características da Label 6 private java.awt.Label getLabel15() { if (ivjLabel15 == null) { try { ivjLabel15 = new java.awt.Label(); ivjLabel15.setName("Label15"); ivjLabel15.setBackground(new Color(191, 223, 253)); ivjLabel15.setFont(new java.awt.Font("dialog", 1, 12)); ivjLabel15.setText("Tipo de solução desejada :"); ivjLabel15.setBounds(28, 156, 196, 32); } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); } }; return ivjLabel15; } // Campo correspondente ao nº de Faltas máxima private java.awt.TextField getTextField1() { if (ivjTextField1 == null) { try { ivjTextField1 = new java.awt.TextField(); ivjTextField1.setName("TextField1"); ivjTextField1.setBackground(java.awt.Color.white); ivjTextField1.setBounds(413, 121, 34, 23); ivjTextField1.setEditable(false); ivjTextField1.setText("0"); } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); } }; return ivjTextField1; } // Método responsável pelo tratamento de excepções dos Componentes private void handleException(Throwable exception) { System.out.println("--------- UNCAUGHT EXCEPTION ---------"); } // Método responsável pela Inicialização private void initialize() { // Inicialização da Label 7 ivjLabel16 = new java.awt.Label(); ivjLabel16.setName("Label14"); ivjLabel16.setFont(new java.awt.Font("dialog", 1, 12)); ivjLabel16.setText("Nº Iterações"); ivjLabel16.setBounds(163, 121, 80, 23); // Inicialização da Choice 4 ivjChoice13 = new Choice(); ivjChoice13.setName("Choice12"); ivjChoice13.setBackground(java.awt.Color.white); ivjChoice13.setBounds(240, 121, 70, 23); // Colocação do nº de Iterações na Choice 4 for (int i=0;i<7;i++) ivjChoice13.add(iterations[i]); pág. 103 WEB Agenda- Sistemas Periciais pág. 104 // Chama o método responsável pela configuração da Frame getFrame1(); add(ivjLabel16); add(ivjChoice13); show(); } // Activação da Janela public void windowActivated (WindowEvent e ) { } // Fecho da Janela public void windowClosed(WindowEvent e ) { return; } public void windowClosing(WindowEvent e ) { Window originator=e.getWindow(); if (originator.equals(this)) { this.hide(); this.dispose(); } } // Desactivação da Janela public void windowDeactivated(WindowEvent e ) { return; } public void windowDeiconified(WindowEvent e ) { return; } public void windowIconified(WindowEvent e ) { return; } public void windowOpened(WindowEvent e ) { return; } } 2.15 Classe Display_Solution Esta classe encarrega-se de mostrar a solução obtida (no caso de uma das 3 primeiras soluções). O seu constructor recebe como parâmetros de entrada o dia da reunião, a hora, o sucesso, o nº de pessoas ausentes e o nome das pessoas ausentes. Este objecto é também uma Frame. Segue-se a listagem do código referente a esta classe. import java.awt.*; public class Display_Solution extends Frame{ // Declaração das variáveis private java.awt.Button dsjButton1 = null; private java.awt.Button dsjButton11 = null; private java.awt.Label ivjLabel1 = null; private java.awt.Label ivjLabel2 = null; private java.awt.Label ivjLabel21 = null; private java.awt.Label ivjLabel22 = null; WEB Agenda- Sistemas Periciais private java.awt.Label ivjLabel3 = null; private java.awt.Label ivjLabel4 = null; private java.awt.Label ivjLabel41 = null; private java.awt.List ivjList1 = null; private java.awt.Panel ivjPanel1 = null; private java.awt.ScrollPane ivjScrollPane1 = null; private java.awt.TextField ivjTextField1 = null; private java.awt.TextField ivjTextField11 = null; private java.awt.TextField ivjTextField12 = null; private java.awt.TextField ivjTextField121 = null; String day,hour; String ausent_people[]; int number_of_falts; double success; boolean solution_option,wait; // Constructor public Display_Solution(String d,String h,double s,int na,String people[] ) { super(); // Inicialização das variáveis wait=true; day=d; hour=h; success=s; number_of_falts=na; ausent_people=people; // Chama inicialização initialize(); } // Método responsável pelo tratamento dos eventos da Janela public boolean action(Event e,Object o ) { // Se o evento é do tipo botão if (e.target instanceof Button) { // Se escolheu marcar if (e.target==dsjButton1) { solution_option=true; hide(); dispose(); wait=false; } // Se escolheu cancelar if (e.target==dsjButton11) { solution_option=false; hide(); dispose(); wait=false; } } return true; } // Definição das características do Botão 1 (Marcar) private java.awt.Button getButton1() { if (dsjButton1 == null) { try { dsjButton1 = new java.awt.Button(); dsjButton1.setName("Button1"); dsjButton1.setFont(new java.awt.Font("dialog", 0, 11)); pág. 105 WEB Agenda- Sistemas Periciais dsjButton1.setBounds(226, 235, 90, 24); dsjButton1.setLabel("Marcar"); } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); } }; return dsjButton1; } // Definição das características do Botão 2 (Cancelar) private java.awt.Button getButton11() { if (dsjButton11 == null) { try { dsjButton11 = new java.awt.Button(); dsjButton11.setName("Button11"); dsjButton11.setFont(new java.awt.Font("dialog", 0, 11)); dsjButton11.setBounds(226, 277, 90, 24); dsjButton11.setLabel("Cancelar"); } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); } }; return dsjButton11; } // Definição das características da Frame private void getFrame1() { setTitle("Solução Obtida"); setLayout(null); setBackground(java.awt.SystemColor.activeCaptionBorder); setBounds(44, 26, 404, 357); setResizable(false); // Colocação dos Componentes na Janela add(getLabel1(), getLabel1().getName()); add(getLabel2(), getLabel2().getName()); add(getLabel3(), getLabel3().getName()); add(getTextField1(), getTextField1().getName()); add(getTextField11(), getTextField11().getName()); add(getLabel4(), getLabel4().getName()); add(getTextField12(), getTextField12().getName()); add(getLabel41(), getLabel41().getName()); add(getTextField121(), getTextField121().getName()); add(getLabel21(), getLabel21().getName()); add(getList1(), getList1().getName()); } // Definição das características da Label 1 private java.awt.Label getLabel1() { if (ivjLabel1 == null) { try { ivjLabel1 = new java.awt.Label(); ivjLabel1.setName("Label1"); ivjLabel1.setFont(new java.awt.Font("dialog", 0, 12)); ivjLabel1.setText("Solução obtida segundo as suas opções: "); ivjLabel1.setBounds(30, 25, 264, 28); } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); } }; pág. 106 WEB Agenda- Sistemas Periciais return ivjLabel1; } // Definição das características da Label 2 private java.awt.Label getLabel2() { if (ivjLabel2 == null) { try { ivjLabel2 = new java.awt.Label(); ivjLabel2.setName("Label2"); ivjLabel2.setFont(new java.awt.Font("dialog", 1, 12)); ivjLabel2.setText("Dia"); ivjLabel2.setBounds(30, 66, 21, 32); } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); } }; return ivjLabel2; } // Definição das características da Label 3 private java.awt.Label getLabel21() { if (ivjLabel21 == null) { try { ivjLabel21 = new java.awt.Label(); ivjLabel21.setName("Label21"); ivjLabel21.setFont(new java.awt.Font("dialog", 1, 12)); ivjLabel21.setText("Pessoas Ausentes:"); ivjLabel21.setBounds(30, 176, 116, 33); } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); } }; return ivjLabel21; } // Definição das características da Label 4 private java.awt.Label getLabel22() { if (ivjLabel22 == null) { try { ivjLabel22 = new java.awt.Label(); ivjLabel22.setName("Label22"); ivjLabel22.setFont(new java.awt.Font("dialog", 2, 12)); ivjLabel22.setText("Prosseguir com a marcação ? "); ivjLabel22.setBounds(451, 265, 211, 29); } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); } }; return ivjLabel22; } // Definição das características da Label 5 private java.awt.Label getLabel3() { if (ivjLabel3 == null) { try { ivjLabel3 = new java.awt.Label(); ivjLabel3.setName("Label3"); ivjLabel3.setFont(new java.awt.Font("dialog", 1, 12)); ivjLabel3.setText("Hora"); ivjLabel3.setBounds(238, 68, 36, 30); pág. 107 WEB Agenda- Sistemas Periciais } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); } }; return ivjLabel3; } // Definição das características da Label 6 private java.awt.Label getLabel4() { if (ivjLabel4 == null) { try { ivjLabel4 = new java.awt.Label(); ivjLabel4.setName("Label4"); ivjLabel4.setFont(new java.awt.Font("dialog", 1, 12)); ivjLabel4.setText("Grau de Sucesso"); ivjLabel4.setBounds(30, 123, 100, 30); } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); } }; return ivjLabel4; } // Definição das características da Label 7 private java.awt.Label getLabel41() { if (ivjLabel41 == null) { try { ivjLabel41 = new java.awt.Label(); ivjLabel41.setName("Label41"); ivjLabel41.setFont(new java.awt.Font("dialog", 1, 12)); ivjLabel41.setText("Nº Ausências"); ivjLabel41.setBounds(226, 123, 85, 30); } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); } }; return ivjLabel41; } // Definição das características da Lista de Ausências private java.awt.List getList1() { if (ivjList1 == null) { try { ivjList1 = new java.awt.List(); ivjList1.setName("List1"); ivjList1.setBackground(java.awt.Color.white); ivjList1.setBounds(32, 211, 99, 119); } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); } }; return ivjList1; } // Adição dos Botões e da Label à Frame private java.awt.Panel getPanel1() { if (ivjPanel1 == null) { try { add(getLabel22(), getLabel22().getName()); add(getButton1(), getButton1().getName()); pág. 108 WEB Agenda- Sistemas Periciais add(getButton11(), getButton11().getName()); } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); } }; return ivjPanel1; } // Definição das características do campo 1(Dia) private java.awt.TextField getTextField1() { if (ivjTextField1 == null) { try { ivjTextField1 = new java.awt.TextField(); ivjTextField1.setName("TextField1"); ivjTextField1.setBackground(java.awt.Color.white); ivjTextField1.setBounds(72, 70, 84, 25); } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); } }; return ivjTextField1; } // Definição das características do campo 2(Hora) private java.awt.TextField getTextField11() { if (ivjTextField11 == null) { try { ivjTextField11 = new java.awt.TextField(); ivjTextField11.setName("TextField11"); ivjTextField11.setBackground(java.awt.Color.white); ivjTextField11.setBounds(285, 71, 84, 25); } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); } }; return ivjTextField11; } // Definição das características do campo 3(Sucesso) private java.awt.TextField getTextField12() { if (ivjTextField12 == null) { try { ivjTextField12 = new java.awt.TextField(); ivjTextField12.setName("TextField12"); ivjTextField12.setBackground(java.awt.Color.white); ivjTextField12.setBounds(140, 128, 52, 23); } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); } }; return ivjTextField12; } // Definição das características do campo 4(Nº de Ausências) private java.awt.TextField getTextField121() { if (ivjTextField121 == null) { try { ivjTextField121 = new java.awt.TextField(); ivjTextField121.setName("TextField121"); ivjTextField121.setBackground(java.awt.Color.white); pág. 109 WEB Agenda- Sistemas Periciais pág. 110 ivjTextField121.setBounds(317, 128, 52, 23); } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); } }; return ivjTextField121; } // Método responsável pelo tratamento de excepções dos Componentes private void handleException(Throwable exception) { System.out.println("--------- UNCAUGHT EXCEPTION ---------"); } // Inicialização private void initialize() { // Inicialização das variáveis solution_option=false; // Definição das características da Frame getFrame1(); // Adição de Alguns componentes à Frame getPanel1(); // Adição do nome de pessoas ausentes for (int i=0;i<number_of_falts;i++) ivjList1.addItem(ausent_people[i]); // Escrita da Solução ivjTextField1.setText(day); ivjTextField11.setText(hour); ivjTextField12.setText(String.valueOf(success)); ivjTextField121.setText(String.valueOf(number_of_falts)); show(); } } 2.16 Classe Display_3_Solution Classe responsável pelo display do tipo de solução 4, na qual são apresentadas as 3 soluções e o utilizador tem a última palavra a dizer. Este objecto representa também uma Frame. Este recebe como parâmetros de entrada as 3 soluções que o sistema encontrou. Segue-se a listagem de código referente a este objecto. import java.awt.*; public class Display_3_Solution extends Frame { // Declaração das variáveis private java.awt.Button d3sButton1 = null; private java.awt.Button d3sButton11 = null; private java.awt.Button d3sButton12 = null; private java.awt.Button d3sButton13 = null; private java.awt.Button d3sButton14 = null; private java.awt.Checkbox ivjCheckbox1 = null; private java.awt.Checkbox ivjCheckbox11 = null; private java.awt.Checkbox ivjCheckbox12 = null; private java.awt.CheckboxGroup ivjCheckboxGroup1 = null; private java.awt.Frame ivjFrame1 = null; private java.awt.Label ivjLabel1 = null; private java.awt.Label ivjLabel11 = null; private java.awt.Label ivjLabel111 = null; WEB Agenda- Sistemas Periciais private java.awt.Label ivjLabel2 = null; private java.awt.Label ivjLabel21 = null; private java.awt.Label ivjLabel22 = null; private java.awt.Label ivjLabel23 = null; private java.awt.Label ivjLabel231 = null; private java.awt.List ivjList1 = null; private java.awt.Panel ivjPanel1 = null; private java.awt.Panel ivjPanel2 = null; private java.awt.ScrollPane ivjScrollPane1 = null; private java.awt.TextField ivjTextField1 = null; private java.awt.TextField ivjTextField11 = null; private java.awt.TextField ivjTextField12 = null; private java.awt.TextField ivjTextField13 = null; private String week_days[]={"Segunda","Terça","Quarta","Quinta", "Sexta"}; private String hours[]={"8h00m","9h00m","10h00m","11h00m","14h00m", "15h00m","16h00m","17h00m","18h00m","19h00m"}; Solution solution1,solution2,solution3; int solution_option; boolean wait; // Constructor public Display_3_Solution(Solution s1,Solution s2,Solution s3) { super(); // Inicialização das variáveis solution1=s1; solution2=s2; solution3=s3; wait=true; // Chama a inicialização initialize(); } // Definição das características do botão 1(Solução 1) private java.awt.Button getButton1() { if (d3sButton1 == null) { try { d3sButton1 = new java.awt.Button(); d3sButton1.setName("Button1"); d3sButton1.setFont(new java.awt.Font("dialog", 0, 11)); d3sButton1.setBounds(343, 54, 80, 21); d3sButton1.setLabel("Solução 1"); } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); } }; return d3sButton1; } // Definição das características do botão 2(Solução 2) private java.awt.Button getButton11() { if (d3sButton11 == null) { try { d3sButton11 = new java.awt.Button(); d3sButton11.setName("Button11"); d3sButton11.setFont(new java.awt.Font("dialog", 0, 11)); d3sButton11.setBounds(343, 93, 80, 21); d3sButton11.setLabel("Solução 2"); } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); pág. 111 WEB Agenda- Sistemas Periciais } }; return d3sButton11; } // Definição das características do botão 3(Solução 3) private java.awt.Button getButton12() { if (d3sButton12 == null) { try { d3sButton12 = new java.awt.Button(); d3sButton12.setName("Button12"); d3sButton12.setFont(new java.awt.Font("dialog", 0, 11)); d3sButton12.setBounds(343, 132, 80, 21); d3sButton12.setLabel("Solução 3"); } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); } }; return d3sButton12; } // Definição das características do botão 4(Cancelar) private java.awt.Button getButton13() { if (d3sButton13 == null) { try { d3sButton13 = new java.awt.Button(); d3sButton13.setName("Button13"); d3sButton13.setFont(new java.awt.Font("dialog", 0, 11)); d3sButton13.setBounds(317, 307, 80, 21); d3sButton13.setLabel("Cancelar"); } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); } }; return d3sButton13; } // Definição das características do botão 5(Marcar) private java.awt.Button getButton14() { if (d3sButton14 == null) { try { d3sButton14 = new java.awt.Button(); d3sButton14.setName("Button14"); d3sButton14.setFont(new java.awt.Font("dialog", 0, 11)); d3sButton14.setBounds(317, 267, 80, 21); d3sButton14.setLabel("Marcar"); } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); } }; return d3sButton14; } // Definição das características da Checkbox 1( Escolha da Solução 1) private java.awt.Checkbox getCheckbox1() { if (ivjCheckbox1 == null) { try { ivjCheckbox1 = new java.awt.Checkbox(); ivjCheckbox1.setName("Checkbox1"); ivjCheckbox1.setCheckboxGroup(getCheckboxGroup1()); pág. 112 WEB Agenda- Sistemas Periciais ivjCheckbox1.setFont(new java.awt.Font("dialog", 0, 11)); ivjCheckbox1.setBounds(174,220, 70, 29); ivjCheckbox1.setLabel("Solução 1"); ivjCheckbox1.setState(true); } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); } }; return ivjCheckbox1; } // Definição das características da Checkbox 2( Escolha da Solução 2) private java.awt.Checkbox getCheckbox11() { if (ivjCheckbox11 == null) { try { ivjCheckbox11 = new java.awt.Checkbox(); ivjCheckbox11.setName("Checkbox11"); ivjCheckbox11.setCheckboxGroup(getCheckboxGroup1()); ivjCheckbox11.setFont(new java.awt.Font("dialog", 0, 11)); ivjCheckbox11.setBounds(259, 220, 70, 29); ivjCheckbox11.setLabel("Solução 2"); ivjCheckbox11.setState(false); } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); } }; return ivjCheckbox11; } // Definição das características da Checkbox 3( Escolha da Solução 3) private java.awt.Checkbox getCheckbox12() { if (ivjCheckbox12 == null) { try { ivjCheckbox12 = new java.awt.Checkbox(); ivjCheckbox12.setName("Checkbox12"); ivjCheckbox12.setCheckboxGroup(getCheckboxGroup1()); ivjCheckbox12.setFont(new java.awt.Font("dialog", 0, 11)); ivjCheckbox12.setBounds(343, 220, 70, 29); ivjCheckbox12.setLabel("Solução 3"); ivjCheckbox12.setState(false); } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); } }; return ivjCheckbox12; } // Definição das características do grupo das Checkboxs private java.awt.CheckboxGroup getCheckboxGroup1() { if (ivjCheckboxGroup1 == null) { try { ivjCheckboxGroup1 = new java.awt.CheckboxGroup(); } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); } }; return ivjCheckboxGroup1; } pág. 113 WEB Agenda- Sistemas Periciais // Definição das características da Frame private void getFrame1() { setLayout(null); setBackground(java.awt.SystemColor.activeCaptionBorder); setBounds(35, 34, 457, 351); // Adição dos componentes à Frame add(getLabel1(), getLabel1().getName()); add(getLabel2(), getLabel2().getName()); add(getTextField1(), getTextField1().getName()); add(getLabel21(), getLabel21().getName()); add(getTextField11(), getTextField11().getName()); add(getLabel22(), getLabel22().getName()); add(getTextField12(), getTextField12().getName()); add(getLabel23(), getLabel23().getName()); add(getTextField13(), getTextField13().getName()); getPanel1(); add(getLabel231(), getLabel231().getName()); add(getList1(), getList1().getName()); } // Definição das características da Label 1 private java.awt.Label getLabel1() { if (ivjLabel1 == null) { try { ivjLabel1 = new java.awt.Label(); ivjLabel1.setName("Label1"); ivjLabel1.setFont(new java.awt.Font("dialog", 1, 12)); ivjLabel1.setText("Clique nos botões para ver as soluções obtidas"); ivjLabel1.setBounds(23, 22, 290, 30); } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); } }; return ivjLabel1; } // Definição das características da Label 2 private java.awt.Label getLabel11() { if (ivjLabel11 == null) { try { ivjLabel11 = new java.awt.Label(); ivjLabel11.setName("Label11"); ivjLabel11.setFont(new java.awt.Font("dialog", 3, 12)); ivjLabel11.setText("Solução mais adequada :"); ivjLabel11.setBounds(177,185, 241, 29); } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); } }; return ivjLabel11; } // Definição das características da Label 3 private java.awt.Label getLabel111() { if (ivjLabel111 == null) { try { ivjLabel111 = new java.awt.Label(); ivjLabel111.setName("Label111"); ivjLabel111.setFont(new java.awt.Font("dialog", 3, 12)); pág. 114 WEB Agenda- Sistemas Periciais ivjLabel111.setText("Deseja marcar ?"); ivjLabel111.setBounds(177, 258, 121, 29); } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); } }; return ivjLabel111; } // Definição das características da Label 4 private java.awt.Label getLabel2() { if (ivjLabel2 == null) { try { ivjLabel2 = new java.awt.Label(); ivjLabel2.setName("Label2"); ivjLabel2.setFont(new java.awt.Font("dialog", 1, 12)); ivjLabel2.setText("Dia"); ivjLabel2.setBounds(24, 63, 22, 28); } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); } }; return ivjLabel2; } // Definição das características da Label 5 private java.awt.Label getLabel21() { if (ivjLabel21 == null) { try { ivjLabel21 = new java.awt.Label(); ivjLabel21.setName("Label21"); ivjLabel21.setFont(new java.awt.Font("dialog", 1, 12)); ivjLabel21.setText("Hora"); ivjLabel21.setBounds(177, 63, 31, 28); } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); } }; return ivjLabel21; } // Definição das características da Label 6 private java.awt.Label getLabel22() { if (ivjLabel22 == null) { try { ivjLabel22 = new java.awt.Label(); ivjLabel22.setName("Label22"); ivjLabel22.setFont(new java.awt.Font("dialog", 1, 12)); ivjLabel22.setText("Nº Ausências"); ivjLabel22.setBounds(167, 116, 75, 29); } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); } }; return ivjLabel22; } // Definição das características da Label 7 private java.awt.Label getLabel23() { pág. 115 WEB Agenda- Sistemas Periciais if (ivjLabel23 == null) { try { ivjLabel23 = new java.awt.Label(); ivjLabel23.setName("Label23"); ivjLabel23.setFont(new java.awt.Font("dialog", 1, 12)); ivjLabel23.setText("Sucesso"); ivjLabel23.setBounds(23, 118, 55, 27); } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); } }; return ivjLabel23; } // Definição das características da Label 8 private java.awt.Label getLabel231() { if (ivjLabel231 == null) { try { ivjLabel231 = new java.awt.Label(); ivjLabel231.setName("Label231"); ivjLabel231.setFont(new java.awt.Font("dialog", 1, 12)); ivjLabel231.setText("Lista de Ausências"); ivjLabel231.setBounds(21, 162, 116, 26); } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); } }; return ivjLabel231; } // Definição das características da Lista de Ausências private java.awt.List getList1() { if (ivjList1 == null) { try { ivjList1 = new java.awt.List(); ivjList1.setName("List1"); ivjList1.setBackground(java.awt.Color.white); ivjList1.setBounds(22, 194, 109, 139); } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); } }; return ivjList1; } // Adição dos botões de solução private void getPanel1() { add(getButton1(), getButton1().getName()); add(getButton11(), getButton11().getName()); add(getButton12(), getButton12().getName()); } // Adição de 2 botões e uma label private void getPanel2() { add(getLabel111(), getLabel111().getName()); add(getButton13(), getButton13().getName()); add(getButton14(), getButton14().getName()); } pág. 116 WEB Agenda- Sistemas Periciais // Definição das Características do campo 1 (Dia) private java.awt.TextField getTextField1() { if (ivjTextField1 == null) { try { ivjTextField1 = new java.awt.TextField(); ivjTextField1.setName("TextField1"); ivjTextField1.setBackground(java.awt.Color.white); ivjTextField1.setBounds(53, 66, 91, 22); } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); } }; return ivjTextField1; } // Definição das Características do campo 2 (Hora) private java.awt.TextField getTextField11() { if (ivjTextField11 == null) { try { ivjTextField11 = new java.awt.TextField(); ivjTextField11.setName("TextField11"); ivjTextField11.setBackground(java.awt.Color.white); ivjTextField11.setBounds(217, 66, 84, 22); } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); } }; return ivjTextField11; } // Definição das Características do campo 3 (Sucesso) private java.awt.TextField getTextField12() { if (ivjTextField12 == null) { try { ivjTextField12 = new java.awt.TextField(); ivjTextField12.setName("TextField12"); ivjTextField12.setBackground(java.awt.Color.white); ivjTextField12.setBounds(258, 120, 41, 22); } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); } }; return ivjTextField12; } // Definição das Características do campo 4(Nº de Ausências) private java.awt.TextField getTextField13() { if (ivjTextField13 == null) { try { ivjTextField13 = new java.awt.TextField(); ivjTextField13.setName("TextField13"); ivjTextField13.setBackground(java.awt.Color.white); ivjTextField13.setBounds(88, 120, 42, 22); } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); } }; return ivjTextField13; pág. 117 WEB Agenda- Sistemas Periciais pág. 118 } // Método responsável pelo tratamento dos eventos da Frame public boolean handleEvent(Event e) { // Declaração das variáveis String names_selected[]; solution_option=0; // Se foi carregado um botão if (e.target instanceof Button) { // Se foi carregado o botão Solução 1 if (e.target==d3sButton1) { // Mostra a Solução 1 names_selected=solution1.getfails(); ivjTextField1.setText(String.valueOf(week_days[solution1.getday()])); ivjTextField11.setText(String.valueOf(hours[solution1.gethour()])); ivjTextField12.setText(String.valueOf(solution1.getzeros())); ivjTextField13.setText(String.valueOf(solution1.getvalue())); ivjList1.removeAll(); for (int i=0;i<solution1.getzeros();i++) ivjList1.addItem(names_selected[i]); return true; } // Se foi carregado o botão Solução 2 if (e.target==d3sButton11) { // Mostra a Solução 2 names_selected=solution2.getfails(); ivjTextField1.setText(String.valueOf(week_days[solution2.getday()])); ivjTextField11.setText(String.valueOf(hours[solution2.gethour()])); ivjTextField12.setText(String.valueOf(solution2.getzeros())); ivjTextField13.setText(String.valueOf(solution2.getvalue())); ivjList1.removeAll(); for (int i=0;i<solution2.getzeros();i++) ivjList1.addItem(names_selected[i]); return true; } // Se foi carregado o botão Solução 3 if (e.target==d3sButton12) { // Mostra a Solução 3 names_selected=solution3.getfails(); ivjTextField1.setText(String.valueOf(week_days[solution3.getday()])); ivjTextField11.setText(String.valueOf(hours[solution3.gethour()])); ivjTextField12.setText(String.valueOf(solution3.getzeros())); ivjTextField13.setText(String.valueOf(solution3.getvalue())); ivjList1.removeAll(); for (int i=0;i<solution3.getzeros();i++) ivjList1.addItem(names_selected[i]); return true; } // Se foi carregado em Cancelar if (e.target==d3sButton13) { // Fecha a Janela wait=false; hide(); dispose(); return true; } // Se foi carregado em Marcar if (e.target==d3sButton14) { // Se foi escolhida a Solução 1 try{ pág. 119 WEB Agenda- Sistemas Periciais if (ivjCheckbox1.getState()) solution_option=1; } catch (NullPointerException h) { // Se não existe Solução 1 e Se foi escolhida a Solução 2 try { if (ivjCheckbox11.getState()) solution_option=2; } catch (NullPointerException f){ // Se não existe Solução 2 e Se foi escolhida a Solução 3 try { if (ivjCheckbox12.getState()) solution_option=3; } // Senão não existe solução catch (NullPointerException g) { System.out.println("Não existe solução"); } } } try { // Se foi escolhida a Solução 2 if (ivjCheckbox11.getState()) solution_option=2; } catch (NullPointerException f){ // Se não existe a Solução 2 e foi escolhida a Solução 3 try { if (ivjCheckbox12.getState()) solution_option=3; } catch (NullPointerException g) { System.out.println("Não existe solução"); } } // Se foi escolhida a Solução 3 try { if (ivjCheckbox12.getState()) solution_option=3; } catch (NullPointerException g) { System.out.println("Não existe solução"); } // Fecha a Janela hide(); dispose(); wait=false; return true; } } return true; } WEB Agenda- Sistemas Periciais // Método que trata das Excepções dos Componentes do Ecran private void handleException(Throwable exception) { System.out.println("--------- UNCAUGHT EXCEPTION ---------"); } // Inicialização private void initialize() { // Definição da Frame getFrame1(); // Adição de Componentes do Ecran getPanel2(); add(ivjLabel11); String names_selected[]; try { // Adição de um campo ivjTextField1.setText(String.valueOf(week_days[solution1.getday()])); ivjTextField11.setText(String.valueOf(hours[solution1.gethour()])); ivjTextField12.setText(String.valueOf(solution1.getzeros())); ivjTextField13.setText(String.valueOf(solution1.getvalue())); names_selected=solution1.getfails(); for (int i=0;i<solution1.getzeros();i++) ivjList1.addItem(names_selected[i]); add(getCheckbox1(), getCheckbox1().getName()); // Se existir solução 2 coloca no Ecran a checkbox 2 if (solution2.getday()<5) add(getCheckbox11(), getCheckbox11().getName()); // Se existir solução 3 coloca no Ecran a checkbox 3 if (solution3.getday()<5) add(getCheckbox12(), getCheckbox12().getName()); show(); } // No caso de não existir solução 1 catch (ArrayIndexOutOfBoundsException e) { try { // Desactiva o botão de Solução 1 d3sButton1.disable(); ivjTextField1.setText(String.valueOf(week_days[solution2.getday()])); ivjTextField11.setText(String.valueOf(hours[solution2.gethour()])); ivjTextField12.setText(String.valueOf(solution2.getzeros())); ivjTextField13.setText(String.valueOf(solution2.getvalue())); names_selected=solution2.getfails(); // Coloca a Checkbox 2 relativamente à solução 2 for (int i=0;i<solution2.getzeros();i++) ivjList1.addItem(names_selected[i]); add(getCheckbox11(), getCheckbox11().getName()); // Se existir Solução 3 coloca no ecran if (solution3.getday()<5) add(getCheckbox12(), getCheckbox12().getName()); show(); } catch (ArrayIndexOutOfBoundsException f) { // Se não existir solução 2 try { // Desactiva o botão de solução 2 d3sButton11.disable(); ivjTextField1.setText(String.valueOf(week_days[solution3.getday()])); ivjTextField11.setText(String.valueOf(hours[solution3.gethour()])); ivjTextField12.setText(String.valueOf(solution3.getzeros())); pág. 120 WEB Agenda- Sistemas Periciais pág. 121 ivjTextField13.setText(String.valueOf(solution3.getvalue())); names_selected=solution3.getfails(); for (int i=0;i<solution3.getzeros();i++) ivjList1.addItem(names_selected[i]); // Coloca a Checkbox relativamente à solução 3 add(getCheckbox12(), getCheckbox12().getName()); show(); } // Senão, não existe nenhuma solução catch (ArrayIndexOutOfBoundsException g) { d3sButton12.disable(); Error_handler error; error=new Error_handler("","Não foi possível obter nenhuma solução"); } } } } // Desenha os fundos onde os botões estão colocados public void paint(Graphics g ) { g.setColor(new Color(174, 174, 174)); g.fill3DRect(325, 44, 116, 123,false); g.fill3DRect(307,255,100,85,false); } } 2.17 Classe Solution Esta classe representa uma solução, isto é, permite guarda as informações sobre uma solução tais como todas as preferências diferentes de zero, o dia e a hora da reunião, o valor do sucesso, o nome das pessoas que vão estar ausentes, e o nº de falhas. Segue-se a listagem de código relativa a este objecto. public class Solution { // Declaração das variáveis private int zeros; private int day,hour; private double value; private Double preferences[]; private String fails[]; // Constructor public Solution(Double pref[],int d,int h,double v,int z,String f[]) { // Inicialização das variáveis zeros=z; day=d; hour=h; preferences=pref; value=v; zeros=z; fails=f; } // Este método retorna o dia da reunião public int getday ( ) { return day; } // Este método retorna um array de String com o nome das pessoas que vão estar ausentes public String[] getfails( ) { WEB Agenda- Sistemas Periciais pág. 122 return fails; } // Este método retorna a hora da reunião public int gethour( ) { return hour; } // Este método retorna um array de Double’s com o valor das preferências public Double[] getpreferences( ) { return preferences; } // Este método retorna o valor do sucesso public double getvalue ( ) { return value; } // Este método retorna o nº de ausências public int getzeros ( ) { return zeros; } } 2.18 Classe Instance Esta classe representa um objecto que constitui uma instância das agendas de cada utilizador, isto é, cada agenda é um conjunto de instancias deste tipo. Cada instância contém a preferência associada a um dia numa determinada hora. O seu constructor recebe portanto, um dia, uma hora e a preferência associada. Seguese a listagem do código respectiva a este objecto. import java.awt.*; import java.applet.Applet; public class Instance extends Frame { // Declaração das variáveis private int day,hour; private double pref; // Constructor public Instance (int d,int h,double ivjChoice) { super("Resultados dos items Seleccionados:"); // Inicialização das variáveis day=d; hour=h; pref=ivjChoice; } // Este método retorna o dia public int getday ( ) { return day; } // Este método retorna a preferência public double getdisp ( ) { return pref; } // Este método retorna a hora public int gethour ( ) { WEB Agenda- Sistemas Periciais pág. 123 return hour; } } 2.19 Classe LinkedList Esta classe constitui uma implementação de uma “queue” através de uma lista ligada. Cada instância da lista é do tipo Instance. Segue-se a listagem do código referente a este objecto. import java.awt.*; public class LinkedList { // Declaração das Variáveis private Node firstnode; private Node lastnode; // Constructor public LinkedList() { // Constroi lista vazia firstnode=lastnode=null; } // Verifica a existência de um elemento na lista public boolean exists (int day,int hour ) { boolean find=false; // Se a lista está vazia manda tratar da excepção if (isEmpty() ) throw new EmptyListException (); Node next; next=firstnode; // Enquanto não chegar ao fim da lista while (next!=null) { // Se encontrar a variável que retorna fica true if (next.data.getday()==day & next.data.gethour()==hour) { find=true; break; } next=next.next; } return find; } // Este método retorna o melhor elemento da lista tendo em conta a função heurística public Instance getbest (int i_day,int i_hour ) { // Declaração das variáveis int drm,hrm; double peso_d,peso_h,result,result_best; Node node,best; // Inicialização node=firstnode; best=firstnode; result_best=0.0; result=0.0; peso_d=0.4; WEB Agenda- Sistemas Periciais peso_h=0.3; // Enquanto não chegar ao fim da lista while (node!=null) { drm=Math.abs(i_day-node.data.getday()); hrm=Math.abs(i_hour-node.data.gethour()); result=node.data.getdisp()*(1-drm*peso_d/8-hrm*peso_h/18); // Se for melhor guarda if (result_best<result) { best=node; result_best=result; } // Se for igual vê se tem melhor preferência else if (result_best==result) { if (best.data.getdisp()<node.data.getdisp()) { best=node; result_best=result; } } node=node.next; } return best.data; } // Retorna o valor do cimo da lista public Instance getbestvalue ( ) { return firstnode.data; } // Inserir um elemento na lista por ordem de preferência public void insert (Instance insertItem ) { Node previous,next; // Se a lista está vazia este é o primeiro elemento if (isEmpty()) firstnode=lastnode=new Node(insertItem); // Se é melhor que o primeiro elemento então passa a ser o primeiro elemento else if (insertItem.getdisp()>firstnode.data.getdisp()) firstnode=new Node(insertItem,firstnode); // Se é pior que o último elemento então é o último elemento else if (insertItem.getdisp()<=lastnode.data.getdisp()) lastnode=lastnode.next=new Node(insertItem); // Senão está no meio na lista else { previous=next=firstnode; // Percorre a lista até encontrar o lugar de inserção while (insertItem.getdisp()<=next.data.getdisp()) { previous=next; next=next.next; } // Cria um novo nó previous.next=new Node(insertItem,next); } } pág. 124 WEB Agenda- Sistemas Periciais // Insere um elemento na frente da lista public void insertIntoFront (Instance propost ) { Node previous,next; // Se está vazia é o primeiro elemento if (isEmpty()) firstnode=lastnode=new Node(propost); // Senão passa a ser o primeiro elemento else firstnode=new Node(propost,firstnode); } // Este método verifica se o elemento item é o melhor da lista public boolean isBest (double item ) { // Declaração e inicialização das variáveis Instance temporary; temporary=firstnode.data; if (temporary.getdisp()>item) return false; else return true; } // Verifica se a lista está vazia public boolean isEmpty ( ) { return firstnode==null; } // Retira o primeiro elemento da lista public Instance removeFromFront() throws EmptyListException { // Declaração da variável Instance removeItem=null; // SE a lista está vazia trata da excepção if (isEmpty() ) throw new EmptyListException (); // Retira o elemento da lista removeItem=firstnode.data; // Se é o último elemento da lista então a lista fica vazia if (firstnode.equals(lastnode)) firstnode=lastnode=null; else firstnode=firstnode.next; return removeItem; } // Remove um elemento específico da lista public Instance removepropost (int d,int h) throws EmptyListException { // Declaração das variáveis Node next,previous; Instance temporary; boolean find=false; // Se a lista está vazia lança excepção if (isEmpty() ) throw new EmptyListException (); temporary=firstnode.data; next=firstnode; previous=firstnode; pág. 125 WEB Agenda- Sistemas Periciais pág. 126 // Enquanto não atingir o fim da lista while (next!=null) { // Se encontrou sai if (next.data.getday()==d & next.data.gethour()==h) { temporary=next.data; break; } // Passa a o próximo nó previous=next; next=next.next; } // Se só existe um elemento então a lista fica vazia if (firstnode.equals(lastnode)) firstnode=lastnode=null; // Se é o primeiro nó o segundo nó passa agora a ser o primeiro else if (next.equals(firstnode)) firstnode=firstnode.next; // Se é o último o anterior passa agora a ser o último else if (next.equals(lastnode)) lastnode=previous; else previous.next=next.next; return temporary; } } 2.20 Objecto Node Esta classe representa as instâncias que são adicionadas ou retiradas ao objecto LinkedList. Cada um dos Nodes tem 2 atributos que são um objecto do tipo Instance e um apontador para o próximo nó respectivamente. O constructor recebe como parâmetro de entrada um objecto Instance.Segue-se a listagem de código correspondente a este Objecto. public class Node { Instance data; Node next; // Constructor para nó a apontar para null public Node (Instance o) { data=o; next=null; } // Constructor para nó a apontar para outro nó public Node(Instance o,Node nextnode) { data=o; next=nextnode; } WEB Agenda- Sistemas Periciais pág. 127 // Este método retorna o próximo nó Node getNext() {return next;} // Este método retorna o objecto Instance referente a este nó Object getObject() {return data;} } 2.21 Classe EmptyListException Esta classe tem como função tratar as excepções que ocorrem devido à lista se encontrar vazia. Segue-se a listagem do código referente a esta classe. public class EmptyListException extends RuntimeException { // Constructor public EmptyListException() { super("A Lista não contém nenhum elemento"); } } 2.22 Classe Preferences_Matrix Esta classe é formada por um array de 2 dimensões em que a primeira dimensões representa o dia e a segunda a hora sendo guardada a preferência respeitante a esse dia e a essa hora. public class Preferences_Matrix { // Declaração das variáveis private double matrix[][]; // Constructor public Preferences_Matrix() { matrix=new double[5][10]; } // Este método retorna a preferência referente ao dia e hora especificados public double getpreference (int day,int hour ) { return matrix[day][hour]; } // Este método coloca a preferência referente ao dia e hora especificados public void putpreference (int day,int hour,double pref ) { matrix[day][hour]=pref; } } 2.23 Classe Reunion Este objecto representa o conceito de reunião, isto é, tem como atributos o assunto sobre o qual se vai falar, o nº de pessoas ausentes e o total e o sucesso WEB Agenda- Sistemas Periciais pág. 128 obtido na negociação. O seu constructor recebe como parâmetros de entrada os 3 atributos referidos na linha anterior. Segue a listagem do código deste objecto. import java.awt.*; public class Reunion { // Declaração das variáveis String talkabout; String present; String success; // Constructor public Reunion(String ta,String p,String s) { //Inicialização das variáveis talkabout=ta; present=p; success=s; } } 2.24 Classe Boolean_Matrix Esta classe representa uma matrix booleana, sendo constituida por um array de 2 dimensões em que a primeira constitui o dia e o segundo a hora, tendo assim um valor boolean associado. Esta matriz permite marcar os dias que já foram propostos na negociação ou que não podem ser propostos por motivo de indisponibilidade. Segue-se a listagem do código relativo a este objecto. public class Boolean_Matrix { // Declaração da variável private boolean matrix[][]; // Constructor public Boolean_Matrix() { matrix=new boolean[5][10]; // Inicialização da Matriz for (int i=0;i<5;i++) { for (int j=0;j<10;j++) matrix[i][j]=true; } } // Método que permite saber de um determinado dia pode ou não ser proposto public boolean getvalue (int day ,int hour ) { return matrix[day][hour]; } // Permite alterar o estado de um dia a uma dada hora de acordo com o valor Value que pode ser 1 ou 0 public void setvalue (int day,int hour,boolean value ) { matrix[day][hour]=value; } } pág. 129 WEB Agenda- Sistemas Periciais 2.25 Classe Special_Label Este objecto permite fazer um “Override” ao componente Label criando assim um tipo de Label que responde a eventos de entrada e saída do “mouse” na Label. O que se pretende é quando o “mouse” entar na Label, se houver, alguma reunião marcada, será criada uma janela que indica qual vai ser o assunto da reunião assim como o nº de ausências e o nº de presenças. O constructor deste objecto recebe como entrada um array de 2 dimensões de objectos Reunion. Segue-se a listagem do código referente a este objecto. import java.awt.*; import java.awt.event.MouseEvent; public class Special_Label extends Label { // Declaração das variáveis Window_Reunion reunion; Reunion records[][]; public Special_Label(Reunion r[][]) { super(); records=r; reunion=new Window_Reunion(); // Faz o enable dos Eventos do Rato enableEvents(AWTEvent.MOUSE_EVENT_MASK); } // Trata dos eventos do Rato protected void processMouseEvent(MouseEvent e) { // Declaração e Inicialização das Variáveis Point point,point1; point1=getLocation(); int x,y; x=20; y=20; // Determina a localização do rato for (int i=0;i<5;i++) { for (int j=0;j<10;j++) { if (point1.x==93+i*73) { x=i; if (point1.y==139+j*26) { y=j; break; } } } } // Se existe uma reunião nesse dia if (!records[x][y].talkabout.substring(0,1).equals("0")) { // Determina a localização da label no Ecran point=getLocationOnScreen(); // Mostra a Janela reunion.setbounds( point.x, (int) (point.y-95)); WEB Agenda- Sistemas Periciais pág. 130 reunion.getWindow().toFront(); reunion.writeValues(records[x][y]); reunion.getWindow().show(); } // Quando é detectada a saída if (e.getID()==MouseEvent.MOUSE_EXITED) { // Retira a Janela do Ecran reunion.getWindow().hide(); } super.processMouseEvent(e); } } 2.26 Classe Window_Reunion Esta classe é chamada pela Special_Label e tem como objectivo criar a janela que reporta informações sobre a reunião marcada no dia respectivo. Segue-se a listagem do código referente a esta classe. public class Window_Reunion { // Declaração de variáveis private java.awt.Label ivjLabel1 = null; private java.awt.Label ivjLabel11 = null; private java.awt.Label ivjLabel111 = null; private java.awt.Label ivjLabel112 = null; private java.awt.Label ivjLabel2 = null; private java.awt.Label ivjLabel3 = null; private java.awt.Window ivjWindow1 = null; // Constructor public Window_Reunion() { // Propriedades da janela ivjWindow1 = new java.awt.Window(new java.awt.Frame()); ivjWindow1.setName("Window1"); ivjWindow1.setLayout(null); ivjWindow1.setBackground(new java.awt.Color(255, 255, 225)); ivjWindow1.setBounds(39, 57, 237, 94); // Propriedades da label 1 ivjLabel1 = new java.awt.Label(); ivjLabel1.setName("Label1"); ivjLabel1.setAlignment(java.awt.Label.CENTER); ivjLabel1.setFont(new java.awt.Font("dialog", 1, 12)); ivjLabel1.setText("Reunião Marcada"); ivjLabel1.setBounds(57, 0, 125, 30); ivjWindow1.add(ivjLabel1); // Propriedades da label2 ivjLabel11 = new java.awt.Label(); ivjLabel11.setName("Label11"); ivjLabel11.setAlignment(java.awt.Label.CENTER); ivjLabel11.setFont(new java.awt.Font("dialog", 1, 12)); ivjLabel11.setText("Vão estar"); ivjLabel11.setBounds(11, 26, 60, 21); ivjWindow1.add(ivjLabel11); // Propriedades da label 3 ivjLabel111 = new java.awt.Label(); WEB Agenda- Sistemas Periciais ivjLabel111.setName("Label111"); ivjLabel111.setAlignment(java.awt.Label.CENTER); ivjLabel111.setFont(new java.awt.Font("dialog", 1, 12)); ivjLabel111.setText("pessoas ausentes"); ivjLabel111.setBounds(115, 26, 111, 21); ivjWindow1.add(ivjLabel111); // Propriedades da label 4 ivjLabel112 = new java.awt.Label(); ivjLabel112.setName("Label112"); ivjLabel112.setAlignment(java.awt.Label.CENTER); ivjLabel112.setFont(new java.awt.Font("dialog", 1, 12)); ivjLabel112.setText("Assunto :"); ivjLabel112.setBounds(9, 56, 52, 23); ivjWindow1.add(ivjLabel112); // Propriedades da label 5 ivjLabel2 = new java.awt.Label(); ivjLabel2.setName("Label111"); ivjLabel2.setAlignment(java.awt.Label.CENTER); ivjLabel2.setFont(new java.awt.Font("dialog", 1, 12)); ivjLabel2.setBounds(72, 28, 34, 19); ivjWindow1.add(ivjLabel2); // Propriedades da label 6 ivjLabel3 = new java.awt.Label(); ivjLabel3.setName("Label111"); ivjLabel3.setAlignment(java.awt.Label.CENTER); ivjLabel3.setFont(new java.awt.Font("dialog", 1, 12)); ivjLabel3.setBounds(63, 58, 163, 20); ivjWindow1.add(ivjLabel3); } // Retorna a Janela public Window getWindow( ) { return ivjWindow1; } // Propriedades da Janela private Window getWindow1() { ivjWindow1 = new java.awt.Window(new java.awt.Frame()); ivjWindow1.setName("Window1"); ivjWindow1.setLayout(null); ivjWindow1.setBackground(java.awt.SystemColor.activeCaptionBorder); ivjWindow1.setBounds(123, 300, 307, 115); return ivjWindow1; } // Método que permite indicar a localização da Janela public void setbounds (int x,int y ) { ivjWindow1.setBounds(x,y,237,94); } // Método que permite escrever os valores da Janela public void writeValues(Reunion r ) { // Declaração da variáveis Integer number; int index; String aux; pág. 131 WEB Agenda- Sistemas Periciais pág. 132 aux=r.present.substring(r.present.indexOf("/")+1,r.present.length()); number=new Integer(aux); ivjLabel2.setText(r.present.substring(0,r.present.indexOf("/"))+"/"+String.valueOf(number.intValue()+1 )); ivjLabel3.setText(r.talkabout); } } 2.27 Classe Error_Handler Esta classe é responsável por mostrar no ecrã as mensagens de erro que vão sucedendo. O constructor desta classe recebe como parâmetros de entrada correespondentes a 2 Strings. A primeira reporta o erro e a segundo sugere uma resolução para o erro. Segue-se a listagem do código correspondente a esta classe. import java.awt.*; public class Error_handler extends Frame { // Declaração das variáveis private java.awt.Button ehjButton111 = null; private java.awt.Frame ivjFrame1 = null; private java.awt.Label ivjLabel1 = null; private java.awt.Label ivjLabel2 = null; String error_message1,error_message2; //Constructor public Error_handler(String message1,String message2) { super("Error Window"); // Inicialização das variáveis error_message1=message1; error_message2=message2; // Chama a inicialização initialize(); } // Definição das propriedades do botão 1(Continuar) private java.awt.Button getButton1() { if (ehjButton111 == null) { try { ehjButton111 = new java.awt.Button(); ehjButton111.setName("Button1"); ehjButton111.setFont(new java.awt.Font("dialog", 0, 11)); ehjButton111.setBounds(122, 124, 82, 22); ehjButton111.setLabel("Continuar"); } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); } }; return ehjButton111; } // Definição das propriedades da Frame private void getFrame1() { setName("Frame1"); setLayout(null); setBounds(38, 39, 329, 158); // Adição das 2 Labels e do Botão WEB Agenda- Sistemas Periciais add(getButton1(), getButton1().getName()); add(getLabel1(), getLabel1().getName()); add(getLabel2(), getLabel2().getName()); } // Definição das propriedades da Label 1 private java.awt.Label getLabel1() { if (ivjLabel1 == null) { try { ivjLabel1 = new java.awt.Label(); ivjLabel1.setName("Label1"); ivjLabel1.setAlignment(java.awt.Label.CENTER); ivjLabel1.setText(error_message1); ivjLabel1.setBounds(50, 29, 260, 22); } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); } }; return ivjLabel1; } // Definição das propriedades da Label 2 private java.awt.Label getLabel2() { if (ivjLabel2 == null) { try { ivjLabel2 = new java.awt.Label(); ivjLabel2.setName("Label2"); ivjLabel2.setAlignment(java.awt.Label.CENTER); ivjLabel2.setFont(new java.awt.Font("dialog", 1, 12)); ivjLabel2.setText(error_message2); ivjLabel2.setBounds(60, 63, 250, 30); } catch (java.lang.Throwable ivjExc) { handleException(ivjExc); } }; return ivjLabel2; } // Método responsável pelo tratamento dos eventos da janela public boolean handleEvent(Event e) { // Se o evento for um click do botão if (e.target instanceof Button) { // Se for carregado o botão continuar if (e.target==ehjButton111) { hide(); dispose(); return true; } return super.handleEvent(e); } return super.handleEvent(e); } // Método responsável por tratar as Excepções dos componentes private void handleException(Throwable exception) { System.out.println("--------- UNCAUGHT EXCEPTION ---------"); } // Método de Inicialização pág. 133 WEB Agenda- Sistemas Periciais pág. 134 private void initialize() { // Chama as propriedades da Frame show(); } } Com este objecto está finalizada a listagem do módulo principal do sistema. Falta agora para terminar a listagem do código em JAVA a listagem do código referente aos objectos utilizados em cada cliente. Os módulos que constituem cada cliente são: Agent1, EmptyListException, ReadSeqFile1, Instance, Receiver, LinkedList, Preferences_Matrix, ReadSeqFile, Node, Reunion, Boolean_Matrix, CreateSeqFile. Todos os módulos mencionados, à excepção de Agent1 e Receiver, são iguais aos módulos do sistema principal e daí que já foram descritos. Vamos passar agora à descricção de Agent1 e Receiver. 2.28 Classe Agent1 Esta classe é responsável por gerir a propostas recebidas do Coordenador da reunião e através do seu algoritmo conseguir dar a sua opinião sobre a proposta, lançar uma Segunda alternativa no caso de concordar com ela ou uma contraproposta no caso contrário. O constructor desta classe recebe como parâmetro de entrada o IPAdress do Coordenador e o utilizador que ele representa para através do ip conseguir a comunicação via Sockets. O código respeitante a este objecto é apresentado de seguida. import java.awt.*; public class Agent1 extends Frame{ // Declaração das variáveis int day_,hour_,countaux; String actual_user; private TextArea ivjArea[]; private Canvas ivjCanvas[]; private Instance table_pref[][]; private Integer count; private String week_days[]={"Segunda","Terça","Quarta","Quinta", "Sexta"}; private String hours[]={"8h00m","9h00m","10h00m","11h00m","14h00m", "15h00m","16h00m","17h00m","18h00m","19h00m"}; private LinkedList listpref; private Preferences_Matrix matrixpref; private Boolean_Matrix matrixbool; private String ipadress; public Agent1(String us,String ip) { // Inicialização das variáveis super("Cliente"); WEB Agenda- Sistemas Periciais pág. 135 ipadress=ip; listpref=new LinkedList(); matrixpref=new Preferences_Matrix(); matrixbool=new Boolean_Matrix(); setLayout(null); setSize(482, 600); actual_user=us; } // Aceita o Socket e começa o processo de negociação public void begin_comunication ( ) { // Declaração e Inicialização das variáveis String mess4,mess5; Instance pref,prefant; Integer day,hour; Double preference; Double antpreference; int initial_day,initial_hour; boolean connection; Receiver socket; boolean end; end=false; socket=new Receiver(); String instruction; String mess,mess1; String mess2; String code; String mess3="Não concordo."; mess4="Concordo."; mess5=""; int counting=0; day=new Integer("0"); hour=new Integer("0"); initial_day=10; initial_hour=10; boolean end_comunication=false; // Cria a ligação para o ipadress e o seu porto é 5001 logo representa o user0001 mess5=socket.createconnection(5001,ipadress); // Enquanto não for anunciada o fim da comunicação while (!end_comunication) { // Lê a proposta mess2=socket.receivemessage(); // Lê os primeiros 6 caracteres da mensagem instruction=mess2.substring(0,6); // Se igual a apagar if (instruction.equals("Apagar")) { // Se a lista não estiver vazia if (!listpref.isEmpty()) { // Retira o dia day=new Integer(mess2.substring(6,7)); // Retira a hora hour=new Integer(mess2.substring(7,8)); // Se este dia tem disponibilidade diferente de zero e existe na lista if (matrixpref.getpreference(day.intValue(),hour.intValue())!=0.0 listpref.exists(day.intValue(),hour.intValue())) // remove listpref.removepropost(day.intValue(),hour.intValue()); & pág. 136 WEB Agenda- Sistemas Periciais } // Manda mensagem de OK (pode continuar) mess="Ok\n"; socket.sendmessage(mess); } else { // Soma uma iteração counting++; // Guarda valores e conta o número de zeros code=mess2.substring(0,2); day=new Integer(mess2.substring(2,3)); hour=new Integer(mess2.substring(3,4)); preference=new Double(mess2.substring(4,7)); // Se código for 02 significa que é o fim da comunicação if (code.equals("02")) end_comunication=true; // Se é a primeira iteração guarda o dia e hora inicial para utilizar na função // heurística if (counting==1) { initial_day=day.intValue(); initial_hour=hour.intValue(); } // Se a comunicação é true então a comunicação continua if (mess2.substring(7,11).equals("true")) connection=true; else connection=false; // Se vai acabar a comunicação sai if (connection) break; // Marca a proposta que foi feita matrixbool.setvalue(day.intValue(),hour.intValue(),false); // Se tem preferência diferente de zero if (matrixpref.getpreference(day.intValue(),hour.intValue())!=0.0) { // Retira da lista prefant=listpref.removepropost(day.intValue(),hour.intValue()); } // Senão cria um nó com preferência zero (para não dar erro) else prefant=new Instance(day.intValue(),hour.intValue(),0.0); // Retira da lista a sua melhor proposta try { pref=listpref.getbest(initial_day,initial_hour); } catch (java.lang.NullPointerException e) { pref=new Instance(0,0,0.0); } day_=day.intValue(); hour_=hour.intValue(); // Constroi a mensagem mess=String.valueOf(prefant.getdisp())+String.valueOf(pref.getday())+ String.valueOf(pref.gethour())+ pág. 137 WEB Agenda- Sistemas Periciais String.valueOf(pref.getdisp())+String.valueOf(end)+"\n"; // Manda a mensagem socket.sendmessage(mess); } } // Recebe a última mensagem mess2=socket.receivemessage(); code=mess2.substring(0,2); int loc1=mess2.indexOf((int) '#',2); int loc2=mess2.indexOf((int) '#',(loc1+1)); mess4=mess2.substring(2,loc1); mess3=mess2.substring(loc1+1,loc2); preference=new Double(mess2.substring(loc2+1,loc2+4)); // Manda a mensagem de finalização socket.sendmessage("bye\n"); // Fecha o socket socket.closeconnection(); // Sai do sistema System.exit(0); } // Inicialização public void initialize ( ) { // Declaração e Inicialização das Variáveis ReadSeqFile file; file=new ReadSeqFile(); // Abre o ficheiro de agenda file.open_file(actual_user); file.readRecord(); file.cleanup(); // Inicialização da matriz de Preferências ,da Matriz Booleana e Lista Ligada for (int i=0;i<5;i++) { for (int j=0;j<10;j++) { matrixpref.putpreference(i,j,file.records[i][j].getdisp()); matrixbool.setvalue(i,j,true); listpref.insert(file.records[i][j]); } } // Chama o ínicio da comunicação begin_comunication(); } // Método que permite correr o programa da linha de comando public static void main(String args[] ) { Agent1 agent; agent=new Agent1("user0001",args[0]); agent.initialize(); } } WEB Agenda- Sistemas Periciais pág. 138 2.29 Classe Receiver Esta classe é responsável pela criação de sockets, leitura de mensagens e envio de mensagens do lado dos clientes. Segue-se a listagem de código referente a este objecto. import java.io.*; import java.net.*; import java.awt.*; public class Receiver { // Declaração das variáveis boolean done; boolean notcontinue=true; Socket connection; InputStream input; OutputStream output; // Permite fechar a comunicação public String closeconnection ( ) { // Declaração e Inicialização das variáveis String mess; mess=""; // Fecha a comunicação try { connection.close(); mess="O Cliente 1 fechou a ligação"; } catch (IOException e) { e.printStackTrace(); } return mess; } // Cria socket do lado do cliente public String createconnection (int port,String ip) { // Declaração e Inicialização das variáveis String mess; mess=""; try { connection=new Socket(ip,port+1); mess="Socket criado...\n"; } catch (IOException e) { e.printStackTrace(); } return mess; } // Permite ler mensagens do Coordenador public String receivemessage ( ) { // Declaração e Inicialização das variáveis String mess; mess=""; WEB Agenda- Sistemas Periciais pág. 139 try { char c; mess=""; // Cria uma Stream de leitura input=connection.getInputStream(); // Lê os caracteres até encontrar o caracter de “newline” while ( (c=(char) input.read())!='\n'){ mess+=String.valueOf(c); } } catch (IOException e) { e.printStackTrace(); } return mess; } // Permite enviar mensagem ao Coordenador public void sendmessage (String message ) { try{ // Cria uma Stream de Saída output=connection.getOutputStream(); // Envia a mensagem caracter a caracter for (int j=0;j<message.length();j++) output.write((int) message.charAt(j)); } catch (IOException e) { e.printStackTrace(); } } } Com esta classe terminaram as listagens de Java. Vamos agora passar à listagem dos scripts (Cgi’s) que estão feitos em linguagem Perl. Passemos então à descrição de cada um dos Scripts. 2.30 Script Acorda.pl Este script é responsável por realizar chamar o script urlget.pl que vai executar chamadas URL para a conta de cgi’s de cada um dos clientes. Este script recebe como parâmetros o URL e o IPadress do Coordenador. Segue-se a listagem do script. #!/usr/local/bin/perl // lê a variável de ambiente Query_String (Parâmetros de entrada) $entry=$ENV{'QUERY_STRING'}; // Como os URL e o IP são fornecidos com um “+” entre os dois, separa os dois e coloca-os em 2 variáveis ($urll,$IPadress) = split /\+/ , $entry; // Separa por “?” my @zbr = split/\?/,$urll; $url = $zbr[0]; print "content-type: text/html\n\n"; // Chamada ao sistema para executar o script urlget1.pl // Envia para o dev/null para não ficar preso system "/home/fjorge/html/.cgi-bin/urlget1.pl $url $IPadress > /dev/null &"; print "<HTML> $urlcomp<p>all is well when it ends well... <p>1 $url WEB Agenda- Sistemas Periciais pág. 140 <p>2 $IPadress </HTML>"; // sai do script exit(0); 2.31 Script urlget1.pl Este script recebe do script acorda.pl o URL e o IPadress , formando depois o novo URL que vai chamar através através da biblioteca de perl para executar um outro script (executa.pl) já na directoria do cliente. Segue-se a listagem do script. #!/usr/local/bin/perl use LWP::Simple; // primeiro parâmetro enviado (URL) $urll = $ARGV[0]; // segundo parâmetro enviado (IPAdress) $IPadress = $ARGV[1]; // Forma novo URL $urlcomp=$urll."?".$IPadress; // Chama o novo URL através da biblioteca de Perl $doc = get $urlcomp; 2.32 Script executa.pl Este script recebe o Ipadress do Coordenador através da variável de ambiente (Query_String), configurando depois as variáveis de ambiente do sistema para o utilizador nobody, executando depois o programa em JAVA Agent1. Segue-se a listagem do script. #!/usr/local/bin/perl // Leitura da variável de ambiente Query String (IPAdress) $IPadress=$ENV{'QUERY_STRING'}; // Faz o auto-flush da Stream $|=1; print "Content-type: text/html\n\n"; print "<HTML>"; print "Going out.....<BR>"; // Configura a CLASSPATH do nobody que indica onde se encontram os ficheiros de JAVA $ENV{CLASSPATH}="/home/fjorge/html/.cgi-bin"; // Se suceder executa o programa em JAVA senão sai do script system("/home2/fjorge/jdk1.1.3/bin/java Agent1 $IPadress &") || die $!; print "yellow?? $IPadress</HTML>"; // Sai do script exit 0; 2.33 Script escreve.pl Este script é responsável pela escrita no ficheiro de agenda de um utilizador especificado. Recebe como parâmetros, através da variável de ambiente Query_String, o utilizador e o conteúdo a escrever no ficheiro da agenda. Seguese a listagem do script. #!/usr/local/bin/perl WEB Agenda- Sistemas Periciais pág. 141 // Lê a variável de ambiente Query_String $entry=$ENV{'QUERY_STRING'}; // Separa os parâmetros por “++” em utilizador e linhas do conteúdo a escrever ($user, @parametros) = split /\+\+/ ,$entry; // Abre o ficheiro open(FICH,">/home/fjorge/html/agenda".$user); // Para cada um das linhas do conteúdo foreach (@parametros) { //escreve no ficheiro print FICH $_."&\n"; } // Fecha o ficheiro close FICH; print "Content-type: text/html\n\n"; print "<HTML>yellow??? @parametros</HTML>"; 2.34 Script escreve1.pl Este script é responsável pela escrita no ficheiro de reunião de um utilizador especificado. Recebe como parâmetros, através da variável de ambiente Query_String, o utilizador e o conteúdo a escrever no ficheiro de reunião. Seguese a listagem do script. #!/usr/local/bin/perl // Lê a variável de ambiente Query_String $entry=$ENV{'QUERY_STRING'}; // Separa os parâmetros por “++” em utilizador e linhas do conteúdo a escrever ($user,@info) = split /\+\+/ , $entry; // Abre o ficheiro open(FICH,"+>/home/fjorge/html/reunion".$user); // Para cada um das linhas do conteúdo foreach (@info) { //escreve no ficheiro print FICH $_."&\n"; } // Fecha o ficheiro close FICH; print "content-type: text/html\n\n"; print "<HTML>yellow??? $user @info</HTML>"; 2.35 Script password.pl Este script é responsável pela escrita no ficheiro de passwords do admnistrador. Recebe como parâmetros, através da variável de ambiente Query_String, o utilizador a escrever e as características específicas desse utilizador. Segue-se a listagem do script. #!/usr/local/bin/perl // Lê a variável de ambiente Query_String $entry=$ENV{'QUERY_STRING'}; // Separa os parâmetros por “+” em características do utilizador WEB Agenda- Sistemas Periciais pág. 142 ($user,@nao) = split /\+/ ,$entry; // Se é igual ao user0000 if ($user eq "user0000") { // abre o ficheiro open(FICH,"+>/home/fjorge/html/password.dat"); // escreve no ficheiro print FICH $entry."&\n"; // fecha o ficheiro close FICH; } else { // abre o ficheiro open(FICH,">>/home/fjorge/html/password.dat"); // escreve no ficheiro print FICH $entry."&\n"; // fecha o ficheiro close FICH; } print "Content-type: text/html\n\n"; print "<HTML>yellow??? $user @nao $entry</HTML>"; 2.36 Script touching.pl Este script encarrega-se de verificar se o ficheiro de passwords existe. Se não existir cria-o. Se existir não faz nada. Segue-se a listagem do script. #!/usr/local/bin/perl // faz o touch `touch /home/fjorge/html/password.dat`; print "Content-type: text/html\n\n"; print "<HTML>yellow??? </HTML>";