рдореБрджреНрд░рд╛ рдХрд╛ рд╕рдордп рдореВрд▓реНрдп рдФрд░ рдбрд┐рдЬрд┐рдЯрд▓ рд╕рдВрдкрддреНрддрд┐ рдХреИрд▓рдХреБрд▓реЗрдЯрд░

рдкрд╛рд░рдВрдкрд░рд┐рдХ рдФрд░ рдбрд┐рдЬрд┐рдЯрд▓ рд╕рдВрдкрддреНрддрд┐рдпреЛрдВ рдХреЗ рд╕рд╛рде рд╡рд┐рддреНрддреАрдп рдирд┐рд░реНрдгрдпреЛрдВ рдореЗрдВ рдорд╣рд╛рд░рдд рд╣рд╛рд╕рд┐рд▓ рдХрд░реЗрдВред USD, рдмрд┐рдЯрдХреЙрдЗрди, рдПрдереЗрд░рд┐рдпрдо рдФрд░ рдкреНрд░рдореБрдЦ рдХреНрд░рд┐рдкреНрдЯреЛрдХрд░реЗрдВрд╕реА рдХреЗ рд▓рд┐рдП рд╡рд░реНрддрдорд╛рди рдореВрд▓реНрдп, рднрд╡рд┐рд╖реНрдп рдореВрд▓реНрдп, рднреБрдЧрддрд╛рди рдФрд░ рд░рд┐рдЯрд░реНрди рдХреА рдЧрдгрдирд╛ рдХрд░реЗрдВред

рдбрд┐рдЬрд┐рдЯрд▓ рд╕рдВрдкрддреНрддрд┐рдпреЛрдВ рдХреЗ рд╕рд╛рде 5-рдХреБрдВрдЬреА рд╕рдордп рдореВрд▓реНрдп рдХреИрд▓рдХреБрд▓реЗрдЯрд░

рдХреЛрдИ рднреА 4 рдорд╛рди рджрд░реНрдЬ рдХрд░реЗрдВ рдФрд░ 5рд╡реЗрдВ рдХреЗ рд▓рд┐рдП рд╣рд▓ рдХрд░реЗрдВред рдкрд╛рд░рдВрдкрд░рд┐рдХ рдореБрджреНрд░рд╛ рдФрд░ рдмрд┐рдЯрдХреЙрдЗрди, рдПрдереЗрд░рд┐рдпрдо рд╕рд╣рд┐рдд рдкреНрд░рдореБрдЦ рдХреНрд░рд┐рдкреНрдЯреЛрдХрд░реЗрдВрд╕реА рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред

USD (рдбреЙрд▓рд░)
рдмрд┐рдЯрдХреЙрдЗрди (BTC)
рдПрдереЗрд░рд┐рдпрдо (ETH)
рд╕реЛрд▓рд╛рдирд╛ (SOL)
WIA (WIA)
XRP (XRP)
рд╡рд░реНрддрдорд╛рди рдореВрд▓реНрдп (PV)
рднрд╡рд┐рд╖реНрдп рдореВрд▓реНрдп (FV)
рднреБрдЧрддрд╛рди (PMT)
рдмреНрдпрд╛рдЬ рджрд░ (I/Y)
рдЕрд╡рдзрд┐ (N)
Traditional assets: 3-12%, Crypto: 5-30%
рд╕рд╛рдзрд╛рд░рдг рд╡рд╛рд░реНрд╖рд┐рдХреА (рдЕрдВрдд)
рджреЗрдп рд╡рд╛рд░реНрд╖рд┐рдХреА (рдкреНрд░рд╛рд░рдВрдн)

рдЛрдг рднреБрдЧрддрд╛рди рдХреИрд▓рдХреБрд▓реЗрдЯрд░

рдмрдВрдзрдХ, рдСрдЯреЛ рдЛрдг рдФрд░ рд╡реНрдпрдХреНрддрд┐рдЧрдд рдЛрдгреЛрдВ рдХреЗ рд▓рд┐рдП рдорд╛рд╕рд┐рдХ рднреБрдЧрддрд╛рди, рдХреБрд▓ рдмреНрдпрд╛рдЬ рдФрд░ рдкрд░рд┐рд╢реЛрдзрди рдЕрдиреБрд╕реВрдЪреА рдХреА рдЧрдгрдирд╛ рдХрд░реЗрдВред

рд╡рд╛рд░реНрд╖рд┐рдХреА рдореВрд▓реНрдп рдХреИрд▓рдХреБрд▓реЗрдЯрд░

рд╕рд╛рдзрд╛рд░рдг рд╡рд╛рд░реНрд╖рд┐рдХреА рдФрд░ рджреЗрдп рд╡рд╛рд░реНрд╖рд┐рдХреА рдХреЗ рд╡рд░реНрддрдорд╛рди рдФрд░ рднрд╡рд┐рд╖реНрдп рдореВрд▓реНрдпреЛрдВ рдХреА рдЧрдгрдирд╛ рдХрд░реЗрдВред рд╕реЗрд╡рд╛рдирд┐рд╡реГрддреНрддрд┐ рдпреЛрдЬрдирд╛ рдФрд░ рдирд┐рд╡реЗрд╢ рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдХреЗ рд▓рд┐рдП рдЙрдкрдпреБрдХреНрддред

рдирд┐рд╡реЗрд╢ рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдХреИрд▓рдХреБрд▓реЗрдЯрд░

рд░рд┐рдЯрд░реНрди, рдЖрд╡рд╢реНрдпрдХ рджрд░реЛрдВ рдФрд░ рдмреНрд░реЗрдХ-рдИрд╡рди рдкреЙрдЗрдВрдЯ рдХреА рдЧрдгрдирд╛ рдХрд░рдХреЗ рдирд┐рд╡реЗрд╢ рд╡рд┐рдХрд▓реНрдкреЛрдВ рдХреА рддреБрд▓рдирд╛ рдХрд░реЗрдВред рдирд┐рд╡реЗрд╢ рдирд┐рд░реНрдгрдп рд▓реЗрдиреЗ рдХреЗ рд▓рд┐рдП рдЖрджрд░реНрд╢ред

рд╢реБрджреНрдз рд╡рд░реНрддрдорд╛рди рдореВрд▓реНрдп рд╡рд┐рд╢реНрд▓реЗрд╖рдг

рдПрдирдкреАрд╡реА рдФрд░ рдЖрдИрдЖрд░рдЖрд░ рдХреА рдЧрдгрдирд╛ рдХрд░рдХреЗ рдкрд░рд┐рдпреЛрдЬрдирд╛ рд▓рд╛рднрдкреНрд░рджрддрд╛ рдХрд╛ рдореВрд▓реНрдпрд╛рдВрдХрди рдХрд░реЗрдВред рд╡реНрдпрд╛рдкрдХ рдирд┐рд╡реЗрд╢ рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдХреЗ рд▓рд┐рдП рдирдХрджреА рдкреНрд░рд╡рд╛рд╣ рджрд░реНрдЬ рдХрд░реЗрдВред

Enter positive values for cash inflows, negative for outflows

рддреНрд╡рд░рд┐рдд рдЖрд░рдВрдн рдкрд░рд┐рджреГрд╢реНрдп

30-рд╡рд░реНрд╖реАрдп рдЧреГрд╣ рдЛрдг
тВ╣300K рдХрд╛ рдЛрдг 6.5% рдкрд░ 30 рд╡рд░реНрд╖реЛрдВ рдХреЗ рд▓рд┐рдП
рд╕реЗрд╡рд╛рдирд┐рд╡реГрддреНрддрд┐ рдпреЛрдЬрдирд╛
тВ╣1K рдорд╛рд╕рд┐рдХ 25 рд╡рд░реНрд╖реЛрдВ рдХреЗ рд▓рд┐рдП 8% рдкрд░
рдХреЙрд▓реЗрдЬ рдлрдВрдб
рдЖрдЬ рдХрд╛ тВ╣25K 18 рд╡рд░реНрд╖реЛрдВ рдореЗрдВ тВ╣100K рддрдХ рдмрдврд╝рддрд╛ рд╣реИ
рд╡рд╛рд╣рди рдЛрдг
тВ╣40K рдХрд╛рд░ рдЛрдг 5.5% рдкрд░ 5 рд╡рд░реНрд╖реЛрдВ рдХреЗ рд▓рд┐рдП
рдмрд┐рдЯрдХреЙрдЗрди рдирд┐рд╡реЗрд╢
1 рдмрд┐рдЯрдХреЙрдЗрди 5 рд╡рд░реНрд╖реЛрдВ рдореЗрдВ 15% рдХреА рджрд░ рд╕реЗ рдмрдврд╝рддрд╛ рд╣реИ
рдЗрдереЗрд░рд┐рдпрдо рдбреАрд╕реАрдП
0.1 рдЗрдереЗрд░рд┐рдпрдо рдорд╛рд╕рд┐рдХ 3 рд╡рд░реНрд╖реЛрдВ рдХреЗ рд▓рд┐рдП 20% рдкрд░
рдбрдмреНрд▓реНрдпреВрдЖрдИрдП рдирд┐рд╡реЗрд╢
1000 рдбрдмреНрд▓реНрдпреВрдЖрдИрдП + 100 рдорд╛рд╕рд┐рдХ 10 рд╡рд░реНрд╖реЛрдВ рдХреЗ рд▓рд┐рдП

