GIGAParviz commited on
Commit
b21cd02
·
verified ·
1 Parent(s): 61754c6

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +248 -249
app.py CHANGED
@@ -1,250 +1,249 @@
1
- import gradio as gr
2
- import pandas as pd
3
- import main as backend
4
- import os
5
-
6
- def process_data(project_years, base_capacity, inflation, tax, depr_years,
7
- tech_data_df, strategy_data_df, product_prices_df,
8
- opt_space_df, run_button_click):
9
-
10
- if not run_button_click:
11
- return None, None, None, "لطفاً برای شروع تحلیل، دکمه 'اجرا' را فشار دهید."
12
-
13
- backend.PROJECT_YEARS = int(project_years)
14
- backend.BASE_CAPACITY_KTA = int(base_capacity)
15
- backend.INFLATION_RATE = float(inflation)
16
- backend.TAX_RATE = float(tax)
17
- backend.DEPRECIATION_YEARS = int(depr_years)
18
-
19
- tech_data_df.rename(columns={
20
- 'CAPEX (M$)': 'capex_base_M',
21
- 'OPEX (cents/kg)': 'opex_base_cents_kg'
22
- }, inplace=True)
23
-
24
- backend.TECHNOLOGY_DATA = tech_data_df.set_index('Technology').to_dict('index')
25
-
26
- strategy_dict = {}
27
- for index, row in strategy_data_df.iterrows():
28
- strategy_dict[row['Strategy']] = {
29
- 'sourcing_cost_per_ton_pvc': row['Sourcing Cost per Ton PVC'],
30
- 'byproducts': {
31
- 'caustic_soda_ton': row['Byproduct Caustic Soda (ton)'],
32
- 'surplus_edc_ton': row['Byproduct Surplus EDC (ton)']
33
- }
34
- }
35
- backend.STRATEGY_DATA = strategy_dict
36
-
37
- backend.PRODUCT_PRICES_USD_PER_TON = product_prices_df.set_index('Product')['Price (USD/ton)'].to_dict()
38
-
39
- opt_space = {}
40
- for _, row in opt_space_df.iterrows():
41
- param = row['Parameter']
42
- value_type = row['Type']
43
- values = str(row['Values']).split(',')
44
- if value_type == 'range':
45
- opt_space[param] = (float(values[0]), float(values[1]))
46
- elif value_type == 'list':
47
- opt_space[param] = [v.strip() for v in values]
48
- elif value_type == 'boolean':
49
- opt_space[param] = [v.strip().lower() in ('true', '1', 't') for v in values]
50
- backend.OPTIMIZATION_SPACE = opt_space
51
-
52
- try:
53
- for f in ["results.csv", "kpi_dashboard.png", "sensitivity_analysis_tornado.png"]:
54
- if os.path.exists(f):
55
- os.remove(f)
56
-
57
- x_data, y_data = backend.build_ml_dataset()
58
- trained_models = backend.train_and_evaluate_models(x_data, y_data)
59
- optimization_results = backend.run_all_optimizations(trained_models)
60
- df_results = pd.DataFrame(optimization_results).sort_values(by="irr", ascending=False).reset_index(drop=True)
61
-
62
- backend.display_and_save_results(df_results)
63
- backend.create_kpi_comparison_dashboard(df_results)
64
-
65
- if not df_results.empty:
66
- best_scenario = df_results.iloc[0]
67
- backend.run_sensitivity_analysis(best_scenario['Params'], best_scenario['irr'])
68
-
69
- results_df = pd.read_csv("results.csv") if os.path.exists("results.csv") else pd.DataFrame()
70
- kpi_dashboard_img = "kpi_dashboard.png" if os.path.exists("kpi_dashboard.png") else None
71
- sensitivity_tornado_img = "sensitivity_analysis_tornado.png" if os.path.exists("sensitivity_analysis_tornado.png") else None
72
-
73
- return results_df, kpi_dashboard_img, sensitivity_tornado_img, "✅ تحلیل با موفقیت انجام شد!"
74
-
75
- except Exception as e:
76
- import traceback
77
- print(traceback.format_exc())
78
- return None, None, None, f"❌ خطا در اجرای تحلیل: {str(e)}"
79
-
80
- def load_from_excel(file):
81
- try:
82
- xls = pd.ExcelFile(file.name)
83
-
84
- assumptions = pd.read_excel(xls, 'Global_Assumptions').set_index('Parameter')['Value']
85
- tech_data = pd.read_excel(xls, 'Technology_Data')
86
- strategy_data = pd.read_excel(xls, 'Sourcing_Strategy')
87
- prices = pd.read_excel(xls, 'Product_Prices')
88
- opt_space = pd.read_excel(xls, 'Optimization_Space')
89
-
90
- return (assumptions['PROJECT_YEARS'], assumptions['BASE_CAPACITY_KTA'],
91
- assumptions['INFLATION_RATE'], assumptions['TAX_RATE'],
92
- assumptions['DEPRECIATION_YEARS'], tech_data, strategy_data,
93
- prices, opt_space, "فایل با موفقیت بارگذاری شد.")
94
- except Exception as e:
95
- return 0, 0, 0, 0, 0, pd.DataFrame(), pd.DataFrame(), pd.DataFrame(), pd.DataFrame(), f"خطا در بارگذاری فایل: {e}"
96
-
97
-
98
- css = """
99
- body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; }
100
- .gradio-container { max-width: 1280px !important; margin: auto !important; }
101
- .gr-button { background-color: #0056b3; color: white; border-radius: 8px; font-weight: bold; }
102
- .gr-button:hover { background-color: #004494; }
103
- footer { display: none !important; }
104
- """
105
-
106
- def create_template_excel():
107
- template_path = "data_template.xlsx"
108
- if not os.path.exists(template_path):
109
- with pd.ExcelWriter(template_path, engine='openpyxl') as writer:
110
-
111
- pd.DataFrame([
112
- {'Parameter': 'PROJECT_YEARS', 'Value': 15},
113
- {'Parameter': 'BASE_CAPACITY_KTA', 'Value': 300},
114
- {'Parameter': 'INFLATION_RATE', 'Value': 0.015},
115
- {'Parameter': 'TAX_RATE', 'Value': 0.10},
116
- {'Parameter': 'DEPRECIATION_YEARS', 'Value': 15}
117
- ]).to_excel(writer, sheet_name='Global_Assumptions', index=False)
118
-
119
- 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)
120
-
121
- pd.DataFrame({
122
- 'Strategy': ['Integrated_Production', 'Purchase_VCM'],
123
- 'Sourcing Cost per Ton PVC': [450.0, 650.0],
124
- 'Byproduct Caustic Soda (ton)': [1.1, 0],
125
- 'Byproduct Surplus EDC (ton)': [0.523, 0]
126
- }).to_excel(writer, sheet_name='Sourcing_Strategy', index=False)
127
-
128
- pd.DataFrame(list(backend.PRODUCT_PRICES_USD_PER_TON.items()), columns=['Product', 'Price (USD/ton)']).to_excel(writer, sheet_name='Product_Prices', index=False)
129
-
130
- pd.DataFrame([
131
- {'Parameter': 'capacity_kta', 'Type': 'range', 'Values': '500,600'},
132
- {'Parameter': 'technology', 'Type': 'list', 'Values': 'Engro_Pakistan,Shin_Etsu_2004'},
133
- {'Parameter': 'sourcing_strategy', 'Type': 'list', 'Values': 'Integrated_Production'},
134
- {'Parameter': 'export_market_mix', 'Type': 'range', 'Values': '0.6,0.8'},
135
- {'Parameter': 'sell_byproducts', 'Type': 'boolean', 'Values': 'True'}
136
- ]).to_excel(writer, sheet_name='Optimization_Space', index=False)
137
- return template_path
138
-
139
- template_file_path = create_template_excel()
140
-
141
-
142
- with gr.Blocks(theme=gr.themes.Soft(), css=css, title="داشبورد بهینه‌سازی پروژه") as demo:
143
-
144
- with gr.Row(elem_id="header"):
145
- logo_path = "logo.png"
146
- if os.path.exists(logo_path):
147
- gr.Image(logo_path, width=150, show_label=False, show_download_button=False, container=False)
148
- else:
149
- gr.Markdown("**(محل قرارگیری لوگو)**")
150
-
151
- gr.Markdown("# داشبورد تحلیل و بهینه‌سازی پروژه مالی", elem_id="app-title")
152
-
153
- gr.Markdown("---")
154
-
155
- with gr.Row():
156
- with gr.Column(scale=1):
157
- gr.Markdown("## ۱. ورودی‌ها و تنظیمات مدل")
158
-
159
- with gr.Accordion("بارگذاری داده‌ها از فایل", open=False):
160
- gr.Markdown("می‌توانید تمام پارامترها را با آپلود یک فایل اکسل (`.xlsx`) بارگذاری کنید. لطفاً از فرمت فایل نمونه استفاده کنید.")
161
- upload_button = gr.UploadButton("آپلود فایل اکسل", file_types=[".xlsx"], file_count="single")
162
- gr.File(value=template_file_path, label="دانلود فایل نمونه (Template)")
163
- upload_status = gr.Textbox(label="وضعیت بارگذاری", interactive=False)
164
-
165
- with gr.Tabs() as tabs:
166
- with gr.TabItem("الف) مفروضات اصلی پروژه", id=0):
167
- project_years = gr.Slider(5, 30, value=backend.PROJECT_YEARS, step=1, label="سال‌های پروژه (Project Years)")
168
- base_capacity = gr.Number(value=backend.BASE_CAPACITY_KTA, label="ظرفیت پایه (KTA)")
169
- inflation_rate = gr.Slider(0, 0.1, value=backend.INFLATION_RATE, label="نرخ تورم سالانه (Inflation Rate)")
170
- tax_rate = gr.Slider(0, 0.5, value=backend.TAX_RATE, label="نرخ مالیات (Tax Rate)")
171
- depreciation_years = gr.Slider(5, 20, value=backend.DEPRECIATION_YEARS, step=1, label="سال‌های استهلاک (Depreciation Years)")
172
-
173
- with gr.TabItem("ب) داده‌های تکنولوژی", id=1):
174
- tech_df = gr.DataFrame(
175
- 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)'}),
176
- headers=['Technology', 'CAPEX (M$)', 'OPEX (cents/kg)'],
177
- label="داده‌های تکنولوژی‌های مختلف",
178
- row_count=(5, 'dynamic'),
179
- col_count=(3, 'fixed'),
180
- interactive=True
181
- )
182
-
183
- with gr.TabItem("ج) استراتژی تأمین و محصولات جانبی", id=2):
184
- strategy_df = gr.DataFrame(
185
- value=pd.DataFrame({
186
- 'Strategy': ['Integrated_Production', 'Purchase_VCM'],
187
- 'Sourcing Cost per Ton PVC': [450.0, 650.0],
188
- 'Byproduct Caustic Soda (ton)': [1.1, 0],
189
- 'Byproduct Surplus EDC (ton)': [0.523, 0]
190
- }),
191
- label="داده‌های استراتژی تأمین مواد اولیه",
192
- interactive=True
193
- )
194
-
195
- with gr.TabItem("د) قیمت محصولات", id=3):
196
- prices_df = gr.DataFrame(
197
- value=pd.DataFrame(list(backend.PRODUCT_PRICES_USD_PER_TON.items()), columns=['Product', 'Price (USD/ton)']),
198
- label="قیمت فروش محصولات (دلار بر تن)",
199
- interactive=True
200
- )
201
-
202
- with gr.TabItem("ه) فضای بهینه‌سازی", id=4):
203
- opt_space_df = gr.DataFrame(
204
- value=pd.DataFrame([
205
- {'Parameter': 'capacity_kta', 'Type': 'range', 'Values': '500,600'},
206
- {'Parameter': 'technology', 'Type': 'list', 'Values': 'Engro_Pakistan,Shin_Etsu_2004'},
207
- {'Parameter': 'sourcing_strategy', 'Type': 'list', 'Values': 'Integrated_Production'},
208
- {'Parameter': 'export_market_mix', 'Type': 'range', 'Values': '0.6,0.8'},
209
- {'Parameter': 'sell_byproducts', 'Type': 'boolean', 'Values': 'True'}
210
- ]),
211
- headers=['Parameter', 'Type', 'Values'],
212
- label="پارامترهای مورد استفاده در الگوریتم بهینه‌سازی",
213
- interactive=True
214
- )
215
-
216
- gr.Markdown("---")
217
- run_button = gr.Button("🚀 اجرا و بهینه‌سازی", variant="primary")
218
- run_status = gr.Textbox(label="وضعیت فرآیند", interactive=False)
219
-
220
- with gr.Column(scale=2):
221
- gr.Markdown("## ۲. نتایج تحلیل و نمودارها")
222
- with gr.Tabs():
223
- with gr.TabItem("خلاصه نتایج بهینه‌سازی"):
224
- results_table = gr.DataFrame(label="جدول مقایسه سناریوهای بهینه", wrap=True)
225
-
226
- with gr.TabItem("داشبورد شاخص‌های کلیدی (KPI)"):
227
- kpi_dashboard = gr.Image(label="نمودار مقایسه KPI ها", show_label=True, type="filepath")
228
-
229
- with gr.TabItem("تحلیل حساسیت (Tornado Chart)"):
230
- sensitivity_chart = gr.Image(label="نمودار تحلیل حساسیت IRR", show_label=True, type="filepath")
231
-
232
- run_click_trigger = gr.Checkbox(value=False, visible=False)
233
- run_button.click(lambda: True, outputs=run_click_trigger)
234
-
235
-
236
- upload_button.upload(
237
- load_from_excel,
238
- inputs=[upload_button],
239
- outputs=[project_years, base_capacity, inflation_rate, tax_rate, depreciation_years,
240
- tech_df, strategy_df, prices_df, opt_space_df, upload_status]
241
- )
242
-
243
- run_button.click(
244
- process_data,
245
- inputs=[project_years, base_capacity, inflation_rate, tax_rate, depreciation_years,
246
- tech_df, strategy_df, prices_df, opt_space_df, run_click_trigger],
247
- outputs=[results_table, kpi_dashboard, sensitivity_chart, run_status]
248
- )
249
-
250
  demo.launch(share=True)
 
