āϟāĻžāχāĻŽ āĻ­ā§āϝāĻžāϞ⧁ āĻ…āĻĢ āĻŽāĻžāύāĻŋ āĻāĻŦāĻ‚ āĻĄāĻŋāϜāĻŋāϟāĻžāϞ āϏāĻŽā§āĻĒāĻĻ āĻ•ā§āϝāĻžāϞāϕ⧁āϞ⧇āϟāϰ

āϐāϤāĻŋāĻšā§āϝāĻŦāĻžāĻšā§€ āĻāĻŦāĻ‚ āĻĄāĻŋāϜāĻŋāϟāĻžāϞ āϏāĻŽā§āĻĒāĻĻ⧇āϰ āφāĻ°ā§āĻĨāĻŋāĻ• āϏāĻŋāĻĻā§āϧāĻžāĻ¨ā§āϤāϗ⧁āϞāĻŋ āύāĻŋāϖ⧁āρāϤāĻ­āĻžāĻŦ⧇ āύāĻŋāύāĨ¤ āχāωāĻāϏāĻĄāĻŋ, āĻŦāĻŋāϟāĻ•āϝāĻŧ⧇āύ, āχāĻĨ⧇āϰāĻŋāϝāĻŧāĻžāĻŽ āĻāĻŦāĻ‚ āĻĒā§āϰāϧāĻžāύ āĻ•ā§āϰāĻŋāĻĒā§āĻŸā§‹āĻ•āĻžāϰ⧇āĻ¨ā§āϏāĻŋāϰ āϜāĻ¨ā§āϝ āĻŦāĻ°ā§āϤāĻŽāĻžāύ āĻŽā§‚āĻ˛ā§āϝ, āĻ­āĻŦāĻŋāĻˇā§āĻ¯ā§Ž āĻŽā§‚āĻ˛ā§āϝ, āĻĒ⧇āĻŽā§‡āĻ¨ā§āϟ āĻāĻŦāĻ‚ āϰāĻŋāϟāĻžāĻ°ā§āύ āĻ—āĻŖāύāĻž āĻ•āϰ⧁āύāĨ¤

āĻĄāĻŋāϜāĻŋāϟāĻžāϞ āϏāĻŽā§āĻĒāĻĻ āϏāĻš ā§Ģ-āϕ⧀ āϟāĻžāχāĻŽ āĻ­ā§āϝāĻžāϞ⧁ āĻ…āĻĢ āĻŽāĻžāύāĻŋ āĻ•ā§āϝāĻžāϞāϕ⧁āϞ⧇āϟāϰ

āϝ⧇āϕ⧋āύ⧋ ā§ĒāϟāĻŋ āĻŽāĻžāύ āĻĒā§āϰāĻŦ⧇āĻļ āĻ•āϰāĻžāύ āĻāĻŦāĻ‚ ā§ĢāĻŽ āĻŽāĻžāύāϟāĻŋ āĻŦ⧇āϰ āĻ•āϰ⧁āύāĨ¤ āϐāϤāĻŋāĻšā§āϝāĻŦāĻžāĻšā§€ āĻŽā§āĻĻā§āϰāĻž āĻāĻŦāĻ‚ āĻŦāĻŋāϟāĻ•āϝāĻŧ⧇āύ, āχāĻĨ⧇āϰāĻŋāϝāĻŧāĻžāĻŽ āϏāĻš āĻĒā§āϰāϧāĻžāύ āĻ•ā§āϰāĻŋāĻĒā§āĻŸā§‹āĻ•āĻžāϰ⧇āĻ¨ā§āϏāĻŋāϗ⧁āϞāĻŋāϰ āϏāĻžāĻĨ⧇ āĻ•āĻžāϜ āĻ•āϰ⧇āĨ¤

āχāωāĻāϏāĻĄāĻŋ ($)
āĻŦāĻŋāϟāĻ•āϝāĻŧ⧇āύ (BTC)
āχāĻĨ⧇āϰāĻŋāϝāĻŧāĻžāĻŽ (ETH)
āϏ⧋āϞāĻžāύāĻž (SOL)
āĻĄāĻŦā§āϞāĻŋāωāφāχāĻ (WIA)
āĻāĻ•ā§āϏāφāϰāĻĒāĻŋ (XRP)
āĻŦāĻ°ā§āϤāĻŽāĻžāύ āĻŽā§‚āĻ˛ā§āϝ (PV)
āĻ­āĻŦāĻŋāĻˇā§āĻ¯ā§Ž āĻŽā§‚āĻ˛ā§āϝ (FV)
āĻĒ⧇āĻŽā§‡āĻ¨ā§āϟ (PMT)
āϏ⧁āĻĻ⧇āϰ āĻšāĻžāϰ (I/Y)
āϏāĻŽāϝāĻŧāĻ•āĻžāϞ (N)
Traditional assets: 3-12%, Crypto: 5-30%
āϏāĻžāϧāĻžāϰāĻŖ āĻŦāĻžāĻ°ā§āώāĻŋāϕ⧀ (āĻļ⧇āώ⧇)
āĻ…āĻ—ā§āϰāĻŋāĻŽ āĻŦāĻžāĻ°ā§āώāĻŋāϕ⧀ (āĻļ⧁āϰ⧁āϤ⧇)