рдЕрдкрдиреА рд╡рд┐рддреНрддреАрдп рд╕рдлрд▓рддрд╛ рдХрд╛ рдЬрд╢реНрди рдордирд╛ рд░рд╣реЗ рд╣реИрдВ? рдЦреБрдж рдХреЛ рдкреБрд░рд╕реНрдХреГрдд рдХрд░рдиреЗ рдХрд╛ рд╕рдордп!

рд╕реНрдорд╛рд░реНрдЯ рд╡рд┐рддреНрддреАрдп рдпреЛрдЬрдирд╛ рдХреЛ рдорд┐рд▓рдирд╛ рдЪрд╛рд╣рд┐рдП рдЗрдирд╛рдо - рджреБрдирд┐рдпрд╛рднрд░ рдХреА рд╢рд╛рдирджрд╛рд░ рдпрд╛рддреНрд░рд╛ рдбреАрд▓реНрд╕ рдЦреЛрдЬреЗрдВ

тЬи Smart Nation's Core Infrastructure: WIA Code тЬи

рдбреНрд░реЛрдитАврд░реЛрдмреЛрдЯ рдбрд┐рд▓реАрд╡рд░реА, рд╕реНрд╡рд╛рдпрддреНрдд рдбреНрд░рд╛рдЗрд╡рд┐рдВрдЧ, рдЖрдкрд╛рддрдХрд╛рд▓реАрди рдмрдЪрд╛рд╡ рдФрд░ рдмрд╣реБрдд рдХреБрдЫ - 30 рджрд┐рдиреЛрдВ рдореЗрдВ рднрд╡рд┐рд╖реНрдп рдХрд╛ рдЕрдиреБрднрд╡ рдХрд░реЗрдВ, рдЖрдкрдХреЗ рджреЗрд╢ рдХреЗ рд▓рд┐рдП рдкреВрд░реА рддрд░рд╣ рдореБрдлреНрдд!

рдбрдмреНрд▓реНрдпреВрдЖрдИрдП рдХреЛрдб рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдФрд░ рдЬрд╛рдиреЗрдВ

ЁЯдЦ рдЕрдкрдирд╛ рдПрдЖрдИ рд╕рд╣рд╛рдпрдХ рдЪреБрдиреЗрдВ

