sexta-feira, 24 de agosto de 2018

Manual VUE - Substituição de variáveis

Durante a execução de um programa, no interior da memória do dispositivo eletrônico programável, uma variável de programa só tem seu valor modificado se estiver à esquerda de uma atribuição. Na primeira fase da Tecnologia de Informação, existia um programa em execução e uma console de inspeção das variáveis deste programa. Os resultados também eram apresentados na console.

Na segunda fase de programação, separou-se o programa do Banco de dados.

Depois, na terceira fase da Tecnologia de Informação, existia uma interface permanente de apresentação – não mais uma console de múltipla atribuição – da informação, da forma mais dinâmica possível. Para alterar o valor das variáveis, era preciso que um evento ocorresse. Mas, mesmo assim, o valor exibido na interface poderia estar desatualizado em relação ao valor da memória, pois era preciso um esforço de programação para sincronizar o calculado com o exibido.

E agora, na quarta fase da Tecnologia da Informação, frameworks que operam na interface foram desenvolvidas para sincronizar o calculado com o exibido. Tal é o caso do VUE, entre outros, como Angular, React, Kendo e jQuery. Poderíamos deixar o jQuery em uma posição intermediária entre a terceira e quarta fase, pois ele não implementa uma interface reativa tão eficiente quanto os demais.

Confeccionamos um manual que explica a substituição destas variáveis:

BAIXAR

sexta-feira, 10 de agosto de 2018

Manual VUE - Variáveis Reativas

Durante a execução de um programa, no interior da memória do dispositivo eletrônico programável, uma variável de programa só tem seu valor modificado se estiver à esquerda de uma atribuição. Na primeira fase da Tecnologia de Informação, existia um programa em execução e uma console de inspeção das variáveis deste programa. Os resultados também eram apresentados na console.

Na segunda fase de programação, separou-se o programa do Banco de dados.

Depois, na terceira fase da Tecnologia de Informação, existia uma interface permanente de apresentação – não mais uma console de múltipla atribuição – da informação, da forma mais dinâmica possível. Para alterar o valor das variáveis, era preciso que um evento ocorresse. Mas, mesmo assim, o valor exibido na interface poderia estar desatualizado em relação ao valor da memória, pois era preciso um esforço de programação para sincronizar o calculado com o exibido.

E agora, na quarta fase da Tecnologia da Informação, frameworks que operam na interface foram desenvolvidas para sincronizar o calculado com o exibido. Tal é o caso do VUE, entre outros, como Angular, React, Kendo e jQuery. Poderíamos deixar o jQuery em uma posição intermediária entre a terceira e quarta fase, pois ele não implementa uma interface reativa tão eficiente quanto os demais.

Confeccionamos um manual que explica a fundo estas variáveis:

BAIXAR

terça-feira, 31 de julho de 2018

Manual VUE - Processo de compilação

O VUE é uma framework muito flexível, construída em javascript, para implementar o MVC (Model View Controller) em aplicações Web.

Construímos esta apostila que vai fundo no código VUE para que você possa compreender o processo de compilação da função que renderiza a página Web.

Deixamos abaixo um link para que você possa baixar o trabalho.

Coloque suas contribuições nos comentários para completar o trabalho.

BAIXAR

domingo, 22 de abril de 2018

Conta OneNote e OneDrive Microsoft dando erro 80004005

Há dias estamos tentando entrar em contas OneNote do OneDrive da Microsoft, sem sucesso.

Ao tentar o login, surge o erro 80004005, característico do VBscript quando existem vários tipos de erros de acesso. Mesmo com recuperação e desbloqueio da conta, o erro não é sanado.

Mesmo colocando a mesma conta de uso do OneNote como default no Android, o problema não foi resolvido.

Perguntamos:

Como um dos maiores conglomerados de software básico e de aplicativos e ferramentas para computadores pode se dar ao luxo de apresentar um erro deste numa aplicação na nuvem ?

É muita falta de profissionalismo, que mostra que a Microsoft já se especializou em ganhar dinheiro, e não em apresentar produtos de qualidade.

Vamos continuar usando o Evernote ou produtos Google, como Google Keep, que possuem muito mais estabilidade e confiabilidade.

