GitHub commits ahead after merge

Olá. Hoje eu vou falar de algo que me assombrou por muitos anos, e só agora, depois de muito tempo, eu consegui entender, e do entendimento, conseguir a solução. Um problema clássico, que são os repositórios fork no GitHub estarem eternamente dessincronizados, mesmo após merges de pull requests.

O GitHub é uma hospedagem git muito boa no geral, porém a funcionalidade de squash (esmagar) commits no momento do merge causa problemas que podem ser apavorantes às pessoas com pouco ou nenhum domínio da ferramenta git.

Em resumo, utilizar squash merges em conjunto com repositórios fork, deixa os repositórios fork eternamente divergentes, e a divergência só cresce com o tempo. E isso por sua vez decorre do fato que, ao contrário da intuição, os merge commits não unificam a história de dois repositórios separados, mas apenas documentam em um repositório que um commit tem duas dependências locais, ao invés de uma.

Vamos ver isso no caso típico. A história normalmente começa a partir de um repositório oficial ou upstream hospedado no GitHub. A partir desse repositório é criado um segundo repositório fork. E por fim, para trabalhar diretamente com os arquivos, desse segundo repositório é criado um terceiro repositório local, através do comando git clone.

Apesar de em um primeiro momento os três repositórios estarem idênticos, eles podem (e provavelmente vão) divergir livremente. O máximo de relação que existe entre os repositórios é que eles tem vários commits individuais em comum, e que, para além disso, há uma marcação no repositório fork (B) que indica que ele pode falar com o upstream (A), e uma marcação no repositório local (C) que indica que ele pode falar com o repositório fork. Mas repare que não há links nas direções opostas. Ou seja, C pode falar com B, e B pode falar com A, mas nada além disso.

Agora vamos ver como é o dia a dia. Depois de criados os repositórios fork e local, são feitos variados commits no repositório local, até o ponto que a alteração é considerada pronta e pode ser enviada. Porém o processo de envio é feito em fases. Primeiro os repositórios local e fork são sincronizados via um git pull, de C para B. Mas para enviar a alteração de B para A, não é utilizado o protocolo git, mas sim as telas do GitHub, e é nesse momento que é possível fazer um squashed commit.

Um commit esmagado é implementado internamente como:

  • Um novo commit normal em A;
  • Um novo commit merge em B;
  • Não tem efeitos imediatos em C.

Por exemplo, vamos supor que foram criados os commits 1, 2 e 3 no repositório local. Após o push, eles passam a existir também no repositório fork, e C e B ficam iguais. Depois, um pull request é aberto de B para A, que depois de um tempo é aceito. No momento que é aceito, é criado um novo commit 4, apenas no repositório upstream e que não se parece com nenhum outro commit anterior, e é criado um merge commit 5, apenas no fork, que também não se parece com nenhum commit do repositório oficial. Nesse ponto, A, B e C estão diferentes entre si.

RepositórioCommits
upstream0-5
fork0-1-2-3-4
local0-1-2-3

Note que o commit 5 só existe no upstream, que o commit 4 só existe no fork. Isso torna os repositórios upstream e fork incompatíveis. Os repositórios fork e local continuam compatíveis porque o commit 4 existe a mais “ordem certa”, e pode ser tranquilamente copiado de B para C. Mas o commit 5 é uma mesclagem dos commits 1 a 3, e por isso tentar copiar entre A para B/C, ou vice versa, as alterações vão se sobrepor, causando um conflito.

É por isso que repositórios forks no GitHub ficam eternamente dessincronizados, mostrando mensagens do tipo This branch is N commits ahead of proj/repo:branch. E o único jeito de resolver isso seria através de alterações destrutivas no repositório fork e local. É preciso destruir os commits 1, 2, 3 e 5, para assim “abrir espaço” para a criação do commit 4 do repositório oficial.

As interfaces do GitHub não implementam essas ações destrutivas, de forma que só sobra fazê-las por fora do GitHub (que será explicado abaixo).

Mas sabendo que serão necessárias ações destrutivas, daí dois conselhos imediatos. Primeiro, faça um backup do seu repositório local antes de mais nada, e assim ao menos será possível voltar à situação original se alguma coisa der errado no meio do caminho (o que é bastante comum de acontecer) Segundo, que em alguns casos, é possível diminuir um tanto o tamanho da destruição.

