# Project export: Crisis Map

This document was generated by HackStack to give an AI agent context about a hackathon project. Sections are labeled with their provenance; content marked as truncated was cut to keep this document small.

## Project metadata

- Hackathon: Cal Hacks 11.0
- Tagline: Real time map of weather danger-zones, allowing users in disaster-stricken areas to find adaptive evacuation routes, supply drops, and priority emergency responder locations.
- Devpost: https://devpost.com/software/crisis-map-v4ic7h
- GitHub: https://github.com/Enchantek/CalHacks11.0_CrisisMap
- Team: 3 GitHub contributor(s) — Enchantek (9 commits), yashberawala (3 commits), Brandon Sandoval (1 commits)

## Devpost submission (written by the team)

### Inspiration

Hurricane Milton has affected millions of lives in the Southeastern portion of the United States inducing one of the biggest evacuations in history, with more than 5 million residents in the East Coast receiving orders to evacuate for safety. Thinking about if we were in their shoes, we thought about how easy it would have been if we access to all the information we need for our safety in a single area: weather status, evacuation routes, emergency relief; all of this information would be a necessity in a dire situation where time and information affects your safety.

### What it does

At its current state, our project accepts a zip code as user input, grabbing the weather conditions of that area and visualizing this information on the main map of the front page.

### How we built it

We implemented the project through Reflex, a framework allowing developers to create fullstack websites through Python. We utilized multiple APIs, including Google Map's API and Openweathermap's API for weather condition gathering.

### Challenges we ran into

One of the biggest challenges we ran into was learning the new tools at our disposal. CalHacks introduced lots of technologies we haven't heard of before: Reflex, FetchAI, and Hume. We ran into many errors learning Reflex, kept running into API pricing issues, and the limited bandwidth of the hackathon venue made it difficult to make progress. We thought of lots of different ways we might have been able to use these tools, but had to narrow down our vision in order to make project completion feasible within the time limit. Learning these new tools on the fly was a tough challenge, but it was a great learning experience nonetheless.

### Accomplishments we're proud of

Despite being cobbled-together, we're proud of the logic we came up with user input and data returning. We managed to get the first stages of the heatmap working.

### What we learned

We're most proud of the new skills we learned, figuring out how to implement APIs, heatmaps, and website deployment. We're proud of learning Reflex within 36 hours since we were able to build our website using python instead of just HTML/JS/CSS.

### What's next

In the future we plan on incorporating more data from governments and official resources, giving users in a single space access to multiple resources and information they would normally have trouble finding. We plan on harnessing the power of artificial intelligence to find the best evacuation routes given factors like weather patterns, infrastructure status, and shelter availability, giving the real-time critical data to users. We also aim to refine the severity calculations and explore expansion into other types of crises, such as wildfires and earthquakes.

## README (from the GitHub repository)

No README available.

## Detected evidence (automated analysis)

Indexed codebase: 13 recognized source files, 15 KB.
- HTML (language) — detected in the code
- JavaScript (language) — detected in the code
- Python (language) — detected in the code

## Codebase structure (from repository index)

### Files (15 of 15)

```
.gitignore
assets/map.html
assets/map.js
CalHacks_CrisisMap/__init__.py
CalHacks_CrisisMap/CalHacks_CrisisMap.py
CalHacks_CrisisMap/components/google_map.py
CalHacks_CrisisMap/components/open_weather.py
CalHacks_CrisisMap/components/user_input.py
CalHacks_CrisisMap/pages/index.py
CalHacks_CrisisMap/state/state.py
CalHacks_CrisisMap/tests/javascript_test.html
CalHacks_CrisisMap/tests/openweather_api_request_test.html
CalHacks_CrisisMap/tests/social_media_scan_test.py
requirements.txt
rxconfig.py
```

### Dependencies

- requirements.txt: reflex@==0.6.3

### Recent commits (newest first)

- Merge remote-tracking branch 'origin/master'
- zip code to lon/lat conversion implemented
- Delete .venv directory
- Merge branch 'master' of github.com:Enchantek/CalHacks11.0_CrisisMap
- changed gitignore
- Remove .venv directory
- Added a header
- Merge pull request #1 from Enchantek/yash
- added heatmap
- changed
- changed map logic
- first commit
- first commit

## Key source files (fetched from GitHub, selected and truncated for size)

### requirements.txt

```
reflex==0.6.3

```

### CalHacks_CrisisMap/pages/index.py

