Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -5,6 +5,9 @@ from datetime import datetime
|
|
| 5 |
from dateutil import parser
|
| 6 |
from io import BytesIO
|
| 7 |
from PIL import Image
|
|
|
|
|
|
|
|
|
|
| 8 |
|
| 9 |
# Russian translations for planets
|
| 10 |
planet_ru = {
|
|
@@ -18,15 +21,11 @@ planet_symbols = {
|
|
| 18 |
'Mars': '♂', 'Jupiter': '♃', 'Saturn': '♄'
|
| 19 |
}
|
| 20 |
|
| 21 |
-
#
|
| 22 |
-
|
| 23 |
-
|
| 24 |
-
dt = parser.parse(date_time_str)
|
| 25 |
-
return dt.isoformat()
|
| 26 |
-
except ValueError:
|
| 27 |
-
return None
|
| 28 |
|
| 29 |
-
#
|
| 30 |
def lon_to_sign(lon):
|
| 31 |
signs = ["Овен", "Телец", "Близнецы", "Рак", "Лев", "Дева",
|
| 32 |
"Весы", "Скорпион", "Стрелец", "Козерог", "Водолей", "Рыбы"]
|
|
@@ -35,7 +34,7 @@ def lon_to_sign(lon):
|
|
| 35 |
minutes = int((lon % 1) * 60)
|
| 36 |
return f"{signs[sign_index]} {degrees}°{minutes}'"
|
| 37 |
|
| 38 |
-
#
|
| 39 |
def PLadder_ZSizes(date_time_iso, lat, lon):
|
| 40 |
try:
|
| 41 |
dt = datetime.fromisoformat(date_time_iso)
|
|
@@ -84,7 +83,7 @@ def PLadder_ZSizes(date_time_iso, lat, lon):
|
|
| 84 |
except Exception as e:
|
| 85 |
return {"error": f"Ошибка: {str(e)}"}
|
| 86 |
|
| 87 |
-
#
|
| 88 |
def plot_pladder(PLadder):
|
| 89 |
fig, ax = plt.subplots()
|
| 90 |
ax.plot([0, 1.5, 3, 0], [0, 3, 0, 0], 'k-') # Triangle
|
|
@@ -99,27 +98,63 @@ def plot_pladder(PLadder):
|
|
| 99 |
ax.axis('off')
|
| 100 |
return fig
|
| 101 |
|
| 102 |
-
# Main interface function
|
| 103 |
-
def chat_interface(query
|
|
|
|
| 104 |
if not query.startswith("PLadder "):
|
| 105 |
-
return "Запрос должен начинаться с 'PLadder' и содержать
|
| 106 |
|
| 107 |
-
|
| 108 |
-
|
| 109 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 110 |
return "Неверный формат даты и времени.", None
|
| 111 |
|
| 112 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 113 |
if "error" in result:
|
| 114 |
return result["error"], None
|
| 115 |
|
|
|
|
| 116 |
PLadder = result["PLadder"]
|
| 117 |
ZSizes = result["ZSizes"]
|
| 118 |
longitudes = result["longitudes"]
|
| 119 |
|
|
|
|
| 120 |
planet_list = "\n".join([f"{planet_ru[p]}: {lon_to_sign(longitudes[p])}" for p in PLadder])
|
| 121 |
zones_text = "\n".join([f"Зона {i+1}: {size} ({cls})" for i, (size, cls) in enumerate(ZSizes)])
|
| 122 |
|
|
|
|
| 123 |
fig = plot_pladder(PLadder)
|
| 124 |
buf = BytesIO()
|
| 125 |
fig.savefig(buf, format='png', bbox_inches='tight')
|
|
@@ -127,26 +162,23 @@ def chat_interface(query, lat, lon):
|
|
| 127 |
img = Image.open(buf)
|
| 128 |
plt.close(fig)
|
| 129 |
|
|
|
|
| 130 |
text = f"Планетарная лестница:\n{planet_list}\n\nРазмеры зон:\n{zones_text}"
|
| 131 |
return text, img
|
| 132 |
|
| 133 |
-
# Gradio UI
|
| 134 |
with gr.Blocks() as interface:
|
|
|
|
|
|
|
| 135 |
with gr.Row():
|
| 136 |
with gr.Column(scale=2):
|
| 137 |
output_text = gr.Textbox(label="Ответ", lines=10)
|
| 138 |
with gr.Column(scale=1):
|
| 139 |
output_image = gr.Image(label="График планетарной лестницы")
|
| 140 |
-
with gr.Row():
|
| 141 |
-
with gr.Column(scale=1):
|
| 142 |
-
query_text = gr.Textbox(label="Запрос", placeholder="Пример: PLadder 2023-10-10 12:00")
|
| 143 |
-
location_lat = gr.Textbox(label="Широта", placeholder="Пример: 37.7749")
|
| 144 |
-
location_lon = gr.Textbox(label="Долгота", placeholder="Пример: -122.4194")
|
| 145 |
-
submit_button = gr.Button("Отправить")
|
| 146 |
|
| 147 |
submit_button.click(
|
| 148 |
fn=chat_interface,
|
| 149 |
-
inputs=
|
| 150 |
outputs=[output_text, output_image]
|
| 151 |
)
|
| 152 |
|
|
|
|
| 5 |
from dateutil import parser
|
| 6 |
from io import BytesIO
|
| 7 |
from PIL import Image
|
| 8 |
+
from geopy.geocoders import Nominatim
|
| 9 |
+
from timezonefinder import TimezoneFinder
|
| 10 |
+
import pytz
|
| 11 |
|
| 12 |
# Russian translations for planets
|
| 13 |
planet_ru = {
|
|
|
|
| 21 |
'Mars': '♂', 'Jupiter': '♃', 'Saturn': '♄'
|
| 22 |
}
|
| 23 |
|
| 24 |
+
# Initialize geolocator and timezone finder
|
| 25 |
+
geolocator = Nominatim(user_agent="pladder_app")
|
| 26 |
+
tf = TimezoneFinder()
|
|
|
|
|
|
|
|
|
|
|
|
|
| 27 |
|
| 28 |
+
# Function to convert longitude to zodiac sign and degrees
|
| 29 |
def lon_to_sign(lon):
|
| 30 |
signs = ["Овен", "Телец", "Близнецы", "Рак", "Лев", "Дева",
|
| 31 |
"Весы", "Скорпион", "Стрелец", "Козерог", "Водолей", "Рыбы"]
|
|
|
|
| 34 |
minutes = int((lon % 1) * 60)
|
| 35 |
return f"{signs[sign_index]} {degrees}°{minutes}'"
|
| 36 |
|
| 37 |
+
# Function to calculate PLadder and zone sizes (unchanged)
|
| 38 |
def PLadder_ZSizes(date_time_iso, lat, lon):
|
| 39 |
try:
|
| 40 |
dt = datetime.fromisoformat(date_time_iso)
|
|
|
|
| 83 |
except Exception as e:
|
| 84 |
return {"error": f"Ошибка: {str(e)}"}
|
| 85 |
|
| 86 |
+
# Function to plot the planetary ladder (unchanged)
|
| 87 |
def plot_pladder(PLadder):
|
| 88 |
fig, ax = plt.subplots()
|
| 89 |
ax.plot([0, 1.5, 3, 0], [0, 3, 0, 0], 'k-') # Triangle
|
|
|
|
| 98 |
ax.axis('off')
|
| 99 |
return fig
|
| 100 |
|
| 101 |
+
# Main interface function (reworked)
|
| 102 |
+
def chat_interface(query):
|
| 103 |
+
# Check for valid command
|
| 104 |
if not query.startswith("PLadder "):
|
| 105 |
+
return "Запрос должен начинаться с 'PLadder' и содержать дату, время и местоположение.", None
|
| 106 |
|
| 107 |
+
# Extract date, time, and location
|
| 108 |
+
query_rest = query[len("PLadder "):]
|
| 109 |
+
try:
|
| 110 |
+
parsed_dt, skipped = parser.parse(query_rest, fuzzy_with_tokens=True)
|
| 111 |
+
location = " ".join(skipped)
|
| 112 |
+
if not location:
|
| 113 |
+
return "Укажите местоположение (город или населённый пункт).", None
|
| 114 |
+
except ValueError:
|
| 115 |
return "Неверный формат даты и времени.", None
|
| 116 |
|
| 117 |
+
# Geocode the location to get latitude and longitude
|
| 118 |
+
try:
|
| 119 |
+
location_data = geolocator.geocode(location)
|
| 120 |
+
if location_data:
|
| 121 |
+
lat = location_data.latitude
|
| 122 |
+
lon = location_data.longitude
|
| 123 |
+
else:
|
| 124 |
+
return f"Не удалось найти координаты для '{location}'.", None
|
| 125 |
+
except Exception as e:
|
| 126 |
+
return f"Ошибка геокодирования: {str(e)}", None
|
| 127 |
+
|
| 128 |
+
# Determine time zone from coordinates
|
| 129 |
+
tz_name = tf.timezone_at(lng=lon, lat=lat)
|
| 130 |
+
if tz_name is None:
|
| 131 |
+
return f"Не удалось определить часовой пояс для '{location}'.", None
|
| 132 |
+
tz = pytz.timezone(tz_name)
|
| 133 |
+
|
| 134 |
+
# Localize the parsed local time and convert to UTC
|
| 135 |
+
try:
|
| 136 |
+
timezone_aware_dt = tz.localize(parsed_dt)
|
| 137 |
+
except pytz.exceptions.AmbiguousTimeError:
|
| 138 |
+
# Handle ambiguous times (e.g., DST transitions) by defaulting to standard time
|
| 139 |
+
timezone_aware_dt = tz.localize(parsed_dt, is_dst=False)
|
| 140 |
+
utc_dt = timezone_aware_dt.astimezone(pytz.utc)
|
| 141 |
+
date_time_iso = utc_dt.isoformat()
|
| 142 |
+
|
| 143 |
+
# Pass UTC time and coordinates to PLadder_ZSizes
|
| 144 |
+
result = PLadder_ZSizes(date_time_iso, str(lat), str(lon))
|
| 145 |
if "error" in result:
|
| 146 |
return result["error"], None
|
| 147 |
|
| 148 |
+
# Extract results
|
| 149 |
PLadder = result["PLadder"]
|
| 150 |
ZSizes = result["ZSizes"]
|
| 151 |
longitudes = result["longitudes"]
|
| 152 |
|
| 153 |
+
# Format output text
|
| 154 |
planet_list = "\n".join([f"{planet_ru[p]}: {lon_to_sign(longitudes[p])}" for p in PLadder])
|
| 155 |
zones_text = "\n".join([f"Зона {i+1}: {size} ({cls})" for i, (size, cls) in enumerate(ZSizes)])
|
| 156 |
|
| 157 |
+
# Generate plot
|
| 158 |
fig = plot_pladder(PLadder)
|
| 159 |
buf = BytesIO()
|
| 160 |
fig.savefig(buf, format='png', bbox_inches='tight')
|
|
|
|
| 162 |
img = Image.open(buf)
|
| 163 |
plt.close(fig)
|
| 164 |
|
| 165 |
+
# Combine text output
|
| 166 |
text = f"Планетарная лестница:\n{planet_list}\n\nРазмеры зон:\n{zones_text}"
|
| 167 |
return text, img
|
| 168 |
|
| 169 |
+
# Gradio UI (reworked for single query field)
|
| 170 |
with gr.Blocks() as interface:
|
| 171 |
+
query_text = gr.Textbox(label="Запрос", placeholder="Пример: PLadder 2023-10-10 12:00 New York")
|
| 172 |
+
submit_button = gr.Button("Отправить")
|
| 173 |
with gr.Row():
|
| 174 |
with gr.Column(scale=2):
|
| 175 |
output_text = gr.Textbox(label="Ответ", lines=10)
|
| 176 |
with gr.Column(scale=1):
|
| 177 |
output_image = gr.Image(label="График планетарной лестницы")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 178 |
|
| 179 |
submit_button.click(
|
| 180 |
fn=chat_interface,
|
| 181 |
+
inputs=query_text,
|
| 182 |
outputs=[output_text, output_image]
|
| 183 |
)
|
| 184 |
|