O grande problema é que a decisão de fazer um merge normal ou um merge squashed está nas mãos do controlador do repositório upstream, e você não tenha como prever que tipo de merge ele vai fazer. No final, você pode ter de lidar com uma situação de destruição maior. Porém, se você souber de antemão que o merge será squashed, você pode diminuir os seus problemas fazendo branches “rasos”. Em outras palavras, evitando fazer um monte de commits pontuais nos seus repositórios, que no final serão todos perdidos de qualquer jeito. Esse não é um conselho muito bom, mas diminui bastante as chances do git falhar fazendo um rebase automaticamente.

Rebase automático menos destrutivo

Depois do backup feito, hora de tentar resolver e sincronizar seus repositórios de uma maneira automatizada. A primeira coisa que vamos fazer é ensinar o seu repositório local a falar diretamente com o repositório upstream. Lembrar que o repositório local nasce sabendo falar apenas com o fork.

git remote add upstream git@github.com:user/repo.git
git remote set-url --push upstream /dev/null
git fetch upstream

O primeiro comando permite a C conversar com A, o segundo comando bloqueia a comunicação de escrita (e assim você pode trabalhar com menos medo), e o terceiro comando anexa os dados do repositório A na sua cópia C.

Para ver como ficou, você pode rodar um git remote -v show. O resultado deve ser algo parecido com isso:

origin git@github.com:user/repo.git (fetch)
origin git@github.com:user/repo.git (push)
upstream git@github.com:upstream/repo.git (fetch)
upstream /dev/null (push)

Se você já teve a infelicidade de executar um git rebase interativo, já descobriu que é um comando feito por masoquistas, para masoquistas, com amor. Mas aqui queremos um processo automatizado, tudo ou nada. Será um processo destrutivo, e talvez por isso você queira entender exatamente o irá acontecer. Os comandos git log servem para isso, e podem ser comentados ou removidos.

Os comandos abaixo funcionam supondo que vamos fazer a reescrita destrutiva em um branch chamado master que existe em todos os repositórios. Em teoria seria possível fazer os comandos misturando branchs diferentes de repositórios diferentes, mas fica o alerta que isso fica bem confuso, bem rápido.

Hora da verdade:

git log -500 --format="%h %s" > ../log1.txt

git switch master
git rebase -s ours upstream/master

git log -500 --format="%h %s" > ../log2.txt

Se tudo der certo, você vaii um monte de mensagens, mais ou menos assim:

dropping hash message -- patch contents already upstream
dropping hash message -- patch contents already upstream
dropping hash message -- patch contents already upstream
Successfully rebased and updated refs/heads/master.

As mensagens do tipo dropping -- patch contents already upstream indicam que o git conseguiu encontrar as suas alterações pontuais no upstream, e por isso jogou fora vários commits individuais. E isso é o que queríamos.

Eu sugiro que aproveite esse momento para olhar os arquivos ../log1.txt e ../log2.txt, para ver como estava e como ficou o seu repositório local. Usando a numeração utilizada acima, deve ter ficado mais ou menos assim, no topo do começo do arquivo ../log1.txt:

hash5 Merge branch 'php:master' into master
hash3 Msg commit local 3
hash2 Msg commit local 2
hash1 Msg commit local 1
hash0 Mensagem de um commit em comum.

E assim o começo do arquivo ../log2.txt:

hash4 Mensagem commit esmagado
hash0 Mensagem de um commit em comum.

Ou seja, agora o ramo master do repositório local está idêntico ao do repositório oficial A. Além disso, os demais branchs devem ter sido preservados. Ainda assim, uma verdadeira reescrita destrutiva no repositório local, que ainda precisa ser enviado ao repositório fork B.

Porém, caso não tenha recebido a mensagem Successfully rebased, não tema. Execute um git rebase --abort, e tudo voltará como era antes. Porém isso significa que o procedimento menos destrutivo falhou, e não adianta continuar.

Bom.. supondo que deu certo, a reescrita destrutiva foi feita localmente. Nesse momento, A e C estão iguais, mas B continua diferente, e para além disso, continua mostrando a mensagem de This branch is N commits ahead of proj/repo:branch, que era o problema original.

Nesse momento, você pode ficar tentado em evitar uma reescrita destrutiva no seu fork, fazendo um simples git push. Pode tentar, mas não vai funcionar.

E não vai funcionar porque no repositório fork, o último hash de master ainda é o hash5, o merge commit criado pelo GitHub, que torna esse repositório B incompatível com a história do repositório A, que nunca nem viu esse merge. Será preciso sim fazer uma reescrita destrutiva em B. E foi para isso que modificamos o repositório local C.

