Как я могу настроить свою формулу для непрерывного автоматического заполнения отсутствующего параметра?

#reactjs #typescript #algorithm

Вопрос:

Поэтому я создаю калькулятор/оценщик, который в основном является просто более сложной версией этого калькулятора маржи: https://www.omnicalculator.com/finance/margin

Итак, вот один крайний случай, который я пытаюсь исправить прямо сейчас.

Мои расходы разбиты на 3 части из — за переданных на аутсорсинг данных- рабочая сила, материалы и трудовые ресурсы. Труд и материал-это сумма труда и материала, но это может быть единственным известным фактором затрат, поэтому он разбит на 3 части.

Так вот в чем проблема. Допустим, мы знаем, что laborAndMaterial имеет значение 100, а рабочая сила и материал равны 0

 cost: {
  labor: 0,
  material: 0,
  laborAndMaterial: 100
}
 

Затем пользователь вводит 50 для оплаты труда. Поскольку laborAndMaterial равен 100, а рабочая сила теперь равна 50, мы можем автоматически заполнить материал до 50.

Но то, что происходит прямо сейчас, когда пользователь набирает «50», автоматически заполняет материал до 95, когда пользователь вводит 5 из 50. Затем, когда они вводят «0», он устанавливает значение laborAndMaterial равным 145 (50 95). Но в этом примере мне нужно настроить способ автоматического заполнения материала, чтобы он продолжал обновляться по мере того, как пользователь вводит больше цифр (трудозатраты = 5 -> 50 ->> 506) (материал = 95, 50, -406). На данный момент я в основном использую свою формулу, как:

 if(key === "cogs.labor") {
  if(laborAndMaterial > 0) {
    params["cogs.material"] = laborAndMaterial - value // value is what was entered
  }
}
 

Но мне все еще нужно учитывать другое преимущество, потому что, когда вводится рабочая сила и известен материал, он обновляет стоимость рабочей силы и материала

 cost {
  labor: 50,
  material: 50,
  laborAndMaterial: 100
}
 

Поэтому, если кто-то вводит 100 для рабочей силы, а мы знаем, что материал равен 50, мы можем автоматически заполнить рабочую силу и материал до 150.

Так что у меня есть что-то вроде:

 if(material > 0) {
  params["cogs.laborAndMaterial"] = material   value // value is what was entered
}
 

Есть какие-нибудь идеи, как я могу настроить свою формулу для определения автозаполнения и продолжить обновление этого параметра, сохраняя при этом возможность нескольких крайних случаев?

Калькулятор маржи от omnicalculator-хороший пример того, как они решили проблему, но я уже некоторое время ломаю над этим голову.

Ответ №1:

Я думаю, что вам в основном нужно различать, какие центры затрат рассматриваются как входные, а какие-как выходные. Поэтому, когда вы начинаете, каждый предоставленный вами фрагмент данных вводится, а данные, которые вы используете для автоматического заполнения остальной части формы, выводятся.

По мере ввода пользователем любая информация, которую они предоставляют, затем обрабатывается как входные данные. Учитывая, что любые два значения могут быть использованы для вычисления третьего, вы можете одновременно обрабатывать только два поля в качестве входных данных.

Вот пример кода, чтобы получить представление о том, что я имею в виду:

 // This is a queue to hold your two input cost centers
const inputFields = [];

// Determine the odd one out that we need to calculate
function getVariableCostCenter() {
    if (!inputFields.includes('labor')) {
        return 'labor';
    }

    if (!inputFields.includes('material')) {
        return 'material';
    }

    return 'laborAndMaterial';
}

function calculateCostCenters(costCenters) {
    const variableCostCenter = getVariableCostCenter();
    if (variableCostCenter === 'labor') {
        return {
            ...costCenters,
            labor: costCenters.laborAndMaterial - costCenters.material,
        };
    }

    if (variableCostCenter === 'material') {
        return {
            ...costCenters,
            material: costCenters.laborAndMaterial - costCenters.labor,
        };
    }

    return {
        ...costCenters,
        laborAndMaterial: costCenters.labor   costCenters.material,
    };
}

