sexta-feira, 19 de fevereiro de 2016

Como fazer uma espécie de GROUP_CONCAT no SQL SERVER

Ele rega os montes desde as suas câmaras; a terra farta-se do fruto das suas obras. (Salmos 104:13)
Imaginemos que, queremos retornar uma lista de produtos de uma loja numa consulta só. Será que é possível? Por exemplo: Que
retorne no atributo 'produtos' o seguinte: videogame,cd,dvd,cadeira. 
 
No MYSQL, é mais simples, basta apenas chamar a função GROUP_CONCAT. 
 
Mas, no SQL SERVER, é um pouco mais complicado. Para se realizar isto deve-se fazer o seguinte;
 
Considere a seguinte estrutura de tabelas:
 
        CREATE TABLE loja(
 id INTEGER,
 nome varchar(50)
  
 )

 CREATE TABLE produto(
 id INTEGER,
 id_loja INTEGER
 nome VARCHAR(10),
 preco FLOAT
 )
Agora, vamos realizar algumas inserções:
 

INSERT INTO loja VALUES(1,'CARREFULL');

INSERT INTO produto VALUES (1,1,'videogame',2.00);
INSERT INTO produto VALUES (2,1,'cd',3.00);
INSERT INTO produto VALUES (3,1,'dvd',4.00);
INSERT INTO produto VALUES (4,1,'cadeira',5.00);

Criação de uma tabela temporária (Isto pode variar dependendo do SGBD usado) com os dados dos produtos

SELECT produto.nome, 
 Values1 = CAST(NULL AS VARCHAR(8000))
 INTO #teste
 FROM produto
 WHERE produto.id_loja = '1'

Atualização para percorrer todos os registros da tabela temporária

 /* Criação de variáveis */
 DECLARE

  @retorno VARCHAR(8000),

  @Values1 varchar(8000)

 
 /* Setando valor padrão para a variável @Values1 */
 SET @Values1 = ''

 /* Realizando uma atualização  na tabela temporária #teste para percorrer todos os registros, e assim, poder adicionar o nome de cada produto á variável @Values1 */
 UPDATE #teste
  SET Values1 = nome,

  @Values1 =  @Values1  + nome + ','

 /* Setando condicionalmente o valor da varíavel @retorno como equivalente ao valor da variável @Values1 */ 
 if  @Values1 = ''

  SET @retorno = '-'

 else

  SET @retorno = @Values1

Na consulta de loja, definimos que a lista de nomes de produtos separados por vírgula, ficarão na coluna 'produtos'

 select loja.*,produtos=@retorno from loja WHERE id = 1;

quinta-feira, 28 de janeiro de 2016

Aplicação em python utilizando Pyramid com SQLAlchemy

Ainda antes que houvesse dia, eu sou; e ninguém há que possa fazer escapar das minhas mãos; agindo eu, quem o impedirá? Isaías 43:13
Olá pessoas.
Esta é mais uma postagem sobre programação, depois de quase 2 anos sem ter atualizado este blog. Isso devido á muita correria e trabalho, graças á Deus.
Nesta publicação, falarei como desenvolver uma aplicação simples em PYTHON, utilizando os frameworks PYRAMID e SQLAlchemy. 
Segue o link para documentação abaixo: 
 

quinta-feira, 24 de julho de 2014

Workers em javascript

O Senhor é o meu rochedo, e o meu lugar forte, e o meu libertador; o meu Deus, a minha fortaleza, em quem confio; o meu escudo, a força da minha salvação, e o meu alto refúgio. (Salmos 18:2)

WebWorkers são, basicamente, "scripts trabalhadores da WEB". Basicamente, são, semelhante á qualquer outro arquivo javascript, ou seja, scripts que interagem com a página principal. Porém, há uma pequena diferença: Durante a execução de qualquer instrução, seja uma requisição ou algum tipo de processamento, a outra instrução aguarda o fim da primeira. A execução de instruções em javascript é linear e não paralela. O navegador interpreta e executa linha a linha os comandos do bloco de intruções. Por exemplo: Quando há uma requisição em andamento, o interpretador simplesmente para, até a requisição estiver concluída. Só depois, segue a execução até a próxima linha.

No caso de WebWorkers, é diferente: A página principal aciona ou manda uma mensagem para algum script worker, e o mesmo, em executa determinado processamento em paralelo. Ou seja, a página principal continua executando seu bloco de instruções sem aguardar o fim da linha anterior.

Este mecanismo funciona graças á uma eficiente troca de mensagens entre o script e a página principal: Quando a página principal aciona o script (Evento postMessage), é executado o evento onMessage() no worker, que irá retornar sua resposta á página principal através do método postaMessage(). A resposta do worker estará no atributo data, do manipulador de evento event.

O exemplo consiste em um campo, um container e um botão para enviar. Depois que você digita algo, e clique em ENVIAR, o valor digitado é enviado ao worker, que retorna uma resposta com o valor, e alguma mensagem aleatória, como se fosse um chat.

 


onconnect = function (event) {

 
 var newPort = event.ports[0];
 
 var msgs = new Array();
 msgs.push("Como c ta");
 msgs.push("DDDDDDDDD");
 msgs.push("MMMMMMMMMMMMMMM");
 

 
 newPort.postMessage("Estabelecida conexao: ");
 
 newPort.onmessage = function (event) {
  var x = Math.floor(Math.random() * (msgs.length));
  var m = msgs[x];
  newPort.postMessage("Recebido: " + event.data); newPort.postMessage("Enviado: " +  m); 
 };
  //newPort.postMessage('ready!');
};

LINK PRO EXEMPLO
BAIXAR EXEMPLO

terça-feira, 1 de julho de 2014

Colisões com Easeljs

Assim diz o Senhor, o teu Redentor, o Santo de Israel: Eu sou o Senhor teu Deus, que te ensina o que é útil, e te guia pelo caminho em que deves andar. (Isaías 48:17)

Uma colisão é o choque entre dois corpos num determinado espaço. É, basicamente, o que acontece quando 2 carros se batem em alta velocidade. Também é por causa disto que você não atravessa paredes, tendo sua liberdade  de andar e explorar o espaço limitada. Este conceito é bastante utilizado na criação de jogos, pois, na grande maioria deles, há colisão ou choque entre corpos. Sem a aplicação deste conceito, seu objeto poderia tranquilamente atravessar uma parede sem que você queira.

O nosso exemplo se baseará no mesmo apresentado na postagem anterior: Criando animações com EaselJs. Porém ,com algumas diferenças. Nesta demonstração, será utilizado canvas (Onde se desenham animações específicas), javascript (Linguagem de script utilizada nos navegadores) e easeljs (Biblioteca javascript que encapsula alguns métodos próprios para lidar com CANVAS). A documentação desta biblioteca está disponível em EaselJs

Será criada uma animação que se consistirá no seguinte: Duas bolas (Vermelha e azul). A bola azul irá onde sempre seguir o quadrado laranja. O quadrado laranja será o ponto onde você pode fazer clique ou toque (Caso utilize um dispositivo TOUCH). Depois de um tempo,  irá aparecer um círculo negro, que é aonde, empregando os métodos de colisão, você deverá levar a bola vermelha.

Então, seguem abaixo as propriedades das 2 bolas:

 function constroe(){
  pos = definePosicaoRandomica(w,l);
  bola.x = pos.x;
  bola.y = pos.y;
  bola.vx = 4;
  bola.vy = 4;
  bola.r = r;
  
  pos = definePosicaoRandomica(w,l);
  red.x = pos.x;
  red.y = pos.y;
  red.vx = 2;
  red.vy = 2;
  red.r = r;

  pos = definePosicaoRandomica(w,l);
  saida.x = pos.x;
  saida.y = pos.y;
  saida.r = 20;
 }

Quando a página é carregada, é executado o método init(). Este método, basicamente, instancia os objetos, desenha os mesmos na tela, e associa eventos de clique e de toque á determinados métodos. 

 function init() {
  w = document.getElementById("demoCanvas").width;
  l = document.getElementById("demoCanvas").height;
  stage = new createjs.Stage("demoCanvas");
  r = 10;
  bola = new createjs.Shape();
  red = new createjs.Shape();
  es = new createjs.Shape();
  saida = new createjs.Shape();
  saida.ex = false;
        var is_touch_device = 'ontouchstart' in document.documentElement;

  constroe();
  
  desenha();

  createjs.Ticker.init();

  createjs.Ticker.on("tick", tick);
  
  
  createjs.Ticker.setFPS(50);
  
 
  if(is_touch_device === true){
   document.getElementById("demoCanvas").addEventListener("touchstart",handleTouch,false);
  }else{
   document.getElementById("demoCanvas").onclick = function(e){
    handleClique(e);
   }
  }
  
 }

 

