Pular para conteúdo

CALCULATOR - Calculadora Matemática

O que é este Node?

O CALCULATOR é o node responsável por realizar cálculos matemáticos complexos com suporte a variáveis, expressões aritméticas e operações avançadas.

Por que este Node existe?

Flows precisam processar números e realizar cálculos. O CALCULATOR existe para:

  1. Cálculos dinâmicos: Processar valores capturados do usuário em tempo real
  2. Operações complexas: Suporta +, -, *, /, parênteses e múltiplas operações
  3. Uso de variáveis: Pode referenciar valores de outras partes do flow
  4. Segurança: Avalia expressões de forma segura sem permitir código arbitrário
  5. Formatação de resultados: Retorna valores numéricos prontos para uso

Como funciona internamente?

Quando o CALCULATOR é executado, o sistema:

  1. Recebe a expressão matemática com possíveis variáveis
  2. Substitui variáveis pelos valores do contexto ({{variavel}})
  3. Valida segurança - apenas caracteres permitidos: números, +, -, *, /, ., (, )
  4. Avalia a expressão de forma segura
  5. Retorna o resultado numérico
  6. Se inválido: Retorna erro com mensagem específica
  7. Se válido: Salva resultado para uso em próximos nodes

Código interno (ai-processing-executor.service.ts:604-648):

private async executeCalculator(parameters: any, context: any): Promise<any> {
  const { expression, variables: calcVariables } = parameters;

  this.logger.log(`🧮 CALCULATOR - Calculating: ${expression}`);

  if (!expression) {
    throw new Error('Expression is required for calculation');
  }

  try {
    // Replace variables in expression
    let processedExpression = expression;
    const allVariables = { ...context.variables, ...calcVariables };

    Object.keys(allVariables).forEach(key => {
      const placeholder = `{{${key}}}`;
      processedExpression = processedExpression.replace(
        new RegExp(placeholder, 'g'),
        allVariables[key]
      );
    });

    // Safe evaluation (in production, use a proper math expression evaluator)
    const allowedChars = /^[0-9+\-*/.() ]+$/;
    if (!allowedChars.test(processedExpression)) {
      throw new Error('Expression contains invalid characters');
    }

    const result = Function(`"use strict"; return (${processedExpression})`)();

    return {
      success: true,
      action: 'calculation_completed',
      expression: expression,
      processedExpression: processedExpression,
      result: result,
      resultType: typeof result,
      timestamp: new Date().toISOString()
    };
  } catch (error) {
    throw new Error(`Calculation failed: ${error.message}`);
  }
}

Quando você DEVE usar este Node?

Use CALCULATOR quando precisar de cálculos matemáticos:

Casos de uso

  1. Calcular totais: Somar múltiplos valores capturados
  2. Calcular descontos: Aplicar porcentagens sobre valores
  3. Conversões: Converter unidades (km para milhas, etc)
  4. Fórmulas: IMC, taxas, juros, proporções
  5. Preços dinâmicos: Calcular preço final com impostos/descontos
  6. Comissões: Calcular valores baseados em porcentagens

Quando NÃO usar CALCULATOR

Parâmetros Detalhados

expression (string, obrigatório)

O que é: A expressão matemática a ser calculada. Pode conter números, operadores (+, -, *, /, parênteses) e variáveis no formato {{variavel}}.

Operações suportadas:

  • Adição: +
  • Subtração: -
  • Multiplicação: *
  • Divisão: /
  • Parênteses: ( e )
  • Decimais: .

Flow completo para testar:

{
  "name": "Teste CALCULATOR - Expressão Simples",
  "nodes": [
    {
      "id": "start_1",
      "type": "start",
      "position": { "x": 100, "y": 100 },
      "data": { "label": "Início" }
    },
    {
      "id": "calculator_1",
      "type": "calculator",
      "position": { "x": 300, "y": 100 },
      "data": {
        "label": "Calcular",
        "parameters": {
          "expression": "(10 + 5) * 2"
        }
      }
    },
    {
      "id": "message_1",
      "type": "message",
      "position": { "x": 500, "y": 100 },
      "data": {
        "label": "Mostrar Resultado",
        "parameters": {
          "message": "Resultado: {{calculator_result}}"
        }
      }
    },
    {
      "id": "end_1",
      "type": "end",
      "position": { "x": 700, "y": 100 },
      "data": { "label": "Fim" }
    }
  ],
  "edges": [
    { "source": "start_1", "target": "calculator_1" },
    { "source": "calculator_1", "target": "message_1" },
    { "source": "message_1", "target": "end_1" }
  ]
}