```python
import reflex as rx
from CalHacks_CrisisMap.components.google_map import google_map
#from CalHacks_CrisisMap.state.weather_state import weather_state
from CalHacks_CrisisMap.components.open_weather import get_weather_data
from CalHacks_CrisisMap.components.user_input import location_input
from reflex import Component
import requests
# State to store and manage the lat/lon and map data
class MapState(rx.State):
    lat: float = 37.7749
    lon: float = -122.4194
    population_data: list = []

    def set_coordinates(self, lat, lon):
        """Set the latitude and longitude."""
        self.lat = lat
        self.lon = lon
        self.population_data = get_population_heatmap_data(lat, lon)

    def update_map(self):
        """Update the map with current coordinates and population data."""
        print(f"Updating map with Lat: {self.lat}, Lon: {self.lon}")
        return google_map(self.lat, self.lon, self.population_data)

# Function to get mock population data (replace with real data)
def get_population_heatmap_data(lat, lon):
    return [
        (lat, lon),
        (lat + 0.01, lon + 0.01),
        (lat + 0.02, lon - 0.01),
        (lat - 0.01, lon + 0.02),
        (lat - 0.02, lon - 0.02)
    ]

def create_logo_section():
    """Create the logo section with CrisisMap icon and text."""
    return rx.flex(
        rx.icon(
            alt="CrisisMap Logo",
            tag="map",
            height="2rem",
            margin_right="0.5rem",
            color="#EF4444",
            width="2rem",
        ),
        rx.text.span(
            "CrisisMap",
            font_weight="700",
            color="#ffffff",
            font_size="1.25rem",
            line_height="1.75rem",
        ),
        display="flex",
        align_items="center",
    )

def create_nav_link(link_text):
    """Create a navigation link with hover effect and white text color."""
    return rx.el.a(
        link_text,
        href="#",
        _hover={"color": "#D1D5DB"},
        color="#ffffff",
    )

def create_header():
    """Create the complete header with logo, navigation links, and responsive menu button."""
    return rx.center(
        rx.flex(
            create_logo_section(),
            rx.box(
                create_nav_link(link_text="Home"),
                create_nav_link(link_text="Map"),
                create_nav_link(link_text="Alerts"),
                create_nav_link(link_text="Resources"),
                create_nav_link(link_text="Contact"),
                display=rx.breakpoints(
                    {"0px": "none", "768px": "flex"}
                ),
                column_gap="1rem",
            ),
            rx.box(
                rx.el.button(
                    rx.icon(
                        alt="Menu",
                        tag="menu",
                        height="1.5rem",
                        width="1.5rem",
                    ),
                    _focus={"outline-style": "none"},
                    color="#ffffff",
                ),
                display=rx.breakpoints({"768px": "none"}),
            ),
            width="100%",
            style=rx.breakpoints(
                {
                    "640px": {"max-width": "640px"},
                    "768px": {"max-width": "768px"},
                    "1024px": {"max-width": "1024px"},
                    "1280px": {"max-width": "1280px"},
                    "1536px": {"max-width": "1536px"},
                }
            ),
            display="flex",
            align_items="center",
            justify_content="space-between",
            margin_left="auto",
            margin_right="auto",
        )
    )

# Main layout with static map based on lat/lon
def index():
    # Default lat/lon for map (can adjust these)
    lat, lon = 37.7749, -122.4194
    # Populate population heatmap data for these coordinates
    population_data = get_population_heatmap_data(lat, lon)
    
    return rx.vstack(
        rx.box(
            create_header(),
            width="100%",
        ),
        rx.center(
            rx.flex(
                rx.box(
                    location_input(),
                    id="zip_code_input",
                    width="20%",
                    height="95%",   
                    border_radius="md",
                    box_shadow="lg",
                ),
                rx.box(
                    google_map(lat, lon, population_data),  # Pass lat/lon and population heatmap data
                    id="google_map_container",  # Unique ID for dynamic updates
                    width="80%",
                    height="95%",   
                    bg="white",
                    border_radius="md",
                    box_shadow="lg",
                ),
                width="90%",
                height="calc(100vh - 60px)",  # Adjust this value based on your header height
                align="center",
                justify="center",
            ),
            width="100%",
            height="calc(100vh - 60px)",  # Adjust this value based on your header height
        ),
        width="100%",
        height="100vh",
        spacing="0",
    )
```

### rxconfig.py

```python
import reflex as rx

config = rx.Config(
    app_name="CalHacks_CrisisMap",
)
```

### CalHacks_CrisisMap/CalHacks_CrisisMap.py

```python
import reflex as rx
from CalHacks_CrisisMap.pages.index import index

app = rx.App()
app.add_page(index) 
```

### assets/map.html

```html
<!DOCTYPE html>
<html>
<head>
    <title>Google Map with Weather Data</title>
</head>
<body>
    <div id="map" style="width: 100%; height: 100vh;"></div>
    <script src="map.js"></script>
    <script async defer src="https://maps.googleapis.com/maps/api/js?key=AIzaSyB00U7TY2GZJANOC34L6KXnWnlr3bax8rE&callback=initMap"></script>
</body>
</html>

```

### CalHacks_CrisisMap/components/open_weather.py

