|
|
(92 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.
| |
− | | |
− | = 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 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.
| |
− | | |
− | 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.
| |
− | | |
− | = 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.
| |
− | | |
− | = 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 leitura e escrita devem realizar-se através do objecto ist.po.ui.Dialog.IO. As mensagens são produzidas pelos métodos das bibliotecas de suporte (po-uilib e calc-support). As mensagens não podem ser usadas no núcleo da aplicação. 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 ist.po.ui.DialogException, são lançadas pelos comandos e tratadas por ist.po.ui.Menu. Outras excepções não devem substituir as fornecidas nos casos descritos.
| |
− | | |
− | == Menu Principal ==
| |
− | | |
− | As acções deste menu permitem manipular ficheiros ([[#Manipulação de Ficheiros|§Manipulação de Ficheiros]]), editar células ([[#Menu de Edição|§Menu de Edição]]) e efectuar consultas ([[#Menu de Consultas|§Menu de Consultas]]). Os métodos para as mensagens de diálogo estão definidos em calc.textui.main.Message.
| |
− | | |
− | 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.
| |
− | | |
− | === Manipulação de Ficheiros ===
| |
− | | |
− | O estado da aplicação pode ser guardado em ficheiros, para posterior recuperação (serialização Java: java.io.Serializable).
| |
− | Na manipulação de ficheiros, devem ser tratadas as excepções associadas. A funcionalidade de cada operação é a seguinte:
| |
− | | |
− | - Criar – Permite criar de uma nova folha vazia: pedem-se as dimensões da nova folha, devendo ser utilizadas as mensagens linesRequest() e columnsRequest(). Esta folha não fica associada a nenhum ficheiro (é anónima).
| |
− | | |
− | - Abrir – Carrega uma nova folha a partir de um ficheiro previamente guardado, ficando associada a esse ficheiro. Pede-se o nome do ficheiro a abrir (openFile()): caso não exista, é apresentada a mensagem fileNotFound().
| |
− | | |
− | - Guardar – Guarda a folha no ficheiro associado. Se a folha for anónima, pede-se o nome do ficheiro a utilizar, ficando a ele associada. 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.
| |
− | | |
− | - Guardar como... – Esta opção permite associar um (novo) ficheiro à folha, guardando nele o estado da folha. Esta interacção utiliza o método saveAs(). É ignorada a associação actual a um ficheiro, mesmo que existam alterações.
| |
− | | |
− | 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 da mensagem saveBeforeExit() (a resposta é obtida invocando readBoolean()). A opção “Sair” nunca guarda a folha, mesmo que existam alterações.
| |
− | | |
− | === Outras Opções ===
| |
− | | |
− | Além das operações de manipulação de ficheiros e das opções de visualização básicas, existem ainda no menu principal as opções Menu de Edição e Menu de Consultas. Estas opções só estão disponíveis quando existir uma folha activa válida.
| |
− | | |
− | == 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.
| |
− | | |
− | == 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]]
| |