Teste: O resultado será 30 (15 * 2)

variables (object, opcional)

O que é: Objeto contendo variáveis adicionais para usar na expressão. Variáveis do contexto também são automaticamente disponibilizadas.

Flow completo para testar:

{
  "name": "Teste CALCULATOR - Com Variáveis",
  "nodes": [
    {
      "id": "start_1",
      "type": "start",
      "position": { "x": 100, "y": 100 },
      "data": { "label": "Início" }
    },
    {
      "id": "number_1",
      "type": "number",
      "position": { "x": 300, "y": 100 },
      "data": {
        "label": "Pedir Valor",
        "parameters": {
          "message": "Digite o valor do produto:",
          "variable": "valor_produto",
          "decimals": 2
        }
      }
    },
    {
      "id": "calculator_1",
      "type": "calculator",
      "position": { "x": 500, "y": 100 },
      "data": {
        "label": "Calcular com Desconto",
        "parameters": {
          "expression": "{{valor_produto}} * 0.9",
          "variables": {}
        }
      }
    },
    {
      "id": "message_1",
      "type": "message",
      "position": { "x": 700, "y": 100 },
      "data": {
        "label": "Mostrar",
        "parameters": {
          "message": "Valor original: R$ {{valor_produto}}\nValor com 10% desconto: R$ {{calculator_result}}"
        }
      }
    },
    {
      "id": "end_1",
      "type": "end",
      "position": { "x": 900, "y": 100 },
      "data": { "label": "Fim" }
    }
  ],
  "edges": [
    { "source": "start_1", "target": "number_1" },
    { "source": "number_1", "target": "calculator_1" },
    { "source": "calculator_1", "target": "message_1" },
    { "source": "message_1", "target": "end_1" }
  ]
}

Teste: Digite 100 - o resultado será 90.00 (100 com 10% de desconto)

Parâmetros

Campo Tipo Obrigatório Descrição
expression string Sim Expressão matemática a calcular
variables object Não Variáveis adicionais para usar na expressão

Exemplo 1: Calcular IMC (Índice de Massa Corporal)

Objetivo: Capturar peso e altura do usuário e calcular o IMC automaticamente.

JSON para Importar

{
  "name": "Calculadora de IMC",
  "nodes": [
    {
      "id": "start_1",
      "type": "start",
      "position": { "x": 100, "y": 100 },
      "data": { "label": "Início" }
    },
    {
      "id": "message_1",
      "type": "message",
      "position": { "x": 300, "y": 100 },
      "data": {
        "label": "Boas-vindas",
        "parameters": {
          "message": "Calculadora de IMC\n\nVamos calcular seu Índice de Massa Corporal!"
        }
      }
    },
    {
      "id": "number_1",
      "type": "number",
      "position": { "x": 500, "y": 100 },
      "data": {
        "label": "Pedir Peso",
        "parameters": {
          "message": "Qual seu peso em kg?",
          "variable": "peso",
          "min": 30,
          "max": 300,
          "decimals": 1
        }
      }
    },
    {
      "id": "number_2",
      "type": "number",
      "position": { "x": 700, "y": 100 },
      "data": {
        "label": "Pedir Altura",
        "parameters": {
          "message": "Qual sua altura em metros? (Ex: 1.75)",
          "variable": "altura",
          "min": 1,
          "max": 2.5,
          "decimals": 2
        }
      }
    },
    {
      "id": "calculator_1",
      "type": "calculator",
      "position": { "x": 900, "y": 100 },
      "data": {
        "label": "Calcular IMC",
        "parameters": {
          "expression": "{{peso}} / ({{altura}} * {{altura}})"
        }
      }
    },
    {
      "id": "message_2",
      "type": "message",
      "position": { "x": 1100, "y": 100 },
      "data": {
        "label": "Mostrar Resultado",
        "parameters": {
          "message": "SEU IMC\n\nPeso: {{peso}} kg\nAltura: {{altura}} m\nIMC: {{calculator_result}}\n\nInterpretação:\n• Abaixo de 18.5: Abaixo do peso\n• 18.5 - 24.9: Peso normal\n• 25.0 - 29.9: Sobrepeso\n• Acima de 30: Obesidade"
        }
      }
    },
    {
      "id": "end_1",
      "type": "end",
      "position": { "x": 1300, "y": 100 },
      "data": { "label": "Fim" }
    }
  ],
  "edges": [
    { "source": "start_1", "target": "message_1" },
    { "source": "message_1", "target": "number_1" },
    { "source": "number_1", "target": "number_2" },
    { "source": "number_2", "target": "calculator_1" },
    { "source": "calculator_1", "target": "message_2" },
    { "source": "message_2", "target": "end_1" }
  ]
}

