Ir ao conteúdo
  • Cadastre-se

TwistedSoul

Membro Pleno
  • Posts

    161
  • Cadastrado em

  • Última visita

Tudo que TwistedSoul postou

  1. Já tentou usar um sniffer de porta serial para capturar o que o Hercules envia ao projetor? Eu imagino que ele deva repassar diretamente o valor que você digitou em caso de Hexa e, em casos onde ele possui uma pre-definição onde você apenas envia um código, ele manda o comando correto para a porta. É uma alternativa mais simples. Claro, eu posso estar completamente equivocado como o Hercules funciona, mas não custa tentar.
  2. De nada, mas mesmo assim te recomendo instalar uma versão mais nova de JDK (o Java 6 é bem velhinho) e a nova versão da IDE. Os projeto são retrocompatíveis e vão abrir sem problemas. Se por um acaso você está trabalhando em um software desenvolvido para Java 6 e que deve continuar assim, apenas altere nas opções do projeto que ele deve ser compilado em Java 6 e não em Java 8.
  3. Andressa, esse seu problema é bem complicado. Primeiro porque é necessário saber se o respectivo projetor aceita comandos direto via porta serial e quais seriam esses comandos. Sem um manual de desenvolvimento para o projetor fica impossível saber os comandos que ele necessita. Outra coisa é que talvez seja necessário utilizar alguma .dll (no Windows) ou algum .so (no Linux) para fazer a comunicação. Nesse caso, porém, também precisa da documentação do fabricante do projetor. Se descobrir como esse Hercules executa os envios das requisições com os respectivos códigos, será mais simples de fazer, mas com certeza não é algo trivial. Fazer Java conversar com hardware não é simples, ainda mais quando queremos operar periféricos. Qual marca e modelo do projetor?
  4. Alguma particularidade em especial para usar essa versão antiga? Já experimentou a 8.2? Se você já tinha um outro JDK instalado, experimente alterar o netbeans.conf que fica em C:\Program Files\NetBeans 8.2\etc (no seu caso será NetBeans 7.2) Procure com uma linha com algo semelhante a netbeans jdkhome="C:\Program Files\Java\jdk1.8.0_121" Altere o caminho da pasta onde está instalado o JDK que deve funcionar. No seu caso: jdkhome="C:\Program Files\Java\jdk1.8.0_111"
  5. A lógica dele é bem simples. Crie um objeto para guardar as informações solicitadas Faça um loop perguntando se o usuário deseja cadastrar outro candidato Em caso positivo, mostre um formulário com os campos para resposta. Ao concluir, atribua os valores informados aos campos do objeto e armazene esse objeto em um ArrayList Repita o processo acima até o usuário decidir que não quer calcular mais nada Interrompa o loop quando o usuário terminar, itere pela lista e comece a calcular/acumular as informações em um objeto (ou diversas variáveis globais nesse caso) para exibir os resultados em tela Se você mostrar parte do código feito fica mais simples de te auxiliar.
  6. Bom dia galera. Obrigado pelas dicas de todos. Acho que depois dessa o tópico pode ser fechado. Resolvi pegar um i5-7600 mesmo. Ao invés de 16GB de RAM, coloquei "apenas" 8GB, dei uma maneirada em alguns componentes e peguei uma GTX 1070 da Galax. No total, acabei gastando R$ 800,00 a menos (não tinha como gastar nenhum real a mais do que configurei) e mesmo assim peguei o equipamento que desejava. Por causa das dicas acabei pegando componentes de qualidade mas que me ofereceriam aquilo que eu realmente vou utilizar e nada de "frufrus" que estariam lá apenas pra dizer que existem. Um abraço a todos pela ajuda.
  7. Ahhhhh... data e hora com Java. Bem-vindo ao inferno na Terra. Bom, vamos lá. Primeiro, é que o padrão de uma data ou hora deve SEMPRE seguir um determinado padrão de escrita senão o Parser default não funciona. No seu caso, é simples. Leia o valor digitado como String, e não como float ou integer. Depois de ter o valor lido, você pode criar um vetor dando um split na sua String usando o caracter . (ponto) para aplicar o split. No exemplo que você deu acima, ao dar um split na String 14.5, vai gerar um vetor com os valores [14][5]. Pegue a primeira posição do vetor, transforme horas em minutos e depois some com os minutos da segunda posição do vetor e terá seu resultado. String[] horas = valorDigitado.split(".");
  8. Cara, desculpe ser chato mas você está fazendo um curso de engenharia de software. Você precisa realmente se dedicar e seguir exemplos de livros e vídeos pra aprender o básico da linguagem. O seu curso daí pra frente só tende a "piorar" e sem saber o básico fica complicado avançar. Se você der uma passadinha rápida pelo Youtube e procurar por "Java para iniciantes", vai simplesmente CHOVER vídeo aulas, tutoriais e guias. Tudo que você aprendeu em algoritmos agora é posto em prática usando sintaxe e semântica de uma linguagem real. Como o @Black Fox disse, o método mais simples é fazer um fluxograma/algoritmo no papel para que você possa visualizar as etapas que precisa programar. Os exercícios são bem básicos e simples de fazer. Posso te garantir isso. Dei uma lida por cima e eles exigem o conhecimento básico da linguagem. Se você der uma pesquisada e se dedicar um pouco, os 3-4 primeiros exercícios já te dão todo o norte para fazer o restante dos exercícios com algumas modificações no código. Cara, não tenha medo de errar. Tenta fazer, pelo menos. Deu errado? Posta aqui o código que a gente te ajuda. Ninguém nasce sabendo mas a iniciativa tem que vir de quem está aprendendo. Abraço.
  9. As ordens. Precisando novamente, só perguntar. Boa sorte no desenvolvimento.
  10. Cara, siga a seguinte lógica que o código é bem simples de fazer. O problema aqui é apenas a lógica de estruturação das suas chamadas. - Mostrar menu com as opções - Usuário escolhe a opção de remover usuário - Perguntar ao usuário o nome do funcionário a ser removido (através de um JOptionPane, por exemplo) - Capturar a resposta do usuário e iterar sobre o array, buscando funcionário que tenha o nome informado - Ao achar o funcionário, remover o mesmo do array - Depois disso, chame um método que itere sobre o array e mostre em tela os funcionário cadastrados PS.: uma ideia boa seria, ao escolher a opção de remover funcionários, antes de perguntar o nome do mesmo, imprimir em tela a lista de funcionários para que o usuário saiba o que digitar no próximo passo Eu poderia te dar o código do programa inteiro funcionando, mas daí você realmente não aprenderia. Esqueletos e pseudo-códigos ajudam bastante com isso. Você apenas tem que ter a boa vontade e a persistência de alterar o seu código ou até mesmo refaze-lo por completo até aprender. Mas, vou te dar uma dica que vale ouro nessas horas. Faça seu programa do zero novamente. Ignore o que seu professor pediu e apenas monte um sistema de menu, como o que eu te passei antes. Aquele código funciona normalmente e consegue cobrir todos os passos que você precisa. Depois disso funcionando e você entendendo como ele funciona, altere o código. Não exiba determinados menus caso seu vetor não tenha sido inicializado com um tamanho pre-definido. Peça ao usuário digitar o tamanho do array, inicialize ele e depois volte ao menu, apresentando todas as opções já que seu vetor agora tem um tamanho (mas vazio). Depois disso, implemente o método de adicionar funcionário. Coloque um contador de quantos funcionários tem cadastrados ou consulte o vetor para não deixar o usuário clicar em cadastrar pela quinta vez quando seu vetor tem apenas um tamanho igual a 4. Faça cada uma das coisas funcionar de forma independente. No final das coisas, você vai perceber que nenhuma das suas funções de adicionar, remover, etc.. depende das outras. Todas elas dependem única e exclusivamente do seu vetor e a única coisa que elas vão ter em comum é iterar e alterar essa estrutura de dados.
  11. Então gente, desenterrando o tópico... Finalmente vão liberar a grana do seguro. Estava esperançoso que com a demora começasse a aparecer no mercado mobos para Ryzen, mas infelizmente o que ocorre é só piada de mal gosto. Lojas vendendo processadores, sempre com estoque e a disposição mas... sem placa-mãe. Na verdade até existem mobos, as Aorus, mas são placas ridiculamente caras com recursos que 99% dos mortais jamais vão utilizar. Então, pensando em ter mais longevidade no kit atual, pensei em substituir o i5 7600 pelo i7 7700 e a RX480 por uma GTX1070 para não ter que encostar a mão nesse computador pelos próximos 4 anos pelo menos. Eu adoraria ter um kit AMD de cabo a rabo, mas AMD aqui no Brasil está complicado, vendendo carro (Ryzen) sem motor (mobo). Eu sei que a RX480 é uma tremenda GPU, mas ela só vai começar a brilhar quando DX12/Vulkan forem populares, ou seja, vai demorar. Nesse caso, eu pensei em partir pra força bruta mesmo e infelizmente fazer um novo kit Intel + NVidia. E aí.. alguém, sabe onde comprar mobos AM4 por valores dentro da realidade (e com nota, super importante isso) ou meu achismo com processador + gpu faz sentido? Abraço e obrigado.
  12. O erro ocorre por causa de como o seu código está estruturado. Ele precisa mudar consideravelmente para você executar dessa forma. Por exemplo: Você precisa criar um método na sua model de funcionário que faça o cadastro. No caso, esse método deve instanciar novo objeto Funcionario(), setar as variáveis dele com os valores informados em tela pelo usuário, inserir o objeto criado na sua lista de funcionários e simplesmente encerrar o método. //Na sua classe principal, existe uma lista com os funcionarios List<Funcionario> listFunc = new ArrayList<>(); //Execute o exemplo que te passei anteriormente. String resposta = ""; do { resposta = JOptionPane.showInputDialog(null, "1. Cadastrar\n2. Excluir\n3. Mostrar funcionarios cadastrados\n4. Mostrar folha de pagamento\n0. Fim\n\nDigite uma Opcao"); switch (resposta) { case "1": listFunc.add(asus.cadastrarFuncionario()); break; case "2": // asus.removerRegistro(resposta, quant); break; case "3": // asus.todosFuncionarios(quant); break; case "4": // asus.folhaDePagamento(quant); break; } } while (!resposta.equals("0")); Em asus.cadastrarFuncionario(), você faz a leitura dos inputs do usuário, seta os valores em um objeto do tipo Funcionario e retorna esse objeto no método para ser inserido na sua lista. Você não precisa passar a quantidade de usuários a ser cadastrados como parâmetro. Como você tem um menu, o usuário pode escolher quantos ele deseja cadastrar, exibir folha, cadastrar de novo e depois sair. Faça métodos específicos para cada função a ser realizada e não tudo em um único método com chamadas lineares.
  13. É bem mais simples do que você imagina. Faça um loop do while com o menu e fique repetindo até o usuário escolher sair String resposta = ""; do { resposta = JOptionPane.showInputDialog(null, "1. Cadastrar\n2. Excluir\n3. Mostrar funcionarios cadastrados\n4. Mostrar folha de pagamento\n0. Fim\n\nDigite uma Opcao"); switch (resposta) { case "1": //método de cadastro; break; case "2": //método de exclusão; break; case "3": //método mostra funcionários; break; case "4": //método mostra forma pagto break; } } while (!resposta.equals("0")); O menu será exibido uma primeira vez. Ao dar a resposta, o switch executa o método referente a opção escolhida. Enquanto não for digitado zero, o menu será exibido a cada método executado. Caso o usuário escolha a opção 0, o loop while será encerrado e nenhum menu será exibido novamente. Daí você pode tratar o que ocorre quando o usuário escolher sair.
  14. Não seria mais simples remover o funcionário e depois retornar o menu? Se o usuário quiser remover outro funcionário ele escolhe a opção de remover novamente. Mas se você precisa fazer um loop pra essa função específica, apenas execute ela a primeira vez, chame o método de exclusão e pergunte em um JOptionPane se o usuário pretende remover outro funcionário. Nessa hora você entra em loop. Enquanto a resposta for sim, fique exibindo a opção até a lista estar vazia ou o usuário escolher que não quer remover outro funcionário.
  15. @anonymouatour Entendi... nesse caso, o seu problema é só inicializar as variáveis com algum valor (pode ser no momento em que você declara a variável) e os erros de null e zero desaparecem.
  16. Olá.. Antes de mais nada, bem-vindo ao maravilhoso (ou não) mundo da programação. Sua classe de dados, Caneta, possui diversos erros graves no que diz respeito a OO. As variáveis dessa classe (salvo em situações específicas), jamais devem ser públicas, senão qualquer um consegue alterar seus valores fora das regras. O ideal é que suas variáveis sejam private e para gravar e ler valores nelas, utilize getters e setters para cada variável. Outra coisa é que sua classe deveria ter um construtor e a partir dele inicializar as suas variáveis com valores default (evitando retorno de dados do tipo null e 0.0 que você vem enfrentando). Exemplo: public class Teste { private String nome; private int idade; /** Esse construtor instancia a classe com valores padrão para as variáveis nome e idade. Não vai retornar null em nada */ public Teste() { setNome(""); setIdade(0); } /** Esse construtor instancia a classe com valores de nome e idade passados via parâmetro */ public Teste(String nome, int idade) { setNome(nome); setIdade(idade); } public void setNome(String nomeViaParametro){ this.nome = nomeViaParametro; } public String getNome() { return this.nome; } public void setIdade(int idadeViaParametro) { this.idade = idadeViaParametro; } public int getIdade() { return this.idade; } //Coloque outros métodos caso necessário, como o destampar, tampar, etc; } Dessa forma, sua classe de dados sempre terá os valores inicializados e com valores padrão. Ao instanciar essa classe, você faria dessa forma para ler e gravar dados: Teste teste = new Teste(); //com esse construtor, você instancia a classe com os valores padrão para Nome e idade Teste teste2 = new Teste("Um Nome", 10); //com esse construtor, você já instancia a classe com os valores "Um nome" e 10 para nome e idade, respectivamente //Para gravar um novo valor teste.setNome("Outro nome"); teste.setIdade(20); //E para ler System.out.println("Nome = " + teste.getNome()); System.out.println("Idade = " + teste.getIdade()); //O mesmo vale para a variável teste2. Você pode informar novos valores para ela a partir dos setter e ler os valores através dos getters Se você organizar sua classe Caneta de forma semelhante e alterar a forma como atribui os valores às variáveis na main, esses erros de null e zero desaparecem.
  17. Concordo, mas existe vida sem hibernate. Existem diversas outras soluções de ORM. Hibernate pode ser "grande e desengonçado" dependendo do que será feito. O JPA não é indicado para qualquer tipo de projeto. O próprio Spring também poderia ser usado. Aqui onde trabalho o framework todo foi desenvolvido "in house". Temos controle total de tudo que acontece, não se depende de terceiros para corrigir um bug e com certeza é bem mais simples que o hibernate (operamos com cache e persistência também). Hibernate é ruim? Claro que não. É bom conhecer a ferramenta até mesmo para questão de currículo e busca de empregos decentes mas ele não é a resposta pra tudo. Se você não é um desenvolvedor profissional, ou seja, se não conhece intimamente a linguagem e não sabe como utilizar seus recursos, cair de cabeça em cima de um framework vai gerar mais problemas do que resolvê-los. Abração
  18. Se o projeto for pequeno ou você está aprendendo, usar hibernate é como dar um tiro de canhão em formiga. Simplifique as coisas. Para gravar o valor do enum em banco, você pode simplesmente usar o ordinal dele. No seu caso, 0 masculino e 1 feminino. E para escrever o valor no SQL, apenas repasse como valor //Onde getSexo() devolve um Enum do tipo sexo cliente.getSexo().ordinal(); Para recuperar esses dados do banco, é simples: faça um parser do valor que vem do banco para mapear o seu Enum. public Enum sexo { MASCULINO, FEMININO; public static sexo parseSQL(int valorDoBanco) { try { return values()[valorDoBanco]; } catch (Exception e) { return values()[0]; } } } Assim, quando você está lendo um ResultSet e populando o objeto de dados, quando chegar na hora de ler o Enum, faça assim: //rs é o nome da variável para um ResultSet contendo sua lista com a consulta SQL cliente.setSexo(sexo.parseSQL(rs.getInt("sexo"))); //Onde no objeto cliente, sexo é uma variável do tipo sexo (Enum) Resolvido.
  19. Depende MUITO do que você quer fazer. Se a sua tela for, por exemplo, de um cadastro e quando digitar o CPF e sair do campo (no evento onblur do componente type='text') e quiser validar o CPF e/ou conferir se ele já não está cadastrado no banco para outra pessoa, a melhor opção sim é o Ajax. Agora, se o seu formulário em tela for simples e você não necessita de validações em tempo real, pode passar as informações tanto via GET como POST. Tudo depende de como você quer tratar a sua tela e os dados digitados nela. Se você quiser apenas fazer validações de campo (se foi preenchido, se tem caracteres com comprimento mínimo para um determinado campo, etc), uma simples rotina de validação em javascript resolve seu problema antes de enviar os dados via GET ou POST.
  20. @Renanzinthhh Você pode fazer exatamente o que falei se alterar seu código. Você criou uma interface para chamar o método de validação. Certo. Mas ele está no local errado. Colocar um método de validação de tela dentro do objeto de dados não é bom. Você possui uma classe ProdutoDAO. Além de fazer acesso ao banco para ler e gravar dados, essa classe atua como uma model, onde todos os métodos de negócio (validações, consultas, etc) tem que estar. Implemente a interface nessa classe. Dentro dela você terá os métodos de validação do produto e gravação em banco de dados. Eu fiz o exemplo tudo dentro da mesma classe. Esse método de cadastra produto foi só pra demonstrar que você pode jogar livremente com métodos e classes, mas mantendo lógica e seguindo padrões de boa programação. public ProdutoDAO implements InterfaceDeValidacao { public ProdutoDAO (DataBaseConnector dbc) { //método do construtor } public validaProdutoPorDescricao(String descricao) { //método de validação } public void registra(DataProduto dp) { //método de gravação em banco de dados } } E na classe que você apresentou inicialmente com o código do JButton, pode fazer isso: private ProdutoDAO prodao = new ProdutoDAO(Database.getConnection()); public void actionPerformed(ActionEvent e) { if (prodao.validaProdutoPorDescricao(campoDescricao.getText()) { cadastraProduto(); } else { JOptionPane.showMessageDialog(null, "Produto com nome inválido"); } } //Este método pode estar na mesma classe onde você desenhou a tela private void cadastraProduto() { Produto prod = new Produto(); prod.setDescricao(campoDescricao.getText()); prod.setSaldoEstoque(Integer.parseInt(campoSaldoEstoque.getText())); prod.setPrecoCompra(Float.parseFloat(campoPrecoDeCompra.getText())); prod.setPrecoVenda(Float.parseFloat(campoPrecoDeVenda.getText())); prodao.registra(prod); campoDescricao.setText(""); campoSaldoEstoque.setText(""); campoPrecoDeCompra.setText(""); campoPrecoDeVenda.setText(""); } Viu como simples mudanças deixaram o código mais fácil de ler e delegamos funções específicas para cada método? Claro, poderíamos dividir ainda mais as coisas em métodos especializados mas o código é pequeno e não teria necessidade, mas para fins de aprendizado é interessante. O que eu fiz é a melhor alternativa? Não. É a única? Também não. Agora, tente imaginar esse programa crescendo. Cadastro de produtos, clientes, controle de estoque, vendas, etc. É necessário estruturar o software antes de começar a escrever código para que exista um padrão nele. Dessa forma, você sabe que tipo de métodos vai encontrar nas classes DAO de cada parte do sistema, a estrutura de cada BO e quais seriam os métodos comuns a cada tela e como criar uma interface para gerenciar telas.
  21. TwistedSoul

    ocr

    Cara, procura pelo projeto Tesseract disponibilizado pelo javacpp. E esse tipo de coisa você não vai achar em português e, caso ache, vai ser mais antigo ou bem desatualizado. Eu sei que é complicado mas atualmente programar sem saber inglês torna tudo muito mais difícil. As publicações, tutoriais, cursos e dicas mais recentes costumam sempre estar em inglês. Única forma de achar algo em português é se alguém teve paciência e boa vontade de traduzir uma documentação ou tutorial. Talvez você consiga achar algum pocket video ou video tutorial sobre Tesseract em português, mas daí tem que conferir se a versão apresentada no vídeo vale para o atual trunk disponibilizado no github do projeto: https://github.com/bytedeco/javacpp-presets/tree/master/tesseract Além de ter uma biblioteca de OCR que funcione, ainda existe a necessidade de tratar/otimizar a imagem capturada pela câmera, identificar nessa imagem o que poderia ser uma placa para depois aplicar a solução de OCR em cima dela. Isso não é nem um pouco trivial.
  22. Você pode fazer algo simples, assim: JButton btnCadastrarProduto = new JButton("Cadastrar"); btnCadastrarProduto.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { Produto prod = new Produto(); prod.setDescricao(campoDescricao.getText()); if (!prod.validaProdutoPorDescricao(prod)) { JOptionPane.showMessageDialog(null, "Produto com nome inválido"); } else { prod.setSaldoEstoque(Integer.parseInt(campoSaldoEstoque.getText())); prod.setPrecoCompra(Float.parseFloat(campoPrecoDeCompra.getText())); prod.setPrecoVenda(Float.parseFloat(campoPrecoDeVenda.getText())); ProdutoDAO prodao = new ProdutoDAO(Database.getConnection()); prodao.registra(prod); campoDescricao.setText(""); campoSaldoEstoque.setText(""); campoPrecoDeCompra.setText(""); campoPrecoDeVenda.setText(""); // TODO FAZER AÇÃO DO BOTÃO CADASTRAR } } }); btnCadastrarProduto.setBounds(231, 200, 135, 25); contentPane.add(btnCadastrarProduto); Ou criar um método que executa a gravação caso a resposta seja positiva, assim: public boolean validaProduto(String descricao) { //Escreva o método de validação do produto } public void actionPerformed(ActionEvent e) { if (validaProduto(campoDescricao.getText()) { cadastraProduto(); } else { JOptionPane.showMessageDialog(null, "Produto com nome inválido"); } } public void cadastraProduto() { Produto prod = new Produto(); prod.setDescricao(campoDescricao.getText()); prod.setSaldoEstoque(Integer.parseInt(campoSaldoEstoque.getText())); prod.setPrecoCompra(Float.parseFloat(campoPrecoDeCompra.getText())); prod.setPrecoVenda(Float.parseFloat(campoPrecoDeVenda.getText())); ProdutoDAO prodao = new ProdutoDAO(Database.getConnection()); prodao.registra(prod); campoDescricao.setText(""); campoSaldoEstoque.setText(""); campoPrecoDeCompra.setText(""); campoPrecoDeVenda.setText(""); } A melhor prática de programação é criar métodos especializados. Um que faça validações, outro que prepare o objeto com os dados da tela e outro que efetivamente grave os dados e outro que gerencie a tela. Poderia ter um método que "limpe" a tela e zere as variáveis toda vez que o frame for aberto ou um produto seja gravado. No exemplo acima, preparar o objeto, gravar em banco e limpar a tela é feito no mesmo método cadastraProduto() pois o objeto é pequeno e a tela simples. Mas fica a dica quando for criar telas mais complexas e com validações mais rebuscadas.
  23. @natan500 Mas você faz mais alguma coisa com esses valores? Se você passar como parâmetro 50 e 500, respectivamente, ao dar um print nesses valores vai sair exatamente 50 e 500. Você apenas está atribuindo valores às variáveis de classe desse objeto e mais nada. Se precisa de uma resposta e/ou cálculo em cima desses números, precisa implementar o código que faça isso.
  24. Você tem dois construtores nessa classe. public Conta (int numero ) { this.numero = numero; } public Conta (int numero , double limite ) { this(numero); this.limite = limite; } Quando a classe for instanciada usando segundo construtor (com dois argumentos), ao executar this(numero); Seria o mesmo que chamar public Conta (int numero) { this.numero = numero; } Sempre que você tem dúvida com isso, coloque um break point na linha que você tem dúvida e depure com o F7 (uso Netbeans) para fazer um step in e ver o que acontece. Se colocar um break point em this(numero) e pressionar F7, você vai observar que o próximo ponto/linha a ser depurada é exatamente o primeiro construtor. Depois disso o código segue executando em this.limite = limite;
  25. Esse this(numero); está utilizando o primeiro construtor para setar o valor da variável numero;

Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas comunidades sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×
×
  • Criar novo...

Ebook grátis: Aprenda a ler resistores e capacitores!

EBOOK GRÁTIS!

CLIQUE AQUI E BAIXE AGORA MESMO!