Como você deve perceber, quando houve clique em alguma área delimitada pelo canvas, ou algum toque, são executados métodos específicos de toque ou de clique. Porém, ambos fazem a mesma coisa: Capturar coordenadas do mouse ou do toque. Isto para que, onde você tocar ou clicar, ficará o ponto laranja. O ponto laranja será seguido pela bola azul, graças ao método perseguicao(). 

 function handleTouch(e){
  
  es.x = 0;
  es.y = 0;
  var coords = getCoordsTouch(e);
  es.x = coords.x;
  es.y = coords.y;

 }
 
 function getCoordsTouch(event){
  var saida = {};
  saida.x = event.targetTouches[0].pageX - document.getElementById("demoCanvas").offsetLeft;
  saida.y = event.targetTouches[0].pageY - document.getElementById("demoCanvas").offsetTop;
  
  return saida;
 }
 function handleClique(e){
  es.x = 0;
  es.y = 0;
  
  var pX;
  var pY;
  pX = e.pageX - document.getElementById("demoCanvas").offsetLeft;
  pY = e.pageY - document.getElementById("demoCanvas").offsetTop;
  es.x = pX;
  es.y = pY;

}
 function perseguicao(obj1,obj2){
  // Animação de perseguição
  if(obj1.x < obj2.x){
   if(obj1.vx < 0){
    obj1.vx *= -1;
   }
  }else if(obj1.x > obj2.x){
   if(obj1.vx > 0){
    obj1.vx *= -1;
   }  
  }
  
  if(obj1.y < obj2.y){
   if(obj1.vy < 0){
    obj1.vy *= -1;
   }  
  }else if(obj1.y > obj2.y){
   if(obj1.vy > 0){
    obj1.vy *= -1;
   } 
  }
 }
 

 

A função tick() será executada á cada 50 milisegundos, sendo a função responsável pela continuidade e por dar vida á animação.

 

 function tick(event) {
  perseguicao(bola,es);
  
  
  bola.x += bola.vx;
  bola.y += bola.vy;
  
  red.x += red.vx;
  red.y += red.vy;

  if(checaColisao(bola,red) === true  ){
   if(red.x > bola.x){
    if(red.vx < 0){
     red.vx *= -1;
     bola.vx *= -1;
    }
   }else if(red.x < bola.x){
    if(red.vx > 0){
     red.vx *= -1;
     bola.vx *= -1;
    }
   }
   
   if(red.y > bola.y){
    if(red.vy < 0){
     red.vy *= -1;
     bola.vy *= -1;

    }
   }else if(red.y < bola.y){
    if(red.vy > 0){
     red.vy *= -1;
     bola.vy *= -1;

    }
   } 
   

  }
  
  
  checaLimites(bola);
  
  checaLimites(red);
  
  if(createjs.Ticker.getTime() > 10000){
   saida.ex = true;
   if(checaColisao(red,saida) === true){
    alert("FINISH");
    
    createjs.Ticker.reset();
    

    // Rever como reexecutar o ticker
    init();
   }
  }
  
  stage.removeAllChildren();

  desenha();

  stage.update(event);
 }

 

Vejamos como serão tratadas as colisões nesta animação, que ocorrem entre a bolinha azul e a vermelha: 

Primeiramente, na função tick(), especificamente no método checaColisao(), é feita uma verificação. Nesta checagem, basicamente, é calculada a distância entre estes dois objetos, utilizando o princípio de distância de dois pontos.  Caso queira saber mais, acesse Distância entre dois pontos. Se houve colisão, a bolinha vermelha é empurrada, graças ao impacto trazido pela bola azul. Logo, como houve resistência, o mesmo acontece com a bolinha azul. 

 function checaColisao(obj1,obj2){
        var dX = obj2.x - obj1.x;
        var dY = obj2.y - obj1.y;
        var distance = Math.sqrt((dX * dX) + (dY * dY));
        if(distance < (obj1.r + obj2.r )){
         return true;
        }
        return false;
 }

É verificado se algum dos elementos se choca com as bordas da tela, através do método checaLimites(), chamado  dentro de tick(). Se sim, então a parede reflete o impacto recebido pelo corpo.

 function checaLimites(obj){
  if( (obj.x + obj.r) > w ){
   obj.vx *= -1;
  }else if( (obj.x-obj.r ) < 0){
   obj.vx *= -1;
  }
  

  if( (obj.y + obj.r) > l ){
   obj.vy *= -1;
  }else if( (obj.y-obj.r) < 0){
   obj.vy *= -1;
  } 
 }

 

 Depois de 10 segundos, aparece um círculo negro, que é para onde você deve levar o círculo azul. Se houve colisão entre a bola azul e o círculo negro, então, o jogo se encerra. 

Links:

Página de testes
Download
Outro exemplo de colisões (De um cara que manja muito, que não sou eu!)

 

terça-feira, 24 de junho de 2014

EaselJs: Biblioteca javascript para criação de animações em Canvas

Porque todo o que é nascido de Deus vence o mundo; e esta é a vitória que vence o mundo, a nossa fé. (1 João 5:4)

Segue agora uma breve introdução á uma importante biblioteca feita em javascript, para criação de animações e jogos em CANVAS. Antes de prosseguir, é necessário que tenha uma noção de HTML5, principamente da utlização da TAG CANVAS. Para tanto, recomento a leitura do seguinte artigo: Animações com canvas e Criando jogos em canvas.

Esta biblioteca, do qual estamos falando, chama-se EaselJs, cuja documentação e código-fonte está disponível em EaselJs. Esta biblioteca é utilizada para facilitar na criação de gráficos e animações com CANVAS. No site da desenvolvedora, há muitos exemplos e links para jogos que implementam esta ferramenta. Se voçê já criou algo com CANVAS, irá reparar que esta ferramenta agiliza bastante para voçê atingir o objetivo, sem se preocupar, por exemplo, com a instanciação do elemento CANVAS para fazer desenhos simples, ou ficar executando a função setTImeout, para chamar a função de atualização da animação.

O jogo consiste no seguinte: Há duas bolas no cenário (Uma azul e outra vermelha). Quando voçê clica em algum ponto do cenário, ou toca em algum ponto do cenário (Caso utilize algum dispositivo com touchScreen), aparece um quadrado laranja, que é o destino do ponto azul. A bola vermelha persegue a bola azul, e se a alcança, é o fim do jogo. Depois de um tempo, aparece uma bola preta, que é onde a bola azul irá escapar, encerrando a animação.

O funcionamento do easeljs, de forma resumida, se resume no seguinte: Quando se carrega uma página, é necessária a execução de inicialização da animação, que é acionada pelo evento onLoad da página. Ou seja, a animação é inicializada quando a página é carregada, ou quando alguém inicia a animação, clicando em INICIAR. Logo em seguida, é necessária uma função que dá continuidade á animação. Á cada intervalo de tempo, é executado o evento tick pelo objeto estático Ticker, que é responsável por todo o controle da animação. Segue abaixo a estrutura codificada:


< !DOCTYPE html >
< html lang=”en-US” >
< head >


TESTES
 
< /head >
< body >
< /body >
< /html >

 

Agora que voçê tem uma noção de como o easeljs trabalha, vamos ver passo-a-passo a construção da animação:

Quando se carrega a página, é executada a função init(), que inicializa a animação.

 function init() {
  w = document.getElementById("demoCanvas").width;
  l = document.getElementById("demoCanvas").height;
  stage = new createjs.Stage("demoCanvas");
  r = 10;
  bola = new createjs.Shape();
  red = new createjs.Shape();
  es = new createjs.Shape();
  saida = new createjs.Shape();
  saida.ex = false;
        var is_touch_device = 'ontouchstart' in document.documentElement;
 
  constroe();
  
  desenha();

  createjs.Ticker.init();

  
  createjs.Ticker.on("tick", tick);
  
  
  createjs.Ticker.setFPS(20);
  
  if(is_touch_device === true){
   document.getElementById("demoCanvas").addEventListener("touchstart",handleTouch,false);
  }else{
   document.getElementById("demoCanvas").onclick = function(e){
    handleClique(e);
   }
  }
 }

 function tick(event) {
  
  if(checaColisao(es,bola) === true && bola.x == es.x && bola.y == es.y){
   // Quadrado laranja some, e bola azul fica no lugar
   
  }else{
   // Bola azul segue bola laranja
   perseguicao(bola,es);

  }
  
  if(checaColisao(bola,red) === true || ( (bola.x > red.x - r ) && (bola.x < red.x + r ) && (bola.y > red.y - r) && (bola.y < red.y + r) ) ){
   // Quadrado laranja some, e bola azul fica no lugar
   alert("GAME OVER");

   createjs.Ticker.reset();
   

   // Rever como reexecutar o ticker
   init();
  }else{
   // Bola vermelha segue bola azul
   perseguicao(red, bola);

  }
  
  // Aumentando velocidade do vilão
  
  if(createjs.Ticker.getTime() > 10000){
   console.log("INCREMENTANDO");
   red.v += 0.02;
   
   // Fazendo aparecer bola preta
   saida.ex = true;
   
   if(checaColisao(saida,bola) || ( (bola.x > saida.x - 20 ) && (bola.x < saida.x + 20 ) && (bola.y > saida.y - 20) && (bola.y < saida.y + 20) )){
    alert("VOCE ESCAPOU");
    createjs.Ticker.reset();
    // Rever como reexecutar o ticker
    init();
   }
  }
  
  stage.removeAllChildren();

  desenha();

  stage.update(event);
 }



Note que, na função init(), as variáveis são inicializadas, os objetos são instanciados (Função constroe()), depois, são desenhados na tela (Função desenha()), e é verificado se a interface aceita toque de tela (7 últimas linhas da função). Além disso, é inicializado o Ticker, além de ser associada a função tick() ao evento tick do Ticker. A função setFps define velocidade de animação para 20 milisegundos por frame - Cada frame é uma execução da função tick.

