|
|
(One intermediate revision by the same user not shown) |
Line 1: |
Line 1: |
| {{PRJPOAvisosEN20172018}}
| | #REDIRECT [[ist:Programação com Objectos/Projecto de Programação com Objectos/Enunciado do Projecto de 2017-2018 (rascunho de Agosto)]] |
| {{PRJPOMandatory20172018}}
| |
| {{TOCright}}
| |
| <!--'''<font color="red">ÉPOCA NORMAL</font>'''-->
| |
| | |
| O objectivo do projecto é criar uma aplicação que gere os itinerários de passageiros que usam comboios.
| |
| | |
| Os itinerários são constituídos por um ou mais segmentos, realizados por comboios que cumprem serviços pré-definidos.
| |
| | |
| Neste texto, o tipo '''negrito''' indica um literal (i.e., é exactamente como apresentado); o símbolo <amsmath>\verb*| |</amsmath> indica um espaço; e o tipo ''itálico'' indica uma parte variável (i.e., uma descrição).
| |
| | |
| = Estrutura dos serviços, dos passageiros e dos itinerários =
| |
| | |
| Existem três conceitos básicos: serviços, passageiros e itinerários.
| |
| | |
| == Estrutura de um serviço ==
| |
| | |
| Um serviço é um percurso realizado por um comboio ao longo de várias estações. A cada estação de um serviço está associado o momento de partida do comboio. Assume-se que todos os serviços se realizam em todos os dias. Além das informações anteriores, o serviço tem ainda um identificador numérico único (definido na criação do serviço).
| |
| | |
| {{CollapsedCode|Exemplo de serviço: Serviço 850: Valença >> Porto - Campanhã|
| |
| Serviço #850 - 10.95
| |
| 07:36 Valença
| |
| 07:47 Vila Nova de Cerveira
| |
| 07:56 Caminha
| |
| 08:03 Âncora Praia
| |
| 08:16 Viana do Castelo
| |
| 08:20 Areia-Darque
| |
| 08:30 Barroselas
| |
| 08:37 Tamel
| |
| 08:53 Barcelos
| |
| 09:05 Nine
| |
| 09:13 Famalicão
| |
| 09:21 Trofa
| |
| 09:35 Ermesinde
| |
| 09:45 Porto - Campanhã
| |
| }}
| |
| | |
| Cada segmento de um serviço tem um custo base, que depende da distância entre estações. A distância entre estações corresponde ao tempo gasto na viagem entre essas estações. Assim, considerando que a totalidade do custo do serviço 850 (no exemplo acima) é de €10.95 (para 129 minutos), o custo do segmento Viana do Castelo >> Nine (para 49 minutos) é de 10.95 * 49 / 129 = €4.16.
| |
| | |
| O preço pago pelo passageiro depende ainda da sua categoria, que pode ser normal ou outra (a adição de novas categorias deve ter impacto reduzido no código da aplicação).
| |
| | |
| Considera-se que apenas existem as estações que aparecem em, pelo menos, um serviço.
| |
| | |
| == Estrutura de um passageiro ==
| |
| | |
| Um passageiro tem um identificador único e um nome (cadeia de caracteres). O identificador único é atribuído automaticamente e de forma sequencial no momento do registo do passageiro, sendo atribuído o identificador 0 (zero) ao primeiro passageiro.
| |
| | |
| Os passageiros são categorizados como normais, frequentes ou especiais. Um passageiro é considerado frequente enquanto o valor dos últimos 10 itinerários for superior a €250. Volta a ser normal se esta condição deixar de se verificar. Um cliente é considerado especial enquanto tiver gasto mais de €2500 nos últimos 10 itinerários. Deixa de ser especial se esta condição deixar de se verificar. Se se verificarem simultâneamente as condições para ser um cliente frequente e especial, o cliente é considerado especial. Aplicam-se as seguintes condições para atribuição de descontos em itinerários: passageiros normais, 0%; passageiros frequentes, 15%; passageiros especiais, 50%.
| |
| | |
| == Estrutura de um itinerário ==
| |
| | |
| Um itinerário corresponde a uma viagem realizada num dado dia, com base num conjunto de segmentos lógicos, correspondentes a partes de serviços, i.e., partidas (ou chegadas) agendadas para cada estação. <!-- Cada segmento tem uma estação e hora de partida e uma estação e hora de chegada.-->É possível saber, através do serviço associado, qual o percurso a realizar nesse segmento.
| |
| | |
| O custo base do itinerário é a soma dos custos parciais de cada serviço que o constitui, correspondentes aos segmentos realizados nesses serviços. Dependendo da categoria do passageiro, podem ser realizados descontos.
| |
| | |
| Os itinerários são identificados por um número de ordem no contexto de cada passageiro. Não é possível remover itinerários já registados.
| |
| | |
| {{CollapsedCode|Exemplo de itinerário: Évora >> Loulé|
| |
| <text>
| |
| Itinerário 3 para 2017-10-18 - 25.84
| |
| Serviço #690 - 6.37
| |
| 07:06 Évora
| |
| 07:17 Casa Branca
| |
| 07:31 Vendas Novas
| |
| 07:53 Pinhal Novo
| |
| Serviço #180 - 19.47
| |
| 09:06 Pinhal Novo
| |
| 10:54 Tunes
| |
| 11:01 Albufeira - Ferreiras
| |
| 11:13 Loulé
| |
| </text>
| |
| }}
| |
| | |
| = Funcionalidade da aplicação =
| |
| | |
| A aplicação permite manter informação sobre serviços. Permite ainda registar e gerir passageiros e criar novos itinerários para eles. 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).
| |
| | |
| A base de dados de serviços é [[#Leitura de Dados a Partir de Ficheiros Textuais|carregada no início da aplicação]]. Não é possível adicionar ou remover serviços durante a execução da aplicação.
| |
| | |
| {{Suggestion|Note-se que não é necessário 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 '''mmt.TicketOffice''' e outras fornecdidas (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.}}
| |
| | |
| == Consultas de Serviços ==
| |
| | |
| É possível fazer várias consultas sobre serviços (ver também abaixo). É possível ver todos os serviços, inspeccionar um serviço particular e inspeccionar serviços com base na especificação de estações. Podem ser definidas, no futuro, outras formas de pesquisa e de apresentação de serviços.
| |
| | |
| == Manipulação de Passageiros ==
| |
| | |
| A aplicação permite realizar várias operações sobre passageiros. É possível obter a lista completa de passageiros conhecidos, assim como informação detalhada sobre passageiros individuais. É ainda possível registar novos passageiros e alterar o nome dos passageiros.
| |
| | |
| == Manipulação de Itinerários ==
| |
| | |
| A aplicação permite obter informações sobre todos os itinerários já comprados ou, em pormenor, sobre os itinerários de passageiros específicos. Permite ainda criar novos itinerários.
| |
| | |
| Os passageiros são creditados com o valor monetário de cada itinerário comprado e com o tempo decorrido nesses itinerários (medido entre os pontos extremos). <!--O crédito destes valores depende da categoria do passageiro.-->
| |
| | |
| == Serialização ==
| |
| | |
| É possível reiniciar (ou seja, mantendo a informação sobre serviços, eliminar a informação sobre passageiros e itinerários), guardar e recuperar o estado actual da aplicação, preservando todos a informação sobre serviços, passageiros e itinerários.
| |
| | |
| = 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 proceder à 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-uuilib''' e '''mmt-app'''). As mensagens não podem ser usadas no núcleo da aplicação ('''mmt-core'''). Além disso, não podem ser definidas novas. Potenciais omissões devem ser esclarecidas antes de qualquer implementação.
| |
| | |
| As excepções usadas na interacção, excepto se indicado, são subclasses de '''pt.tecnico.po.ui.DialogException''', são lançadas pelos comandos e tratadas por '''pt.tecnico.po.ui.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'' '''mmt.app''', '''mmt.app.main''', '''mmt.app.service''', '''mmt.app.passenger''' e '''mmt.app.itinerary'''. 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 '''mmt-app''').}}
| |
| | |
| == Menu Principal ==
| |
| | |
| As acções do menu permitem gerir a salvaguarda do estado da aplicação e abrir submenus. A lista completa é a seguinte: [[#Salvaguarda do estado actual da aplicação|Reiniciar]], [[#Salvaguarda do estado actual da aplicação|Abrir]], [[#Salvaguarda do estado actual da aplicação|Guardar]] e [[#Gestão e consulta de dados da aplicação|Consulta de Serviços]], [[#Gestão e consulta de dados da aplicação|Manipulação de Passageiros]] e [[#Gestão e consulta de dados da aplicação|Manipulação de Itinerários]]. Inicialmente, a aplicação apenas tem informação sobre os serviços que foram carregados no arranque.
| |
| | |
| As etiquetas das opções deste menu estão definidas na classe '''mmt.app.main.Label'''. Todos os métodos correspondentes às mensagens de diálogo para este menu estão definidos na classe '''mmt.app.main.Message'''.
| |
| | |
| {{CVSCode|Estes comandos já estão implementados nas classes da ''package'' '''mmt.app.main''' (disponível no CVS), respectivamente: '''DoReset''', '''DoOpen''', '''DoSave''', '''DoOpenServicesMenu''', '''DoOpenPassengersMenu''', '''DoOpenItinerariesMenu'''.}}
| |
| | |
| === Salvaguarda do estado actual da aplicação ===
| |
| | |
| O conteúdo da aplicação (inclui todos os serviços, passageiros e itinerários 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:
| |
| | |
| * '''Reiniciar''' -- Reinicia a aplicação: destrói toda a informação sobre passageiros e itinerários; mantém toda a informação sobre serviços.
| |
| * '''Abrir''' -- Carrega os dados de uma sessão anterior a partir de um ficheiro (ficando associado à aplicação). A informação a carregar compreende serviços, passageiros e itinerários. Pede-se o nome do ficheiro a abrir ('''openFile()'''). Caso o ficheiro não exista, é apresentada a mensagem '''fileNotFound()'''.
| |
| * '''Guardar''' -- Guarda o estado actual da aplicação (serviços, passageiros e itinerários) 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 '''newSaveAs()'''. Não é executada nenhuma acção se não existirem alterações desde a última salvaguarda.
| |
| | |
| As opções '''Reiniciar''' e '''Abrir''' substituem a informação na aplicação nas condições indicadas acima.
| |
| | |
| A opção '''Sair''' nunca guarda o estado da aplicação, mesmo que existam alterações.
| |
| | |
| === Gestão e consulta de dados da aplicação ===
| |
| | |
| * '''Consulta de Serviços''' -- Abre o menu de consulta de serviços (se existirem serviços registados).
| |
| * '''Gestão de Passageiros''' -- Abre o menu de gestão de passageiros (se existirem passageiros registados).
| |
| * '''Gestão de Itinerários''' -- Abre o menu de gestão de itinerários (se existirem itinerários registados).
| |
| | |
| == Menu de Consulta de Serviços ==
| |
| | |
| Este menu permite efectuar consultas sobre a base de dados de serviços. A lista completa é a seguinte: [[#Mostrar todos os serviços|Mostrar todos os serviços]], [[#Mostrar serviço com um dado número|Mostrar serviço com um dado número]], [[#Mostrar serviços com origem numa estação dada|Mostrar serviços com origem numa estação dada]], [[#Mostrar serviços com término numa estação dada|Mostrar serviços com término numa estação dada]].
| |
| | |
| As etiquetas das opções deste menu estão definidas na classe '''mmt.app.service.Label'''. Todos os métodos correspondentes às mensagens de diálogo para este menu estão definidos na classe '''mmt.app.service.Message'''.
| |
| | |
| Sempre que for pedido o identificador de um serviço ('''requestServiceId()''') e o serviço não existir, é lançada a excepção '''mmt.app.NoSuchServiceException'''.
| |
| Sempre que for pedido o nome de uma estção ('''requestStationName()''') e a estação não existir, é lançada a excepção '''mmt.app.NoSuchStationException'''.
| |
| | |
| {{CVSCode|Estes comandos já estão implementados nas classes da ''package'' '''mmt.app.service''' (disponível no CVS), respectivamente: '''DoShowAllServices''', '''DoShowServiceByNumber''', '''DoShowServicesDepartingFromStation''', '''DoShowServicesArrivingAtStation'''.}}
| |
| | |
| === Mostrar todos os serviços ===
| |
| | |
| Apresenta informações sobre todos os serviços conhecidos. A lista é ordenada pelo identificador do serviço e o formato é o descrito em [[#Mostrar serviço com um dado número|Mostrar serviço com um dado número]].
| |
| | |
| === Mostrar serviço com um dado número ===
| |
| | |
| Apresenta informações sobre um serviço. Depois de pedir o identificador do serviço ('''requestServiceId()'''), apresenta a informação sobre o serviço, tal como indicado no formato seguinte, para um serviço com N paragens (HH;MM representa o tempo em horas e minutos). O preço deve ser apresentado com duas casas decimais.
| |
| | |
| Serviço #<font color="brown">''número-do-serviço''</font> @ <font color="brown">''preço''</font>
| |
| <font color="brown">''HH:MM''</font> <font color="brown">''nome-de-estação-1''</font>
| |
| ...
| |
| <font color="brown">''HH:MM''</font> <font color="brown">''nome-de-estação-N''</font>
| |
| | |
| {{CollapsedCode|Exemplo de apresentação de serviço: Serviço 180: Porto >> Faro|
| |
| <text>
| |
| Serviço #180 @ 51.50
| |
| 05:47 Porto - Campanhã
| |
| 05:52 Vila Nova de Gaia-Devesas
| |
| 06:21 Aveiro
| |
| 06:46 Coimbra-B
| |
| 08:23 Lisboa - Oriente
| |
| 08:31 Lisboa - Entrecampos
| |
| 09:06 Pinhal Novo
| |
| 10:54 Tunes
| |
| 11:01 Albufeira - Ferreiras
| |
| 11:13 Loulé
| |
| 11:23 Faro
| |
| </text>
| |
| }}
| |
| | |
| === Mostrar serviços com origem numa estação dada ===
| |
| | |
| Apresenta os números e estações terminais dos serviços com origem na estação indicada como resposta a '''requestStationName()''', ordenado por hora de partida do serviço.
| |
| | |
| O formato de apresentação é o descrito em [[#Mostrar serviço com um dado número|Mostrar serviço com um dado número]].
| |
| | |
| === Mostrar serviços com término numa estação dada ===
| |
| | |
| Apresenta os números e estações de origem dos serviços com término na estação indicada como resposta a '''requestStationName()''', ordenado por hora de chegada do serviço.
| |
| | |
| O formato de apresentação é o descrito em [[#Mostrar serviço com um dado número|Mostrar serviço com um dado número]].
| |
| | |
| == Menu de Gestão de Passageiros ==
| |
| | |
| Este menu permite efectuar operações sobre um passageiro. A lista completa é a seguinte: [[#Mostrar passageiros|Mostrar passageiros]], [[#Mostrar passageiro|Mostrar passageiro]], [[#Registar passageiro|Registar passageiro]], [[#Alterar nome de passageiro|Alterar nome de passageiro]].
| |
| | |
| As etiquetas das opções deste menu estão definidas na classe '''mmt.app.passenger.Label'''. Todos os métodos correspondentes às mensagens de diálogo para este menu estão definidos na classe '''mmt.app.passenger.Message'''.
| |
| | |
| Sempre que for pedido o identificador de um passageiro ('''requestPassengerId()''') e o passageiro não existir, é lançada a excepção '''mmt.app.NoSuchPassengerException'''.
| |
| | |
| {{CVSCode|Estes comandos já estão implementados nas classes da ''package'' '''mmt.app.passenger''' (disponível no CVS), respectivamente: '''DoShowAllPassengers''', '''DoShowPassengerById''', '''DoRegisterPassenger''', '''DoChangePassengerName'''.}}
| |
| | |
| === Mostrar passageiros ===
| |
| | |
| Apresenta informações sobre todos os passageiros conhecidos. A lista é ordenada pelo identificador e o formato é o descrito em [[#Mostrar passageiro|Mostrar passageiro]].
| |
| | |
| === Mostrar passageiro ===
| |
| | |
| Apresenta informações sobre um passageiro. Depois de pedir o identificador do passageiro ('''requestPassengerId()'''), apresenta o nome, a categoria do passageiro ('''NORMAL''', '''FREQUENTE''', '''ESPECIAL'''), o número de itinerários adquiridos, o tempo acumulado (formato HH:MM) correspondente aos itinerários adquiridos e o valor pago por esses itinerários (o valor pago deve ser apresentado com duas casas decimais).
| |
| | |
| Formato:
| |
| ''id'' | ''nome'' | ''categoria'' | ''número-de-itinerários'' | ''valor-pago'' | ''tempo-acumulado''
| |
| | |
| Exemplo:
| |
| 1234|John Doe|NORMAL|123|9876.54|123:45
| |
| | |
| === Registar passageiro ===
| |
| | |
| Permite registar um passageiro no sistema. É pedido o nome do passageiro ('''requestPassengerName()'''). O novo passageiro é categorizado como '''NORMAL'''.
| |
| | |
| === Alterar nome de passageiro ===
| |
| | |
| Permite alterar o nome do passageiro. Para tal, pede-se o identificador do passageiro cujo nome deve ser alterado ('''requestPassengerId()''') e o novo nome ('''requestPassengerName()''').
| |
| | |
| == Menu de Gestão de Itinerários ==
| |
| | |
| Este menu permite efectuar operações sobre itinerários. A lista completa é a seguinte: [[#Mostrar todos os itinerários|Mostrar todos os itinerários]], [[#Mostrar itinerários associados a um passageiro|Mostrar itinerários associados a um passageiro]], [[#Registar itinerário para um passageiro|Registar itinerário para um passageiro]]<!--, [[#Mostrar histogramas por serviço|Mostrar histogramas por serviço]]-->.
| |
| | |
| As etiquetas das opções deste menu estão definidas na classe '''mmt.app.itinerary.Label'''. Todos os métodos correspondentes às mensagens de diálogo para este menu estão definidos na classe '''mmt.app.itinerary.Message'''.
| |
| | |
| {{CVSCode|Estes comandos já estão parcialmente implementados nas classes da ''package'' '''mmt.app.passenger''' (disponível no CVS), respectivamente: '''DoShowAllItineraries''', '''DoShowPassengerItineraries''', '''DoRegisterItinerary''', '''DoShowTotalValue''', '''DoShowServiceHistograms'''.}}
| |
| | |
| === Mostrar todos os itinerários ===
| |
| | |
| Apresenta todos os itinerários registados para todos os passageiros. O formato de apresentação é como para os serviços, mas apenas se apresenta o segmento percorrido e o respectivo custo. A informação é apresentada para cada passageiro, sendo os passageiros apresentados por ordem crescente do seu número de identificação. <!-- e, para cada passageiro, pela estação de origem do itinerário.-->
| |
| | |
| O formato de apresentação é como definido para a [[#Mostrar itinerários associados a um passageiro|apresentação dos itinerários de um passageiro]], mas apresenta-se a informação relativamente a todos os passageiros.
| |
| | |
| Note-se que a apresentação de itinerários apenas tem significado quando existem itinerários para mostrar, i.e., não se devem apresentar passageiros que não têm itinerários.
| |
| | |
| === Mostrar itinerários associados a um passageiro ===
| |
| | |
| Apresenta os itinerários do passageiro cujo identificador é pedido através de '''requestPassengerId()'''. A lista é ordenada pela data dos itinerários.
| |
| | |
| Se o passageiro não tiver itinerários, deve ser apresentada a mensagem '''noItineraries()'''.
| |
| | |
| O formato de apresentação é análogo ao dos serviços, iniciado com uma linha com o identificador do passageiro, à qual se segue a lista de itinerários, cada um precedido da linha com o número de ordem do itinerário (no contexto de cada passageiro) e da data correspondente:
| |
| | |
| <nowiki>==</nowiki> Passageiro <font color="brown">''identificador-do-passageiro''</font>: <font color="brown">''nome-do-passageiro''</font> <nowiki>==</nowiki>
| |
| Itinerário <font color="brown">''número-de-ordem-do-itinerário''</font> para <font color="brown">''data''</font> @ <font color="brown">''preço-total-do-itinerário''</font>
| |
| | |
| O preço associado a cada serviço no itinerário é o da fracção do tempo do serviço nesse itinerário, com duas casas decimais. O preço do itinerário é a soma (sem arredondamentos) dos preços dos segmentos que o formam, apresentado com duas casas decimais.
| |
| | |
| {{CollapsedCode|Exemplo de apresentação de itinerários para um passageiro|
| |
| <text>
| |
| == Passageiro 2: José Simão ==
| |
| | |
| Itinerário 1 para 2017-10-18 @ 20.03
| |
| Serviço #692 @ 6.37
| |
| 09:06 Évora
| |
| 09:17 Casa Branca
| |
| 09:31 Vendas Novas
| |
| 09:53 Pinhal Novo
| |
| Serviço #570 @ 13.66
| |
| 10:48 Pinhal Novo
| |
| 11:19 Grândola
| |
| 11:33 Ermidas-Sado
| |
| 11:55 Funcheira
| |
| 12:24 Santa Clara-Sabóia
| |
| 12:52 Messines-Alte
| |
| 13:02 Tunes
| |
| | |
| Itinerário 2 para 2017-10-25 @ 22.57
| |
| Serviço #184 @ 16.41
| |
| 15:35 Tunes
| |
| 17:23 Pinhal Novo
| |
| Serviço #596 @ 6.17
| |
| 17:48 Pinhal Novo
| |
| 18:10 Vendas Novas
| |
| 18:24 Casa Branca
| |
| 18:35 Évora
| |
| </text>
| |
| }}
| |
| | |
| === Registar itinerário para um passageiro ===
| |
| | |
| Esta acção permite registar um novo itinerário para um passageiro.
| |
| | |
| Para tal, pede-se o identificador do passageiro ('''requestPassengerId()'''), a nome da estação de partida ('''requestDepartureStationName()'''), o nome da estação de destino ('''requestArrivalStationName()'''), a data da partida, no formato [https://en.wikipedia.org/wiki/ISO_8601 YYYY-MM-DD] ('''requestDepartureDate()'''), e a hora mínima para a partida, no formato HH:MM ('''requestDepartureTime()''').
| |
| | |
| Se a data não estiver num formato correcto, é lançada a excepção '''mmt.app.BadDateException''', não sendo realizada nenhuma acção.
| |
| | |
| Se a hora não estiver num formato correcto, é lançada a excepção '''mmt.app.BadTimeException''', não sendo realizada nenhuma acção.
| |
| | |
| Se não for possível fazer uma reserva, i.e., o número de candidatos é nulo, é apresentada a mensagem '''noItinerariesBetween()''', não sendo realizada nenhuma acção.
| |
| | |
| Em caso de sucesso, como resultado, o sistema apresenta uma lista com todos os candidatos encontrados (ordenados hierarquicamente pelos seguintes critérios: hora de partida, hora de chegada e tempo de viagem). Se forem encontradas múltiplas alternativas com o mesmo serviço de partida, apenas se apresenta a que chega mais cedo (excepto se existir uma ligação directa nesse serviço, mesmo que mais lenta). De seguida, o sistema pede o número da alternativa ('''requestItineraryChoice()''') a guardar (1 para a primeira alternativa, etc.) no registo dos itinerários adquiridos pelo passageiro, actualizando-se o estado correspondente.
| |
| | |
| Se a escolha for 0 (zero), não é realizada nenhuma acção e os itinerários candidatos são descartados.
| |
| | |
| Se a escolha corresponder a um número de itinerário inválido, é lançada a excepção '''mmt.app.NoSuchItineraryException''', não sendo realizada nenhuma acção (são descartados eventuais itinerários candidatos).
| |
| | |
| O formato de apresentação das escolhas é como definido para os itinerários, mas sem a linha relativa ao passageiro.
| |
| | |
| {{CollapsedCode|Exemplo de apresentação de hipótese de itinerário: Évora >> Tunes (opção #3)|
| |
| <text>
| |
| Itinerário 3 para 2017-11-21 @ 20.38
| |
| Serviço #694 @ 6.65
| |
| 16:57 Évora
| |
| 17:08 Casa Branca
| |
| 17:22 Vendas Novas
| |
| 17:29 São João das Craveiras
| |
| 17:33 Pegoes
| |
| 17:38 Fernando Pó
| |
| 17:43 Poceirão
| |
| 17:51 Pinhal Novo
| |
| Serviço #574 @ 13.73
| |
| 18:18 Pinhal Novo
| |
| 18:46 Grândola
| |
| 19:01 Ermidas-Sado
| |
| 19:29 Funcheira
| |
| 19:57 Santa Clara-Sabóia
| |
| 20:24 Messines-Alte
| |
| 20:34 Tunes
| |
| </text>
| |
| }}
| |
| | |
| = 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]]'''. <!--Este ficheiro contém um programa que é avaliado pelo interpretador. Se não existirem definições de variáveis, a avaliação não deixa traços na memória da calculadora. Apenas é lida a primeira expressão presente no ficheiro. O programa fica registado com o nome '''import'''.-->
| |
| | |
| == Exemplo de ficheiro a importar ==
| |
| | |
| O formato é como exemplificado a seguir. A notação "..." significa repetição de formato. Nos itinerários, o primeiro número indica o identificador único do passageiro e as outras entradas (a seguir à data) indicam o serviço e as estações correspondentes de início e fim do troço que faz parte do itinerário.
| |
| <text>
| |
| SERVICE|180|51.5|05:47|Porto - Campanhã|...|11:23|Faro
| |
| SERVICE|694|12.2|16:57|Évora|17:08|Casa Branca|...|18:36|Lisboa - Oriente
| |
| SERVICE|420|11.45|08:36|Valença|09:09|Viana do Castelo|09:50|Nine|10:18|Porto - Campanhã
| |
| SERVICE|5500|11.35|15:48|Elvas|...|18:25|Entroncamento
| |
| PASSENGER|Obi-Wan
| |
| PASSENGER|Yoda
| |
| ITINERARY|0|2017-10-18|690/Évora/Pinhal Novo|180/Pinhal Novo/Tunes|5904/Tunes/Silves
| |
| </text>
| |
| <!--
| |
| Embora o interpretador de expressões tenha de assinalar problemas relativos à interpretação de expressões mal especificadas, a-->Assume-se que não existem entradas mal-formadas nestes ficheiros.<!-- (embora tenham de ser detectadas).-->
| |
| | |
| = Considerações sobre Flexibilidade e Eficiência =
| |
|
| |
| 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:
| |
| * A aplicação deve permitir a adição de novas categorias de passageiro sem alterações no código já realizado.
| |
| * A aplicação deve permitir a adição de novas procuras de serviços com baixo impacto no código já realizado (em termos do código para suportar a nova procura).
| |
| | |
| = 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 ('''mmt.app.App.main'''). As propriedades são tratadas automaticamente pelo código de apoio.
| |
| | |
| java -Dimport=test.import -Din=test.in -Dout=test.outhyp mmt.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]]
| |