"""
# Avoid duplicate injection if user reruns
if "cmpDashBody" not in html:
html = html[:m.start()] + m.group(1) + "\n" + dash_html + html[m.end():]
# Extend cmpRead only if not already extended
if "const costPerKgProduct = c.value;" in html and "productCostHa" not in html:
html = html.replace(
" const costPerKgProduct = c.value;",
" const costPerKgProduct = c.value;\n const baseCostPerKg = priceT / 1000.0;\n const appCostHa = (Number.isNaN(appHa) ? 0 : appHa);\n const doseKgHa = dose;\n const productCostHa = baseCostPerKg * doseKgHa;\n const totalCostHa = productCostHa + appCostHa;"
)
# Update return object
html = html.replace(
" return {ok:true, name, type, unit, costs};",
" return {ok:true, name, type, unit, costs, baseCostPerKg, appCostHa, doseKgHa, productCostHa, totalCostHa};"
)
# Early no-data return patch
html = html.replace(
'$("#cmpVerdict").textContent = "Brak danych";\n $("#cmpVerdict").className = "badge warn";\n return;',
'$("#cmpVerdict").textContent = "Brak danych";\n $("#cmpVerdict").className = "badge warn";\n const bestEl = $("#cmpBestTotal");\n if (bestEl){ bestEl.textContent = "Brak danych"; bestEl.className = "badge warn"; }\n const db0 = $("#cmpDashBody");\n if (db0) db0.innerHTML = `Wprowadź dane i kliknij „Oblicz” dla nawozów.`;\n return;'
)
# Add helper cmpRenderDashboard if not present
if "function cmpRenderDashboard()" not in html:
inject_point = "function cmpRender(){"
if inject_point not in html:
raise ValueError("cmpRender function not found")
helper = r"""
function cmpRenderDashboard(){
const db = $("#cmpDashBody");
const bestEl = $("#cmpBestTotal");
if (!db || !bestEl) return;
db.innerHTML = "";
const items = CMP.items.filter(x=>x && x.ok);
if (items.length === 0){
db.innerHTML = `Wprowadź dane i kliknij „Oblicz” dla nawozów.`;
bestEl.textContent = "Brak danych";
bestEl.className = "badge warn";
return;
}
let best = null;
items.forEach(it=>{
const tr = document.createElement("tr");
tr.innerHTML = `
${it.name}
${fmt(it.doseKgHa,0)}
${fmt(it.productCostHa,0)}
${fmt(it.appCostHa,0)}
${fmt(it.totalCostHa,0)}
`;
db.appendChild(tr);
if (best===null || it.totalCostHa < best.totalCostHa) best = it;
});
bestEl.textContent = `${best.name} (${fmt(best.totalCostHa,0)} PLN/ha)`;
bestEl.className = "badge ok";
}
"""
html = html.replace(inject_point, helper + "\n" + inject_point, 1)
# Ensure cmpRender calls cmpRenderDashboard in warn and ok branches
warn_block_pat = r'if \(candidates\.length < 2\)\{\n\s*\$\("#cmpVerdict"\)\.textContent = "Oblicz co najmniej 2 nawozy \(z danym parametrem\)";\n\s*\$\("#cmpVerdict"\)\.className = "badge warn";\n\s*return;\n\s*\}'
if re.search(warn_block_pat, html):
html = re.sub(
warn_block_pat,
'if (candidates.length < 2){\n $("#cmpVerdict").textContent = "Oblicz co najmniej 2 nawozy (z danym parametrem)";\n $("#cmpVerdict").className = "badge warn";\n cmpRenderDashboard();\n return;\n }',
html
)
ok_set_point = '$("#cmpVerdict").className = "badge ok";'
if ok_set_point in html:
# call dashboard right after verdict OK if not already called nearby
if "cmpRenderDashboard();" not in html.split(ok_set_point,1)[1][:120]:
html = html.replace(ok_set_point, ok_set_point + "\n cmpRenderDashboard();", 1)
# --- Write to new file (permission safe) ---
out_path = Path("/mnt/data/agem_tool_updated.html")
out_path.write_text(html, encoding="utf-8")
# Also update PWA package as separate zip (optional)
pwa_out = Path("/mnt/data/agem_tool_pwa_updated.zip")
# Build minimal PWA folder using existing pwa zip if present; else just create one with index + existing assets if available
base_dir = Path("/mnt/data/agem_tool_pwa")
if base_dir.exists():
# update index in a temp copy directory
tmp = Path("/mnt/data/agem_tool_pwa_updated")
if tmp.exists():
import shutil; shutil.rmtree(tmp)
import shutil
shutil.copytree(base_dir, tmp)
(tmp/"index.html").write_text(html, encoding="utf-8")
with zipfile.ZipFile(pwa_out, "w", zipfile.ZIP_DEFLATED) as z:
for fp in tmp.rglob("*"):
z.write(fp, fp.relative_to(tmp))
# cleanup not necessary
else:
with zipfile.ZipFile(pwa_out, "w", zipfile.ZIP_DEFLATED) as z:
z.writestr("index.html", html)
(str(out_path), str(pwa_out))
Ag'em Tool — Kalkulatory dla rolnictwa regeneratywnego
Ag'em Tool
Kalkulatory online dla rolnictwa regeneratywnego
Ag'em Agency - doradztwo i narzędzia agronomiczne
Koszty nawozów
Potrzeby nawozowe
Norma wysiewu
Zysk vs koszt
Opłacalność roku
Kalkulator kosztów nawozów
Oblicza koszt produktu oraz koszt 1 kg składnika pokarmowego. Wybierz podzakładkę: makro lub mikro.
Makroelementowe
Mikroelementowe
W PLN za tonę (t). Jeśli masz cenę za kg, wpisz 1000 × cena/kg.
W PLN/ha (np. koszt rozsiewu / wozu asenizacyjnego).
W kg/ha. Pozwala rozłożyć koszt aplikacji na koszt 1 kg produktu.
Skład nawozu
Wpisz zawartość w % masy (np. 6 oznacza 6%).
Uwaga: Jeżeli wybierzesz tlenki, wpisuj P2O5/K2O/MgO/SO3. Jeżeli pierwiastki — wpisuj P/K/Mg/S.
W PLN za kg (typowe dla mikro).
W PLN/ha (np. koszt oprysku).
W kg/ha (lub l/ha traktowane jak kg/ha w uproszczeniu).
Skład mikroelementowy
Wpisz zawartość w % masy. Pozostaw puste jeśli składnik nie występuje.
Wyniki pokazują koszt 1 kg produktu (z aplikacją) oraz koszt 1 kg czystego składnika (np. Zn).
Wyniki
Wyniki aktualizują się po kliknięciu Oblicz.
Status
Wprowadź dane i oblicz
Koszt 1 kg produktu (z aplikacją)
—
Uwzględnia koszt aplikacji rozłożony przez dawkę.
Składnik
Zawartość
Koszt 1 kg składnika
Brak danych.
Interpretacja: koszt 1 kg składnika = (koszt 1 kg produktu) / (udział składnika w kg/kg).