Pesquisar

28 de fevereiro de 2016

Godot Engine: Visualizando o log do android com o Adb

A história é a seguinte: você está desenvolvendo um jogo utilizando a Engine Godot e precisa dar uma olhada no log do aplicativo que está rodando no celular. 

O log pode ser visualizado através do adb:

adb logcat [options] [filterspecs]

onde [options] são as opções do comando e [filterspecs] são os filtros a serem utilizados.

Para obter apenas o log do Godot deve-se silenciar a saída de log:

adb logcat -s

e filtrar pela Tag do godot

"godot"

O comando completo fica da seguinte forma:

adb logcat -s godot

O mesmo pode ser obtido pelo seguinte comando:

adb logcat *:S godot:V



PS: uma introdução à Engine Godot pode ser visualizada neste vídeo


25 de janeiro de 2016

Automatização do Navegador utilizando o IMacros - 2ª parte

Voltando ao exemplo do Imacros para preencher automaticamente um formulário. Vamos supor que você queira responder várias vezes o formulário, sendo que cada preenchimento vão ser colocadas informações ligeiramente diferentes no formulário (Figura 1). 



Figura 1: Minions - ligeiramente diferentes mas tudo igual 


A melhor forma de realizar esta tarefa é colocar as respostas em um arquivo csv, sendo cada linha do arquivo vai conter um preenchimento das respostas (colunas) do formulário. O arquivo contendo as respostas vai ter a seguinte estrutura (Figura 2).


Pergunta 1 Pergunta 2 Pergunta 3 Pergunta 4
Da Padoca da Esquina Por que eu quero Com açúcar Sou programador: por volta de 7 litros
Requentado Café de ontem é melhor Sem açúcar Duas
Feito na hora Não tem nada melhor do que o café feito na hora Filtrado com meia velha Uma

Figura 2: Formato do arquivo csv contendo os dados a serem utilizados

Após criar este arquivo csv basta fazer o IMacros obter as respostas deste arquivo. Portanto, a partir do script do artigo anterior:


TAB T=1
URL GOTO=https://docs.google.com/forms/d/1nXuAGqskiTm8vU1Gm8bEMUpe9NSTgrtHhqlcsQgzgis/viewform?fbzx=-5150429435447904810
TAG POS=1 TYPE=INPUT:RADIO FORM=ID:ss-form ATTR=NAME:entry.1925481785&&VALUE:Da<SP>padoca<SP>da<SP>esquina CONTENT=YES
TAG POS=1 TYPE=INPUT:TEXT FORM=ID:ss-form ATTR=ID:entry_1632006682 CONTENT=Por<SP>que<SP>sim
TAG POS=1 TYPE=INPUT:RADIO FORM=ID:ss-form ATTR=NAME:entry.1254744817&&VALUE:Com<SP>açúcar CONTENT=YES
TAG POS=1 TYPE=INPUT:RADIO FORM=ID:ss-form ATTR=NAME:entry.753234863&&VALUE:Sou<SP>programador:<SP>por<SP>volta<SP>de<SP>7<SP>litros CONTENT=YES
WAIT SECONDS=6
TAG POS=1 TYPE=INPUT:SUBMIT FORM=ID:ss-form ATTR=ID:ss-submit


Vamos alterar o script para retirar os dados a serem preenchidos no formulário a partir do arquivo csv criado anteriormente. 

Inicialmente vamos indicar a localização do arquivo (exemplo.csv) contendo os dados a serem inseridos no formulário. Neste exemplo o arquivo se encontra na pasta
"C:/temp".

SET !DATASOURCE "C:/temp/exemplo.csv"

Agora indicamos para o IMacros ignorar a primeira linha do arquivo. Vamos utilizar esta linha como cabeçalho (header) do arquivo csv. 

SET !LOOP 2
SET !DATASOURCE_LINE {{!LOOP}}

Finalmente vamos utilizar as colunas do arquivo csv para preencher os campos do formulário.

Para a pergunta nº1 a resposta se encontra na 1ª coluna do arquivo csv (COL1).

