Autor Tópico: Projeto AV1  (Lida 6946 vezes)

0 Membros e 1 Visitante estão vendo este tópico.

Offline Jefferson

  • Zelador
  • Hero Member
  • *****
  • Mensagens: 1854
  • Aprovação: +0/-0
    • Ver Perfil
    • http://ryan.com.br
Projeto AV1
« Online: Maio 04, 2019, 03:22:55 pm »
Descrição do projeto publicada com a permissão do professor Anderson Silva


Citar
Locadora de Veículos

A APS Locadora de Veículos precisa de uma sistema que organize todos os carros que estão alugados e não alugados.

Sabendo que a locadora possui 20 carros em seu pátio, sendo eles divididos da seguinte forma:

  • 3 – Fiat Pálio 1.0 cor prata Totalflex – 50.000km rodados
  • 2 – Hyundai HB20 1.6 cor branco Totalflex – 40.000 km rodados;
  • 5 – Volkswagen Gol 1.0 cor preto Gasolina – 55.000 km rodados;
  • 3 – GM Camaros 3.0 cor amarelo TotalFlex – 7.000 km rodados;
  • 1 – Ford Fusion 2.0 cor preto TotalFlex – 15.000 km rodados;
  • 1 – Dodge Viper 8.3 cor azul Gasolina – 5.000 km rodados;

Cada cliente da locadora APS possui um cadastro com os seguintes itens:

  • Nome
  • Endereço
  • Telefone
  • Idade
  • RG
  • CPF
  • Carro alugado
  • Data de aluguel
  • Data de devolução

Os carros devem ter todos os atributos mencionados anteriormente no Slide 2;

Os carros devem possuir métodos para informar:

  • A quantidade de quilômetros rodados;

Os clientes, por sua vez, devem possuir métodos para informar todos os atributos apresentados no slide 3.

O Sr. Manoel, dono da Locadora APS, deseja controlar os carros que estão atualmente alugados e os carros que estão disponíveis na locadora.

Para isso crie um sistema que tenha as Classes:

  • Carro
  • Cliente

Crie também os arrays:
  • totalDeCarros;
  • carrosAlugados;
  • clientes;
  • clentesAlugando.

Crie um sistema que pergunte se o cliente quer alugar um carro:

Caso a resposta seja sim, crie um novo cliente e adicione-o a liste de clientes (no máximo 20);

Ao se cadastrar, o cliente escolhe um dos carros disponíveis (devem ser apresentados apenas os carros que estejam disponibilizados, não devem ser apresentados os carros já alugados);

No menu principal o usuário também pode escolher apresentar todos os clientes juntamente com os carros que ele está alugando.

Fim da descrição do projeto

AVISO: Meu projeto contém muito mais do que o que foi solicitado pelo professor e em alguns pontos não tem o que foi solicitado pelo mesmo, mas eu chequei com o professor se era aceitável antes de fazer a apresentação e ele concordou.

Por exemplo:
  • Eu ignorei as instruções para perguntar ao cliente se queria se cadastrar e depois alugar um carro, porque achei isso mais adequado para um quiosque. Optei por um design diferente, visando ser operado pelo funcionário da locadora;
  • Eu não uso os mesmos nomes de arrays indicados pelo professor;
  • Eu suprimi os dois arrays carrosAlugados e clientesAlugando, que tinham o objetivo de registrar as informações de aluguel e em vez disso usei atributos das classes


Menu do programa:

Citar
Digite a opcao desejada seguida de ENTER:

1 - Listar frota
2 - Listar clientes com os respectivos carros alugados - versão completa
3 - Listar clientes com os respectivos carros alugados - versão curta
4 - Adicionar cliente
5 - Editar cliente
6 - Procurar cliente pelo CPF
7 - Alugar veículo
8 - Listar veículos alugados
9 - Encerrar aluguel
0 - Sair do programa


O projeto é constituído de seis arquivos:
  • Principal.java  - A classe que contém a função Main e o menu
  • Funcoes.java - Uma classe com todas as funções de uso geral
  • Cliente.java - A classe que define o objeto Cliente com todos as funções de validação e formatação de dados
  • Carro.java - Idem para o objeto Carro
  • carros.txt - Banco de dados (do tipo flat-file database) com todos os carros da frota. Carregado ao iniciar o programa e salvo a cada alteração
  • clientes.txt - Banco de dados (também do tipo flat-file database) com clientes fictícios, usado para testar o programa. Nomes, telefones, CPF e RG (São Paulo) são válidos mas falsos. Os endereços são verdadeiros, mas não identificam nenhuma pessoa

Copiar  e colar o conteúdo dos arquivos clientes.txt e carros.txt pode não dar certo, principalmente no casso de carros.txt, que pode requerer uma linha em branco no final para que o programa inicie. Além disso, para não deixar esta página longa demais eu decidi exibir apenas uma amostra do conteúdo desses dois arquivos.  Por isso eu anexei no final do post um arquivo zip com todos os arquivos. Se quiser tentar rodar este projeto, use o conteúdo do zip e não o que está exibido aqui.

AVISO: O lugar certo para colocar carros.txt e clientes.txt depende do IDE que você está usando. No caso do Eclipse, se o nome do projeto for ProjetoAV1, os arquivos txt devem ser depositados em \eclipse-workspace\ProjetoAV1\.

Para descobrir qual o lugar correto, descomente a linha:
//System.out.println(new File(".").getAbsoluteFile());
no arquivo Principal.java.

Se ainda assim precisar de ajuda para descobrir o lugar certo no seu IDE, me pergunte isso na sala de aula.