function initializeCostCenters(costCenters) {
    // First, we determine which field(s) are known up front
    if (costCenters.labor > 0) {
        inputFields.push('labor');
    }
    if (costCenters.material > 0) {
        inputFields.push('material');
    }
    if (costCenters.laborAndMaterial > 0 amp;amp; inputFields.length < 2) {
        inputFields.push('laborAndMaterial');
    }

    // ...then do whatever you normally do to populate the form
}

function updateCostCenters(previousCostCenters) {
    // Update the input fields so that the user's input
    // is always treated as one of the two input fields
    if (!inputFields.includes(key)) {
        inputFields.shift();
        inputFields.push(field);
    }

    const costCenters = calculateCostCenters({
        ...previousCostCenters,
        [key]: value,
    });

    params['cogs.labor'] = costCenters.labor;
    params['cogs.material'] = costCenters.material;
    params['cogs.laborAndMaterial'] = costCenters.laborAndMaterial;
}

 

Ответ №2:

Довольно приблизительно это может выглядеть так, как показано ниже.

Обратите внимание, что я помню последние touched поля, которые стали «фиксированными», потому что мы не можем пересчитывать значения по кругу.

Кроме того, обратите внимание, что я использую прямое обновление значений, в то время как в некоторых фреймворках/библиотеках оно может генерировать change/input событие, поэтому вы захотите установить значения молча.

 setup = {
  labor: {
    value: 0
  },
  material: {
    value: 0
  },
  laborAndMaterial: {
    value: 100
  }
};

// the number which we are treat as "fixed", may be changed later
let prevFixed = 'labor';
let fixed = 'labor';

const calculateTheRest = () => {
  if (!setup.material.touched amp;amp; !setup.laborAndMaterial.touched ||
    !setup.labor.touched amp;amp; !setup.laborAndMaterial.touched ||
    !setup.labor.touched amp;amp; !setup.material.touched) {
    return false; // two unknowns, can't recalculate
  }

  if (!setup.labor.touched || fixed !== 'labor' amp;amp; prevFixed !== 'labor') {
    setup.labor.value = setup.laborAndMaterial.value - setup.material.value;
  } else if (!setup.material.touched || fixed !== 'material' amp;amp; prevFixed !== 'material') {
    setup.material.value = setup.laborAndMaterial.value - setup.labor.value;
  } else {
    setup.laborAndMaterial.value = setup.material.value   setup.labor.value;
  }
}

const $els = {};
Object.keys(setup).forEach(key => $els[key] = document.querySelector('#'   key))

const onInputChanged = (e) => {
  const key = e.target.id;
  setup[key].value =  e.target.value;
  setup[key].touched = true;
  if (fixed !== key) {
    prevFixed = fixed;
    fixed = key;
  }
  calculateTheRest();
  Object.keys(setup).forEach(key => $els[key].value = setup[key].value);
}

Object.keys(setup).forEach(key => {
  $els[key].value = setup[key].value; // initial set
  setup[key].touched = setup[key].value !== 0; // 0 on initial setup are the numbers that not set
  $els[key].addEventListener('input', onInputChanged);
}) 
 <p><label>labor: <input id="labor" type="number"/></label></p>
<p><label>material: <input id="material" type="number"/></label></p>
<p><label> laborAndMaterial: <input id="laborAndMaterial" type="number" /></label></p> 

Ответ №3:

Я думаю, что вам нужно выполнить условие в вашей области труда и материалов.

Проверьте состояние: —

 if(labor > 0 amp;amp; material > 0){
    let laborAndMaterial = labor   material;
}
 

И после этого установите значение переменной laborAndMaterial в поле,

Я думаю, что это может вам помочь.

Комментарии:

1. Даже с этой проверкой я все равно столкнусь с проблемой, с которой я сталкиваюсь, когда условия не позволяют пользователю вводить последние 1 цифру (5 -> 50) и продолжать обновлять отсутствующий параметр, который больше не отсутствует после ввода первой цифры