Saída esperada:

Sistema: Calculadora de IMC - Vamos calcular seu Índice de Massa Corporal!
Sistema: Qual seu peso em kg?
Usuário: 75.5
Sistema: Qual sua altura em metros? (Ex: 1.75)
Usuário: 1.75
Sistema: SEU IMC
Peso: 75.5 kg
Altura: 1.75 m
IMC: 24.65

Exemplo 2: Calcular Preço com Desconto e Frete

Objetivo: Calcular preço final de uma compra com desconto progressivo e frete.

JSON para Importar

{
  "name": "Calculadora de Preço Final",
  "nodes": [
    {
      "id": "start_1",
      "type": "start",
      "position": { "x": 100, "y": 100 },
      "data": { "label": "Início" }
    },
    {
      "id": "message_1",
      "type": "message",
      "position": { "x": 300, "y": 100 },
      "data": {
        "label": "Boas-vindas",
        "parameters": {
          "message": "Calculadora de Preço Final\n\nVamos calcular o valor da sua compra!"
        }
      }
    },
    {
      "id": "number_1",
      "type": "number",
      "position": { "x": 500, "y": 100 },
      "data": {
        "label": "Valor do Produto",
        "parameters": {
          "message": "Qual o valor do produto?",
          "variable": "valor",
          "min": 0.01,
          "decimals": 2
        }
      }
    },
    {
      "id": "number_2",
      "type": "number",
      "position": { "x": 700, "y": 100 },
      "data": {
        "label": "Quantidade",
        "parameters": {
          "message": "Quantas unidades?",
          "variable": "quantidade",
          "min": 1,
          "max": 100
        }
      }
    },
    {
      "id": "calculator_1",
      "type": "calculator",
      "position": { "x": 900, "y": 100 },
      "data": {
        "label": "Calcular Subtotal",
        "parameters": {
          "expression": "{{valor}} * {{quantidade}}"
        }
      }
    },
    {
      "id": "variable_1",
      "type": "variable",
      "position": { "x": 1100, "y": 100 },
      "data": {
        "label": "Salvar Subtotal",
        "parameters": {
          "name": "subtotal",
          "value": "{{calculator_result}}"
        }
      }
    },
    {
      "id": "calculator_2",
      "type": "calculator",
      "position": { "x": 1300, "y": 100 },
      "data": {
        "label": "Aplicar Desconto 15%",
        "parameters": {
          "expression": "{{subtotal}} * 0.85"
        }
      }
    },
    {
      "id": "variable_2",
      "type": "variable",
      "position": { "x": 1500, "y": 100 },
      "data": {
        "label": "Salvar Com Desconto",
        "parameters": {
          "name": "com_desconto",
          "value": "{{calculator_result}}"
        }
      }
    },
    {
      "id": "calculator_3",
      "type": "calculator",
      "position": { "x": 1700, "y": 100 },
      "data": {
        "label": "Adicionar Frete",
        "parameters": {
          "expression": "{{com_desconto}} + 15.90"
        }
      }
    },
    {
      "id": "message_2",
      "type": "message",
      "position": { "x": 1900, "y": 100 },
      "data": {
        "label": "Mostrar Resumo",
        "parameters": {
          "message": "RESUMO DO PEDIDO\n\nProduto: R$ {{valor}} x {{quantidade}} unidades\nSubtotal: R$ {{subtotal}}\nDesconto 15%: -R$ {{subtotal}} → R$ {{com_desconto}}\nFrete: +R$ 15.90\n\nTOTAL: R$ {{calculator_result}}"
        }
      }
    },
    {
      "id": "end_1",
      "type": "end",
      "position": { "x": 2100, "y": 100 },
      "data": { "label": "Fim" }
    }
  ],
  "edges": [
    { "source": "start_1", "target": "message_1" },
    { "source": "message_1", "target": "number_1" },
    { "source": "number_1", "target": "number_2" },
    { "source": "number_2", "target": "calculator_1" },
    { "source": "calculator_1", "target": "variable_1" },
    { "source": "variable_1", "target": "calculator_2" },
    { "source": "calculator_2", "target": "variable_2" },
    { "source": "variable_2", "target": "calculator_3" },
    { "source": "calculator_3", "target": "message_2" },
    { "source": "message_2", "target": "end_1" }
  ]
}