Observe que o repositório local C contém, nesse momento:

  • um branch master compatível com o do repositório A;
  • todos os seus outros branchs, que não existem no repositório A.

Ou seja, tem tudo o que você quer. Basta então sobrescrever o repositório B com os dados do repositório C, com o seguinte comando:

git push --force origin +master

Feito isso, é só navegar até a página do seu repositório no GitHub, e verá que a mensagem de This branch is N commits ahead finalmente desapareceu.

Rebase automático mais destrutivo

Eu expliquei acima o rebase menos destrutivo, mas o que seria então orebase mais destrutivo?

O jeito mais destrutivo, e também o mais rápido, de resolver a mensagem This branch is N commits ahead seria usar a sequência de comandos abaixo, que sempre funciona, mas que ainda assim eu não recomendo.

git fetch upstream               // Anexa dados do upstream no repositório local
git checkout master              // Garante que está no local/master
git reset --hard upstream/master // Descarta dados locais
git push --force                 // Descarta dados no repositório

Os descartes de dados comentados linha a linha são irreversíveis. Jogou fora, é para sempre.

E por isso mesmo que não recomendo o seu uso, a não ser no caso mais desesperador, quando você já está decidido a apagar repositórios inteiros, local e fork, para resolver o problema. Que é mais ou menos isso que os comandos acima fazem.

Epílogo

E aí ajudou? Resolveu? Depois de ler, entendeu mais, ou piorou o entendimento?

Imposto de Renda Negativo e Renda Básica Universal

Esses dias estive envolvido em algumas discussões e reflexões sobre esses dois temas, as noções de Imposto de Renda Negativo e o seu conterrâneo, a Renda Básica Universal.

Para quem nem nunca ouviu falar deles, vai um resumo exetutivo:

  • Imposto de Renda Negativo, apesar do nome, é mais ou menos o Imposto de Renda qual conhecemos hoje, com a diferença que em vez de ele ter uma faixa de isenção inicial, cobrando imposto apenas de quem ganha acima de uma faixa, ele começaria a partir de um patamar negativo de renda (e daí o nome). O efeito disso é quem tivesse pouca ou nenhuma renda estaria na faixa negativa, e portanto receberia dinheiro, em vez de pagar;
  • Renda Básica Universal, por outro lado, é mais direto e simples: todo mundo recebe o mesmo valor minúsculo, mensalmente, sem questões ou condições.

A parte em que as duas noções se encontram é que ambas são mecanismos de transferência de renda, e focados naqueles de baixíssima ou nenhuma renda. As maiores diferenças são algo no nível de detalhe de implementação, e dependendo de como mexer nos detalhes, elas acabam convergindo… até certo ponto.

O que ambos os projetos propõem é retirar “condições” e “direcionamentos” dos programas de enfrentamento de pobreza, que desde sempre são muito caros, um verdadeiro custo que retira dinheiro que chega na ponta e, francamente, falham miseravelmente em causar os direcionamentos que se propõem.

A Renda Básica vai no cerne dessa questão, simplificando a atendimento ao máximo: todo mundo recebe, ponto. Isso reduz a burocracia ao mínimo, aumentando a efetividade e diminuindo as distorções. Já o Imposto de Renda Negativo faz um pouco mais de conta, ao entregar apenas um diferencial de renda.

Agora ao ponto que importante qual eu queria chegar: ainda que possam ser muito semelhantes em resultado final, Imposto de Renda Negativo e Renda Básica Universal são muito diferentes durante a implementação.

Isso porque embora a Renda Básica Universal seja um objetivo interessante em si mesmo, ele é algo utópico de se implementar. Isso porque são necessários dois passos:

  1. Retirar os benefícios atuas;
  2. Implantar a Renda Básica Universal.

Muita gente fala do (2), mas o que sempre dá problema é o (1). Eis que o objetivo é tirar condições e direcionamentos, mas para efetivamente realizar isso, é necessário demolir as condições e direcionamentos existentes. Ou tão diretamente quanto possível: de eliminar os benefícios atuais. Coisa que quase nunca ocorre. E por sua vez, elimina a impede a implementação de Renda Básica em todo lugar.