```python
import requests

def get_weather_data (lat, lon):
    api_key = "05405fe3529fd2f607778d7b5f7122bb" # API key for open weather
    base_url = f"http://api.openweathermap.org/data/2.5/weather?lat={lat}&lon={lon}&appid={api_key}&units=metric"

    response = requests.get(base_url)
    data = response.json()
    
    if response.status_code == 200:
        weather = data['weather'][0]['description']
        temperature = data['main']['temp']
        wind_speed = data['wind']['speed']
        return {
            "weather": weather,
            "temperature": temperature,
            "wind_speed": wind_speed
        }
    else:
        return {"error": "Unable to fetch weather data"}
```

### CalHacks_CrisisMap/components/user_input.py

```python
import reflex as rx
from CalHacks_CrisisMap.state.state import State

def location_input():
    return rx.vstack(
        rx.input(
            placeholder="Enter zip code...",
            on_change=State.set_zip_code,
            max_length=5,
            type_="tel",
        ),
        rx.button("Submit", on_click=State.convert_zip_to_coords),
        rx.text(State.error, color="red"),
        rx.text(rx.cond(
            State.lat != 37.7749,  # Only show if coordinates have been updated
            rx.vstack(
                rx.text(f"Latitude: {State.lat}"),
                rx.text(f"Longitude: {State.lon}"),
            ),
        )),
        width="100%",
        spacing="4",
    )
```

### CalHacks_CrisisMap/tests/social_media_scan_test.py

```python
import tweepy

# Replace with your Bearer Token
BEARER_TOKEN = 'AAAAAAAAAAAAAAAAAAAAACr%2BwQEAAAAAvgb1hvtpKeOHZ6ZUNRu5%2FPtLAxs%3DmdpnQBLrfakoTtZfKJPSefuHsLOsUmg5Ufy63Fnoaoj5AzmNv2'

# Authenticate with the Twitter API v2
client = tweepy.Client(bearer_token=BEARER_TOKEN)

# Define your search query and geocode parameters
search_query = 'your search query has:geo'
# Since Twitter API v2 does not support direct geocode, 
# you can search for tweets with geo-tagged data using 'has:geo'

# Define other query parameters
query_params = {
    'query': search_query,
    'max_results': 10,  # Retrieve up to 10 tweets
    'tweet.fields': 'geo',  # Get geographical info if available
    'expansions': 'geo.place_id',
    'place.fields': 'full_name'
}

# Search for tweets
response = client.search_recent_tweets(**query_params)

# Process and print the results
if response.data:
    for tweet in response.data:
        print(f'Tweet: {tweet.text}')
        if 'geo' in tweet:
            print(f'Geo data available: {tweet.geo}')
else:
    print("No tweets found with the specified query.")

```

### CalHacks_CrisisMap/tests/openweather_api_request_test.html

```html
<!DOCTYPE html>
<html>
<head>
<script>
    async function myFunction() {
        const api_key = '30bfedf90f5f33c670ff02053c1e493e';
        const url = `https://api.openweathermap.org/data/2.5/weather?lat=44.34&lon=10.99&appid=30bfedf90f5f33c670ff02053c1e493e`;

        try {
            const response = await fetch(url);
            const data = await response.json();
            console.log(data);
            // Example of fetching hurricane information from the weather API
            // You'll need to adapt this based on the weather API's structure
            // const hurricaneCoordinates = [
            //     { lat: 25.7617, lng: -80.1918 },
            //     { lat: 26.7617, lng: -81.1918 },
            //     { lat: 27.7617, lng: -82.1918 },
            // ];

            //addHurricaneZone(map, hurricaneCoordinates);
        } catch (error) {
            console.error("Error fetching weather data:", error);
        }
    }
</script>
</head>
<body>
<h2>Demo JavaScript in Head</h2>

<p id="demo">A Paragraph</p>
<button type="button" onclick="myFunction()">Try it</button>

</body>
</html>
```

### CalHacks_CrisisMap/state/state.py

```python
import reflex as rx
import requests

class State(rx.State):
    zip_code: str = ""
    lat: float = 37.7749  # Default to San Francisco
    lon: float = -122.4194
    error: str = ""

    def set_zip_code(self, zip_code: str):
        if len(zip_code) <= 5 and zip_code.isdigit():
            self.zip_code = zip_code
            self.error = ""
            print(zip_code)
        else:
            self.error = "Please enter a valid 5-digit zip code."

    def convert_zip_to_coords(self):
        if len(self.zip_code) != 5:
            self.error = "Please enter a valid 5-digit zip code."
            return
        
        api_key = "AIzaSyB00U7TY2GZJANOC34L6KXnWnlr3bax8rE"  # Replace with your actual API key
        url = f"https://maps.googleapis.com/maps/api/geocode/json?address={self.zip_code}&key={api_key}"
        
        response = requests.get(url)
        data = response.json()
        
        if data['status'] == 'OK':
            location = data['results'][0]['geometry']['location']
            self.lat = location['lat']
            self.lon = location['lng']
            self.error = ""
        else:
            self.error = "Unable to find coordinates for the given zip code."
```

[2 more indexed source files omitted to keep this export small. The full file list is in the Codebase structure section above.]