Explicações para algumas decisões de design

  • Ler os dados de um arquivo externo: Misturar dados com código é uma prática deselegante. O professor não cobrou de ninguém nesse projeto o uso de algum tipo de banco de dados porque nesse estágio do curso ninguém é obrigado a saber como se usa um e muito menos saber distinguir práticas deselegantes de programação. Mas se você souber usar um, em um próximo projeto use pois isso certamente vai contar positivamente na sua nota. Além disso, colocar os dados em um arquivo externo permite sua fácil reutilização em outros projetos;
  • O programa já começar com diversos clientes cadastrados - Isso não foi solicitado pelo professor mas já começar automaticamente com diversos dados reais permite acelerar o teste das funções de validação e formatação, reduzindo o número de situações em que você tem que perder tempo digitando dados efêmeros; 
  • As funções AdicionarCliente() e CarregarClientes() foram desenhadas para trabalhar com um objeto "cliente" intermediário antes de salvar o cliente no array. Fiz isso porque me parece uma forma mais elegante e mais robusta de lidar com objetos.  Em vez de "abrir" o elemento no array e esperar pacientemente enquanto o usuário termina de preencher os campos usamos um objeto intermediário que faz todas as validações e que você só "aplica" no array quando estiver satisfeito. Isso possibilitou também incluir a oportunidade de cancelar o cadastro;
  • Fiz com que todo método que requeria um Scanner recebesse o Scanner de Main() como parâmetro, para evitar criar vários objetos Scanner e o problema que era gerado ao dar um .close() em um desses objetos (o Scanner em Main() parava de funcionar também);
  • Eu evito usar declarações "import" e em vez disso coloco o nome das funções externas por extenso no programa. Por exemplo,  onde eu escrevo:

          java.util.Scanner scan = new java.util.Scanner (System.in);

    Eu poderia simplesmente escrever:

          Scanner scan = new Scanner (System.in);

    Se fizesse um "import java.util.Scanner".

    Isso deixa várias linhas desnecessariamente longas, é verdade, mas eu prefiro dessa forma enquanto estou aprendendo Java porque basta olhar para o código para saber de onde danado vem as funções e é mais fácil reutilizá-las, porque você não precisa saber que "imports" são necessários.
« Última modificação: Outubro 13, 2019, 07:41:28 pm por Jefferson »
http://jefferson-ryan.blogspot.com
http://ryan.com.br

Se o que você escreve não merece sua atenção, vai merecer a atenção de quem?!

Offline Jefferson

  • Zelador
  • Hero Member
  • *****
  • Mensagens: 1854
  • Aprovação: +0/-0
    • Ver Perfil
    • http://ryan.com.br
Re:Projeto AV1
« Responder #1 Online: Maio 04, 2019, 10:17:24 pm »
Principal.java