A Microsoft está mesmo indo para o buraco. Cresceu e virou um câncer.

sexta-feira, 6 de outubro de 2017

Construindo um PARSER em javascript - IX - Notação científica e Funções

Nos posts anteriores, apresentamos a estrutura e o código de um Parser de expressões aritméticas, com as operações triviais e tratamento dos níveis de parênteses. O leitor pode ter notado que ele possuía algumas deficiências em torno do tratamento de valores cujo resultado atingisse uma ordem de grandeza que tornasse necessário lidar com a notação científica. Nesta versão contemplaremos esta deficiência com uma solução simples. Também incluímos a manipulação de funções com um parâmetro, para que o leitor possa implementar Fatorial, Seno, Cosseno, logarítmo decimal, logarítmo neperiano, função Inversa e tantas outras que necessitar. Também fizemos a generalização do tratamento das funções aritméticas.

Diagrama hierárquico das funções



Em relação ao modelo anterior, a lógica comum de equacionamento de um par de operandos foi concentrada na função equateOper. Para tratamento da notação científica foi criada a função parseCientific. A quebra dos valores da notação científica é feita pela função parseValue. A função parseVariables teve que ser modificada para contemplar a possibilidade de que resultados obtidos pudessem vir no formato de notação científica.

A nova função parseVariables

A diferença para a versão anterior é a preocupação com o sinal e valor do expoente da potência de 10 (dez) do valor, quando este vem na forma de notação científica.


Os números da expressão podem ocorrer no formato mantissa, letra "e" (apontando que em seguida virá um expoente), o sinal do expoente e o próprio expoente.

Esta possibilidade de haver expoente em ALGUNS operandos da expressão traz a necessidade de se ter os dois novos arrays: SIGNAL e EXPONENT. Isto é necessário pelo fato de que ao ocorrer um SINAL de expoente, ainda não temos a ciência do valor do expoente, que só será conhecido no momento em que um novo operador da expressão, ou o fim desta.

Fluxograma básico

Neste fluxograma algumas variáveis temporárias não foram utilizadas, preferindo-se a abordagem esquemática:


E a continuação do label A:


Código da função

function parseVariables(texto){
var tamTexto = texto.length;
var VR = [];
var carctr = "";
var ind = 0;
// Próximo caracter
var proxCarctr = "";
// Anterior caracter
var antCarctr = "";
var S = "";
var SE = "";
var Variable;
var SINAL, PROX_SINAL;
var tmp = "";
var tmpe = "";
var tmpx = "";
SIGNAL["v01"] = "";
EXPONENT["v01"] = 0;
for(i=0;i<tamTexto;i++){
carctr = texto[i];
SINAL = "";
tmp = "";
tmpe = "";
// Caracter ATUAL é o OPERADOR de expoente "e" ou "E"
//EXPONENT[Variable] = 0;
if( isExponent(carctr) ){
// ind não precisa ser incrementado, pois o expoente se refere à uma mantissa anteriormente lida
// próximo caracter é um sinal "+" ou "-" do expoente
i++;
Variable = adjustZero((ind+1).toString());
EXPONENT[Variable] = parseFloat(texto[i]+"1");
i++;
j=0;
SE = "";
for(j=i;j<texto.length;j++){
if( isOperator(texto[j])){
break;
}
SE = SE + texto[j];
}
EXPONENT[Variable] = EXPONENT[Variable] * parseFloat(SE);
} else {
// Caracter ATUAL é OPERADOR
if( isOperator(carctr) ){
// Índice das variáveis armazenadas
ind++;
Variable = adjustZero((ind+1).toString());
SIGNAL[Variable] = "";
EXPONENT[Variable] = 0;
// Verifica se o operador do caracter atual é "-" (subtração)
if( carctr == "-" ){
Variable = adjustZero((ind+1).toString());
SIGNAL[Variable] = "-";
}
// Obtem próximo caracter
proxCarctr = texto[i+1]; //
// Caracter seguinte é OPERADOR também (^-  OU *- OU /-)
Variable = adjustZero((ind+1).toString());
if( proxCarctr == "-" ){
SIGNAL[Variable] = "-";
i++; // OBSERVAR
}
// Vai lidar com o sinal no fim do Parse
tmp = SIGNAL[Variable];
// Alimenta o array VARIABLES **
VARIABLES[ind] = parseFloat(S);
Variable = adjustZero(ind.toString());
VARIABLES[Variable] = parseFloat(S);
// Refaz a expressão
if( carctr == "-" ) { carctr = "+"; } //**
textoConv = textoConv + Variable + carctr;
S = "";
// Númeral, e não operador
} else {
S = S + carctr;
} // fim do if isOperator
}
}
// Lida com o sinal
Variable = adjustZero((ind+1).toString());
tmp = SIGNAL[Variable];
ind++;
// S vem com o resultado
tmpe = parseFloat(S);
if( findExpoent(S) >= 0 ){
VR = parseCientific(S);
Resultado = VR.semExpoente;
tmpx = parseInt(VR.expoente)+EXPONENT[Variable];
tmpe = parseFloat(VR.mantissa).toPrecision(8);
}
VARIABLES[ind] = tmpe; //*
Variable = adjustZero(ind.toString());
VARIABLES[Variable] = tmpe;
textoConv = textoConv + Variable;
showExpression(texto);
S = ""; //**
// Concatena os sinais no array VARIABLES
for(i=1;i<=ind;i++){
Variable = adjustZero(i.toString());
S = SIGNAL[Variable]+VARIABLES[Variable].toString();
VARIABLES[Variable] = parseFloat(S);
}
return tamTexto;
}

