diff --git a/1ano/fp/avaliacao/apx1/apx1.py b/1ano/fp/avaliacao/apx1/apx1.py new file mode 100755 index 0000000..473574f --- /dev/null +++ b/1ano/fp/avaliacao/apx1/apx1.py @@ -0,0 +1,57 @@ +def isLeapYear(year): + return year % 400 == 0 if year % 100 == 0 else year % 4 == 0 + + +def monthDays(year, month): + assert month > 0 + + MONTHDAYS = (0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31) + days = MONTHDAYS[month] + + return days + 1 if (isLeapYear(year) and month == 2) else days + + +def nextDay(year, month, day): + if not dateIsValid(year, month, day): return + + # Verifica se é o último dia do ano + if (month, day) == (12, 31): + year += 1 + month = 1 + day = 1 + + # Verifica se é o último dia do mês + elif (monthDays(year, month) == day): + month += 1 + day = 1 + + # Dia comum + else: + day += 1 + + return year, month, day + + +def dateIsValid(year, month, day): + return False if (month > 12 or month <= 0) or (day > monthDays(year, month) or day <= 0) else True + + +def previousDay(year, month, day): + if not dateIsValid(year, month, day): return + + # Primeiro dia do ano + if (month, day) == (1, 1): + year -= 1 + month = 12 + day = 31 + + # Primeiro dia do mês (sem ser janeiro) + elif day == 1: + day = monthDays(year, month - 1) + month -= 1 + + # Dia comum + else: + day -= 1 + + return year, month, day \ No newline at end of file diff --git a/1ano/fp/avaliacao/apx2/apx2.pdf b/1ano/fp/avaliacao/apx2/apx2.pdf new file mode 100644 index 0000000..fa6d425 Binary files /dev/null and b/1ano/fp/avaliacao/apx2/apx2.pdf differ diff --git a/1ano/fp/avaliacao/apx2/produtos.txt b/1ano/fp/avaliacao/apx2/produtos.txt new file mode 100644 index 0000000..90e251b --- /dev/null +++ b/1ano/fp/avaliacao/apx2/produtos.txt @@ -0,0 +1,26 @@ +CODIGO;NOME;SECCAO;PRECO-BASE;TAXA +p1;Ketchup;Mercearia Salgado;1.59;23% +p2;Atum;Mercearia Salgado;3.38;6% +p3;Cogumelos;Mercearia Salgado;1.98;23% +p4;Bolachas Cacau;Mercearia Doce;1.39;23% +p5;Cerelac;Mercearia Doce;5.65;6% +p6;Heineken 12x25CL;Bebidas;8.99;23% +p7;Gel Banho;Higiene;5.99;23% +p8;Lencos de Bolso;Limpeza;1.59;23% +p9;Jardineira;Congelados;1.99;6% +p10;Leite 6x1L;Lacticinios;4.92;6% +p11;Natas;Lacticinios;0.79;6% +p12;Ovos;Lacticinios;0.94;6% +p13;Espadarte Posta;Peixaria;6.49;6% +p14;Queijo;Charcutaria;3.89;6% +p15;Laranjas;Frutas e Legumes;1.449;6% +p16;Ameixa Seca;Frutas e Legumes;2.00;6% +p17;Tabuleiro;Casa;7.00;23% +p18;Batatas;Frutas e Legumes;17.0;6% +p19;Limpa Vidros;Limpeza;3.69;23% +p20;Oregaos;Mercearia Salgado;1.42;6% +p21;Bolachas Maria;Mercearia Doce;2.39;23% +p22;Pedras Salgadas;Bebidas;2.46;13% +p23;Detergente Roupa;Limpeza;12.99;23% +p24;Pao Aveia;Padaria;1.99;6% +p25;Iogurte Grego;Lacticinios;2.59;6% diff --git a/1ano/fp/avaliacao/apx2/produtos1.txt b/1ano/fp/avaliacao/apx2/produtos1.txt new file mode 100644 index 0000000..e940f7e --- /dev/null +++ b/1ano/fp/avaliacao/apx2/produtos1.txt @@ -0,0 +1,6 @@ +CODIGO;NOME;SECCAO;PRECO-BASE;TAXA +q1;Televisor 43pol;Tecnologia;300.0;23% +q2;Computador i7;Tecnologia;500.0;23% +q3;Frigorifico;Eletrodomesticos;400.0;23% +q4;Forno microondas;Eletrodomesticos;60.0;23% +q5;Tinteiro impressora;Consumiveis;10.0;13% diff --git a/1ano/fp/avaliacao/apx2/shop.py b/1ano/fp/avaliacao/apx2/shop.py new file mode 100644 index 0000000..7f42456 --- /dev/null +++ b/1ano/fp/avaliacao/apx2/shop.py @@ -0,0 +1,124 @@ +# Pode correr o programa sem argumentos: +# python3 shop +# ou passando outros ficheiros de produtos como argumento: +# python3 shop produtos1.txt ... + +def loadDataBase(fname, produtos): + """Lê dados do ficheiro fname e atualiza/acrescenta a informação num + dicionário de produtos com o formato {código: (nome, secção, preço, iva), ...}. + """ + with open(fname, 'r') as f: # Abre o ficheiro em modo de leitura + productsFileContent = f.read() # Cria uma string com o conteudo do ficheiro + + for product in productsFileContent.split('\n')[1:]: # Divide a string 'productsFileContent' numa lista com cada produto + productComponents = product.split(';') # Divide as componentes do produto (código, nome, secção, preço, iva) + + if len(productComponents) != 5: + continue + + produtos.update({productComponents[0]: ( # Atualiza a entrada de uma determinada chave (código) + productComponents[1], # Nome + productComponents[2], # Secção + float(productComponents[3]), # Preço + float(productComponents[4].strip('%')) / 100 # IVA + )}) + + +def registaCompra(produtos): + """Lê códigos de produtos (ou códigos e quantidades), + mostra nome, quantidade e preço final de cada um, + e devolve dicionário com {codigo: quantidade, ...} + """ + compra = {"totals": [0, 0, 0]} # Inicia o dicionário da compra com os totais da mesma: [total bruto, total iva, total liquido] + userInput = input('Code? ') + while userInput != "": + try: + code, amount = userInput.split(' ') # Divide o input do utilizador no código e na quantia + except ValueError: + code, amount = userInput, 1 # No caso de não ser introduzida quantia, então ela fica 1 + + # Caso a segunda parcela da entrada não seja um número, é pedido ao utilizador para introduzir o código de novo + try: + amount = int(amount) + except ValueError: + userInput = input('Code? ') + continue + + if code in produtos: + if code not in compra: # Se o produto ainda não estiver na lista é adicionado à mesma + compra[code] = 0 + + compra[code] += amount # Adiciona ao dicionário da compra a quantidade comprada do produto + noIvaPrice = produtos[code][2] * amount # Obtém o preço (sem iva) do determinado produto + compra["totals"][0] += noIvaPrice # Adiciona o preço sem iva ao total bruto + compra["totals"][1] += noIvaPrice * produtos[code][3] # Adiciona o valor do iva ao total iva + print(f"{produtos[code][0]} {amount} {noIvaPrice * (1+produtos[code][3]):.2f}") + + userInput = input('Code? ') + + compra["totals"][2] += compra["totals"][0] + compra["totals"][1] # Calcula o total liquido da compra + return compra # Devolve a lista + + +def fatura(produtos, compra): + """Imprime a fatura de uma dada compra.""" + + # Obtém a lista de secções presentes na compra (por ordem alfabética) + sections = sorted(list({section for section in [product[1] for code, product in produtos.items() if code in compra]})) + + # Itera as secções para apresentar os produtos ordenados por secção + for section in sections: + print(section) # Mostra a secção + + # Obtém a lista de codigos usados na compra presentes na secção atual + sectionProductsCodes = sorted([code for code in produtos if produtos[code][1] == section and code in compra]) + + # Itera os códigos para apresentar as informações de cada produto + for code in sectionProductsCodes: + print(f"{compra[code]:>4} {produtos[code][0]:<31}({int(produtos[code][3]*100):>2}%){round(compra[code]*produtos[code][2]*(1+produtos[code][3]), 2):>11}") + + # Apresenta os totais da compra + print(f"""{'Total Bruto:':>41}{round(compra["totals"][0], 2):>11} +{'Total IVA:':>41}{round(compra["totals"][1], 2):>11} +{'Total Liquido:':>41}{round(compra["totals"][2], 2):>11}""") + + +def main(args): + # produtos guarda a informação da base de dados numa forma conveniente. + produtos = {'p1': ('Ketchup.', 'Mercearia Salgado', 1.59, 0.23)} + # Carregar base de dados principal + loadDataBase("produtos.txt", produtos) + # Juntar bases de dados opcionais (Não altere) + for arg in args: + loadDataBase(arg, produtos) + + # Use este código para mostrar o menu e ler a opção repetidamente + MENU = "(C)ompra (F)atura (S)air ? " + compras = {} + repetir = True + while repetir: + # Utilizador introduz a opção com uma letra minúscula ou maiúscula + op = input(MENU).upper() + # Processar opção + if op == "C": + # Esta opção regista os produtos de uma compra + compras[len(compras)+1] = registaCompra(produtos) + + elif op == "F": + # Esta opção apresenta a fatura de uma compra + try: + numCompra = int(input("Numero compra? ")) + fatura(produtos, compras[numCompra]) + except: + continue + + elif op == "S": + repetir = False + + print("Obrigado!") + + +# Não altere este código / Do not change this code +import sys +if __name__ == "__main__": + main(sys.argv[1:])