É aqui que a ideia mais antiga, e um tanto esquecida, mostra o seu valor. O Imposto de Renda Negativo permite criar uma sistemática de Renda Básica Universal mesmo na presença dos programas atuais, ao realizar uma aritmética tão simples quando efetiva, a saber:

  1. Acrescenta a Renda Básica Universal, para cada pessoa viva;
  2. Subtrai os valores repassados em programas assistenciais outros, para a mesma pessoa.

Ou seja, um sistema de Imposto de Renda Negativo tem o potencial de permitir a criação de um sistema de Renda Básica Universal, com menos riscos de aumentar ou reforçar condições, direcionamentos e duplicações durante a implantação do sistema.

Eis que consigo imaginar os comentários sendo digitados imediatamente à essas afirmações, no sentido que um Imposto de Renda Negativo ainda assim vai contra a noção de Renda Básica Universal de ser, bem… Universal, todos recebem e todos recebem sem condições. Ter de pedir para as pessoas fazerem Imposto de Renda mensal para, daí, recebem a RBU é vexatoso e condicionante.

À segunda colocação eu diria que não é vexatório ter de fazer Imposto de Renda, e que mensal não é nem uma coisa que é requisitada em programas sociais, sendo mais espantalhos que argumentos. Quanto a primeira, eis uma observação importante que surgiu nas conversas e reflexões, que qual é o verdadeiro motivo desse post. E é o seguinte:

O Imposto de Renda Negativo não é uma questão da Receita Federal.

Isso, e literalmente isso. Ainda que nesse caso não deva ser chamado de Imposto de Renda algo que não seja de domínio da Receita Federal (por conta de nomeclaturas de lei), o ponto principal reside. O Imposto de Renda Negativo, como uma política pública da baixa ou nenhuma renda, não é atribuição do Fisco e nem, exatamente, deve ser executado por ele.

Bem pode, e provavelmente deve ser executado por órgãos outros, focados em políticas sociais, e não um órgão eminentemente de execução tributária, ainda que possam existir políticas tributárias de cunho redistributivo.

Mas se o nome é a questão, nome então é necessário. Eu estou falando aqui de implantar:

A Renda Básica Universal Líquida

O “Líquida” que é importante, e bem pode ser só detalhe de implementação, em vez de constar no nome.

Novamente e novamente, a RBU deve, pelos seus próprios proponentes, ser universal e sem condições. Porém, por essa mesma razão, não pode ela ser duplicada, paga em duplicado, triplicado ou mais, a qualquer um, seja no próprio benefício ou por benefícios proximais.

E a quantidade de programas sobrepostos é enorme e distorcida, por força de leis, e portanto obrigatórias. A própria inércia legislativa na prática elimina a possibilidade de remoção de benefícios existentes, o que só faz perpetuar a situação, que por sua vez daí impede a realização de RBU.

A noção que Imposto de Renda Negativo e Renda Básica Universal podem, na prática, diferir muito pouco, a depender dos detalhes, é normalmente utilizado para jogar a escanteio a ideia antiga, sem nada avançar na ideia nova. Eis que aqui chamo atenção que deveria ser o contrário, que a proximidade prática em muitos pontos demonstra a viabilidade de se implementar não a RBU, utópica e reforçadora de distorções, mas sim uma versão “líquida” da ideia, mais próxima do Imposto de Renda Negativo, justamente para se atingir os objetivos utópicos.


Adendo em 14/02/2023: Sai em noticiário que uma reforma tributária onde haveria um cashback para baixa renda… Eis um termo que eu não imaginei que seria utilizado, mas… porque não? Comunica a ideia.

“Imposto de renda, com cashback para baixa renda.”

Conta de investimento previdenciária, take 2

Esse assunto voltou à tona nos últimos dias, então vale a pena fazer uma atualização sobre o post anterior.

Em resumo, investir no Brasil, fora dos bancos, é difícil pra caramba. Muito por conta da tributação que é longa, complexa e cheia de meandros. Para incentivar os investimentos, alguma outra forma precisa ser implantada.

Para simplificar, o jeito é colocar a tributação na fonte e, até, incentivar o investimento através de estímulos diretos. Uma solução simples de implantar e simples de explicar seria a criação de contas de investimento específicas para isso. Funcionaria assim: dentro dessas contas, todos os rendimentos e ganhos de capital são isentos, e você só é tributado na hora que realiza saques. Seriam dois tipos de contas:

  1. Contas de investimento simples: Nessas contas os depósitos e saques não são incentivados. Os rendimentos e ganhos realizados dentro da conta ficam isentos. Os saques são isentos até igualar com os depósitos efetuados, e a partir desse ponto são tributados na fonte na alíquota fixa de renda variável (hoje de 15%).
  2. Contas de investimento previdenciárias: Parecidas com as contas simples, com a diferença que depósitos aqui podem ser abatidos na Declaração de Imposto de Renda com as mesmas regras de previdências privadas, e com a mesma tributação dessas na hora do saque.