Conclusão

Os três arrays, VARIABLES, SIGNAL e EXPONENT, são alimentados a contento, indexados pelos índices "v01", "v02", ..., "vnn". Eles serão aproveitados na próxima etapa, que resolve as operações segundo a sua ordem de prioridade.






segunda-feira, 25 de setembro de 2017

Construindo um PARSER em javascript - VIII - Código completo

<html>
<head>
<title>Parse By Priority</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<script type="text/javascript">
// Routines
// Obtém o valor armazenado em uma variável
function varValue(nomeVar){
return VARIABLES[nomeVar];
}
// Obtém a variável à esquerda DE UMA POSIÇÃO (no caso um operador aritmético)
function leftOperand(pos){
return textoConv.substr(pos-3,3);
}
// Obtém a variável à direita DE UMA POSIÇÃO (no caso um operador aritmético)
function rightOperand(pos){
return textoConv.substr(pos+1,3);
}
// Obtém o conteúdo À ESQUERDA de uma string
function left(texto,n){
return texto.substr(0,n);
}
// Obtém o conteúdo À DIREITA de uma string (NÃO USADO)
function right0(texto,n){
return texto.slice(-n);
}
// Obtém o conteúdo À DIREITA DE UMA POSIÇÃO de uma string
function right1(texto,n){
return texto.substr(texto.length-n,n);
}
// Obtém o conteúdo À DIREITA DE UMA POSIÇÃO de uma string
function right(texto,n){
return texto.slice(-(texto.length-n));
}
// Ajusta um nome de variável num campo de número precedido de zeros
function adjustZero(texto){
texto = right1("000"+texto,2);
return "v"+texto
}
// Verifica se o caracter recolhido é um operador aritmético ou modificador de prioridade ()
function isOperator(Op){
var achou = (1==0);
var posicao = findOperator(Op,"+-/*^()");
if( posicao >= 0 ){
achou = (1==1);
}
return achou;
}
// Acha um tipo de operador em um texto ou expressão
function findOperator(op,texto){
return texto.indexOf(op);
}
// Acha uma operação de EXPONENCIAÇÃO em uma expressão
function findExponential(texto){
var posicao = findOperator("^", texto);
return posicao;
}
// Acha uma operação de MULTIPLICAÇÃO em uma expressão
function findMultiplication(texto){
var posicao = findOperator("*", texto);
return posicao;
}
// Acha uma operação de DIVISÃO em uma expressão
function findDivision(texto){
var posicao = findOperator("/", texto);
return posicao;
}
// Acha uma operação de SOMA em uma expressão
function findSum(texto){
var posicao = findOperator("+", texto);
return posicao;
}
// Acha uma operação de SUBTRAÇÃO em uma expressão
function findSub(texto){
var posicao = findOperator("-", texto);
return posicao;
}
// Acha um FECHA PARENTESES
function findCloseBrace(texto){
var posicao = findOperator(")", texto);
return posicao;
}
// Acha um ABRE PARENTESES
function findOpenBrace(posicao,texto){
for(i=posicao;i>=0;i--){
if( texto[i] == "(" ){
posicao = i;
break;
}
}
return posicao;
}
// Faz o teste de finalização e atualiza a Expressão aritmética
function updExpression(textoConv, posExp){
if( left(textoConv,posExp) == left(right(textoConv,posExp+4),left(textoConv,posExp).length) ) {
textoConv  = left(textoConv,posExp);
} else {
textoConv  = left(textoConv,posExp)+right(textoConv,posExp+4);
}
return textoConv;
}
// Faz o parse de valores, transformando-os em nomes de variáveis e vai armazenando os valores nestas variáveis
function parseVariables(texto){
var tamTexto = texto.length;

var carctr = "";
var ind = 0;
var proxCarctr = "";
var S = "";
var Variable;
var SINAL, PROX_SINAL;
for(i=0;i<tamTexto;i++){
carctr = texto[i];
SINAL = "";
if( isOperator(carctr) ){
// Obtem próximo caracter
proxCarctr = texto[i+1];
if( isOperator(proxCarctr) ){
SINAL = proxCarctr;
i++;
} else {
SINAL = "";
if( PROX_SINAL == "-" ){
SINAL = PROX_SINAL;
PROX_SINAL = "";
}
}
// Verifica se o operador do caracter atual é "-" (subtração)
if( carctr == "-" ){
PROX_SINAL = carctr;
}
ind++;
// Lida com o sinal
S = SINAL.concat(S);
// Alimenta o array VARIABLES
VARIABLES[ind] = parseFloat(S);
Variable = adjustZero(ind.toString());
VARIABLES[Variable] = parseFloat(S);
// Refaz a expressão
if( carctr == "-" ) { carctr = "+"; }
textoConv = textoConv + Variable + carctr;
S = "";
// Númeral, e não operador
} else {
S = S + carctr;
}
}
// Último sinal armazenado em PROX_SINAL
if( PROX_SINAL == "-" ){
SINAL = PROX_SINAL;
PROX_SINAL = "";
}
S = SINAL.concat(S);
ind++;
VARIABLES[ind] = parseFloat(S);
Variable = adjustZero(ind.toString());
VARIABLES[Variable] = parseFloat(S);
textoConv = textoConv + Variable;
S = "";
return tamTexto;
}
function equate(Expressao){
// É NECESSÁRIO EXECUTAR parseVariables
console.log("Tamanho: "+ parseVariables(Expressao));
var posExp = 0;
var aindaTem;
// Operador de expoente
OPERATOR = "Exp";
aindaTem = (0==0);
while ( aindaTem ){
//posExp = findExponential(textoConv);
posExp = FUNCOES[OPERATOR](textoConv);
if( posExp >= 0 ){
console.log("Exp:("+textoConv+")"+posExp);
// Divide operandos à esquerda e à direita do operador
var OpDir = rightOperand(posExp);
var OpEsq = leftOperand(posExp);
// Concretiza a operação
Resultado = Math.pow(varValue(OpEsq),varValue(OpDir));
console.log("Esq.:"+ OpEsq + "(" + varValue(OpEsq) + ") : " + OpDir + "(" + varValue(OpDir) + ") = " + Resultado);
// Substitui o valor da variável à esquerda
VARIABLES[OpEsq] = Resultado;
// Zera a variável à direita
VARIABLES[OpDir] = 0;
// testa o fim e refaz a expressão
textoConv = updExpression(textoConv, posExp);
} else {
aindaTem = (0==1);
}
}
console.log(textoConv);
// Operador de multiplicação
OPERATOR = "Mul";
aindaTem = (0==0);
while ( aindaTem ){
//posExp = findMultiplication(textoConv);
posExp = FUNCOES[OPERATOR](textoConv);
if( posExp >= 0 ){
console.log("Mul:("+textoConv+")"+posExp);
// Divide operandos à esquerda e à direita do operador
var OpDir = rightOperand(posExp);
var OpEsq = leftOperand(posExp);
// Concretiza a operação
Resultado = varValue(OpEsq)*varValue(OpDir);
console.log("Esq.:"+ OpEsq + "(" + varValue(OpEsq) + ") : " + OpDir + "(" + varValue(OpDir) + ") = " + Resultado);
// Substitui o valor da variável à esquerda
VARIABLES[OpEsq] = Resultado;
// Zera a variável à direita
VARIABLES[OpDir] = 0;
// testa o fim e refaz a expressão
textoConv = updExpression(textoConv, posExp);
} else {
aindaTem = (0==1);
}
}
console.log(textoConv);
// Operador de divisão
OPERATOR = "Div";
aindaTem = (0==0);
while ( aindaTem ){
//posExp = findDivision(textoConv);
posExp = FUNCOES[OPERATOR](textoConv);
if( posExp >= 0 ){
console.log("Div:("+textoConv+")"+posExp);
// Divide operandos à esquerda e à direita do operador
var OpDir = rightOperand(posExp);
var OpEsq = leftOperand(posExp);
// Concretiza a operação
Resultado = varValue(OpEsq)/varValue(OpDir);
console.log("Esq.:"+ OpEsq + "(" + varValue(OpEsq) + ") : " + OpDir + "(" + varValue(OpDir) + ") = " + Resultado);
// Substitui o valor da variável à esquerda
VARIABLES[OpEsq] = Resultado;
// Zera a variável à direita
VARIABLES[OpDir] = 0;
// testa o fim e refaz a expressão
textoConv = updExpression(textoConv, posExp);
} else {
aindaTem = (0==1);
}
}
console.log(textoConv);
// Operador de subtração

// Operador de soma
OPERATOR = "Sum";
aindaTem = (0==0);
while ( aindaTem ){
//posExp = findSum(textoConv);
posExp = FUNCOES[OPERATOR](textoConv);
if( posExp >= 0 ){
console.log("Sum:("+textoConv+") - Pos: "+posExp);
// Divide operandos à esquerda e à direita do operador
var OpDir = rightOperand(posExp);
var OpEsq = leftOperand(posExp);
// Concretiza a operação
Resultado = varValue(OpEsq)+varValue(OpDir);
console.log("Esq.:"+ OpEsq + "(" + varValue(OpEsq) + ") : " + OpDir + "(" + varValue(OpDir) + ") = " + Resultado);
// Substitui o valor da variável à esquerda
VARIABLES[OpEsq] = Resultado;
// Zera a variável à direita
VARIABLES[OpDir] = 0;
// testa o fim e refaz a expressão
textoConv = updExpression(textoConv, posExp);
} else {
aindaTem = (0==1);
}
}
return textoConv;
}