Saída esperada:

Sistema: Calculadora de Preço Final - Vamos calcular o valor da sua compra!
Sistema: Qual o valor do produto?
Usuário: 50.00
Sistema: Quantas unidades?
Usuário: 3
Sistema: RESUMO DO PEDIDO
Produto: R$ 50.00 x 3 unidades
Subtotal: R$ 150.00
Desconto 15%: -R$ 150.00 → R$ 127.50
Frete: +R$ 15.90
TOTAL: R$ 143.40

Exemplo 3: Calcular Porcentagem e Proporção

Objetivo: Demonstrar cálculos com porcentagens e proporções complexas.

JSON para Importar

{
  "name": "Cálculos de Porcentagem",
  "nodes": [
    {
      "id": "start_1",
      "type": "start",
      "position": { "x": 100, "y": 100 },
      "data": { "label": "Início" }
    },
    {
      "id": "message_1",
      "type": "message",
      "position": { "x": 300, "y": 100 },
      "data": {
        "label": "Introdução",
        "parameters": {
          "message": "Calculadora de Porcentagens\n\nVamos calcular várias porcentagens de um valor!"
        }
      }
    },
    {
      "id": "number_1",
      "type": "number",
      "position": { "x": 500, "y": 100 },
      "data": {
        "label": "Valor Base",
        "parameters": {
          "message": "Digite o valor base:",
          "variable": "valor_base",
          "decimals": 2
        }
      }
    },
    {
      "id": "calculator_1",
      "type": "calculator",
      "position": { "x": 700, "y": 50 },
      "data": {
        "label": "Calcular 10%",
        "parameters": {
          "expression": "{{valor_base}} * 0.10"
        }
      }
    },
    {
      "id": "variable_1",
      "type": "variable",
      "position": { "x": 900, "y": 50 },
      "data": {
        "label": "Salvar 10%",
        "parameters": {
          "name": "dez_porcento",
          "value": "{{calculator_result}}"
        }
      }
    },
    {
      "id": "calculator_2",
      "type": "calculator",
      "position": { "x": 700, "y": 150 },
      "data": {
        "label": "Calcular 25%",
        "parameters": {
          "expression": "{{valor_base}} * 0.25"
        }
      }
    },
    {
      "id": "variable_2",
      "type": "variable",
      "position": { "x": 900, "y": 150 },
      "data": {
        "label": "Salvar 25%",
        "parameters": {
          "name": "vinte_cinco_porcento",
          "value": "{{calculator_result}}"
        }
      }
    },
    {
      "id": "calculator_3",
      "type": "calculator",
      "position": { "x": 700, "y": 250 },
      "data": {
        "label": "Calcular 50%",
        "parameters": {
          "expression": "{{valor_base}} / 2"
        }
      }
    },
    {
      "id": "variable_3",
      "type": "variable",
      "position": { "x": 900, "y": 250 },
      "data": {
        "label": "Salvar 50%",
        "parameters": {
          "name": "cinquenta_porcento",
          "value": "{{calculator_result}}"
        }
      }
    },
    {
      "id": "merge_1",
      "type": "merge",
      "position": { "x": 1100, "y": 150 },
      "data": {
        "label": "Juntar Resultados"
      }
    },
    {
      "id": "message_2",
      "type": "message",
      "position": { "x": 1300, "y": 150 },
      "data": {
        "label": "Mostrar Todos",
        "parameters": {
          "message": "CÁLCULOS DE PORCENTAGEM\n\nValor Base: R$ {{valor_base}}\n\n10% = R$ {{dez_porcento}}\n25% = R$ {{vinte_cinco_porcento}}\n50% = R$ {{cinquenta_porcento}}"
        }
      }
    },
    {
      "id": "end_1",
      "type": "end",
      "position": { "x": 1500, "y": 150 },
      "data": { "label": "Fim" }
    }
  ],
  "edges": [
    { "source": "start_1", "target": "message_1" },
    { "source": "message_1", "target": "number_1" },
    { "source": "number_1", "target": "calculator_1" },
    { "source": "calculator_1", "target": "variable_1" },
    { "source": "number_1", "target": "calculator_2" },
    { "source": "calculator_2", "target": "variable_2" },
    { "source": "number_1", "target": "calculator_3" },
    { "source": "calculator_3", "target": "variable_3" },
    { "source": "variable_1", "target": "merge_1" },
    { "source": "variable_2", "target": "merge_1" },
    { "source": "variable_3", "target": "merge_1" },
    { "source": "merge_1", "target": "message_2" },
    { "source": "message_2", "target": "end_1" }
  ]
}

