Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -96,7 +96,7 @@ def plot_routes_on_folium_map(G, route1, route2, start_point, end_point):
|
|
| 96 |
print("✅ Вспомогательные функции готовы.")
|
| 97 |
|
| 98 |
# ==============================================================================
|
| 99 |
-
# ШАГ 5: ГЛАВНАЯ ФУНКЦИЯ И ИНТЕРФЕЙС GRADIO
|
| 100 |
# ==============================================================================
|
| 101 |
print("\n🚀 Шаг 5: Настройка и запуск веб-интерфейса Gradio...")
|
| 102 |
|
|
@@ -104,7 +104,6 @@ geolocator = Nominatim(user_agent="bishkek_navigator_app_v3")
|
|
| 104 |
geocode = RateLimiter(geolocator.geocode, min_delay_seconds=1)
|
| 105 |
|
| 106 |
def find_and_plot_routes_by_address(start_address, end_address, day_of_week, hour, minute):
|
| 107 |
-
# --- Начало блока: обработка ошибок и геокодирование (без изменений) ---
|
| 108 |
if not start_address or not end_address: return None, "<h3>Ошибка</h3><p>Пожалуйста, введите оба адреса.</p>"
|
| 109 |
if hour is None or minute is None: return None, "<h3>Ошибка</h3><p>Пожалуйста, установите значения для часа и минуты.</p>"
|
| 110 |
try:
|
|
@@ -121,8 +120,7 @@ def find_and_plot_routes_by_address(start_address, end_address, day_of_week, hou
|
|
| 121 |
r1, t1, r2, t2 = find_two_routes(G, start_node, end_node, weight='travel_time')
|
| 122 |
if r1 is None: return None, "<h3>Ошибка</h3><p>Не удалось построить маршрут.</p>"
|
| 123 |
|
| 124 |
-
|
| 125 |
-
SIGNAL_DELAY_SECONDS = 30
|
| 126 |
signals_on_route1 = sum(1 for node in r1 if node in signal_nodes_set); t1_total = t1 + signals_on_route1 * SIGNAL_DELAY_SECONDS
|
| 127 |
distance1_km = sum(G[u][v][0]['length'] for u, v in zip(r1[:-1], r1[1:])) / 1000
|
| 128 |
t1_min_total = t1_total / 60
|
|
@@ -135,9 +133,6 @@ def find_and_plot_routes_by_address(start_address, end_address, day_of_week, hou
|
|
| 135 |
|
| 136 |
final_map = plot_routes_on_folium_map(G, r1, r2, start_point, end_point)
|
| 137 |
|
| 138 |
-
# --- НОВЫЙ БЛОК: ФОРМИРОВАНИЕ КРАСИВОГО HTML ВЫВОДА ---
|
| 139 |
-
|
| 140 |
-
# 1. Определяем стили для карточек
|
| 141 |
css_styles = """
|
| 142 |
<style>
|
| 143 |
.container { display: flex; flex-wrap: wrap; gap: 20px; font-family: sans-serif; }
|
|
@@ -150,8 +145,6 @@ def find_and_plot_routes_by_address(start_address, end_address, day_of_week, hou
|
|
| 150 |
.card .value { font-size: 1.1em; color: #000; font-weight: 500;}
|
| 151 |
</style>
|
| 152 |
"""
|
| 153 |
-
|
| 154 |
-
# 2. Формируем HTML для первой карточки
|
| 155 |
card1_html = f"""
|
| 156 |
<div class="card">
|
| 157 |
<h3>Маршрут 1 (зеленый)</h3>
|
|
@@ -162,8 +155,6 @@ def find_and_plot_routes_by_address(start_address, end_address, day_of_week, hou
|
|
| 162 |
</ul>
|
| 163 |
</div>
|
| 164 |
"""
|
| 165 |
-
|
| 166 |
-
# 3. Формируем HTML для второй карточки, если она есть
|
| 167 |
card2_html = ""
|
| 168 |
if t2_total is not None:
|
| 169 |
card2_html = f"""
|
|
@@ -176,33 +167,31 @@ def find_and_plot_routes_by_address(start_address, end_address, day_of_week, hou
|
|
| 176 |
</ul>
|
| 177 |
</div>
|
| 178 |
"""
|
| 179 |
-
|
| 180 |
-
# 4. Собираем все вместе
|
| 181 |
final_html_output = f"{css_styles}<div class='container'>{card1_html}{card2_html}</div>"
|
| 182 |
-
|
| 183 |
return final_map._repr_html_(), final_html_output
|
| 184 |
|
| 185 |
except Exception as e:
|
| 186 |
return None, f"<h3>Произошла внутренняя ошибка</h3><p>{e}</p>"
|
| 187 |
|
| 188 |
-
# ---
|
| 189 |
-
|
|
|
|
|
|
|
| 190 |
gr.Markdown("# 🗺️ Умный навигатор по Бишкеку")
|
| 191 |
with gr.Row():
|
| 192 |
with gr.Column(scale=1):
|
| 193 |
-
start_address_input = gr.Textbox(label="Откуда?", placeholder="Например, 7 микрорайон")
|
| 194 |
end_address_input = gr.Textbox(label="Куда?", placeholder="Например, Ошский базар")
|
| 195 |
day_dropdown = gr.Dropdown(label="День недели", choices=["Понедельник", "Вторник", "Среда", "Четверг", "Пятница", "Суббота", "Воскресенье"], value="Понедельник", type="index")
|
| 196 |
hour_slider = gr.Slider(label="Час", minimum=0, maximum=23, step=1, value=8)
|
| 197 |
minute_slider = gr.Slider(label="Минута", minimum=0, maximum=59, step=1, value=30)
|
| 198 |
build_btn = gr.Button("🚀 Построить маршруты", variant="primary")
|
| 199 |
-
|
| 200 |
-
|
| 201 |
|
| 202 |
with gr.Column(scale=2):
|
| 203 |
output_map_html = gr.HTML(label="Карта с маршрутами")
|
| 204 |
|
| 205 |
-
# Обновляем `outputs` для соответствия новому компоненту
|
| 206 |
build_btn.click(
|
| 207 |
fn=find_and_plot_routes_by_address,
|
| 208 |
inputs=[start_address_input, end_address_input, day_dropdown, hour_slider, minute_slider],
|
|
|
|
| 96 |
print("✅ Вспомогательные функции готовы.")
|
| 97 |
|
| 98 |
# ==============================================================================
|
| 99 |
+
# ШАГ 5: ГЛАВНАЯ ФУНКЦИЯ И ИНТЕРФЕЙС GRADIO
|
| 100 |
# ==============================================================================
|
| 101 |
print("\n🚀 Шаг 5: Настройка и запуск веб-интерфейса Gradio...")
|
| 102 |
|
|
|
|
| 104 |
geocode = RateLimiter(geolocator.geocode, min_delay_seconds=1)
|
| 105 |
|
| 106 |
def find_and_plot_routes_by_address(start_address, end_address, day_of_week, hour, minute):
|
|
|
|
| 107 |
if not start_address or not end_address: return None, "<h3>Ошибка</h3><p>Пожалуйста, введите оба адреса.</p>"
|
| 108 |
if hour is None or minute is None: return None, "<h3>Ошибка</h3><p>Пожалуйста, установите значения для часа и минуты.</p>"
|
| 109 |
try:
|
|
|
|
| 120 |
r1, t1, r2, t2 = find_two_routes(G, start_node, end_node, weight='travel_time')
|
| 121 |
if r1 is None: return None, "<h3>Ошибка</h3><p>Не удалось построить маршрут.</p>"
|
| 122 |
|
| 123 |
+
SIGNAL_DELAY_SECONDS = 40
|
|
|
|
| 124 |
signals_on_route1 = sum(1 for node in r1 if node in signal_nodes_set); t1_total = t1 + signals_on_route1 * SIGNAL_DELAY_SECONDS
|
| 125 |
distance1_km = sum(G[u][v][0]['length'] for u, v in zip(r1[:-1], r1[1:])) / 1000
|
| 126 |
t1_min_total = t1_total / 60
|
|
|
|
| 133 |
|
| 134 |
final_map = plot_routes_on_folium_map(G, r1, r2, start_point, end_point)
|
| 135 |
|
|
|
|
|
|
|
|
|
|
| 136 |
css_styles = """
|
| 137 |
<style>
|
| 138 |
.container { display: flex; flex-wrap: wrap; gap: 20px; font-family: sans-serif; }
|
|
|
|
| 145 |
.card .value { font-size: 1.1em; color: #000; font-weight: 500;}
|
| 146 |
</style>
|
| 147 |
"""
|
|
|
|
|
|
|
| 148 |
card1_html = f"""
|
| 149 |
<div class="card">
|
| 150 |
<h3>Маршрут 1 (зеленый)</h3>
|
|
|
|
| 155 |
</ul>
|
| 156 |
</div>
|
| 157 |
"""
|
|
|
|
|
|
|
| 158 |
card2_html = ""
|
| 159 |
if t2_total is not None:
|
| 160 |
card2_html = f"""
|
|
|
|
| 167 |
</ul>
|
| 168 |
</div>
|
| 169 |
"""
|
|
|
|
|
|
|
| 170 |
final_html_output = f"{css_styles}<div class='container'>{card1_html}{card2_html}</div>"
|
|
|
|
| 171 |
return final_map._repr_html_(), final_html_output
|
| 172 |
|
| 173 |
except Exception as e:
|
| 174 |
return None, f"<h3>Произошла внутренняя ошибка</h3><p>{e}</p>"
|
| 175 |
|
| 176 |
+
# --- ИНТЕРФЕЙС GRADIO С ИСПРАВЛЕНИЕМ ТРЯСКИ ---
|
| 177 |
+
css_fix = """.results-container { min-height: 180px; }"""
|
| 178 |
+
|
| 179 |
+
with gr.Blocks(theme=gr.themes.Soft(), css=css_fix) as demo:
|
| 180 |
gr.Markdown("# 🗺️ Умный навигатор по Бишкеку")
|
| 181 |
with gr.Row():
|
| 182 |
with gr.Column(scale=1):
|
| 183 |
+
start_address_input = gr.Textbox(label="Откуда?", placeholder="Например, 7-й микрорайон")
|
| 184 |
end_address_input = gr.Textbox(label="Куда?", placeholder="Например, Ошский базар")
|
| 185 |
day_dropdown = gr.Dropdown(label="День недели", choices=["Понедельник", "Вторник", "Среда", "Четверг", "Пятница", "Суббота", "Воскресенье"], value="Понедельник", type="index")
|
| 186 |
hour_slider = gr.Slider(label="Час", minimum=0, maximum=23, step=1, value=8)
|
| 187 |
minute_slider = gr.Slider(label="Минута", minimum=0, maximum=59, step=1, value=30)
|
| 188 |
build_btn = gr.Button("🚀 Построить маршруты", variant="primary")
|
| 189 |
+
with gr.Box(elem_classes="results-container"):
|
| 190 |
+
output_info_html = gr.HTML(label="Информация о маршрутах")
|
| 191 |
|
| 192 |
with gr.Column(scale=2):
|
| 193 |
output_map_html = gr.HTML(label="Карта с маршрутами")
|
| 194 |
|
|
|
|
| 195 |
build_btn.click(
|
| 196 |
fn=find_and_plot_routes_by_address,
|
| 197 |
inputs=[start_address_input, end_address_input, day_dropdown, hour_slider, minute_slider],
|