A função constroe() é responsável por definir o posicionamento inicial dos objetos, de forma randômica. Ou seja, são definidas, de forma aleatória, coordenadas x,y de cada objeto.

A função desenha() é responsável por desenhar os objetos na tela, com base nas propriedades já definidas (Coordenadas x e y). Observe que são desenhados dois círculos e um quadrado; e que, ambos são adicionados como nós do objeto Stage, que gerencia a disposição dos desenhos na tela.

 function constroe(){
  pos = definePosicaoRandomica(w,l);
  bola.x = pos.x;
  bola.y = pos.y;
  bola.v = 7;

  pos = definePosicaoRandomica(w,l);
  red.x = pos.x;
  red.y = pos.y;
  red.v = 2;
  
  pos = definePosicaoRandomica(w,l);
  saida.x = pos.x;
  saida.y = pos.y;
  
 }
 
 function desenha(){

  bola.graphics.beginFill("blue").drawCircle(0,0,r);

  red.graphics.beginFill("red").drawCircle(0,0,r);
  
  es.graphics.beginFill('#FF7F50').drawRect(es.x,es.y,10,10);
  
  stage.addChild(bola);
  
  stage.addChild(red);
  
  stage.addChild(es);
  
  if(saida.ex == true){
   saida.graphics.beginFill("#000000").drawCircle(0,0,20,20);
   stage.addChild(saida);
  }
  
 }

 Note que, quando há toque na tela, é executada a função handleTouch. E quando há algum clique no CANVAS, é executada a função handleClique. Porém, ambos fazem a mesma coisa: Setar as coordenadas do quadrado laranja, que é o alvo da bola azul.

 function handleTouch(e){
  
  es.x = 0;
  es.y = 0;
  var coords = getCoordsTouch(e);
  es.x = coords.x;
  es.y = coords.y;

 }
 
 function getCoordsTouch(event){
  var saida = {};
  saida.x = event.targetTouches[0].pageX - document.getElementById("demoCanvas").offsetLeft;
  saida.y = event.targetTouches[0].pageY - document.getElementById("demoCanvas").offsetTop;
  
  return saida;
 }
 
 function handleClique(e){
  es.x = 0;
  es.y = 0;
  
  var pX;
  var pY;
  pX = e.pageX - document.getElementById("demoCanvas").offsetLeft;
  pY = e.pageY - document.getElementById("demoCanvas").offsetTop;
  es.x = pX;
  es.y = pY;

 }

 

Na função tick(), que executo de tempos em tempos, eu verifico se há colisão entre as bolinhas, ou se a bolinha azul chegou no ponto indicado pelo quadrado laranja. Se a bolinha azul chegou no quadrado laranja, a mesma para. Se, porventura, a bolinha vermelha alcançou a bolinha azul, é exibida a mensagem "GAME OVER", e a animação é encerrada. Caso não ocorra nenhuma coisa nem outra, é executada a função perseguicao(), que é responsável por direcionar, a cada frame, um objeto á seu destino.

 function tick(event) {
  
  if(checaColisao(es,bola) === true && bola.x == es.x && bola.y == es.y){
   // Quadrado laranja some, e bola azul fica no lugar
   
  }else{
   // Bola azul segue bola laranja
   perseguicao(bola,es);

  }
  
  if(checaColisao(bola,red) === true || ( (bola.x > red.x - r ) && (bola.x < red.x + r ) && (bola.y > red.y - r) && (bola.y < red.y + r) ) ){
   // Quadrado laranja some, e bola azul fica no lugar
   alert("GAME OVER");

   createjs.Ticker.reset();
   

   // Rever como reexecutar o ticker
   init();
  }else{
   // Bola vermelha segue bola azul
   perseguicao(red, bola);

  }
  
  // Aumentando velocidade do vilão
  
  if(createjs.Ticker.getTime() > 10000){
   console.log("INCREMENTANDO");
   red.v += 0.02;
   
   // Fazendo aparecer bola preta
   saida.ex = true;
   
   if(checaColisao(saida,bola) || ( (bola.x > saida.x - 20 ) && (bola.x < saida.x + 20 ) && (bola.y > saida.y - 20) && (bola.y < saida.y + 20) )){
    alert("VOCE ESCAPOU");
    createjs.Ticker.reset();
    // Rever como reexecutar o ticker
    init();
   }
  }
  
  stage.removeAllChildren();

  desenha();

  stage.update(event);
 }
 function perseguicao(obj1,obj2){
  // Animação de perseguição
  if(obj1.x < obj2.x){
   obj1.x += obj1.v;
  }else if(obj1.x > obj2.x){
   obj1.x -= obj1.v;
  }
  
  if(obj1.y < obj2.y){
   obj1.y += obj1.v;
  }else if(obj1.y > obj2.y){
   obj1.y -= obj1.v;
  }
  
  if(obj1.x >= w){
   obj1.x -= obj1.v; 
  }else if(obj1.y >= l){
   obj1.y -= obj1.v;
  } 
 }

 

No final da função tick, é verificado se o tempo decorrido desde o início da animação é maior do que 10 segundos. Se sim, aparece um círculo preto, que é por onde o herói deve escapar, e, a cada frame, a velocidade da bolinha vermelha aumenta 0,2.

Como se vê, o que dá a sensação de movimento no jogo, é que, a cada frame, é executada a função desenha(), que printa os elementos na tela. Quando voçê faz um clique, voçê redefine propriedades dos objetos que estão sendo manipulados, porém, o que dispôe os objetos na tela com base em seus atributos, é a função desenha(), chamada através do evento tick().

 

  stage.removeAllChildren();

  desenha();

  stage.update(event);

 

Exemplo disponível para visualização:  Exemplo

Para baixar clique no link ao lado: BAIXAR

 

 

quarta-feira, 16 de abril de 2014

O que é JAVASCRIPT?

Mas aquele Consolador, o Espírito Santo, que o Pai enviará em meu nome, esse vos ensinará todas as coisas, e vos fará lembrar de tudo quanto vos tenho dito. (João 14:26)

Javascript é extremamente importante pra quem trabalha com desenvolvimento WEB. Além de tornar a navegação um pouco mais agradável ao usuário, a maioria das validações de formulários hoje em dia é feita no lado do cliente, não apenas no lado do servidor. Pode-se dizer que, toda página HTML é estática, ou seja, é apenas visualizada e renderizada pelo navegador. Hoje em dia, já existem alguns elementos em HTML que fazem algum processamento (Validação, animação, etc). Porém, em tese, todo o processamento do lado do cliente é feito via JAVASCRIPT. Deslocamento de divs, gerenciamento de eventos; tudo isso é controlado via javascript. Sem JS, voçê não poderia controlar o comportamento da página, apenas o desenho da mesma.

Afinal, o que é javascript? Em poucas palavras, é uma linguagem de script empregada nos navegadores, afim de alterar o comportamento ou tornar mais funcional determinada página em HTML. Mas, antes de aprender um pouco mais sobre este assunto, é bom entender alguns conceitos.

Primeiro, o DOM. DOM é uma sigla equivalente á Document Object Model. O DOM representa a árvore hierárquica de elementos, conforme observado na fígura abaixo:

 

 

Como voçê vê, o desenho acima pode representar a seguinte marcação em HTML

<!DOCTYPE html>
<html lang=”en-US”>
<head>
 
 BRINCANDO COM JAVASCRIPT
</head>
<body>
 

OI

ALGUM TEXTO AQUI

OUTRO TEXTO AQUI

</body> </html>

Então, o DOM é uma interface única provida pelo navegador de acesso á estes elementos em HTML, que permite tanto ao CSS quanto ao JAVASCRIPT acessarem elementos específicos do documento. Por exemplo: 




   

 

Caso queira saber um pouco mais, acesse: http://tableless.com.br/tenha-o-dom/

Outro conceito importante é o de evento. Eventos são, digamos, gatilhos disparados por uma ação. Por exemplo: Quando o usuário clica em um botão, ocorre o evento CLick no botão clicado. Quando a página acaba de ser carregada, é executado o evento load do documento. Voçê pode associar uma função ou qualquer instrução á um evento em específico, conforme demonstrado abaixo:


    

    /*OU */

    

   

Observe que, todo evento tem o prefixo on. Por exemplo: onClick, onBlur, etc.

Caso queire ter acesso á uma lista completa de eventos, acesse: http://www.marciobrasil.net.br/javascript-2/lista-completa-de-eventos-javascript.html

Voçê também pode criar funções, e associá-las á algum evento em específico, conforme demonstrado abaixo:

    
    
    

    /* OU */
    
    
   

 

Seguem alguns exemplos abaixo, que voçê pode baixar clicando aqui, e que serão explicados um á um. Isto é só pra voçê ter uma idéia do quanto javascript é importante e do que este pode fazer. 

1)  Mudar valor de um campo de texto

    

    <body>
     
Mudar valor de campo
</body>

 

2) validar formulário, pra não deixar passar formulário em branco

    
    <body>
    
Formulário não deixa passar em branco
</body>

 

3) enviar requisição ajax

Caso queira saber um pouco mais, acesse esta postagem: http://nunes-developer.blogspot.com.br/2014/04/o-que-sao-requisicoes-ajax.html

 

    
<body>
 
