Я пытаюсь решить проблему, в которой мне нужно рассчитать питательную ценность рецепта, например «Мой бутерброд»
У меня есть база данных с «рецептами» и «ингредиентами» и необходимым количествомв кг.
рецепт может содержать ингредиенты, а также другие рецепты, которые затем могут содержать рецепты / ингредиенты.
Это пример "списка деталей" "Тестового сэндвича" собщий вес 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,
),
),
),
)
Как я могу уменьшить такую структуру до списка количества / веса каждого отдельного «конечного» ингредиента, такого как мука, вода, бананы, сыр, ветчина, кунжутсемена и т. д. *
Я написал эту функцию для запуска через структуру, но она на самом деле не выполняет свою работу (похоже, она правильно рассчитывает общий вес)
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
Текущий результат функции resolAssembly ():
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 кг «Тестового сэндвича»
Также, если это поможет, я использую эту систему для хранения этих рецептов: https://github.com/stevebauman/inventory/blob/v1.7/docs/ASSEMBLIES.md (но изменена для хранения десятичных чисел, а также отрицательных чисел (например,для обработки воды, потерянной или добавленной в процессе приготовления))
А вот все вычисления, сделанные для суммирования общего веса «Тестового сэндвича»:
"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"