function solvExpression(Expressao){
// Variáveis iniciais

//var ind = 0;
var Resultado = 0;
var OPERATOR;
var posExp_ant = 999999;
var posIni = 0;
var posFim = 0;

var ExpressaoTemp = "";
var Tam = 0;
var Temp;
var LadoEsq,LadoDir;
// Operador de parênteses
OPERATOR = ")";
aindaTem = (0==0);
while ( aindaTem ){
posExp = findCloseBrace(Expressao);
if( posExp >= 0 ){
VARIABLES = [];
textoConv = "";
ind = 0;
posFim = findCloseBrace(Expressao);
posIni = findOpenBrace(posFim,Expressao);
ExpressaoTemp = Expressao.substr(posIni+1,posFim-posIni-1);
Temp = equate(ExpressaoTemp);
LadoEsq = left(Expressao,posIni);
LadoDir = Expressao.substr(posFim+1,9999);
Expressao =  LadoEsq +VARIABLES["v01"]+ LadoDir;
} else {
aindaTem = (0==1);
}
}
VARIABLES = [];
textoConv = "";
ind = 0;
Temp = equate(Expressao);
return VARIABLES["v01"];
}
//// Program
/*
solvExpression                        Fornece o resultado de uma expressão aritmética
           |
+---------  equate          Resolve a expressão, operação por operação
|
+-------- parseVariables Faz o parse da expressão aritmética
1 - Coloca cada número em um item do array VARIABLES
2 - Coloca sinais negativos dentro dos respectivos itens do array VARIABLES
*/

