Spaces:
Sleeping
Sleeping
Update nutri_call.html
Browse files- nutri_call.html +34 -192
nutri_call.html
CHANGED
@@ -1071,6 +1071,8 @@ document.getElementById('calculate-btn').addEventListener('click', function () {
|
|
1071 |
|
1072 |
calculateMicroElements();
|
1073 |
|
|
|
|
|
1074 |
// Рассчитываем EC
|
1075 |
const temperature = parseFloat(document.getElementById('profile_temp').value) || 25;
|
1076 |
const ecValue = calculateEC(call_data, temperature);
|
@@ -1257,8 +1259,8 @@ function calculateCationsAndAnions() {
|
|
1257 |
// 9. Обновление UI
|
1258 |
document.getElementById("n1-value").textContent =
|
1259 |
`Катионы: ${totalCations.toFixed(2)} mEq/L | Анионы: ${totalAnions.toFixed(2)} mEq/L`;
|
1260 |
-
|
1261 |
-
|
1262 |
document.getElementById("anion-indicator").style.width = `${anionPercent}%`;
|
1263 |
}
|
1264 |
|
@@ -1375,6 +1377,35 @@ function calculateMicroElements() {
|
|
1375 |
|
1376 |
console.log("=== РАСЧЕТ PPM ===", ppm);
|
1377 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1378 |
|
1379 |
</script>
|
1380 |
|
@@ -1405,199 +1436,10 @@ function showCalculationStatus(response) {
|
|
1405 |
}
|
1406 |
}
|
1407 |
</script>
|
1408 |
-
<script>
|
1409 |
-
const INPUT_DATA = {
|
1410 |
-
fertilizerConstants: {
|
1411 |
-
"Кальциевая селитра": { "N (NO3-)": 0.11863, "Ca": 0.16972 },
|
1412 |
-
"Калий азотнокислый": { "N (NO3-)": 0.13854, "K": 0.36672 },
|
1413 |
-
"Аммоний азотнокислый": { "N (NO3-)": 0.17499, "N (NH4+)": 0.17499 },
|
1414 |
-
"Сульфат магния": { "Mg": 0.10220, "S": 0.13483 },
|
1415 |
-
"Монофосфат калия": { "P": 0.22761, "K": 0.28731 },
|
1416 |
-
"Калий сернокислый": { "K": 0.44874, "S": 0.18401 },
|
1417 |
-
"Кальций хлорид": { "Ca": 0.272, "Cl": 0.483 } // Хлор теперь учитывается
|
1418 |
-
},
|
1419 |
-
profileSettings: {
|
1420 |
-
"P": 60, "K": 194, "Mg": 48.5, "Ca": 89.25, "S": 79.445, "CaCl": 38.5, // Добавлен Cl
|
1421 |
-
"NO3_RAT": 1.5, "TOTAL_NITROG": 138.57, "liters": 100
|
1422 |
-
}
|
1423 |
-
};
|
1424 |
|
1425 |
-
class NutrientCalculator {
|
1426 |
-
constructor(inputData) {
|
1427 |
-
this.fertilizers = inputData.fertilizerConstants;
|
1428 |
-
this.profile = inputData.profileSettings;
|
1429 |
-
this.volume = this.profile.liters;
|
1430 |
-
|
1431 |
-
const totalParts = this.profile.NO3_RAT + 1;
|
1432 |
-
this.target = {
|
1433 |
-
'P': this.profile.P,
|
1434 |
-
'K': this.profile.K,
|
1435 |
-
'Mg': this.profile.Mg,
|
1436 |
-
'Ca': this.profile.Ca, // Общий кальций
|
1437 |
-
'S': this.profile.S,
|
1438 |
-
'N (NO3-)': this.profile.TOTAL_NITROG * (this.profile.NO3_RAT / totalParts),
|
1439 |
-
'N (NH4+)': this.profile.TOTAL_NITROG * (1 / totalParts)
|
1440 |
-
};
|
1441 |
-
|
1442 |
-
this.actual = Object.fromEntries(Object.keys(this.target).map(k => [k, 0.0])); // CaCl не учитываем в фактическом балансе
|
1443 |
-
this.results = Object.fromEntries(Object.keys(this.fertilizers).map(fert => [fert, { граммы: 0.0 }]));
|
1444 |
-
}
|
1445 |
-
|
1446 |
-
calculate() {
|
1447 |
-
// 1. Вносим аммонийный азот
|
1448 |
-
this._applyFertilizer("Аммоний азотнокислый", "N (NH4+)", this.target["N (NH4+)"]);
|
1449 |
-
|
1450 |
-
// 2. Вносим фосфор
|
1451 |
-
this._applyFertilizer("Монофосфат калия", "P", this.target.P);
|
1452 |
-
|
1453 |
-
// 3. Вносим магний
|
1454 |
-
this._applyFertilizer("Сульфат магния", "Mg", this.target.Mg);
|
1455 |
-
|
1456 |
-
// 4. Балансируем калий и серу
|
1457 |
-
this._balanceKS();
|
1458 |
-
|
1459 |
-
// 5. Распределяем кальций между селитрой и хлоридом
|
1460 |
-
this._distributeCalcium();
|
1461 |
-
|
1462 |
-
// 6. Компенсируем NO3 калийной селитрой
|
1463 |
-
const no3Needed = this.target["N (NO3-)"] - this.actual["N (NO3-)"];
|
1464 |
-
if (no3Needed > 0) {
|
1465 |
-
this._applyFertilizer("Калий азотнокислый", "N (NO3-)", no3Needed);
|
1466 |
-
}
|
1467 |
-
|
1468 |
-
return this._verifyResults();
|
1469 |
-
}
|
1470 |
-
|
1471 |
-
_applyFertilizer(name, element, targetPPM) {
|
1472 |
-
if (!this.fertilizers[name]) {
|
1473 |
-
throw new Error(`Удобрение '${name}' не найдено в fertilizerConstants!`);
|
1474 |
-
}
|
1475 |
-
|
1476 |
-
const content = this.fertilizers[name][element] || 0; // Получаем содержание элемента
|
1477 |
-
if (content === 0) {
|
1478 |
-
console.warn(`ПРЕДУПРЕЖДЕНИЕ: Удобрение '${name}' не содержит элемент '${element}'`);
|
1479 |
-
return;
|
1480 |
-
}
|
1481 |
-
|
1482 |
-
const grams = (targetPPM * this.volume) / (content * 1000);
|
1483 |
-
this.results[name].граммы += grams;
|
1484 |
-
|
1485 |
-
for (const [el, val] of Object.entries(this.fertilizers[name])) {
|
1486 |
-
const addedPPM = (grams * val * 1000) / this.volume;
|
1487 |
-
if (el in this.actual) {
|
1488 |
-
this.actual[el] += addedPPM;
|
1489 |
-
}
|
1490 |
-
}
|
1491 |
-
}
|
1492 |
|
1493 |
-
|
1494 |
-
const kNeeded = this.target.K - this.actual.K;
|
1495 |
-
const sNeeded = this.target.S - this.actual.S;
|
1496 |
-
|
1497 |
-
if (kNeeded > 0 && sNeeded > 0) {
|
1498 |
-
const kFromK2SO4 = Math.min(kNeeded, sNeeded * 0.44874 / 0.18401);
|
1499 |
-
this._applyFertilizer("Калий сернокислый", "K", kFromK2SO4);
|
1500 |
-
}
|
1501 |
-
|
1502 |
-
const remainingK = this.target.K - this.actual.K;
|
1503 |
-
if (remainingK > 0) {
|
1504 |
-
this._applyFertilizer("Калий азотнокислый", "K", remainingK);
|
1505 |
-
}
|
1506 |
-
}
|
1507 |
-
|
1508 |
-
_distributeCalcium() {
|
1509 |
-
const caTarget = this.target.Ca; // Общий кальций
|
1510 |
-
|
1511 |
-
// Проверка соотношения NO3/NH4
|
1512 |
-
const no3Ratio = this.profile.NO3_RAT;
|
1513 |
-
if (no3Ratio >= 8) { // Если соотношение NO3/NH4 >= 8, кальций хлористый не добавляется
|
1514 |
-
console.log("Соотношение NO3/NH4 >= 8. Кальций хлористый не добавляется.");
|
1515 |
-
var remainingCa = caTarget;
|
1516 |
-
} else {
|
1517 |
-
// 1. Определяем, сколько кальция взять из хлористого кальция
|
1518 |
-
const caclRatio = 0.3; // Например, 50% кальция берем из хлористого кальция
|
1519 |
-
const caclTarget = caTarget * caclRatio;
|
1520 |
-
|
1521 |
-
// 2. Вносим кальций из хлористого кальция
|
1522 |
-
if (caclTarget > 0) {
|
1523 |
-
this._applyFertilizer("Кальций хлорид", "Ca", caclTarget); // Исправлено на "Кальций хлорид"
|
1524 |
-
}
|
1525 |
-
|
1526 |
-
// 3. Оставшийся кальций берем из кальциевой селитры
|
1527 |
-
remainingCa = caTarget - caclTarget;
|
1528 |
-
}
|
1529 |
-
|
1530 |
-
// Добавляем оставшийся кальций из кальциевой селитры
|
1531 |
-
if (remainingCa > 0) {
|
1532 |
-
this._applyFertilizer("Кальциевая селитра", "Ca", remainingCa);
|
1533 |
-
}
|
1534 |
-
}
|
1535 |
-
|
1536 |
-
_verifyResults() {
|
1537 |
-
const deficits = {};
|
1538 |
-
for (const el in this.target) {
|
1539 |
-
const diff = this.target[el] - this.actual[el];
|
1540 |
-
if (Math.abs(diff) > 0.1) {
|
1541 |
-
deficits[el] = parseFloat(diff.toFixed(3));
|
1542 |
-
}
|
1543 |
-
}
|
1544 |
-
|
1545 |
-
return {
|
1546 |
-
fertilizers: Object.fromEntries(Object.entries(this.results).map(([k, v]) => [k, parseFloat(v.граммы.toFixed(3))])),
|
1547 |
-
actualProfile: Object.fromEntries(Object.entries(this.actual).map(([k, v]) => [k, parseFloat(v.toFixed(3))])),
|
1548 |
-
deficits: deficits,
|
1549 |
-
totalPPM: parseFloat(Object.values(this.actual).reduce((sum, val) => sum + val, 0).toFixed(3))
|
1550 |
-
};
|
1551 |
-
}
|
1552 |
-
|
1553 |
-
generateReport(results) {
|
1554 |
-
let fertTable = [];
|
1555 |
-
for (const [name, data] of Object.entries(results.fertilizers)) {
|
1556 |
-
fertTable.push([name, `${data} г`]);
|
1557 |
-
}
|
1558 |
-
|
1559 |
-
let elementTable = [];
|
1560 |
-
for (const el of Object.keys(this.target).sort()) {
|
1561 |
-
if (el === "CaCl") continue; // Пропускаем CaCl в отчете
|
1562 |
-
elementTable.push([
|
1563 |
-
el,
|
1564 |
-
`${this.target[el]} ppm`,
|
1565 |
-
`${results.actualProfile[el]} ppm`,
|
1566 |
-
`${parseFloat((results.actualProfile[el] - this.target[el]).toFixed(2))} ppm`
|
1567 |
-
]);
|
1568 |
-
}
|
1569 |
-
|
1570 |
-
let report = "РЕКОМЕНДУЕМЫЕ УДОБРЕНИЯ:\n";
|
1571 |
-
report += this._formatTable(fertTable, ["Удобрение", "Количество"]);
|
1572 |
-
|
1573 |
-
report += "\n\nБАЛАНС ЭЛЕМЕНТОВ:\n";
|
1574 |
-
report += this._formatTable(elementTable, ["Элемент", "Цель", "Факт", "Отклонение"]);
|
1575 |
-
|
1576 |
-
report += `\n\nОбщая концентрация: ${results.totalPPM} ppm`;
|
1577 |
-
|
1578 |
-
if (Object.keys(results.deficits).length > 0) {
|
1579 |
-
report += "\n\nВНИМАНИЕ: Обнаружены небольшие отклонения:";
|
1580 |
-
for (const [el, diff] of Object.entries(results.deficits)) {
|
1581 |
-
report += `\n- ${el}: не хватает ${Math.abs(diff)} ppm`;
|
1582 |
-
}
|
1583 |
-
}
|
1584 |
-
|
1585 |
-
return report;
|
1586 |
-
}
|
1587 |
-
|
1588 |
-
_formatTable(data, headers) {
|
1589 |
-
const table = [headers, ...data];
|
1590 |
-
const columnWidths = headers.map((_, i) => Math.max(...table.map(row => row[i].toString().length)));
|
1591 |
-
const formatRow = row => row.map((cell, i) => cell.padEnd(columnWidths[i])).join(" | ");
|
1592 |
-
return table.map(formatRow).join("\n");
|
1593 |
-
}
|
1594 |
-
}
|
1595 |
|
1596 |
-
// Запуск расчета
|
1597 |
-
const calculator = new NutrientCalculator(INPUT_DATA);
|
1598 |
-
const results = calculator.calculate();
|
1599 |
-
console.log(calculator.generateReport(results));
|
1600 |
-
</script>
|
1601 |
|
1602 |
|
1603 |
<script src="https://unpkg.com/tippy.js@6"></script>
|
|
|
1071 |
|
1072 |
calculateMicroElements();
|
1073 |
|
1074 |
+
calculateN1Ratio(call_data);
|
1075 |
+
|
1076 |
// Рассчитываем EC
|
1077 |
const temperature = parseFloat(document.getElementById('profile_temp').value) || 25;
|
1078 |
const ecValue = calculateEC(call_data, temperature);
|
|
|
1259 |
// 9. Обновление UI
|
1260 |
document.getElementById("n1-value").textContent =
|
1261 |
`Катионы: ${totalCations.toFixed(2)} mEq/L | Анионы: ${totalAnions.toFixed(2)} mEq/L`;
|
1262 |
+
|
1263 |
+
|
1264 |
document.getElementById("anion-indicator").style.width = `${anionPercent}%`;
|
1265 |
}
|
1266 |
|
|
|
1377 |
|
1378 |
console.log("=== РАСЧЕТ PPM ===", ppm);
|
1379 |
}
|
1380 |
+
|
1381 |
+
|
1382 |
+
|
1383 |
+
|
1384 |
+
// Функция для расчета соотношений и формирования строки
|
1385 |
+
function calculateN1Ratio(data) {
|
1386 |
+
// Получаем значения элементов из ответа сервера
|
1387 |
+
const { actual_profile, total_ppm } = response;
|
1388 |
+
const { P, K, Ca, Mg, S } = actual_profile;
|
1389 |
+
|
1390 |
+
// Общий азот (N_total) = N (NH4+) + N (NO3-)
|
1391 |
+
const N_total = actual_profile["N (NH4+)"] + actual_profile["N (NO3-)"];
|
1392 |
+
|
1393 |
+
// Вычисляем соотношения относительно общего азота (принимаем его за единицу)
|
1394 |
+
const P_ratio = (P / N_total).toFixed(2);
|
1395 |
+
const K_ratio = (K / N_total).toFixed(2);
|
1396 |
+
const CaO_ratio = (Ca / N_total).toFixed(2); // Предполагается, что Ca - это оксид кальция
|
1397 |
+
const MgO_ratio = (Mg / N_total).toFixed(2); // Предполагается, что Mg - это оксид магния
|
1398 |
+
const SO_ratio = (S / N_total).toFixed(2); // Предполагается, что S - это оксид серы
|
1399 |
+
|
1400 |
+
// Формируем строку в требуемом формате
|
1401 |
+
const n1String = `${P_ratio}:${K_ratio}:${CaO_ratio}:${MgO_ratio}:${SO_ratio} PPM=${total_ppm.toFixed(2)}`;
|
1402 |
+
|
1403 |
+
// Вставляем строку в HTML
|
1404 |
+
document.getElementById("n1-value").textContent = n1String;
|
1405 |
+
}
|
1406 |
+
|
1407 |
+
|
1408 |
+
|
1409 |
|
1410 |
</script>
|
1411 |
|
|
|
1436 |
}
|
1437 |
}
|
1438 |
</script>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1439 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1440 |
|
1441 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1442 |
|
|
|
|
|
|
|
|
|
|
|
1443 |
|
1444 |
|
1445 |
<script src="https://unpkg.com/tippy.js@6"></script>
|