Código: Java
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
package br.com.automalabs.estacio.projetoAV1;  public class Principal {         public static void main(String[] args){                                 Cliente clientes[] = new Cliente[Cliente.MAX_CLIENTES] ; //aloco a memória necessária                Funcoes.carregarClientes(clientes);                                     Carro carros[] = new Carro[Carro.MAX_VEICULOS] ; //aloco a memória necessária                Funcoes.carregarVeiculos(carros);                                       //DEBUG                //Retorna o local onde deveriam estar os arquivos carro.txt e cliente.txt                //System.out.println(new File(".").getAbsoluteFile());                 String opcao="";                java.util.Scanner scan = new java.util.Scanner (System.in);                do{                        System.out.println("\nDigite a opção desejada seguida de ENTER:\n");                        System.out.println("1 - Listar frota");                        System.out.println("2 - Listar clientes com os respectivos carros alugados - versão completa");                        System.out.println("3 - Listar clientes com os respectivos carros alugados - versão curta");                        System.out.println("4 - Adicionar cliente");                        System.out.println("5 - Editar cliente");                        System.out.println("6 - Procurar cliente pelo CPF");                        System.out.println("7 - Alugar veículo");                               System.out.println("8 - Listar veículos alugados");                             System.out.println("9 - Encerrar aluguel");                                                     System.out.println("0 - Sair do programa");                 String opcoesValidas="0123456789";                      opcao = scan.nextLine();                                //Se eu usar a opção "default" do switch para isso o menu vai ter                 //que ser redesenhado a cada erro                while (opcoesValidas.indexOf(opcao) == -1) {                        System.out.print("Opção inválida. As opçoes válidas são ");                        System.out.println(opcoesValidas + ". Tente novamente.");                               opcao = scan.nextLine();                }                                switch(opcao){                case "0":                                               System.out.println("Encerrado pelo usuário.");                        break;                case "1":                        Funcoes.imprimirFrota(carros, true);                        Funcoes.waitForEnter(scan, true);                        break;                case "2":                        Funcoes.imprimirClientes(clientes, carros);                        Funcoes.waitForEnter(scan, true);                        break;                case "3":                        Funcoes.imprimirClientesSimplificado(clientes, carros);                        Funcoes.waitForEnter(scan, true);                        break;                                  case "4":                        if(Funcoes.adicionarCliente(clientes, scan)) Funcoes.salvarClientes(clientes);                        Funcoes.waitForEnter(scan, true);                        break;                case "5":                        if(Funcoes.editarCliente(clientes, carros, scan)) Funcoes.salvarClientes(clientes);                        Funcoes.waitForEnter(scan, true);                        break;                  case "6":                        String resposta="";                        do {                                System.out.println("Digite o CPF:");                                resposta=scan.nextLine();                                resposta=resposta.replaceAll("\\D",""); //removo tudo o que não for numérico                        } while (resposta.equals(""));                         String cliente=Funcoes.buscarClientePeloCPF(clientes, resposta);                        if (cliente.isEmpty())System.out.println("Não há cliente cadastrado com este CPF");                        else System.out.println(cliente);                                                Funcoes.waitForEnter(scan, true);                        break;                                          case "7":                        Funcoes.alugarVeiculo(carros, clientes, scan);                        Funcoes.salvarVeiculos (carros);                        Funcoes.waitForEnter(scan, true);                        break;                  case "8":                        Funcoes.imprimirAlugados(carros, clientes);                        Funcoes.waitForEnter(scan, true);                        break;                  case "9":                        Funcoes.encerrarAluguel(carros, clientes, scan);                        Funcoes.salvarVeiculos (carros);                                                Funcoes.waitForEnter(scan, true);                        break;                   }                }while(!opcao.contentEquals("0"));                                System.out.println("Programa encerrado.");                scan.close();                                }}

Funcoes.java

Código: Java
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591
package br.com.automalabs.estacio.projetoAV1; import java.util.Scanner; public class Funcoes {                //Em vários lugares eu declaro variáveis dentro de loops por ser mais conveniente.         //Eu imaginei que poderia ser uma má prática, mas isto aqui me fez mudar de idéia:        //https://stackoverflow.com/questions/4501482/java-declaring-variables-in-for-loops                //Os métodos e atributos desta classe são declarados como static porque são chamados         // a partir de main, que é declarado como static. Isso evita o erro:        //Cannot make a static reference to the non-static method        // Para evitar isso seria necessário instanciar um objeto desta classe          // e chamar os métodos do objeto, que é a forma como operamos com Carro e Cliente        //Em outras palavras, um método static pode ser chamado sem a necessidade de criar uma instância da classe.                public static final String ARQ_VEICULOS="carros.txt";        public static final String ARQ_CLIENTES="clientes.txt";                        public static void clrscr(){                System.out.println("Se você está vendo esta mensagem, este programa está rodando");                System.out.println("no Eclipse. A rotina de apagamento de tela não funciona aqui.");            try {                if (System.getProperty("os.name").contains("Windows"))                    new ProcessBuilder("cmd", "/c", "cls").inheritIO().start().waitFor();                else                    Runtime.getRuntime().exec("clear");            } catch (java.io.IOException | InterruptedException ex) {}        }                               public static void waitForEnter(Scanner scan, boolean apagarTela) {                 System.out.println("Tecle ENTER para voltar ao menu...");                scan.nextLine();                if (apagarTela) clrscr();         }                static String getDataAtual() {                java.util.Date date = java.util.Calendar.getInstance().getTime();        java.text.DateFormat dateFormat = new java.text.SimpleDateFormat("dd/MM/yyyy hh:mm:ss");        String strDate = dateFormat.format(date);               return strDate;        }                        public static void imprimirCarroPeloIndice(Carro car[], int indice) {                 System.out.print("Carro ");                System.out.print(car[indice].getRegistroLoc()+" : ");                System.out.print(car[indice].getFabricante()+" ");                System.out.print(car[indice].getModelo()+" ");                System.out.print(car[indice].getMotor()+" ");                System.out.print(car[indice].getCor()+" ");                System.out.print(car[indice].getTipoCombustivel()+" ");                System.out.println(car[indice].getKmRodados()+"Km");                }                public static void imprimirFrota(Carro carros[], boolean todos) {            //Imprime a frota                for (int i=0; i<(Carro.getTotalCarros()); i++) {                         boolean alugado= !(carros[i].getAlugadoPor().equalsIgnoreCase(""));                                if (todos || !alugado ) {                                        imprimirCarroPeloIndice(carros, i);                                }                                        }                        }         public static void imprimirAlugados(Carro carros[], Cliente clientes[]) {                 for (int i=0; i<(Carro.getTotalCarros()); i++) {                        String alugadoPor=carros[i].getAlugadoPor();                        boolean alugado= !(alugadoPor.equalsIgnoreCase(""));                                if (alugado) {                                        imprimirCarroPeloIndice(carros, i);                                        System.out.print("Alugado para: ");                                        System.out.println(clientes[Integer.parseInt(alugadoPor)].getNome());                                        System.out.println("");                                }                                }                        }                       public static void encerrarAluguel(Carro car[], Cliente cl[], Scanner scan) {                imprimirAlugados(car, cl);                                String resposta="";                do {                        System.out.println("Digite o código do carro que deseja devolver:");                        resposta=scan.nextLine();                        resposta=resposta.replaceAll("\\D",""); //removo tudo o que não for numérico                } while (resposta.equals("")|| (Integer.parseInt(resposta)>Carro.getTotalCarros()));                                 String veiculo= resposta;                                boolean achei=false;                for (int i=0; i<(Carro.getTotalCarros()); i++) {                        String registroLoc=car[i].getRegistroLoc();                                                if (registroLoc.equalsIgnoreCase(veiculo)) {                                                                if (!(car[i].getAlugadoPor().equalsIgnoreCase(""))) {                                        do {                                                achei=true;                                                System.out.println("Qual a kilometragem atual do veículo?");                                                resposta=scan.nextLine();                                                resposta=resposta.replaceAll("\\D",""); //removo tudo o que não for numérico                                                                                                if (Integer.parseInt(resposta)< car[i].getKmRodados()) {                                                        System.out.println("Este número é menor que o anterior.");                                                        resposta="";                                                }                                        } while (resposta.equals(""));                                                                          car[i].setKmRodados(Integer.parseInt(resposta));                                        car[i].setAlugadoPor("");                                                                        }                                }                }                if (achei) {                        System.out.println("Aluguel encerrado");                }else {                        System.out.println("O código fornecido não é de um veículo atualmente alugado.");                }                        }                public static int imprimirCarroPeloRegistro(Carro car[], String registro) {                        for (int i=0; i<(Carro.getTotalCarros()); i++) {                        String registroLoc=car[i].getRegistroLoc();                                                if (registroLoc.equalsIgnoreCase(registro)) {                                imprimirCarroPeloIndice(car, i);                                return i;                                                                }                }                return -1; //carro não encontrado                        }                public static void imprimirClientes(Cliente cl[], Carro car[]) {                 for (int i=0; i<(Cliente.getTotalClientes()); i++) {                        System.out.println("Nome: " + cl[i].getNome());                        System.out.println("Endereço: "+ cl[i].getEndereco());                        System.out.println("Telefone: "+ cl[i].getTelefone());                        System.out.println("Idade: "+ cl[i].getIdade()+" anos");                        System.out.println("CPF: "+ cl[i].getCpf());                        System.out.println("RG: "+ cl[i].getRg());                                                                    for (int j=0; j<Carro.getTotalCarros(); j++) {                                                if (car[j].getAlugadoPor().equalsIgnoreCase(Integer.toString(i))) {                                        System.out.print("Alugando: ");                                     imprimirCarroPeloIndice(car,j);                                }                                                                                    }                                                    System.out.println("");                }                                       }                public static void imprimirClientesSimplificado(Cliente cl[], Carro car[]) {                 for (int i=0; i<(Cliente.getTotalClientes()); i++) {                        System.out.print( i+1+ " - " + cl[i].getNome()+", ");                        System.out.println("CPF: "+ cl[i].getCpf());                                            for (int j=0; j<Carro.getTotalCarros(); j++) {                                                        if (car[j].getAlugadoPor().equalsIgnoreCase(Integer.toString(i))) {                                        System.out.print("      Alugando: ");                                     imprimirCarroPeloIndice(car,j);                                }                                            }                                                                                           }                                       }                public static String buscarClientePeloCPF(Cliente cl[], String cpf) {                                String valFornecido=cpf.replaceAll("\\D","");                 for (int i=0; i<(Cliente.getTotalClientes()); i++) {                        String valCadastrado=cl[i].getCpf().replaceAll("\\D","");                         if (valFornecido.contentEquals(valCadastrado)) {                        String texto= Integer.toString(i+1).concat(" - ").concat(cl[i].getNome());                              return texto;                                                                         }                        }                return ""; //Se nada foi achado;        }                public static void alugarVeiculo(Carro car[], Cliente cl[], Scanner scan) {                                //TODO: Este trecho é idéntico ao de editarCliente. Incorporar em uma função                imprimirClientesSimplificado(cl, car);                                String resposta="";                do {                        System.out.println("Digite o número do cliente:");                        resposta=scan.nextLine();                        resposta=resposta.replaceAll("\\D",""); //removo tudo o que não for numérico                } while (resposta.equals(""));                                 int cliente= Integer.parseInt(resposta)-1;                //--------------------------------------------------------------------------------                                imprimirFrota(car, false); //com false eu imprimo apenas os carros disponíveis                 resposta="";                do {                        System.out.println("Digite o código do carro que deseja alugar:");                        resposta=scan.nextLine();                        resposta=resposta.replaceAll("\\D",""); //removo tudo o que não for numérico                } while (resposta.equals("")|| (Integer.parseInt(resposta)>Carro.getTotalCarros()));                                 String veiculo= resposta;                 System.out.println(cl[cliente].getNome());                              System.out.println("Você escolheu o veículo: ");                int indexVeiculo=imprimirCarroPeloRegistro(car, veiculo);                System.out.println("Confirma o aluguel deste veículo? (s,n) ");                String opcao=scan.nextLine();                if (opcao.equalsIgnoreCase("s")) {                        cl[cliente].setDataAluguel(getDataAtual());                             //TODO: usar o indice do cliente vai cria problemas quando um cliente for apagado.                         //O correto é usar um código de cliente                        car[indexVeiculo].setAlugadoPor(Integer.toString(cliente));                        System.out.println("Aluguel registrado.");                      }else System.out.println("Aluguel cancelado.");         }                public static void carregarVeiculos(Carro car[]) {                                try {                        java.io.FileReader reader = new java.io.FileReader(ARQ_VEICULOS);                    java.io.BufferedReader bufferedReader = new java.io.BufferedReader(reader);                    Carro.setTotalCarros(Integer.parseInt(bufferedReader.readLine()));                                        for (int i=0; i<Carro.getTotalCarros(); i++) {                        Carro v = new Carro();                                                String fabricante=bufferedReader.readLine();                        String modelo=bufferedReader.readLine();                        String motor=bufferedReader.readLine();                        String cor=bufferedReader.readLine();                        String tipoCombustivel=bufferedReader.readLine();                        int kmRodados=Integer.parseInt(bufferedReader.readLine());                        String alugadoPor=bufferedReader.readLine();                                                        v.setRegistroLoc(Integer.toString(i+1));                                v.setFabricante(fabricante);                                v.setModelo(modelo);                                v.setMotor(motor);                                v.setCor(cor);                                v.setTipoCombustivel(tipoCombustivel);                                v.setKmRodados(kmRodados);                                v.setAlugadoPor(alugadoPor);                                                                    car[i]=v;                                                    }                                                       reader.close();                   } catch (java.io.IOException e) {                    e.printStackTrace();                    throw new Error("Erro ao carregar os veículos do arquivo.");                   }            }                public static void carregarClientes(Cliente cl[]) {                                try {                        java.io.FileReader reader = new java.io.FileReader(ARQ_CLIENTES);                    java.io.BufferedReader bufferedReader = new java.io.BufferedReader(reader);                    //A primeira linha do arquivo armazena o número de clientes a ler                    Cliente.setTotalClientes(Integer.parseInt(bufferedReader.readLine()));                                        for (int i=0; i<Cliente.getTotalClientes(); i++) {                                                Cliente cli= new Cliente();                         String nome=bufferedReader.readLine();                        String endereco=bufferedReader.readLine();                        String telefone=bufferedReader.readLine();                        String dataNasc=bufferedReader.readLine();                        String cpf=bufferedReader.readLine();                        String rg=bufferedReader.readLine();                                 cli.setNome(nome);                                cli.setEndereco(endereco);                                cli.setTelefone(telefone);                                cli.setDataNasc(dataNasc);                                cli.setCpf(cpf);                                cli.setRg(rg);                                                                cl[i]=cli;                          }                    reader.close();                   } catch (java.io.IOException e) {                    e.printStackTrace();                    throw new Error("Erro ao carregar os clientes do arquivo.");                   }            }                        public static boolean adicionarCliente(Cliente cl[], Scanner scan) {                if (Cliente.getTotalClientes()==Cliente.MAX_CLIENTES) {                        System.out.println("Já foi atingido o número máximo de clientes: "+Cliente.MAX_CLIENTES);                        return false;                }                         Cliente cli = new Cliente();                                                                 System.out.println("Nome: ");                while(!cli.setNome(scan.nextLine())) {                        System.out.println("Nome inválido.");                        System.out.println("Nome: ");                }                               System.out.println("Endereço: ");                while(!cli.setEndereco(scan.nextLine())) {                        System.out.println("Endereço inválido.");                        System.out.println("Endereço: ");                }                                System.out.println("Telefone com DDD (exemplo: 81 987654321): ");                while(!cli.setTelefone(scan.nextLine())) {                        System.out.println("Telefone inválido.");                        System.out.println("Telefone com DDD (exemplo: 81 987654321): ");                }                                       System.out.println("Data de Nascimento (dd/mm/aaaa): ");                while(!cli.setDataNasc(scan.nextLine())) {                        System.out.println("Data inválida.");                        System.out.println("Data de Nascimento (dd/mm/aaaa): ");                }                                System.out.println("CPF: ");                String resposta= scan.nextLine();                boolean sucesso=false;                do {                        String cliente=Funcoes.buscarClientePeloCPF(cl, resposta);                        if (!cliente.isEmpty()) {                                                                System.out.print("Já existe um cliente cadastrado com este CPF: ");                                System.out.println(cliente);                                sucesso=false;                        } else sucesso=cli.setCpf(resposta);                 if (!sucesso) {                        System.out.println("CPF inválido.");                        System.out.println("CPF: ");                        resposta= scan.nextLine();                      }                }while (!sucesso);                                        System.out.println("RG: ");                while(!cli.setRg(scan.nextLine())) {                        System.out.println("RG inválido.");                        System.out.println("RG: ");                }                                                System.out.println("Confirma a inclusão deste cliente? (s,n) ");                String opcao=scan.nextLine();                if (opcao.equalsIgnoreCase("s")) {                        int indice= Cliente.getTotalClientes();                        cl[indice]=cli; //aplico o objeto inteiro na última posição livre do array                                                System.out.println("Cliente Cadastrado.");                                                Cliente.incTotalClientes();                        return true;                }else {                        System.out.println("Cadastro cancelado.");                        return false;                }        }                public static boolean editarCliente(Cliente cl[], Carro car[], Scanner scan) {                        Cliente clEditado = new Cliente();                                //TODO: esta função recebe o array car[] apenas para poder repassar para a função seguinte                //Existe um jeito de evitar isso?                imprimirClientesSimplificado(cl, car);                                String resposta="";                do {                        System.out.println("Digite o número do cliente a editar:");                        resposta=scan.nextLine();                        resposta=resposta.replaceAll("\\D",""); //removo tudo o que não for numérico                } while (resposta.equals(""));                                 int numero= Integer.parseInt(resposta)-1;                                               System.out.println("O valor atual de cada campo será exibido entre parênteses");                System.out.println("Se quiser deixar o campo inalterado basta teclar ENTER\n");                                String valorAtual= cl[numero].getNome();                System.out.println("Nome ( "+valorAtual+" ): ");                resposta= scan.nextLine();                if (resposta.isEmpty()) clEditado.setNome(valorAtual); //preservo o valor atual se o usuário respondeu com ENTER                else {                        while(!clEditado.setNome(resposta)) {                                System.out.println("Nome inválido.");                                System.out.println("Nome: ");                                resposta= scan.nextLine();                        }                }                        valorAtual= cl[numero].getEndereco();                System.out.println("Endereço: ( "+valorAtual+" ): ");                resposta= scan.nextLine();                if (resposta.isEmpty()) clEditado.setEndereco(valorAtual); //preservo o valor atual se o usuário respondeu com ENTER                else {                        while(!clEditado.setEndereco(resposta)) {                                System.out.println("Endereço inválido.");                                System.out.println("Endereço: ");                                resposta= scan.nextLine();                        }                }                                                valorAtual= cl[numero].getTelefone();                System.out.println("Telefone: ( "+valorAtual+" ): ");                resposta= scan.nextLine();                if (resposta.isEmpty()) clEditado.setTelefone(valorAtual); //preservo o valor atual se o usuário respondeu com ENTER                else {                        while(!clEditado.setTelefone(resposta)) {                                System.out.println("Telefone inválido.");                                System.out.println("Telefone com DDD (exemplo: 81 987654321): ");                                resposta= scan.nextLine();                        }                }                                                               valorAtual= cl[numero].getDataNasc();                System.out.println("Data de Nascimento (dd/mm/aaaa): ( "+valorAtual+" ): ");                resposta= scan.nextLine();                if (resposta.isEmpty()) clEditado.setDataNasc(valorAtual); //preservo o valor atual se o usuário respondeu com ENTER                else {                        while(!clEditado.setDataNasc(resposta)) {                                System.out.println("Data inválida.");                                System.out.println("Data de Nascimento (dd/mm/aaaa): ");                                resposta= scan.nextLine();                        }                }                                valorAtual= cl[numero].getCpf();                System.out.println("CPF: ( "+valorAtual+" ): ");                resposta= scan.nextLine();                if (resposta.isEmpty()) clEditado.setCpf(valorAtual); //preservo o valor atual se o usuário respondeu com ENTER                else {                        boolean sucesso=false;                        do {                                String cliente=Funcoes.buscarClientePeloCPF(cl, resposta);                                if (!cliente.isEmpty()) {                                                                                System.out.print("Já existe um cliente cadastrado com este CPF: ");                                        System.out.println(cliente);                                        sucesso=false;                                } else sucesso=clEditado.setCpf(resposta);                                                        if (!sucesso) {                                System.out.println("CPF inválido.");                                System.out.println("CPF: ");                                resposta= scan.nextLine();                              }                        }while (!sucesso);                 }                                               valorAtual= cl[numero].getRg();                System.out.println("RG: ( "+valorAtual+" ): ");                resposta= scan.nextLine();                if (resposta.isEmpty()) clEditado.setRg(valorAtual); //preservo o valor atual se o usuário respondeu com ENTER                else {                        while(!clEditado.setRg(resposta)) {                                System.out.println("RG inválido.");                                System.out.println("RG: ");                                resposta= scan.nextLine();                        }                }                                       System.out.println("Confirma as alterações feitas? (s,n) ");                String opcao=scan.nextLine();                if (opcao.equalsIgnoreCase("s")) {                         cl[numero]=clEditado; //substituo o objeto inteiro                                                 System.out.println("Alterações aplicadas.");                        return true;                }else {                        System.out.println("Alterações descartadas.");                        return false;                }        }                       /*        public static int obterNovoCodCliente(Cliente[] c) {                if (numClientesCadastrados==0) return 1;                else                {                        int codUltimoCliente= c[numClientesCadastrados-1].getCodCliente();                         return codUltimoCliente+1;                }                                        }        */        public static void salvarClientes (Cliente[] cl){                  try {        java.io.BufferedWriter outputWriter = null;          outputWriter = new java.io.BufferedWriter(new java.io.FileWriter(ARQ_CLIENTES));          outputWriter.write(Integer.toString(Cliente.getTotalClientes()));          outputWriter.newLine(); //A primeira linha registra o número de elementos          for (int i = 0; i < Cliente.getTotalClientes(); i++) {             outputWriter.write(cl[i].getNome());            outputWriter.newLine();            outputWriter.write(cl[i].getEndereco());            outputWriter.newLine();            outputWriter.write(cl[i].getTelefone());            outputWriter.newLine();            outputWriter.write(cl[i].getDataNasc());            outputWriter.newLine();            outputWriter.write(cl[i].getCpf());            outputWriter.newLine();            outputWriter.write(cl[i].getRg());            outputWriter.newLine();          }          outputWriter.flush();            outputWriter.close();             } catch (java.io.IOException e) {                    e.printStackTrace();                   }        }          public static void salvarVeiculos (Carro[] car){                  try {                java.io.BufferedWriter outputWriter = null;          outputWriter = new java.io.BufferedWriter(new java.io.FileWriter(ARQ_VEICULOS));          outputWriter.write(Integer.toString(Carro.getTotalCarros()));          outputWriter.newLine(); //A primeira linha registra o número de elementos          for (int i = 0; i < Carro.getTotalCarros(); i++) {             outputWriter.write(car[i].getFabricante());            outputWriter.newLine();            outputWriter.write(car[i].getModelo());            outputWriter.newLine();            outputWriter.write(car[i].getMotor());            outputWriter.newLine();            outputWriter.write(car[i].getCor());            outputWriter.newLine();            outputWriter.write(car[i].getTipoCombustivel());            outputWriter.newLine();            outputWriter.write(Integer.toString(car[i].getKmRodados()));            outputWriter.newLine();            outputWriter.write(car[i].getAlugadoPor());            outputWriter.newLine();          }          outputWriter.flush();            outputWriter.close();             } catch (java.io.IOException e) {                    e.printStackTrace();                   }        }}

Cliente.java

Código: Java
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
package br.com.automalabs.estacio.projetoAV1; public class Cliente {        /*adicionar qualquer atributo aqui requer alterações também em clientes.txt        e nas funções que salvam e carregam os dados do arquivo        */        //private int codCliente;               private String nome;        private String endereco;        private String telefone;        private String rg;        private String cpf;        private String dataNasc;        private String carroAlugado;        private String dataAluguel;        private String dataDevolucao;        private static int totalClientes=0;        public static final int MAX_CLIENTES=20;         /*         * Por que não usar um construtor mais elaborado, que receba os dados como parâmetros?         * Razão: Usar um contrutor mais elaborado requer que todos os dados do cliente sejam entregues de uma vez e validados também de uma vez.         * Isso tem o efeito de fazer com que o usuário só saiba de um erro após digitar e aplicar todos os dados         * Usar um contrutor simples que simplesmente inicializa todos os atributos e depois chamar os respectivos setters à medida         * que o usuário vai digitando os dados pareceu um modo mais adequado de lidar com o problema.             */        public Cliente() {                //this.codCliente=0;                this.nome="";                this.endereco="";                this.telefone="";                this.rg="";                this.cpf="";                this.dataNasc="";                this.carroAlugado="";                this.dataAluguel="";                this.dataDevolucao="";        };                  //Como armazenamos a data de nascimento, precisamos de um método para calcular a idade         public int getIdade(){                java.time.format.DateTimeFormatter dtf = java.time.format.DateTimeFormatter.ofPattern("dd/MM/yyyy");                // Locale specifies human language for translating, and cultural norms for lowercase/uppercase                //and abbreviations and such. Example: Locale.US or Locale.CANADA_FRENCH                //dtf = dtf.withLocale( putAppropriateLocaleHere );                  java.time.LocalDate birthDate = java.time.LocalDate.parse(this.dataNasc, dtf);                java.time.LocalDate dataAtual = java.time.LocalDate.now();        if ((birthDate != null) && (dataAtual != null)) {            return java.time.Period.between(birthDate, dataAtual).getYears();        } else {            return 0;        }        };                //usado para dataNasc, dataAluguel e dataDevolucao        private boolean validarData(String data){                java.text.DateFormat format = new java.text.SimpleDateFormat("dd/MM/yyyy");                 format.setLenient(false);                 try {                    format.parse(data);                } catch (java.text.ParseException e) {                     return false;                }                               return true;                        };          private boolean validarTelefone(String telefone) {         //Baseado no original para javascript:         //https://gist.github.com/jonathangoncalves/7bdec924e9bd2bdf353d6b7520820b62             //retira todos os caracteres não-numéricos (incluindo espaço,tab, etc)    telefone = telefone.replaceAll("\\D","");        //verifica se tem a qtde de numeros correta    if (!(telefone.length() >= 10 && telefone.length() <= 11)) return false;     //Se tiver 11 caracteres, verificar se começa com 9 o celular    if (telefone.length() == 11 && Integer.parseInt(telefone.substring(2, 3)) != 9) return false;     //verifica se o numero foi digitado com todos os dígitos iguais    //TODO: criar função e chamar também na validação de CPF    java.util.regex.Pattern p = java.util.regex.Pattern.compile(telefone.charAt(0)+"{"+telefone.length()+"}");    java.util.regex.Matcher m = p.matcher(telefone);    if(m.find()) return false;        //DDDs validos    Integer[] codigosDDD = {        11, 12, 13, 14, 15, 16, 17, 18, 19, 21, 22, 24, 27, 28, 31, 32, 33, 34,        35, 37, 38, 41, 42, 43, 44, 45, 46, 47, 48, 49, 51, 53, 54, 55, 61, 62,        64, 63, 65, 66, 67, 68, 69, 71, 73, 74, 75, 77, 79, 81, 82, 83, 84, 85,        86, 87, 88, 89, 91, 92, 93, 94, 95, 96, 97, 98, 99};    //verifica se o DDD é valido (se é um dos códigos no array acima)    if ( java.util.Arrays.asList(codigosDDD).indexOf(Integer.parseInt(telefone.substring(0, 2))) == -1) return false;        //Se o número só tiver dez digitos não é um celular e por isso o número logo após o DDD deve ser 2, 3, 4, 5 ou 7      if (telefone.length() == 10 &&  "23457".indexOf(telefone.substring(2, 3)) == -1) return false;     //se passar por todas as validações acima, então está tudo certo    return true;}  private String formatarNumero(String tipo, String numero) {     numero=numero.replaceAll("\\D", ""); //Removo todos os caracteres não-numéricos    String mascara="";        if (tipo.equalsIgnoreCase("telefone")) {                //Neste ponto o telefone ou tem 11 digitos (celulares) ou 10 digitos (fixos)                mascara= "(##) #####-####"; //Celulares                if (numero.length()==10) mascara="(##) ####-####"; //Telefones fixos    }    if (tipo.equalsIgnoreCase("cpf")) {                mascara="###.###.###-##";      }               try {                javax.swing.text.MaskFormatter formatadorNumero = new javax.swing.text.MaskFormatter(mascara);                javax.swing.JFormattedTextField txtNumero = new javax.swing.JFormattedTextField(formatadorNumero);                txtNumero.setText(numero);                return txtNumero.getText();        } catch (java.text.ParseException e) {                e.printStackTrace();                return "";        }          }  /*         public int getCodCliente(){                return this.codCliente;        };                public boolean setCodCliente(int numero){                                if (numero==0) {                        return false;                }                this.codCliente=numero;                return true;                            };        */            public String getNome(){                return this.nome;        };                public boolean setNome(String nome){                                if (nome.equals("")) {                        return false;                }                this.nome=nome;                return true;                            };              public String getEndereco(){                return this.endereco;        };                public boolean setEndereco(String endereco){                                if (endereco.equals("")) {                        return false;                }                this.endereco=endereco;                return true;            };                public String getTelefone(){                return this.telefone;        };                public boolean setTelefone(String telefone){                //Estou considerando que neste sistema o telefone não seja obrigatório            if (telefone.contentEquals("")) return true;                            if (validarTelefone(telefone)) {                        this.telefone=formatarNumero("telefone", telefone);                        return true;                }                 return false;                                                   };              public String getRg(){                return this.rg;        };                public boolean setRg(String rg){                //Checar o RG adequadamente requer solicitar também o órgão expedidor                //e conhecer as regras de validação desse órgão                                if (rg.equals("")) {                        return false;                }                this.rg=rg;                return true;                            };                               public String getDataNasc(){                return this.dataNasc;        };                public boolean setDataNasc(String dataNasc){                        if (validarData(dataNasc)) {                        this.dataNasc=dataNasc;                        return true;                }                 return false;                        };                        public static int getTotalClientes(){                return totalClientes;        };                public static void setTotalClientes(int num){                totalClientes=num;        };                public static void incTotalClientes(){                totalClientes++;                        };                public String getCarroAlugado() {                return this.carroAlugado;        }                public void setCarroAlugado(String carroAlugado) {                this.carroAlugado=carroAlugado;                }                public String getDataAluguel() {                return this.dataAluguel;        }                public boolean setDataAluguel(String dataAluguel) {                                if (validarData(dataAluguel)) {                        this.dataAluguel=dataAluguel;                        return true;                }                 return false;                }         public String getDataDevolucao() {                return this.dataDevolucao;        }                public boolean setDataDevolucao(String dataDevolucao) {                                if (validarData(dataDevolucao)) {                        this.dataDevolucao=dataDevolucao;                        return true;                }                 return false;            }                       //Usado por isValidCPF().        //Infelizmente usar "nested methods" em Java parece ser extraordinarimente complexo        private int calcularDigito(String str) {                int soma = 0;                for(int indice = str.length()-1, digito; indice >= 0; indice--) {                        digito = Character.getNumericValue(str.charAt(indice));                        int valorPeso = str.length()+1 - indice;                        soma += digito*valorPeso;                }                soma = 11 - soma % 11;                return soma > 9 ? 0 : soma;        }    //usado por setCpf()     private boolean isValidCPF(String cpf) {           cpf=cpf.replaceAll("\\D","");           if ((cpf==null) || (cpf.length()!=11) ||            cpf.equals("00000000000") || cpf.equals("11111111111") ||            cpf.equals("22222222222") || cpf.equals("33333333333") ||            cpf.equals("44444444444") || cpf.equals("55555555555") ||            cpf.equals("66666666666") || cpf.equals("77777777777") ||            cpf.equals("88888888888") || cpf.equals("99999999999")) return false;                Integer digito1 = calcularDigito(cpf.substring(0,9));               Integer digito2 = calcularDigito(cpf.substring(0,9) + digito1);               return cpf.equals(cpf.substring(0,9) + digito1.toString() + digito2.toString());            }         public boolean setCpf(String cpf){                if(isValidCPF(cpf)) {                        this.cpf = formatarNumero("cpf", cpf);                        return true;                } else {                        return false;                }        }                       public String getCpf(){                return this.cpf;        };}

Carro.java

Código: Java
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
package br.com.automalabs.estacio.projetoAV1; public class Carro {        /*adicionar qualquer atributo aqui requer alterações também em carros.txt          e nas funções que salvam e carregam os dados do arquivo        */        private String registroLoc;        private String fabricante;        private String modelo;        private String cor;        private String motor;        private String tipoCombustivel;        private int kmRodados;        private String alugadoPor;         private static int totalCarros=0;        public static final int MAX_VEICULOS=30;             Carro(){                this.fabricante="";                this.modelo="";                         this.cor="";                this.motor="";                this.tipoCombustivel="";                this.kmRodados=0;                this.alugadoPor="";    }        public String getAlugadoPor() {                return this.alugadoPor;        }               public String getRegistroLoc() {                return this.registroLoc;         }               public String getFabricante() {                return this.fabricante;         }        public String getModelo() {                return this.modelo;         }        public String getTipoCombustivel() {                return this.tipoCombustivel;        }                public String getMotor() {                return this.motor;        }                public String getCor() {                return this.cor;        }                public int getKmRodados() {                return this.kmRodados;        }                       public void setCor(String cor) {                this.cor=cor;        }                public void setAlugadoPor(String cliente) {                this.alugadoPor=cliente;        }                public void setRegistroLoc(String registroLoc) {                this.registroLoc=registroLoc;        }               public void setFabricante(String fabricante) {                this.fabricante=fabricante;        }        public void setModelo(String modelo) {                this.modelo=modelo;        }        public void setMotor(String motor) {                this.motor=motor;        }        public void setTipoCombustivel(String tipoCombustivel) {                this.tipoCombustivel=tipoCombustivel;        }               public void setKmRodados(int kmRodados) {                this.kmRodados=kmRodados;        }                public static int getTotalCarros(){                return totalCarros;        };                public static void setTotalCarros(int num){                totalCarros=num;        };                public static void incTotalCarros(){                totalCarros++;                        };}

carros.txt (amostra - arquivo completo no ZIP anexo)

A linha em branco entre cada registro não é um separador - é o campo reservado para a informação de aluguel, se houver.

Código: [Selecionar]
20
Fiat
Palio
1.0
prata
Totalflex
50000

Fiat
Palio
1.0
prata
Totalflex
50000

Fiat
Palio
1.0
prata
Totalflex
50000

Hyundai
HB20
1.6
branco
Totalflex
40000

Hyundai
HB20
1.6
branco
Totalflex
40000

VolksWagen
Gol
1.0
preto
Gasolina
55000


clientes.txt  (amostra - arquivo completo no ZIP anexo)

Código: [Selecionar]
16
Ruan Luís Márcio Araújo
Rua Pedro Scripe, São Marcos, São José dos Pinhais - Paraná
(61) 3739-8145
10/05/1971
987.479.600-60
26.678.046-5
Gael Renan Antonio Fernandes
Rua Lazaro de Paula Victor, Vila Áurea Mendes Gimenes, Sertãozinho - São Paulo
(61) 99615-1632
10/12/1930
056.429.140-49
22.220.238-5
Thomas Otávio Martin Ramos
Rua Santo Antônio, Parque São Sebastião, Luziânia - Goiás
(79) 2872-3576
10/12/1971
773.154.740-05
37.003.116-7
Ryan Anderson Ricardo Silva
Vila Manuel Padilha, Tauape, Fortaleza - Ceará
(79) 98502-7218
23/05/1980
958.303.610-27
48.732.895-4
« Última modificação: Maio 04, 2019, 11:47:01 pm por Jefferson »
http://jefferson-ryan.blogspot.com
http://ryan.com.br

Se o que você escreve não merece sua atenção, vai merecer a atenção de quem?!

FORUM.RYAN.COM.BR

Re:Projeto AV1
« Responder #1 Online: Maio 04, 2019, 10:17:24 pm »

Offline Jefferson

  • Zelador
  • Hero Member
  • *****
  • Mensagens: 1854
  • Aprovação: +0/-0
    • Ver Perfil
    • http://ryan.com.br
Re:Projeto AV1
« Responder #2 Online: Maio 05, 2019, 01:37:14 am »
Nova versão:

  • Comecei a implementar exception handling.
  • Agora se o programa não conseguir ler o número de clientes ou carros esperado do arquivo, tenta continuar assim mesmo.
  • Agora totalCarros e totalClientes são definidos inicialmente pelo número de registros efetivamente lidos de cada arquivo e não do número lido no cabeçalho
  • Agora se não conseguir achar o arquivo carros.txt aborta execução. 
  • Agora se não conseguir achar o arquivo clientes.txt, começa do zero, exibindo apenas os itens de menu adequados, mas informa sobre o problema.
        Problema a resolver: como o arquivo carros.txt agora pode conter informações de aluguel para clientes que não mais existem isso precisa ser detectado e removido se for o  caso (perguntar ao usuário?)
  • Mudei a função editarCliente para permitir o cancelamento antes mesmo de começar a editar. 
 
« Última modificação: Maio 05, 2019, 12:31:21 pm por Jefferson »
http://jefferson-ryan.blogspot.com
http://ryan.com.br

Se o que você escreve não merece sua atenção, vai merecer a atenção de quem?!

Offline Jefferson

  • Zelador
  • Hero Member
  • *****
  • Mensagens: 1854
  • Aprovação: +0/-0
    • Ver Perfil
    • http://ryan.com.br
Re:Projeto AV1
« Responder #3 Online: Maio 05, 2019, 02:53:08 pm »
Nova versão:

  • Corrigi um bug introduzido na versão anterior que fazia o programa esperar por um ENTER antes mesmo de exibir o menu (Funcoes.waitForEnter(scan, true); no lugar errado)
  • alugarVeiculo() e encerrarAluguel() agora retornam boolean e as chamadas no menu foram alteradas de acordo
  • Seção de codigo que era similar em alugarVeiculo() e editarCliente() foi colocada em uma função obterNumCLiente(), que recebeu melhorias
« Última modificação: Maio 05, 2019, 04:04:45 pm por Jefferson »
http://jefferson-ryan.blogspot.com
http://ryan.com.br

Se o que você escreve não merece sua atenção, vai merecer a atenção de quem?!

FORUM.RYAN.COM.BR

Re:Projeto AV1
« Responder #3 Online: Maio 05, 2019, 02:53:08 pm »