Saída esperada:

Sistema: Calculadora de Porcentagens - Vamos calcular várias porcentagens de um valor!
Sistema: Digite o valor base:
Usuário: 1000
Sistema: CÁLCULOS DE PORCENTAGEM
Valor Base: R$ 1000
10% = R$ 100
25% = R$ 250
50% = R$ 500

Exemplo 4: Conversão de Unidades

Objetivo: Converter valores entre diferentes unidades de medida.

JSON para Importar

{
  "name": "Conversor de Unidades",
  "nodes": [
    {
      "id": "start_1",
      "type": "start",
      "position": { "x": 100, "y": 100 },
      "data": { "label": "Início" }
    },
    {
      "id": "message_1",
      "type": "message",
      "position": { "x": 300, "y": 100 },
      "data": {
        "label": "Boas-vindas",
        "parameters": {
          "message": "Conversor de Unidades\n\nVamos converter Celsius para Fahrenheit!"
        }
      }
    },
    {
      "id": "number_1",
      "type": "number",
      "position": { "x": 500, "y": 100 },
      "data": {
        "label": "Temperatura Celsius",
        "parameters": {
          "message": "Digite a temperatura em Celsius:",
          "variable": "celsius",
          "min": -273.15,
          "decimals": 1
        }
      }
    },
    {
      "id": "calculator_1",
      "type": "calculator",
      "position": { "x": 700, "y": 100 },
      "data": {
        "label": "Converter para Fahrenheit",
        "parameters": {
          "expression": "({{celsius}} * 9 / 5) + 32"
        }
      }
    },
    {
      "id": "variable_1",
      "type": "variable",
      "position": { "x": 900, "y": 100 },
      "data": {
        "label": "Salvar Fahrenheit",
        "parameters": {
          "name": "fahrenheit",
          "value": "{{calculator_result}}"
        }
      }
    },
    {
      "id": "calculator_2",
      "type": "calculator",
      "position": { "x": 1100, "y": 100 },
      "data": {
        "label": "Converter para Kelvin",
        "parameters": {
          "expression": "{{celsius}} + 273.15"
        }
      }
    },
    {
      "id": "message_2",
      "type": "message",
      "position": { "x": 1300, "y": 100 },
      "data": {
        "label": "Mostrar Conversões",
        "parameters": {
          "message": "CONVERSÕES DE TEMPERATURA\n\nCelsius: {{celsius}}°C\nFahrenheit: {{fahrenheit}}°F\nKelvin: {{calculator_result}}K"
        }
      }
    },
    {
      "id": "end_1",
      "type": "end",
      "position": { "x": 1500, "y": 100 },
      "data": { "label": "Fim" }
    }
  ],
  "edges": [
    { "source": "start_1", "target": "message_1" },
    { "source": "message_1", "target": "number_1" },
    { "source": "number_1", "target": "calculator_1" },
    { "source": "calculator_1", "target": "variable_1" },
    { "source": "variable_1", "target": "calculator_2" },
    { "source": "calculator_2", "target": "message_2" },
    { "source": "message_2", "target": "end_1" }
  ]
}