Fazendo requisição AJAX
</body>

 

4) Adicionar elementos á um container

    
    <body>
     
Adicionando campos dinamicamente
</body>

 

5) Mudar propriedades CSS de um elemento (Cor de fundo, largura, altura)

  
   <body>
    
Mudar propriedades CSS de um elemento (Cor de fundo, largura e altura)
</body>

 

Observe que, quando altera o campo altura, a altura da div muda. Isto porque o evento change do campo altura é associado á função mudaAltura. O mesmo acontece com os campos de mudança de largura e cor.

Como voçês viram, dá um pouco de trabalho programar em javascript puro, para realizar coisas relativamente simples. Por isso, já existem alguns frameworks javascript que podem agilizar seu processo. Porém, antes de aprender qualquer framework, é recomendável aprender  a linguagem, independente de qual seja.

Seguem abaixo alguns frameworks mais utilizados no mercado:

http://api.jquery.com

http://dojotoolkit.org/

 

Segue abaixo o código-fonte do exemplo: CÓDIGO-FONTE DO EXEMPLO

 

segunda-feira, 14 de abril de 2014

Dojo e Jquery: 2 frameworks javascript em alta

O Senhor o sustentará no leito da enfermidade; tu o restaurarás da sua cama de doença. (Salmos 41:3)

Programar em javascript, em alguns casos, é escrever N linhas de código. Se lembrar de todos os atributos e métodos de determinados elementos do DOM, ás vezes, é algo penoso. Por isso, foram criados alguns frameworks, que abstraem toda esta lógica de uma forma um pouco mais intuitiva. No nosso caso, falemos de 2 especificamente: Dojo e Jquery. 

Esta postagem visa introduzir, de forma concisa, um pouco da síntaxe e de como funciona cada um destes frameworks. Como voçê verá, ambos tem uma síntaxe simples e de fácil aprendizado. Lembrando que, antes de aprender qualquer framework, seja de javascript ou qualquer outra linguagem, é importante ter a base, conhecer a linguagem. Frameworks servem apenas como atalho pra agilizar o trabalho. Mas, antes de buscar atalhos, é necessário conhecer o trabalho. Há coisas que se pode fazer em javascript puro, mas não dá pra fazer em jquery ou em dojo. 

No exemplo de hoje, há 3 funcionalidades que são implementadas tanto em dojo quanto em jquery:

a) Mudar cor de uma div

b) Fazer requisição AJAX

c) Adicionar campos de texto

 

Se quizer, voçê pode ver como funciona cada uma destas implementações visualizando o código-fonte.

Os scripts em DOJO são executados normalmente no fim da página. Como devem ter acesso ao documento, primeiramente o documento deve ter sido carregado.

 

Segue abaixo o código-fonte do exemplo.

<!DOCTYPE html>
<html lang=”en-US”>
<head>

TESTE DE MESA




</head>
<body>
 

TESTE COM DOJO E JQUERY

</body> </html>

 

Segue o código completo no link abaixo

Código-fonte completo

 

É bom dar uma olhada nos sites oficiais de cada framework:

JQUERY

DOJO

 

sexta-feira, 11 de abril de 2014

DESIGN RESPONSIVO: Introdução e exemplo

A glória de Deus está nas coisas encobertas; mas a honra dos reis, está em descobri-las. (Provérbios 25:2)

Design responsivo já um termo que já está na boca de todo webdesigner que está ligado nas novidades. Mas, afinal de contas, o que é isto? Eu não sou nenhum expert no assunto, tanto é que, nem sou webdesigner, mas, em poucas palavras: Layout responsivo é um layout que se adequa á largura de tela de diversos dispositivos, sem, contudo, ser necessário criar um site inteiro adaptado pra isso. Ou seja, o código HTML deste site se mantém íntegro, deixando toda a parte da adaptação para o CSS. Voçê quer um exemplo? Este site aqui:  http://sergiolopes.org/.

Para ver funcionando, tente redimensionar a tela do navegador o menor possível. Notou alguma diferença? Percebeu que os elementos conseguem se adaptar á variação de largura, sem comprometer a visualização do usuário? Então, isso é DESIGN RESPONSIVO. Mas, qual é o segredo? Precisa recriar um site do zero? Não necessariamente, vai depender de cada caso. Mas, na maioria dos casos, basta apenas uma ligeira adaptação no CSS. Já existem frameworks que auxiliam neste aspecto? Sim. Entre eles posso citar o bootstrap, zurb, etc. Porém, é sempre importante conhecer um pouco o fundamento disso tudo, afim de não ficarmos tão dependentes de frameworks. 

Quando se lida com este assunto, normalmente aparecem duas palavras mágicas: User-agent e media-query. User-agent é uma frase que representa quem esté acessando o site. Ele vem através de um header de requisição. Identifica se o cliente é IPAD, IPHONE ou ANDROID, por exemplo. Media-query, pelo que entendi, calcula e redimensiona os elementos da página para se adequar á tela do usuário.

Para que os media-query entrem em ação, voçê deve, primeiramente, colocar o seguinte trecho de código no cabeçalho de seu site:


OK. Este é o primeiro passo. Sugiro que voçê crie uma página qualquer em HTML, com esta tag mágica, e acesse. Redimensione a janela do navegador até a largura mínima. Voçê pode observar que os elementos são automaticamente ajustados á largura da tela. Agora, voçê pode ir um pouco mais além: O menu  é horizontal quando a largura é maior, e, vertical, caso a largura fique menor. Voçê pode fazer isso através do código CSS, como veremos em seguida:

 @media screen and (max-width: VALOR){
  /* Código CSS aqui */
 } // Tratamento por tipo de largura

Como voçê vê, tu pode definir as propriedades CSS caso a largura de tela seja inferior ao atributo max-width, por exemplo. Voçẽ pode trabalhar também com min-width ou max-device-width (Largura máxima de dispositivo). 

Num exemplo que fiz, em tela normal, há a seguinte apresentação:

Agora, aplicando o conceito de DESIGN RESPONSIVO para telas com largura máxima de 600 px e 300 px, há a seguinte apresentação:

Pois bem, observe que, há algumas alterações á mais além de uma simples adaptação de layout:

a) O menu ficou vertical

b) A fonte ficou menor quando a largura ficou menor do que 600 px, e menor ainda quando ficou menor do que 300 px.

c) Divs com ids conteudo e plus passaram a ocupar a largura inteira do container principal.

 

Estas alterações acima são específicas para telas menores, e obedecem ao código CSS abaixo:

    @media screen and (max-width: 600px) {
  #left{
   float: none;
   width: 100%;
  }
  
 
  #content{
   float: none;
   width: 100%;
  }
  
  #plus{
   float: none;
   width: 100%;
  }
  
  #nav ul li{
   clear: both;
   display: block;
  }
 
  #nav{
   width: 100%; 
  }
  
  #nav ul li a{
   line-height: 100%;
   font-size: 80%;
  }
  
  h1{
   font-size: 80%;
  }
  
  #foot{
   font-size: 80%;
  }
  
  #imagens{
   width: 80%;
   margin-top: 2em;
  }
 
 }
 
 @media screen and (max-width: 300px) {

 
  #left{
   float: none;
   width: 100%;
  }
  
  #imagens{
   width: 80%;
   margin-top: 2em;
  }
  
  #plus{
   float: none;
   width: 100%;
  }
  
  #nav ul li{
   clear: both;
   display: block;
   margin-bottom: 0.5em;
  }
 
  #nav{
   width: 100%; 
  }
  
  #nav ul li a{
   line-height: 100%;
   font-size: 70%;
  }
  
  h1{
   font-size: 70%;
  }
  
  #foot{
   font-size: 70%;
  }
 
 }

   

 

Como voçê pode ver, a única diferença entre as adaptações de 600 e 300px é quanto ao tamanho da fonte.

Caso queira se aprofundar, sugiro a visita do seguinte site:

http://webdesignerwall.com/tutorials/responsive-design-with-css3-media-queries

 

Clique no link abaixo para baixar o código-fonte do exemplo:

Código do exemplo

 

 

 

 

segunda-feira, 7 de abril de 2014

O que são requisições AJAX?

Porque Moisés disse: Honra a teu pai e a tua mãe; e quem maldisser, ou o pai ou a mãe, certamente morrerá. (Marcos 7:10)

AJAX é um acrônimo para: Asynchronous JavaScript And XML. Mas, o que é isto? Antes de respondermos esta pergunta, levantemos a problemática que permitiu seu surgimento: quando o site deve buscar alguma informação no servidor, é necessário recarregar a página para ter esta informação acessível, o que é custoso para o usuário.

Por exemplo: Imaginemos que voçê acessa uma página na qual há 3 caixas de seleção: Continente, país e estado. Para nao ter que carregar todas as informações de país ou estado, e nem correr o risco de  ser selecionado um país que não faz parte do continente selecionado, quando voçê seleciona algum continente, logo o sistema deve buscar os países deste continente, e por aí vai. Do ponto de vista cliente-servidor, isto implicaria em recarregar o formulário com os valores á cada alteração de continente. Para evitar este fluxo de dados desnecessário, é que se faz necessário o uso do AJAX. O mesmo é constituído de um conjunto de tecnologias que permite que haja a comunicação entre o cliente (Página carregada pelo navegador) e o servidor (Que provê os dados e sempre retornar as páginas HTML). No nosso exemplo, quando voçê seleciona um continente, há um objeto em javascript que faz a conexão com o servidor para retornar os países desejados.  Este objeto literalmente acessa a página onde está a informação desejada, e retorna a resposta do servidor. Dependendo do navegador utilizado, este objeto pode ser o XMLHttpRequest (Navegadores modernos); ou o XMLHttp(IE7-). 

