import gradio as gr import pandas as pd import main as backend import os def process_data(project_years, base_capacity, inflation, tax, depr_years, tech_data_df, strategy_data_df, product_prices_df, opt_space_df, run_button_click): if not run_button_click: return None, None, None, "لطفاً برای شروع تحلیل، دکمه 'اجرا' را فشار دهید." backend.PROJECT_YEARS = int(project_years) backend.BASE_CAPACITY_KTA = int(base_capacity) backend.INFLATION_RATE = float(inflation) backend.TAX_RATE = float(tax) backend.DEPRECIATION_YEARS = int(depr_years) tech_data_df.rename(columns={ 'CAPEX (M$)': 'capex_base_M', 'OPEX (cents/kg)': 'opex_base_cents_kg' }, inplace=True) backend.TECHNOLOGY_DATA = tech_data_df.set_index('Technology').to_dict('index') strategy_dict = {} for index, row in strategy_data_df.iterrows(): strategy_dict[row['Strategy']] = { 'sourcing_cost_per_ton_pvc': row['Sourcing Cost per Ton PVC'], 'byproducts': { 'caustic_soda_ton': row['Byproduct Caustic Soda (ton)'], 'surplus_edc_ton': row['Byproduct Surplus EDC (ton)'] } } backend.STRATEGY_DATA = strategy_dict backend.PRODUCT_PRICES_USD_PER_TON = product_prices_df.set_index('Product')['Price (USD/ton)'].to_dict() opt_space = {} for _, row in opt_space_df.iterrows(): param = row['Parameter'] value_type = row['Type'] values = str(row['Values']).split(',') if value_type == 'range': opt_space[param] = (float(values[0]), float(values[1])) elif value_type == 'list': opt_space[param] = [v.strip() for v in values] elif value_type == 'boolean': opt_space[param] = [v.strip().lower() in ('true', '1', 't') for v in values] backend.OPTIMIZATION_SPACE = opt_space try: for f in ["results.csv", "kpi_dashboard.png", "sensitivity_analysis_tornado.png"]: if os.path.exists(f): os.remove(f) optimization_results_list = backend.run_optimizations_without_ml() df_results = pd.DataFrame(optimization_results_list).sort_values(by="irr", ascending=False).reset_index(drop=True) backend.display_and_save_results(df_results) backend.create_kpi_comparison_dashboard(df_results) if not df_results.empty: best_scenario = df_results.iloc[0] backend.run_sensitivity_analysis(best_scenario['Params'], best_scenario['irr']) results_df = pd.read_csv("results.csv") if os.path.exists("results.csv") else pd.DataFrame() kpi_dashboard_img = "kpi_dashboard.png" if os.path.exists("kpi_dashboard.png") else None sensitivity_tornado_img = "sensitivity_analysis_tornado.png" if os.path.exists("sensitivity_analysis_tornado.png") else None return results_df, kpi_dashboard_img, sensitivity_tornado_img, "✅ تحلیل بهینه‌سازی با موفقیت انجام شد!" except Exception as e: import traceback print(traceback.format_exc()) return None, None, None, f"❌ خطا در اجرای تحلیل: {str(e)}" def load_from_excel(file): try: xls = pd.ExcelFile(file.name) assumptions = pd.read_excel(xls, 'Global_Assumptions').set_index('Parameter')['Value'] tech_data = pd.read_excel(xls, 'Technology_Data') strategy_data = pd.read_excel(xls, 'Sourcing_Strategy') prices = pd.read_excel(xls, 'Product_Prices') opt_space = pd.read_excel(xls, 'Optimization_Space') return (assumptions['PROJECT_YEARS'], assumptions['BASE_CAPACITY_KTA'], assumptions['INFLATION_RATE'], assumptions['TAX_RATE'], assumptions['DEPRECIATION_YEARS'], tech_data, strategy_data, prices, opt_space, "فایل با موفقیت بارگذاری شد.") except Exception as e: return 0, 0, 0, 0, 0, pd.DataFrame(), pd.DataFrame(), pd.DataFrame(), pd.DataFrame(), f"خطا در بارگذاری فایل: {e}" css = """ body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; } .gradio-container { max-width: 1280px !important; margin: auto !important; } .gr-button { background-color: #0056b3; color: white; border-radius: 8px; font-weight: bold; } .gr-button:hover { background-color: #004494; } footer { display: none !important; } """ def create_template_excel(): template_path = "data_template.xlsx" if not os.path.exists(template_path): with pd.ExcelWriter(template_path, engine='openpyxl') as writer: pd.DataFrame([ {'Parameter': 'PROJECT_YEARS', 'Value': 15}, {'Parameter': 'BASE_CAPACITY_KTA', 'Value': 300}, {'Parameter': 'INFLATION_RATE', 'Value': 0.015}, {'Parameter': 'TAX_RATE', 'Value': 0.10}, {'Parameter': 'DEPRECIATION_YEARS', 'Value': 15} ]).to_excel(writer, sheet_name='Global_Assumptions', index=False) pd.DataFrame(backend.TECHNOLOGY_DATA).T.reset_index().rename(columns={'index':'Technology', 'capex_base_M':'CAPEX (M$)', 'opex_base_cents_kg':'OPEX (cents/kg)'}).to_excel(writer, sheet_name='Technology_Data', index=False) pd.DataFrame({ 'Strategy': ['Integrated_Production', 'Purchase_VCM'], 'Sourcing Cost per Ton PVC': [450.0, 650.0], 'Byproduct Caustic Soda (ton)': [1.1, 0], 'Byproduct Surplus EDC (ton)': [0.523, 0] }).to_excel(writer, sheet_name='Sourcing_Strategy', index=False) pd.DataFrame(list(backend.PRODUCT_PRICES_USD_PER_TON.items()), columns=['Product', 'Price (USD/ton)']).to_excel(writer, sheet_name='Product_Prices', index=False) pd.DataFrame([ {'Parameter': 'capacity_kta', 'Type': 'range', 'Values': '500,600'}, {'Parameter': 'technology', 'Type': 'list', 'Values': 'Engro_Pakistan,Shin_Etsu_2004'}, {'Parameter': 'sourcing_strategy', 'Type': 'list', 'Values': 'Integrated_Production'}, {'Parameter': 'export_market_mix', 'Type': 'range', 'Values': '0.6,0.8'}, {'Parameter': 'sell_byproducts', 'Type': 'boolean', 'Values': 'True'} ]).to_excel(writer, sheet_name='Optimization_Space', index=False) return template_path template_file_path = create_template_excel() with gr.Blocks(theme=gr.themes.Soft(), css=css, title="داشبورد بهینه‌سازی پروژه") as demo: with gr.Row(elem_id="header"): logo_path = "logo.png" if os.path.exists(logo_path): gr.Image(logo_path, width=150, show_label=False, show_download_button=False, container=False) else: gr.Markdown("**(محل قرارگیری لوگو)**") gr.Markdown("# داشبورد تحلیل و بهینه‌سازی پروژه مالی", elem_id="app-title") gr.Markdown("---") with gr.Row(): with gr.Column(scale=1): gr.Markdown("## ۱. ورودی‌ها و تنظیمات مدل") with gr.Accordion("بارگذاری داده‌ها از فایل", open=False): gr.Markdown("می‌توانید تمام پارامترها را با آپلود یک فایل اکسل (`.xlsx`) بارگذاری کنید. لطفاً از فرمت فایل نمونه استفاده کنید.") upload_button = gr.UploadButton("آپلود فایل اکسل", file_types=[".xlsx"], file_count="single") gr.File(value=template_file_path, label="دانلود فایل نمونه (Template)") upload_status = gr.Textbox(label="وضعیت بارگذاری", interactive=False) with gr.Tabs() as tabs: with gr.TabItem("الف) مفروضات اصلی پروژه", id=0): project_years = gr.Slider(5, 30, value=backend.PROJECT_YEARS, step=1, label="سال‌های پروژه (Project Years)") base_capacity = gr.Number(value=backend.BASE_CAPACITY_KTA, label="ظرفیت پایه (KTA)") inflation_rate = gr.Slider(0, 0.1, value=backend.INFLATION_RATE, label="نرخ تورم سالانه (Inflation Rate)") tax_rate = gr.Slider(0, 0.5, value=backend.TAX_RATE, label="نرخ مالیات (Tax Rate)") depreciation_years = gr.Slider(5, 20, value=backend.DEPRECIATION_YEARS, step=1, label="سال‌های استهلاک (Depreciation Years)") with gr.TabItem("ب) داده‌های تکنولوژی", id=1): tech_df = gr.DataFrame( value=pd.DataFrame(backend.TECHNOLOGY_DATA).T.reset_index().rename(columns={'index':'Technology', 'capex_base_M':'CAPEX (M$)', 'opex_base_cents_kg':'OPEX (cents/kg)'}), headers=['Technology', 'CAPEX (M$)', 'OPEX (cents/kg)'], label="داده‌های تکنولوژی‌های مختلف", row_count=(5, 'dynamic'), col_count=(3, 'fixed'), interactive=True ) with gr.TabItem("ج) استراتژی تأمین و محصولات جانبی", id=2): strategy_df = gr.DataFrame( value=pd.DataFrame({ 'Strategy': ['Integrated_Production', 'Purchase_VCM'], 'Sourcing Cost per Ton PVC': [450.0, 650.0], 'Byproduct Caustic Soda (ton)': [1.1, 0], 'Byproduct Surplus EDC (ton)': [0.523, 0] }), label="داده‌های استراتژی تأمین مواد اولیه", interactive=True ) with gr.TabItem("د) قیمت محصولات", id=3): prices_df = gr.DataFrame( value=pd.DataFrame(list(backend.PRODUCT_PRICES_USD_PER_TON.items()), columns=['Product', 'Price (USD/ton)']), label="قیمت فروش محصولات (دلار بر تن)", interactive=True ) with gr.TabItem("ه) فضای بهینه‌سازی", id=4): opt_space_df = gr.DataFrame( value=pd.DataFrame([ {'Parameter': 'capacity_kta', 'Type': 'range', 'Values': '500,600'}, {'Parameter': 'technology', 'Type': 'list', 'Values': 'Engro_Pakistan,Shin_Etsu_2004'}, {'Parameter': 'sourcing_strategy', 'Type': 'list', 'Values': 'Integrated_Production'}, {'Parameter': 'export_market_mix', 'Type': 'range', 'Values': '0.6,0.8'}, {'Parameter': 'sell_byproducts', 'Type': 'boolean', 'Values': 'True'} ]), headers=['Parameter', 'Type', 'Values'], label="پارامترهای مورد استفاده در الگوریتم بهینه‌سازی", interactive=True ) gr.Markdown("---") run_button = gr.Button("🚀 اجرا و بهینه‌سازی", variant="primary") run_status = gr.Textbox(label="وضعیت فرآیند", interactive=False) with gr.Column(scale=2): gr.Markdown("## ۲. نتایج تحلیل و نمودارها") with gr.Tabs(): with gr.TabItem("خلاصه نتایج بهینه‌سازی"): results_table = gr.DataFrame(label="جدول مقایسه سناریوهای بهینه", wrap=True) with gr.TabItem("داشبورد شاخص‌های کلیدی (KPI)"): kpi_dashboard = gr.Image(label="نمودار مقایسه KPI ها", show_label=True, type="filepath") with gr.TabItem("تحلیل حساسیت (Tornado Chart)"): sensitivity_chart = gr.Image(label="نمودار تحلیل حساسیت IRR", show_label=True, type="filepath") run_click_trigger = gr.Checkbox(value=False, visible=False) run_button.click(lambda: True, outputs=run_click_trigger) upload_button.upload( load_from_excel, inputs=[upload_button], outputs=[project_years, base_capacity, inflation_rate, tax_rate, depreciation_years, tech_df, strategy_df, prices_df, opt_space_df, upload_status] ) run_button.click( process_data, inputs=[project_years, base_capacity, inflation_rate, tax_rate, depreciation_years, tech_df, strategy_df, prices_df, opt_space_df, run_click_trigger], outputs=[results_table, kpi_dashboard, sensitivity_chart, run_status] ) demo.launch(share=True)