Programação com Objectos/Projecto de Programação com Objectos/Enunciado do Projecto de 2022-2023 (rascunho): Difference between revisions
From Wiki**3
| Line 90: | Line 90: | ||
Os terminais podem realizar três tipos de comunicação: texto, voz e vídeo. | Os terminais podem realizar três tipos de comunicação: texto, voz e vídeo. | ||
Cada comunicação tem um identificador único (número inteiro, no contexto de todos os clientes) e possui informação sobre os terminais de origem e de destino, assim como a duração da comunicação, em termos de unidade de contabilização de custos (no caso do texto, esta duração é o número de caracteres da mensagem; nos outros casos, é o número de unidades de tempo da comunicação). A primeira comunicação tem como identificador “1”, sendo os identificadores das comunicações subsequentes obtidos por incremento unitário do mais recente identificador utilizado. | Cada comunicação tem um identificador único (número inteiro, no contexto de todos os clientes) e possui informação sobre os terminais de origem e de destino, assim como a duração da comunicação, em termos de unidade de contabilização de custos (no caso do texto, esta duração é o número de caracteres da mensagem; nos outros casos, é o número de unidades de tempo da comunicação). A primeira comunicação tem como identificador “1”, sendo os identificadores das comunicações subsequentes obtidos por incremento unitário do mais recente identificador utilizado. A comunicação contém ainda informação sobre o estado: em curso <!--'''ONGOING'''--> ou terminada.<!-- '''FINISHED''' (a comunicação teve lugar); '''MISSED''' (a comunicação não teve lugar e a tentativa não ficou registada no chamador); '''LOGGED''' (a comunicação não teve lugar, mas a tentativa ficou registada no chamador). | ||
A comunicação contém ainda informação sobre o estado: '''ONGOING''' | |||
Quando o estado de uma comunicação é '''MISSED''' ou '''LOGGED''', tanto a duração (''length'') como o custo (''cost'') são 0 (zero). | Quando o estado de uma comunicação é '''MISSED''' ou '''LOGGED''', tanto a duração (''length'') como o custo (''cost'') são 0 (zero). | ||
POSSIVELMENTE TIRAR O MISSED E O LOGGED. | POSSIVELMENTE TIRAR O MISSED E O LOGGED. | ||
--> | --> | ||
O custo das comunicações é definido peolo [[#Planos tarifários|plano tarifário]].<!--, dependendo do cliente e do terminal, entre outros factores.--> | |||
== Planos tarifários == | == Planos tarifários == | ||
Revision as of 16:07, 2 September 2022
| AVISOS - Avaliação em Época Normal |
|---|
|
Esclarecimento de dúvidas:
|
|
Requisitos para desenvolvimento, material de apoio e actualizações do enunciado (ver informação completa em Projecto de Programação com Objectos):
|
|
Processo de avaliação (ver informação completa em Avaliação do Projecto):
|
| Material de Uso Obrigatório |
|---|
| As bibliotecas po-uilib e o conteúdo inicial do CVS são de uso obrigatório: |
|
| A máquina virtual, fornecida para desenvolvimento do projecto, já contém todo o material de apoio. |
| Uso Obrigatório: Repositório CVS |
| Apenas se consideram para avaliação os projectos existentes no repositório CVS oficial.
Trabalhos não presentes no repositório no final do prazo têm classificação 0 (zero) (não são aceites outras formas de entrega). Não são admitidas justificações para atrasos em sincronizações do repositório. A indisponibilidade temporária do repositório, desde que inferior a 24 horas, não justifica atrasos na submissão de um trabalho. |
EM PREPARAÇÃO
ÉPOCA NORMAL
O objectivo do projecto e desenvolver uma aplicação de gestão de uma rede de terminais de comunicação, denominada por prr. Genericamente, o programa permite a criação, gestão e consulta de clientes, terminais e comunicações.
Clientes, terminais, comunicações, planos tarifários
Os clientes, terminais e comunicações possuem chaves únicas, cadeias de caracteres para os clientes e para os terminais e inteiros para as comunicações.
Propriedades e funcionalidade dos clientes
Cada cliente, para além da chave única, tem ainda o nome (cadeia de caracteres) e o número de identificação fiscal (inteiro). A cada cliente podem estar associados vários terminais.
O saldo do cliente é a soma de todos os pagamentos efectuados menos o valor das dívidas (comunicações cujo valor ainda não foi pago). Note-se que um cliente pode ter saldo positivo e ter dívidas. É possível realizar um pagamento de valor superior ao montante das dívidas: neste caso, o cliente fica com saldo global positivo. O saldo positivo pode ser usado em pagamentos futuros.
Existem três tipos de clientes: Normal (situação inicial, após o registo), Gold e Platinum. O tipo de cliente influencia o custo das comunicações que efectua (ver planos tarifários). O tipo do cliente evolui nas seguintes condições:
| Antes | Depois | Condição |
| Normal | Gold | O saldo do cliente (após realizar um pagamento) é superior a 500 cêntimos. |
| Normal | Platinum | (não é possível) |
| Gold | Normal | O saldo do cliente (após realizar uma comunicação) é negativo. |
| Gold | Platinum | O cliente realizou 5 comunicações de vídeo consecutivas (a contabilização da 5ª comunicação ainda considera que o cliente é do tipo Gold). |
| Platinum | Gold | O cliente realizou 2 comunicações de texto consecutivas (a contabilização da 2ª comunicação ainda considera que o cliente é do tipo Platinum). |
| Platinum | Normal | O saldo do cliente (após realizar uma comunicação) é negativo. |
Propriedades e funcionalidade dos terminais
Cada terminal é identificado por uma cadeia de caracteres numérica (exactamente 6 dígitos) e está associado a um único cliente.
As comunicações realizadas pelo terminal são contabilizadas de acordo com o tarifário associado ao cliente. O terminal tem contabilidade própria, sendo sempre possível saber o saldo que lhe está associado (comunicações pagas e devidas).
Existem pelo menos dois tipos de terminal: básicos (BASIC) e sofisticados (FANCY). Os terminais básicos só conseguem realizar comunicações de texto e de voz, não podendo nem iniciar nem receber comunicações de vídeo. Os terminais sofisticados podem realizar todos os tipos de comunicação.
Estados dos terminais
Cada terminal pode estar em espera, em silêncio, ocupado ou desligado.
- Espera -- situação normal sem actividade (idle);
- Silêncio -- pode iniciar-se qualquer tipo de comunicação suportada pelo terminal, mas só pode receber comunicações de texto;
- Ocupado -- apenas podem receber-se mensagens de texto, não podendo iniciar-se comunicações;
- Desligado -- não podem ser iniciadas ou recebidas comunicações.
Transições entre estados de terminais
Um terminal pode chegar aos vários estados nas seguintes condições (outras transições não são possíveis):
- Espera -- de desligado (ao ligar); de silêncio (ir para estado de espera); de ocupado (final de comunicação);
- Silêncio -- de espera (colocar em silêncio); de ocupado (final de comunicação);
- Ocupado -- de espera ou de silêncio (início de comunicação);
- Desligado -- de espera ou de silêncio (ao desligar).
Notificações
Apenas são passíveis de notificação os clientes que tentaram comunicação com um terminal e a comunicação não foi possível nessa altura. Quando uma comunicação não se efectua, regista-se a tentativa de contacto, para que, assim que seja possível a realização do contacto pretendido, se enviarem notificações aos terminais de origem. O registo da tentativa de contactos só tem lugar quando o cliente do terminal de origem tem activa a recepção de contactos falhados no instante em que se tentou efectuar a comunicação.
São geradas notificações e é possível avisar um cliente nas seguintes circunstâncias:
- Um terminal desligado é colocado em silêncio (off-to-silent): notifica-se disponibilidade para comunicações de texto.
- Um terminal desligado ou em silêncio é colocado em espera (off-to-idle ou silent-to-idle): notifica-se disponibilidade para comunicações (qualquer suportada).
- Um terminal deixa de estar ocupado (busy-to-idle ou busy-to-silent, conforme os casos): notifica-se como nos casos anteriores, considerando o estado atingido.
Propriedades e funcionalidade das comunicações
Os terminais podem realizar três tipos de comunicação: texto, voz e vídeo.
Cada comunicação tem um identificador único (número inteiro, no contexto de todos os clientes) e possui informação sobre os terminais de origem e de destino, assim como a duração da comunicação, em termos de unidade de contabilização de custos (no caso do texto, esta duração é o número de caracteres da mensagem; nos outros casos, é o número de unidades de tempo da comunicação). A primeira comunicação tem como identificador “1”, sendo os identificadores das comunicações subsequentes obtidos por incremento unitário do mais recente identificador utilizado. A comunicação contém ainda informação sobre o estado: em curso ou terminada.
O custo das comunicações é definido peolo plano tarifário.
Planos tarifários
Os custos de uma comunicação dependem de um plano tarifário associado a cada cliente. Cada plano tarifário define os custos para cada tipo de comunicação, baseado no nível do cliente, no tipo de comunicação, entre outras características. Os planos tarifários têm um nome podem ser alterados em qualquer momento.
Quando é efectuada uma comunicação do tipo texto com N caracteres, o custo no plano tarifário base em cêntimos é como indicado na tabela:
| Normal | Gold | Platinum | |
|---|---|---|---|
| N < 50 caracteres | 10 | 10 | 0 |
| 50 caracteres <= N < 100 caracteres | 16 | 10 | 4 |
| N >= 100 caracteres | 2 x N | 2 x N | 4 |
Quando é efectuada uma comunicação de voz ou de vídeo, o custo no plano tarifário base é proporcional ao tempo de conversação e quando se liga para um terminal registado como amigo é aplicado um desconto de 50%. O custo, em cêntimos por minuto, é o seguinte para terminais não registados como amigos:
| Normal | Gold | Platinum | |
|---|---|---|---|
| Comunicação de voz | 20 | 10 | 10 |
| Comunicação de vídeo | 30 | 20 | 10 |
O custo de uma comunicação deve ser calculado quando a comunicação termina e guardado, por forma a garantir que o custo não é afectado por mudanças futuras dos planos tarifários.
Todos os cálculos envolvendo os custos das comunicações devem ser realizados sem arredondamentos.
Entrega de notificações
Os clientes devem ser colocados como entidades interessadas em receber notificações sobre eventos associados a terminais em algumas circunstâncias. Em qualquer momento, um cliente pode activar ou desactivar essas notificações. A entrega de notificações deve ser flexível e deve prever vários meios de entrega, e.g., correio postal, SMS, email, entre outras. O meio de entrega por omissão corresponde a registar a notificação na aplicação.
As notificações contêm informação acerca da sua natureza e do terminal a que dizem respeito. O cliente que as recebe apenas mantém informação sobre a primeira notificação de um certo tipo por terminal, não sendo admitidos duplicados.
Funcionalidade da aplicação
A aplicação permite manter informação sobre as entidades do modelo. Possui ainda a capacidade de preservar o seu estado (não é possível manter várias versões do estado da aplicação em simultâneo).
Deve ser possível efectuar pesquisas sujeitas a vários critérios e sobre as diferentes entidades geridas pela aplicação.
Uma base de dados textual com conceitos pré-definidos pode ser carregada no início da aplicação.
Serialização
É possível guardar e recuperar o estado actual da aplicação, preservando toda a informação relevante, descrita acima.
Funcionalidade Associada a Entidades do Domínio
Funcionalidade associadas aos clientes
A seguinte funcionalidade sobre clientes deve ser suportada pela aplicação: (i) visualizar clientes; (ii) registar novos clientes; (iii) registar contactos falhados; (iv) controlar o registo de contactos falhados; (v) calcular saldos de clientes.
Um cliente não pode ser removido, sendo sempre possível aceder a todo o seu historial.
Funcionalidade associadas aos terminais
A seguinte funcionalidade sobre terminais deve ser suportada pela aplicação: (i) visualizar um terminal; (ii) registar um novo terminal; (iii) ligar e desligar um terminal; (iv) colocar terminal em silêncio; (v) adicionar e remover terminais da lista de amigos de um terminal; (vi) proceder a um pagamento; (vii) apresentar o saldo de um terminal.
Um terminal não pode ser removido, sendo sempre possível aceder a todo o seu historial.
Funcionalidade associada a comunicações
A seguinte funcionalidade está associada às comunicações: (i) registar comunicações efectuadas por um terminal; (ii) activar/desactivar notificações associadas a terminais; (iii) consultar comunicações. A seguinte funcionalidade de consulta deve ser suportada: (i) comunicações efectuadas por um cliente; (ii) terminais que iniciaram comunicações para um determinado terminal; (iii) terminais que iniciaram uma comunicação para um determinado cliente; (iv) terminais com um determinado plano tarifário; (v) clientes com pagamentos em atraso.
As comunicações, uma vez registadas, não podem ser alteradas ou removidas.
Requisitos de Desenho
Devem ser possíveis extensões ou alterações de funcionalidade com impacto mínimo no código já produzido para a aplicação. O objectivo é aumentar a flexibilidade da aplicação relativamente ao suporte de novas funções. Assim, deve ser possível: definir novos tipos de clientes; definir novos tipos de comunicação; definir novos planos tarifários; definir novas formas de pesquisa; permitir a gestão de várias redes de terminais.
Deve ser possível a definição de diferentes entidades que estejam interessadas em ser notificadas com os dados referentes a cada comunicação realizada por um dado terminal sem que isso provoque alterações no código da aplicação. As entidades podem registar ou cancelar o seu interesse em qualquer momento e podem existir várias entidades distintas interessadas em simultâneo.
Embora na especificação actual não seja possível remover algumas entidades, a inclusão desta funcionalidade deve ser prevista, por forma a minimizar o impacto da sua futura inclusão.
Interacção com o utilizador
Descreve-se nesta secção a funcionalidade máxima da interface com o utilizador. Em geral, os comandos pedem toda a informação antes de procederem à sua validação (excepto onde indicado). Todos os menus têm automaticamente a opção Sair (fecha o menu).
As operações de pedido e apresentação de informação ao utilizador devem realizar-se através dos objectos form e display, respectivamente, presentes em cada comando. As mensagens são produzidas pelos métodos das bibliotecas de suporte (po-uilib e prr-app). As mensagens não podem ser usadas no núcleo da aplicação (prr-core). Além disso, não podem ser definidas novas. Potenciais omissões devem ser esclarecidas antes de qualquer implementação.
A apresentação de valores monetários (preços, saldos, etc.) é sempre feita com arredondamento ao inteiro mais próximo (note-se que a representação interna não deve ser arredondada).
A apresentação de listas de entidades do domínio (clientes, etc.) faz-se por ordem crescente da respectiva chave: dependendo dos casos, a ordem pode ser numérica ou lexicográfica (UTF-8), não havendo distinção entre maiúsculas e minúsculas.
As excepções usadas na interacção (subclasses de pt.tecnico.uilib.menus.CommandException), excepto se indicado, são lançadas pelos comandos (subclasses de pt.tecnico.uilib.menus.Command) e tratadas pelos menus (instâncias de subclasses de pt.tecnico.uilib.menus.Menu). Outras excepções não devem substituir as fornecidas nos casos descritos.
Menu Principal
As acções deste menu permitem gerir a salvaguarda do estado da aplicação, abrir submenus e aceder a alguma informação global. A lista completa é a seguinte: Abrir, Guardar, Gestão de clientes, Gestão de terminais, Consultas, Mostrar saldo global.
As etiquetas das opções deste menu estão definidas na classe prr.app.main.Label. Todos os métodos correspondentes às mensagens de diálogo para este menu estão definidos na classe prr.app.main.Message.
Salvaguarda do estado actual da aplicação
Inicialmente, a aplicação está vazia ou tem apenas informação sobre as entidades que foram carregadas via ficheiro textual.
O conteúdo da aplicação (toda a informação actualmente em memória) pode ser guardado para posterior recuperação (via serialização Java: java.io.Serializable). Na leitura e escrita do estado da aplicação, devem ser tratadas as excepções associadas. A funcionalidade é a seguinte:
- Abrir -- Carrega os dados de uma sessão anterior a partir de um ficheiro previamente guardado (ficando este ficheiro associado à aplicação, para futuras operações de salvaguarda). Pede-se o nome do ficheiro a abrir (Prompt.openFile()). Caso ocorra um problema na abertura ou processamento do ficheiro, deve ser lançada a excepção FileOpenFailedException. A execução bem-sucedida desta opção substitui toda a informação da aplicação.
- Guardar -- Guarda o estado actual da aplicação no ficheiro associado. Se não existir associação, pede-se o nome do ficheiro a utilizar, ficando a ele associado (para operações de salvaguarda subsequemtes). Esta interacção realiza-se através do método Prompt.newSaveAs(). Não é executada nenhuma acção se não existirem alterações desde a última salvaguarda.
Note-se que a opção Abrir não permite a leitura de ficheiros de texto (estes apenas podem ser utilizados no início da aplicação).
A opção Sair nunca implica a salvaguarda do estado da aplicação, mesmo que existam alterações.
Gestão e consulta de dados da aplicação
- Menu de Gestão de Clientes -- Abre o menu de gestão de clientes.
- Menu de Gestão de Terminais -- Abre o menu de gestão de terminais.
- Menu de Consultas -- Abre o menu de consultas (pesquisas).
Mostrar saldo global
Esta opção apresenta o valor correspondente ao saldo global (soma dos sados de todos os clientes registados), através da mensagem Message.globalBalance().
Menu de gestão de clientes
Este menu permite efectuar operações sobre a base de dados de clientes. A lista completa é a seguinte: Visualizar todos os clientes, Registar cliente, Activar recepção de contactos falhados, Desactivar recepção de contactos falhados, Mostrar saldo de cliente.
Todos os métodos correspondentes às mensagens de diálogo para este menu estão definidos na classe prr.app.clients.Message.
Sempre que é pedido o identificador de um cliente (Prompt.key()) e o identificador não existir (excepto no processo de registo), é lançada a excepção UnknownClientKeyException. Na ocorrência de excepções, as operações não têm efeito.
Visualizar cliente
É pedido o identificador do cliente e apresentada a sua informação. O formato de apresentação de cada cliente é como se indica de seguida. Os valores para type são NORMAL, GOLD, ou PLATINUM. Os valores para notifications são YES ou NO (notificações activas/inactivas). O campo terminals representa o número de terminais activos associados ao cliente e balance é o saldo do cliente. Se o cliente não tiver terminais, o saldo é 0 (zero).
CLIENT|key|name|taxId|type|notifications|terminals|balance
Após esta linha, são apresentadas as notificações do cliente (modo de entrega por omissão), pela ordem em que foram enviadas pela aplicação.
tipo-de-notificação|idTerminal
O tipo de notificação é um de O2S (off-to-silent), O2I (off-to-idle) ou S2I (silent-to-idle), tal como descritos acima. Após esta visualização, considera-se que o cliente fica sem notificações registadas.
Visualizar todos os clientes
O formato de apresentação é como para clientes individuais (opção anterior), mas não se apresentam as notificações dos clientes (nem se limpam as listas correspondentes).
Registar cliente
O sistema pede o identificador que ficará associado ao cliente (identificador único}. De seguida, pede o nome do cliente (Prompt.name()) e o número de identificação fiscal (Prompt.taxId()). Após o registo, o cliente fica no estado Normal e o registo de contactos falhados fica activo.
Caso o identificador indicado já exista, deve ser lançada a excepção DuplicateClientKeyException, não se realizando o registo.
Activar recepção de contactos falhados
É pedido o identificador do cliente. Se o registo de contactos falhados já estava activo, o cliente não é alterado e é apresentada a mensagem clientNotificationsAlreadyEnabled().
Desactivar recepção de contactos falhados
É pedido o identificador do cliente. Se o registo de contactos falhados já estava inactivo, o cliente não é alterado e é apresentada a mensagem clientNotificationsAlreadyDisabled().
Mostrar saldo de cliente
O sistema pede o identificador do cliente, apresentando o seu saldo (Message.clientBalance()).
Menu de Gestão de Terminais
Este menu permite efectuar operações sobre a base de dados de parceiros. A lista completa é a seguinte: Mostrar todos os terminais, Registar terminal, Menu de administração de terminal.
Todos os métodos correspondentes às mensagens de diálogo para este menu estão definidos na classe prr.app.terminals.Message.
Sempre que for pedido o identificador de um terminal (Prompt.terminalKey()) e o terminal não existir, é lançada a excepção UnknownTerminalKeyException (excepto no processo de registo). Sempre que é pedido o identificador de um cliente (Prompt.clientKey()) e o identificador não existir, é lançada a excepção UnknownClientKeyException. Na ocorrência de excepções (estas ou outras), as operações não têm efeito.
Mostrar todos os terminais
O formato de apresentação de cada terminal é o seguinte:
terminalType|terminalId|clientId|terminalStatus|terminalBalance|friend1,...,friendN
Os valores para o campo terminalType são BASIC (terminais básicos) ou FANCY (terminais sofisticados). Os valores para o campo terminalStatus são IDLE, OFF, SILENCE, BUSY. Os valores friend1, ..., friendN são os identificadores dos terminais amigos e são apresentados por ordem crescente desses identificadores. Se não tiver amigos, a última parte não é apresentada.
Registar terminal
É pedido o número identificador do terminal com exactamente 6 dígitos. De seguida, o sistema pede o tipo de terminal (Prompt.terminalType()). A resposta deve ser BASIC (terminal básico) ou FANCY (terminal sofisticado). Se a resposta não corresponder a nenhum dos dois valores, a pergunta é repetida até se obter uma resposta válida. Finalmente, é pedido o identificador do cliente que ficará associado ao terminal.
Caso o identificador não tenha exactamente 6 dígitos, lança-se a excepção InvalidTerminalKeyException, não se realizando o registo. Caso o identificador indicado já exista, deve ser lançada a excepção DuplicateTerminalKeyException, não se realizando o registo.
Quando um terminal é registado, fica no estado ligado, com saldo zero e com uma lista de amigos vazia.
Menu de administração de terminal
É pedido o número identificador de um terminal, sendo aberto o correspondente menu de administração.
Menu de Consultas
Este menu apresenta as operações relacionadas com consultas. A lista completa é a seguinte: Mostrar todas as comunicações, Mostrar comunicações feitas por um cliente, Mostrar comunicações recebidas por um cliente, Mostrar clientes sem dívidas, Mostrar clientes com dívidas, Mostrar terminais sem actividade, Mostrar terminais com saldo positivo.
Sempre que é pedido o identificador do parceiro (Prompt.clientKey()), é lançada a excepção UnknownClinetKeyException, se o parceiro indicado não existir. Sempre que é pedido o identificador de produto (Prompt.terminalKey()), é lançada a excepção UnknownTerminalKeyException, se o produto indicado não existir.
A apresentação de resultados é como se indica nos casos já descritos de apresentação das várias entidades. Sempre que for feita uma consulta e nenhuma entidade satisfizer as condições associadas ao pedido, nada deve ser apresentado.
Mostrar todas as comunicações
O formato de apresentação é o seguinte:
type|idCommunication|idSender|idReceiver|units|price|status
Os possíveis valores para o campo type são VOICE, TEXT ou VIDEO. Os possíveis valores para o campo status são ONGOING ou FINISHED. O valor de units corresponde às unidades de contabilização (caracteres ou minutos).
Mostrar comunicações feitas por um cliente
É pedido o identificador do cliente, sendo apresentadas as comunicações por ele originadas.
Mostrar comunicações recebidas por um cliente
É pedido o identificador do cliente, sendo apresentadas as comunicações por ele recebidas.
Mostrar clientes sem dívidas
São apresentados os clientes sem dívidas.
Mostrar clientes com dívidas
São apresentados os clientes por ordem decrescente do valor das respectivas dívidas (valores superiores a zero). Se as dívidas tiverem o mesmo valor, apresentam-se os clientes por ordem crescente do seu identificador.
Mostrar terminais sem actividade
São apresentados os terminais que ainda não efectuaram nem receberam qualquer comunicação.
Mostrar terminais com saldo positivo
São apresentados os terminais que que têm saldo estritamente positivo.
Menu da consola de um terminal
Este menu apresenta as operações relacionadas com a consola de um terminal, i.e., o seu uso e administração. A lista completa é a seguinte: Ligar terminal, Desligar terminal, Silenciar terminal, Adicionar amigo, Retirar amigo, Efectuar pagamento, Consultar saldo, Iniciar comunicação, Terminar comunicação, Mostrar comunicações em curso.
Todos os métodos correspondentes às mensagens de diálogo para este menu estão definidos na classe prr.app.admin.Message.
Sempre que é pedido o identificador do cliente (Prompt.clientKey()), é lançada a excepção UnknownClientKeyException, se o cliente indicado não existir. Sempre que é pedido o identificador do terminal (Prompt.terminalKey()), é lançada a excepção UnknownTerminalKeyException, se o terminal indicado não existir.
Colocar terminal em espera
Se o terminal indicado já estiver em espera, é apresentada a mensagem alreadyIdle() e o comando não realiza outras acções.
Desligar terminal
Se o terminal indicado já estiver desligado, é apresentada a mensagem alreadyOff() e o comando não realiza outras acções.
Silenciar terminal
Se o terminal indicado já estiver em silêncio, é apresentada a mensagem alreadySilent() e o comando não realiza outras acções.
Adicionar amigo
É pedido o identificador do terminal a adicionar à lista de amigos. Se o terminal indicado já fizer parte da lista de amigos, a operação termina sem alterações.
Retirar amigo
É pedido o identificador do terminal a retirar da lista de amigos. Se o terminal indicado não fizer parte da lista de amigos, a operação termina sem alterações.
Efectuar pagamento
É pedido o valor (inteiro) a pagar através da mensagem Prompt.paymentValue(). O valor indicado é em cêntimos.
Consultar saldo
É apresentado o saldo (terminalBalance()) associado ao terminal.
Iniciar comunicação
Esta operação está disponível para um terminal que não esteja desligado ou em comunicação. Permite estabelecer uma comunicação com outro terminal.
É pedido o número do terminal de destino e o tipo de comunicação (Prompt.commType()). A resposta deve ser uma das seguintes opções (cadeia de caracteres): TEXT, VIDEO, VOICE. Se a resposta não corresponder a nenhum dos três valores, a pergunta é repetida até se obter uma resposta válida.
Quando o terminal de destino está desligado, é apresentada a mensagem destinationIsOff(). Quando o terminal de destino está ocupado, é apresentada a mensagem destinationIsBusy(). Quando o terminal de destino está em silêncio e a comunicação pretendida é VIDEO ou VOICE, é apresentada a mensagem destinationIsSilent().
Se se tenta iniciar uma comunicação de video a partir de um terminal Basic, deve ser apresentada a mensagem unsupportedAtOrigin(). Se se tenta iniciar uma comunicação de vídeo para um terminal Basic, deve ser apresentada a mensagem unsupportedAtDestination(). Em qualquer destes casos, a operação termina sem qualquer acção.
Terminar comunicação
Esta operação está disponível para um terminal que iniciou uma comunicação enquanto a comunicação está em curso. O terminal de destino não pode interromper a comunicação, pelo que o comando não está disponível. O comando permite terminar a comunicação e registar a sua duração (ou comprimento, no caso das comunicações de texto).
É pedida a duração da comunicação (Prompt.duration(), em segundos), para comunicações de voz ou vídeo, ou o número de caracteres (Prompt.chararacters()), para comunicações de texto. Após o término da comunicação, é apresentado o seu custo, através da mensagem communicationCost().
Mostrar comunicação em curso
É apresentada a comunicação em curso (de acordo com o formato indicado acima).
Se não houver nenhuma comunicação em curso, é apresentada a mensagem noOngoingCommunication().
Leitura de Dados a Partir de Ficheiros Textuais
Além das opções de manipulação de ficheiros descritas no menu principal, é possível iniciar a aplicação com um ficheiro de texto especificado pela propriedade Java import.
As várias entidades têm os formatos descritos abaixo. Assume-se que os títulos não podem conter o carácter | e que o preço é um número inteiro (sugere-se a utilização do método String.split para o processamento preliminar destas linhas). Não existem entradas mal-formadas.
Cada linha tem uma descrição distinta, mas que segue os seguintes formatos:
CLIENT|id|nome|taxId|client-level terminal-type|idTerminal|idClient|state|balance FRIENDS|idTerminal|idTerminal1,...,idTerminalN
As definições de clientes precedem sempre as dos terminais. As ligações entre amigos estão sempre após a definição das restantes entidades. Para os terminais, terminal-type é BASIC ou FANCY.
Um exemplo de conteúdo do ficheiro inicial é como se segue:
| Exemplo de ficheiro de entrada textual |
|---|
CLIENT|cli001|Manuel Pinheiro|103443|NORMAL
CLIENT|cli002|Pedro Pinheiro|103447|NORMAL
CLIENT|Cli201|Ludgero Oliveira|103440|NORMAL
CLIENT|cli Es|Maria Eucalipto|103441|GOLD
CLIENT|01|Oliveira Preto|103547|NORMAL
CLIENT|cli003|Pedro Oliveira|103449|PLATINUM
BASIC|969001|cli001|ON|-900
BASIC|969003|cli002|ON|0
FANCY|969002|cli002|SILENCE|330
FANCY|969007|cli Es|ON|700
BASIC|969008|cli003|OFF|2500
BASIC|969009|cli003|OFF|1200
BASIC|969010|cli003|ON|-2100
FANCY|969006|cli003|ON|4800
FANCY|969005|cli003|ON|3400
BASIC|969004|cli003|ON|1000
FRIENDS|969001|969008,969009,969004
FRIENDS|969004|969001
FRIENDS|969003|969008
|
A codificação dos ficheiros a ler é garantidamente UTF-8.
Execução dos Programas e Testes Automáticos
Usando os ficheiros test.import, test.in e test.out, é possível verificar automaticamente o resultado correcto do programa. Note-se que é necessária a definição apropriada da variável CLASSPATH (ou da opção equivalente -cp do comando java), para localizar as classes do programa, incluindo a que contém o método correspondente ao ponto de entrada da aplicação (prr.app.App.main). As propriedades são tratadas automaticamente pelo código de apoio.
java -Dimport=test.import -Din=test.in -Dout=test.outhyp prr.app.App
Assumindo que aqueles ficheiros estão no directório onde é dado o comando de execução, o programa produz o ficheiro de saída test.outhyp. Em caso de sucesso, os ficheiros das saídas esperada (test.out) e obtida (test.outhyp) devem ser iguais. A comparação pode ser feita com o comando:
diff -b test.out test.outhyp
Este comando não deve produzir qualquer resultado quando os ficheiros são iguais. Note-se, contudo, que este teste não garante o correcto funcionamento do código desenvolvido, apenas verificando alguns aspectos da sua funcionalidade.
Notas de Implementação
Tal como indicado acima, algumas classes fornecidas como material de apoio, são de uso obrigatório e não podem ser alteradas. Outras dessas classes são de uso obrigatório e têm de ser alteradas.
A serialização Java usa as classes da package java.io, em particular, a interface java.io.Serializable e as classes de leitura java.io.ObjectInputStream e escrita java.io.ObjectOutputStream (entre outras).