Normalmente, ou o servidor retorna uma simples string, ou código HTML. É melhor, que retorne em forma de algum formato de transporte de dados, como o JSON ou o XML, por exemplo, afim de ser fácil interpretar a resposta por parte da página que fez a requisição.  

No exemplo abaixo, há 2 formas de fazer requisições AJAX: Uma, com AJAX puro, sem uso de nenhum framework. O outro, é com Jquery, que é um framework javascript. A segunda forma é a mais fácil, e menos sujeita a erros, pois, funciona em todos os navegadores (Comigo, nunca deu errado). A primeira é mais sujeita a erros, pois, algumas funções podem funcionar em uns navegadores, e em outros requer uma certa adaptação. Além disso, atente-se que nem todos usam o XMLHttpRequest como objeto realizador de requisições AJAX. No caso do Jquery, isto tudo está encapsulado. 

No código abaixo, há um campo onde voçê faz a pesquisa e 2 botões, que te permite fazer requisições das duas formas. Ambas irão retornar a mesma lista de pessoas.

Caso queire aprender a fazer o mesmo com XML, sugiro o seguinte tópico: AJAX com XML

Quando se faz um requisição AJAX, podem ocorrer 2 coisas: O usuário não mexe na página até a requisição acabar, ou, ele mexe normalmente enquanto a página aguarda o fim da requisição. Quando ocorre o primeiro caso, dizemos que a requisição é síncrona.  No segundo, que ela é assíncrona. Qual é a melhor alternativa? Voçê, provavelmente diria que é a segunda, mas, depende de cada caso em particular. Se estiver asíncrona, voçê pode permitir que haja N requisições desnecessárias ao servidor, o que pode fazer com que o javascript "enlouqueça". 

Só pra lembrar: Nossos exemplos utilizam como linguagem do lado do servidor, o PHP.  

Segue abaixo o código-fonte do exemplo e algumas observações:


 <!DOCTYPE html>
<html lang=”en-US”>
<head>

Requisições AJAX








 

PROCESSAR NO CONTAINER ABAIXO UMA RESPOSTA AJAX

DADOS FICAM AQUI  

</body> </html>

Segue abaixo o código do lado do servidor:

<?php

/*
 * Dados virão em formato de JSON, que é um formato de transporte de dados, como o XML. 
 * 
 * */
header('Content-Type: application/json');

header('Cache-Control: no-cache');


$dados = array();
$x = 0;
$q = $_REQUEST['q'];

$dados[$x]['nome'] = "ALBERTO";
$dados[$x]['idade'] = "18";
$x++;

$dados[$x]['nome'] = "LUIZ";
$dados[$x]['idade'] = "19";

$x++;

$dados[$x]['nome'] = "LUIZA";
$dados[$x]['idade'] = "19";

if(!empty($q)){
 foreach($dados as $i => $v){
  if(!preg_match('/.*'.$q.'.*/',$dados[$i]['nome'])){
   unset($dados[$i]);
  }
 }
}

foreach($dados as $i => $v){
 $saida[] = $dados[$i];
}

sleep(2);

echo json_encode($saida);

 

Segue abaixo todos os códigos para voçê baixar:  EXEMPLO COMPLETO

 

 

 

 

 

 

terça-feira, 1 de abril de 2014

ASSEMBLY com NASM

Eu sou o pão vivo que desceu do céu; se alguém comer deste pão, viverá para sempre; e o pão que eu der é a minha carne, que eu darei pela vida do mundo. ( João 6:51 )

Antes de dar continuidade á leitura desta postagem, seria bom voçê já ter uma noção de programação. Já tem? Pois bem, então, esqueça. Estamos diante de um paradigma totalmente diferente. Assembly é uma linguagem considerada de baixo nível, ou seja, mais próxima da linguagem de máquina (Que só a máquina entende). PHP, JAVA e PYTHON podem ser consideradas linguagem de alto nível (Muito mais próximo do entendimento humano).  Ela tem algumas peculiaridades bem interessantes, que deixam qualquer programador acostumado com linguagens de alto nível de cabelo em pé.

Este tutorial serve para voçê ter uma noção de como trabalha e se desenvolve nesta linguagem tão clássica. Voçê terá uma noção teórica importante antes de por a mão na massa, e alguns exemplos para analisar e ir treinando.

Esta linguagem, hoje em dia, é utilizada para escrever softwares que se comunicam diretamente com o hardware, como, por exemplo: controle remoto, microcontrolador, etc.

Pra começar, voçê deve saber que, uma vez que o código-fonte já esteja sido escrito, ele precisa ser compilado, ou seja, precisa ser transformado num programa executável, para poder rodar. Os programas que fazem este papel chamam-se ASSEMBLADORES. Assemblador, em poucas palavras, converte a linguagem assembly em linguagem de máquina, por processo conhecido como montagem. A máquina só entende agrupamentos de bits 0 e 1. O assemblador converte o seu código em bits 0 e 1, compreensíveis ao seu computador.

Para utilizar nossos exemplos, utilizaremos o assemblador NASM, que pode rodar tanto em WINDOWS quanto em LINUX. Está disponível no seguinte endereço:  Site oficial da NASM.

Sugiro que baixe e instale este programa antes de dar continuidade á este artigo.

Pois bem, antes de continuar, vamos entender o que é registrador, pois, voçê vai manipulá-los direto. Registrador é a unidade de armazenamento interno do processador. Em poucas palavras, são os espaços para manipular dados. Normalmente, através das  instruções em assembly, estes registradores são manipulados. Fique esperto que, alguns registradores tem finalidade específica. Por exemplo: EAX pode ser usada para realização de operações aritméticas, mas também é utilizadas para fazer chamadas ao núcleo do sistema operacional, como por exemplo: Exibir algo na tela, finalizar execução, etc. Segue ao lado uma lista destas interrupções que se deve setar no registrador EAX:  Lista de interrupções.

É preciso lembrar que, existem registradores de 32 bits, de 16 bits e de 8 bits. Por exemplo: EAX é um registrador acumulador de 32 bits, AX é o mesmo só que em 16 bits; AL e AH  são o mesmo em 8 bits. Neste caso, AX é composto por AX e AL, tendo 8 bits cada. Uma explicação mais detalhada sobre cada registrador voçê vê em:  Lista de registradores

Agora sim, vamos por  a mão na massa. Lembrando que, cada assemblador possui uma estrutura própria de programa. No nosso caso, a estrutura própria é a seguinte:

section .data
 ; Dados inicializados
section .bss
 ; Dados não-inicializados

section .text
 ; Conteúdo do programa
global _start ; Definindo como global, para ser interceptado por alguma biblioteca em C
 
_start:
 ; Conteúdo mesmo é aqui

 

Pois bem, segue abaixo um programa que recebe dois números (Que voçê ira digitar), e irá retornar a soma.

 

 

 

section .data
 ; Onde ficam dados inicializados. Normalmente o padrão para declarar variável é:
 ; NOME TIPO (POde ser DB-BYTE,DD-DOUBLE WORD,DW-WORD) VALOR
 p DB "Digite um número: "
 len_p  equ $-p ; Tamanho da variável p. É necessário para passar ao registrador edx
 pp DB "Digite o segundo número: "
 len_pp equ $-pp

 m DB "Resultado: "
 len_m equ $-m




section .bss
 ; Reservando espaço de 1 byte para posterior uso. No nosso caso, troca-se apenas o D por RES
 numero RESB 2
 resultado RESB 2
 segundo RESB 2

section .text

global _start

_start:
 ; Qualquer instrução do trecho de programa _start ficará aqui. Neste caso, _start é um rótulo dado á este trecho específico de programa. _start é o fluxo principal do programa


; Em instruções que se exibe algo na tela. O EAX possui valor 4, que é a interrupção para se exibir algo na tela. EDX armazena a quantidade de caracteres a serem exibidas
 mov edx, len_p ; Tamanho da string que será exibir
 mov ecx, p ; Conteúdo da mensagem
 mov eax, 4 ; Chamada ao núcleo do sistema para exibir algo na tela
 mov ebx, 1 ; 0 = NADA; 1 = STDOUT (Saída); 2 = STDIN (Entrada)  
 int 0x80 ; CHamada ao núcleo do sistema, que recebe o valor contido em eax para executar

 ; Trecho abaixo  trata de receber o número digitado pelo usuário e o armazena na variável numero
 mov eax, 3 ; Indica ao núcleo que é pra receber um valor preenchido pelo usuário
 mov ebx, 2 ; STDIN (Preparar o programa para uma entrada de texto)
 mov edx, 1 ; Tamanho do campo recebido
 mov ecx, numero ; Armazena a entrada na variável numero
 int 0x80 ; Interrupção


 ; Exibindo na tela a segunda mensagem
 mov edx, len_pp
 mov ecx, pp
 mov eax, 4
 mov ebx, 1
 int 0x80

 ; Recebendo o segundo parâmetro
 mov eax, 3
 mov ebx, 2
 mov edx, 2
 mov ecx, segundo
 int 0x80

 ; Exibindo terceira mensagem
 mov edx, len_m
 mov ecx, m
 mov eax, 4
 mov ebx, 1
 int 0x80


 ; Efetuando a soma
 mov bl, [segundo] ; Atribuindo o valor da variável segundo ao registrador BL
 mov al, [numero] ; Atribuindo o valor da variável numero ao registrador AL
 
 sub bl, '0' ; Convertendo valor de ASCII em decimal para fins de operação


 add al, bl ; Efetuando a soma, sendo que, o resultado fica armazenado no registrador al
 
 mov [resultado], al ; Movendo o valor de al na variável resultado


 ; Trecho abaixo exibe o resultado na tela
 mov ecx, resultado
 mov edx, 2
 mov eax, 4
 mov ebx, 1
 int 0x80

 mov eax,1 ; SAIDA
 int 0x80

 

