import gradio as gr
import numpy as np
import plotly.graph_objects as go
def calculate_chemeng_tvm(capex, revenue, opex_fixed, opex_var, plant_life, marr_pct, salvage_pct, inflation_pct):
capex = float(capex)
revenue = float(revenue)
opex_fixed = float(opex_fixed)
opex_var = float(opex_var)
plant_life = int(plant_life)
marr = float(marr_pct) / 100
salvage = float(salvage_pct) / 100
inflation = float(inflation_pct) / 100
# Generate cash flows
cashflows = [-capex]
for year in range(1, plant_life + 1):
opex_total = (opex_fixed + opex_var) * (1 + inflation) ** year
rev = revenue * (1 + inflation) ** year
net_cf = rev - opex_total
cashflows.append(net_cf)
cashflows[-1] += capex * salvage
# NPV Calculation
npv_val = sum(cf / (1 + marr)**i for i, cf in enumerate(cashflows))
# IRR Approximation (Newton-Raphson)
irr_guess = 0.1
for _ in range(50):
npv_est = sum(cf / (1 + irr_guess)**i for i, cf in enumerate(cashflows))
deriv = sum(-i * cf / (1 + irr_guess)**(i+1) for i, cf in enumerate(cashflows))
if abs(deriv) < 1e-10: break
irr_guess -= npv_est / deriv
irr_val = max(0, irr_guess * 100)
# Payback Period
cum_cf = [0]
for cf in cashflows[1:]:
cum_cf.append(cum_cf[-1] + cf)
payback = next((i for i, total in enumerate(cum_cf) if total >= 0), plant_life)
# Results HTML
results_html = f"""
๐งช Chemical Engineering Economics
| Metric |
Value |
| ๐ NPV |
0 else 'red'};'>${npv_val:,.0f} |
| โก IRR |
{irr_val:.1f}% |
| โฑ๏ธ Payback |
{payback:.1f} years |
| ๐ Profitability Index |
{abs(npv_val/capex)*100:.1f}% |
0 else '#f8d7da'}; padding: 15px; border-radius: 8px; border-left: 5px solid {'#28a745' if npv_val > 0 else '#dc3545'};'>
Status: {'โ
PROJECT VIABLE (NPV > 0)' if npv_val > 0 else 'โ ๏ธ REVIEW REQUIRED'}
"""
# Cash Flow Chart
years = list(range(len(cashflows)))
fig = go.Figure()
fig.add_trace(go.Bar(x=years[1:], y=cashflows[1:],
name="Annual Cash Flow", marker_color='#1f77b4'))
fig.add_trace(go.Scatter(x=years, y=cum_cf,
mode='lines+markers', name="Cumulative CF",
line=dict(color='#ff4444', width=4)))
fig.add_hline(y=0, line_dash="dash", line_color="gray", annotation_text="Breakeven")
fig.update_layout(
title="๐ธ Chemical Plant Cash Flow Analysis",
xaxis_title="Year", yaxis_title="Cash Flow ($)",
height=400, showlegend=True,
font=dict(size=12)
)
return results_html, fig.to_html(full_html=False, div_id="cashflow-chart")
# Gradio Interface
with gr.Blocks(title="ChemEng TVM Calculator") as demo:
gr.Markdown("# ๐งช Chemical Engineering TVM Calculator")
gr.Markdown("**CAPEX โข OPEX โข NPV โข IRR โข Plant Investment Analysis**")
with gr.Row():
with gr.Column(scale=1):
gr.Markdown("### ๐ Chemical Plant Inputs")
gr.Markdown("**๐ฐ Investment & Revenue**")
with gr.Row():
capex_input = gr.Number(value=10000000, label="CAPEX ($)", precision=0)
revenue_input = gr.Number(value=5000000, label="Revenue/Year ($)", precision=0)
gr.Markdown("**๐ญ Operating Costs**")
with gr.Row():
opex_fixed_input = gr.Number(value=1500000, label="Fixed OPEX ($)", precision=0)
opex_var_input = gr.Number(value=2000000, label="Variable OPEX ($)", precision=0)
gr.Markdown("**๐
Economic Parameters**")
with gr.Row():
plant_life_input = gr.Slider(5, 30, value=15, step=1, label="Plant Life (years)")
marr_input = gr.Slider(8, 20, value=12, step=1, label="MARR (%)")
with gr.Row():
salvage_input = gr.Slider(0, 20, value=10, step=1, label="Salvage Value (%)")
inflation_input = gr.Slider(1, 8, value=3, step=0.5, label="Inflation (%)")
calculate_btn = gr.Button("๐ฌ RUN ECONOMIC ANALYSIS", variant="primary", size="lg")
with gr.Column(scale=2):
results_output = gr.HTML()
chart_output = gr.HTML()
# Connect button to function
calculate_btn.click(
calculate_chemeng_tvm,
inputs=[capex_input, revenue_input, opex_fixed_input, opex_var_input,
plant_life_input, marr_input, salvage_input, inflation_input],
outputs=[results_output, chart_output]
)
gr.Markdown("---")
gr.Markdown("*Professional tool for Chemical Engineers | Powered by Gradio*")
# Launch (Hugging Face auto-runs this)
demo.launch()