TAG POS=1 TYPE=INPUT:RADIO FORM=ID:ss-form ATTR=NAME:entry.1925481785&&VALUE:{{!COL1}} CONTENT=YES

Para a pergunta nº2 a resposta se encontra na 2ª coluna do arquivo csv (COL2).

TAG POS=1 TYPE=INPUT:TEXT FORM=ID:ss-form ATTR=ID:entry_1632006682 CONTENT={{!COL2}}

Para a pergunta nº3 a resposta se encontra na 3ª coluna do arquivo csv (COL3).

TAG POS=1 TYPE=INPUT:RADIO FORM=ID:ss-form ATTR=NAME:entry.1254744817&&VALUE:{{!COL3}} CONTENT=YES

Para a pergunta nº4 a resposta se encontra na 4ª coluna do arquivo csv (COL4).

TAG POS=1 TYPE=INPUT:RADIO FORM=ID:ss-form ATTR=NAME:entry.753234863&&VALUE:{{!COL4}} CONTENT=YES

Apenas para visualização do funcionamento do script indicamos para o IMACROS esperar alguns segundos antes de submeter o formulário:

WAIT SECONDS=6

E na última etapa submetemos o formulário:

TAG POS=1 TYPE=INPUT:SUBMIT FORM=ID:ss-form ATTR=ID:ss-submit


E o script completo fica da seguinte  forma:

TAB T=1
URL GOTO=https://docs.google.com/forms/d/1nXuAGqskiTm8vU1Gm8bEMUpe9NSTgrtHhqlcsQgzgis/viewform?fbzx=-5150429435447904810

SET !DATASOURCE "C:/temp/exemplo.csv"
SET !LOOP 2
SET !DATASOURCE_LINE {{!LOOP}}

TAG POS=1 TYPE=INPUT:RADIO FORM=ID:ss-form ATTR=NAME:entry.1925481785&&VALUE:{{!COL1}} CONTENT=YES
TAG POS=1 TYPE=INPUT:TEXT FORM=ID:ss-form ATTR=ID:entry_1632006682 CONTENT={{!COL2}}
TAG POS=1 TYPE=INPUT:RADIO FORM=ID:ss-form ATTR=NAME:entry.1254744817&&VALUE:{{!COL3}} CONTENT=YES
TAG POS=1 TYPE=INPUT:RADIO FORM=ID:ss-form ATTR=NAME:entry.753234863&&VALUE:{{!COL4}} CONTENT=YES
WAIT SECONDS=6
TAG POS=1 TYPE=INPUT:SUBMIT FORM=ID:ss-form ATTR=ID:ss-submit

Para rodar o script basta utilizar a opção Play (Loop) do Imacros (Figura 3)



Figura 3: Print screen da tela do Imacros com a opção Play (Loop)

14 de janeiro de 2016

Automatização do Navegador utilizando o IMacros



A história é sempre a mesma. Todo dia você abre o navegador e realiza sempre o mesmo conjunto de atividades nele. Seja checar o site de notícias, dar uma olhada na cotação dos Títulos do Tesouro Direto, ou testar uma aplicação que você está desenvolvendo.

Nessas horas o IMacros cai como uma luva para realizar essas tarefas repetitivas. O IMacros é um gerador de macro, com ele você pode gravar/escrever uma macro para executar um conjunto de comandos no navegador (Figura 1). 


Figura 1: SkyNet - Um executor de macro: matar John Connor


Indo para a parte prática vamos imaginar a seguinte situação:

Você está desenvolvendo aquele sisteminha web porreta onde existe um formulário enorme para o usuário preencher. Você vai ter que testar a funcionalidade deste formulário, mas convenhamos, ficar preenchendo o formulário a cada teste é um pouco estressante (Figura 2).

Figura 2: Testando o formulário manualmente


Para o exemplo ficar mais didático, vamos reduzir o formulário do sistema para algo mais simples (Figura 3) e a partir disto vamos construir a macro para preencher os dados do formulário. 



Figura 3: formulário a ser preenchido

O formulário de exemplo é formado por 4 perguntas simples relacionadas com o café, sendo 3 delas de alternativas e 1 dissertativa. 


