Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -1,439 +1,56 @@
|
|
1 |
-
import streamlit as st
|
2 |
import pandas as pd
|
|
|
3 |
import folium
|
4 |
from streamlit_folium import folium_static
|
5 |
-
import jdatetime
|
6 |
-
import plotly.express as px
|
7 |
-
from folium.plugins import HeatMap, Fullscreen, Search
|
8 |
-
import branca.colormap as cm
|
9 |
-
from datetime import datetime
|
10 |
-
import base64
|
11 |
-
|
12 |
-
# تنظیمات اولیه صفحه
|
13 |
-
st.set_page_config(
|
14 |
-
page_title="مدیریت چاهکهای مزارع نیشکر",
|
15 |
-
page_icon="🌱",
|
16 |
-
layout="wide",
|
17 |
-
initial_sidebar_state="expanded"
|
18 |
-
)
|
19 |
-
|
20 |
-
# CSS برای ظاهر جذاب و متحرک
|
21 |
-
st.markdown(
|
22 |
-
"""
|
23 |
-
<style>
|
24 |
-
@import url('https://fonts.googleapis.com/css2?family=Vazirmatn:wght@400;700&display=swap');
|
25 |
-
|
26 |
-
* {
|
27 |
-
font-family: 'Vazirmatn', sans-serif !important;
|
28 |
-
}
|
29 |
-
|
30 |
-
.css-1d391kg {
|
31 |
-
direction: rtl;
|
32 |
-
}
|
33 |
-
|
34 |
-
.stButton>button {
|
35 |
-
float: right;
|
36 |
-
background: linear-gradient(45deg, #1CB5E0 0%, #000851 100%);
|
37 |
-
color: white;
|
38 |
-
transition: all 0.3s ease;
|
39 |
-
}
|
40 |
-
|
41 |
-
.stButton>button:hover {
|
42 |
-
transform: translateY(-2px);
|
43 |
-
box-shadow: 0 5px 15px rgba(0,0,0,0.2);
|
44 |
-
}
|
45 |
-
|
46 |
-
.css-1y4p8pa {
|
47 |
-
padding: 2rem;
|
48 |
-
border-radius: 15px;
|
49 |
-
background: rgba(255,255,255,0.95);
|
50 |
-
box-shadow: 0 8px 32px 0 rgba(31,38,135,0.37);
|
51 |
-
backdrop-filter: blur(4px);
|
52 |
-
margin: 1rem 0;
|
53 |
-
}
|
54 |
-
|
55 |
-
.css-1v0mbdj {
|
56 |
-
border-radius: 15px;
|
57 |
-
box-shadow: 0 4px 12px rgba(0,0,0,0.1);
|
58 |
-
transition: all 0.3s ease;
|
59 |
-
}
|
60 |
-
|
61 |
-
.css-1v0mbdj:hover {
|
62 |
-
transform: translateY(-3px);
|
63 |
-
box-shadow: 0 6px 15px rgba(0,0,0,0.2);
|
64 |
-
}
|
65 |
-
|
66 |
-
/* انیمیشن برای عناوین */
|
67 |
-
@keyframes slideIn {
|
68 |
-
from {
|
69 |
-
transform: translateX(50px);
|
70 |
-
opacity: 0;
|
71 |
-
}
|
72 |
-
to {
|
73 |
-
transform: translateX(0);
|
74 |
-
opacity: 1;
|
75 |
-
}
|
76 |
-
}
|
77 |
-
|
78 |
-
h1, h2, h3 {
|
79 |
-
animation: slideIn 0.5s ease-out;
|
80 |
-
}
|
81 |
-
|
82 |
-
/* استایل برای کارتهای آمار */
|
83 |
-
.metric-card {
|
84 |
-
background: linear-gradient(135deg, #00B4DB 0%, #0083B0 100%);
|
85 |
-
color: white;
|
86 |
-
padding: 20px;
|
87 |
-
border-radius: 10px;
|
88 |
-
text-align: center;
|
89 |
-
transition: all 0.3s ease;
|
90 |
-
}
|
91 |
-
|
92 |
-
.metric-card:hover {
|
93 |
-
transform: scale(1.05);
|
94 |
-
}
|
95 |
-
</style>
|
96 |
-
""",
|
97 |
-
unsafe_allow_html=True
|
98 |
-
)
|
99 |
-
|
100 |
-
# تعریف دادههای اولیه با چاهک نصب شده
|
101 |
-
@st.cache_data
|
102 |
-
def load_initial_data():
|
103 |
-
data = {
|
104 |
-
'مزرعه': ['06-10', '10-15', '12-27', '24-04', '22-21', '20-05', '14-21', '14-19', '14-24', '14-18', '22-17', '16-13', '16-27', '02-19', '02-27', '17-02', '15-22', '15-12', '15-04', '23-07'],
|
105 |
-
'کانال': ['06', '10', '12', '24', '22', '20', '14', '14', '14', '14', '22', '16', '16', '02', '02', '17', '15', '15', '15', '23'],
|
106 |
-
'چاهک_1_نصب': [True] * 20,
|
107 |
-
'چاهک_1_تکنسین': ['علی دغاغله', 'علی دغاغله', 'علی دغاغله', 'مسعود بن موسی', 'مسعود بن موسی', 'مسعود بن موسی',
|
108 |
-
'علی دغاغله', 'علی دغاغله', 'مسعود بن موسی', 'علی دغاغله', 'مسعود بن موسی', 'علی دغاغله',
|
109 |
-
'مسعود بن موسی', 'مسعود بن موسی', 'مسعود بن موسی', 'علی دغاغله', 'علی دغاغله', 'علی دغاغله',
|
110 |
-
'علی دغاغله', 'علی دغاغله'],
|
111 |
-
'چاهک_1_تاریخ': ['1404/01/10', '1404/01/09', '1404/01/08', '1404/01/12', '1404/01/12', '1404/01/11',
|
112 |
-
'1404/01/10', '1404/01/09', '1404/01/11', '1404/01/09', '1404/01/10', '1404/01/12',
|
113 |
-
'1404/01/12', '1404/01/16', '1404/01/16', '1404/01/16', '1404/01/16', '1404/01/16',
|
114 |
-
'1404/01/16', '1404/01/16'],
|
115 |
-
'چاهک_1_lat': [31.578944, 31.551778, 31.535056, 31.446083, 31.459917, 31.459861, 31.516472, 31.515722,
|
116 |
-
31.525056, 31.525472, 31.458528, 31.496722, 31.498083, 31.597933, 31.600053, 31.494345,
|
117 |
-
31.510917, 31.512250, 31.513139, 31.448096],
|
118 |
-
'چاهک_1_lon': [48.731222, 48.721556, 48.703139, 48.713444, 48.703972, 48.722472, 48.707083, 48.711778,
|
119 |
-
48.707583, 48.713778, 48.706861, 48.715639, 48.698889, 48.721920, 48.711327, 48.737393,
|
120 |
-
48.766361, 48.750944, 48.740556, 48.738048],
|
121 |
-
'چاهک_2_نصب': [False] * 20,
|
122 |
-
'چاهک_2_تکنسین': [''] * 20,
|
123 |
-
'چاهک_2_تاریخ': [''] * 20,
|
124 |
-
'چاهک_2_lat': [0.0] * 20,
|
125 |
-
'چاهک_2_lon': [0.0] * 20,
|
126 |
-
'اداره': [1] * 20, # Placeholder value
|
127 |
-
'واریته': ['CP69'] * 20, # Placeholder value
|
128 |
-
'مساحت': [24.0] * 20, # Placeholder value
|
129 |
-
}
|
130 |
-
return pd.DataFrame(data)
|
131 |
-
|
132 |
-
# لود دادهها
|
133 |
-
if 'farms_data' not in st.session_state:
|
134 |
-
st.session_state.farms_data = load_initial_data()
|
135 |
-
|
136 |
-
# تعریف تکنسینها
|
137 |
-
TECHNICIANS = [
|
138 |
-
'علی دغاغله',
|
139 |
-
'علیرضا حمیدی',
|
140 |
-
'مسعود بن موسی',
|
141 |
-
'امین هنری'
|
142 |
-
]
|
143 |
-
|
144 |
-
# عنوان اصلی با افکت گرادیان
|
145 |
-
st.markdown(
|
146 |
-
"""
|
147 |
-
<h1 style='text-align: center; color: #0083B0; background: -webkit-linear-gradient(45deg, #1CB5E0, #000851);
|
148 |
-
-webkit-background-clip: text; -webkit-text-fill-color: transparent; padding: 20px;'>
|
149 |
-
🌱 سامانه مدیریت چاهکهای مزارع نیشکر
|
150 |
-
</h1>
|
151 |
-
""",
|
152 |
-
unsafe_allow_html=True
|
153 |
-
)
|
154 |
-
|
155 |
-
# سایدبار با استایل جدید
|
156 |
-
with st.sidebar:
|
157 |
-
st.markdown(
|
158 |
-
"""
|
159 |
-
<div style='background: linear-gradient(45deg, #1CB5E0 0%, #000851 100%); padding: 20px; border-radius: 10px; color: white;'>
|
160 |
-
<h2 style='text-align: center; margin: 0;'>🔍 فیلترها</h2>
|
161 |
-
</div>
|
162 |
-
""",
|
163 |
-
unsafe_allow_html=True
|
164 |
-
)
|
165 |
-
selected_department = st.selectbox(
|
166 |
-
"انتخاب اداره",
|
167 |
-
options=[0, 1, 2, 3, 4],
|
168 |
-
format_func=lambda x: "همه ادارات" if x == 0 else f"اداره {x}",
|
169 |
-
)
|
170 |
-
|
171 |
-
search_term = st.text_input("جستجو بر اساس نام مزرعه یا کانال")
|
172 |
-
|
173 |
-
# فیلتر کردن دادهها
|
174 |
-
filtered_data = st.session_state.farms_data.copy()
|
175 |
-
if selected_department != 0:
|
176 |
-
filtered_data = filtered_data[filtered_data['اداره'] == selected_department]
|
177 |
-
if search_term:
|
178 |
-
mask = (filtered_data['مزرعه'].str.contains(search_term)) | (filtered_data['کانال'].str.contains(search_term))
|
179 |
-
filtered_data = filtered_data[mask]
|
180 |
-
|
181 |
-
# نمایش آمار کلی با کارتهای متحرک
|
182 |
-
col1, col2, col3 = st.columns(3)
|
183 |
-
with col1:
|
184 |
-
st.markdown(
|
185 |
-
f"""
|
186 |
-
<div class='metric-card'>
|
187 |
-
<h2>{len(filtered_data) * 2}</h2>
|
188 |
-
<p>کل چاهکها</p>
|
189 |
-
</div>
|
190 |
-
""",
|
191 |
-
unsafe_allow_html=True
|
192 |
-
)
|
193 |
-
|
194 |
-
with col2:
|
195 |
-
installed_wells = filtered_data['چاهک_1_نصب'].sum() + filtered_data['چاهک_2_نصب'].sum()
|
196 |
-
st.markdown(
|
197 |
-
f"""
|
198 |
-
<div class='metric-card' style='background: linear-gradient(135deg, #00B09B 0%, #96C93D 100%);'>
|
199 |
-
<h2>{installed_wells}</h2>
|
200 |
-
<p>چاهکهای نصب شده</p>
|
201 |
-
</div>
|
202 |
-
""",
|
203 |
-
unsafe_allow_html=True
|
204 |
-
)
|
205 |
-
|
206 |
-
with col3:
|
207 |
-
st.markdown(
|
208 |
-
f"""
|
209 |
-
<div class='metric-card' style='background: linear-gradient(135deg, #FF416C 0%, #FF4B2B 100%);'>
|
210 |
-
<h2>{len(filtered_data) * 2 - installed_wells}</h2>
|
211 |
-
<p>چاهکهای باقیمانده</p>
|
212 |
-
</div>
|
213 |
-
""",
|
214 |
-
unsafe_allow_html=True
|
215 |
-
)
|
216 |
-
|
217 |
-
# نمایش نقشه با تصویر ماهوارهای
|
218 |
-
st.markdown(
|
219 |
-
"""
|
220 |
-
<h2 style='text-align: right; color: #0083B0;'>🗺️ نقشه چاهکها</h2>
|
221 |
-
""",
|
222 |
-
unsafe_allow_html=True
|
223 |
-
)
|
224 |
|
225 |
-
#
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
#
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
.
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
|
271 |
-
</h4>
|
272 |
-
<div style='margin-top: 10px;'>
|
273 |
-
<p style='margin: 5px 0;'><strong>👨🌾 تکنسین:</strong> {row['چاهک_1_تکنسین']}</p>
|
274 |
-
<p style='margin: 5px 0;'><strong>📅 تاریخ نصب:</strong> {row['چاهک_1_تاریخ']}</p>
|
275 |
-
<p style='margin: 5px 0;'><strong>📍 موقعیت:</strong></p>
|
276 |
-
<p style='margin: 5px 0; direction: ltr;'>{row['چاهک_1_lat']:.6f}°N, {row['چاهک_1_lon']:.6f}°E</p>
|
277 |
-
</div>
|
278 |
-
</div>
|
279 |
-
"""
|
280 |
-
|
281 |
-
folium.CircleMarker(
|
282 |
-
location=[row['چاهک_1_lat'], row['چاهک_1_lon']],
|
283 |
-
radius=8,
|
284 |
-
popup=folium.Popup(popup_html, max_width=300),
|
285 |
-
color='#0083B0',
|
286 |
-
fill=True,
|
287 |
-
fill_color='#0083B0',
|
288 |
-
fill_opacity=0.7,
|
289 |
-
weight=2,
|
290 |
-
className='pulsing-marker'
|
291 |
).add_to(m)
|
292 |
-
|
293 |
-
if row['چاهک_2_نصب'] and row['چاهک_2_lat'] != 0:
|
294 |
-
popup_html = f"""
|
295 |
-
<div style='direction: rtl; text-align: right; padding: 10px;'>
|
296 |
-
<h4 style='color: #FF416C; margin: 0;'>مزرعه {row['مزرعه']}</h4>
|
297 |
-
<p><strong>چاهک:</strong> 2</p>
|
298 |
-
<p><strong>تکنسین:</strong> {row['چاهک_2_تکنسین']}</p>
|
299 |
-
<p><strong>تاریخ نصب:</strong> {row['چاهک_2_تاریخ']}</p>
|
300 |
-
<p><strong>موقعیت:</strong> {row['چاهک_2_lat']:.6f}°N, {row['چاهک_2_lon']:.6f}°E</p>
|
301 |
-
</div>
|
302 |
-
"""
|
303 |
-
|
304 |
-
folium.CircleMarker(
|
305 |
-
location=[row['چاهک_2_lat'], row['چاهک_2_lon']],
|
306 |
-
radius=10,
|
307 |
-
popup=folium.Popup(popup_html, max_width=300),
|
308 |
-
color='#FF416C',
|
309 |
-
fill=True,
|
310 |
-
fill_color='#FF416C',
|
311 |
-
fill_opacity=0.7,
|
312 |
-
weight=2,
|
313 |
-
className='pulsing-marker'
|
314 |
-
).add_to(m)
|
315 |
-
|
316 |
-
# نمایش نقشه با اندازه بزرگتر
|
317 |
-
folium_static(m, width=1200, height=600)
|
318 |
-
|
319 |
-
# لیست مزارع و ثبت چاهک با ظاهر جدید
|
320 |
-
st.markdown(
|
321 |
-
"""
|
322 |
-
<h2 style='text-align: right; color: #0083B0;'>📝 لیست مزارع و ثبت چاهک</h2>
|
323 |
-
""",
|
324 |
-
unsafe_allow_html=True
|
325 |
-
)
|
326 |
-
|
327 |
-
for idx, row in filtered_data.iterrows():
|
328 |
-
with st.expander(f"🌾 مزرعه {row['مزرعه']} - کانال {row['کانال']}", expanded=False):
|
329 |
-
st.markdown(
|
330 |
-
f"""
|
331 |
-
<div style='background: linear-gradient(135deg, #f6f9fc 0%, #f0f4f8 100%); padding: 15px; border-radius: 10px;'>
|
332 |
-
<p><strong>واریته:</strong> {row['واریته']}</p>
|
333 |
-
<p><strong>مساحت:</strong> {row['مساحت']} هکتار</p>
|
334 |
-
</div>
|
335 |
-
""",
|
336 |
-
unsafe_allow_html=True
|
337 |
-
)
|
338 |
-
|
339 |
-
col1, col2 = st.columns(2)
|
340 |
-
|
341 |
-
# چاهک 1
|
342 |
-
with col1:
|
343 |
-
st.markdown("<h3 style='color: #0083B0;'>چاهک 1</h3>", unsafe_allow_html=True)
|
344 |
-
if not row['چاهک_1_نصب']:
|
345 |
-
if st.button(f"ثبت نصب چاهک 1 - مزرعه {row['مزرعه']}", key=f"well1_{idx}"):
|
346 |
-
technician = st.selectbox(
|
347 |
-
"انتخاب تکنسین",
|
348 |
-
options=TECHNICIANS,
|
349 |
-
key=f"tech1_{idx}"
|
350 |
-
)
|
351 |
-
lat = st.number_input("عرض جغرافیایی", value=31.504, key=f"lat1_{idx}")
|
352 |
-
lon = st.number_input("طول جغرافیایی", value=48.752, key=f"lon1_{idx}")
|
353 |
-
if st.button("ثبت نهایی", key=f"save1_{idx}"):
|
354 |
-
st.session_state.farms_data.at[idx, 'چاهک_1_نصب'] = True
|
355 |
-
st.session_state.farms_data.at[idx, 'چاهک_1_تکنسین'] = technician
|
356 |
-
st.session_state.farms_data.at[idx, 'چاهک_1_تاریخ'] = jdatetime.datetime.now().strftime("%Y/%m/%d")
|
357 |
-
st.session_state.farms_data.at[idx, 'چاهک_1_lat'] = lat
|
358 |
-
st.session_state.farms_data.at[idx, 'چاهک_1_lon'] = lon
|
359 |
-
st.success("چاهک 1 با موفقیت ثبت شد")
|
360 |
-
st.rerun()
|
361 |
-
else:
|
362 |
-
st.markdown(
|
363 |
-
f"""
|
364 |
-
<div style='background: #e3f2fd; padding: 15px; border-radius: 10px;'>
|
365 |
-
<p>✅ نصب شده توسط {row['چاهک_1_تکنسین']}</p>
|
366 |
-
<p>📅 تاریخ نصب: {row['چاهک_1_تاریخ']}</p>
|
367 |
-
<p>📍 موقعیت: {row['چاهک_1_lat']:.6f}°N, {row['چاهک_1_lon']:.6f}°E</p>
|
368 |
-
</div>
|
369 |
-
""",
|
370 |
-
unsafe_allow_html=True
|
371 |
-
)
|
372 |
-
|
373 |
-
# چاهک 2 (مشابه چاهک 1)
|
374 |
-
with col2:
|
375 |
-
st.markdown("<h3 style='color: #FF416C;'>چاهک 2</h3>", unsafe_allow_html=True)
|
376 |
-
if not row['چاهک_2_نصب']:
|
377 |
-
if st.button(f"ثبت نصب چاهک 2 - مزرعه {row['مزرعه']}", key=f"well2_{idx}"):
|
378 |
-
technician = st.selectbox(
|
379 |
-
"انتخاب تکنسین",
|
380 |
-
options=TECHNICIANS,
|
381 |
-
key=f"tech2_{idx}"
|
382 |
-
)
|
383 |
-
lat = st.number_input("عرض جغرافیایی", value=31.504, key=f"lat2_{idx}")
|
384 |
-
lon = st.number_input("طول جغرافیایی", value=48.752, key=f"lon2_{idx}")
|
385 |
-
if st.button("ثبت نهایی", key=f"save2_{idx}"):
|
386 |
-
st.session_state.farms_data.at[idx, 'چاهک_2_نصب'] = True
|
387 |
-
st.session_state.farms_data.at[idx, 'چاهک_2_تکنسین'] = technician
|
388 |
-
st.session_state.farms_data.at[idx, 'چاهک_2_تاریخ'] = jdatetime.datetime.now().strftime("%Y/%m/%d")
|
389 |
-
st.session_state.farms_data.at[idx, 'چاهک_2_lat'] = lat
|
390 |
-
st.session_state.farms_data.at[idx, 'چاهک_2_lon'] = lon
|
391 |
-
st.success("چاهک 2 با موفقیت ثبت شد")
|
392 |
-
st.rerun()
|
393 |
-
else:
|
394 |
-
st.markdown(
|
395 |
-
f"""
|
396 |
-
<div style='background: #ffe0e6; padding: 15px; border-radius: 10px;'>
|
397 |
-
<p>✅ نصب شده توسط {row['چاهک_2_تکنسین']}</p>
|
398 |
-
<p>📅 تاریخ نصب: {row['چاهک_2_تاریخ']}</p>
|
399 |
-
<p>📍 موقعیت: {row['چاهک_2_lat']:.6f}°N, {row['چاهک_2_lon']:.6f}°E</p>
|
400 |
-
</div>
|
401 |
-
""",
|
402 |
-
unsafe_allow_html=True
|
403 |
-
)
|
404 |
-
|
405 |
-
# نمودار پیشرفت نصب به تفکیک اداره
|
406 |
-
st.markdown(
|
407 |
-
"""
|
408 |
-
<h2 style='text-align: right; color: #0083B0;'>📊 گزارش پیشرفت نصب</h2>
|
409 |
-
""",
|
410 |
-
unsafe_allow_html=True
|
411 |
-
)
|
412 |
-
|
413 |
-
progress_data = []
|
414 |
-
for dept in range(1, 5):
|
415 |
-
dept_data = st.session_state.farms_data[st.session_state.farms_data['اداره'] == dept]
|
416 |
-
total = len(dept_data) * 2
|
417 |
-
installed = dept_data['چاهک_1_نصب'].sum() + dept_data['چاهک_2_نصب'].sum()
|
418 |
-
progress_data.append({
|
419 |
-
'اداره': f'اداره {dept}',
|
420 |
-
'درصد پیشرفت': (installed / total * 100) if total > 0 else 0
|
421 |
-
})
|
422 |
|
423 |
-
|
424 |
-
|
425 |
-
|
426 |
-
x='اداره',
|
427 |
-
y='درصد پیشرفت',
|
428 |
-
title='درصد پیشرفت نصب چاهکها به تفکیک اداره',
|
429 |
-
color='درصد پیشرفت',
|
430 |
-
color_continuous_scale='Viridis',
|
431 |
-
template='plotly_white'
|
432 |
-
)
|
433 |
-
fig.update_layout(
|
434 |
-
plot_bgcolor='rgba(0,0,0,0)',
|
435 |
-
paper_bgcolor='rgba(0,0,0,0)',
|
436 |
-
font_family='Vazirmatn',
|
437 |
-
title_x=0.5
|
438 |
-
)
|
439 |
-
st.plotly_chart(fig, use_container_width=True)
|
|
|
|
|
1 |
import pandas as pd
|
2 |
+
import streamlit as st
|
3 |
import folium
|
4 |
from streamlit_folium import folium_static
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
5 |
|
6 |
+
# خواندن دادهها
|
7 |
+
df_representative = pd.read_csv('مزارع نماینده راتون.csv')
|
8 |
+
df_coordinates = pd.read_csv('مختصات و مشخصات کامل مزارع (4).csv')
|
9 |
+
|
10 |
+
# استخراج لیست مزارع نماینده
|
11 |
+
representatives = df_representative['مزرعه نماینده'].unique().tolist()
|
12 |
+
|
13 |
+
# دیکشنری برای نگاشت مزرعه نماینده به زیرمجموعهها
|
14 |
+
sub_farms_dict = df_representative.groupby('مزرعه نماینده')['زیر مجموعه'].apply(list).to_dict()
|
15 |
+
|
16 |
+
# رابط کاربری
|
17 |
+
st.title('داشبورد پایش هفتگی مزارع نماینده')
|
18 |
+
selected_representative = st.selectbox('انتخاب مزرعه نماینده', representatives)
|
19 |
+
|
20 |
+
if selected_representative:
|
21 |
+
# نمایش زیرمجموعهها
|
22 |
+
sub_farms = sub_farms_dict[selected_representative]
|
23 |
+
st.write('**زیرمجموعههای مزرعه انتخاب شده:**', sub_farms)
|
24 |
+
|
25 |
+
# استخراج مختصات مزرعه نماینده
|
26 |
+
rep_coords = df_coordinates[df_coordinates['مزرعه'] == selected_representative][['عرض جغرافیایی', 'طول جغرافیایی]].values
|
27 |
+
if len(rep_coords) > 0:
|
28 |
+
rep_lat, rep_lon = rep_coords[0]
|
29 |
+
else:
|
30 |
+
st.error('مختصات مزرعه نماینده یافت نشد!')
|
31 |
+
st.stop()
|
32 |
+
|
33 |
+
# استخراج مختصات زیرمجموعهها
|
34 |
+
sub_coords = df_coordinates[df_coordinates['مزرعه'].isin(sub_farms)][['عرض جغرافیایی', 'طول جغرافیایی', 'مزرعه']]
|
35 |
+
|
36 |
+
# ایجاد نقشه
|
37 |
+
m = folium.Map(location=[rep_lat, rep_lon], zoom_start=10, tiles='Satellite')
|
38 |
+
|
39 |
+
# مارکر مزرعه نماینده
|
40 |
+
folium.Marker(
|
41 |
+
[rep_lat, rep_lon],
|
42 |
+
popup=selected_representative,
|
43 |
+
icon=folium.Icon(color='blue', icon='info-sign')
|
44 |
+
).add_to(m)
|
45 |
+
|
46 |
+
# مارکرهای زیرمجموعهها
|
47 |
+
for idx, row in sub_coords.iterrows():
|
48 |
+
folium.Marker(
|
49 |
+
[row['عرض جغرافیایی'], row['طول جغرافیایی']],
|
50 |
+
popup=row['مزرعه'],
|
51 |
+
icon=folium.Icon(color='red', icon='info-sign')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
52 |
).add_to(m)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
53 |
|
54 |
+
# نمایش نقشه
|
55 |
+
st.write('**نقشه مزرعه و زیرمجموعهها:**')
|
56 |
+
folium_static(m)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|