ЁЯТм рдЪреИрдЯрдЬреАрдкреАрдЯреА
рд╕рдмрд╕реЗ рдмрд╣реБрдореБрдЦреА тАв рд╕рд╛рдорд╛рдиреНрдп рдХрд╛рд░реНрдпреЛрдВ рдХреЗ рд▓рд┐рдП рд╕рд░реНрд╡рд╢реНрд░реЗрд╖реНрда
ЁЯза рдХреНрд▓рд╛рдЙрдб
рд╕рд░реНрд╡рд╢реНрд░реЗрд╖реНрда рддрд░реНрдХ тАв рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдХреЗ рд▓рд┐рдП рдЙрддреНрддрдо
тЬи рдЬреЗрдорд┐рдиреА рдирд┐рдГрд╢реБрд▓реНрдХ
рджреИрдирд┐рдХ рдореБрдлреНрдд рд╕реАрдорд╛ тАв рдЕрдВрддрд░реНрдирд┐рд╣рд┐рдд рдЪреИрдЯ
, expectedReturn: { min: 3, max: 12, default: 8 }, riskLevel: 'рдХрдо' }, 'рдмреАрдЯреАрд╕реА': { name: 'рдмрд┐рдЯрдХреЙрдЗрди', symbol: 'рдмреАрдЯреАрд╕реА', expectedReturn: { min: 5, max: 40, default: 15 }, riskLevel: 'рдмрд╣реБрдд рдЕрдзрд┐рдХ', currentPrice: 97000 // Mock price - in production would use API }, 'рдИрдЯреАрдПрдЪ': { name: 'рдЗрдереЗрд░рд┐рдпрдо', symbol: 'рдИрдЯреАрдПрдЪ', expectedReturn: { min: 8, max: 35, default: 20 }, riskLevel: 'рдмрд╣реБрдд рдЕрдзрд┐рдХ', currentPrice: 3400 }, 'рдПрд╕рдУрдПрд▓': { name: 'рд╕реЛрд▓рд╛рдирд╛', symbol: 'рдПрд╕рдУрдПрд▓', expectedReturn: { min: 10, max: 45, default: 25 }, riskLevel: 'рдЕрддреНрдпрдзрд┐рдХ', currentPrice: 195 }, 'рдПрдбреАрдП': { name: 'рдХрд╛рд░реНрдбрд╛рдиреЛ', symbol: 'рдПрдбреАрдП', expectedReturn: { min: 5, max: 30, default: 18 }, riskLevel: 'рдмрд╣реБрдд рдЕрдзрд┐рдХ', currentPrice: 1.15 }, 'рдПрдХреНрд╕рдЖрд░рдкреА': { name: 'рдПрдХреНрд╕рдЖрд░рдкреА', symbol: 'рдПрдХреНрд╕рдЖрд░рдкреА', expectedReturn: { min: 8, max: 35, default: 22 }, riskLevel: 'рдмрд╣реБрдд рдЕрдзрд┐рдХ', currentPrice: 3.20 } }; // Asset Type Selection function setAssetType(assetType) { document.querySelectorAll('[data-asset]').forEach(option => { option.classList.remove('active'); }); event.target.classList.add('active'); currentAssetType = assetType; updateAssetLabels(); updatePriceDisplay(); updateRateHints(); toggleCryptoDisclaimer(); } // Update labels based on asset type function updateAssetLabels() { const asset = CRYPTO_ASSETS[currentAssetType]; const symbol = currentAssetType === 'рдпреВрдПрд╕рдбреА' ? ' // Tab Management function switchTab(tabName) { document.querySelectorAll('.tab-content').forEach(tab => { tab.classList.remove('active'); }); document.querySelectorAll('.tab-button').forEach(btn => { btn.classList.remove('active'); }); document.getElementById(tabName + 'рдЯреИрдм').classList.add('active'); event.target.classList.add('active'); } // Solve For Selection function setSolveFor(solveType) { document.querySelectorAll('.solve-for-option').forEach(option => { option.classList.remove('active'); }); event.target.classList.add('active'); currentSolveFor = solveType; // Clear the field we're solving for const fieldMap = { 'pv': 'presentValue', 'fv': 'futureValue', 'pmt': 'payment', 'rate': 'interestRate', 'periods': 'periods' }; document.getElementById(fieldMap[solveType]).value = ''; } // Annuity Type Selection function setAnnuityType(type) { document.querySelectorAll('.toggle-button').forEach(btn => { btn.classList.remove('active'); }); event.target.classList.add('active'); currentAnnuityType = type; } // Main TVM Calculation function calculateTVM() { try { const pv = parseFloat(document.getElementById('presentValue').value) || 0; const fv = parseFloat(document.getElementById('futureValue').value) || 0; const pmt = parseFloat(document.getElementById('payment').value) || 0; const rate = parseFloat(document.getElementById('interestRate').value) || 0; const periods = parseFloat(document.getElementById('periods').value) || 0; const compFreq = parseInt(document.getElementById('compoundingFreq').value) || 12; if (rate <= 0 && currentSolveFor !== 'rate') { showNotification('Interest rate must be greater than 0', 'error'); return; } if (periods <= 0 && currentSolveFor !== 'periods') { showNotification('Number of periods must be greater than 0', 'error'); return; } const result = solveTVM(pv, fv, pmt, rate, periods, compFreq, currentSolveFor, currentAnnuityType); displayTVMResult(result); showOTA(); trackEvent('tvm_calculated', { solveFor: currentSolveFor }); } catch (error) { showNotification(`Calculation error: ${error.message}`, 'error'); } } // Core TVM Solver function solveTVM(pv, fv, pmt, rate, periods, compFreq, solveFor, annuityType) { const periodicRate = rate / 100 / compFreq; const totalPeriods = periods * compFreq; let result = {}; switch (solveFor) { case 'pv': result.value = calculatePresentValue(fv, pmt, periodicRate, totalPeriods, annuityType); result.label = 'рд╡рд░реНрддрдорд╛рди рдореВрд▓реНрдп'; break; case 'fv': result.value = calculateFutureValue(pv, pmt, periodicRate, totalPeriods, annuityType); result.label = 'Future Value'; break; case 'pmt': result.value = calculatePayment(pv, fv, periodicRate, totalPeriods, annuityType); result.label = 'рднреБрдЧрддрд╛рди рд░рд╛рд╢рд┐'; break; case 'rate': const solvedRate = calculateInterestRate(pv, fv, pmt, totalPeriods, annuityType); result.value = solvedRate * compFreq * 100; result.label = 'рд╡рд╛рд░реНрд╖рд┐рдХ рдмреНрдпрд╛рдЬ рджрд░'; result.isPercentage = true; break; case 'periods': const solvedPeriods = calculatePeriods(pv, fv, pmt, periodicRate, annuityType); result.value = solvedPeriods / compFreq; result.label = 'рдЕрд╡рдзрд┐рдпреЛрдВ рдХреА рд╕рдВрдЦреНрдпрд╛'; result.isYears = true; break; } // Calculate additional details const effectiveRate = Math.pow(1 + periodicRate, compFreq) - 1; const totalPayments = Math.abs(pmt) * totalPeriods; result.effectiveRate = effectiveRate * 100; result.totalPayments = totalPayments; if (solveFor === 'pv') { result.totalInterest = Math.abs(result.value) - Math.abs(fv) + totalPayments; } else if (solveFor === 'fv') { result.totalInterest = Math.abs(result.value) - Math.abs(pv) - totalPayments; } else { result.totalInterest = totalPayments - Math.abs(pv); } return result; } // Present Value Calculation function calculatePresentValue(fv, pmt, rate, periods, type) { let pv = 0; if (fv !== 0) { pv += fv / Math.pow(1 + rate, periods); } if (pmt !== 0 && rate !== 0) { const annuityPV = pmt * (1 - Math.pow(1 + rate, -periods)) / rate; if (type === 'due') { pv += annuityPV * (1 + rate); } else { pv += annuityPV; } } else if (pmt !== 0 && rate === 0) { pv += pmt * periods; } return -pv; // Financial calculator convention } // Future Value Calculation function calculateFutureValue(pv, pmt, rate, periods, type) { let fv = 0; if (pv !== 0) { fv += -pv * Math.pow(1 + rate, periods); } if (pmt !== 0 && rate !== 0) { const annuityFV = pmt * (Math.pow(1 + rate, periods) - 1) / rate; if (type === 'due') { fv += annuityFV * (1 + rate); } else { fv += annuityFV; } } else if (pmt !== 0 && rate === 0) { fv += pmt * periods; } return fv; } // Payment Calculation function calculatePayment(pv, fv, rate, periods, type) { if (rate === 0) { return -(pv + fv) / periods; } const pvFactor = pv * Math.pow(1 + rate, periods); const numerator = -(pvFactor + fv); const denominator = (Math.pow(1 + rate, periods) - 1) / rate; let pmt = numerator / denominator; if (type === 'due') { pmt = pmt / (1 + rate); } return pmt; } // Interest Rate Calculation (Newton-Raphson method) function calculateInterestRate(pv, fv, pmt, periods, type) { if (pv === 0 && pmt === 0) return 0; if (fv === 0 && pmt === 0) return 0; let rate = 0.1; // Initial guess const tolerance = 1e-8; const maxIterations = 100; for (let i = 0; i < maxIterations; i++) { const f = evaluateTVMFunction(pv, fv, pmt, rate, periods, type); const df = evaluateTVMDerivative(pv, fv, pmt, rate, periods, type); if (Math.abs(df) < tolerance) break; const newRate = rate - f / df; if (Math.abs(newRate - rate) < tolerance) { return newRate; } rate = newRate; } return rate; } // TVM Function Evaluation function evaluateTVMFunction(pv, fv, pmt, rate, periods, type) { if (rate === 0) { return pv + fv + pmt * periods; } const pvTerm = pv; const fvTerm = fv / Math.pow(1 + rate, periods); let pmtTerm = 0; if (pmt !== 0) { pmtTerm = pmt * (1 - Math.pow(1 + rate, -periods)) / rate; if (type === 'due') { pmtTerm *= (1 + rate); } } return pvTerm + fvTerm + pmtTerm; } // TVM Derivative Evaluation function evaluateTVMDerivative(pv, fv, pmt, rate, periods, type) { const h = 1e-8; const f1 = evaluateTVMFunction(pv, fv, pmt, rate + h, periods, type); const f2 = evaluateTVMFunction(pv, fv, pmt, rate - h, periods, type); return (f1 - f2) / (2 * h); } // Periods Calculation function calculatePeriods(pv, fv, pmt, rate, type) { if (rate === 0) { return -(pv + fv) / pmt; } // Simplified calculation for common cases if (pmt === 0) { return Math.log(-fv / pv) / Math.log(1 + rate); } // For annuity calculations, use iterative method let periods = 10; // Initial guess const tolerance = 1e-8; const maxIterations = 100; for (let i = 0; i < maxIterations; i++) { const calculatedFV = calculateFutureValue(pv, pmt, rate, periods, type); const error = Math.abs(calculatedFV - fv); if (error < tolerance) break; // Adjust periods based on error if (calculatedFV < fv) { periods += 0.1; } else { periods -= 0.1; } if (periods <= 0) { periods = 0.1; } } return periods; } // Display TVM Results function displayTVMResult(result) { const resultContainer = document.getElementById('tvmResult'); const resultLabel = document.getElementById('resultLabel'); const resultValue = document.getElementById('resultValue'); const effectiveRate = document.getElementById('effectiveRate'); const totalPayments = document.getElementById('totalPayments'); const totalInterest = document.getElementById('totalInterest'); resultLabel.textContent = result.label; if (result.isPercentage) { resultValue.textContent = result.value.toFixed(2) + '%'; } else if (result.isYears) { resultValue.textContent = result.value.toFixed(1) + ' years'; } else { resultValue.textContent = formatCurrency(result.value); } effectiveRate.textContent = result.effectiveRate.toFixed(2) + '%'; totalPayments.textContent = formatCurrency(result.totalPayments); totalInterest.textContent = formatCurrency(result.totalInterest); resultContainer.style.display = 'block'; } // Loan Calculator function calculateLoan() { const principal = parseFloat(document.getElementById('loanAmount').value) || 0; const rate = parseFloat(document.getElementById('loanRate').value) || 0; const years = parseFloat(document.getElementById('loanTerm').value) || 0; const freq = parseInt(document.getElementById('paymentFreq').value) || 12; if (principal <= 0 || rate <= 0 || years <= 0) { showNotification('рдХреГрдкрдпрд╛ рд╡реИрдз рдЛрдг рдорд╛рдкрджрдВрдб рджрд░реНрдЬ рдХрд░реЗрдВ', 'error'); return; } const periodicRate = rate / 100 / freq; const totalPayments = years * freq; // Calculate monthly payment using PMT formula const payment = principal * (periodicRate * Math.pow(1 + periodicRate, totalPayments)) / (Math.pow(1 + periodicRate, totalPayments) - 1); const totalOfPayments = payment * totalPayments; const totalInterest = totalOfPayments - principal; const interestPercentage = (totalInterest / principal) * 100; // Display results document.getElementById('loanPayment').textContent = formatCurrency(payment); document.getElementById('totalLoanPayments').textContent = formatCurrency(totalOfPayments); document.getElementById('totalLoanInterest').textContent = formatCurrency(totalInterest); document.getElementById('interestPercentage').textContent = interestPercentage.toFixed(1) + '%'; document.getElementById('loanResult').style.display = 'block'; // Generate amortization table generateAmortizationTable(principal, payment, periodicRate, 12); showOTA(); } // Generate Amortization Table function generateAmortizationTable(principal, payment, periodicRate, numPayments) { const container = document.getElementById('amortizationData'); let balance = principal; let html = `
рднреБрдЧрддрд╛рди #
рднреБрдЧрддрд╛рди
рдмреНрдпрд╛рдЬ
рдореВрд▓рдзрди
рд╢реЗрд╖ рд░рд╛рд╢рд┐
`; for (let i = 1; i <= numPayments; i++) { const interestPayment = balance * periodicRate; const principalPayment = payment - interestPayment; balance -= principalPayment; html += `
${i}
${formatCurrency(payment)}
${formatCurrency(interestPayment)}
${formatCurrency(principalPayment)}
${formatCurrency(balance)}
`; } container.innerHTML = html; document.getElementById('amortizationTable').style.display = 'block'; } // Annuity Calculator function calculateAnnuity() { const payment = parseFloat(document.getElementById('annuityPayment').value) || 0; const rate = parseFloat(document.getElementById('annuityRate').value) || 0; const periods = parseInt(document.getElementById('annuityPeriods').value) || 0; const timing = document.getElementById('annuityTiming').value; if (payment <= 0 || rate <= 0 || periods <= 0) { showNotification('рдХреГрдкрдпрд╛ рд╡реИрдз рд╡рд╛рд░реНрд╖рд┐рдХреА рдорд╛рдкрджрдВрдб рджрд░реНрдЬ рдХрд░реЗрдВ', 'error'); return; } const periodicRate = rate / 100 / 12; // Assuming monthly payments // Calculate present value let pv = payment * (1 - Math.pow(1 + periodicRate, -periods)) / periodicRate; // Calculate future value let fv = payment * (Math.pow(1 + periodicRate, periods) - 1) / periodicRate; // Adjust for annuity due if (timing === 'due') { pv *= (1 + periodicRate); fv *= (1 + periodicRate); } const totalPayments = payment * periods; const interestEarned = fv - totalPayments; const effectiveRate = Math.pow(1 + periodicRate, 12) - 1; // Display results document.getElementById('annuityPV').textContent = formatCurrency(pv); document.getElementById('annuityFV').textContent = formatCurrency(fv); document.getElementById('totalAnnuityPayments').textContent = formatCurrency(totalPayments); document.getElementById('annuityInterest').textContent = formatCurrency(interestEarned); document.getElementById('annuityEffectiveRate').textContent = (effectiveRate * 100).toFixed(2) + '%'; document.getElementById('annuityResult').style.display = 'block'; showOTA(); } // Investment Analysis function calculateInvestment() { const initial = parseFloat(document.getElementById('initialInvestment').value) || 0; const target = parseFloat(document.getElementById('targetAmount').value) || 0; const years = parseFloat(document.getElementById('investmentPeriod').value) || 0; const annual = parseFloat(document.getElementById('annualContribution').value) || 0; if (initial <= 0 || target <= 0 || years <= 0) { showNotification('рдХреГрдкрдпрд╛ рд╡реИрдз рдирд┐рд╡реЗрд╢ рдорд╛рдкрджрдВрдб рджрд░реНрдЬ рдХрд░реЗрдВ', 'error'); return; } // Calculate required return rate const totalInvested = initial + (annual * years); // Use iterative method to find required rate let rate = 0.05; // Initial guess for (let i = 0; i < 100; i++) { const futureValue = initial * Math.pow(1 + rate, years) + annual * (Math.pow(1 + rate, years) - 1) / rate; if (Math.abs(futureValue - target) < 1) break; if (futureValue < target) { rate += 0.001; } else { rate -= 0.001; } } const growth = target - totalInvested; const breakEven = Math.log(initial * 2 / initial) / Math.log(1 + rate); // Display results document.getElementById('requiredReturn').textContent = (rate * 100).toFixed(2) + '%'; document.getElementById('totalInvested').textContent = formatCurrency(totalInvested); document.getElementById('investmentGrowth').textContent = formatCurrency(growth); document.getElementById('breakEvenTime').textContent = breakEven.toFixed(1) + ' years'; document.getElementById('investmentResult').style.display = 'block'; showOTA(); } // NPV Calculator function calculateNPV() { const initial = parseFloat(document.getElementById('npvInitial').value) || 0; const discountRate = parseFloat(document.getElementById('discountRate').value) || 0; const cashFlowsText = document.getElementById('cashFlows').value; if (discountRate <= 0) { showNotification('рдХреГрдкрдпрд╛ рд╡реИрдз рдЫреВрдЯ рджрд░ рджрд░реНрдЬ рдХрд░реЗрдВ', 'error'); return; } // Parse cash flows const cashFlows = cashFlowsText.split(',').map(cf => parseFloat(cf.trim())).filter(cf => !isNaN(cf)); if (cashFlows.length === 0) { showNotification('рдХреГрдкрдпрд╛ рд╡реИрдз рдирдХрджреА рдкреНрд░рд╡рд╛рд╣ рджрд░реНрдЬ рдХрд░реЗрдВ', 'error'); return; } const rate = discountRate / 100; // Calculate NPV let npv = initial; const discountedCashFlows = []; for (let i = 0; i < cashFlows.length; i++) { const discounted = cashFlows[i] / Math.pow(1 + rate, i + 1); npv += discounted; discountedCashFlows.push(discounted); } // Calculate IRR (approximate) const irr = calculateIRR([initial, ...cashFlows]) * 100; // Calculate payback period let cumulative = initial; let paybackPeriod = 0; for (let i = 0; i < cashFlows.length; i++) { cumulative += cashFlows[i]; if (cumulative >= 0) { paybackPeriod = i + 1; break; } } // Calculate profitability index const presentValueInflows = discountedCashFlows.reduce((sum, cf) => sum + cf, 0); const profitabilityIndex = presentValueInflows / Math.abs(initial); // Investment decision const decision = npv > 0 ? 'Accept (NPV > 0)' : 'Reject (NPV < 0)'; // Display results document.getElementById('npvValue').textContent = formatCurrency(npv); document.getElementById('irrValue').textContent = irr.toFixed(2) + '%'; document.getElementById('paybackPeriod').textContent = paybackPeriod + ' years'; document.getElementById('profitabilityIndex').textContent = profitabilityIndex.toFixed(2); document.getElementById('investmentDecision').textContent = decision; document.getElementById('npvResult').style.display = 'block'; // Generate NPV breakdown generateNPVBreakdown([initial, ...cashFlows], discountedCashFlows, rate); showOTA(); } // Calculate IRR using Newton-Raphson method function calculateIRR(cashFlows) { let rate = 0.1; // Initial guess const tolerance = 1e-8; const maxIterations = 100; for (let i = 0; i < maxIterations; i++) { let npv = 0; let dnpv = 0; for (let j = 0; j < cashFlows.length; j++) { npv += cashFlows[j] / Math.pow(1 + rate, j); if (j > 0) { dnpv -= j * cashFlows[j] / Math.pow(1 + rate, j + 1); } } if (Math.abs(npv) < tolerance) break; if (Math.abs(dnpv) < tolerance) break; rate = rate - npv / dnpv; } return rate; } // Generate NPV Breakdown function generateNPVBreakdown(cashFlows, discountedCashFlows, rate) { const container = document.getElementById('npvData'); let html = `
рд╡рд░реНрд╖
рдирдХрджреА рдкреНрд░рд╡рд╛рд╣
рдЫреВрдЯ рдХрд╛рд░рдХ
рд╡рд░реНрддрдорд╛рди рдореВрд▓реНрдп
`; for (let i = 0; i < cashFlows.length; i++) { const discountFactor = 1 / Math.pow(1 + rate, i); const presentValue = i === 0 ? cashFlows[i] : discountedCashFlows[i - 1]; html += `
${i}
${formatCurrency(cashFlows[i])}
${discountFactor.toFixed(4)}
${formatCurrency(presentValue)}
`; } container.innerHTML = html; document.getElementById('npvBreakdown').style.display = 'block'; } // Sample Scenarios function useSample(scenario) { const scenarios = { mortgage: () => { switchTab('loan'); document.querySelector('[onclick="switchTab(\'loan\')"]').click(); document.getElementById('loanAmount').value = 300000; document.getElementById('loanRate').value = 6.5; document.getElementById('loanTerm').value = 30; document.getElementById('paymentFreq').value = 12; }, retirement: () => { switchTab('annuity'); document.querySelector('[onclick="switchTab(\'annuity\')"]').click(); document.getElementById('annuityPayment').value = 1000; document.getElementById('annuityRate').value = 8; document.getElementById('annuityPeriods').value = 300; // 25 years * 12 months document.getElementById('annuityTiming').value = 'ordinary'; }, college: () => { switchTab('basic'); document.querySelector('[onclick="switchTab(\'basic\')"]').click(); setSolveFor('rate'); document.getElementById('presentValue').value = 25000; document.getElementById('futureValue').value = 100000; document.getElementById('payment').value = 0; document.getElementById('periods').value = 18; document.getElementById('interestRate').value = ''; }, carloan: () => { switchTab('loan'); document.querySelector('[onclick="switchTab(\'loan\')"]').click(); document.getElementById('loanAmount').value = 40000; document.getElementById('loanRate').value = 5.5; document.getElementById('loanTerm').value = 5; document.getElementById('paymentFreq').value = 12; }, investment: () => { switchTab('investment'); document.querySelector('[onclick="switchTab(\'investment\')"]').click(); document.getElementById('initialInvestment').value = 50000; document.getElementById('targetAmount').value = 100000; document.getElementById('investmentPeriod').value = 6; document.getElementById('annualContribution').value = 0; }, annuity: () => { switchTab('annuity'); document.querySelector('[onclick="switchTab(\'annuity\')"]').click(); document.getElementById('annuityPayment').value = 50000; document.getElementById('annuityRate').value = 6; document.getElementById('annuityPeriods').value = 240; // 20 years * 12 months document.getElementById('annuityTiming').value = 'ordinary'; } }; if (scenarios[scenario]) { scenarios[scenario](); // Smooth scroll to calculate button setTimeout(() => { const calculateBtn = document.querySelector('.tab-content.active .btn'); if (calculateBtn) { calculateBtn.scrollIntoView({ behavior: 'smooth', block: 'center' }); // Highlight button calculateBtn.style.animation = 'pulse 0.5s ease-in-out'; setTimeout(() => calculateBtn.style.animation = '', 500); } }, 100); } } // Utility Functions function formatCurrency(amount) { return new Intl.NumberFormat('en-US', { style: 'currency', currency: 'рдпреВрдПрд╕рдбреА', minimumFractionDigits: 0, maximumFractionDigits: 0 }).format(Math.abs(amount)); } function showNotification(message, type = 'success') { const toast = document.createElement('div'); toast.className = `toast ${type}`; toast.textContent = message; document.body.appendChild(toast); setTimeout(() => { toast.remove(); }, 3000); } function showOTA() { const otaContainer = document.getElementById('otaContainer'); if (otaContainer && (otaContainer.style.display === 'none' || !otaContainer.style.display)) { otaContainer.style.display = 'block'; setTimeout(() => { const otaHeader = document.querySelector('.ota-header h3'); if (otaHeader) { otaHeader.style.animation = 'pulse 1s ease-in-out'; } }, 100); } } function trackEvent(eventName, data = {}) { if (typeof gtag !== 'undefined') { gtag('event', eventName, { 'event_category': TOOL_CONFIG.category, 'event_label': TOOL_CONFIG.name, ...data }); } } // AI Assistant Functions function openAIModal() { const modal = document.getElementById('aiModal'); modal.classList.add('show'); } function closeAIModal() { const modal = document.getElementById('aiModal'); modal.classList.remove('show'); } function selectAI(aiType) { switch(aiType) { case 'chatgpt': const toolContext = `I need help with Time Value of Money calculations using the WIA Code TVM Calculator. Please help me understand present value, future value, annuities, loan calculations, and investment analysis.`; const chatUrl = `https://chat.openai.com/?q=${encodeURIComponent(toolContext)}`; window.open(chatUrl, '_blank'); closeAIModal(); trackEvent('ai_selection', { ai_type: 'chatgpt' }); break; case 'claude': const claudeContext = `I need help with Time Value of Money calculations using the WIA Code TVM Calculator. Please help me understand present value, future value, annuities, loan calculations, and investment analysis.`; const claudeUrl = `https://claude.ai/chat?q=${encodeURIComponent(claudeContext)}`; window.open(claudeUrl, '_blank'); closeAIModal(); trackEvent('ai_selection', { ai_type: 'claude' }); break; case 'gemini': showNotification('Gemini integration coming soon!', 'warning'); trackEvent('ai_selection', { ai_type: 'gemini' }); break; } } // Event Listeners document.addEventListener('рдбреАрдУрдПрдо рдХрдВрдЯреЗрдВрдЯ рд▓реЛрдбреЗрдб', function() { // Enter key support for inputs document.querySelectorAll('input[type="number"], input[type="text"]').forEach(input => { input.addEventListener('keypress', function(e) { if (e.key === 'рдПрдВрдЯрд░') { const activeTab = document.querySelector('.tab-content.active'); const calculateBtn = activeTab.querySelector('.btn'); if (calculateBtn) { calculateBtn.click(); } } }); }); // AI button event document.getElementById('aiBtn').addEventListener('click', openAIModal); // Modal outside click close document.getElementById('aiModal').addEventListener('click', function(e) { if (e.target === this) { closeAIModal(); } }); // ESC key to close modal document.addEventListener('keydown', function(e) { if (e.key === 'рдПрд╕реНрдХреЗрдк') { closeAIModal(); } }); updateCurrentYear(); updateToolCount(); }); // Dynamic Tool Count async function updateToolCount() { try { const response = await fetch('/api/tool-count.php'); const data = await response.json(); document.querySelectorAll('.dynamic-tools-count').forEach(el => { el.textContent = `${data.count}+ free online tools in 206 languages. No signup, no fees, just tools that work.`; }); document.querySelectorAll('.dynamic-count').forEach(el => { const prefix = el.getAttribute('data-text') || ''; const suffix = el.getAttribute('data-suffix') || ''; const icon = el.textContent.split(' ')[0] || ''; el.textContent = `${icon} ${prefix} ${data.count}+ ${suffix}`; }); } catch (error) { const fallbackCount = 333; document.querySelectorAll('.dynamic-tools-count').forEach(el => { el.textContent = `${fallbackCount}+ free online tools in 206 languages. No signup, no fees, just tools that work.`; }); document.querySelectorAll('.dynamic-count').forEach(el => { const prefix = el.getAttribute('data-text') || ''; const suffix = el.getAttribute('data-suffix') || ''; const icon = el.textContent.split(' ')[0] || ''; el.textContent = `${icon} ${prefix} ${fallbackCount}+ ${suffix}`; }); } } function updateCurrentYear() { const currentYear = new Date().getFullYear(); document.querySelectorAll('.current-year').forEach(el => { el.textContent = currentYear; }); } // Google Analytics window.dataLayer = window.dataLayer || []; function gtag(){dataLayer.push(arguments);} gtag('js', new Date()); gtag('config', 'G-XXXXXXXXX'); trackEvent('page_view', { tool: TOOL_CONFIG.name, category: TOOL_CONFIG.category }); : asset.symbol; document.getElementById('pvLabel').textContent = `Present Value (PV) ${symbol}`; document.getElementById('fvLabel').textContent = `Future Value (FV) ${symbol}`; document.getElementById('pmtLabel').textContent = `Payment (PMT) ${symbol}`; } // Update crypto price display function updatePriceDisplay() { const priceDisplay = document.getElementById('cryptoPriceDisplay'); const priceTitle = document.getElementById('cryptoPriceTitle'); const priceValue = document.getElementById('cryptoPriceValue'); if (currentAssetType === 'рдпреВрдПрд╕рдбреА') { priceDisplay.style.display = 'none'; } else { const asset = CRYPTO_ASSETS[currentAssetType]; priceDisplay.style.display = 'block'; priceTitle.textContent = `${asset.name} Current Price`; priceValue.textContent = `1 ${asset.symbol} = ${asset.currentPrice.toLocaleString()} USD`; } } // Update rate hints based on asset type function updateRateHints() { const asset = CRYPTO_ASSETS[currentAssetType]; const rateHint = document.getElementById('rateHint'); if (currentAssetType === 'рдпреВрдПрд╕рдбреА') { rateHint.textContent = 'Traditional assets: 3-12%, Enter your expected return'; } else { rateHint.textContent = `${asset.name} - Risk: ${asset.riskLevel}, Enter your expected return`; // Clear any auto-filled rate to let user decide const rateField = document.getElementById('interestRate'); if (rateField.value == 8) { rateField.value = ''; } } } // Toggle crypto disclaimer function toggleCryptoDisclaimer() { const disclaimer = document.getElementById('cryptoDisclaimer'); if (currentAssetType === 'рдпреВрдПрд╕рдбреА') { disclaimer.style.display = 'none'; } else { disclaimer.style.display = 'block'; } } // Tab Management function switchTab(tabName) { document.querySelectorAll('.tab-content').forEach(tab => { tab.classList.remove('active'); }); document.querySelectorAll('.tab-button').forEach(btn => { btn.classList.remove('active'); }); document.getElementById(tabName + 'рдЯреИрдм').classList.add('active'); event.target.classList.add('active'); } // Solve For Selection function setSolveFor(solveType) { document.querySelectorAll('.solve-for-option').forEach(option => { option.classList.remove('active'); }); event.target.classList.add('active'); currentSolveFor = solveType; // Clear the field we're solving for const fieldMap = { 'pv': 'presentValue', 'fv': 'futureValue', 'pmt': 'payment', 'rate': 'interestRate', 'periods': 'periods' }; document.getElementById(fieldMap[solveType]).value = ''; } // Annuity Type Selection function setAnnuityType(type) { document.querySelectorAll('.toggle-button').forEach(btn => { btn.classList.remove('active'); }); event.target.classList.add('active'); currentAnnuityType = type; } // Main TVM Calculation function calculateTVM() { try { const pv = parseFloat(document.getElementById('presentValue').value) || 0; const fv = parseFloat(document.getElementById('futureValue').value) || 0; const pmt = parseFloat(document.getElementById('payment').value) || 0; const rate = parseFloat(document.getElementById('interestRate').value) || 0; const periods = parseFloat(document.getElementById('periods').value) || 0; const compFreq = parseInt(document.getElementById('compoundingFreq').value) || 12; if (rate <= 0 && currentSolveFor !== 'rate') { showNotification('Interest rate must be greater than 0', 'error'); return; } if (periods <= 0 && currentSolveFor !== 'periods') { showNotification('Number of periods must be greater than 0', 'error'); return; } const result = solveTVM(pv, fv, pmt, rate, periods, compFreq, currentSolveFor, currentAnnuityType); displayTVMResult(result); showOTA(); trackEvent('tvm_calculated', { solveFor: currentSolveFor }); } catch (error) { showNotification(`Calculation error: ${error.message}`, 'error'); } } // Core TVM Solver function solveTVM(pv, fv, pmt, rate, periods, compFreq, solveFor, annuityType) { const periodicRate = rate / 100 / compFreq; const totalPeriods = periods * compFreq; let result = {}; switch (solveFor) { case 'pv': result.value = calculatePresentValue(fv, pmt, periodicRate, totalPeriods, annuityType); result.label = 'рд╡рд░реНрддрдорд╛рди рдореВрд▓реНрдп'; break; case 'fv': result.value = calculateFutureValue(pv, pmt, periodicRate, totalPeriods, annuityType); result.label = 'Future Value'; break; case 'pmt': result.value = calculatePayment(pv, fv, periodicRate, totalPeriods, annuityType); result.label = 'рднреБрдЧрддрд╛рди рд░рд╛рд╢рд┐'; break; case 'rate': const solvedRate = calculateInterestRate(pv, fv, pmt, totalPeriods, annuityType); result.value = solvedRate * compFreq * 100; result.label = 'рд╡рд╛рд░реНрд╖рд┐рдХ рдмреНрдпрд╛рдЬ рджрд░'; result.isPercentage = true; break; case 'periods': const solvedPeriods = calculatePeriods(pv, fv, pmt, periodicRate, annuityType); result.value = solvedPeriods / compFreq; result.label = 'рдЕрд╡рдзрд┐рдпреЛрдВ рдХреА рд╕рдВрдЦреНрдпрд╛'; result.isYears = true; break; } // Calculate additional details const effectiveRate = Math.pow(1 + periodicRate, compFreq) - 1; const totalPayments = Math.abs(pmt) * totalPeriods; result.effectiveRate = effectiveRate * 100; result.totalPayments = totalPayments; if (solveFor === 'pv') { result.totalInterest = Math.abs(result.value) - Math.abs(fv) + totalPayments; } else if (solveFor === 'fv') { result.totalInterest = Math.abs(result.value) - Math.abs(pv) - totalPayments; } else { result.totalInterest = totalPayments - Math.abs(pv); } return result; } // Present Value Calculation function calculatePresentValue(fv, pmt, rate, periods, type) { let pv = 0; if (fv !== 0) { pv += fv / Math.pow(1 + rate, periods); } if (pmt !== 0 && rate !== 0) { const annuityPV = pmt * (1 - Math.pow(1 + rate, -periods)) / rate; if (type === 'due') { pv += annuityPV * (1 + rate); } else { pv += annuityPV; } } else if (pmt !== 0 && rate === 0) { pv += pmt * periods; } return -pv; // Financial calculator convention } // Future Value Calculation function calculateFutureValue(pv, pmt, rate, periods, type) { let fv = 0; if (pv !== 0) { fv += -pv * Math.pow(1 + rate, periods); } if (pmt !== 0 && rate !== 0) { const annuityFV = pmt * (Math.pow(1 + rate, periods) - 1) / rate; if (type === 'due') { fv += annuityFV * (1 + rate); } else { fv += annuityFV; } } else if (pmt !== 0 && rate === 0) { fv += pmt * periods; } return fv; } // Payment Calculation function calculatePayment(pv, fv, rate, periods, type) { if (rate === 0) { return -(pv + fv) / periods; } const pvFactor = pv * Math.pow(1 + rate, periods); const numerator = -(pvFactor + fv); const denominator = (Math.pow(1 + rate, periods) - 1) / rate; let pmt = numerator / denominator; if (type === 'due') { pmt = pmt / (1 + rate); } return pmt; } // Interest Rate Calculation (Newton-Raphson method) function calculateInterestRate(pv, fv, pmt, periods, type) { if (pv === 0 && pmt === 0) return 0; if (fv === 0 && pmt === 0) return 0; let rate = 0.1; // Initial guess const tolerance = 1e-8; const maxIterations = 100; for (let i = 0; i < maxIterations; i++) { const f = evaluateTVMFunction(pv, fv, pmt, rate, periods, type); const df = evaluateTVMDerivative(pv, fv, pmt, rate, periods, type); if (Math.abs(df) < tolerance) break; const newRate = rate - f / df; if (Math.abs(newRate - rate) < tolerance) { return newRate; } rate = newRate; } return rate; } // TVM Function Evaluation function evaluateTVMFunction(pv, fv, pmt, rate, periods, type) { if (rate === 0) { return pv + fv + pmt * periods; } const pvTerm = pv; const fvTerm = fv / Math.pow(1 + rate, periods); let pmtTerm = 0; if (pmt !== 0) { pmtTerm = pmt * (1 - Math.pow(1 + rate, -periods)) / rate; if (type === 'due') { pmtTerm *= (1 + rate); } } return pvTerm + fvTerm + pmtTerm; } // TVM Derivative Evaluation function evaluateTVMDerivative(pv, fv, pmt, rate, periods, type) { const h = 1e-8; const f1 = evaluateTVMFunction(pv, fv, pmt, rate + h, periods, type); const f2 = evaluateTVMFunction(pv, fv, pmt, rate - h, periods, type); return (f1 - f2) / (2 * h); } // Periods Calculation function calculatePeriods(pv, fv, pmt, rate, type) { if (rate === 0) { return -(pv + fv) / pmt; } // Simplified calculation for common cases if (pmt === 0) { return Math.log(-fv / pv) / Math.log(1 + rate); } // For annuity calculations, use iterative method let periods = 10; // Initial guess const tolerance = 1e-8; const maxIterations = 100; for (let i = 0; i < maxIterations; i++) { const calculatedFV = calculateFutureValue(pv, pmt, rate, periods, type); const error = Math.abs(calculatedFV - fv); if (error < tolerance) break; // Adjust periods based on error if (calculatedFV < fv) { periods += 0.1; } else { periods -= 0.1; } if (periods <= 0) { periods = 0.1; } } return periods; } // Display TVM Results function displayTVMResult(result) { const resultContainer = document.getElementById('tvmResult'); const resultLabel = document.getElementById('resultLabel'); const resultValue = document.getElementById('resultValue'); const effectiveRate = document.getElementById('effectiveRate'); const totalPayments = document.getElementById('totalPayments'); const totalInterest = document.getElementById('totalInterest'); resultLabel.textContent = result.label; if (result.isPercentage) { resultValue.textContent = result.value.toFixed(2) + '%'; } else if (result.isYears) { resultValue.textContent = result.value.toFixed(1) + ' years'; } else { resultValue.textContent = formatCurrency(result.value); } effectiveRate.textContent = result.effectiveRate.toFixed(2) + '%'; totalPayments.textContent = formatCurrency(result.totalPayments); totalInterest.textContent = formatCurrency(result.totalInterest); resultContainer.style.display = 'block'; } // Loan Calculator function calculateLoan() { const principal = parseFloat(document.getElementById('loanAmount').value) || 0; const rate = parseFloat(document.getElementById('loanRate').value) || 0; const years = parseFloat(document.getElementById('loanTerm').value) || 0; const freq = parseInt(document.getElementById('paymentFreq').value) || 12; if (principal <= 0 || rate <= 0 || years <= 0) { showNotification('рдХреГрдкрдпрд╛ рд╡реИрдз рдЛрдг рдорд╛рдкрджрдВрдб рджрд░реНрдЬ рдХрд░реЗрдВ', 'error'); return; } const periodicRate = rate / 100 / freq; const totalPayments = years * freq; // Calculate monthly payment using PMT formula const payment = principal * (periodicRate * Math.pow(1 + periodicRate, totalPayments)) / (Math.pow(1 + periodicRate, totalPayments) - 1); const totalOfPayments = payment * totalPayments; const totalInterest = totalOfPayments - principal; const interestPercentage = (totalInterest / principal) * 100; // Display results document.getElementById('loanPayment').textContent = formatCurrency(payment); document.getElementById('totalLoanPayments').textContent = formatCurrency(totalOfPayments); document.getElementById('totalLoanInterest').textContent = formatCurrency(totalInterest); document.getElementById('interestPercentage').textContent = interestPercentage.toFixed(1) + '%'; document.getElementById('loanResult').style.display = 'block'; // Generate amortization table generateAmortizationTable(principal, payment, periodicRate, 12); showOTA(); } // Generate Amortization Table function generateAmortizationTable(principal, payment, periodicRate, numPayments) { const container = document.getElementById('amortizationData'); let balance = principal; let html = `
рднреБрдЧрддрд╛рди рдХреНрд░рдорд╛рдВрдХ
рднреБрдЧрддрд╛рди
рдмреНрдпрд╛рдЬ
рдореВрд▓рдзрди
рд╢реЗрд╖ рд░рд╛рд╢рд┐
`; for (let i = 1; i <= numPayments; i++) { const interestPayment = balance * periodicRate; const principalPayment = payment - interestPayment; balance -= principalPayment; html += `
${i}
${formatCurrency(payment)}
${formatCurrency(interestPayment)}
${formatCurrency(principalPayment)}
${formatCurrency(balance)}
`; } container.innerHTML = html; document.getElementById('amortizationTable').style.display = 'block'; } // Annuity Calculator function calculateAnnuity() { const payment = parseFloat(document.getElementById('annuityPayment').value) || 0; const rate = parseFloat(document.getElementById('annuityRate').value) || 0; const periods = parseInt(document.getElementById('annuityPeriods').value) || 0; const timing = document.getElementById('annuityTiming').value; if (payment <= 0 || rate <= 0 || periods <= 0) { showNotification('рдХреГрдкрдпрд╛ рд╡реИрдз рд╡рд╛рд░реНрд╖рд┐рдХреА рдорд╛рдкрджрдВрдб рджрд░реНрдЬ рдХрд░реЗрдВ', 'error'); return; } const periodicRate = rate / 100 / 12; // Assuming monthly payments // Calculate present value let pv = payment * (1 - Math.pow(1 + periodicRate, -periods)) / periodicRate; // Calculate future value let fv = payment * (Math.pow(1 + periodicRate, periods) - 1) / periodicRate; // Adjust for annuity due if (timing === 'due') { pv *= (1 + periodicRate); fv *= (1 + periodicRate); } const totalPayments = payment * periods; const interestEarned = fv - totalPayments; const effectiveRate = Math.pow(1 + periodicRate, 12) - 1; // Display results document.getElementById('annuityPV').textContent = formatCurrency(pv); document.getElementById('annuityFV').textContent = formatCurrency(fv); document.getElementById('totalAnnuityPayments').textContent = formatCurrency(totalPayments); document.getElementById('annuityInterest').textContent = formatCurrency(interestEarned); document.getElementById('annuityEffectiveRate').textContent = (effectiveRate * 100).toFixed(2) + '%'; document.getElementById('annuityResult').style.display = 'block'; showOTA(); } // Investment Analysis function calculateInvestment() { const initial = parseFloat(document.getElementById('initialInvestment').value) || 0; const target = parseFloat(document.getElementById('targetAmount').value) || 0; const years = parseFloat(document.getElementById('investmentPeriod').value) || 0; const annual = parseFloat(document.getElementById('annualContribution').value) || 0; if (initial <= 0 || target <= 0 || years <= 0) { showNotification('рдХреГрдкрдпрд╛ рд╡реИрдз рдирд┐рд╡реЗрд╢ рдорд╛рдкрджрдВрдб рджрд░реНрдЬ рдХрд░реЗрдВ', 'error'); return; } // Calculate required return rate const totalInvested = initial + (annual * years); // Use iterative method to find required rate let rate = 0.05; // Initial guess for (let i = 0; i < 100; i++) { const futureValue = initial * Math.pow(1 + rate, years) + annual * (Math.pow(1 + rate, years) - 1) / rate; if (Math.abs(futureValue - target) < 1) break; if (futureValue < target) { rate += 0.001; } else { rate -= 0.001; } } const growth = target - totalInvested; const breakEven = Math.log(initial * 2 / initial) / Math.log(1 + rate); // Display results document.getElementById('requiredReturn').textContent = (rate * 100).toFixed(2) + '%'; document.getElementById('totalInvested').textContent = formatCurrency(totalInvested); document.getElementById('investmentGrowth').textContent = formatCurrency(growth); document.getElementById('breakEvenTime').textContent = breakEven.toFixed(1) + ' years'; document.getElementById('investmentResult').style.display = 'block'; showOTA(); } // NPV Calculator function calculateNPV() { const initial = parseFloat(document.getElementById('npvInitial').value) || 0; const discountRate = parseFloat(document.getElementById('discountRate').value) || 0; const cashFlowsText = document.getElementById('cashFlows').value; if (discountRate <= 0) { showNotification('рдХреГрдкрдпрд╛ рд╡реИрдз рдЫреВрдЯ рджрд░ рджрд░реНрдЬ рдХрд░реЗрдВ', 'error'); return; } // Parse cash flows const cashFlows = cashFlowsText.split(',').map(cf => parseFloat(cf.trim())).filter(cf => !isNaN(cf)); if (cashFlows.length === 0) { showNotification('рдХреГрдкрдпрд╛ рд╡реИрдз рдирдХрджреА рдкреНрд░рд╡рд╛рд╣ рджрд░реНрдЬ рдХрд░реЗрдВ', 'error'); return; } const rate = discountRate / 100; // Calculate NPV let npv = initial; const discountedCashFlows = []; for (let i = 0; i < cashFlows.length; i++) { const discounted = cashFlows[i] / Math.pow(1 + rate, i + 1); npv += discounted; discountedCashFlows.push(discounted); } // Calculate IRR (approximate) const irr = calculateIRR([initial, ...cashFlows]) * 100; // Calculate payback period let cumulative = initial; let paybackPeriod = 0; for (let i = 0; i < cashFlows.length; i++) { cumulative += cashFlows[i]; if (cumulative >= 0) { paybackPeriod = i + 1; break; } } // Calculate profitability index const presentValueInflows = discountedCashFlows.reduce((sum, cf) => sum + cf, 0); const profitabilityIndex = presentValueInflows / Math.abs(initial); // Investment decision const decision = npv > 0 ? 'Accept (NPV > 0)' : 'Reject (NPV < 0)'; // Display results document.getElementById('npvValue').textContent = formatCurrency(npv); document.getElementById('irrValue').textContent = irr.toFixed(2) + '%'; document.getElementById('paybackPeriod').textContent = paybackPeriod + ' years'; document.getElementById('profitabilityIndex').textContent = profitabilityIndex.toFixed(2); document.getElementById('investmentDecision').textContent = decision; document.getElementById('npvResult').style.display = 'block'; // Generate NPV breakdown generateNPVBreakdown([initial, ...cashFlows], discountedCashFlows, rate); showOTA(); } // Calculate IRR using Newton-Raphson method function calculateIRR(cashFlows) { let rate = 0.1; // Initial guess const tolerance = 1e-8; const maxIterations = 100; for (let i = 0; i < maxIterations; i++) { let npv = 0; let dnpv = 0; for (let j = 0; j < cashFlows.length; j++) { npv += cashFlows[j] / Math.pow(1 + rate, j); if (j > 0) { dnpv -= j * cashFlows[j] / Math.pow(1 + rate, j + 1); } } if (Math.abs(npv) < tolerance) break; if (Math.abs(dnpv) < tolerance) break; rate = rate - npv / dnpv; } return rate; } // Generate NPV Breakdown function generateNPVBreakdown(cashFlows, discountedCashFlows, rate) { const container = document.getElementById('npvData'); let html = `
рд╡рд░реНрд╖
рдирдХрджреА рдкреНрд░рд╡рд╛рд╣
рдЫреВрдЯ рдХрд╛рд░рдХ
рд╡рд░реНрддрдорд╛рди рдореВрд▓реНрдп
`; for (let i = 0; i < cashFlows.length; i++) { const discountFactor = 1 / Math.pow(1 + rate, i); const presentValue = i === 0 ? cashFlows[i] : discountedCashFlows[i - 1]; html += `
${i}
${formatCurrency(cashFlows[i])}
${discountFactor.toFixed(4)}
${formatCurrency(presentValue)}
`; } container.innerHTML = html; document.getElementById('npvBreakdown').style.display = 'block'; } // Sample Scenarios function useSample(scenario) { const scenarios = { mortgage: () => { switchTab('loan'); document.querySelector('[onclick="switchTab(\'loan\')"]').click(); document.getElementById('loanAmount').value = 300000; document.getElementById('loanRate').value = 6.5; document.getElementById('loanTerm').value = 30; document.getElementById('paymentFreq').value = 12; }, retirement: () => { switchTab('annuity'); document.querySelector('[onclick="switchTab(\'annuity\')"]').click(); document.getElementById('annuityPayment').value = 1000; document.getElementById('annuityRate').value = 8; document.getElementById('annuityPeriods').value = 300; // 25 years * 12 months document.getElementById('annuityTiming').value = 'ordinary'; }, college: () => { switchTab('basic'); document.querySelector('[onclick="switchTab(\'basic\')"]').click(); setSolveFor('rate'); document.getElementById('presentValue').value = 25000; document.getElementById('futureValue').value = 100000; document.getElementById('payment').value = 0; document.getElementById('periods').value = 18; document.getElementById('interestRate').value = ''; }, carloan: () => { switchTab('loan'); document.querySelector('[onclick="switchTab(\'loan\')"]').click(); document.getElementById('loanAmount').value = 40000; document.getElementById('loanRate').value = 5.5; document.getElementById('loanTerm').value = 5; document.getElementById('paymentFreq').value = 12; }, investment: () => { switchTab('investment'); document.querySelector('[onclick="switchTab(\'investment\')"]').click(); document.getElementById('initialInvestment').value = 50000; document.getElementById('targetAmount').value = 100000; document.getElementById('investmentPeriod').value = 6; document.getElementById('annualContribution').value = 0; }, annuity: () => { switchTab('annuity'); document.querySelector('[onclick="switchTab(\'annuity\')"]').click(); document.getElementById('annuityPayment').value = 50000; document.getElementById('annuityRate').value = 6; document.getElementById('annuityPeriods').value = 240; // 20 years * 12 months document.getElementById('annuityTiming').value = 'ordinary'; } }; if (scenarios[scenario]) { scenarios[scenario](); // Smooth scroll to calculate button setTimeout(() => { const calculateBtn = document.querySelector('.tab-content.active .btn'); if (calculateBtn) { calculateBtn.scrollIntoView({ behavior: 'smooth', block: 'center' }); // Highlight button calculateBtn.style.animation = 'pulse 0.5s ease-in-out'; setTimeout(() => calculateBtn.style.animation = '', 500); } }, 100); } } // Utility Functions function formatCurrency(amount) { return new Intl.NumberFormat('en-US', { style: 'currency', currency: 'рдпреВрдПрд╕рдбреА', minimumFractionDigits: 0, maximumFractionDigits: 0 }).format(Math.abs(amount)); } function showNotification(message, type = 'success') { const toast = document.createElement('div'); toast.className = `toast ${type}`; toast.textContent = message; document.body.appendChild(toast); setTimeout(() => { toast.remove(); }, 3000); } function showOTA() { const otaContainer = document.getElementById('otaContainer'); if (otaContainer && (otaContainer.style.display === 'none' || !otaContainer.style.display)) { otaContainer.style.display = 'block'; setTimeout(() => { const otaHeader = document.querySelector('.ota-header h3'); if (otaHeader) { otaHeader.style.animation = 'pulse 1s ease-in-out'; } }, 100); } } function trackEvent(eventName, data = {}) { if (typeof gtag !== 'undefined') { gtag('event', eventName, { 'event_category': TOOL_CONFIG.category, 'event_label': TOOL_CONFIG.name, ...data }); } } // AI Assistant Functions function openAIModal() { const modal = document.getElementById('aiModal'); modal.classList.add('show'); } function closeAIModal() { const modal = document.getElementById('aiModal'); modal.classList.remove('show'); } function selectAI(aiType) { switch(aiType) { case 'chatgpt': const toolContext = `I need help with Time Value of Money calculations using the WIA Code TVM Calculator. Please help me understand present value, future value, annuities, loan calculations, and investment analysis.`; const chatUrl = `https://chat.openai.com/?q=${encodeURIComponent(toolContext)}`; window.open(chatUrl, '_blank'); closeAIModal(); trackEvent('ai_selection', { ai_type: 'chatgpt' }); break; case 'claude': const claudeContext = `I need help with Time Value of Money calculations using the WIA Code TVM Calculator. Please help me understand present value, future value, annuities, loan calculations, and investment analysis.`; const claudeUrl = `https://claude.ai/chat?q=${encodeURIComponent(claudeContext)}`; window.open(claudeUrl, '_blank'); closeAIModal(); trackEvent('ai_selection', { ai_type: 'claude' }); break; case 'gemini': showNotification('Gemini integration coming soon!', 'warning'); trackEvent('ai_selection', { ai_type: 'gemini' }); break; } } // Event Listeners document.addEventListener('рдбреАрдУрдПрдо рдХрдВрдЯреЗрдВрдЯ рд▓реЛрдбреЗрдб', function() { // Enter key support for inputs document.querySelectorAll('input[type="number"], input[type="text"]').forEach(input => { input.addEventListener('keypress', function(e) { if (e.key === 'рдПрдВрдЯрд░') { const activeTab = document.querySelector('.tab-content.active'); const calculateBtn = activeTab.querySelector('.btn'); if (calculateBtn) { calculateBtn.click(); } } }); }); // AI button event document.getElementById('aiBtn').addEventListener('click', openAIModal); // Modal outside click close document.getElementById('aiModal').addEventListener('click', function(e) { if (e.target === this) { closeAIModal(); } }); // ESC key to close modal document.addEventListener('keydown', function(e) { if (e.key === 'рдПрд╕реНрдХреЗрдк') { closeAIModal(); } }); updateCurrentYear(); updateToolCount(); }); // Dynamic Tool Count async function updateToolCount() { try { const response = await fetch('/api/tool-count.php'); const data = await response.json(); document.querySelectorAll('.dynamic-tools-count').forEach(el => { el.textContent = `${data.count}+ free online tools in 206 languages. No signup, no fees, just tools that work.`; }); document.querySelectorAll('.dynamic-count').forEach(el => { const prefix = el.getAttribute('data-text') || ''; const suffix = el.getAttribute('data-suffix') || ''; const icon = el.textContent.split(' ')[0] || ''; el.textContent = `${icon} ${prefix} ${data.count}+ ${suffix}`; }); } catch (error) { const fallbackCount = 333; document.querySelectorAll('.dynamic-tools-count').forEach(el => { el.textContent = `${fallbackCount}+ free online tools in 206 languages. No signup, no fees, just tools that work.`; }); document.querySelectorAll('.dynamic-count').forEach(el => { const prefix = el.getAttribute('data-text') || ''; const suffix = el.getAttribute('data-suffix') || ''; const icon = el.textContent.split(' ')[0] || ''; el.textContent = `${icon} ${prefix} ${fallbackCount}+ ${suffix}`; }); } } function updateCurrentYear() { const currentYear = new Date().getFullYear(); document.querySelectorAll('.current-year').forEach(el => { el.textContent = currentYear; }); } // Google Analytics window.dataLayer = window.dataLayer || []; function gtag(){dataLayer.push(arguments);} gtag('js', new Date()); gtag('config', 'G-XXXXXXXXX'); trackEvent('page_view', { tool: TOOL_CONFIG.name, category: TOOL_CONFIG.category });