如何计算每种成分的用量?

How to calculate the amount of each ingredient?

我正在尝试解决一个问题,我需要计算 "My sandwich"

等食谱的营养价值

我有一个包含 "recipes" 和 "ingredients" 的数据库以及以公斤为单位的所需数量。

一个食谱可以包含配料,但也可以包含其他食谱,然后又可以包含 recipes/ingredients。

这是一个 "part list" 的 "Test Sandwich" 的例子,总重量为 0.095 公斤。

array (
  0 => 
  array (
    'id' => 2,
    'name' => 'Test Cheese',
    'metric_id' => 1,
    'category_id' => NULL,
    'quantity' => 0.015,
    'depth' => 1,
  ),
  1 => 
  array (
    'id' => 3,
    'name' => 'Test Ham',
    'metric_id' => 1,
    'category_id' => NULL,
    'quantity' => 0.03,
    'depth' => 1,
  ),
  2 => 
  array (
    'id' => 4,
    'name' => 'Test Sesam Bread',
    'metric_id' => 1,
    'category_id' => NULL,
    'quantity' => 0.05,   // Only use some of the test bread (with added Sesam)
    'depth' => 1,
    'parts' => 
    array (
      0 => 
      array (
        'id' => 5,
        'name' => 'Test Bread',
        'metric_id' => 1,
        'category_id' => NULL,
        'quantity' => 1.0,         // This a recipe for 1 kg of banana bread 
        'depth' => 2,
        'parts' => 
        array (
          0 => 
          array (
            'id' => 6,
            'name' => 'Test Flour',
            'metric_id' => 1,
            'category_id' => NULL,
            'quantity' => 0.5,
            'depth' => 3,
          ),
          1 => 
          array (
            'id' => 7,
            'name' => 'Test Water',
            'metric_id' => 1,
            'category_id' => NULL,
            'quantity' => 0.3,
            'depth' => 3,
          ),
          2 => 
          array (
            'id' => 8,
            'name' => 'Test Yeast',
            'metric_id' => 1,
            'category_id' => NULL,
            'quantity' => 0.05,
            'depth' => 3,
          ),
          3 => 
          array (
            'id' => 9,
            'name' => 'Test Banan',
            'metric_id' => 1,
            'category_id' => NULL,
            'quantity' => 0.15,
            'depth' => 3,
          ),
        ),
      ),
      1 => 
      array (
        'id' => 10,
        'name' => 'Test Sesam Seeds',
        'metric_id' => 1,
        'category_id' => NULL,
        'quantity' => 0.1,
        'depth' => 2,
      ),
    ),
  ),
)

我怎样才能将这样的结构缩减为每个 "end" 成分的 amount/weight 列表,例如面粉、水、香蕉、奶酪、火腿、芝麻等?

我通过结构将这个函数写到运行,但它并没有真正完成工作(似乎它正确计算了总重量)

function resolveAssembly($items, $number = 1, $declaration = [])
{
    $weight = 0;

    foreach ($items as $item) {
        // Get the quantity (weight) of the item
        $amount = $item['quantity'];

        // Check if the item also contains an ingredients list
        if (array_key_exists('parts', $item)) {

            // Get the total weight of the whole assembly
            list($assembly_weight, $assembly_declaration) = resolveAssembly($item['parts'], $number * $amount, $declaration);

            $declaration = array_merge($declaration, $assembly_declaration);

            // Calculate the relative weight of each part in the assembly
            foreach ($item['parts'] as $part) {
                $weight = $weight + ($amount / $assembly_weight) * $part['quantity'];
            }
        } else {
            // Add the amount to the declaration
            if (!array_key_exists($item['name'], $declaration)) {
                $declaration[$item['name']] =  $number * $amount;
            }

            $weight = $weight + $amount;
        }
    }

    return [$weight, $declaration];
}

编辑:合并程序集声明数组

我是这样使用上面的函数的:

