Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -2,17 +2,20 @@ import gradio as gr
|
|
| 2 |
import pandas as pd
|
| 3 |
import json
|
| 4 |
import os
|
| 5 |
-
|
|
|
|
|
|
|
| 6 |
|
| 7 |
-
#
|
| 8 |
DB_PATH = "material_db.json"
|
|
|
|
| 9 |
|
| 10 |
class ElectricPoleEstimator:
|
| 11 |
def __init__(self):
|
| 12 |
-
# ایجاد فایل دیتابیس اگر وجود ندارد
|
| 13 |
self._initialize_db()
|
| 14 |
self.db = self._load_db()
|
| 15 |
self.rule_engine = RuleEngine()
|
|
|
|
| 16 |
|
| 17 |
def _initialize_db(self):
|
| 18 |
"""ایجاد فایل دیتابیس اولیه"""
|
|
@@ -49,7 +52,10 @@ class ElectricPoleEstimator:
|
|
| 49 |
'quantity_expr': str(row['تعداد']) if pd.notna(row['تعداد']) else None,
|
| 50 |
'pole_height': float(row['ارتفاع پایه']) if pd.notna(row['ارتفاع پایه']) else None,
|
| 51 |
'pole_capacity': float(row['توان پایه']) if pd.notna(row['توان پایه']) else None,
|
| 52 |
-
'conductor_type': row['نوع هادی'] if pd.notna(row['نوع هادی']) else None
|
|
|
|
|
|
|
|
|
|
| 53 |
}
|
| 54 |
new_items.append(item)
|
| 55 |
|
|
@@ -59,76 +65,176 @@ class ElectricPoleEstimator:
|
|
| 59 |
except Exception as e:
|
| 60 |
return f"❌ خطا: {str(e)}"
|
| 61 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 62 |
def estimate(self,
|
| 63 |
pole_height: Optional[float] = None,
|
| 64 |
pole_capacity: Optional[float] = None,
|
| 65 |
conductor_type: Optional[str] = None,
|
| 66 |
config_type: Optional[str] = None) -> List[Dict]:
|
| 67 |
-
"""محاسبه برآورد"""
|
| 68 |
context = {
|
| 69 |
'pole_height': pole_height,
|
| 70 |
'pole_capacity': pole_capacity,
|
| 71 |
'conductor_type': conductor_type,
|
| 72 |
'configuration': config_type
|
| 73 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 74 |
|
| 75 |
-
|
| 76 |
-
|
| 77 |
-
|
| 78 |
-
|
|
|
|
|
|
|
|
|
|
| 79 |
results = []
|
| 80 |
for item in self.db:
|
| 81 |
-
if self._is_item_required(item,
|
| 82 |
qty = self._calculate_quantity(item, context)
|
| 83 |
results.append({
|
| 84 |
-
'
|
| 85 |
-
'
|
| 86 |
-
'
|
| 87 |
-
'
|
| 88 |
-
'
|
| 89 |
})
|
| 90 |
return results
|
| 91 |
|
| 92 |
-
def _is_item_required(self, item: Dict,
|
| 93 |
-
"""بررسی نیاز به آیتم"""
|
| 94 |
-
|
| 95 |
-
|
| 96 |
-
|
| 97 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 98 |
|
| 99 |
def _calculate_quantity(self, item: Dict, context: Dict) -> float:
|
| 100 |
-
"""محاسبه مقدار"""
|
| 101 |
-
if not item['quantity_expr']:
|
| 102 |
-
return 1.0
|
| 103 |
try:
|
| 104 |
-
|
| 105 |
-
|
| 106 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 107 |
except:
|
| 108 |
-
|
|
|
|
| 109 |
|
| 110 |
-
def _format_conditions(self, item: Dict) -> str:
|
| 111 |
"""قالببندی شرایط برای نمایش"""
|
| 112 |
conditions = []
|
| 113 |
-
if item
|
| 114 |
-
if item
|
| 115 |
-
if item
|
| 116 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 117 |
|
| 118 |
class RuleEngine:
|
| 119 |
-
"""موتور قوانین
|
| 120 |
def __init__(self):
|
| 121 |
self.rules = [
|
| 122 |
self._minck_rule,
|
| 123 |
-
self._passing_config_rule
|
|
|
|
| 124 |
]
|
| 125 |
|
| 126 |
def apply_rules(self, context: Dict) -> Dict:
|
| 127 |
-
"""اعمال تمام قوانین"""
|
| 128 |
overrides = {}
|
| 129 |
for rule in self.rules:
|
| 130 |
overrides.update(rule(context))
|
| 131 |
-
return overrides
|
| 132 |
|
| 133 |
def _minck_rule(self, context: Dict) -> Dict:
|
| 134 |
"""قانون سیم مینک"""
|
|
@@ -141,22 +247,63 @@ class RuleEngine:
|
|
| 141 |
if context.get('configuration') == 'عبوری':
|
| 142 |
return {'pole_capacity': 400}
|
| 143 |
return {}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 144 |
|
| 145 |
-
#
|
| 146 |
estimator = ElectricPoleEstimator()
|
| 147 |
|
| 148 |
# رابط کاربری Gradio
|
| 149 |
-
with gr.Blocks(title="
|
| 150 |
-
gr.Markdown("## سیستم برآورد
|
| 151 |
|
| 152 |
-
with gr.Tab("بارگذاری دادهها"):
|
| 153 |
gr.Markdown("### بارگذاری فایل اکسل جدید")
|
| 154 |
-
file_input = gr.File(label="فایل اکسل برآورد",
|
| 155 |
-
upload_btn = gr.Button("بارگذاری و ذخیره در دیتابیس")
|
| 156 |
upload_output = gr.Textbox(label="نتایج بارگذاری")
|
| 157 |
upload_btn.click(estimator.add_materials, inputs=file_input, outputs=upload_output)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 158 |
|
| 159 |
-
with gr.Tab("
|
| 160 |
with gr.Row():
|
| 161 |
height = gr.Number(label="ارتفاع پایه (متر)", value=12)
|
| 162 |
capacity = gr.Number(label="توان پایه (kVA)", value=600)
|
|
@@ -170,31 +317,17 @@ with gr.Blocks(title="برآورد هوشمند مصالح تاسیسات برق
|
|
| 170 |
choices=["", "عبوری", "انتهایی", "زانویی"],
|
| 171 |
value=""
|
| 172 |
)
|
| 173 |
-
|
| 174 |
|
| 175 |
-
|
| 176 |
-
headers=["کد", "عنوان", "مقدار", "واحد"
|
| 177 |
-
datatype=["str", "str", "number", "str"
|
| 178 |
-
wrap=True
|
| 179 |
)
|
| 180 |
|
| 181 |
-
|
| 182 |
estimator.estimate,
|
| 183 |
inputs=[height, capacity, conductor, config],
|
| 184 |
-
outputs=
|
| 185 |
-
)
|
| 186 |
-
|
| 187 |
-
with gr.Tab("مشاهده دیتابیس"):
|
| 188 |
-
gr.Markdown("### محتوای فعلی دیتابیس")
|
| 189 |
-
db_viewer = gr.Dataframe(
|
| 190 |
-
headers=["کد", "عنوان", "واحد", "ارتفاع", "توان", "هادی"],
|
| 191 |
-
datatype=["str", "str", "str", "number", "number", "str"],
|
| 192 |
-
interactive=False
|
| 193 |
-
)
|
| 194 |
-
refresh_btn = gr.Button("بروزرسانی نمایش")
|
| 195 |
-
refresh_btn.click(
|
| 196 |
-
lambda: pd.DataFrame(estimator.db)[['code', 'title', 'unit', 'pole_height', 'pole_capacity', 'conductor_type']],
|
| 197 |
-
outputs=db_viewer
|
| 198 |
)
|
| 199 |
|
| 200 |
if __name__ == "__main__":
|
|
|
|
| 2 |
import pandas as pd
|
| 3 |
import json
|
| 4 |
import os
|
| 5 |
+
import re
|
| 6 |
+
import math
|
| 7 |
+
from typing import Dict, List, Optional, Union
|
| 8 |
|
| 9 |
+
# تنظیمات پایه
|
| 10 |
DB_PATH = "material_db.json"
|
| 11 |
+
os.environ["TOKENIZERS_PARALLELISM"] = "false"
|
| 12 |
|
| 13 |
class ElectricPoleEstimator:
|
| 14 |
def __init__(self):
|
|
|
|
| 15 |
self._initialize_db()
|
| 16 |
self.db = self._load_db()
|
| 17 |
self.rule_engine = RuleEngine()
|
| 18 |
+
self.nlp_processor = NLPProcessor()
|
| 19 |
|
| 20 |
def _initialize_db(self):
|
| 21 |
"""ایجاد فایل دیتابیس اولیه"""
|
|
|
|
| 52 |
'quantity_expr': str(row['تعداد']) if pd.notna(row['تعداد']) else None,
|
| 53 |
'pole_height': float(row['ارتفاع پایه']) if pd.notna(row['ارتفاع پایه']) else None,
|
| 54 |
'pole_capacity': float(row['توان پایه']) if pd.notna(row['توان پایه']) else None,
|
| 55 |
+
'conductor_type': row['نوع هادی'] if pd.notna(row['نوع هادی']) else None,
|
| 56 |
+
'conditions': self._parse_conditions(row),
|
| 57 |
+
'description': row['عنوان'], # استفاده از عنوان به عنوان توضیحات اولیه
|
| 58 |
+
'keywords': self._generate_keywords(row['عنوان'])
|
| 59 |
}
|
| 60 |
new_items.append(item)
|
| 61 |
|
|
|
|
| 65 |
except Exception as e:
|
| 66 |
return f"❌ خطا: {str(e)}"
|
| 67 |
|
| 68 |
+
def _parse_conditions(self, row) -> Optional[Dict]:
|
| 69 |
+
"""استخراج شرایط از ردیف اکسل"""
|
| 70 |
+
conditions = {}
|
| 71 |
+
if pd.notna(row['تعداد']) and '=' in str(row['تعداد']):
|
| 72 |
+
conditions.update({
|
| 73 |
+
'type': 'formula',
|
| 74 |
+
'formula': str(row['تعداد'])[1:] if str(row['تعداد']).startswith('=') else str(row['تعداد'])
|
| 75 |
+
})
|
| 76 |
+
return conditions if conditions else None
|
| 77 |
+
|
| 78 |
+
def _generate_keywords(self, text: str) -> List[str]:
|
| 79 |
+
"""تولید کلمات کلیدی از عنوان"""
|
| 80 |
+
persian_keywords = re.findall(r'[\w\-]+', text)
|
| 81 |
+
return list(set(persian_keywords))
|
| 82 |
+
|
| 83 |
def estimate(self,
|
| 84 |
pole_height: Optional[float] = None,
|
| 85 |
pole_capacity: Optional[float] = None,
|
| 86 |
conductor_type: Optional[str] = None,
|
| 87 |
config_type: Optional[str] = None) -> List[Dict]:
|
| 88 |
+
"""محاسبه برآورد پارامتریک"""
|
| 89 |
context = {
|
| 90 |
'pole_height': pole_height,
|
| 91 |
'pole_capacity': pole_capacity,
|
| 92 |
'conductor_type': conductor_type,
|
| 93 |
'configuration': config_type
|
| 94 |
}
|
| 95 |
+
return self._estimate_with_context(context)
|
| 96 |
+
|
| 97 |
+
def estimate_from_text(self, project_description: str) -> Dict:
|
| 98 |
+
"""محاسبه برآورد از توضیحات متنی"""
|
| 99 |
+
features = self.nlp_processor.extract_features(project_description)
|
| 100 |
+
context = self.rule_engine.apply_rules(features)
|
| 101 |
+
estimates = self._estimate_with_context(context)
|
| 102 |
|
| 103 |
+
return {
|
| 104 |
+
'extracted_features': features,
|
| 105 |
+
'estimates': estimates
|
| 106 |
+
}
|
| 107 |
+
|
| 108 |
+
def _estimate_with_context(self, context: Dict) -> List[Dict]:
|
| 109 |
+
"""هسته اصلی محاسبه برآورد"""
|
| 110 |
results = []
|
| 111 |
for item in self.db:
|
| 112 |
+
if self._is_item_required(item, context):
|
| 113 |
qty = self._calculate_quantity(item, context)
|
| 114 |
results.append({
|
| 115 |
+
'code': item['code'],
|
| 116 |
+
'title': item['title'],
|
| 117 |
+
'quantity': qty,
|
| 118 |
+
'unit': item['unit'],
|
| 119 |
+
'conditions': self._format_conditions(item, context)
|
| 120 |
})
|
| 121 |
return results
|
| 122 |
|
| 123 |
+
def _is_item_required(self, item: Dict, context: Dict) -> bool:
|
| 124 |
+
"""بررسی نیاز به آیتم براساس شرایط"""
|
| 125 |
+
# شرایط عمومی
|
| 126 |
+
height_ok = (item.get('pole_height') is None) or (item.get('pole_height') == context.get('pole_height'))
|
| 127 |
+
capacity_ok = (item.get('pole_capacity') is None) or (item.get('pole_capacity') == context.get('pole_capacity'))
|
| 128 |
+
conductor_ok = (item.get('conductor_type') is None) or (item.get('conductor_type') == context.get('conductor_type'))
|
| 129 |
+
|
| 130 |
+
# شرایط پیشرفته
|
| 131 |
+
advanced_ok = True
|
| 132 |
+
if 'conditions' in item and item['conditions']:
|
| 133 |
+
if item['conditions']['type'] == 'formula':
|
| 134 |
+
try:
|
| 135 |
+
advanced_ok = eval(item['conditions'].get('rule', 'True'), {}, context)
|
| 136 |
+
except:
|
| 137 |
+
advanced_ok = True
|
| 138 |
+
|
| 139 |
+
return height_ok and capacity_ok and conductor_ok and advanced_ok
|
| 140 |
|
| 141 |
def _calculate_quantity(self, item: Dict, context: Dict) -> float:
|
| 142 |
+
"""محاسبه مقدار با پشتیبانی از تمام حالتها"""
|
|
|
|
|
|
|
| 143 |
try:
|
| 144 |
+
# فرمولهای پیشرفته
|
| 145 |
+
if 'conditions' in item and item['conditions']:
|
| 146 |
+
if item['conditions']['type'] == 'formula':
|
| 147 |
+
return eval(item['conditions']['formula'], {'math': math}, context)
|
| 148 |
+
|
| 149 |
+
# فرمولهای ساده
|
| 150 |
+
if item.get('quantity_expr'):
|
| 151 |
+
if item['quantity_expr'].startswith('='):
|
| 152 |
+
return eval(item['quantity_expr'][1:], {}, context)
|
| 153 |
+
return float(item['quantity_expr'])
|
| 154 |
except:
|
| 155 |
+
pass
|
| 156 |
+
return 1.0
|
| 157 |
|
| 158 |
+
def _format_conditions(self, item: Dict, context: Dict) -> str:
|
| 159 |
"""قالببندی شرایط برای نمایش"""
|
| 160 |
conditions = []
|
| 161 |
+
if item.get('pole_height'): conditions.append(f"ارتفاع: {item['pole_height']}m")
|
| 162 |
+
if item.get('pole_capacity'): conditions.append(f"توان: {item['pole_capacity']}kVA")
|
| 163 |
+
if item.get('conductor_type'): conditions.append(f"هادی: {item['conductor_type']}")
|
| 164 |
+
|
| 165 |
+
# نمایش فرمول اگر وجود دارد
|
| 166 |
+
if 'conditions' in item and item['conditions']:
|
| 167 |
+
if item['conditions']['type'] == 'formula':
|
| 168 |
+
conditions.append(f"فرمول: {item['conditions']['formula']}")
|
| 169 |
+
|
| 170 |
+
return " | ".join(conditions) if conditions else "عمومی"
|
| 171 |
+
|
| 172 |
+
class NLPProcessor:
|
| 173 |
+
"""پردازشگر هوشمند متن ورودی"""
|
| 174 |
+
def __init__(self):
|
| 175 |
+
self.keyword_rules = {
|
| 176 |
+
'مینک': ['مینک', 'mink'],
|
| 177 |
+
'هاینا': ['هاینا', 'haina'],
|
| 178 |
+
'عبوری': ['عبوری', 'passing'],
|
| 179 |
+
'خاکی': ['خاکی', 'soil'],
|
| 180 |
+
'اسفالت': ['اسفالت', 'asphalt']
|
| 181 |
+
}
|
| 182 |
+
|
| 183 |
+
def extract_features(self, text: str) -> Dict:
|
| 184 |
+
"""استخراج هوشمند ویژگیها از متن"""
|
| 185 |
+
return {
|
| 186 |
+
'length': self._extract_length(text),
|
| 187 |
+
'road_type': self._extract_road_type(text),
|
| 188 |
+
'conductor_type': self._extract_conductor_type(text),
|
| 189 |
+
'pole_height': self._extract_pole_height(text),
|
| 190 |
+
'pole_capacity': self._extract_pole_capacity(text),
|
| 191 |
+
'keywords': self._extract_keywords(text)
|
| 192 |
+
}
|
| 193 |
+
|
| 194 |
+
def _extract_length(self, text: str) -> Optional[float]:
|
| 195 |
+
match = re.search(r'(\d+)\s*متری', text)
|
| 196 |
+
return float(match.group(1)) if match else None
|
| 197 |
+
|
| 198 |
+
def _extract_road_type(self, text: str) -> Optional[str]:
|
| 199 |
+
for rt, keywords in self.keyword_rules.items():
|
| 200 |
+
if any(kw in text for kw in keywords):
|
| 201 |
+
return rt
|
| 202 |
+
return None
|
| 203 |
+
|
| 204 |
+
def _extract_conductor_type(self, text: str) -> Optional[str]:
|
| 205 |
+
for ct, keywords in [('مینک', self.keyword_rules['مینك']),
|
| 206 |
+
('هاینا', self.keyword_rules['هاینا'])]:
|
| 207 |
+
if any(kw in text for kw in keywords):
|
| 208 |
+
return ct
|
| 209 |
+
return None
|
| 210 |
+
|
| 211 |
+
def _extract_pole_height(self, text: str) -> Optional[float]:
|
| 212 |
+
matches = re.findall(r'پایه\s*(\d+)', text) or re.findall(r'ارتفاع\s*(\d+)', text)
|
| 213 |
+
return float(matches[0]) if matches else None
|
| 214 |
+
|
| 215 |
+
def _extract_pole_capacity(self, text: str) -> Optional[float]:
|
| 216 |
+
matches = re.findall(r'(\d+)\s*کیلوولت', text) or re.findall(r'(\d+)\s*kV', text)
|
| 217 |
+
return float(matches[0]) if matches else None
|
| 218 |
+
|
| 219 |
+
def _extract_keywords(self, text: str) -> List[str]:
|
| 220 |
+
return [kw for kw, keywords in self.keyword_rules.items()
|
| 221 |
+
if any(k in text for k in keywords)]
|
| 222 |
|
| 223 |
class RuleEngine:
|
| 224 |
+
"""موتور قوانین هوشمند"""
|
| 225 |
def __init__(self):
|
| 226 |
self.rules = [
|
| 227 |
self._minck_rule,
|
| 228 |
+
self._passing_config_rule,
|
| 229 |
+
self._road_type_rule
|
| 230 |
]
|
| 231 |
|
| 232 |
def apply_rules(self, context: Dict) -> Dict:
|
| 233 |
+
"""اعمال تمام قوانین به ترتیب"""
|
| 234 |
overrides = {}
|
| 235 |
for rule in self.rules:
|
| 236 |
overrides.update(rule(context))
|
| 237 |
+
return {**context, **overrides}
|
| 238 |
|
| 239 |
def _minck_rule(self, context: Dict) -> Dict:
|
| 240 |
"""قانون سیم مینک"""
|
|
|
|
| 247 |
if context.get('configuration') == 'عبوری':
|
| 248 |
return {'pole_capacity': 400}
|
| 249 |
return {}
|
| 250 |
+
|
| 251 |
+
def _road_type_rule(self, context: Dict) -> Dict:
|
| 252 |
+
"""قانون نوع معبر"""
|
| 253 |
+
if context.get('road_type') == 'خاکی':
|
| 254 |
+
return {'length_coefficient': 1.2}
|
| 255 |
+
elif context.get('road_type') == 'اسفالت':
|
| 256 |
+
return {'length_coefficient': 0.9}
|
| 257 |
+
return {}
|
| 258 |
|
| 259 |
+
# نمونه اصلی برنامه
|
| 260 |
estimator = ElectricPoleEstimator()
|
| 261 |
|
| 262 |
# رابط کاربری Gradio
|
| 263 |
+
with gr.Blocks(title="سیستم هوشمند برآورد مصالح تاسیسات برقی", css=".gradio-container {direction: rtl}") as demo:
|
| 264 |
+
gr.Markdown("## 🏗️ سیستم هوشمند برآورد مصالح تاسیسات برقی")
|
| 265 |
|
| 266 |
+
with gr.Tab("📤 بارگذاری دادهها"):
|
| 267 |
gr.Markdown("### بارگذاری فایل اکسل جدید")
|
| 268 |
+
file_input = gr.File(label="فایل اکسل برآورد", file_types=[".xlsx"])
|
| 269 |
+
upload_btn = gr.Button("بارگذاری و ذخیره در دیتابیس", variant="primary")
|
| 270 |
upload_output = gr.Textbox(label="نتایج بارگذاری")
|
| 271 |
upload_btn.click(estimator.add_materials, inputs=file_input, outputs=upload_output)
|
| 272 |
+
|
| 273 |
+
gr.Markdown("### محتوای فعلی دیتابیس")
|
| 274 |
+
db_viewer = gr.Dataframe(
|
| 275 |
+
headers=["کد", "عنوان", "واحد", "شرایط"],
|
| 276 |
+
datatype=["str", "str", "str", "str"],
|
| 277 |
+
interactive=False
|
| 278 |
+
)
|
| 279 |
+
refresh_btn = gr.Button("بروزرسانی نمایش")
|
| 280 |
+
refresh_btn.click(
|
| 281 |
+
lambda: [{"کد": x["code"], "عنوان": x["title"], "واحد": x["unit"],
|
| 282 |
+
"شرایط": estimator._format_conditions(x, {})} for x in estimator.db],
|
| 283 |
+
outputs=db_viewer
|
| 284 |
+
)
|
| 285 |
+
|
| 286 |
+
with gr.Tab("📝 ورود متنی پروژه"):
|
| 287 |
+
gr.Markdown("### توضیحات کامل پروژه را وارد کنید")
|
| 288 |
+
project_desc = gr.Textbox(label="مثال: نصب ترانس 75 کیلوولت با کابلکشی 20 متری در معبر خاکی")
|
| 289 |
+
text_submit = gr.Button("محاسبه برآورد", variant="primary")
|
| 290 |
+
|
| 291 |
+
gr.Markdown("### ویژگیهای استخراج شده")
|
| 292 |
+
features_output = gr.JSON(label="")
|
| 293 |
+
|
| 294 |
+
gr.Markdown("### لیست مصالح مورد نیاز")
|
| 295 |
+
estimates_output = gr.Dataframe(
|
| 296 |
+
headers=["کد", "عنوان", "مقدار", "واحد"],
|
| 297 |
+
datatype=["str", "str", "number", "str"]
|
| 298 |
+
)
|
| 299 |
+
|
| 300 |
+
text_submit.click(
|
| 301 |
+
estimator.estimate_from_text,
|
| 302 |
+
inputs=project_desc,
|
| 303 |
+
outputs=[features_output, estimates_output]
|
| 304 |
+
)
|
| 305 |
|
| 306 |
+
with gr.Tab("⚙️ ورود پارامتری"):
|
| 307 |
with gr.Row():
|
| 308 |
height = gr.Number(label="ارتفاع پایه (متر)", value=12)
|
| 309 |
capacity = gr.Number(label="توان پایه (kVA)", value=600)
|
|
|
|
| 317 |
choices=["", "عبوری", "انتهایی", "زانویی"],
|
| 318 |
value=""
|
| 319 |
)
|
| 320 |
+
param_submit = gr.Button("محاسبه برآورد", variant="primary")
|
| 321 |
|
| 322 |
+
param_output = gr.Dataframe(
|
| 323 |
+
headers=["کد", "عنوان", "مقدار", "واحد"],
|
| 324 |
+
datatype=["str", "str", "number", "str"]
|
|
|
|
| 325 |
)
|
| 326 |
|
| 327 |
+
param_submit.click(
|
| 328 |
estimator.estimate,
|
| 329 |
inputs=[height, capacity, conductor, config],
|
| 330 |
+
outputs=param_output
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 331 |
)
|
| 332 |
|
| 333 |
if __name__ == "__main__":
|