|
|
| (233 intermediate revisions by the same user not shown) |
| Line 1: |
Line 1: |
| {{PRJPOAvisosEN20222023}}
| | #REDIRECT [[Programação com Objectos/Projecto de Programação com Objectos/Enunciado do Projecto de 2022-2023]] |
| {{PRJPOMandatory20222023}}
| |
| {{TOCright}}
| |
| '''<font color="red">EM PREPARAÇÃO</font>'''
| |
| | |
| '''<font color="red">ÉPOCA NORMAL</font>'''
| |
| | |
| O objectivo do projecto e desenvolver um gestor de uma rede de terminais de comunicação, denominado por '''prr'''. Genericamente, o programa permite a gestão e consulta de clientes, terminais e comunicações.
| |
| | |
| Especificamente, o sistema disponibiliza vários serviços, entre outros: (i) registar dados sobre os clientes; (ii) registar dados sobre os terminais; (iii) registar dados sobre comunicações efectuadas; (iv) fazer pesquisas sobre comunicações efectuadas; (v) contabilizar o saldo associado a terminais.
| |
| | |
| = Clientes, terminais, comunicações, planos tarifários =
| |
| | |
| Os clientes, terminais e comunicações possuem chaves únicas, cadeias de caracteres para os clientes e inteiros para os terminais e para as comunicações.
| |
| | |
| == Propriedades e funcionalidade dos clientes ==
| |
| | |
| Cada cliente, para além da chave única, é identificado pelo nome (cadeia de caracteres) e número de identificação fiscal (inteiro). A cada cliente podem estar associados vários terminais.
| |
| | |
| Existem três tipos de clientes: '''Normal''' (situação inicial, após o registo), '''Gold''' e '''Platinum'''. O custo das comunicações está indexado ao tipo de cliente (ver [[#Planos tarifários|planos tarifários]]). Um cliente transita de tipo nas seguintes condições:
| |
| | |
| {|
| |
| | '''Antes'''
| |
| | '''Depois'''
| |
| | '''Condições'''
| |
| |-
| |
| | Normal
| |
| | Gold
| |
| | o saldo (após realizar um pagamento) é superior a 500 cêntimos
| |
| |-
| |
| | Normal
| |
| | Platinum
| |
| | (não é possível)
| |
| |-
| |
| | Gold
| |
| | Normal
| |
| | o saldo (após realizar uma comunicação) é inferior a 0 cêntimos
| |
| |-
| |
| | Ouro
| |
| | Platinum
| |
| | realizar 5 comunicações de vídeo consecutivas (a contabilização da 5ª comunicação ainda considera que o cliente é do tipo Gold)
| |
| |-
| |
| | Platinum
| |
| | Gold
| |
| | realizar 2 comunicações de texto consecutivas (a contabilização da 2ª comunicação ainda considera que o cliente é do tipo Platinum)
| |
| |-
| |
| | Platinum
| |
| | Normal
| |
| | tentativa de realizar uma comunicação de vídeo para um terminal Basic
| |
| |}
| |
| | |
| Um cliente tem dívidas se tiver, pelo menos, um terminal com saldo negativo, sendo a sua dívida total a soma de todos os saldos negativos.
| |
| | |
| == Propriedades e funcionalidade dos terminais ==
| |
| | |
| Os terminais são identificados por um número (exactamente 6 dígitos) e estão associados a um cliente. Cada terminal pode estar ligado, em silêncio, ocupado ou desligado. Quando o terminal está desligado, não pode iniciar ou receber comunicações. Quando o terminal está em silêncio, pode iniciar qualquer tipo de comunicação que suporte, mas só pode receber comunicações de texto. Quando um terminal está ocupado, apenas pode receber mensagens de texto, não podendo iniciar outras comunicações. Não é possível desligar um terminal ocupado. Cada terminal está associado a um plabo tarifário e tem contabilidade própria, sendo sempre possível saber o saldo que lhe está associado.
| |
| | |
| Os terminais Basic só conseguem realizar comunicações texto e de voz, não podendo nem iniciar nem receber comunicações de vídeo. Os terminais Fancy podem realizar todos os tipos de comunicação.
| |
| | |
| Para promover as comunicações, quando uma comunicação não se efectua por o terminal de destino estar num estado incompatível, 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 destino tem activa a recepção de contactos falhados no instante em que se tentou efectuar a comunicação (que não teve lugar por o terminal de destino o não permitir). VER MELHOR AS NOTIFICAÇÕES
| |
| | |
| Dependendo do cliente, é possível avisar quem o tentou contactar quando: (i) um terminal desligado é colocado em silêncio; (ii) um terminal desligado é ligado; ou (iii) um terminal em silêncio é ligado.
| |
| | |
| == Propriedades das comunicações ==
| |
| | |
| Existem 3 tipos de comunicação entre terminais: texto (denominada '''TEXT'''), voz (denominada '''VOICE''') e vídeo (denominada '''VIDEO''').
| |
| | |
| Cada comunicação, além do identificador único (no contexto de um dado cliente), possui ainda informação sobre o terminal que a originou, o terminal de destino, a sua duração (no caso do texto, esta duração é o número de caracteres da mensagem; nos outros casos, é o número de segundos da comunicação) e o tipo de comunicação (voz, texto ou vídeo). A primeira comunicação tem como identificador “1”, devendo o identificador das comunicações subsequentes ser obtido por incremento unitário do identificador anterior.
| |
| | |
| O custo das comunicações não é uniforme: depende do [[#Planos tarifários|plano tarifário]].<!--, dependendo do cliente e do terminal, entre outros factores.-->
| |
| | |
| == Planos tarifários ==
| |
| | |
| Os custos de uma comunicação dependem do tipo de cliente que inicia a comunicação, do tipo da comunicação e do plano tarifário. Os planos tarifários têm um nome podem ser alterados depois da criação do cliente.
| |
| | |
| 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 * '''N'''
| |
| | 2 * '''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'''
| |
| |-
| |
| | '''VOICE'''
| |
| | 20
| |
| | 10
| |
| | 10
| |
| |-
| |
| | '''VIDEO'''
| |
| | 30
| |
| | 20
| |
| | 10
| |
| |}
| |
| | |
| Todos os cálculos envolvendo os custos das comunicações devem ser realizados sem arredondamentos. <!--Por exemplo, uma comunicação de voz que dure 6 minutos tem um custo de 120 cêntimos para um cliente Normal e 60 cêntimos para clientes Gold ou Platinum.-->
| |
| | |
| = 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 [[#Leitura de Dados a Partir de Ficheiros Textuais|carregada no início da aplicação]].
| |
| | |
| {{Suggestion|Note-se que não é necessário/desejável implementar de raiz a aplicação: já existem classes que representam e definem a interface geral da funcionalidade do ''core'' da aplicação, tal como é visível pelos comandos da aplicação.}}
| |
| {{CVSCode|A interface geral do ''core'' já está parcialmente implementada na classe '''prr.Manager''' e outras fornecidas (cujos nomes devem ser mantidos), devendo ser adaptadas onde necessário. É ainda necessário criar e implementar as restantes classes que suportam a operação 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 um cliente; (ii) registar um novo cliente; (iii) permitir o registo de contactos falhados; (iv) inibir o registo de contactos falhados; (v) calcular o saldo de um cliente.
| |
| | |
| 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, desligar e colocar no silêncio um terminal; (iv) adicionar e remover telefones da lista dos telefones amigos de um terminal; (v) proceder a um pagamento; (vi) calcular 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 de pesquisa 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;
| |
| * Adicionar novos planos tarifários;
| |
| * Adicionar 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 interessadas distintas 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 [[Programação com Objectos/Projecto de Programação com Objectos/Material de Apoio ao Desenvolvimento|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.
| |
| | |
| {{CVSCode|Note-se que o programa principal e os comandos e menus, a seguir descritos, já estão parcialmente implementados nas ''packages'' '''prr.app''', '''prr.app.clients''', '''prr.app.lookups''', '''prr.app.main''', '''prr.app.terminal''', '''prr.app.terminals'''. Estas classes são de uso obrigatório e estão disponíveis no [[Programação com Objectos/Projecto de Programação com Objectos/Repositório CVS|CVS]] (módulo '''prr-app''').}}
| |
| | |
| == 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: [[#Salvaguarda do estado actual da aplicação|Abrir]], [[#Salvaguarda do estado actual da aplicação|Guardar]], [[#Gestão e consulta de dados da aplicação|Gestão de clientes]], [[#Gestão e consulta de dados da aplicação|Gestão de terminais]], [[#Gestão e consulta de dados da aplicação|Consultas]], [[#Mostrar saldo global|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'''.
| |
| | |
| {{CVSCode|Estes comandos já estão implementados nas classes da ''package'' '''prr.app.main''' (disponível no CVS), respectivamente: '''DoOpenFile''', '''DoSaveFile''', '''DoOpenMenuClients''', '''DoOpenMenuTerminals''', '''DoOpenMenuLookups''', '''DoShowGlobalBalance'''.}}
| |
| | |
| === Salvaguarda do estado actual da aplicação ===
| |
| | |
| Inicialmente, a aplicação está vazia ou tem apenas informação sobre as entidades que foram carregados no arranque (via [[#Leitura de Dados a Partir de Ficheiros Textuais|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. 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 são utilizados na inicialização 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 na rede). Embora internamente os valores dos saldos estejam representados em vírgula flutuante, a apresentação é arredondada ao inteiro mais próximo.
| |
| | |
| A apresentação faz-se através da mensagem '''Message.currentBalance()'''.
| |
| | |
| == 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|Visualizar todos os clientes]], [[#Registar cliente|Registar cliente]], [[#Activar recepção de contactos falhados|Activar recepção de contactos falhados]], [[#Desactivar recepção de contactos falhados|Desactivar recepção de contactos falhados]], [[#Mostrar saldo de cliente|Mostrar saldo de cliente]].
| |
| | |
| <!--As etiquetas das opções deste menu estão definidas na classe '''prr.app.products.Label'''. -->Todos os métodos correspondentes às mensagens de diálogo para este menu estão definidos na classe '''prr.app.products.Message'''.
| |
| | |
| Sempre que é pedido o identificador de um cliente ('''Prompt.clientKey()''') e o identificador não existir (excepto no processo de registo), é lançada a excepção '''UnknownClientKeyException'''. Na ocorrência de excepções<!-- (estas ou outras)-->, as operações não têm efeito.
| |
| | |
| {{CVSCode|Estes comandos já estão implementados nas classes da ''package'' '''prr.app.clients''' (disponível no CVS), respectivamente: '''DoShowAllClients''', '''DoRegisterClient''', '''DoSetFailedContactsOn''', '''DoSetFailedContactsOff''', '''DoShowClientBalance'''.}}
| |
| | |
| === Visualizar todos os clientes ===
| |
| O formato de apresentação de cada cliente é o seguinte, em que ''nTerminals'' é o número de terminais activos associados ao cliente e ''balance'' é o somatório do saldo de cada um desses terminais (valor arredondado ao inteiro mais próximo). Os valores para ''clientType'' são '''NORMAL''', '''GOLD''', ou '''PLATINUM'''. Os valores para ''answeringStatus'' são '''ON''' ou '''OFF'''. Se o cliente não tiver terminais, o saldo é 0 (zero).
| |
| | |
| CLIENTE|''clientId''|''clientName''|''NIF''|''clientType''|''answeringStatus''|''nTerminals''|''balance''
| |
| | |
| === Registar cliente ===
| |
| | |
| O sistema pede o identificador que ficará associado ao cliente (identificador único}. De seguida, pede o nome do cliente ('''Prompt.clientName()''') e o número de identificação fiscal ('''Prompt.fiscalId()'''). 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 é enviada a mensagem '''alreadyActive()'''.
| |
| | |
| === 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 é enviada a mensagem '''alreadyInactive()'''.
| |
| | |
| === Mostrar saldo de cliente ===
| |
| | |
| O sistema pede o identificador do cliente, apresentando o seu saldo. Tal como acima, o saldo do cliente é o somatório do saldo de cada um desses terminais (valor arredondado ao inteiro mais próximo).
| |
| | |
| == 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|Mostrar todos os terminais]], [[#Registar terminal|Registar terminal]], [[#Menu de administração de terminal|Menu de administração de terminal]].
| |
| | |
| <!--As etiquetas das opções deste menu estão definidas na classe '''prr.app.terminals.Label'''. -->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).<!-- No processo de registo, caso o identificador indicado já exista, deve ser lançada a excepção '''DuplicateTerminalKeyException'''.--> 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.
| |
| | |
| {{CVSCode|Estes comandos já estão implementados nas classes da ''package'' '''prr.app.partners''' (disponível no CVS), respectivamente: '''DoShowAllTerminals''', '''DoRegisterTerminal''', '''DoOpenMenuTerminalAdministration'''.}}
| |
| | |
| === Mostrar todos os terminais ===
| |
| | |
| O formato de apresentação de cada terminal é o seguinte:
| |
| | |
| TERMINAL|''terminalId''|''clientId''|''terminalType''|''terminalStatus''|''terminalBalance''|''friend1'',...,''friendN''
| |
| | |
| Os valores para o campo ''terminalType'' são '''Basic''' ou '''Fancy'''. Os valores para o campo ''terminalStatus'' são '''ON''', '''OFF''', '''SILENCE'''. Os valores ''friend1'', ..., ''friendN'' são os identificadores dos terminais amigos e são apresentados por ordem crescente desses identificadores.
| |
| | |
| === Registar terminal ===
| |
| | |
| É pedido o número identificador do terminal com exactamente 6 dígitos (se o número introduzido não contiver exactamente 6 dígitos, o pedido é repetido). De seguida, o sistema pede o tipo de terminal ('''Prompt.terminalType()'''). A resposta deve ser '''Basic''' ou '''Fancy'''. 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 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 todas as comunicações]], [[#Mostrar comunicações feitas por um cliente|Mostrar comunicações feitas por um cliente]], [[#Mostrar comunicações recebidas por um cliente|Mostrar comunicações recebidas por um cliente]], [[#Mostrar clientes sem dívidas|Mostrar clientes sem dívidas]], [[#Mostrar clientes com dívidas|Mostrar clientes com dívidas]], [[#Mostrar terminais sem actividade|Mostrar terminais sem actividade]], [[#Mostrar terminais com saldo positivo|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.
| |
| | |
| {{CVSCode|Estes comandos já estão parcialmente implementados nas classes da ''package'' '''prr.app.lookups''' (disponível no CVS), respectivamente: '''DoShowAllCommunications''', '''DoShowCommunicationsInitiatedByClient''', '''DoShowCommunicationsReceivedByClient''', '''DoShowClientsWithoutDebt''', '''DoShowClientsWithDebt''', '''DoShowUnusedTerminals''', '''DoShowTerminalsWithPositiveBalance'''.}}
| |
| | |
| === Mostrar todas as comunicações ===
| |
| | |
| O formato de apresentação é o seguinte:
| |
| | |
| COMMUNICATION|''idCommunication''|''idSender''|''idReceiver''|''type''|''cost''|''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 '''COMPLETE''' (a comunicação teve lugar); '''FORGOTTEN''' (a comunicação não teve lugar e a tentativa não ficou registada no chamador); '''REGISTERED''' (a comunicação não teve lugar, mas a tentativa ficou registada no chamador).
| |
| Quando o tipo de mensagem é '''FORGOTTEN''' ou '''REGISTERED''', tanto a duração (''length'') como o custo (''cost'') são 0 (zero).
| |
| | |
| === Mostrar comunicações feitas por um cliente ===
| |
| | |
| É pedido o identificador do cliente, sendo apresentadas as por ele originadas.
| |
| | |
| === Mostrar comunicações recebidas por um cliente ===
| |
| | |
| É pedido o identificador do cliente, sendo apresentadas as 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 positivo, ou seja, superior a zero cêntimos.
| |
| | |
| == Menu de administração de terminal ==
| |
| Este menu apresenta as operações relacionadas com admibistração de um terminal. A lista completa é a seguinte: [[#Ligar terminal|Ligar terminal]], [[#Desligar terminal|Desligar terminal]], [[#Silenciar terminal|Silenciar terminal]], [[#Adicionar amigo|Adicionar amigo]], [[#Retirar amigo|Retirar amigo]], [[#Efectuar pagamento|Efectuar pagamento]], [[#Consultar saldo|Consultar saldo]], [[#Efectuar comunicação|Efectuar comunicação]].
| |
| | |
| 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.
| |
| <!--
| |
| Se o parceiro indicado estiver inibido de efectuar transacções, deve ser lançada a excepção '''UnauthorizedPartnerException''' e o comando não tem efeito. --><!--Se o identificador de um produto não corresponder ao fornecedor indicado, deve ser lançada a excepção '''WrongSupplierException''' e o comando não tem efeito.-->
| |
| | |
| {{CVSCode|Estes comandos já estão implementados nas classes da ''package'' '''prr.app.admin''' (disponível no CVS), respectivamente: '''DoTurnTerminalOn''', '''DoTurnTerminalOff''', '''DoSilenceTerminal''', '''DoAddFriend''', '''DoRemoveFriend''', '''DoPerformPayment''', '''DoShowBalance''', '''DoPerformCommunication.}}
| |
| | |
| === Ligar terminal ===
| |
| Se o terminal indicado já estiver ligado, envia a mensagem '''alreadyOn()'''. Se for necessário enviar mensagens aos terminais que tentaram o contacto enquanto o terminal não permaneceu ligado, usa-se a mensagem '''isNowAvailable()''', indicando-se o emissor. Estas mensagens devem ser ordenadas pelos números dos terminais que tentaram o contacto e só deve ser enviada uma mensagem a cada terminal que tentou o contacto, mesmo que tenha havido mais do que uma tentativa de contacto.
| |
| | |
| === Desligar terminal ===
| |
| Se o terminal indicado já estiver desligado, envia a mensagem '''alreadyOff()'''.
| |
| | |
| === Silenciar terminal ===
| |
| Se o terminal já estiver em silêncio, envia a mensagem '''alreadySilent()'''. Se estava anteriormente desligado e se for necessário enviar mensagens aos terminais que tentaram o contacto por SMS enquanto o terminal permaneceu desligado, usa-se a mensagem '''isAvailableForSMS()''', indicando-se o emissor. Estas mensagens devem ser ordenadas pelos números dos terminais que tentaram o contacto e só deve ser enviada uma mensagem a cada terminal que tentou o contacto, mesmo que tenha havido mais do que uma tentativa de contacto.
| |
| | |
| === 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, em cêntimos, associado ao terminal.
| |
| | |
| === Iniciar comunicação ===
| |
| Se o terminal a partir do qual se pretende efectuar a comunicação estiver desligado, apresenta a mensagem '''terminalIsOff()''' e a operação termina.
| |
| | |
| É pedido o identificador do número do terminal a contactar. Se o número pretendido não existir, apresenta a mensagem '''noSuchTerminal()''' (neste caso, excepcionalmente, não é lançada nenhuma excepção). Se o número existir, é pedido o tipo de comunicação ('''Prompt.commType()''') (a resposta deve ser uma cadeia de caracteres: '''VOICE''', '''TEXT''', '''VIDEO'''. Se a resposta não corresponder a nenhum dos três valores, a pergunta é repetida até se obter uma resposta válida.
| |
| | |
| Sempre que se tenta iniciar uma comunicação '''VIDEO''' a partir de um terminal Basic, deve ser lançada a excepção '''VideoFromBasicException'''. Se o terminal de origem for Fancy mas tentar realizar uma comunicação '''VIDEO''' para um terminal Basic, é lançada a excepção '''VideoToBasicException'''. Quando é lançada uma excepção, não se regista a tentativa de comunicação (o contador de chamadas não deve ser incrementado) e não são feitas mais perguntas.
| |
| | |
| Quando o terminal de destino está desligado, é apresentada a mensagem '''termoinalIsOff()'''. Quando o terminal de destino está em silêncio e a comunicação pretendida é '''VOICE''' ou '''VIDEO''', é apresentada a mensagem terminalIsSilent()''.
| |
| | |
| No caso de comunicações de texto, a mensagem termina automaticamente.
| |
| | |
| === Terminar comunicação ===
| |
| | |
| Se o terminal estiver em comunicação (ocupado), é terminada a comunicação e registada a sua duração da não estiver ocupado. Só o chamador é que pode terminar a comunicação.
| |
| | |
| Se e só se a comunicação for possível, é pedida a duração da chamada ('''VOICE''' e '''VIDEO''') com '''Prompt.duration()''' (número inteiro) ou o número de caracteres ('''TEXT''') com '''Prompt.chararacters()'''. É ainda apresentada a mensagem '''costOfMessage()''' com o custo da comunicação para o interlocutor (chamador ou chamado -- o custo para o chamado é zero).
| |
| | |
| = Leitura de Dados a Partir de Ficheiros Textuais =
| |
|
| |
| Além das opções de manipulação de ficheiros descritas no [[#Salvaguarda do Documento Actual|menu principal]], é possível iniciar a aplicação com um ficheiro de texto especificado pela propriedade Java '''[[#Execução dos Programas e Testes Automáticos|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''|''xxx''|''nível''
| |
| TERMINAL|''idTerminal''|''idClient''|''type''|''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.
| |
| | |
| Um exemplo de conteúdo do ficheiro inicial é como se segue:
| |
| | |
| {{CollapsedCode|Exemplo de ficheiro de entrada textual|
| |
| <source lang="text">
| |
| 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
| |
| TERMINAL|969001|cli001|Basic|ON|-900
| |
| TERMINAL|969003|cli002|Basic|ON|0
| |
| TERMINAL|969002|cli002|Fancy|SILENCE|330
| |
| TERMINAL|969007|cli Es|Fancy|ON|700
| |
| TERMINAL|969008|cli003|Basic|OFF|2500
| |
| TERMINAL|969009|cli003|Basic|OFF|1200
| |
| TERMINAL|969010|cli003|Basic|ON|-2100
| |
| TERMINAL|969006|cli003|Fancy|ON|4800
| |
| TERMINAL|969005|cli003|Fancy|ON|3400
| |
| TERMINAL|969004|cli003|Basic|ON|1000
| |
| FRIENDS|969001|969008,969009,969004
| |
| FRIENDS|969004|969001
| |
| FRIENDS|969003|969008
| |
| </source>
| |
| }}
| |
| A codificação dos ficheiros a ler é garantidamente [[wp:UTF-8|UTF-8]].
| |
| | |
| {{Suggestion|Note-se que o programa nunca produz ficheiros com este formato.}}
| |
| | |
| = 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 [[Programação com Objectos/Projecto de Programação com Objectos/Material de Apoio ao Desenvolvimento|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'' '''[https://docs.oracle.com/javase/8/docs/api/java/io/package-summary.html java.io]''', em particular, a interface '''[https://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html java.io.Serializable]''' e as classes de leitura '''[https://docs.oracle.com/javase/8/docs/api/java/io/ObjectInputStream.html java.io.ObjectInputStream]''' e escrita '''[https://docs.oracle.com/javase/8/docs/api/java/io/ObjectOutputStream.html java.io.ObjectOutputStream]''' (entre outras).
| |
| <!--
| |
| A representação e manipulação de datas e tempos deve ser realizada através das classes da ''package'' '''[https://docs.oracle.com/javase/8/docs/api/java/time/package-summary.html java.time]''', em particular, através das classes '''[https://docs.oracle.com/javase/8/docs/api/java/time/LocalDate.html java.time.LocalDate]''' e '''[https://docs.oracle.com/javase/8/docs/api/java/time/LocalTime.html java.time.LocalTime]'''. Diferenças entre tempos são representadas pela classe '''[https://docs.oracle.com/javase/8/docs/api/java/time/Duration.html java.time.Duration]'''.
| |
| -->
| |
| <!--
| |
| [[category:Ensino]]
| |
| [[category:PO]]
| |
| [[category:Projecto de PO]]
| |
| [[en:Object-Oriented Programming]]
| |
| -->
| |