Arquitetura-Sistema de Fórmulas

Tenho que fazer um sistema aqui(usando Menta+MySQL5) que é o seguinte:

O Administrador pode cadastrar/alterar/excluir usuários e fórmulas.
Os usuários do sistema usam as fórmulas para gerarem uma planilha de cálculo(simples, só com data de início, de fim e uns 2 ou 3 índices e o resultado).
Meu problema:
o ADMIN cadastra cada fórmula nesse formato(há algumas mais simples):
0,35 X MO + 0,30 X C + 0,20 X FAD + 0,15 X CS
e atribui a ela um número, por exemplo 35.
Na página de consulta que o usuário irá gerar os dados, tem um espaço onde ele irá digitar o número da fórmula que quer usar(por exemplo 35) e depois apertar o botão para gerar os dados .Minha pergunta é: Como gravar essa fórmula de forma decente no BD(MySQL)???
Tô sentindo que vou ter que deixar o ADMIN gravar + ou - nesse formato(digitando todos os valores das constantes):
0,35 X 1,433 + 0,30 X 2,9018 + 0,20 X 2,13 + 0,15 X 1,371
e gravar como texto para depois usar REGEX para substituir por operadores java para que o cálculo possa ser executado.
Sim, é um programa que visa substituir uma aplicação de uma planilha Excel, mas fora esse problema, é super simples, + ou - isso:

Usuario(ID_USUARIO,NOME,NOME_USUARIO,EMPRESA,EMAIL,PERFIL,CONSULTA)
Histórico(ID_USUARIO,OPERACAO,DT_OPERACAO)
Formula(num_formula,grupo_mercadoria,den_grupo_mercadoria,formula_parametrica)
Indices()
Cotacoes()
*O Histórico é pq cada movimento(Consulta,Exclusão,Inserção) é gravada no banco.

Mas quanto as fórmulas, não sei a melhor forma.Sinto um forte cheiro de P.O.G. no ar…damn

Não tem problema gravar texto com elas no banco. Muito melhor que gravar o ast delas. O POG é usar regexp para o parsing.

Não se usam expressões regulares para efetuar parsing, porque expressões regulares não sabem contar parênteses.
Isso é fato.
Em Perl (onde você usa expressões regulares até para coisas que não deveriam ser feitas com expressões regulares) talvez seja possível fazer isso (contar parênteses), mas de uma maneira muito incompreensível para o mero mortal.
Você pode trocar “X” por “*”, no máximo (ao usar expressões regulares), e passar isso para o módulo JavaScript Rhino para poder avaliar suas expressões (se você estiver usando Java 6.0, é claro), mas provavelmente você vai precisar alguma outra coisa.

Pergunta estúpida número 1 - se isso está substituindo uma planilha Excel, por que é que está sendo feita a multiplicação com X em vez de usar o operador de multiplicação padrão “*” ? Nunca vi multiplicar no Excel usando “X”.

Não foi pergunta estúpida, e não estarão usando X não!!!Fui eu que pûs para ilustrar a multiplicação.Eu posso treinar o admin para usar a sintaxe igual ao excel/java, esse não é o problema.Só achei que seria esquisito colocar as fórmulas como texto simples.Tô usando o Mustang sim.

Procure por Java Math Expression Parser (JEP). Dá para substituir variáveis. Não sei se se aplica a constantes.
(teoricamente uma constante é uma variável que tem sempre o mesmo valor)

Olá,

Eu também precisei fazer algo parecido (interpretar fórmulas cadastradas pelo usuário) e usei o GroovyShell. Simples de usar e resolveu meu problema.

[]´s

Parece punk, mas assim como o Abacus, a licença parece que virou paga… :x
Detesto quando ocorre isso…parece má fé, esperam o troço ter uma “base instalada” grande e depois fecham.

Parece interessante, vou dar uma estudada.Mas nem sei se será tão necessário, pois a fórmula mais complexa não passa daquela que eu pûs acima.Talvez se eu treinar o admin para “digitar direitinho” respeitando parênteses, é só eu pegar do banco/converter o necessário e tacar o resultado num BD/double da vida.

Desenterrando essa APP:

sergiotaborda não posso usar o JEP que é pago.
Mas gostaria de saber se há alternativas a gambiarras bem porcas do tipo(explicando):
Quando o usuário digita o número da fórmula, por exemplo “17” dá essa:
0,20MO+0,80PI
Faço um select que retorna todos os Indicadores(MO,US$,Fe…30 no total),
faço uma “extração” dos Indicadores da fórmula(REGEX…arghh???), no caso
MO e PI e comparo com o que foi retornado do banco.Após comparar, substituo
o MO e o PI pelos valores correspondentes(tipo 1,231117) e executo o cálculo
para mostrar ao usuário.O usuário não digita a fórmula, ela já estará salva(como texto)
na Base de dados, ele apenas digita o número dela e pressiona “Confirmar”.
As fórmulas pouco sofrem alterações, mas os indicadores mudam uma vez por mês.

Blz Iron,

até onde eu conheço, dos produtos open-source, o commons do jakarta são os melhores,

mas segue um código de parse que fiz para uma situação semelhante a sua, em que acabei tendo que desenvolver uma interface semelhante a uma planilha, tive até que fazer um método que permitia colar do excel na minha aplicação…

Tem mais uma coisa, se você criar uma árvore com a expressão e passar ela para o pós-ordem, você poderá dispensar os parenteses… notação polonesa hehe.

mas segue o código em anexo.

até mais,

Dieval

Dieval Guizelini
Tô dando uma lida no seu exemplo aqui, valeu.O meu prog pelo que tô vendo é até mais simples, pois minhas fórmulas só possuem as 4 operações.A única coisa chata é que eu acho que não dá muito para me livrar da Gambiarra de usar REGEX antes de passar os dados para a fórmula(ou seja, pesquisa no BD, taca tudo num Collection da vida, quebra a fórmula em string e ver qual bate para depois executar o cálculo). :slight_smile:

Adoro sistemas que mudam de requisitos em andamento! :evil: :roll:

Dieval Guizelini
Se não for fechado, vc teria o código do pack br.ufpr.et.fancalc.planilha.* ? Descobri agora que eu preciso do mesmo que vc fez, colar e copiar com interface semelhante a uma planilha.Vc usou POI???

O código que você quer se encontra na classe PlanilhaPanel…

// // Copia da área de transferência para o jTable // if (e.getActionCommand().compareTo("Paste")==0) { int startRow=(table.getSelectedRows())[0]; int startCol=(table.getSelectedColumns())[0]; String rowstring,value; try { String trstring= (String)(system.getContents(this).getTransferData(DataFlavor.stringFlavor)); StringTokenizer st1=new StringTokenizer(trstring,"\n"); for(int i=0;st1.hasMoreTokens();i++) { rowstring=st1.nextToken(); StringTokenizer st2=new StringTokenizer(rowstring,"\t"); for(int j=0;st2.hasMoreTokens();j++) { value=(String)st2.nextToken(); // if (startRow+i < table.getRowCount() && // startCol+j< jTable1.getColumnCount()) table.setValueAt(value,startRow+i,startCol+j); } } } catch(Exception ex){ex.printStackTrace();} table.updateUI(); }

Como os dados do excel estavam na área de transferência eu não tive que usar API externas…

até mais,

Dieval

MyBad, não me expliquei direito.Eu sei como fazer o copynpaste.Mas lendo o seu código, não entendi como vc mentou a Planilha(Vc não botou o código da Planilha), e nem entendi direito o que seria FormulaConteudo.

EDIT.:Já vi que vc usou double.Valeu! :smiley:

Dieval, tô fazendo alguns testes aqui e funciona maravilhosamente bem(claro, ás vezes é necessário pôr uns parênteses em alguns lugares para ter uma ordem correta de precedência), e eu estive pensando: geralmente o pessoal fala para usar o GroovyShell já que não há nada pronto para isso em java(claro, se não tiver pique para baixar o JScience).Eu penso que isso pode ser útil para o BU(BrazilUtils).Para funcionar como String(não usando os detalhes da planilha), é só mudar a classe TokenNo mesmo.Eu lhe pergunto, vc tem algum problema se colocar essa parte de cálculo simples de expressões(umas 12 classes pelo que vejo aqui) no BU?(Ah, os créditos serão dados a ti, óbvio).