1
+ import gradio as gr
2
+ import pandas as pd
3
+ import main as backend
4
+ import os
5
+
6
+
7
+ def process_data(project_years, base_capacity, inflation, tax, depr_years,
8
+ tech_data_df, strategy_data_df, product_prices_df,
9
+ opt_space_df, run_button_click):
10
+
11
+ if not run_button_click:
12
+ return None, None, None, "لطفاً برای شروع تحلیل، دکمه 'اجرا' را فشار دهید."
13
+
14
+ backend.PROJECT_YEARS = int(project_years)
15
+ backend.BASE_CAPACITY_KTA = int(base_capacity)
16
+ backend.INFLATION_RATE = float(inflation)
17
+ backend.TAX_RATE = float(tax)
18
+ backend.DEPRECIATION_YEARS = int(depr_years)
19
+
20
+ tech_data_df.rename(columns={
21
+ 'CAPEX (M$)': 'capex_base_M',
22
+ 'OPEX (cents/kg)': 'opex_base_cents_kg'
23
+ }, inplace=True)
24
+
25
+ backend.TECHNOLOGY_DATA = tech_data_df.set_index('Technology').to_dict('index')
26
+
27
+ strategy_dict = {}
28
+ for index, row in strategy_data_df.iterrows():
29
+ strategy_dict[row['Strategy']] = {
30
+ 'sourcing_cost_per_ton_pvc': row['Sourcing Cost per Ton PVC'],
31
+ 'byproducts': {
32
+ 'caustic_soda_ton': row['Byproduct Caustic Soda (ton)'],
33
+ 'surplus_edc_ton': row['Byproduct Surplus EDC (ton)']
34
+ }
35
+ }
36
+ backend.STRATEGY_DATA = strategy_dict
37
+
38
+ backend.PRODUCT_PRICES_USD_PER_TON = product_prices_df.set_index('Product')['Price (USD/ton)'].to_dict()
39
+
40
+ opt_space = {}
41
+ for _, row in opt_space_df.iterrows():
42
+ param = row['Parameter']
43
+ value_type = row['Type']
44
+ values = str(row['Values']).split(',')
45
+ if value_type == 'range':
46
+ opt_space[param] = (float(values[0]), float(values[1]))
47
+ elif value_type == 'list':
48
+ opt_space[param] = [v.strip() for v in values]
49
+ elif value_type == 'boolean':
50
+ opt_space[param] = [v.strip().lower() in ('true', '1', 't') for v in values]
51
+ backend.OPTIMIZATION_SPACE = opt_space
52
+
53
+ try:
54
+ for f in ["results.csv", "kpi_dashboard.png", "sensitivity_analysis_tornado.png"]:
55
+ if os.path.exists(f):
56
+ os.remove(f)
57
+
58
+ optimization_results_list = backend.run_optimizations_without_ml()
59
+
60
+ df_results = pd.DataFrame(optimization_results_list).sort_values(by="irr", ascending=False).reset_index(drop=True)
61
+
62
+ backend.display_and_save_results(df_results)
63
+ backend.create_kpi_comparison_dashboard(df_results)
64
+
65
+ if not df_results.empty:
66
+ best_scenario = df_results.iloc[0]
67
+ backend.run_sensitivity_analysis(best_scenario['Params'], best_scenario['irr'])
68
+
69
+ results_df = pd.read_csv("results.csv") if os.path.exists("results.csv") else pd.DataFrame()
70
+ kpi_dashboard_img = "kpi_dashboard.png" if os.path.exists("kpi_dashboard.png") else None
71
+ sensitivity_tornado_img = "sensitivity_analysis_tornado.png" if os.path.exists("sensitivity_analysis_tornado.png") else None
72
+
73
+ return results_df, kpi_dashboard_img, sensitivity_tornado_img, "✅ تحلیل بهینه‌سازی با موفقیت انجام شد!"
74
+ except Exception as e:
75
+ import traceback
76
+ print(traceback.format_exc())
77
+ return None, None, None, f"❌ خطا در اجرای تحلیل: {str(e)}"
78
+
79
+ def load_from_excel(file):
80
+ try:
81
+ xls = pd.ExcelFile(file.name)
82
+
83
+ assumptions = pd.read_excel(xls, 'Global_Assumptions').set_index('Parameter')['Value']
84
+ tech_data = pd.read_excel(xls, 'Technology_Data')
85
+ strategy_data = pd.read_excel(xls, 'Sourcing_Strategy')
86
+ prices = pd.read_excel(xls, 'Product_Prices')
87
+ opt_space = pd.read_excel(xls, 'Optimization_Space')
88
+
89
+ return (assumptions['PROJECT_YEARS'], assumptions['BASE_CAPACITY_KTA'],
90
+ assumptions['INFLATION_RATE'], assumptions['TAX_RATE'],
91
+ assumptions['DEPRECIATION_YEARS'], tech_data, strategy_data,
92
+ prices, opt_space, "فایل با موفقیت بارگذاری شد.")
93
+ except Exception as e:
94
+ return 0, 0, 0, 0, 0, pd.DataFrame(), pd.DataFrame(), pd.DataFrame(), pd.DataFrame(), f"خطا در بارگذاری فایل: {e}"
95
+
96
+
97
+ css = """
98
+ body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; }
99
+ .gradio-container { max-width: 1280px !important; margin: auto !important; }
100
+ .gr-button { background-color: #0056b3; color: white; border-radius: 8px; font-weight: bold; }
101
+ .gr-button:hover { background-color: #004494; }
102
+ footer { display: none !important; }
103
+ """
104
+
105
+ def create_template_excel():
106
+ template_path = "data_template.xlsx"
107
+ if not os.path.exists(template_path):
108
+ with pd.ExcelWriter(template_path, engine='openpyxl') as writer:
109
+
110
+ pd.DataFrame([
111
+ {'Parameter': 'PROJECT_YEARS', 'Value': 15},
112
+ {'Parameter': 'BASE_CAPACITY_KTA', 'Value': 300},
113
+ {'Parameter': 'INFLATION_RATE', 'Value': 0.015},
114
+ {'Parameter': 'TAX_RATE', 'Value': 0.10},
115
+ {'Parameter': 'DEPRECIATION_YEARS', 'Value': 15}
116
+ ]).to_excel(writer, sheet_name='Global_Assumptions', index=False)
117
+
118
+ 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)
119
+
120
+ pd.DataFrame({
121
+ 'Strategy': ['Integrated_Production', 'Purchase_VCM'],
122
+ 'Sourcing Cost per Ton PVC': [450.0, 650.0],
123
+ 'Byproduct Caustic Soda (ton)': [1.1, 0],
124
+ 'Byproduct Surplus EDC (ton)': [0.523, 0]
125
+ }).to_excel(writer, sheet_name='Sourcing_Strategy', index=False)
126
+
127
+ pd.DataFrame(list(backend.PRODUCT_PRICES_USD_PER_TON.items()), columns=['Product', 'Price (USD/ton)']).to_excel(writer, sheet_name='Product_Prices', index=False)
128
+
129
+ pd.DataFrame([
130
+ {'Parameter': 'capacity_kta', 'Type': 'range', 'Values': '500,600'},
131
+ {'Parameter': 'technology', 'Type': 'list', 'Values': 'Engro_Pakistan,Shin_Etsu_2004'},
132
+ {'Parameter': 'sourcing_strategy', 'Type': 'list', 'Values': 'Integrated_Production'},
133
+ {'Parameter': 'export_market_mix', 'Type': 'range', 'Values': '0.6,0.8'},
134
+ {'Parameter': 'sell_byproducts', 'Type': 'boolean', 'Values': 'True'}
135
+ ]).to_excel(writer, sheet_name='Optimization_Space', index=False)
136
+ return template_path
137
+
138
+ template_file_path = create_template_excel()
139
+
140
+
141
+ with gr.Blocks(theme=gr.themes.Soft(), css=css, title="داشبورد بهینه‌سازی پروژه") as demo:
142
+
143
+ with gr.Row(elem_id="header"):
144
+ logo_path = "logo.png"
145
+ if os.path.exists(logo_path):
146
+ gr.Image(logo_path, width=150, show_label=False, show_download_button=False, container=False)
147
+ else:
148
+ gr.Markdown("**(محل قرارگیری لوگو)**")
149
+
150
+ gr.Markdown("# داشبورد تحلیل و بهینه‌سازی پروژه مالی", elem_id="app-title")
151
+
152
+ gr.Markdown("---")
153
+
154
+ with gr.Row():
155
+ with gr.Column(scale=1):
156
+ gr.Markdown("## ۱. ورودی‌ها و تنظیمات مدل")
157
+
158
+ with gr.Accordion("بارگذاری داده‌ها از فایل", open=False):
159
+ gr.Markdown("می‌توانید تمام پارامترها را با آپلود یک فایل اکسل (`.xlsx`) بارگذاری کنید. لطفاً از فرمت فایل نمونه استفاده کنید.")
160
+ upload_button = gr.UploadButton("آپلود فایل اکسل", file_types=[".xlsx"], file_count="single")
161
+ gr.File(value=template_file_path, label="دانلود فایل نمونه (Template)")
162
+ upload_status = gr.Textbox(label="وضعیت بارگذاری", interactive=False)
163
+
164
+ with gr.Tabs() as tabs:
165
+ with gr.TabItem("الف) مفروضات اصلی پروژه", id=0):
166
+ project_years = gr.Slider(5, 30, value=backend.PROJECT_YEARS, step=1, label="سال‌های پروژه (Project Years)")
167
+ base_capacity = gr.Number(value=backend.BASE_CAPACITY_KTA, label="ظرفیت پایه (KTA)")
168
+ inflation_rate = gr.Slider(0, 0.1, value=backend.INFLATION_RATE, label="نرخ تورم سالانه (Inflation Rate)")
169
+ tax_rate = gr.Slider(0, 0.5, value=backend.TAX_RATE, label="نرخ مالیات (Tax Rate)")
170
+ depreciation_years = gr.Slider(5, 20, value=backend.DEPRECIATION_YEARS, step=1, label="سال‌های استهلاک (Depreciation Years)")
171
+
172
+ with gr.TabItem("ب) داده‌های تکنولوژی", id=1):
173
+ tech_df = gr.DataFrame(
174
+ 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)'}),
175
+ headers=['Technology', 'CAPEX (M$)', 'OPEX (cents/kg)'],
176
+ label="داده‌های تکنولوژی‌های مختلف",
177
+ row_count=(5, 'dynamic'),
178
+ col_count=(3, 'fixed'),
179
+ interactive=True
180
+ )
181
+
182
+ with gr.TabItem("ج) استراتژی تأمین و محصولات جانبی", id=2):
183
+ strategy_df = gr.DataFrame(
184
+ value=pd.DataFrame({
185
+ 'Strategy': ['Integrated_Production', 'Purchase_VCM'],
186
+ 'Sourcing Cost per Ton PVC': [450.0, 650.0],
187
+ 'Byproduct Caustic Soda (ton)': [1.1, 0],
188
+ 'Byproduct Surplus EDC (ton)': [0.523, 0]
189
+ }),
190
+ label="داده‌های استراتژی تأمین مواد اولیه",
191
+ interactive=True
192
+ )
193
+
194
+ with gr.TabItem("د) قیمت محصولات", id=3):
195
+ prices_df = gr.DataFrame(
196
+ value=pd.DataFrame(list(backend.PRODUCT_PRICES_USD_PER_TON.items()), columns=['Product', 'Price (USD/ton)']),
197
+ label="قیمت فروش محصولات (دلار بر تن)",
198
+ interactive=True
199
+ )
200
+
201
+ with gr.TabItem("ه) فضای بهینه‌سازی", id=4):
202
+ opt_space_df = gr.DataFrame(
203
+ value=pd.DataFrame([
204
+ {'Parameter': 'capacity_kta', 'Type': 'range', 'Values': '500,600'},
205
+ {'Parameter': 'technology', 'Type': 'list', 'Values': 'Engro_Pakistan,Shin_Etsu_2004'},
206
+ {'Parameter': 'sourcing_strategy', 'Type': 'list', 'Values': 'Integrated_Production'},
207
+ {'Parameter': 'export_market_mix', 'Type': 'range', 'Values': '0.6,0.8'},
208
+ {'Parameter': 'sell_byproducts', 'Type': 'boolean', 'Values': 'True'}
209
+ ]),
210
+ headers=['Parameter', 'Type', 'Values'],
211
+ label="پارامترهای مورد استفاده در الگوریتم بهینه‌سازی",
212
+ interactive=True
213
+ )
214
+
215
+ gr.Markdown("---")
216
+ run_button = gr.Button("🚀 اجرا و بهینه‌سازی", variant="primary")
217
+ run_status = gr.Textbox(label=ضعیت فرآیند", interactive=False)
218
+
219
+ with gr.Column(scale=2):
220
+ gr.Markdown("## ۲. نتایج تحلیل و نمودارها")
221
+ with gr.Tabs():
222
+ with gr.TabItem("خلاصه نتایج بهینه‌سازی"):
223
+ results_table = gr.DataFrame(label="جدول مقایسه سناریوهای بهینه", wrap=True)
224
+
225
+ with gr.TabItem("داشبورد شاخص‌های کلیدی (KPI)"):
226
+ kpi_dashboard = gr.Image(label="نمودار مقایسه KPI ها", show_label=True, type="filepath")
227
+
228
+ with gr.TabItem("تحلیل حساسیت (Tornado Chart)"):
229
+ sensitivity_chart = gr.Image(label="نمودار تحلیل حساسیت IRR", show_label=True, type="filepath")
230
+
231
+ run_click_trigger = gr.Checkbox(value=False, visible=False)
232
+ run_button.click(lambda: True, outputs=run_click_trigger)
233
+
234
+
235
+ upload_button.upload(
236
+ load_from_excel,
237
+ inputs=[upload_button],
238
+ outputs=[project_years, base_capacity, inflation_rate, tax_rate, depreciation_years,
239
+ tech_df, strategy_df, prices_df, opt_space_df, upload_status]
240
+ )
241
+
242
+ run_button.click(
243
+ process_data,
244
+ inputs=[project_years, base_capacity, inflation_rate, tax_rate, depreciation_years,
245
+ tech_df, strategy_df, prices_df, opt_space_df, run_click_trigger],
246
+ outputs=[results_table, kpi_dashboard, sensitivity_chart, run_status]
247
+ )
248
+
 
249
  demo.launch(share=True)