O primeiro comando do script a ser gerado é escolher a aba do navegador onde a macro irá rodar, no nosso caso vamos escolher a aba atual do usuário:

TAB T=1

Agora vamos indicar para o navegador qual a URL a ser visitada: 


Finalmente vamos preencher as respostas do formulário. Vamos colocar as seguintes respostas para as perguntas: 

1) Que tipo de café você gosta? 
Da padoca da esquina  

2) Qual o motivo da escolha anterior?
Por que sim

3) E como o café deve ser feito?
Com açúcar

4) Quantas xícaras de café você bebe por dia?
Sou programador, por volta de 7 litros


Os seguintes comandos devem ser adicionados no script: 

TAG POS=1 TYPE=INPUT:RADIO FORM=ID:ss-form ATTR=NAME:entry.1925481785&& VALUE:Da<SP>padoca<SP>da<SP>esquina CONTENT=YES

TAG POS=1 TYPE=INPUT:TEXT FORM=ID:ss-form ATTR=ID:entry_1632006682 CONTENT=Por<SP>que<SP>sim

TAG POS=1 TYPE=INPUT:RADIO FORM=ID:ss-form ATTR=NAME:entry.1254744817&&VALUE:Com<SP>açúcar CONTENT=YES

TAG POS=1 TYPE=INPUT:RADIO FORM=ID:ss-form ATTR=NAME:entry.753234863&&VALUE:Sou<SP>programador:<SP>por<SP>volta<SP>de<SP>7<SP>litros CONTENT=YES

onde: 

TAG POS=1 TYPE=INPUT:RADIO FORM=ID:ss-form 

busca um elemento do tipo radio no formulário de id ss-form

TAG POS=1 TYPE=INPUT:TEXT FORM=ID:ss-form

busca um elemento do tipo text no formulário de id ss-form

ATTR=NAME:entry.1925481785&&VALUE:Da<SP>padoca<SP>da<SP>esquina 