$item = Inventory::findOrFail(1); // Get "Test sandwich"
$parts = $item->getAssemblyItemsList(); // Get the parts of the "Test sandwich"
$result = resolveAssembly($parts, 1); // Get total weight of 1 "Test sandwich" + a list of amount/weight of each ingredient

resolveAssembly() 函数的当前结果:

0.095
[
  "Test Cheese" => 0.015
  "Test Ham" => 0.03
  "Test Flour" => 0.025
  "Test Water" => 0.015
  "Test Yeast" => 0.0025
  "Test Banan" => 0.0075
  "Test Sesam Seeds" => 0.005 // Should have been factored in the bread ingredients
]

但不太对,加起来应该是 0.095,所以我认为测试芝麻不在面包的成分(面粉、酵母、香蕉等)中。

0.015+0.03+0.025+0.015+0.0025+0.0075+0.005 = 0.1 公斤 "Test Sandwich"

此外,如果这有帮助,我正在使用这个系统来存储这些食谱:https://github.com/stevebauman/inventory/blob/v1.7/docs/ASSEMBLIES.md(但经过修改以存储十进制数和负数(例如处理在烹饪过程中丢失或添加的水) )

这里是对 "Test Sandwich" 的总重量求和的所有计算:

"Test Cheese: 0 + 0.015 = 0.015"

"Test Ham: 0.015 + 0.03 = 0.045"

"Test Flour: 0 + 0.5 = 0.5"

"Test Water: 0.5 + 0.3 = 0.8"

"Test Yeast: 0.8 + 0.05 = 0.85"

"Test Banan: 0.85 + 0.15 = 1"

"Test Flour: 0 + (1 / 1) * 0.5 = 0.5"

"Test Water: 0.5 + (1 / 1) * 0.3 = 0.8"

"Test Yeast: 0.8 + (1 / 1) * 0.05 = 0.85"

"Test Banan: 0.85 + (1 / 1) * 0.15 = 1"

"Test Sesam Seeds: 1 + 0.1 = 1.1"

"Test Bread: 0.045 + (0.05 / 1.1) * 1 = 0.09045454545"

"Test Sesam Seeds: 0.090454545454545 + (0.05 / 1.1) * 0.1 = 0.095"

这会让你们更接近:

function resolveAssembly($items) {
    $weight = 0;
    $declaration = [];
    foreach ($items as $item) {
        $weight += $item['quantity'];
        if (array_key_exists('parts', $item)) {
            // if there are parts, get the full weight and declaration for the sub item
            list($sub_total_weight, $sub_declaration) = resolveAssembly($item['parts']);
            foreach ($sub_declaration as $sub_name => $sub_weight) {
                if (!array_key_exists($sub_name, $declaration)) {
                    $declaration[$sub_name] = 0;
                }
                // Total weight of particular ingredient is the sub items ingredient out of the sub items full weight
                // times the quantity for this particular item
                $declaration[$sub_name] += $item['quantity'] * ($sub_weight / $sub_total_weight);
            }
        } else {
            // if there are no parts, just add the quantity
            if (!array_key_exists($item['name'], $declaration)) {
                $declaration[$item['name']] = 0;
            }
            $declaration[$item['name']] += $item['quantity'];
        }
    }
    return [$weight, $declaration];
}

这会给你这样的结果:

array(2) {
    [0]=>
  float(0.095)
  [1]=>
  array(7) {
        ["Test Cheese"]=>
    float(0.015)
    ["Test Ham"]=>
    float(0.03)
    ["Test Flour"]=>
    float(0.022727272727273)
    ["Test Water"]=>
    float(0.013636363636364)
    ["Test Yeast"]=>
    float(0.0022727272727273)
    ["Test Banan"]=>
    float(0.0068181818181818)
    ["Test Sesam Seeds"]=>
    float(0.0045454545454545)
  }
}

如果你把上面的数字加起来,它们的总和应该是 0.095。

基本上,当你在做 'sub recipe' 时,你需要知道那个食谱的总数 'weight' 是多少,然后你可以根据那个子的数量计算出实际的物品总数.