Spaces:
Sleeping
Sleeping
| 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) |