é a restrição do radio a ser selecionado: deve possuir o nome entry.1925481785 e valor "Da padoca da esquina" (lembre-se que três radio's são identificados por este nome, mas apenas um deles possui o valor indicado)

CONTENT=YES 

indica que o radio vai ser selecionado

O mesmo ocorre para as outras duas questões envolvendo radio's: 

a restrição na seleção: 

ATTR=NAME:entry.1254744817&&VALUE:Com<SP>açúcar
ATTR=NAME:entry.753234863&&VALUE:Sou<SP>programador:<SP>por<SP>volta<SP>de<SP>7<SP>litros

e a seleção do radio:

CONTENT=YES 


ATTR=ID:entry_1632006682 

é a restrição do elemento de texto a ser selecionado: o que possui o ID igual a entry_1632006682 

CONTENT=Por<SP>que<SP>sim

Indica o valor que vai ser colocado no elemento de texto


Só para visualizarmos os campos preenchidos vamos colocar o IMacros para esperar durante uns segundos:

WAIT SECONDS=6

Por último vem o comando para submeter o formulário 

TAG POS=1 TYPE=INPUT:SUBMIT FORM=ID:ss-form ATTR=ID:ss-submit


Com isto o preenchimento do formulário está automatizado e você pode tomar um cafézinho enquanto o IMacro realiza o preenchimento do formulário (Figura 5)



FIGURA 5: Você aceita uma xícara de café?



E o script fica da seguinte forma:

TAB T=1
URL GOTO=https://docs.google.com/forms/d/1nXuAGqskiTm8vU1Gm8bEMUpe9NSTgrtHhqlcsQgzgis/viewform?fbzx=-5150429435447904810
TAG POS=1 TYPE=INPUT:RADIO FORM=ID:ss-form ATTR=NAME:entry.1925481785&&VALUE:Da<SP>padoca<SP>da<SP>esquina CONTENT=YES
TAG POS=1 TYPE=INPUT:TEXT FORM=ID:ss-form ATTR=ID:entry_1632006682 CONTENT=Por<SP>que<SP>sim
TAG POS=1 TYPE=INPUT:RADIO FORM=ID:ss-form ATTR=NAME:entry.1254744817&&VALUE:Com<SP>açúcar CONTENT=YES
TAG POS=1 TYPE=INPUT:RADIO FORM=ID:ss-form ATTR=NAME:entry.753234863&&VALUE:Sou<SP>programador:<SP>por<SP>volta<SP>de<SP>7<SP>litros CONTENT=YES
WAIT SECONDS=6
TAG POS=1 TYPE=INPUT:SUBMIT FORM=ID:ss-form ATTR=ID:ss-submit


17 de dezembro de 2015

Whatsapp fora do ar. Tô nem aí, uso o Telegram mesmo

E a justiça brasileira decide cortar o acesso ao Whatsapp no Brasil. Mas para quê chorar com isso, se existe um aplicativo bem melhor do que o whatsapp para usar. Vamos dar uma olhada na melhor alternativa ao whatsapp no momento. Estou falando do Telegram.  

Já pela sua história, o Telegram nasceu da ideia de um cara que teve que fugir às pressas da Rússia. Segundo relatado na The New York Times


When a SWAT team appeared at Pavel Durov’s door in St. Petersburg, he started thinking about his future in Russia.
He was home alone, and he peered at them through a monitor.
“They had guns and they looked very serious,” said Mr. Durov, once Russia’s biggest celebrity entrepreneur. “They seemed to want to break the door.”


Traduzindo de uma forma BR:

"A polícia tava lá na frente da minha casa querendo entrar na bicuda......"

E foi assim que surgiu o Telegram (depois que o Pavel Durov fugiu da Rússia).

O Telegram já é melhor que  o Whatsapp já pelo fato que não vai transbordar a memória do seu celular gravando todas as imagens de uma maneira bizarra no seu aparelho (deixa tudo espalhado e não adianta remover a conversa, as imagens ficam nele). 

Mas ele é melhor mesmo do que o Whatsapp pelos Stickers existentes: me fala de qual outro aplicativo desse tipo que você pode personalizar com os stickers do Mr. Bean ???





Ah!!! Mas eu não gosto do Mr. Bean. Sou um cara politizado e gosto de discutir sobre política. 

Seus problemas estão resolvidos meu camaradinha. Você pode utilizar os stickers dos políticos brasileiros. 

Não importa se você é mortadela 



coxinha



bolsonarense



marinense



ou tradicionalista



vai sempre ter um sticker que é a sua cara. 







15 de maio de 2013

Artigo Rápido: Como verificar o navegador que está sendo utilizado pelo usuário

Ou no meu caso: "Como verificar se estou utilizando o Internet Explorer (vulgo IE)"

Imagine a seguinte situação: 

"Você quer incluir um arquivo CSS (Cascading Style Sheets) na sua página ou rodar um determinado algoritmo apenas para um determinado tipo de navegador, como por exemplo o IE6."

Aqui neste artigo, vão ser apresentadas algumas opções para resolver este problema: a primeira utilizando, no Zend Framework, o método appendStylesheet do Head Link (já comentado neste artigo); a segunda utilizando diretamente Comentários Condicionais; a terceira utilizando Javascript e a última utilizando apenas PHP


Figura 1: Flash


1ª Utilizando Head Link(*)


Na view basta adicionar o código:


1
2
3
4
5
6
<?php 

// Exemplo de adição de um CSS apenas para o navegador Internet Explorer
$this->headLink()->appendStylesheet('caminho/do/arquivo', 'screen', 'IE');

?>

2ª Utilizando Comentários Condicionais(*)


Basta adicionar o código entre os comentários condicionais, por exemplo:

<!--[if IE]>
<link href="non-ie.css" rel="stylesheet">
<![endif]-->

3ª Utilizando javascript:


1
2
3
4
5

<script type="text/javascript">
   if($.browser.msie){
      alert('Estou utilizando alguma versão do IE. ');
   }
</script>

4ª Utilizando apenas PHP 



1
2
3
4
5
6
7
8
9
<?php 
if(preg_match('/(?i)msie [0-9]*/', $_SERVER['HTTP_USER_AGENT'])){
?>
   <script type="text/javascript">
      alert('Estou utilizando alguma versão do IE. ');
   </script>
<?php
}
?>



(*) Comentários condicionais não são mais reconhecidos no Internet Explorer 10


23 de novembro de 2012

Formulários no Doctrine: Validando a existência do login no Banco de Dados

Ao gerar um formulário para cadastro de usuários em um sistema, usualmente é desejado validar as informações inseridas pelos usuários nos campos do formulário. No caso de um campo que vai ser utilizado na identificação do usuário para este se logar no sistema (login), como por exemplo um apelido (nick) ou um email, deve-se ter a restrição de que nenhum outro usuário já esteja cadastrado com este campo. Um exemplo de duplicação do 'login' ocorre no filme Irmão Gêmeos, onde Julius Benedict (Arnold Schwarzenegger) e Vincent Benedict (Danny DeVito) possuem o mesmo código genético  


Figura 1: exemplo de duplicação de login.  


Neste artigo vai ser apresentado como a classe Zend_Validate_Abstract pode ser estendida para utilizar o Doctrine para validar se o login que está sendo inserido não existe no Banco de Dados. Caso já exista um usuário cadastrado com este login é retornado um código de erro. Além disto, vai ser apresentado um exemplo de como esta classe pode ser utilizado em um formulário de cadastro. 

A seguir é apresentada a classe DoctrineValidateEmail, que estende a Zend_Validate_Abstract e permite a validação do login (neste exemplo básico login = email do usuário). Basicamente nesta classe foi realizada a reimplementação da função isValid que utiliza uma classe DAO (UsuarioDAO) que valida o login passado como parâmetro.


Classe DoctrineValidateEmail


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<?php 

class DoctrineValidateEmail extends \Zend_Validate_Abstract{
    
    const NOK = 1;
    
    protected $_messageTemplates = array(
        self::NOK => "%value% já cadastrado"
    );
    
    public function isValid($email){
        
        try{
            $user = UserDAO::getUserByEmail($email);
        }catch(\Doctrine\ORM\NoResultException $e){
            // Email livre para cadastro
            $user = null;
        }
        if($user){
            $this->_error(self::NOK,$email);
            return false;
        }
        return true;
    }
}

A classe UserDAO que interage com o Banco de Dados utilizando o Doctrine é apresentada a seguir. Para simplificar o exemplo é apresentado apenas a implementação do método getUserByEmail utilizado pela DoctrineValidateEmail.


Classe DAO para interação com o Banco de Dados


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
<?php

class UserDAO {
    
    public static function getUserByEmail($email) {
        /**Obtendo o container contendo as operações básicas envolvendo o doctrine. */
        $doctrine_container = \Zend_Registry::get('doctrine');
        $em = $doctrine_container->getEntityManager();
               
        
        $query = $em->createQuery('select s from UserDoctrine s WHERE s.email = ?1');
        $query->setParameter(1, $email);
        
        $user_doctrine = $query->getSingleResult();
        
        return $user_doctrine;        
    } // function
} // class


E finalmente é apresentado como a classe DoctrineValidateEmail implementada pode ser utilizada em um formulário para validar o login que está sendo inserido pelo usuário.


Exemplo de Formulário


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
<?php

class Cadastro_Form_Cadastro extends Zend_Form
{

    public function init()
    {
        $this->setMethod('post');

        // CSFR (www.frameword.zend.com/manual/en/learning.quickstart.create-form.html)
        $this->addElement('hash', 'csrf', array('ignore' => true));

        // Nome
        $this->addElement(
                'text', 'nome', array(
            'label' => 'Nome:',
            'required' => true,
            'maxlength' => '30',        
            'filters' => array('StringTrim'),
        ));

        // Sobrenome
        $this->addElement(
                'text', 'sobrenome', array(
            'label' => 'Sobrenome:',
            'required' => true,
            'maxlength' => '30',        
            'filters' => array('StringTrim'),
        ));
  
        // Email vai ser utilizado como login
        $email = new Zend_Form_Element_Text('email');
        $email->setLabel('Email:');
        $email->addFilters(array('StringTrim', 'StripTags'));
        $email->addValidator('EmailAddress', TRUE);
        $email->setRequired(true);

        //Adicionando a validação no email                
        $email->addValidator(new DoctrineValidateEmail($email->getValue()));

        $this->addElement($email);

        //Senha        
        $this->addElement(
                'password', 'password', array(
            'label' => 'Senha:',
            'required' => true,
            'maxlength' => '20',        
                )
        );

        $this->addElement(
                'submit', 'submit', array(
            'ignore' => true,
            'label' => 'Cadastrar',
                )
        );
    }
}



1 de setembro de 2012

Herança no Doctrine: Persistindo e recuperando objetos

Em um artigo anterior foi apresentando como a herança pode ser implementada no Doctrine. Neste artigo vamos apresentar como os elementos da herança podem ser persistidos e recuperados do Banco de Dados

Para exemplo didático vamos utilizar novamente o exemplo épico do filme Star Wars (Figura 1), onde existe uma relação de herança entre: DarthVader, Luke Skywalker e Leia Organa.


Figura 1: Exemplo didático de herança. 



As classes que representam cada um dos elementos podem ser visualizadas no post anterior


Para o conjunto de classes do exemplo vamos implementar uma classe DAO (Data Access Object) para interagir com o Banco de Dados. A seguir é apresentado o código da classe DAO:

Classe JediDAO



 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
<?php

class JediDAO {
   
    public static function add($object) {
        /**Obtendo o container contendo as operações básicas envolvendo o doctrine. */
        $doctrine_container = \Zend_Registry::get('doctrine');
        $em = $doctrine_container->getEntityManager();

        if($object->getId()){
            $object = $em->merge($object);
        }else{
            $em->persist($object);
        }
        
        $em->flush();

        return $object;
    }
    
    public static function get($id) {
        /**Obtendo o container contendo as operações básicas envolvendo o doctrine. */
        $doctrine_container = \Zend_Registry::get('doctrine');
        $em = $doctrine_container->getEntityManager();
                       
        $object = $em->getRepository('DarthVader')->find($id);

        return $object;
    } // function
    
    public static function listAll(){
        /**Obtendo o container contendo as operações básicas envolvendo o doctrine. */
        $doctrine_container = \Zend_Registry::get('doctrine');
        $em = $doctrine_container->getEntityManager();
        
        $query = $em->createQuery('select obj from DarthVader obj');
        
        $object_list = $query->getResult();
        
        return $object_list;        
    }
    
} // class

Agora vamos testar os métodos implementados na classe DAO:


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
<?php 
        //Criando um objeto DarthVader
        $darth_1 = new  DarthVader();
        $darth_1->setAtributoAnakin(1);
        
        //Persistindo o objeto
        JediDAO::add($darth_1);
        
        // Criando um objeto Luke
        $luke_1 = new Luke();
        $luke_1->setAtributoLuke(2);
        
        JediDAO::add($luke_1);
        
        //Criando um objeto Leia
        $leia_1 = new Leia();
        $leia_1->setAtributoLeia(3);
        
        JediDAO::add($leia_1);
        
        // Recuperando o objeto de id = 2
        $jedi_2 = JediDAO::get(2);
        
        /*
          var_dump em $jedi_2 retorna: 
            object(Luke)[198]
              private 'atributo_luke' => int 2
              private 'id' (DarthVader) => int 2
              private 'atributo_anakin' (DarthVader) => null

        */
        
        //Listando todos os objetos jedi's do Banco
        $lista_jedis = JediDAO::listAll();
        
        /*
        var_dump em $lista_jedis retorna um array:

        array (size=3)
        0 => 
            object(DarthVader)[209]
              private 'id' => int 1
              private 'atributo_anakin' => int 1
        1 => 
            object(Luke)[198]
              private 'atributo_luke' => int 2
              private 'id' (DarthVader) => int 2
              private 'atributo_anakin' (DarthVader) => null
        2 => 
            object(Leia)[208]
              private 'atributo_leia' => int 3
              private 'id' (DarthVader) => int 3
              private 'atributo_anakin' (DarthVader) => null
 
        */