calcBtn.addEventListener('click', ()=>{ try{ if(!state.ratesAsc || state.ratesAsc.length===0) return alert('Brak danych historycznych. Wczytaj CSV lub użyj przykładu.'); const amount = Number(kwotaInput.value) || 0; const marza = Number(marzaInput.value) || 0; const startDate = formatDateISO(new Date()); const nMonths = Number(okresInput.value) || 360; const tenorMonths = Number(tenorSelect.value) || 3; const scenario = scenarioSel.value; const getReal = dateStr => findRateOnOrBefore(dateStr); const startWibor = findRateOnOrBefore(startDate) || 0; const getFreeze = _ => startWibor; const getZero = _ => 0; const actualSched = computeSchedule(amount, marza, startDate, nMonths, tenorMonths, getReal); let altSched; if(scenario==='freeze') altSched = computeSchedule(amount, marza, startDate, nMonths, tenorMonths, getFreeze); else if(scenario==='zero') altSched = computeSchedule(amount, marza, startDate, nMonths, tenorMonths, getZero); else if(scenario==='const'){ const startMonthly = (startWibor + marza)/100/12; const fixed = calcAnnuity(amount, startMonthly, nMonths); let out = amount; const rows=[]; for(let i=0;i
out) principal=out; const payment = interest + principal; out = Math.max(0, out-principal); rows.push({date:curDate,wibor:startWibor,monthlyRate:startMonthly,payment:payment,interest:interest,principal:principal,balance:out}); } altSched = rows; } const sumActualInterest = sum(actualSched,'interest'); const sumAltInterest = sum(altSched,'interest'); const sumActualPayments = sum(actualSched,'payment'); const sumAltPayments = sum(altSched,'payment'); // prepare results in SKD layout const avgWibor = (actualSched.reduce((s,r)=>s + r.wibor,0)/actualSched.length) || 0; rataEl.innerText = fmtPL(Math.round(actualSched[0].payment || 0)); sredniWiborEl.innerText = fmtPct(avgWibor); sumaOdsetekEl.innerText = fmtPL(Math.round(sumActualInterest)); sumaOdsetekScenEl.innerText = fmtPL(Math.round(sumAltInterest)); roznicaEl.innerText = fmtPL(Math.round(sumAltInterest - sumActualInterest)); totalPaidEl.innerText = fmtPL(Math.round(sumActualPayments)); sumaEl.innerText = fmtPL(Math.round(sumAltInterest - sumActualInterest)); }catch(e){ console.error(e); alert('Błąd: ' + (e.message||e)); } }); // initialize UI values kwotaVal.textContent = Number(kwotaInput.value).toLocaleString('pl-PL'); okresVal.textContent = okresInput.value; marzaVal.textContent = Number(marzaInput.value).toFixed(2); kwotaRange.addEventListener('input', ()=>{ kwotaInput.value = kwotaRange.value; kwotaVal.textContent = Number(kwotaRange.value).toLocaleString('pl-PL'); }); kwotaInput.addEventListener('change', ()=>{ kwotaRange.value = kwotaInput.value; kwotaVal.textContent = Number(kwotaInput.value).toLocaleString('pl-PL'); }); okresRange.addEventListener('input', ()=>{ okresInput.value = okresRange.value; okresVal.textContent = okresRange.value; }); okresInput.addEventListener('change', ()=>{ okresRange.value = okresInput.value; okresVal.textContent = okresInput.value; }); marzaRange.addEventListener('input', ()=>{ marzaInput.value = marzaRange.value; marzaVal.textContent = Number(marzaRange.value).toFixed(2); }); marzaInput.addEventListener('change', ()=>{ marzaRange.value = marzaInput.value; marzaVal.textContent = Number(marzaInput.value).toFixed(2); });