āĻ‹āĻŖ āĻĒāϰāĻŋāĻļā§‹āϧ āĻ•ā§āϝāĻžāϞāϕ⧁āϞ⧇āϟāϰ

āĻŦāĻ¨ā§āϧāϕ⧀ āĻ‹āĻŖ, āĻ—āĻžāĻĄāĻŧāĻŋāϰ āĻ‹āĻŖ āĻāĻŦāĻ‚ āĻŦā§āϝāĻ•ā§āϤāĻŋāĻ—āϤ āĻ‹āϪ⧇āϰ āĻŽāĻžāϏāĻŋāĻ• āĻ•āĻŋāĻ¸ā§āϤāĻŋ, āĻŽā§‹āϟ āϏ⧁āĻĻ āĻāĻŦāĻ‚ āĻ‹āĻŖ āĻĒāϰāĻŋāĻļā§‹āϧ⧇āϰ āϏāĻŽāϝāĻŧāϏ⧂āĻšā§€ āĻ—āĻŖāύāĻž āĻ•āϰ⧁āύāĨ¤

āĻŦāĻžāĻ°ā§āώāĻŋāϕ⧀ āĻŽā§‚āĻ˛ā§āϝ āĻ•ā§āϝāĻžāϞāϕ⧁āϞ⧇āϟāϰ

āϏāĻžāϧāĻžāϰāĻŖ āĻŦāĻžāĻ°ā§āώāĻŋāϕ⧀ āĻāĻŦāĻ‚ āύāĻŋāĻ°ā§āĻĻāĻŋāĻˇā§āϟ āĻŦāĻžāĻ°ā§āώāĻŋāϕ⧀āϰ āĻŦāĻ°ā§āϤāĻŽāĻžāύ āĻ“ āĻ­āĻŦāĻŋāĻˇā§āĻ¯ā§Ž āĻŽā§‚āĻ˛ā§āϝ āĻ—āĻŖāύāĻž āĻ•āϰ⧁āύāĨ¤ āĻ…āĻŦāϏāϰ āĻĒāϰāĻŋāĻ•āĻ˛ā§āĻĒāύāĻž āĻāĻŦāĻ‚ āĻŦāĻŋāύāĻŋāϝāĻŧā§‹āĻ— āĻŦāĻŋāĻļā§āϞ⧇āώāϪ⧇āϰ āϜāĻ¨ā§āϝ āωāĻĒāϝ⧁āĻ•ā§āϤāĨ¤

āĻŦāĻŋāύāĻŋāϝāĻŧā§‹āĻ— āĻŦāĻŋāĻļā§āϞ⧇āώāĻŖ āĻ•ā§āϝāĻžāϞāϕ⧁āϞ⧇āϟāϰ

āϰāĻŋāϟāĻžāĻ°ā§āύ, āĻĒā§āϰāϝāĻŧā§‹āϜāύ⧀āϝāĻŧ āĻšāĻžāϰ āĻāĻŦāĻ‚ āĻŦā§āϰ⧇āĻ•-āχāϭ⧇āύ āĻĒāϝāĻŧ⧇āĻ¨ā§āϟ āĻ—āĻŖāύāĻž āĻ•āϰ⧇ āĻŦāĻŋāύāĻŋāϝāĻŧā§‹āϗ⧇āϰ āĻŦāĻŋāĻ•āĻ˛ā§āĻĒāϗ⧁āϞāĻŋ āϤ⧁āϞāύāĻž āĻ•āϰ⧁āύāĨ¤ āĻŦāĻŋāύāĻŋāϝāĻŧā§‹āĻ— āϏāĻŋāĻĻā§āϧāĻžāĻ¨ā§āϤ āύ⧇āĻ“āϝāĻŧāĻžāϰ āϜāĻ¨ā§āϝ āφāĻĻāĻ°ā§āĻļāĨ¤

āύ⧇āϟ āĻŦāĻ°ā§āϤāĻŽāĻžāύ āĻŽā§‚āĻ˛ā§āϝ āĻŦāĻŋāĻļā§āϞ⧇āώāĻŖ