Ou seja, essas contas funcionariam como “fundos de investimento pessoais”, onde as pessoas poderiam investir tranquilamente qualquer ativos regulados pela CVM, com tributação na fonte, postergada e super simplificada.

Mas não é só a tributação complicada que afasta os investidores da bolsa, mas também a mera declaração. Investir em fundos e previdências hoje é fácil porque vem uma única linha a registrar na DIRPF, a do próprio fundo, não importando quantos ativos esses fundos tenham internamente. A mesma coisa precisa ser aplicada as contas de investimento. Isso incentivará a diversificação de investimentos sem trazer a complicação de detalhar cada investimento.

A diferença entre as contas é para trazer o benefício fiscal que existem nas previdências privadas, um incentivo que já existe hoje, inclusive a ausência do imposto “come-cotas”. As formas de investimento indiretos continuariam iguais.

Gostou da ideia? Ajude a disseminá-la 🙂

Conta de investimento previdenciária

O noticiário de hoje me fez lembrar um antigo sonho: finalmente implantar no Brasil o conceito das individual retirement accounts, ou seja, contas de previdência pessoais, administradas pessoalmente.

A ideia é bem simples. A criação das “contas de investimento previdenciárias”, com características especiais, para incentivar a poupança e o investimento direto.

Essas novas contas poderiam ser abertas em bancos e corretoras, sendo de dois tipos diferentes:

Nas contas tipo 1 (CIP1) os depósitos e saques seguem as mesmas regras de isenção e tributação de previdência privada. Ou seja, depósitos aqui diminuiriam o seu Imposto de Renda anual, até certo limite. A vantagem seria fugir das taxas de administração, taxas de carregamento e taxas de administração das previdências privadas. Você mesmo escolhe os investimentos, você mesmo investe diretamente, reduzindo custos.

Nas contas tipo 2 (CIP2) os depósitos não geram isenção, e saques são isentos até o limite valor depositado. Assim só rendimentos e ganhos capital seriam tributados, no saque. A vantagem aqui é postergar e diminuir o Imposto de Renda, que seria cobrado na fonte de forma simplificada, numa tabela regressiva.

Nas contas poderia-se investir em quaisquer ativos regulados pela CVM, como fundos de investimento, ações, FII, LCI, LCA, LIG, FIP, FIP-IE, etc). Isso contribuiria para o aumento da responsabilidade pessoal, mas também para o desenvolvimento do mercado de capitais e financiamento do desenvolvimento nacional.

Além do controle passar para o investidor final, a constituição das contas permitiria também facilitar algumas questões que afastam as pessoas da bolsa de valores e dos investimentos estruturados: o Imposto de Renda confuso e mensal. Ter a possibilidade de compensar o IR entre classes de ativos e, ao mesmo tempo, simplificar sua cobrança, ajudariam a atrair mais investidores, profissionalizando o mercado.

E aí? Bora promover essa ideia?

Problema Java no Banco do Brasil / Ubuntu Linux

Hoje o site do BB resolveu não funcionar, para variar, por problema do plug-in Java.

Vai ser uma festa só quando essa $%@!& parar de funcionar de vez. O Chrome já deu um pé na bunda da integração Java a muito tempo, assim como outros navegadores. O Firefox será o último, mas também chegará o glorioso dia em que o derradeiro refúgio dessa péssima ideia desaparecer de vez.

no-more-java-plugin

Mas os bancos, pelo jeito, vão deixar pro último momento, em vez de sair o quanto antes dessa barca furada. Caso em pauta, hoje o site do BB não funcionou aqui. A solução? Dar downgrade no plug-in do Java. Em pleno 2016, forçar uma versão antiga de uma coisa que exige segurança máxima para funcionar.

Especificamente, rodei na minha máquina:

sudo update-alternatives --config mozilla-javaplugin.so

Que gerou o seguinte resultado:

Existem 4 escolhas para a alternativa mozilla-javaplugin.so (disponibiliza /usr/lib/mozilla/plugins/libjavaplugin.so).
Selecção Caminho Prioridade Estado
------------------------------------------------------------
0 /usr/lib/jvm/java-8-oracle/jre/lib/amd64/libnpjp2.so 1089 modo automático
1 /usr/lib/jvm/java-7-openjdk-amd64/jre/lib/amd64/IcedTeaPlugin.so 1071 modo manual
2 /usr/lib/jvm/java-7-oracle/jre/lib/amd64/libnpjp2.so 1075 modo manual
3 /usr/lib/jvm/java-8-oracle/jre/lib/amd64/libnpjp2.so 1089 modo manual
* 4 /usr/lib/jvm/java-9-oracle/lib/amd64/libnpjp2.so 1088 modo manual
Pressione enter para manter a escolha actual[*], ou digite o número da selecção:

Escolhida a opção 3, equivalente ao Java 8, e um reboot de navegador depois, funcionou.

Espero que isso lhe resolva. Mas bem sei que esse é só um dos milhares de problemas que de instalação, de configuração, de assinatura e de incompatibilidades que existem nesse assunto. Que, não custa lembrar, vão desaparecer junto suporte ao maledito plug-in.

Estejam os bancos preparados ou não. Avisos não faltaram.

Erro DIRPF / For input string: “9-e”

Mais uma declaração de Imposto de Renda no Linux, mais um problema. Não reclamo tanto porque sei o quão difícil é programar para “ambientes hostis”, mas reclamo ainda assim por não tem um canal de comunicação técnico para poder relatar os problemas (ou código aberto, ainda que não livre, para já mandar patchs de uma vez). O erro, no título, acontece logo de cara, ao tentar abrir o programa.

A explicação com solução. Num terminal (Ctrl+Alt+T), execute:

java -version

Esse primeiro comando mostra a versão padrão do Java da sua máquina. Na minha máquina retorna uma linha com “9-ea” no final, e isso causa o problema. O pessoal da Receita está tentando ler o “9”, mas o “-ea” causa um erro, que por sua vez derruba o programa. Não muito esperto.

Com isso e mente, execute um segundo comando:

update-alternatives --list java

Esse comando mostra uma lista de versões alternativas do Java, instaladas na sua máquina. No meu caso:

/usr/lib/jvm/java-7-openjdk-amd64/jre/bin/java
/usr/lib/jvm/java-7-oracle/jre/bin/java
/usr/lib/jvm/java-9-oracle/bin/java

A versão da DIRPF 2015-2016 instala num caminho padrão, cujo ícone tem o seguinte comando:

/usr/lib/jvm/java-9-oracle/bin/java -Xms128M -Xmx512M -jar ~/ProgramasRFB/IRPF2016/irpf.jar

Que você vai perceber, é um comando que começa com uma das alternativas listadas acima. A solução, bem simples, é substituir a primeira parte por uma das alternativas e rodar no terminal, até funcionar. A ideia é pegar uma das alternativas, indo da maior versão para a menor, sempre preferindo a versão da Oracle (infelizmente).

Eu consegui abrir com a penúltima das alternativas (que minha máquina é a versão 1.7.0_80), mas não fui até o final da declaração ainda para ter certeza.

Tente aí, e comente o sucesso ou insucesso. Ficarei feliz com os agradecimentos, e posso tentar ajudar os casos que não resolver.

E sorte, claro.


ADENDO: Para facilitar, criei um script que tenta os caminhos padrão listados acima. E não, executar código aleatório das internets não é lá muito seguro. Dado o aviso, o script está disponível aqui, e pode ser baixado, habilitado e executado com as sequências abaixo:

wget https://raw.githubusercontent.com/alfsb/dirpf/master/dirpf20152016-init.sh
chmod +x dirpf20152016-init.sh
./dirpf20152016-init.sh

Agradeço quem comentar os caminhos de alternativas Java, versão 7 ou maior, não listadas acima, para complementar o script.

Erro ao acessar a Extrato de Processamento DIRPF na Receita Federal / eCAC

Esse é um erro que vira e mexe aparece, então aproveitar para documentar a solução de contorno.

Depois de logar no eCAC, ao clicar no link do Extrato de Processamento DIRPF, parte da página fica em branco ou aparece um erro. Isso é um problema técnico (um problema de certificado digital não reconhecido em conjunto com um HTML IFRAME). O resultado interno é um erro de segurança, que não aparece, então não é possível contorná-lo.