Para compilar  o programa acima, copie e cole o código acima em seu editor de texto, e salve com o nome de soma.asm. Todo código-fonte em assembly deve ter a extensão .asm.

Em seguida, execute os seguintes comandos em linha de comando:

 

nasm -f elf64 soma.asm // Para compilar
ld soma.o -o soma // Para gerar o executável
./soma   // Para executar

// Lembrando que o comando acima serve para LINUX, não sei como deve ser no WINDOWS

 

Segue outro programa que calcula a área de um triângulo tendo a base e a altura da mesma.

 

 

section .data
 msg DB "Digite a base do triangulo" ,0xa
 l_msg equ $ - msg
 msg2 DB "Digite a altura do triangulo", 0xa
 l_msg2 equ $ - msg2
 msg3 DB "Resultado", 0xa
 l_msg3 equ $ - msg3

 divisor DB '2'
 
section .bss
 base RESB 1
 altura RESB 1
 area RESB 2

section .text

global _start
 
_start:
 mov eax, 4
 mov ebx, 1
 mov edx, l_msg
 mov ecx, msg
 int 0x80

 mov eax, 3
 mov ebx, 2
 mov ecx, base
 mov edx, 2
 int 0x80

 mov eax, 4
 mov ebx, 1
 mov edx, l_msg2
 mov ecx, msg2
 int 0x80

 mov eax, 3
 mov ebx, 2
 mov ecx, altura
 mov edx, 2
 int 0x80


 ; Multiplicando base e altura
 sub [base], byte '0'
 sub [altura], byte '0'
 mov al, [base]
 mov bl, [altura]
 mul bl  ;AL = AL * BL  OU AX = AL * BL
 
 ; Dividindo o produto por 2
 sub [divisor], BYTE '0' ; Conversão de decimal para ASCII

 mov bl, [divisor]

 div bl ; Divisão do acumulador(AX) pelo divisor (bl) . No AX, está o resultado da multiplicação 
 add al, '0'
 mov [area], al

 mov eax, 4
 mov ebx, 1
 mov edx, l_msg3
 mov ecx, msg3
 int 0x80

 mov eax, 4
 mov ebx, 1
 mov edx, 2
 mov ecx, area
 int 0x80
 
 jmp sair

sair:
 mov eax, 1
 mov ebx, 0
 int 0x80

 

 

 

Caso queira conhecer um pouco mais desta linguagem, sugiro os seguintes links abaixo:

 

Tutorial de ASSEMBLY Uma breve introdução ao ASSEMBLY

Segue abaixo uma lista de exemplos que fiz para aprender a usar esta ferramenta:

Outros exemplos

sexta-feira, 7 de março de 2014

GIT: Ferramenta para controle e versionamento de projetos

O que segue a justiça e a beneficência achará a vida, a justiça e a honra. (Provérbios 21:21)

GIT é um programa bastante útil para gerenciamento de fluxos de trabalho em projetos de desenvolvimento. Por exemplo: Em um equipe de 3 desenvolvedores, em que cada um é responsável por uma funcionalidade específica do sistema, é necessário que haja um controle do que cada um está fazendo. Por exemplo: Que arquivo cada um alterou? Seria interessante que os membros desta equipe não consiga editar um mesmo arquivo ao mesmo tempo. 

Para resolver problemas assim é que foi criado o GIT. Git é um programa de versionamento criado e mantido inicialmente por Linus Torvald -- O pai do Linux. Foi elaborado como sendo controle de versões do sistema operacional LINUX e armazenamento do histórico de atualizações, de tal forma que era possível, por exemplo, recuperar as alterações feitas em determinada versão, identificar os usuários responsáveis por determinadas alterações, etc.

Antes de partir para a prática, é muito importante obter um pouco de teoria:

Imaginemos que tenhamos um fluxo de trabalho normal chamada A, que seria o site de produção, onde é feita a manutenção do sistema. Aí, voçê cria um fluxo paralelo, chamado B, que representa a criação de alguma nova funcionalidade. Daí, A e B seguem paralelos na linha do tempo. Só que, quando B está concluído, voçê deve juntar as alterações de B e as alterações de A. Pois, B não tem as atualizações de A e vice-versa. Então, o que voçê faz: Primeiro adiciona o que voçê fez no A em B, e depois o contrário. Neste caso, A e B são branchs (ramificações do projeto) e o cruzamento ou a equivalência de A e B é chamado de MERGE, que traz a funcionalidade nova em A mantendo o que já foi feito. Isto está bem ilustrado na figura abaixo: 

Pois bem, é quase isso o que faremos no exemplo seguinte: Criamos 3 repositórios (Cada repositório é um diretório onde fica cada BRANCH), sendo um repositório central (Não tem arquivos, apenas armazena informações do fluxo principal), um físico (Fluxo principal) e outro do usuário. Para começar, crie um diretório feito unicamente para fazer os testes. Defina de antemão, quais serão os diretórios utilizados (Um físico, um de usuário e outro central). Mas, crie apenas o diretório físico. 

Por exemplo, no meu caso caso, está assim a estrutura de diretórios:

 

  REPOSITORIO=/home/teste/git-projetos/repo/
         DIRETORIO_FISICO=/home/teste/git-projetos/repo-fisico/
         DIRETORIO_USUARIO=/home/teste/git-projetos/repo-user/

 

Porém, eu tinha criado apenas o diretório físico. 

O esquema que será feito é o seguinte: O usuário apenas poderá fazer alterações no seu diretório (DIRETORIO_USUARIO). Em seguida, caso as alterações já tenham sido feitas, ele pode subir as mesmas para o repositório central (REPOSITORIO). Daí, estas alterações são replicadas para  DIRETORIO_FISICO, que representa o diretório de produção, por exemplo. 

 

Pra começar instale o git pelo comando, caso esteja usando linux fedora

yum install git

 

Do contrário, verifique no site abaixo (Como baixar e instalar no seu SO específico).

http://git-scm.com/downloads

Primeiramente,  vá pela linha de comando, em DIRETORIO_FISICO, definido inicialmente:

 

git init

 

 

Com este comando, voçê instancia o git para seu projeto em particular. Se não tiver nada, crie um arquivo neste diretório. Se tiver, apenas digite "git status".

Note que há uma mensagem +/- assim:

 

# On branch master
# Untracked files:
#   (use "git add ..." to include in what will be committed)
#
# teste.php
nothing added to commit but untracked files present (use "git add" to track)

 

Pois bem, isto indica que há uma diferença entre o que está no diretório físico e o que consta na referência do seu BRANCH. Ou seja, no seu BRANCH não consta nada. Se quizer, voçê pode criar, para um mesmo diretório físico, vários BRANCHS, mas, como padrão, só é usado o BRANCH master, que é a ramificação usada neste diretório. Para atualizar seu BRANCH, execute o seguinte comando:

 

git add -A

 

 

git commit -am "Gerando primeiro commit"

 

Com a primeira instrução acima, voçê adicionou o arquivo recém-criado ao BRANCH corrente. E com a segunda, voçê passou as alterações do diretório físico ao BRANCH.  O primeiro é pra passar o arquivo ao BRANCH, o segundo é passar o conteúdo do arquivo ao BRANCH. O conteúdo e o nome do arquivo referenciado são guardados pelo BRANCH. 

 

Agora, iremos criar um repositório central, que armazenará todas as atualizações consolidadas do projeto:

 

git clone --bare DIRETORIO_FISICO REPOSITORIO

 

Como voçê viu,  com a opção --bare, o repositório não conterá arquivos físicos, apenas os BRANCHS do repositório e suas referências. Isto porque teoricamente, ninguém irá editar ou mexer neste repositório.

Depois, é necessário dizer ao DIRETORIO FISICO que toda alteração feita irá para o REPOSITORIO e que, antes de subir qualquer coisa para lá, é preciso antes baixar alterações que possam ser feitas lá.

 

git remote add   -m master -t master -f origin  REPOSITORIO

 

Com o comando acima, o repositório central será apelidado de 'origin' e que os BRANCH master local irá se comunicar com o BRANCH master do repositório central.

Faça qualquer alteração no diretório físico e execute o comando COMMIT 

 

git commit -am "Segundo commit"

 

