Create app.py
Browse files
app.py
ADDED
@@ -0,0 +1,161 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import streamlit as st
|
2 |
+
import folium
|
3 |
+
from streamlit_folium import folium_static
|
4 |
+
from folium.plugins import MarkerCluster
|
5 |
+
import time
|
6 |
+
import math
|
7 |
+
|
8 |
+
# Define California medical centers data
|
9 |
+
california_med_centers = [
|
10 |
+
('UCSF Medical Center', 37.7631, -122.4576, 'General medical and surgical', 'San Francisco'),
|
11 |
+
('Cedars-Sinai Medical Center', 34.0762, -118.3790, 'Heart specialty', 'Los Angeles'),
|
12 |
+
('Stanford Health Care', 37.4331, -122.1750, 'Teaching hospital', 'Stanford'),
|
13 |
+
('UCLA Medical Center', 34.0659, -118.4466, 'Research and teaching', 'Los Angeles'),
|
14 |
+
('Scripps La Jolla Hospitals', 32.8851, -117.2255, 'Multiple specialties', 'La Jolla'),
|
15 |
+
('Sharp Memorial Hospital', 32.7992, -117.1542, 'Trauma center', 'San Diego'),
|
16 |
+
('Huntington Hospital', 34.1330, -118.1475, 'Non-profit hospital', 'Pasadena'),
|
17 |
+
('Hoag Memorial Hospital', 33.6045, -117.8664, 'Community hospital', 'Newport Beach'),
|
18 |
+
('UCSD Medical Center', 32.7554, -117.1682, 'Academic health center', 'San Diego'),
|
19 |
+
('UC Davis Medical Center', 38.5539, -121.4554, 'Public academic health', 'Sacramento'),
|
20 |
+
('John Muir Medical Center', 37.9192, -122.0426, 'Heart care', 'Walnut Creek'),
|
21 |
+
('Santa Clara Valley Medical Center', 37.3121, -121.9769, 'County hospital', 'San Jose'),
|
22 |
+
('Kaiser Permanente San Francisco', 37.7741, -122.4179, 'Health maintenance organization', 'San Francisco'),
|
23 |
+
('City of Hope', 34.1285, -117.9665, 'Cancer center', 'Duarte'),
|
24 |
+
('UCI Medical Center', 33.7886, -117.8572, 'University hospital', 'Orange'),
|
25 |
+
('Good Samaritan Hospital', 34.0506, -118.2831, 'Private hospital', 'Los Angeles'),
|
26 |
+
('Los Angeles County General', 34.0581, -118.2917, 'Public hospital', 'Los Angeles'),
|
27 |
+
('California Pacific Medical Center', 37.7864, -122.4357, 'Private non-profit', 'San Francisco'),
|
28 |
+
('Sutter Roseville Medical Center', 38.7521, -121.2760, 'General medical and surgical', 'Roseville'),
|
29 |
+
('St. Joseph Hospital', 33.7821, -117.9188, 'Faith-based care', 'Orange')
|
30 |
+
]
|
31 |
+
|
32 |
+
# Initialize session state
|
33 |
+
if 'car_position' not in st.session_state:
|
34 |
+
st.session_state.car_position = [37.7631, -122.4576] # Default start: UCSF
|
35 |
+
if 'is_moving' not in st.session_state:
|
36 |
+
st.session_state.is_moving = False
|
37 |
+
if 'start' not in st.session_state:
|
38 |
+
st.session_state.start = california_med_centers[0]
|
39 |
+
if 'destination' not in st.session_state:
|
40 |
+
st.session_state.destination = california_med_centers[1]
|
41 |
+
if 'start_time' not in st.session_state:
|
42 |
+
st.session_state.start_time = None
|
43 |
+
if 'elapsed_time' not in st.session_state:
|
44 |
+
st.session_state.elapsed_time = 0
|
45 |
+
|
46 |
+
# Distance calculation (Haversine in miles)
|
47 |
+
def calculate_distance(lat1, lon1, lat2, lon2):
|
48 |
+
R = 3958.8 # Earth radius in miles
|
49 |
+
lat1_rad, lon1_rad = math.radians(lat1), math.radians(lon1)
|
50 |
+
lat2_rad, lon2_rad = math.radians(lat2), math.radians(lon2)
|
51 |
+
dlat = lat2_rad - lat1_rad
|
52 |
+
dlon = lon2_rad - lon1_rad
|
53 |
+
a = math.sin(dlat / 2)**2 + math.cos(lat1_rad) * math.cos(lat2_rad) * math.sin(dlon / 2)**2
|
54 |
+
c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a))
|
55 |
+
return R * c
|
56 |
+
|
57 |
+
# Create map with hovercar
|
58 |
+
def create_map():
|
59 |
+
m = folium.Map(location=st.session_state.car_position, zoom_start=13, tiles="CartoDB Positron")
|
60 |
+
marker_cluster = MarkerCluster().add_to(m)
|
61 |
+
for center in california_med_centers:
|
62 |
+
folium.Marker(
|
63 |
+
location=[center[1], center[2]],
|
64 |
+
popup=f'<b>{center[0]}</b><br>{center[3]}<br>{center[4]}',
|
65 |
+
icon=folium.Icon(color='red')
|
66 |
+
).add_to(marker_cluster)
|
67 |
+
folium.Marker(
|
68 |
+
location=st.session_state.car_position,
|
69 |
+
popup='Hovercar',
|
70 |
+
icon=folium.Icon(color='purple', icon='rocket', prefix='fa') # Rocket for hovercar
|
71 |
+
).add_to(m)
|
72 |
+
return m
|
73 |
+
|
74 |
+
# Move hovercar
|
75 |
+
def move_car():
|
76 |
+
target = [st.session_state.destination[1], st.session_state.destination[2]]
|
77 |
+
lat_step = (target[0] - st.session_state.car_position[0]) / 50
|
78 |
+
lon_step = (target[1] - st.session_state.car_position[1]) / 50
|
79 |
+
st.session_state.car_position[0] += lat_step
|
80 |
+
st.session_state.car_position[1] += lon_step
|
81 |
+
|
82 |
+
# Calculate speed (mph) and ETA
|
83 |
+
total_distance = calculate_distance(st.session_state.start[1], st.session_state.start[2],
|
84 |
+
st.session_state.destination[1], st.session_state.destination[2])
|
85 |
+
steps = 50 # Number of steps for the trip
|
86 |
+
step_time = 0.5 # Seconds per step
|
87 |
+
total_time = steps * step_time # Total seconds for the trip
|
88 |
+
speed = total_distance / (total_time / 3600) # mph (distance / hours)
|
89 |
+
|
90 |
+
# Layout: Two columns
|
91 |
+
left_col, right_col = st.columns([2, 1])
|
92 |
+
|
93 |
+
# Left column: Map and stats
|
94 |
+
with left_col:
|
95 |
+
st.markdown("### π Hovercar Command Center πΈ")
|
96 |
+
m = create_map()
|
97 |
+
folium_static(m, width=800, height=600) # Adjusted map size
|
98 |
+
|
99 |
+
# Display stats
|
100 |
+
remaining_distance = calculate_distance(
|
101 |
+
st.session_state.car_position[0], st.session_state.car_position[1],
|
102 |
+
st.session_state.destination[1], st.session_state.destination[2]
|
103 |
+
)
|
104 |
+
st.write(f"**Start**: {st.session_state.start[0]} ({st.session_state.start[1]:.4f}, {st.session_state.start[2]:.4f})")
|
105 |
+
st.write(f"**Destination**: {st.session_state.destination[0]} ({st.session_state.destination[1]:.4f}, {st.session_state.destination[2]:.4f})")
|
106 |
+
st.write(f"**Total Distance**: {total_distance:.1f} miles")
|
107 |
+
st.write(f"**Remaining Distance**: {remaining_distance:.1f} miles")
|
108 |
+
st.write(f"**Speed**: {speed:.1f} mph")
|
109 |
+
st.write(f"**ETA**: {total_time:.1f} seconds")
|
110 |
+
if st.session_state.is_moving:
|
111 |
+
elapsed = st.session_state.elapsed_time
|
112 |
+
st.write(f"**Elapsed Time**: {elapsed:.1f} seconds")
|
113 |
+
|
114 |
+
# Controls
|
115 |
+
col1, col2, col3 = st.columns(3)
|
116 |
+
with col1:
|
117 |
+
if st.button("π Launch Hovercar"):
|
118 |
+
st.session_state.is_moving = True
|
119 |
+
st.session_state.start_time = time.time()
|
120 |
+
with col2:
|
121 |
+
if st.button("π Halt Hovercar"):
|
122 |
+
st.session_state.is_moving = False
|
123 |
+
st.session_state.start_time = None
|
124 |
+
with col3:
|
125 |
+
if st.button("π Reset to Start"):
|
126 |
+
st.session_state.car_position = [st.session_state.start[1], st.session_state.start[2]]
|
127 |
+
st.session_state.is_moving = False
|
128 |
+
st.session_state.start_time = None
|
129 |
+
st.session_state.elapsed_time = 0
|
130 |
+
st.rerun()
|
131 |
+
|
132 |
+
# Right column: Start and destination selection
|
133 |
+
with right_col:
|
134 |
+
st.markdown("### π― Navigation Controls")
|
135 |
+
|
136 |
+
st.write("**π¦ Set Start Point**")
|
137 |
+
for center in california_med_centers:
|
138 |
+
if st.button(f"π {center[0]}", key=f"start_{center[0]}"):
|
139 |
+
st.session_state.start = center
|
140 |
+
st.session_state.car_position = [center[1], center[2]]
|
141 |
+
st.session_state.is_moving = False
|
142 |
+
st.session_state.start_time = None
|
143 |
+
st.session_state.elapsed_time = 0
|
144 |
+
st.rerun()
|
145 |
+
|
146 |
+
st.write("**π Set Destination**")
|
147 |
+
for center in california_med_centers:
|
148 |
+
if st.button(f"π― {center[0]}", key=f"dest_{center[0]}"):
|
149 |
+
st.session_state.destination = center
|
150 |
+
st.session_state.is_moving = False
|
151 |
+
st.session_state.start_time = None
|
152 |
+
st.session_state.elapsed_time = 0
|
153 |
+
st.rerun()
|
154 |
+
|
155 |
+
# Movement logic
|
156 |
+
if st.session_state.is_moving:
|
157 |
+
move_car()
|
158 |
+
if st.session_state.start_time:
|
159 |
+
st.session_state.elapsed_time = time.time() - st.session_state.start_time
|
160 |
+
time.sleep(0.5) # Pause for smoothness
|
161 |
+
st.rerun()
|