A solução é:

  1. Acessar e logar no eCAC normalmente.
  2. Utilizar um desses links diretos:

Vai aparecer um erro de segurança, dizendo que o certificado não é confiável. Daí é executar os procedimentos do seu navegador para contornar esse erro.

Como a cadeia de confiança de certificados utilizada no Brasil não vem embutida nos navegadores, então essa a mensagem está tecnicamente correta. Porém o site da Receita está montado de tal forma que esconde esse erro, o que torna impossível acessar a página.

E é isso. Sorte com o leão.

Temperatura em função da pressão relativa, ar como gás ideal

Eu me meto em cada uma…

Mas antes de mais nada, a resposta: y = 2062,203 * exp( ( ( ln(x) + 3,254 ) ^2 ) / 185,219 ) – 1911,206 (para pressões > 0,33)

E esse impressionante resultado começou com a seguinte conversa: “André, eu preciso da inversa de uma função”.

Ok, pensei eu, inversões de função existem algumas online, isso não vai requerer nem instalação de software especializado. Qual função?

“A inversa da função dessa tabela“.

Ah… Não é a inversa de uma função conhecida… Primeiro é preciso deduzir uma função apropriada à tabela para depois inverter. Imediatamente vem aquele feeling de problema mal especificado…

Tabela de termodinâmica, gráfico da função uma exponencial para cima não lá muito “redondo”. Como eu entendo quase nada da matemática subjacente à termodinâmica macroscópica, a conversa seguinte foi no sentido de determinar a natureza do gráfico da função. Respostas no sentido de ser polinomial de 4ª ordem.

Uma inversa de um polinômio à quarta? Isso não vai ser muito pequeno…

Foram bem umas duas horas lidando com sites que “descobriam” os fatores apropriados à funções polinomiais. Sem muito sucesso, porque os resultados quando plotados não ficavam lá muito parecidos com o gráfico inicial. Tentativas de diminuir o grau do polinômio não foram muito melhores. Fora que as inversões dessas funções davam uns monstrinhos de mais de página, como esperado. A fome bate e a pesquisa é interrompida para almoço.

Durante o almoço a conversa continua sobre o problema. Ou antes, como seria a solução do problema. A conversa se desvia para o truque conceitual que o pessoal da matemática/computação as vezes usa para problemas que são intratáveis: apelar a um oráculo.

No caso, um oráculo ideal, onisciente e onipotente. Claro que fazer um oráculo assim é impossível na prática, mas supondo que existisse tal oráculo, que tipo de resposta que esperaria que ele fornece?

Nisso o cara para e pensa: uma resposta curta, uma linha.

Bom, esse é um problema bem diferente do inicial. Em vez de procurar uma função da tabela para depois inverter, inverte-se a tabela e procura-se uma função curta que aproxime a nova tabela. Talvez seja tão difícil de enumerar um problema quanto o outro, mas agora há uma restrição artificial (uma linha), que pelo menos o torna menor. É impossível de construir um oráculo que “tente” todas as combinações de fórmulas e parâmetros, mas é bem mais fácil de construir um oráculo que tente fórmulas curtas.

Até isso já tem pronto, online, hoje em dia. Com direito a repositório de funções, multi task hospedado, programação genética para evoluir fatores e relatórios com tal requinte de informação que coloca muito trabalho universitário no chinelo… (ver abaixo)

20 minutos depois a resposta aparece. Aliás, várias, já devidamente ordenadas por aderência aos dados informados.

E a resposta escolhida é bela. Suficientemente curta para ser operada algebricamente (outro requisito, não demandado inicialmente) e suficientemente aproximado para ser usado como uma inversão interpolada. Uma interpolação invertida de uma tabela empírica, devo acrescentar…

Seria tema de livros discutir as implicações filosóficas de uma função aleatória que dá a interpolação de um processo físico. Ainda mais uma função que não tem a estrutura da processo interpolado, menos ainda, invertido. Mas não deixa de ser um daqueles raros momentos que a força bruta ingênua acaba produzindo um resultado inesperadamente útil.

Detalhe: como a solução usou de programação genética para evoluir os parâmetros, então fórmula e parâmetros são aleatórios. Tudo, enfim.