Saída esperada:

Sistema: Conversor de Unidades - Vamos converter Celsius para Fahrenheit!
Sistema: Digite a temperatura em Celsius:
Usuário: 25
Sistema: CONVERSÕES DE TEMPERATURA
Celsius: 25°C
Fahrenheit: 77°F
Kelvin: 298.15K

Resposta do Node

{
  "success": true,
  "action": "calculation_completed",
  "expression": "{{peso}} / ({{altura}} * {{altura}})",
  "processedExpression": "75.5 / (1.75 * 1.75)",
  "result": 24.653061224489797,
  "resultType": "number",
  "timestamp": "2025-01-15T10:30:00.000Z"
}

Operações Matemáticas Suportadas

Operação Símbolo Exemplo Resultado
Adição + 10 + 5 15
Subtração - 10 - 5 5
Multiplicação * 10 * 5 50
Divisão / 10 / 5 2
Parênteses ( ) (10 + 5) * 2 30
Decimais . 10.5 * 2 21
Múltiplas operações - (100 - 20) * 1.1 88

Casos de Uso Comuns

Caso Expressão Descrição
IMC {{peso}} / ({{altura}} * {{altura}}) Índice de Massa Corporal
Desconto 10% {{valor}} * 0.9 Aplicar desconto de 10%
Desconto 15% {{valor}} * 0.85 Aplicar desconto de 15%
Acréscimo 10% {{valor}} * 1.1 Adicionar 10%
Calcular 30% {{valor}} * 0.30 Obter 30% do valor
Média ({{n1}} + {{n2}} + {{n3}}) / 3 Média de 3 números
Total com Frete {{subtotal}} + {{frete}} Somar frete ao subtotal
Celsius → Fahrenheit ({{celsius}} * 9 / 5) + 32 Converter temperatura
Comissão 5% {{vendas}} * 0.05 Calcular comissão
Juros simples {{valor}} * {{taxa}} * {{meses}} Calcular juros

Boas Práticas

SIM:

  • Use parênteses para garantir ordem de operações: (a + b) * c
  • Salve resultados intermediários em variáveis para cálculos complexos
  • Teste expressões simples antes de complicar
  • Use nomes de variáveis descritivos: {{valor_produto}} em vez de {{v}}
  • Combine com FORMATTER para exibir valores formatados

NÃO:

  • Não use caracteres especiais ou letras fora de variáveis
  • Não tente usar funções (sin, cos, log) - apenas operações básicas
  • Não divida por zero - valide inputs antes
  • Não use vírgula como decimal - use ponto: 10.5 não 10,5

Dicas

💡 Ordem de operações: O CALCULATOR segue ordem matemática padrão (parênteses, multiplicação/divisão, adição/subtração)

💡 Arredondamento: Use FORMATTER após CALCULATOR para formatar casas decimais: {{calculator_result}} → FORMATTER → "150.99"

💡 Variáveis do contexto: Todas as variáveis do flow estão disponíveis automaticamente sem precisar passar no parâmetro variables

💡 Validação: Use VALIDATOR antes do CALCULATOR para garantir que números são válidos

💡 Debug: Teste expressões simples primeiro, depois adicione complexidade gradualmente

💡 Performance: Cálculos são executados instantaneamente - sem delay

Expressões Avançadas

Calcular porcentagem de aumento/diminuição

Aumento: (({{novo}} - {{antigo}}) / {{antigo}}) * 100

Regra de três simples

{{valor1}} * {{valor3}} / {{valor2}}

Área do círculo

3.14159 * {{raio}} * {{raio}}

Teorema de Pitágoras

(({{a}} * {{a}}) + ({{b}} * {{b}}))

Próximo Node

FORMATTER - Formatar números e textos → VALIDATOR - Validar dados → VARIABLE - Salvar valores calculados