āĻāύāĻĒāĻŋāĻ­āĻŋ āĻāĻŦāĻ‚ āφāχāφāϰāφāϰ āĻ—āĻŖāύāĻž āĻ•āϰ⧇ āĻĒā§āϰāĻ•āĻ˛ā§āĻĒ⧇āϰ āϞāĻžāĻ­āϜāύāĻ•āϤāĻž āĻŽā§‚āĻ˛ā§āϝāĻžāϝāĻŧāύ āĻ•āϰ⧁āύāĨ¤ āĻŦāĻŋāĻ¸ā§āϤ⧃āϤ āĻŦāĻŋāύāĻŋāϝāĻŧā§‹āĻ— āĻŦāĻŋāĻļā§āϞ⧇āώāϪ⧇āϰ āϜāĻ¨ā§āϝ āĻ•ā§āϝāĻžāĻļ āĻĢā§āϞ⧋ āĻĒā§āϰāĻŦ⧇āĻļ āĻ•āϰāĻžāύāĨ¤

Enter positive values for cash inflows, negative for outflows

āĻĻā§āϰ⧁āϤ āĻļ⧁āϰ⧁āϰ āϏāĻŋāύāĻžāϰāĻŋāĻ“āϗ⧁āϞāĻŋ

ā§Šā§Ļ-āĻŦāĻ›āϰ⧇āϰ āĻŦāĻ¨ā§āϧāϕ⧀
ā§Šā§Ļ āĻŦāĻ›āϰ⧇āϰ āϜāĻ¨ā§āϝ ā§Ŧ.ā§Ģ% āϏ⧁āĻĻ⧇ $ā§Šā§Ļā§Ļāϕ⧇ āĻ‹āĻŖ
āĻ…āĻŦāϏāϰ āĻĒāϰāĻŋāĻ•āĻ˛ā§āĻĒāύāĻž
ā§Ž% āϏ⧁āĻĻ⧇ ⧍ā§Ģ āĻŦāĻ›āϰ⧇āϰ āϜāĻ¨ā§āϝ āĻŽāĻžāϏāĻŋāĻ• $ā§§āϕ⧇
āĻ•āϞ⧇āϜ āϤāĻšāĻŦāĻŋāϞ
āφāϜāϕ⧇āϰ $⧍ā§Ģāϕ⧇ ā§§ā§Ž āĻŦāĻ›āϰ⧇ $ā§§ā§Ļā§Ļāϕ⧇ āĻšāϝāĻŧ⧇ āĻŦ⧃āĻĻā§āϧāĻŋ āĻĒāĻžāϝāĻŧ
āĻ—āĻžāĻĄāĻŧāĻŋ āĻ‹āĻŖ
ā§Ģ āĻŦāĻ›āϰ⧇āϰ āϜāĻ¨ā§āϝ ā§Ģ.ā§Ģ% āϏ⧁āĻĻ⧇ $ā§Ēā§Ļāϕ⧇ āĻ—āĻžāĻĄāĻŧāĻŋ āĻ‹āĻŖ
āĻŦāĻŋāϟāĻ•āϝāĻŧ⧇āύ āĻŦāĻŋāύāĻŋāϝāĻŧā§‹āĻ—
ā§§ āĻŦāĻŋāϟāĻŋāϏāĻŋ ā§Ģ āĻŦāĻ›āϰ⧇ ā§§ā§Ģ% āĻšāĻžāϰ⧇ āĻŦ⧃āĻĻā§āϧāĻŋ āĻĒāĻžāϝāĻŧ
āχāĻĨ⧇āϰāĻŋāϝāĻŧāĻžāĻŽ āĻĄāĻŋāϏāĻŋāĻ
⧍ā§Ļ% āĻšāĻžāϰ⧇ ā§Š āĻŦāĻ›āϰ⧇āϰ āϜāĻ¨ā§āϝ āĻŽāĻžāϏāĻŋāĻ• ā§Ļ.ā§§ āχāĻĨ⧇āϰāĻŋāϝāĻŧāĻžāĻŽ
āĻĄāĻŦā§āϞāĻŋāωāφāχāĻ āĻŦāĻŋāύāĻŋāϝāĻŧā§‹āĻ—
ā§§ā§Ļ āĻŦāĻ›āϰ⧇āϰ āϜāĻ¨ā§āϝ ā§§ā§Ļā§Ļā§Ļ āĻĄāĻŦā§āϞāĻŋāωāφāχāĻ + āĻŽāĻžāϏāĻŋāĻ• ā§§ā§Ļā§Ļ