O momento que a lista de soluções apareceu e o cara se entusiasmou de ver a aderência me fez lembrar de uma passagem de Travelling Salesman, onde um truque levemente diferente (a transmutação de um problema em outro) torna um problema impossível em possível, apenas com um rearranjo de forma. No meu caso, foi o abandono da explicação “correta” que levou a solução “boa” (que o pessoal da psicologia reconhecerá como um caso de rigidez funcional). O inicialmente queria a inversa de uma função desconhecida, mas o que ele precisava era de uma função algebricamente simples que fosse próxima da inversa da tabela. Que em retrospectiva é óbvio: uma interpolação de um processo empírico é por definição impreciso. Então uma aproximação aleatória é perfeitamente válida.

Bom, é isso.

Se teve paciência de ler até aqui, bem imagino que és uma pessoa bem nerd, que provavelmente tem amigos nerds engenheiros. Se quiser ter umas discussões bem incomuns com eles vai a dica: repassem aos amigos engenheiros apenas o título da mensagem e a fórmula acima, e peça a eles a tentarem validar o resultado ou ainda explicar se está “certo” a fórmula. Já adianto que será confuso pra caramba para eles e para ti 🙂

Agora, se achou o desafio interessante e quiser replicar por conta própria, os inputs únicos são:

  • Paginas 14 e 15, colunas 1 e 3 disso;
  • A inversa delas, em uma linha.

E boa caça 🙂

 

EDIT: Poucas semanas após a publicação do post o serviço saiu do ar, passando da existência a um mito. O fonte ainda sobreviveu, mas não o serviço pronto. A internet se tornou um lugar um pouco menor, com a perda desse desconhecido, mas impressionante recurso 🙁

Ubuntu 14.04 LTS & Gnome Clássico

Estou viajando para SP, e portanto a velha história de fazer backup e por a produção no notebook velho.

Produção. Meu micro tem lá os seus ares de servidor, com processos rodando continuamente. E daí a minha preferência por versões long term support (LTS) do Ubuntu. A que eu rodo no meu desktop é a já antiga 12.04. Pensei em tentar a 14.04 no notebook, já que ele estava desatualizado num remotíssimo Ubuntu 10.10.

Sim, o notebook é velho assim.

Surpreendentemente o Ubuntu 14.04 funcionou num antiquíssimo CCE. E claro, também, tive problemas com lamentável placa de vídeo SiS 771/671. Curioso como foi, durante a instalação a resolução estava alta, mas depois de instalado a eu vi o mundo novamente em 640×480. Depois de me açoitar mentalmente por ter esquecido desse chato detalhe, a segunda surpresa foi ter uma solução simples e rápida (e em português). A terceira surpresa foi ter visto, pela primeira vez, a resolução nativa da tela desse meu antigo hardware.

Porém, mesmo com tantas surpresas, veio a lentidão de tentar rodar um ambiente gráfico Linux sem uma placa especializada. Ou seja, arrancar o Unity, ou pelo menos reduzir a zero as animações.

Reduzir as animações mostrou-se improdutivo. Não há como eliminar todas as animações. Cheguei num ponto onde a única alternativa então era remover o Compiz, mas fazer isso tinha um prospecto bem ruim.

As pesquisas de remoção de animações meio que direcionavam para contornar o Unity, sem removê-lo: instalar o Xfce e, na prática, converter o Ubuntu Desktop num Xumbuntu.

Chame-me de antiquado, mas o que eu queria mesmo era o Gnome 2. E pesquisas outras revelaram poucas chances de conseguir qualquer coisa parecida sem muito trabalho. Não queria forçar o Cinnamon sobre o Unity, nem sair do ecosistema do Ubuntu para conseguir esse resultado específico no Mint. O Gnome Classic (fallback) também não parecia disponível sem muito trabalho.

Eis que no meio das pesquisas surge um tal Gnome Flashback, disponível para instalação e, depois disso, a um logout/login de distância do funcionamento. Nunca tinha ouvido falar, e meio derrotado fui tentar para ver de qual era.

E foi PERFEITO.

Eis um projeto que eu espero que viva para sempre.

Até me peguei pensando em quanto código era necessário para criar um ambiente assim. É literalmente o Gnome 2, rodando em bases modernas.

Se um dia ele se tornar instável, talvez ainda tente o Fallback. Mas até segunda ordem, é Flashback mesmo!

Sábias palavras de 2012

Magnífica analogia: “Gambiarra é Empréstimo de Produtividade”.

Se você não entendeu, veja a explicação aqui.

Já adianto que envolve mistureba generalizada de chão de fábrica em TI e economia clássica :)