Note que havia uma diferença entre o que está no seu diretório físico e o que está no seu BRANCH do diretório físico. Com o segundo commit, acaba-se esta diferença, pois, voçê sobe alterações para o BRANCH. Após o BRANCH estar atualizado, voçê deve verificar se não há atualizações por parte do seu repositório central e subir atualização do BRANCH para o repositório central. 

 

git pull origin master

 

 

git push

 

 

Voçê acabou de subir alterações do teu BRANCH local para o BRANCH remoto do repositório central.  O comando PULL faz com que o BRANCH local puxe alterações do BRANCH remoto, cruzando-os pra ver se não dá conflito. Isto é o que chamamos de MERGE. 

Agora crie um repositório de usuário, como cópia do repositório central.

 

git clone  REPOSITORIO DIRETORIO_USUARIO

 

Agora, em seu repositório de usuário, voçê vai criar um arquivo qualquer e subí-lo ao seu BRANCH local:

 

git add ARQUIVO

 

 

git commit -am "Comit de diretório local"

 

 

git pull origin master

 

 

 

git push -u origin master

 

Após voçê ter subido alterações ao repositório central, acesse o DIRETORIO_FISICO.  Verifique se há atualizações por parte do repositório central -- Com certeza há. Observe que o arquivo criado no DIRETORIO_USUARIO já veio no seu DIRETORIO_FISICO. 

 

git pull origin master

 

Como visto, o GIT é uma ferramenta excelente para controle de versionamento e cruzamento de fluxos de trabalho num só fluxo consolidado. 

Em alguns casos, quando se executa o comando PULL, pode ocorrer de haver algum conflito. Neste caso, execute "git mergetool", escolha o editor de sua preferência e corrija o possível conflito. Faça o commit e teste todas as funcionalidades. 

Se quizer visualizar o histórico de commits em um dado repositório, digite "git log".

Observe que cada atualização (commit) tem um identificador único. Como demonstrado abaixo

 

commit 5db02604d00739ccafd295654c3e7a0d8acb0ac7
Author: Wagner Nunes 
Date:   Fri Mar 7 08:59:22 2014 -0300

    Comitando criação de arquivo vazio

 

Se voçê digitar "git reset IDENTIFICADOR_UNICO", o branch voltará ao estado em que estava neste commit. Aí, para replicar esta alteração no seu diretório, é só digitar "git checkout  -A", ou "git checkout ARQUIVO". -A é uma opção que indica que todos os arquivos vão estar equivalentes ao que está no BRANCH. 

Espero que voçê tenha entendido e gostado desta postagem. 

Caso tenha alguma sugestão, não deixe de incluir em seu comentário.

 

Caso queira saber um pouco mais e queira explorar esta ferramenta, sugiro o seguinte link, que é o da documentação oficial da ferramenta:

http://git-scm.com/doc

 

 

 

 

 

 

 

 

 

 

 

 

 

segunda-feira, 25 de novembro de 2013

HTML5: Animações com Canvas

HTML5: Animações com CANVAS
           Olá! Segue agora uma postagem sobre um tema interessante: CANVAS. Mas, o que é isso? Como se sabe, a versão do HTML reinante nos dias de hoje é a versão 4. Porém, muitas grandes desenvolvedoras, no intuito de melhorar funcionalidades existentes e incluir novas, estavam elaborando uma nova versão pro HTML, o HTML5. 
Entre as novas possibilidades, destaca-se:
1) Conformidade com as especificações do CSS3
2) Reprodução de determinados conteúdos multimídia (Vídeo, audio) sem necessidade de plugins.
3) Possibilidade de armazenamento de cache
4) Tags novas (Canvas, video, audio, nav, sidebar, etc)

Pois bem! Dentre estas tags novas, falaremos agora do canvas. Mas, o que é isto? Em poucas palavras, ela permite que, sejam criadas animações wm 2D apenas com uso de javascript. É como se voçê criasse animações FLASH diretamente em javascript. Enfim, nota-se que esta tecnologia abre um grande leque de possibilidades para designers e programadores de jogos. 
Apenas como aprendizado, sugiro que leia o seguinte tutorial, que me serviu de portas para esta novidade, que agora compartilho:
Tutorial básico de CANVAS

Agora, segue abaixo algumas coisas (Bem toscas!),  sobre o que consegui fazer esta tecnologia:
Jogo de duas bolas
Ponteiro de relógio

Caso queira o link para ambos os testes, baixe-os, clicando no link abaixo:

Segue abaixo o código do primeiro exemplo, no qual, como voçê pode ver, é criado, pixel á pixel, todo o cenário e os personagens.
 <!DOCTYPE html> 
<html> 
<head> 
 Testes com CANVAS 
 
 
 
  
  
 
  

Controlando um boneco com CANVAS

Seu navegador não suporta HTML5

</body> </html>
No arquivo draw.js, estão todas as funções e módulos para controle da animação.

 
/*Toda vez que é  executado algo na tag CANVAS, deve-se instanciar o objeto especificado na variável context abaixo
 * pertencente á própria tag CANVAS. 
 * */
function carregaContexto(id){
   var elemento = document.getElementById(id);
   var context = elemento.getContext("2d");
   if(context){
   return context;
   }else{
   return false;
   }
  }
 /* Função abaixo para desenhar um triângulo simples */
function drawTriangulo(x,y,tamX,tamY){
   var contexto = carregaContexto(document.getElementsByTagName('canvas')[0].id);
   x = parseInt(x);
   y = parseInt(y);
   tamX = parseInt(tamX);
   tamY = parseInt(tamY);
   if(contexto){
    contexto.fillStyle = "#00FF00";
    contexto.moveTo(x-tamX,tamY);
    contexto.lineTo(tamX+x,tamY);
    contexto.lineTo(x,y);
    contexto.fill();
   }
  }
/* Função abaixo necessário para desenhar rostos */
function drawRosto(x,y,r){
 x = parseInt(x);
 y = parseInt(y);
 r = parseInt(r);
 var contexto = carregaContexto(document.getElementsByTagName('canvas')[0].id);
 if(contexto){
  contexto.fillStyle = "#FFE4B5";
  contexto.moveTo(x,y);
  contexto.arc(x,y,r,0,Math.PI*2,false);
  contexto.fill();
  //Desenhando os olhos
  contexto.fillStyle = "#000000";
  contexto.moveTo(x-7,y-4);
  contexto.fillRect(x-7,y-4,4,4);
  contexto.moveTo(x+7,y-4);
  contexto.fillRect(x+7,y-4,4,4);
  //Desenhando a boca
  contexto.beginPath();
  contexto.strokeStyle = "#FF0000";
  contexto.moveTo(x-4,y+10);
  contexto.lineTo(x+5,y+10);
  contexto.stroke();
 }
}
/* Função para se desenhar qualquer forma quadrada */
function drawQuadrada(x,y,tamX,tamY,cor){
 x = parseInt(x);
 y = parseInt(y);
 tamX = parseInt(tamX);
 tamY = parseInt(tamY);
 var contexto = carregaContexto(document.getElementsByTagName('canvas')[0].id);
 if(contexto){
  contexto.fillStyle = cor;
  contexto.beginPath();
  contexto.moveTo(x,y);
  contexto.fillRect(x,y,tamX,tamY);
  contexto.fill();
 }
}

/* Função abaixo desenha um sapato */
function drawSapato(x,y,tamX,tamY,cor){
 x = parseInt(x);
 y = parseInt(y);
 tamX = parseInt(tamX);
 tamY = parseInt(tamY);
 var contexto = carregaContexto(document.getElementsByTagName('canvas')[0].id);
 if(contexto){
  contexto.fillStyle = cor;
  contexto.beginPath();
  contexto.moveTo(x,y);
  contexto.fillRect(x,y,tamX/2,tamY/2);
  contexto.fill();
  contexto.beginPath();
  contexto.moveTo(x+tamX/2,y-tamY/2);
  contexto.arc(x+tamX/2,y+7,9,Math.PI*1.5,Math.PI*0.5,false);
  contexto.fill();
 }
}

/* Função para desenhar mãos */
function drawMao(x,y,r,cor){
var contexto = carregaContexto(document.getElementsByTagName('canvas')[0].id);
 if(contexto){
  contexto.fillStyle = cor;
  contexto.beginPath();
  contexto.moveTo(x,y);
  contexto.arc(x,y,r,0,Math.PI*2,false);
  contexto.fill();
  contexto.beginPath();
  contexto.moveTo(x,y-r);
  contexto.quadraticCurveTo(x+50,y-50,x+2,y+5);
  contexto.moveTo(x,y-r);
  contexto.quadraticCurveTo(x+5,y-100,x-20,y+5);
  contexto.fill();
 }
}

/* Função para desenhar relógio*/
function drawRelogio(x,y,r,cor){
 x = parseInt(x);
 y = parseInt(y);
 r = parseInt(r);
 var contexto = carregaContexto(document.getElementsByTagName('canvas')[0].id);
 if(contexto){
  contexto.fillStyle = cor;
  contexto.beginPath();
  contexto.moveTo(x,y);
  contexto.arc(x,y,r,0,Math.PI*2,false);
  contexto.fill();
  //Marcando os números do relógio
  contexto.fillStyle = "#FFFF00";
  contexto.fillText("12",x,y-(r-10));
  contexto.fillText("3",x+(r-10),y);
  contexto.fillText("6",x,y+(r-10));
  contexto.fillText("9",x-(r-10),y);
  //Desenhando o ponteiro
 
 }

}