āφāĻĒāύāĻžāϰ āφāĻ°ā§āĻĨāĻŋāĻ• āϏāĻžāĻĢāĻ˛ā§āϝ āωāĻĻāϝāĻžāĻĒāύ āĻ•āϰāϛ⧇āύ? āύāĻŋāĻœā§‡āϕ⧇ āĻĒ⧁āϰāĻ¸ā§āĻ•ā§ƒāϤ āĻ•āϰāĻžāϰ āϏāĻŽāϝāĻŧ āĻāϏ⧇āϛ⧇!

āĻ¸ā§āĻŽāĻžāĻ°ā§āϟ āφāĻ°ā§āĻĨāĻŋāĻ• āĻĒāϰāĻŋāĻ•āĻ˛ā§āĻĒāύāĻž āĻāĻ•āϟāĻŋ āĻĒ⧁āϰāĻ¸ā§āĻ•āĻžāϰ āĻĒāĻžāĻ“āϝāĻŧāĻžāϰ āϝ⧋āĻ—ā§āϝ - āĻŦāĻŋāĻļā§āĻŦāĻŦā§āϝāĻžāĻĒā§€ āĻ…āϏāĻžāϧāĻžāϰāĻŖ āĻ­ā§āϰāĻŽāĻŖ āĻ…āĻĢāĻžāϰ āφāĻŦāĻŋāĻˇā§āĻ•āĻžāϰ āĻ•āϰ⧁āύ

✨ Smart Nation's Core Infrastructure: WIA Code ✨

āĻĄā§āϰ⧋āύâ€ĸāϰ⧋āĻŦāϟ āĻĄā§‡āϞāĻŋāĻ­āĻžāϰāĻŋ, āĻ¸ā§āĻŦāϝāĻŧāĻ‚āĻ•ā§āϰāĻŋāϝāĻŧ āĻĄā§āϰāĻžāχāĻ­āĻŋāĻ‚, āϜāϰ⧁āϰāĻŋ āωāĻĻā§āϧāĻžāϰ āĻāĻŦāĻ‚ āφāϰāĻ“ āĻ…āύ⧇āĻ• āĻ•āĻŋāϛ⧁ - ā§Šā§Ļ āĻĻāĻŋāύ⧇āϰ āϜāĻ¨ā§āϝ āĻ­āĻŦāĻŋāĻˇā§āϝāϤ⧇āϰ āĻ…āĻ­āĻŋāĻœā§āĻžāϤāĻž āύāĻŋāύ, āφāĻĒāύāĻžāϰ āĻĻ⧇āĻļ⧇āϰ āϜāĻ¨ā§āϝ āϏāĻŽā§āĻĒā§‚āĻ°ā§āĻŖ āĻŦāĻŋāύāĻžāĻŽā§‚āĻ˛ā§āϝ⧇!

āĻĄāĻŦā§āϞāĻŋāωāφāχāĻ āϕ⧋āĻĄ āϏāĻŽā§āĻĒāĻ°ā§āϕ⧇ āφāϰāĻ“ āϜāĻžāύ⧁āύ

🤖 āφāĻĒāύāĻžāϰ āĻāφāχ āϏāĻšāĻ•āĻžāϰ⧀ āĻŦ⧇āϛ⧇ āύāĻŋāύ

đŸ’Ŧ āĻšā§āϝāĻžāϟāϜāĻŋāĻĒāĻŋāϟāĻŋ
āϏāĻ°ā§āĻŦāĻžāϧāĻŋāĻ• āĻŦāĻšā§āĻŽā§āĻ–ā§€ â€ĸ āϏāĻžāϧāĻžāϰāĻŖ āĻ•āĻžāĻœā§‡āϰ āϜāĻ¨ā§āϝ āϏ⧇āϰāĻž
🧠 āĻ•ā§āϞāĻĄ
āϏ⧇āϰāĻž āϝ⧁āĻ•ā§āϤāĻŋ āĻĒā§āϰāĻĻāĻžāύ â€ĸ āĻŦāĻŋāĻļā§āϞ⧇āώāϪ⧇āϰ āϜāĻ¨ā§āϝ āύāĻŋāϖ⧁āρāϤ
✨ āĻœā§‡āĻŽāĻŋāύāĻžāχ āĻŦāĻŋāύāĻžāĻŽā§‚āĻ˛ā§āϝ⧇
āĻĻ⧈āύāĻŋāĻ• āĻŦāĻŋāύāĻžāĻŽā§‚āĻ˛ā§āϝ⧇ āϏ⧀āĻŽāĻž â€ĸ āĻ…āĻ¨ā§āϤāĻ°ā§āύāĻŋāĻ°ā§āĻŽāĻŋāϤ āĻšā§āϝāĻžāϟ
, 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 });