VicGerardoPR commited on
Commit
28df62a
verified
1 Parent(s): 354795b

Upload 3 files

Browse files
Files changed (3) hide show
  1. app.py +179 -0
  2. readme.MD +6 -0
  3. requirements.txt +7 -0
app.py ADDED
@@ -0,0 +1,179 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import re
3
+ import streamlit as st
4
+ import folium
5
+ from streamlit_folium import st_folium
6
+ import openai
7
+ from bs4 import BeautifulSoup
8
+
9
+ # Configuraci贸n de la p谩gina
10
+ st.set_page_config(page_title="Mapa Interactivo de Puerto Rico", layout="wide")
11
+ st.title("Mapa Interactivo de Puerto Rico y Chatbot de Recomendaciones")
12
+
13
+ # =============================================================================
14
+ # Funciones para parsear archivos
15
+ # =============================================================================
16
+
17
+ def parse_text_file(filepath):
18
+ """
19
+ Parseo para archivos de texto plano.
20
+ Busca l铆neas con 'Name:', 'Latitude:' y 'Longitude:'.
21
+ """
22
+ with open(filepath, 'r', encoding='utf-8') as f:
23
+ content = f.read()
24
+
25
+ name_match = re.search(r'Name:\s*(.*)', content, re.IGNORECASE)
26
+ name = name_match.group(1).strip() if name_match else os.path.splitext(os.path.basename(filepath))[0]
27
+
28
+ lat_match = re.search(r'Latitude:\s*([-+]?[0-9]*\.?[0-9]+)', content, re.IGNORECASE)
29
+ lon_match = re.search(r'Longitude:\s*([-+]?[0-9]*\.?[0-9]+)', content, re.IGNORECASE)
30
+ if lat_match and lon_match:
31
+ try:
32
+ lat = float(lat_match.group(1))
33
+ except ValueError:
34
+ lat = None
35
+ try:
36
+ lon = float(lon_match.group(1))
37
+ except ValueError:
38
+ lon = None
39
+ else:
40
+ lat, lon = None, None
41
+
42
+ return {
43
+ "name": name,
44
+ "lat": lat,
45
+ "lon": lon,
46
+ "content": content
47
+ }
48
+
49
+ def parse_html_file(filepath):
50
+ """
51
+ Parseo para archivos HTML (por ejemplo, de Wikipedia).
52
+ Extrae el t铆tulo desde la etiqueta <title> y las coordenadas desde el bloque "wgCoordinates".
53
+ Si la coordenada es '-' se asigna None.
54
+ """
55
+ with open(filepath, 'r', encoding='utf-8') as f:
56
+ content = f.read()
57
+
58
+ # Extraer el t铆tulo usando BeautifulSoup
59
+ soup = BeautifulSoup(content, "html.parser")
60
+ title = soup.title.string.strip() if soup.title else os.path.splitext(os.path.basename(filepath))[0]
61
+
62
+ # Buscar las coordenadas en el contenido HTML (ej. en el bloque "wgCoordinates")
63
+ coord_match = re.search(r'"wgCoordinates":\s*{\s*"lat":\s*([0-9\.-]+),\s*"lon":\s*([0-9\.-]+)', content)
64
+ if coord_match:
65
+ lat_str = coord_match.group(1)
66
+ lon_str = coord_match.group(2)
67
+ try:
68
+ lat = float(lat_str) if lat_str not in ['-', ''] else None
69
+ except ValueError:
70
+ lat = None
71
+ try:
72
+ lon = float(lon_str) if lon_str not in ['-', ''] else None
73
+ except ValueError:
74
+ lon = None
75
+ else:
76
+ lat, lon = None, None
77
+
78
+ return {
79
+ "name": title,
80
+ "lat": lat,
81
+ "lon": lon,
82
+ "content": content
83
+ }
84
+
85
+ def load_data_from_directory(directory, parser_func):
86
+ """
87
+ Carga todos los archivos .txt de un directorio usando la funci贸n de parseo indicada.
88
+ """
89
+ data_points = []
90
+ if os.path.exists(directory):
91
+ for filename in os.listdir(directory):
92
+ if filename.endswith(".txt"):
93
+ filepath = os.path.join(directory, filename)
94
+ data_points.append(parser_func(filepath))
95
+ return data_points
96
+
97
+ # =============================================================================
98
+ # Carga de los datos desde las carpetas correspondientes
99
+ # =============================================================================
100
+
101
+ landmarks_dir = os.path.join("data", "landmarks")
102
+ municipalities_dir = os.path.join("data", "municipalities")
103
+ news_dir = os.path.join("data", "news")
104
+
105
+ # Para landmarks y news se asume que los archivos son de texto plano.
106
+ landmarks = load_data_from_directory(landmarks_dir, parse_text_file)
107
+ news_data = load_data_from_directory(news_dir, parse_text_file)
108
+
109
+ # Para municipalities, se usa el parseo de HTML
110
+ municipalities = load_data_from_directory(municipalities_dir, parse_html_file)
111
+
112
+ # =============================================================================
113
+ # Creaci贸n del mapa interactivo usando Folium
114
+ # =============================================================================
115
+
116
+ # Coordenadas centrales aproximadas de Puerto Rico
117
+ map_center = [18.2208, -66.5901]
118
+ m = folium.Map(location=map_center, zoom_start=10)
119
+
120
+ # Agregar marcadores para Landmarks
121
+ for landmark in landmarks:
122
+ if landmark["lat"] is not None and landmark["lon"] is not None:
123
+ folium.Marker(
124
+ location=[landmark["lat"], landmark["lon"]],
125
+ popup=folium.Popup(f"<b>{landmark['name']}</b><br>{landmark['content'][:200]}...", max_width=300),
126
+ icon=folium.Icon(color='blue', icon='info-sign')
127
+ ).add_to(m)
128
+
129
+ # Agregar marcadores para Municipios
130
+ for municipality in municipalities:
131
+ if municipality["lat"] is not None and municipality["lon"] is not None:
132
+ folium.Marker(
133
+ location=[municipality["lat"], municipality["lon"]],
134
+ popup=folium.Popup(f"<b>{municipality['name']}</b><br>{municipality['content'][:200]}...", max_width=300),
135
+ icon=folium.Icon(color='green', icon='home')
136
+ ).add_to(m)
137
+
138
+ # Agregar marcadores para Noticias (si se disponen de coordenadas)
139
+ for news_item in news_data:
140
+ if news_item["lat"] is not None and news_item["lon"] is not None:
141
+ folium.Marker(
142
+ location=[news_item["lat"], news_item["lon"]],
143
+ popup=folium.Popup(f"<b>{news_item['name']}</b><br>{news_item['content'][:200]}...", max_width=300),
144
+ icon=folium.Icon(color='red', icon='newspaper')
145
+ ).add_to(m)
146
+
147
+ st.subheader("Mapa Interactivo")
148
+ st_data = st_folium(m, width=700, height=500)
149
+
150
+ # =============================================================================
151
+ # Secci贸n del Chatbot con API de OpenAI
152
+ # =============================================================================
153
+
154
+ st.markdown("---")
155
+ st.subheader("Chatbot de Recomendaciones")
156
+ st.write("Consulta recomendaciones sobre Puerto Rico.")
157
+
158
+ # Entrada de usuario para la consulta
159
+ user_input = st.text_input("Escribe tu consulta:")
160
+
161
+ if st.button("Enviar consulta"):
162
+ if user_input:
163
+ # Configura tu clave API de OpenAI (def铆nela en st.secrets)
164
+ openai.api_key = st.secrets["OPENAI_API_KEY"]
165
+ try:
166
+ response = openai.ChatCompletion.create(
167
+ model="gpt-3.5-turbo",
168
+ messages=[
169
+ {"role": "system", "content": "Eres un asistente experto en recomendaciones tur铆sticas y culturales de Puerto Rico. Ayudas a los usuarios a descubrir lugares de inter茅s y actividades en la isla."},
170
+ {"role": "user", "content": user_input}
171
+ ]
172
+ )
173
+ answer = response.choices[0].message.content.strip()
174
+ st.markdown("**Respuesta:**")
175
+ st.write(answer)
176
+ except Exception as e:
177
+ st.error(f"Error al conectarse con la API de OpenAI: {e}")
178
+ else:
179
+ st.warning("Por favor, ingresa una consulta.")
readme.MD ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ # Mapa Interactivo de Puerto Rico y Chatbot
2
+
3
+ ## 馃搶 Descripci贸n
4
+ Esta aplicaci贸n en Streamlit permite visualizar un mapa interactivo de Puerto Rico con informaci贸n sobre municipios y puntos de referencia. Adem谩s, incluye un chatbot impulsado por OpenAI para responder preguntas sobre Puerto Rico.
5
+
6
+ ## 馃搨 Estructura del Proyecto
requirements.txt ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ streamlit
2
+ openai
3
+ geopandas
4
+ folium
5
+ pandas
6
+ numpy
7
+ requests