// Constantes e ARRAYS do CORE do parser e solve
var VARIABLES = [];
var FUNCOES = [];
FUNCOES["Exp"] = findExponential;
FUNCOES["Mul"] = findMultiplication;
FUNCOES["Div"] = findDivision;
FUNCOES["Sum"] = findSum;
FUNCOES["Sub"] = findSub;
FUNCOES["Abp"] = findOpenBrace;
FUNCOES["Fbp"] = findCloseBrace;
var textoConv = "";
// Processando a expressão
console.log("======================================================");
var result = solvExpression(Expressao);
console.log("Resultado: " + result );
</script>
</head>
<body>
</body>
</html>

Construindo um PARSER em javascript - VII - Código

Neste post apresentaremos e explicaremos a função mestra de nosso Parser, a função solvExpression.

Objetivo da função

O objetivo de solvExpression é scanear a expressão aritmética, com níveis de parênteses, achando, a cada passada, o parênteses mais interno e resolvendo a expressão aritmética no interior dele. Este procedimento será repetido até o fim das operações aritméticas disponíveis.

Variáveis locais necessárias

Uma série de variáveis de apoio são necessárias para o processamento dos níveis de parênteses, por esta função:

function solvExpression(Expressao){
// Variáveis iniciais
var Resultado = 0;
var OPERATOR;
var posExp_ant = 999999;
var posIni = 0;
var posFim = 0;
var ExpressaoTemp = "";
var Tam = 0;
var Temp;
var LadoEsq,LadoDir;
// Operador de parênteses
OPERATOR = ")";
aindaTem = (0==0);

Resultado - Nossa conhecida variável que armazena os resultados das operações aos pares de operandos;
OPERATOR - Armazena o operador aritmético da vez, ou parênteses;
posExp_ant - Armazena a posição onde o operador anterior está. Começa com um valor bem alto;
posIni - Posição inicial na expressão de um fragmento;
posFim - Posição final na expressão de um fragmento;
ExpressãoTemp - armazena a expressão temporária para análise;
Tam - Tamanho da Expressão;
Temp - Variável temporária;
LadoEsq e LadoDir - Fragmentos à esquerda e à direita de uma expressão;
aindaTem - Flag booleana que armazena a condição de continuidade de algum processo;

Loop operacional

A busca por níveis de parênteses é contínua, até que se esgote por completo:

while ( aindaTem ){
posExp = findCloseBrace(Expressao);
if( posExp >= 0 ){
VARIABLES = [];
textoConv = "";
ind = 0;
posFim = findCloseBrace(Expressao);
posIni = findOpenBrace(posFim,Expressao);
ExpressaoTemp = Expressao.substr(posIni+1,posFim-posIni-1);
Temp = equate(ExpressaoTemp);
LadoEsq = left(Expressao,posIni);
LadoDir = Expressao.substr(posFim+1,9999);
Expressao =  LadoEsq +VARIABLES["v01"]+ LadoDir;
} else {
aindaTem = (0==1);
}
}

Em nossas explicações, dissemos que os níveis de parênteses são facilmente identificados pelo operador ")" (fecha parênteses), e não pelo abre-parênteses, como os obsessivos do Parse à esquerda poderiam esperar. Por esta razão, a primeira função a ser chamada neste loop é findCloseBrace:

// Acha um FECHA PARENTESES
function findCloseBrace(texto){
var posicao = findOperator(")", texto);
return posicao;
}

Esta função chama a função mais básica findOperator, que utiliza o método indexOf do objeto string para achar o fecha-parênteses.

Procedimentos pós-loop

Ao fim do loop de parênteses, é necessário tomar algumas providências, pois resta uma expressão sem níveis de parênteses a interpretar:

VARIABLES = [];
textoConv = "";
ind = 0;
Temp = equate(Expressao);
return VARIABLES["v01"];

:A função equate fará a última avaliação de expressão, e o resultado final será devolvido no item cujo índice é "v01".

Conclusão

O último nível aqui apresentado do Parser é o primeiro nível em ordem de execução, que chama os demais.

Neste post apresentamos o código completo.