/*Função abaixo move o braço do boneco com base no clique na mão do mesmo */

function moveBraco(x,y,tamB,bX,bY){
 var contexto = carregaContexto(document.getElementsByTagName('canvas')[0].id);
 if(contexto){
  x = parseInt(x);
  y = parseInt(y);
  tamB = parseInt(tamB);
  
  
  if(y >= bY){
   if(x >= bX){
    c = 2;
   }else{
    c = 4;
   }
  }else{
   if(x >= bX){
    c = 8;
   }else{
    c = 6;
   }
  }
  
  var minX = bX - tamB-15;
  var minY = bY-tamB;
  var maxX = bX + tamB-15;
  var maxY = bY+tamB;
  cX = (xmaxX?maxX:x));
  cY = (ymaxY?maxY:y));
  //Rotação do braço com base nas coordenadas
  drawQuadradaComRotacao(bX,bY,cX,cY,tamB,"#2F4F4F");
  //alert(cX + "-" + minX);
  drawMao(cX,cY,20,"#F0E68C");
 }
}
/*Desenhando o braço, para que sei posicionamento esteja relativo ao posicionamento da mão*/
function drawQuadradaComRotacao(x,y,cX,cY,tamB,cor){
 x = parseInt(x); //Coordenadas do braço
 y = parseInt(y);
 cX = parseInt(cX); // Coordenadas c são coordenadas da mão. São passadas como parâmetro para que o braço possa acompanhar a mão
 cY = parseInt(cY);
 tamB = parseInt(tamB); // Tamanho do braço
 var contexto = carregaContexto(document.getElementsByTagName('canvas')[0].id);
 if(contexto){
  contexto.fillStyle = cor;
  contexto.beginPath();
  contexto.moveTo(x,y);
  //Setar a coordenada do braço para que acompanhe a mão
  contexto.lineTo(cX,(cY-2));
  contexto.lineTo(cX,(cY-2) + tamB);
  contexto.lineTo(x,y + tamB);
  contexto.fill();
 }
}

/*Desenhando um corpo inteiro*/
function desenhoCorpo(){
 var contexto = carregaContexto(document.getElementsByTagName('canvas')[0].id);
 if(contexto){
 
 //Desenho de um corpo humano
   drawRosto(165,50,25);
   //Pesco词
   drawQuadrada(150,70,30,20,"#FFE4B5");
   //Barriga
   
   drawQuadrada(80,100,45,30,"#2F4F4F");
   
   //Perna direita
   drawQuadrada(130,210,30,100,"#000000");
   
   
   //P顥squerdo
   drawSapato(130,310,60,30,"#A52A2A");
   //M䯠direita
   drawMao(75,115,20,"#F0E68C");
   //Barriga
   drawQuadrada(125,90,80,120,"#2F4F4F");
   
   
   //Perna esquerda
   /*drawQuadrada(170,210,30,100,"#000000");
   //Pé ireito
   drawSapato(170,310,60,30,"#A52A2A");*/
   //Ch䯍
   drawQuadrada(0,325,document.getElementsByTagName('canvas')[0].width,document.getElementsByTagName('canvas')[0].height-310,'#8B4513');
   
  
 }
 
}

/* Função para mover o pé */
function movePe(x,y,tamX,tamY,cX,cY){
 var contexto = carregaContexto(document.getElementsByTagName('canvas')[0].id);
 if(contexto){
  //Desenhando a perna com base nas coordenadas c
  contexto.fillStyle =  "#000000";
  contexto.moveTo(x,y);
  contexto.lineTo(cX,cY);
  contexto.lineTo(cX+tamX,cY);
  contexto.lineTo(x+tamX,y);
  contexto.fill();
  drawSapato(cX,cY,60,30,"#A52A2A");
  
 }
}
/*Limpar a tela inteira. Executada quando se encerra o jogo, ou para que tudo se inicie do zero*/
function limpaTela(){

 drawQuadrada(0,0,document.getElementsByTagName('canvas')[0].width,document.getElementsByTagName('canvas')[0].height,'#FFFFFF');
}

No arquivo boneco.js, tem os atributos e métodos próprios dos personagens.
 
/*
 Criando o objeto Boneco, que será o responsável pelas movimentações no cenário(boneco.html)
*/


function Boneco(cor){
 this.cor = cor;
 this.dX = 0; //Coordenada X atual do objeto
 this.dY = 0; // Coordenada Y atual do objeto
 this.s = "d"; //Sentido do objeto: Pode ser d(Direito) ou e(Esquerdo)
 this.minY = 240; // Coordenada Y m[inima(Ponto Y do chão)
 this.sY = "C"; //Sentido horizontal do objeto
 this.maxY = 0;
}
/*Gambiarra abaixo para associar o método constroe á classe Boneco
 * Forma alternativa de definir métodos á uma classe
 * */
Boneco.prototype.constroe = function(x,y){
 this.dX = x;
 this.dY = y;
 this.maxY = 320;
 var contexto = carregaContexto(document.getElementsByTagName('canvas')[0].id);
 if(contexto){
  contexto.beginPath();
  contexto.fillStyle = this.cor;
  contexto.arc(x,y,20,0,2*Math.PI,false);
  contexto.fill();
  //Desenhando os olhos
  contexto.beginPath();
  contexto.fillStyle = "#FFFFFF";
  contexto.moveTo(x+2,y-2);
  contexto.arc(x+2,y-2,3,0,2*Math.PI,false);
  contexto.fill();
  
  contexto.beginPath();
  contexto.fillStyle = "#FFFFFF";
  contexto.moveTo(x+8,y-4);
  contexto.arc(x+8,y-4,3,0,2*Math.PI,false);
  contexto.fill();
 }
}

/*
 Método abaixo executa move o objeto Boneco para os lados. Quando o objeto está no limite(Final do caminho), seu sentido é alterado(Esquerdo ou Direito).
 Como terceiro parâmetro,  recebe o array de obstáculos a serem ultrapassados.
 Se x estiver entre propriedades minX e maxX
  Se for menor ou igual á minY do obstáculo
   Seta atributo dY como sendo equivalente á minY.
  Senão
   Se sentido é igual á direito
    Seta dx como equivalente á minX
   Senão
    Seta dx como equivalente á maxX
 Senão
  Se dx for maior do que maxX e sentido for D OR se dx for menor do que minX e sentido for E
   Seta dY como maxY(Toca o solo)
  
*/

Boneco.prototype.andar = function(dx,s,obstaculos){
 var  maxX = document.getElementsByTagName('canvas')[0].width;
 this.s = s;
 if(this.dX >= maxX){
   this.s = "e";
  }else if(this.dX <= 10){
   this.s = "d";
  }
   for(obs in obstaculos){
    if( (obstaculos[obs].minX <= this.dX)  &&   ( this.dX <= obstaculos[obs].maxX)){
     if(this.dY <= obstaculos[obs].minY){
      this.dY = obstaculos[obs].minY;
     }else{
      if(this.s == "d"  && (this.dX <= obstaculos[obs].minX + obstaculos[obs].width/2)){
       this.dX -= 2*dx;
       return;
      }else if(this.s == "e" && (this.dX >= obstaculos[obs].maxX - obstaculos[obs].width/2)){
       this.dX += 2*dx;
       return;
      }
     }
    }else if((this.dX > obstaculos[obs].maxX && this.s == "d") || (this.dX < obstaculos[obs].minX && this.s == "e")){
     this.dY = this.maxY;
    }
   }
 if(this.s == "d"){
  this.dX += dx;
 }else{
  this.dX -= dx;
 }
}

/*
 Método abaixo faz o objeto pular. Quando o usuário clica na barra de espaço, o usuário pula á uma altura maior do que a caixa 
*/

Boneco.prototype.pular = function(){
 var maxY = this.maxY;
  if(this.dY >= maxY){
   this.sY = "C";
  }else if(this.dY <= this.minY){
   //this.dY = this.minY;
   this.sY = "B";
  }
  if(this.sY == "C"){
   this.dY -= 20;
  }else if(this.sY == "B"){
   this.dY += 20;
  }
}


/*
 Método abaixo serve para criar obstáculos na tela.
*/

function Obstaculo(x,y,lar,tam,cor){
 lar = parseInt(lar);
 x = parseInt(x);
 y = parseInt(y);
 //Desenhando o objeto
 drawQuadrada(x,y,lar,tam,cor);
 this.minY = y;
 this.minX = x;
 this.maxX = x+lar;
 this.width = lar;
 this.altura = tam;
}

Quando se usa CANVAS, pode-se notar que os desenhos são feitos pixel-á-pixel. Ou seja, são feitos especificando as coordenadas de cada fígura. Por isso, apesar de o carregamento ser bem mais rápido, se comparado com o SVG (Mesmo propósito que o CANVAS, porém, mais fácil e menos flexível), demanda muito esforço de desenvolvimento. Além disso, é necessário que se tenha a disposição, um conjunto de funções básicas como: Andar, pular, tratamento de colisões; caso desenvolva animações mais complexas. Do contrário, estará perdendo tempo com detalhes que podem muito bem ser encapsulados.


Espero que tenham gostado, e, se gostou, poste seu comentário. Se não, manda sua crítica, para que possamos sempre melhorar.

Abraços