MahekTrivedi commited on
Commit
d8bd64e
Β·
verified Β·
1 Parent(s): 0fa6c21

Initial Gradio app deployment

Browse files
Files changed (2) hide show
  1. app.py +568 -0
  2. requirements.txt.txt +3 -0
app.py ADDED
@@ -0,0 +1,568 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ """Cute EMI Calculator (Gradio)
3
+
4
+ Automatically generated by Colab.
5
+
6
+ Original file is located at
7
+ https://colab.research.google.com/drive/1KqksMVkMVBWDpSyVGdvuakXi4C8b4fB-
8
+ """
9
+
10
+ import gradio as gr
11
+ import pandas as pd
12
+ import matplotlib.pyplot as plt
13
+ import io
14
+ import base64
15
+
16
+ # Define a dictionary of common currencies and their symbols
17
+ currency_symbols = {
18
+ "United States Dollar ($)": "$",
19
+ "Euro (€)": "€",
20
+ "British Pound (Β£)": "Β£",
21
+ "Japanese Yen (Β₯)": "Β₯",
22
+ "Indian Rupee (β‚Ή)": "β‚Ή",
23
+ "Canadian Dollar (C$)": "C$",
24
+ "Australian Dollar (A$)": "A$",
25
+ "Swiss Franc (CHF)": "CHF",
26
+ "Chinese Yuan (Β₯)": "Β₯", # Note: Yuan uses same symbol as Yen
27
+ "Singapore Dollar (S$)": "S$",
28
+ "Hong Kong Dollar (HK$)": "HK$",
29
+ "New Zealand Dollar (NZ$)": "NZ$",
30
+ "South Korean Won (β‚©)": "β‚©",
31
+ "Swedish Krona (kr)": "kr",
32
+ "Norwegian Krone (kr)": "kr",
33
+ "Danish Krone (kr)": "kr",
34
+ "Mexican Peso (Mex$)": "Mex$",
35
+ "Brazilian Real (R$)": "R$",
36
+ "Russian Ruble (β‚½)": "β‚½",
37
+ "South African Rand (R)": "R",
38
+ "United Arab Emirates Dirham (Ψ―.Ψ₯)": "Ψ―.Ψ₯",
39
+ "Saudi Riyal (ο·Ό)": "ο·Ό",
40
+ "Turkish Lira (β‚Ί)": "β‚Ί",
41
+ "Argentine Peso ($)": "$", # Note: Some pesos use $
42
+ "Egyptian Pound (EΒ£)": "EΒ£",
43
+ "Philippine Peso (β‚±)": "β‚±",
44
+ "Thai Baht (ΰΈΏ)": "ΰΈΏ",
45
+ "Malaysian Ringgit (RM)": "RM",
46
+ "Indonesian Rupiah (Rp)": "Rp",
47
+ "Vietnamese Dong (β‚«)": "β‚«",
48
+ "Pakistani Rupee (₨)": "₨",
49
+ "Bangladeshi Taka (ΰ§³)": "ΰ§³",
50
+ "Sri Lankan Rupee (Rs)": "Rs",
51
+ "Nigerian Naira (₦)": "₦",
52
+ "Kenyan Shilling (KSh)": "KSh",
53
+ "Ghanaian Cedi (β‚΅)": "β‚΅",
54
+ "Chilean Peso (CLP$)": "CLP$",
55
+ "Colombian Peso (COL$)": "COL$",
56
+ "Peruvian Sol (S/.)": "S/.",
57
+ "Czech Koruna (Kč)": "Kč",
58
+ "Polish ZΕ‚oty (zΕ‚)": "zΕ‚",
59
+ "Hungarian Forint (Ft)": "Ft",
60
+ "Romanian Leu (lei)": "lei",
61
+ }
62
+
63
+ # --- IMPORTANT: Placeholder for real-time exchange rates ---
64
+ # In a real application, you would fetch these from a reliable API.
65
+ # These are sample rates relative to USD as the base currency.
66
+ # 1 USD = X of the listed currency.
67
+ exchange_rates = {
68
+ "United States Dollar ($)": 1.0,
69
+ "Euro (€)": 0.85,
70
+ "British Pound (Β£)": 0.73,
71
+ "Japanese Yen (Β₯)": 144.51,
72
+ "Indian Rupee (β‚Ή)": 85.50,
73
+ "Canadian Dollar (C$)": 1.36,
74
+ "Australian Dollar (A$)": 1.53,
75
+ "Swiss Franc (CHF)": 0.79,
76
+ "Chinese Yuan (Β₯)": 7.17,
77
+ "Singapore Dollar (S$)": 1.27,
78
+ "Hong Kong Dollar (HK$)": 7.85,
79
+ "New Zealand Dollar (NZ$)": 1.65,
80
+ "South Korean Won (β‚©)": 1362.33,
81
+ "Swedish Krona (kr)": 9.56,
82
+ "Norwegian Krone (kr)": 10.09,
83
+ "Danish Krone (kr)": 6.33,
84
+ "Mexican Peso (Mex$)": 18.63,
85
+ "Brazilian Real (R$)": 5.42,
86
+ "Russian Ruble (β‚½)": 78.61,
87
+ "South African Rand (R)": 17.61,
88
+ "United Arab Emirates Dirham (Ψ―.Ψ₯)": 3.67,
89
+ "Saudi Riyal (ο·Ό)": 3.75,
90
+ "Turkish Lira (β‚Ί)": 39.87,
91
+ "Argentine Peso ($)": 900.00,
92
+ "Egyptian Pound (EΒ£)": 49.26,
93
+ "Philippine Peso (β‚±)": 56.51,
94
+ "Thai Baht (ΰΈΏ)": 32.39,
95
+ "Malaysian Ringgit (RM)": 4.22,
96
+ "Indonesian Rupiah (Rp)": 16129.03,
97
+ "Vietnamese Dong (β‚«)": 26180.00,
98
+ "Pakistani Rupee (₨)": 283.78,
99
+ "Bangladeshi Taka (ΰ§³)": 121.95,
100
+ "Sri Lankan Rupee (Rs)": 299.94,
101
+ "Nigerian Naira (₦)": 1529.68,
102
+ "Kenyan Shilling (KSh)": 129.15,
103
+ "Ghanaian Cedi (β‚΅)": 10.35,
104
+ "Chilean Peso (CLP$)": 929.99,
105
+ "Colombian Peso (COL$)": 4100.00,
106
+ "Peruvian Sol (S/.)": 3.54,
107
+ "Czech Koruna (Kč)": 20.92,
108
+ "Polish ZΕ‚oty (zΕ‚)": 3.60,
109
+ "Hungarian Forint (Ft)": 338.90,
110
+ "Romanian Leu (lei)": 4.29,
111
+ }
112
+
113
+ BASE_CURRENCY = "United States Dollar ($)"
114
+
115
+ def convert_currency(amount, from_currency_display, to_currency_display):
116
+ """
117
+ Converts an amount from one currency to another using predefined exchange rates.
118
+ """
119
+ if from_currency_display == to_currency_display:
120
+ return amount
121
+
122
+ from_rate = exchange_rates.get(from_currency_display)
123
+ to_rate = exchange_rates.get(to_currency_display)
124
+
125
+ if from_rate is None or to_rate is None:
126
+ raise ValueError(f"Exchange rate not found for {from_currency_display} or {to_currency_display}")
127
+
128
+ amount_in_base = amount / from_rate
129
+ converted_amount = amount_in_base * to_rate
130
+ return converted_amount
131
+
132
+ def calculate_emi(principal, annual_interest_rate, tenure_years, input_currency_display, output_currency_display):
133
+ if principal <= 0 or annual_interest_rate < 0 or tenure_years <= 0:
134
+ # Return gr.update(visible=False) for all outputs in case of an error
135
+ return (
136
+ gr.update(value="Please enter valid positive numbers! πŸ˜…", visible=True),
137
+ gr.update(value="", visible=False),
138
+ gr.update(value="", visible=False),
139
+ gr.update(value=pd.DataFrame(), visible=False),
140
+ gr.update(value=None, visible=False),
141
+ gr.update(visible=False), # Explanation separator
142
+ gr.update(visible=False), # Explanation accordion
143
+ gr.update(visible=False) # Footer markdown
144
+ )
145
+
146
+ monthly_interest_rate = annual_interest_rate / (12 * 100)
147
+ tenure_months = tenure_years * 12
148
+
149
+ if monthly_interest_rate == 0:
150
+ emi = principal / tenure_months
151
+ else:
152
+ emi = principal * monthly_interest_rate * ((1 + monthly_interest_rate) ** tenure_months) / \
153
+ (((1 + monthly_interest_rate) ** tenure_months) - 1)
154
+
155
+ total_payment = emi * tenure_months
156
+ total_interest = total_payment - principal
157
+
158
+ # Convert currency
159
+ try:
160
+ emi_converted = convert_currency(emi, input_currency_display, output_currency_display)
161
+ total_payable_converted = convert_currency(total_payment, input_currency_display, output_currency_display)
162
+ total_interest_converted = convert_currency(total_interest, input_currency_display, output_currency_display)
163
+ except ValueError as e:
164
+ return (
165
+ gr.update(value=f"Currency conversion error: {e}", visible=True),
166
+ gr.update(value="", visible=False),
167
+ gr.update(value="", visible=False),
168
+ gr.update(value=pd.DataFrame(), visible=False),
169
+ gr.update(value=None, visible=False),
170
+ gr.update(visible=False), # Explanation separator
171
+ gr.update(visible=False), # Explanation accordion
172
+ gr.update(visible=False) # Footer markdown
173
+ )
174
+
175
+ output_symbol = currency_symbols.get(output_currency_display, "$")
176
+
177
+ # --- Generate Amortization Table ---
178
+ balance = principal
179
+ schedule = []
180
+ for month in range(1, tenure_months + 1):
181
+ interest_payment = balance * monthly_interest_rate
182
+ principal_payment = emi - interest_payment
183
+ ending_balance = balance - principal_payment
184
+
185
+ # Convert each amount
186
+ bal = convert_currency(balance, input_currency_display, output_currency_display)
187
+ prin = convert_currency(principal_payment, input_currency_display, output_currency_display)
188
+ intr = convert_currency(interest_payment, input_currency_display, output_currency_display)
189
+ end_bal = convert_currency(ending_balance, input_currency_display, output_currency_display)
190
+
191
+ schedule.append([
192
+ month,
193
+ f"{output_symbol} {bal:,.2f}",
194
+ f"{output_symbol} {emi_converted:,.2f}",
195
+ f"{output_symbol} {prin:,.2f}",
196
+ f"{output_symbol} {intr:,.2f}",
197
+ f"{output_symbol} {end_bal:,.2f}"
198
+ ])
199
+ balance = ending_balance
200
+
201
+ df = pd.DataFrame(schedule, columns=[
202
+ "Month", "Beginning Balance", "EMI", "Principal Paid", "Interest Paid", "Outstanding Balance"
203
+ ])
204
+
205
+ # --- Plot Chart ---
206
+ chart_df = pd.DataFrame({
207
+ "Month": range(1, tenure_months + 1),
208
+ "Principal": [float(r[3].replace(output_symbol, "").replace(",", "").strip()) for r in schedule],
209
+ "Interest": [float(r[4].replace(output_symbol, "").replace(",", "").strip()) for r in schedule],
210
+ })
211
+ chart_df["EMI"] = emi_converted
212
+
213
+ fig, ax = plt.subplots(figsize=(10, 4))
214
+ ax.plot(chart_df["Month"], chart_df["Principal"], label="Principal Paid", color="#6a5acd")
215
+ ax.plot(chart_df["Month"], chart_df["Interest"], label="Interest Paid", color="#db7093")
216
+ ax.plot(chart_df["Month"], chart_df["EMI"], label="Monthly EMI", color="orange", linestyle='--')
217
+
218
+ ax.set_xlabel("Month")
219
+ ax.set_ylabel(f"Amount ({output_symbol})")
220
+ ax.set_title("EMI Breakdown Over Time")
221
+ ax.legend()
222
+ plt.tight_layout()
223
+
224
+ # Return gr.update for each output to control visibility
225
+ return (
226
+ gr.update(value=f"πŸ’– Your Monthly EMI: {output_symbol} {emi_converted:,.2f}", visible=True),
227
+ gr.update(value=f"πŸ’° Total Interest Payable: {output_symbol} {total_interest_converted:,.2f}", visible=True),
228
+ gr.update(value=f"✨ Total Amount Payable: {output_symbol} {total_payable_converted:,.2f}", visible=True),
229
+ gr.update(value=df, visible=True),
230
+ gr.update(value=fig, visible=True),
231
+ gr.update(visible=True), # Explanation separator
232
+ gr.update(visible=True), # Explanation accordion
233
+ gr.update(visible=True) # Footer markdown
234
+ )
235
+
236
+
237
+ # --- NEW: Function to provide explanations ---
238
+ def explain_calculation(choice):
239
+ """
240
+ Returns a markdown-formatted explanation based on the user's choice.
241
+ """
242
+ explanations = {
243
+ "How is the Monthly EMI calculated?": """
244
+ ### Monthly EMI (Equated Monthly Installment)
245
+ The EMI is the fixed amount you pay each month. It's calculated using this formula:
246
+ `EMI = P * r * (1+r)^n / ((1+r)^n - 1)`
247
+ Where:
248
+ - **P** is the Principal Loan Amount.
249
+ - **r** is the monthly interest rate (your annual rate divided by 12 and then by 100).
250
+ - **n** is the loan tenure in months (your term in years multiplied by 12).
251
+ """,
252
+ "How is the Total Interest calculated?": """
253
+ ### Total Interest Payable
254
+ This is the total cost of borrowing the money. It's the difference between the total amount you pay back and the original loan amount.
255
+ `Total Interest = (EMI * n) - P`
256
+ Where:
257
+ - **EMI** is the monthly payment we calculated.
258
+ - **n** is the loan tenure in months.
259
+ - **P** is the original Principal Loan Amount.
260
+ """,
261
+ "How does currency conversion work?": """
262
+ ### Currency Conversion
263
+ The calculation is first performed in your **Input Currency**. Then, the final results (EMI, Total Interest, and Total Payable) are converted to your chosen **Output Currency**.
264
+ 1. **Convert to Base Currency (USD):** We take the calculated amount in the input currency and convert it to our base currency (US Dollars) using our stored exchange rates.
265
+ `Amount in USD = Amount in Input Currency / Rate of Input Currency`
266
+ 2. **Convert to Output Currency:** We then take the USD amount and convert it to your desired output currency.
267
+ `Final Amount = Amount in USD * Rate of Output Currency`
268
+ **Note:** The exchange rates used here are static placeholders from July 5, 2025, and are not real-time.
269
+ """
270
+ }
271
+ return explanations.get(choice, "Please select a question to see the explanation! 😊")
272
+
273
+
274
+ # Custom CSS remains the same
275
+ custom_css = """
276
+ /* Import Google Fonts */
277
+ @import url('https://fonts.googleapis.com/css2?family=Emilys+Candy&family=Special+Elite&display=swap');
278
+
279
+ /* Define Lavender/Lilac Color Palette */
280
+ :root {
281
+ --lavender-light: #E6E6FA; /* Very light lavender for background */
282
+ --lilac-medium: #C8A2C8; /* A nice medium lilac for accents */
283
+ --lavender-dark: #9370DB; /* Darker lavender for highlights/buttons */
284
+ --text-color-dark: #4B0082; /* Indigo for darker text */
285
+ --text-color-light: #8A2BE2; /* Blue violet for lighter text */
286
+ --button-hover-color: #AF8EE2; /* Lighter purple for button hover */
287
+ --border-color: #DDA0DD; /* Plum for borders */
288
+ --header-bg: #D8BFD8; /* Thistle for header background */
289
+ --header-border: #BA55D3; /* MediumOrchid for header border */
290
+ }
291
+
292
+ /* Apply Emily's Candy to headings */
293
+ h1, h2, h3, h4, h5, h6 {
294
+ font-family: 'Special Elite', cursive !important;
295
+ color: var(--text-color-dark) !important; /* Apply dark text color to headings */
296
+ }
297
+
298
+ /* Apply Special Elite to the rest of the text */
299
+ body, p, div, span, label, input, textarea, select, button {
300
+ font-family: 'Special Elite', cursive !important;
301
+ color: var(--text-color-dark) !important; /* Apply dark text color to general text */
302
+ }
303
+
304
+ /* Overall container background and borders */
305
+ .gradio-container {
306
+ background-color: var(--lavender-light) !important; /* Light lavender background */
307
+ border: 2px solid var(--border-color) !important;
308
+ border-radius: 15px !important;
309
+ box-shadow: 5px 5px 15px rgba(0, 0, 0, 0.2) !important;
310
+ }
311
+
312
+ /* Input fields (sliders, dropdowns, text) */
313
+ .gradio-input {
314
+ background-color: white !important;
315
+ border: 1px solid var(--lilac-medium) !important;
316
+ border-radius: 8px !important;
317
+ color: var(--text-color-dark) !important;
318
+ }
319
+
320
+ /* Labels for inputs */
321
+ .gradio-label {
322
+ color: var(--text-color-light) !important; /* Lighter text color for labels */
323
+ font-weight: bold !important;
324
+ }
325
+
326
+ /* Buttons */
327
+ .gradio-button {
328
+ background-color: var(--lilac-medium) !important; /* Lilac for buttons */
329
+ color: white !important;
330
+ border: none !important;
331
+ border-radius: 10px !important;
332
+ padding: 10px 20px !important;
333
+ font-size: 1.1em !important;
334
+ cursor: pointer !important;
335
+ transition: background-color 0.3s ease !important;
336
+ }
337
+
338
+ .gradio-button:hover {
339
+ background-color: var(--button-hover-color) !important; /* Lighter purple on hover */
340
+ }
341
+
342
+ /* Markdown components (for results and footer) */
343
+ .gradio-markdown {
344
+ background-color: var(--lavender-light) !important; /* Match container background */
345
+ color: var(--text-color-dark) !important;
346
+ border-radius: 10px !important;
347
+ padding: 10px !important;
348
+ margin-top: 10px !important;
349
+ }
350
+
351
+ /* Specific styling for the main heading within markdown */
352
+ .gradio-markdown h1 {
353
+ color: var(--lavender-dark) !important; /* Darker lavender for the main title */
354
+ text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.1); /* Subtle shadow for headings */
355
+ }
356
+
357
+ /* Ensure the output markdown text also uses Special Elite and appropriate color */
358
+ .gradio-markdown p,
359
+ .gradio-markdown div {
360
+ font-family: 'Special Elite', cursive !important;
361
+ color: var(--text-color-dark) !important;
362
+ }
363
+
364
+ /* Style for the horizontal rule */
365
+ hr {
366
+ border-top: 2px dashed var(--lilac-medium) !important; /* Dashed lilac line */
367
+ margin: 20px 0 !important;
368
+ }
369
+
370
+ /* Style for the footer text for consistency */
371
+ .gradio-container div[style*="text-align: center;"] b {
372
+ color: var(--text-color-dark) !important;
373
+ font-family: 'Special Elite', cursive !important;
374
+ }
375
+
376
+ /* NEW: Styling for the header group (formerly header box) */
377
+
378
+ .gradio-container {
379
+ border: none !important;
380
+ background-color: var(--lavender-light) !important;
381
+ box-shadow: none !important;
382
+ }
383
+
384
+ /* Wipe out Gradio's default internal section border (usually applies to first few blocks) */
385
+ .gradio-container .gr-block:first-child {
386
+ background: transparent !important;
387
+ border: none !important;
388
+ box-shadow: none !important;
389
+ padding: 0 !important;
390
+ margin: 0 !important;
391
+ }
392
+
393
+ .heading-group h1 {
394
+ color: white !important; /* White color for the heading inside the group */
395
+ text-shadow: 2px 2px 5px rgba(0, 0, 0, 0.3) !important;
396
+ }
397
+ .heading-group p {
398
+ color: var(--text-color-dark) !important; /* Dark text for the paragraph in the group */
399
+ font-size: 1.1em !important;
400
+ }
401
+ #heading-button-style {
402
+ width: 100%;
403
+ background-color: var(--lavender-dark);
404
+ color: white !important;
405
+ font-family: 'Special Elite', cursive !important;
406
+ font-size: 2em;
407
+ font-weight: bold;
408
+ text-align: center;
409
+ padding: 20px;
410
+ border-radius: 12px;
411
+ box-shadow: 4px 4px 15px rgba(0, 0, 0, 0.15);
412
+ margin-bottom: 20px;
413
+ transition: background-color 0.3s ease;
414
+ }
415
+
416
+ #heading-button-style:hover {
417
+ background-color: var(--button-hover-color);
418
+ cursor: default;
419
+ }
420
+
421
+ .gradio-container {
422
+ border: none !important;
423
+ background-color: var(--lavender-light) !important;
424
+ box-shadow: none !important;
425
+ }
426
+
427
+ .gradio-container .gr-block:first-child {
428
+ background: transparent !important;
429
+ border: none !important;
430
+ box-shadow: none !important;
431
+ padding: 0 !important;
432
+ margin: 0 !important;
433
+ }
434
+
435
+ #cute_emi_button {
436
+ color: white !important;
437
+ background-color: var(--lavender-dark) !important;
438
+ }
439
+
440
+ """
441
+
442
+ # Create Gradio Interface
443
+ with gr.Blocks(theme=gr.themes.Soft(), title="Cute EMI Calculator", css=custom_css) as demo:
444
+ gr.HTML(
445
+ """
446
+ <div id="heading-button-style">
447
+ Ctrl+Loan EMI Calculator!
448
+ </div>
449
+ """
450
+ )
451
+
452
+ with gr.Row():
453
+ principal_input = gr.Slider(
454
+ minimum=100,
455
+ maximum=10000000,
456
+ step=100,
457
+ value=500000,
458
+ label="🏠 Loan Amount (Principal)",
459
+ info="How much are you borrowing?"
460
+ )
461
+ input_currency_dropdown = gr.Dropdown(
462
+ choices=list(currency_symbols.keys()),
463
+ value="United States Dollar ($)",
464
+ label="Input Currency πŸ’²",
465
+ info="The currency of your loan amount."
466
+ )
467
+
468
+ with gr.Row():
469
+ interest_input = gr.Slider(
470
+ minimum=0.1,
471
+ maximum=20.0,
472
+ step=0.1,
473
+ value=8.5,
474
+ label="πŸ“ˆ Annual Interest Rate (%)",
475
+ info="What's the yearly interest rate?"
476
+ )
477
+ tenure_input = gr.Slider(
478
+ minimum=1,
479
+ maximum=30,
480
+ step=1,
481
+ value=10,
482
+ label="⏳ Loan Tenure (Years)",
483
+ info="How many years to repay the loan?"
484
+ )
485
+
486
+ with gr.Row():
487
+ output_currency_dropdown = gr.Dropdown(
488
+ choices=list(currency_symbols.keys()),
489
+ value="Indian Rupee (β‚Ή)",
490
+ label="Display Results In πŸ’Έ",
491
+ info="Choose the currency for the results."
492
+ )
493
+
494
+ calculate_button = gr.Button("Calculate My EMI!", variant="primary", elem_id="cute_emi_button")
495
+
496
+ # The horizontal rule
497
+ explanation_separator = gr.Markdown("---", visible=False)
498
+
499
+ # Set initial visibility to False for all output components
500
+ emi_output = gr.Markdown("πŸ’– Your Monthly EMI:", visible=False)
501
+ interest_output = gr.Markdown("πŸ’° Total Interest Payable:", visible=False)
502
+ total_output = gr.Markdown("✨ Total Amount Payable:", visible=False)
503
+
504
+ amortization_table = gr.Dataframe(
505
+ label="Amortization Schedule",
506
+ headers=["Month", "Beginning Balance", "EMI", "Principal Paid", "Interest Paid", "Outstanding Balance"],
507
+ wrap=True,
508
+ interactive=False,
509
+ visible=False # Set initial visibility to False
510
+ )
511
+ emi_chart = gr.Plot(label="EMI Breakdown Chart", visible=False) # Set initial visibility to False
512
+
513
+ # --- NEW: "Chatbot" section using an Accordion ---
514
+ with gr.Accordion("πŸ€” How was this calculated? (Click to expand!)", open=False, visible=False) as explanation_accordion:
515
+ explanation_choice = gr.Radio(
516
+ choices=[
517
+ "How is the Monthly EMI calculated?",
518
+ "How is the Total Interest calculated?",
519
+ "How does currency conversion work?"
520
+ ],
521
+ label="Choose a question to learn more!",
522
+ # value="How is the Monthly EMI calculated?" # Default selection
523
+ )
524
+ explanation_output = gr.Markdown()
525
+ explanation_choice.change(
526
+ fn=explain_calculation,
527
+ inputs=explanation_choice,
528
+ outputs=explanation_output
529
+ )
530
+
531
+ # Footer markdown
532
+ footer_markdown = gr.Markdown(
533
+ """
534
+ <div style="text-align: center;">
535
+ <br>
536
+ <b>Calculations are approximate and for illustrative purposes only. Exchange rates are static placeholders and may not reflect real-time values. Always consult with your financial advisor!</b>
537
+ <br>
538
+ <b>Rates are as per 05.07.2025</b>
539
+ </div>
540
+ """,
541
+ visible=False # Set initial visibility to False
542
+ )
543
+
544
+
545
+ calculate_button.click(
546
+ fn=calculate_emi,
547
+ inputs=[
548
+ principal_input,
549
+ interest_input,
550
+ tenure_input,
551
+ input_currency_dropdown,
552
+ output_currency_dropdown
553
+ ],
554
+ outputs=[
555
+ emi_output,
556
+ interest_output,
557
+ total_output,
558
+ amortization_table,
559
+ emi_chart,
560
+ explanation_separator, # Add separator to outputs
561
+ explanation_accordion, # Add accordion to outputs
562
+ footer_markdown # Add footer markdown to outputs
563
+ ]
564
+ )
565
+
566
+ # Launch the Gradio app
567
+ if __name__ == "__main__":
568
+ demo.launch(share=True)
requirements.txt.txt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ gradio
2
+ pandas
3
+ matplotlib