|
|
(85 intermediate revisions by the same user not shown) |
Line 1: |
Line 1: |
− | {{PRJPOAvisosEN20232024}}
| + | #REDIRECT [[Programação com Objectos/Projecto de Programação com Objectos/Enunciado do Projecto de 2023-2024]] |
− | {{PRJPOMandatory20232024}}
| |
− | {{TOCright}}
| |
− | '''<font color="red">EM PREPARAÇÃO</font>'''
| |
− | | |
− | '''<font color="red">ÉPOCA NORMAL</font>'''
| |
− | | |
− | = Propriedades e funcionalidade da folha de cálculo =
| |
− | | |
− | O objectivo do projecto é desenvolver uma folha de cálculo.
| |
− | | |
− | == Endereçamento: Células, Intervalos, Gamas ==
| |
− | | |
− | O número de linhas e de colunas da folha é fixo. Os endereços (posições na folha: linha e coluna) têm início em 1 (um).
| |
− | | |
− | Uma célula é definida com base na sua posição na folha: '''CÉLULA ::= LINHA;COLUNA'''
| |
− | Exemplos: '''1;2''' (linha 1, coluna 2); ou '''23;4''' (linha 23, coluna 4).
| |
− | | |
− | Um intervalo (fechado) é definido entre duas células da mesma linha ou da mesma coluna: '''INTERVALO ::= CÉLULA:CÉLULA'''
| |
− | Exemplos: '''1;2:1;20''' (linha 1, entre as colunas 2 e 20); ou '''23;4:57;4''' (coluna 4, entre as linhas 23 e 57).
| |
− | | |
− | Utiliza-se o termo “gama” para especificar indiscriminadamente uma célula única ou um intervalo de células.
| |
− | | |
− | == Conteúdo: Literais, Referências, Funções ==
| |
− | | |
− | Por omissão, as células estão vazias (sem conteúdo). Os conteúdos admissíveis são: literais (números inteiros), referências, funções. As referências indicam-se com o símbolo “=” seguido do endereço da célula referida ([[#Endereçamento: Células, Intervalos, Gamas|Endereçamento]]). As funções indicam-se com o símbolo '''=''' ("igual"), o nome da função e a lista (possivelmente vazia) de argumentos (separados por vírgulas). Estão pré-definidas:
| |
− | | |
− | 1. Funções binárias, cujos argumentos podem ser referências a células ou valores literais: '''ADD''' (adição), '''SUB''' (subtração), '''MUL''' (multiplicação), '''DIV''' (divisão inteira). Exemplos: '''ADD(2;3,1)''', '''SUB(6;2,22;1)''', '''MUL(1,2)''', '''DIV(1,5;2)'''.
| |
− | | |
− | 2. Funções aplicadas a um intervalo de células: '''AVG''' (média com divisão inteira), '''PRD''' (produtório). Exemplos: '''AVG(1;2:1;19)''', '''PRD(2;33:5;33)'''.
| |
− | | |
− | Considera-se que não existem dependências circulares, nem directas, nem indirectas, entre uma função e as células referidas pelos seus argumentos. Funções com argumentos inválidos (e.g., referem gamas com células vazias), têm valor '''#VALUE'''.
| |
− | | |
− | == Operações Sobre Células ==
| |
− | | |
− | É possível inserir, apagar e mostrar conteúdos ([[#Conteúdo: Literais, Referências, Funções|Conteúdo]]). É ainda possível copiar conteúdos entre células.
| |
− | | |
− | == Pesquisas ==
| |
− | | |
− | É possível pesquisar o conteúdo das células sob diferentes aspectos: (i) valores resultantes de avaliação; (ii) nomes de funções.
| |
− | | |
− | = 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 nem 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 '''xxl.Spreadsheet''' 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.
| |
− | | |
− | = Requisitos de Desenho =
| |
− | | |
− | Devem ser possíveis extensões ou alterações de funcionalidade com impacto mínimo no código produzido: em particular, deve ser simples definir novas funções e novas pesquisas sobre células. O objectivo é aumentar a flexibilidade da aplicação relativamente ao suporte de novas funções. Deve ainda ser possível definir novas políticas de protecção de células.
| |
− | | |
− | A estrutura de armazenamento dos conteúdos da folha deve ser flexível, por forma a permitir a representação eficiente de folhas de diferentes dimensões. Assim, deve ser possível usar diferentes estratégias de representação do conteúdo, sem impacto no resto da aplicação. O objectivo deste requisito é optimizar o espaço ocupado em memória para guardar o conteúdo de uma folha de cálculo. Não é necessário concretizar para todas as situações, bastando ser suficientemente flexível para permitir novas implementações.
| |
− | | |
− | Uma função depende de células cujo conteúdo pode ser alterado em qualquer instante. Por forma a reduzir o custo de execução do programa sempre que uma célula é alterada, o número de vezes que cada fórmula é calculada deve ser minimizado. Este requisito deve ser considerado apenas depois de tudo estar implementado.
| |
− | | |
− | = Interaçã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 '''xxl-app'''). As mensagens não podem ser usadas no núcleo da aplicação ('''xxl-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 (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'' '''xxl.app''', '''xxl.app.---''', '''xxl.app.---''', '''xxl.app.---''', '''xxl.app.---''', '''xxl.app.---'''. 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 '''xxl-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|Menu de Edição]], [[#Gestão e consulta de dados da aplicação|Menu de Consultas]].
| |
− | | |
− | As etiquetas das opções deste menu estão definidas na classe '''xxl.app.main.Label'''. Todos os métodos correspondentes às mensagens de diálogo para este menu estão definidos na classe '''xxl.app.main.Message'''.
| |
− | | |
− | {{CVSCode|Estes comandos já estão implementados nas classes da ''package'' '''prr.app.main''' (disponível no CVS), respectivamente: '''DoCreateFile''', '''DoOpenFile''', '''DoSaveFile''', '''DoOpenMenuEdit''', '''DoOpenMenuLookup'''.}}
| |
− | | |
− | === Salvaguarda do estado actual da aplicação ===
| |
− | | |
− | Inicialmente, a aplicação não tem nenhuma folha. Nesta situação, apenas são apresentadas as opções Criar e Abrir, pois as restantes necessitam uma folha. As opções irrelevantes nesta situação devem ser omitidas.
| |
− | 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:
| |
− | | |
− | * '''Criar''' -- Permite criar de uma nova folha vazia: pedem-se as dimensões da nova folha, devendo ser utilizadas as mensagens '''Prompt.lines()''' e '''Prompt.columns()'''. Esta folha não fica associada a nenhum ficheiro (é anónima).
| |
− | * '''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.
| |
− | | |
− | Apenas existe uma folha na aplicação. Quando se abandona uma folha com modificações não guardadas (porque se cria ou abre outra), deve perguntar-se se se quer guardar a informação actual antes de a abandonar, através de '''Prompt.saveBeforeExit()''' (a resposta é obtida invocando '''readBoolean()'''). A opção “Sair” nunca guarda a folha, mesmo que existam alterações.
| |
− | | |
− | 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 ===
| |
− | | |
− | Além das operações de manipulação de ficheiros, existem ainda no menu principal as seguintes opções. Estas opções só estão disponíveis quando existir uma folha activa válida.
| |
− | | |
− | * '''Menu de Edição''' -- Abre o menu de edição.
| |
− | * '''Menu de Consultas''' -- Abre o menu de consultas (pesquisas).
| |
− | | |
− | == Menu de Edição ==
| |
− | | |
− | O menu de edição permite visualizar e alterar o conteúdo das células da folha activa. A lista completa é a seguinte: Visualizar, Inserir, Apagar, Copiar, Cortar, Colar e Visualizar cut buffer. As secções abaixo descrevem estas opções.
| |
− | | |
− | As opções deste menu estão definidas na classe calc.textui.edit.MenuEntry. Todos os métodos correspondentes às mensagens de diálogo para as acções do menu estão definidos na classe calc.textui.edit.Message.
| |
− | | |
− | === Visualizar ===
| |
− | | |
− | Permite visualizar a gama especificada ([[#Endereçamento: Células, Intervalos, Gamas|§Endereçamento]]), conforme as indicações da tabela. Se o conteúdo não for um literal, deve ser apresentado o seu valor e a sua expressão. Não deve ser apresentado qualquer conteúdo para células vazias.
| |
− | | |
− | Célula, Referências, Funções Intervalo Vertical Intervalo Horizontal
| |
− | linha;coluna|contecdo linha1;coluna|conteúdo
| |
− | linha;coluna|conteúdo linha2;coluna|conteúdo
| |
− | linha;coluna|valor=expressão linha3;coluna|conteúdo
| |
− | | |
− | === Inserir ===
| |
− | | |
− | É especificada a gama ([[#Endereçamento: Células, Intervalos, Gamas|§Endereçamento]]). É especificado o conteúdo a inserir ([[#Conteúdo: Literais, Referências, Funções|§Conteúdo]]), através da mensagem contentsRequest(). O conteúdo é inserido em todas as células da gama. Por simplicidade, não são inseridos nomes de funções inexistentes.
| |
− | | |
− | === Copiar ===
| |
− | | |
− | É especificada a gama ([[#Endereçamento: Células, Intervalos, Gamas|§Endereçamento]]) cujo conteúdo deve ser copiado para o cut buffer. Os conteúdos copiados são independentes da folha (i.e., alterações aos originais não são propagadas para o cut buffer).
| |
− | | |
− | === Apagar ===
| |
− | | |
− | É especificada a gama ([[#Endereçamento: Células, Intervalos, Gamas|§Endereçamento]]) cujo conteúdo deve ser apagado.
| |
− | | |
− | === Cortar ===
| |
− | | |
− | Esta acção corresponde à execução sequencial das acções descritas em §3.3.3 e §3.3.4.
| |
− | | |
− | === Colar ===
| |
− | | |
− | Insere o conteúdo do cut buffer na gama especificada ([[#Endereçamento: Células, Intervalos, Gamas|§Endereçamento]]). Se o cut buffer estiver vazio, não é realizada qualquer operação. Se a gama for a uma única célula, todo o cut buffer deve ser inserido a partir da célula especificada, até ser atingido o limite da folha de cálculo. Caso contrário, se a dimensão do cut buffer for diferente da da gama de destino, não insere nenhum valor.
| |
− | | |
− | === Visualizar cut buffer ===
| |
− | | |
− | Permite visualizar o conteúdo do cut buffer. O formato de apresentação é o descrito em §3.3.1.
| |
− | | |
− | {{CVSCode|Estes comandos já estão implementados nas classes da ''package'' '''prr.app.clients''' (disponível no CVS), respectivamente: '''DoShowClient''', '''DoShowAllClients''', '''DoRegisterClient''', '''DoEnableClientNotifications''', '''DoDisableClientNotifications''', '''DoShowClientPaymentsAndDebts'''.}}
| |
− | | |
− | == Menu de Consultas ==
| |
− | | |
− | Permite efectuar pesquisas sobre as células da folha activa, produzindo listas de células. As células resultantes são apresentadas pela ordem em que aparecem na tabela ([[#Visualizar|§Visualizar]]). As entradas do menu estão definidas em calc.textui.search.MenuEntry.
| |
− | | |
− | As mensagens estão definidas em calc.textui.search.Message.
| |
− | | |
− | Entrada do menu Acção
| |
− | Procurar Valor Pede-se o valor a procurar (mensagem searchValue()) e apresentam-se os resultados.
| |
− | Procurar Função Pede-se o nome da função a procurar (mensagem searchFunction()) e apresentam-se os resultados.
| |
− | | |
− | O termo de pesquisa deve ser comparado com o valor avaliado de cada célula. Assim, considerando as expressões iniciais das células indicadas de seguida, uma pesquisa pelo valor 5 encontraria as células 1;3 e 2;1.
| |
− | | |
− | 1;1|4
| |
− | 1;2|1
| |
− | 1;3|5
| |
− | 2;1|5=ADD(1;1,1;2)
| |
− | 2;2|
| |
− | 2;3|
| |
− | | |
− | Sempre que for feita uma consulta e nenhuma entidade satisfizer as condições associadas ao pedido, nada deve ser apresentado.
| |
− | | |
− | = Inicialização por Ficheiro de Dados Textuais =
| |
− | | |
− | Por omissão, quando a aplicação começa, não existe nenhuma folha activa. Além das opções descritas em [[#Manipulação de Ficheiros|§Manipulação de Ficheiros]], é possível iniciar a aplicação utilizado um ficheiro de texto especificado pela propriedade Java import (apresentada abaixo; este exemplo está presente no ficheiro test.import). Os dados textuais são apenas uma forma cómoda de inicialização e nunca são produzidos pela aplicação (nem mesmo para salvaguardar o estado para execuções futuras). Quando se especifica a propriedade, é criada uma folha activa anónima que representa o conteúdo do ficheiro indicado.
| |
− | | |
− | No processamento destes dados, assume-se que não há entradas mal formadas (células não referidas são vazias). Sugere-se a utilização do método String.split, para dividir uma cadeia de caracteres em campos.
| |
− | | |
− | As duas primeiras linhas definem o número de linhas e de colunas da folha de cálculo. As restantes linhas contêm sempre o formato linha;coluna|conteúdo (o campo conteúdo está descrito em [[#Conteúdo: Literais, Referências, Funções|§Conteúdo]]).
| |
− | | |
− | No seguinte exemplo, o conteúdo do ficheiro inicial (test.import), à esquerda, correspondente à folha apresentada à direita.
| |
− | | |
− | linhas=4
| |
− | colunas=3
| |
− | 3;3|=ADD(3;1,3;2)
| |
− | 4;1|
| |
− | 1;1|5
| |
− | 1;2|49
| |
− | 2;1|25
| |
− | 2;2|43
| |
− | 2;3|=ADD(2;2,5)
| |
− | 3;1|10
| |
− | 3;2|=1;1
| |
− | 1;3|=ADD(2,5)
| |
− | 4;3|=AVG(1;3:3;3)
| |
− | 4;2|
| |
− | | |
− | 1 2 3
| |
− | 1 5 49 =ADD(2,5)
| |
− | 2 25 43 =ADD(2;2,5)
| |
− | 3 10 =1;1 =ADD(3;1,3;2)
| |
− | 4 =AVG(1;3:3;3)
| |
− | | |
− | A codificação dos ficheiros a ler é garantidamente UTF-8.
| |
− | | |
− | 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 (método calc.textui.Calc.main). A propriedade import é acedida através de System.getProperty("import"); (ver manual da linguagem para mais informação). As outras propriedades são tratadas automaticamente pelo código de apoio.
| |
− | | |
− | java -Dimport=test.import -Din=test.in -Dout=test.outhyp calc.textui.Calc
| |
− | | |
− | 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.
| |
− | | |
− | [[category: Ensino]]
| |
− | [[category:PO]]
| |
− | [[category:Projecto de PO]]
| |
− | [[en:Object-Oriented Programming]]
| |