DmitrMakeev commited on
Commit
2fa1074
·
verified ·
1 Parent(s): 595eef3

Update nutri_call.html

Browse files
Files changed (1) hide show
  1. nutri_call.html +191 -1
nutri_call.html CHANGED
@@ -1399,8 +1399,198 @@ function showCalculationStatus(response) {
1399
  }
1400
  }
1401
  </script>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1402
 
 
 
 
1403
 
1404
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1405
  </body>
1406
  </html>
 
1399
  }
1400
  }
1401
  </script>
1402
+ <script>
1403
+ const INPUT_DATA = {
1404
+ fertilizerConstants: {
1405
+ "Кальциевая селитра": { "N (NO3-)": 0.11863, "Ca": 0.16972 },
1406
+ "Калий азотнокислый": { "N (NO3-)": 0.13854, "K": 0.36672 },
1407
+ "Аммоний азотнокислый": { "N (NO3-)": 0.17499, "N (NH4+)": 0.17499 },
1408
+ "Сульфат магния": { "Mg": 0.10220, "S": 0.13483 },
1409
+ "Монофосфат калия": { "P": 0.22761, "K": 0.28731 },
1410
+ "Калий сернокислый": { "K": 0.44874, "S": 0.18401 },
1411
+ "Кальций хлорид": { "Ca": 0.272, "Cl": 0.483 } // Хлор теперь учитывается
1412
+ },
1413
+ profileSettings: {
1414
+ "P": 60, "K": 194, "Mg": 48.5, "Ca": 89.25, "S": 79.445, "CaCl": 38.5, // Добавлен Cl
1415
+ "NO3_RAT": 1.5, "TOTAL_NITROG": 138.57, "liters": 100
1416
+ }
1417
+ };
1418
+
1419
+ class NutrientCalculator {
1420
+ constructor(inputData) {
1421
+ this.fertilizers = inputData.fertilizerConstants;
1422
+ this.profile = inputData.profileSettings;
1423
+ this.volume = this.profile.liters;
1424
+
1425
+ const totalParts = this.profile.NO3_RAT + 1;
1426
+ this.target = {
1427
+ 'P': this.profile.P,
1428
+ 'K': this.profile.K,
1429
+ 'Mg': this.profile.Mg,
1430
+ 'Ca': this.profile.Ca, // Общий кальций
1431
+ 'S': this.profile.S,
1432
+ 'N (NO3-)': this.profile.TOTAL_NITROG * (this.profile.NO3_RAT / totalParts),
1433
+ 'N (NH4+)': this.profile.TOTAL_NITROG * (1 / totalParts)
1434
+ };
1435
+
1436
+ this.actual = Object.fromEntries(Object.keys(this.target).map(k => [k, 0.0])); // CaCl не учитываем в фактическом балансе
1437
+ this.results = Object.fromEntries(Object.keys(this.fertilizers).map(fert => [fert, { граммы: 0.0 }]));
1438
+ }
1439
 
1440
+ calculate() {
1441
+ // 1. Вносим аммонийный азот
1442
+ this._applyFertilizer("Аммоний азотнокислый", "N (NH4+)", this.target["N (NH4+)"]);
1443
 
1444
+ // 2. Вносим фосфор
1445
+ this._applyFertilizer("Монофосфат калия", "P", this.target.P);
1446
+
1447
+ // 3. Вносим магний
1448
+ this._applyFertilizer("Сульфат магния", "Mg", this.target.Mg);
1449
+
1450
+ // 4. Балансируем калий и серу
1451
+ this._balanceKS();
1452
+
1453
+ // 5. Распределяем кальций между селитрой и хлоридом
1454
+ this._distributeCalcium();
1455
+
1456
+ // 6. Компенсируем NO3 калийной селитрой
1457
+ const no3Needed = this.target["N (NO3-)"] - this.actual["N (NO3-)"];
1458
+ if (no3Needed > 0) {
1459
+ this._applyFertilizer("Калий азотнокислый", "N (NO3-)", no3Needed);
1460
+ }
1461
+
1462
+ return this._verifyResults();
1463
+ }
1464
+
1465
+ _applyFertilizer(name, element, targetPPM) {
1466
+ if (!this.fertilizers[name]) {
1467
+ throw new Error(`Удобрение '${name}' не найдено в fertilizerConstants!`);
1468
+ }
1469
+
1470
+ const content = this.fertilizers[name][element] || 0; // Получаем содержание элемента
1471
+ if (content === 0) {
1472
+ console.warn(`ПРЕДУПРЕЖДЕНИЕ: Удобрение '${name}' не содержит элемент '${element}'`);
1473
+ return;
1474
+ }
1475
+
1476
+ const grams = (targetPPM * this.volume) / (content * 1000);
1477
+ this.results[name].граммы += grams;
1478
+
1479
+ for (const [el, val] of Object.entries(this.fertilizers[name])) {
1480
+ const addedPPM = (grams * val * 1000) / this.volume;
1481
+ if (el in this.actual) {
1482
+ this.actual[el] += addedPPM;
1483
+ }
1484
+ }
1485
+ }
1486
+
1487
+ _balanceKS() {
1488
+ const kNeeded = this.target.K - this.actual.K;
1489
+ const sNeeded = this.target.S - this.actual.S;
1490
+
1491
+ if (kNeeded > 0 && sNeeded > 0) {
1492
+ const kFromK2SO4 = Math.min(kNeeded, sNeeded * 0.44874 / 0.18401);
1493
+ this._applyFertilizer("Калий сернокислый", "K", kFromK2SO4);
1494
+ }
1495
+
1496
+ const remainingK = this.target.K - this.actual.K;
1497
+ if (remainingK > 0) {
1498
+ this._applyFertilizer("Калий азотнокислый", "K", remainingK);
1499
+ }
1500
+ }
1501
+
1502
+ _distributeCalcium() {
1503
+ const caTarget = this.target.Ca; // Общий кальций
1504
+
1505
+ // Проверка соотношения NO3/NH4
1506
+ const no3Ratio = this.profile.NO3_RAT;
1507
+ if (no3Ratio >= 8) { // Если соотношение NO3/NH4 >= 8, кальций хлористый не добавляется
1508
+ console.log("Соотношение NO3/NH4 >= 8. Кальций хлористый не добавляется.");
1509
+ var remainingCa = caTarget;
1510
+ } else {
1511
+ // 1. Определяем, сколько кальция взять из хлористого кальция
1512
+ const caclRatio = 0.3; // Например, 50% кальция берем из хлористого кальция
1513
+ const caclTarget = caTarget * caclRatio;
1514
+
1515
+ // 2. Вносим кальций из хлористого кальция
1516
+ if (caclTarget > 0) {
1517
+ this._applyFertilizer("Кальций хлорид", "Ca", caclTarget); // Исправлено на "Кальций хлорид"
1518
+ }
1519
+
1520
+ // 3. Оставшийся кальций берем из кальциевой селитры
1521
+ remainingCa = caTarget - caclTarget;
1522
+ }
1523
+
1524
+ // Добавляем оставшийся кальций из кальциевой селитры
1525
+ if (remainingCa > 0) {
1526
+ this._applyFertilizer("Кальциевая селитра", "Ca", remainingCa);
1527
+ }
1528
+ }
1529
+
1530
+ _verifyResults() {
1531
+ const deficits = {};
1532
+ for (const el in this.target) {
1533
+ const diff = this.target[el] - this.actual[el];
1534
+ if (Math.abs(diff) > 0.1) {
1535
+ deficits[el] = parseFloat(diff.toFixed(3));
1536
+ }
1537
+ }
1538
+
1539
+ return {
1540
+ fertilizers: Object.fromEntries(Object.entries(this.results).map(([k, v]) => [k, parseFloat(v.граммы.toFixed(3))])),
1541
+ actualProfile: Object.fromEntries(Object.entries(this.actual).map(([k, v]) => [k, parseFloat(v.toFixed(3))])),
1542
+ deficits: deficits,
1543
+ totalPPM: parseFloat(Object.values(this.actual).reduce((sum, val) => sum + val, 0).toFixed(3))
1544
+ };
1545
+ }
1546
+
1547
+ generateReport(results) {
1548
+ let fertTable = [];
1549
+ for (const [name, data] of Object.entries(results.fertilizers)) {
1550
+ fertTable.push([name, `${data} г`]);
1551
+ }
1552
+
1553
+ let elementTable = [];
1554
+ for (const el of Object.keys(this.target).sort()) {
1555
+ if (el === "CaCl") continue; // Пропускаем CaCl в отчете
1556
+ elementTable.push([
1557
+ el,
1558
+ `${this.target[el]} ppm`,
1559
+ `${results.actualProfile[el]} ppm`,
1560
+ `${parseFloat((results.actualProfile[el] - this.target[el]).toFixed(2))} ppm`
1561
+ ]);
1562
+ }
1563
+
1564
+ let report = "РЕКОМЕНДУЕМЫЕ УДОБРЕНИЯ:\n";
1565
+ report += this._formatTable(fertTable, ["Удобрение", "Количество"]);
1566
+
1567
+ report += "\n\nБАЛАНС ЭЛЕМЕНТОВ:\n";
1568
+ report += this._formatTable(elementTable, ["Элемент", "Цель", "Факт", "Отклонение"]);
1569
+
1570
+ report += `\n\nОбщая концентрация: ${results.totalPPM} ppm`;
1571
+
1572
+ if (Object.keys(results.deficits).length > 0) {
1573
+ report += "\n\nВНИМАНИЕ: Обнаружены небольшие отклонения:";
1574
+ for (const [el, diff] of Object.entries(results.deficits)) {
1575
+ report += `\n- ${el}: не хватает ${Math.abs(diff)} ppm`;
1576
+ }
1577
+ }
1578
+
1579
+ return report;
1580
+ }
1581
+
1582
+ _formatTable(data, headers) {
1583
+ const table = [headers, ...data];
1584
+ const columnWidths = headers.map((_, i) => Math.max(...table.map(row => row[i].toString().length)));
1585
+ const formatRow = row => row.map((cell, i) => cell.padEnd(columnWidths[i])).join(" | ");
1586
+ return table.map(formatRow).join("\n");
1587
+ }
1588
+ }
1589
+
1590
+ // Запуск расчета
1591
+ const calculator = new NutrientCalculator(INPUT_DATA);
1592
+ const results = calculator.calculate();
1593
+ console.log(calculator.generateReport(results));
1594
+ </script>
1595
  </body>
1596
  </html>