# Project export: SafeRoute

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 12.0
- Tagline: Safety-first navigation app based on real live crime data and user incident reporting.
- Devpost: https://devpost.com/software/saferoute-94s2cx
- GitHub: https://github.com/Christopher-Vu/TheTakeoutBoxCalHacks
- Video: https://www.youtube.com/embed/mBW3udBBkOU?enablejsapi=1&hl=en_US&rel=0&start=&version=3&wmode=transparent
- Team: 4 GitHub contributor(s) — A)exitexit() (21 commits), Christopher Vu (18 commits), ALNgu1 (6 commits), justinjfu7 (4 commits)

## Devpost submission (written by the team)

### Inspiration

At UC Berkeley, we frequently experience scenarios walking home alone late at night, regretting the path we took down that dark alleyway or hoping we had someone with us. What we created This inspired us to create SafeRoute, which automatically finds the safest routes based on historical crime data. Additionally, we added a user self-report feature with uses Groq to classify user incident photos and add them to the map.

### How we built it

The site's crime database based on PostGre SQL has two sources: publicly scraped incident data and self-reported incidents from the application itself (described and classified through groq). These two kinds of incidents are entered into the postgresql database. When the user queries a new route, we use mapbox to identify relevant road segments by using a modified dijkstra algorithm to traverse a K-dimensional Tree data structure with weighted edges that generates the shortest path from point a to b. We decided that the edge weights should be calculated using a cost function based on multiplying time, crime severity score, and distance, in which the algorithm finds the closest unvisited node to take its next direction.

### Challenges we ran into

The public records site with the dataset we were scraping from coincidentally began requiring auth for API requests the second day of the hackathon, leaving us very confused. Luckily we found a workaround. Figuring out how to incorporate road pathing (valid path recognition) was very difficult considering that we had to still have the algorithm optimize for safety.

### Accomplishments we're proud of

The routing algorithm Very strong image recognition accuracy Frontend Development Team communication

### What we learned

Docker Postgresql Mapbox Common routing/pathing algorithms

### What's next

Next, we plan on expanding the platform to have even more advanced routing for safest routes and customized settings. We would also like for SafeRoute to eventually be compatible with Google Maps because of the user concentration. Additionally, we would like to have live rerouting in the case of new incidents.

## README (from the GitHub repository)

# 🛡️ SAFEPATH - Crime-Aware Route Planning System

<div align="center">

**A 36-hour CalHacks project revolutionizing personal safety through intelligent route optimization**

*Don't just get there fast. Get there safe.*

[![FastAPI](https://img.shields.io/badge/FastAPI-005571?style=flat&logo=fastapi)](https://fastapi.tiangolo.com/)
[![React](https://img.shields.io/badge/React-20232A?style=flat&logo=react&logoColor=61DAFB)](https://reactjs.org/)
[![PostgreSQL](https://img.shields.io/badge/PostgreSQL-316192?style=flat&logo=postgresql&logoColor=white)](https://www.postgresql.org/)
[![Mapbox](https://img.shields.io/badge/Mapbox-000000?style=flat&logo=mapbox&logoColor=white)](https://www.mapbox.com/)
[![Groq](https://img.shields.io/badge/Groq-AI-orange)](https://groq.com/)

**🏆 Built for: Best Beginner Project • Best Use of Letta • Social Impact**

</div>

---

## 📋 Table of Contents

- [The Problem](#-the-problem)
- [Our Solution](#-our-solution)
- [2-Minute Demo Overview](#-2-minute-demo-overview)
- [Key Features](#-key-features)
- [Technical Innovation](#-technical-innovation)
- [System Architecture](#-system-architecture)
- [Technology Stack](#-technology-stack)
- [Getting Started](#-getting-started)
- [Usage](#-usage)
- [API Documentation](#-api-documentation)
- [Algorithm Deep Dive](#-algorithm-deep-dive)
- [Project Structure](#-project-structure)
- [Data Sources](#-data-sources)
- [36-Hour Build Journey](#-36-hour-build-journey)
- [Contributing](#-contributing)

---

## 🚨 The Problem

**Nowadays, people only prioritize speed when getting places. But what about safety?**

Look at San Francisco:
- 📈 **Frequent break-ins** and property crimes
- 🌃 **High crime rates** especially during night hours  
- 🚶 **Unsafe night-walking** conditions in many neighborhoods
- ⚠️ **12+ WarnMe alerts** sent to students last month alone

### The Gap in Current Solutions

Traditional navigation apps like Google Maps and Apple Maps focus **exclusively on speed and distance**. They'll route you through high-crime areas to save 2 minutes, potentially putting your safety at risk.

**We built SAFEPATH to change that.**

---

## 💡 Our Solution

**SAFEPATH generates time and safety optimized routes** that help you travel confidently, especially during vulnerable hours.

### How It Works

1. **Real-Time Crime Intelligence**
   - Scrapes police reports, government APIs, and community submissions
   - Updates database every 24 hours with fresh incident data
   - Aggregates crimes into probability clusters using spatial analysis

2. **Dual-Route Generation**
   - **Faster Route**: Shorter distance but lower safety score (may pass through risk zones)
   - **Safer Route**: Slightly longer but avoids high-crime areas with higher safety score
   - Users see **visual comparison** with time estimates and safety ratings

3. **Intelligent Decision Making**
   - Modified Dijkstra's algorithm with weighted edges
   - Cost function: `distance × time × crime_severity_score`
   - Recent crimes (≤24 hours) weighted **extremely heavily** to ensure avoidance

---

## 🎬 2-Minute Demo Overview

### Demo Flow

1. **Opening Hook** (0:00-0:30)
   > "Who's felt unsafe walking on campus at night? Last month: 12 WarnMe alerts in Berkeley. But these don't help if you're already in danger. We built SAFEPATH."

2. **Show The Data** (0:30-1:00)
   - Display interactive crime heatmap (red = dangerous zones)
   - Click on crime marker: "Armed robbery 3 days ago"
   - Emphasize: "Real police data, updates every 24 hours"

3. **Core Routing Demo** (1:00-1:45)
   - Set start point (library) and end point (apartment)
   - System calculates TWO routes:
     - **🔵 Fastest Route**: 8 min, passes through high-crime area
     - **🟢 Safer Route**: 11 min, avoids danger zones
   - "Just 3 extra minutes for significantly improved safety"
   - Visual shows red sections in path have higher historical crime density

4. **AI Image Analysis** (1:45-2:00)
   - Show incident reporting feature
   - Upload image of suspicious activity
   - "Groq AI **instantly assesses** crime type from image"
   - Converted to severity level, added back to database
   - Shown live on map to alert other users

### Key Demo Talking Points

✅ **"Crimes within 24 hours are weighted extremely heavily"** - Show how recent incident forces route detour  
✅ **"Modified Dijkstra on K-dimensional tree"** - Technical depth for judges  
✅ **"Community-driven safety"** - User reports feed back into system  
✅ **"Works on any campus or city"** - Scalability and impact

---

## 🌟 Overview

**SAFEPATH** is an intelligent safety navigation system that helps users plan routes while avoiding high-crime areas. Built in 36 hours for CalHacks, it combines real-time crime data aggregation, advanced graph algorithms, and AI-powered community reporting to create a truly safety-first navigation experience.

### Why SAFEPATH?

- **Real-Time Crime Data**: 92,256+ crime records with 24-hour incremental syncing
- **Modified Dijkstra Algorithm**: Custom path-finding that balances distance and danger
- **AI Image Analysis**: Groq-powered instant crime categorization from photos
- **Visual Safety Insights**: Interactive heatmaps and crime density visualization
- **Community Intelligence**: User reports immediately integrated into routing decisions

---

## 🔬 Technical Innovation

### Modified Dijkstra's Algorithm on K-Dimensional Tree

SAFEPATH doesn't use standard shortest-path algorithms. We implemented a **custom weighted graph traversal** that treats safety as a first-class citizen alongside distance.

#### The Algorithm

```python
# Edge Weight Calculation
edge_weight = distance × time × crime_severity_score

# For each road segment:
1. Query crimes within 100m radius
2. Apply time-decay function to each crime
3. Calculate danger contribution
4. Find closest unvisited node with lowest total cost
```

#### Time Decay Function (Critical Innovation)

| Crime Age | Weight Multiplier | Impact |
|-----------|-------------------|---------|
| < 24 hours | **1.0** | Full weight - route **ALWAYS** avoids |
| 1-7 days | 0.9 → 0.3 | Decreasing influence |
| 7-30 days | 0.2 | Low weight |
| > 30 days | 0.05 | Minimal consideration |

**Key Insight**: Recent crimes (≤24 hours) are weighted so heavily that the algorithm **almost always** ensures routes don't pass through hot locations, even if it means significant detours.

#### Data Structure

- **Graph**: K-dimensional tree with geospatial indexing
- **Nodes**: Street intersections with GPS coordinates
- **Edges**: Road segments with dynamic weights
- **Spatial Index**: PostGIS for O(log n) crime proximity queries

#### Route Comparison

The system generates **two distinct routes**:

```python
Faster Route (Distance Priority):
  - Safety Weight: 0.3
  - Distance Weight: 0.7
  - Result: Shorter, may pass through moderate-risk areas

Safer Route (Safety Priority):
  - Safety Weight: 0.9
  - Distance Weight: 0.1
  - Result: Longer, actively avoids all high-crime zones
```

**Visual Proof**: Red sections in the path indicate historically higher crime density - the safer route intelligently navigates around these zones.

---

## ✨ Key Features

### 🗺️ Crime-Aware Routing
- **Dual-Route Algorithm**: Generates both fastest and safest options simultaneously
- **Dynamic Safety Scoring**: Real-time recalculation based on latest crime data
- **24-Hour Hotspot Avoidance**: Recent crimes trigger automatic route changes
- **Visual Comparison**: Side-by-side time vs. safety trade-off analysis

### 📊 Safety Analytics
- **Point Safety Analysis**: Get safety scores for specific locations
- **Route Safety Analysis**: Comprehensive safety evaluation along entire paths
- **Crime Heatmaps**: Visual representation of high-risk zones
- **Trend Analysis**: Historical crime pattern insights (up to 1 year)

### 🚨 Real-Time Alerts
- **High Crime Area Alerts**: Notifications when 3+ crimes occur in same location
- **Severity Warnings**: Alerts for

[README truncated for size]

## Detected evidence (automated analysis)

Indexed codebase: 76 recognized source files, 556 KB.
- CSS (language) — detected in the code
- FastAPI (technology) — detected in the code
- HTML (language) — detected in the code
- JavaScript (language) — detected in the code
- Python (language) — detected in the code
- React (technology) — detected in the code
- Docker (technology) — claimed on Devpost, not found in the code
- PostgreSQL (technology) — claimed on Devpost, not found in the code
- SQL (language) — claimed on Devpost, not found in the code
- AI coding agent: Claude Code — evidence: config files committed to the repository
- AI coding agent: Cursor — evidence: config files committed to the repository

## Codebase structure (from repository index)

### Files (120 of 573)

```
.claude/settings.local.json
.cursor/plans/crime-density-9d88838b.plan.md
.cursor/plans/fix-image-preview-31e5bbf2.plan.md
.gitattributes
.gitignore
Backend/.env
Backend/.gitignore
Backend/analyze_data.py
Backend/cache/009fe7578bb9ec51faae02c964b2c369ad346c33.json
Backend/cache/00a415373a588b7aed80f6f8dee236c578e93463.json
Backend/cache/019fa38c2891f41510183e2ed06384aa8f4657d2.json
Backend/cache/026099865186d5a410b52dcd4c53c67ef2066c49.json
Backend/cache/0283b6fec0272b936be59ae00ea544b15d063ae4.json
Backend/cache/02b1f1b9682544c2a805dfab6ea5c3adf62cedcc.json
Backend/cache/02f974d5bb9d0400325b3b84e82b2e4fb3a32c34.json
Backend/cache/0344f654ee4dba7994a838352024a9bde6a8bdca.json
Backend/cache/0363b5ad70ec487363ce199d938d226e492139e4.json
Backend/cache/03a389e4e43ab756d0ef72a46afffc0af353aaf3.json
Backend/cache/03d34c2c132a0af9ce289278d3c71d0da31ecc02.json
Backend/cache/0499725d8777021a3f8bc8b84356c78b9990de2c.json
Backend/cache/04f379d86f5b99194aa436df72d3f11cb04af512.json
Backend/cache/04f7ab4cbf8c47d50bbe6f91eb27a63527c2485f.json
Backend/cache/04fab179d6a2e78d8253fa1dbd7fcade1dbaa49f.json
Backend/cache/04fcb19ee07c35117b1a0d9afc71e73353cd8df9.json
Backend/cache/053851e57aa78b8a95269c85e2ffa5ed9cc22b37.json
Backend/cache/0599acc2338807465ce2b13c9dcd913c54fa3f12.json
Backend/cache/05cfd9930b5005b127241c36d5c1e75644da052a.json
Backend/cache/061b3768a368a384eb94dc3f16365c71082b9268.json
Backend/cache/07095e45c6422e66b773349e8a0ec45e3f2941b7.json
Backend/cache/077d655fc993ebdc3cdfc18260572e09270662e3.json
Backend/cache/07b435faf28bfb418c36afa90413c84e29faf5d1.json
Backend/cache/087612fc5c08c835feb0c9d58e3db31de2851c22.json
Backend/cache/08b8d805c6e9bee4e8a2b81478165beb465aa4d6.json
Backend/cache/096e8d63726a084b5fc17177f1e97e1c66e7b55e.json
Backend/cache/09d9d3f0b409a372cdbc05b180263833b02a7b35.json
Backend/cache/0aa9640aa255f9a5b1857901834aa2722a1b93a9.json
Backend/cache/0aaae0c812de99a2137539467b0f012713f9e848.json
Backend/cache/0adc69de7d96e80b5f9a87d17362c8de5308e503.json
Backend/cache/0b7ffab82635bcf2ac5d9599f3c537c35503e3df.json
Backend/cache/0c430b08df526da663ac8134b131d8213c039f02.json
Backend/cache/0c7420f0fac9ed02132c3b683c3d07e2274ca3bd.json
Backend/cache/0caf50b7a826ad83a024b41721c8d0876ea929d3.json
Backend/cache/0cc52d7491ba558829173414bdb729dd142c9149.json
Backend/cache/0d1969c4fb3539e4ab40e9f3978bc0b6dec5269f.json
Backend/cache/0ecce6eeabcda9147b194f5307ea8798c3b550d4.json
Backend/cache/0f955dfa96118fb2d881e458490bc263e3a00cb6.json
Backend/cache/0fbc666dd7cb261c5fcff590af81813c1568a8e7.json
Backend/cache/0fc12c65a66705cbd259006fce79ad4cb79e837c.json
Backend/cache/1049ae9d7b0afa99d357dff357d0810931a6f8ce.json
Backend/cache/10e29b0922e102a0d20cce912fdda1197b90ebd1.json
Backend/cache/1159fd308026ea987ebaa4e39663492138a6805e.json
Backend/cache/11628dd16b84f52c100f038b00e3a9e2c029d9ba.json
Backend/cache/1175ea9df040cac94070599597cfdc4609e914e9.json
Backend/cache/1310fbbfa7022729855674c74462413373ea90fd.json
Backend/cache/139cea569977ebb9b7c54e00e1493fdb81a7c661.json
Backend/cache/14e6741961b6af946119feb0f7b3b226557691f0.json
Backend/cache/1539ecc9c23d0dde59245d08f0eb45ceaa1f42ce.json
Backend/cache/155d4099119974cdcbb9fad0d6b624967753e8d0.json
Backend/cache/1585c28012855b4e3149661f5401323b43f29176.json
Backend/cache/16268dceb662550ba72c3a0e0f7e5c4d8a8e7836.json
Backend/cache/1689a43dc58332a7304f4f641ccced8a589068f9.json
Backend/cache/1720520f3fd760ba9b72ee2e1086eb17f193918d.json
Backend/cache/180e0d7bc505d4d95c99bc5b2eac63823ddec44e.json
Backend/cache/18f8ff85d9bf42f2efd6f58ae019876797f868a2.json
Backend/cache/19568c726b110109ddf7de3c32f923f9aa36f1a5.json
Backend/cache/19a1d5bb92a45317cb45dc2462e68cf86e634114.json
Backend/cache/1a559d269ac4a12f417db3891f1a2026b6cb5cc6.json
Backend/cache/1aa64a72a2470769c1440e0bdb27919567ba5548.json
Backend/cache/1b0422fa790f5e613261d40c0947a3206ccd9bf2.json
Backend/cache/1b1eb6840e77d28b93041ad091f04582c5e9ea6e.json
Backend/cache/1bacadc9b0960d286e42419eaf2db0ba02139411.json
Backend/cache/1bed83b3cfc4cc7db2fed21c7ca826fff6cd26a1.json
Backend/cache/1cb11a77c4fbbfba13d7b5b8d438f99aa0c481b4.json
Backend/cache/1d0ab5fc74563ca45a55e6c38f6a2fa2936cce72.json
Backend/cache/1d2a5e3c5820695b5c080df7976f802d7c033573.json
Backend/cache/1d51267104fb812baf8c14f574178272538be18a.json
Backend/cache/1d6a3f7f5dc87d356774b3b7c3d01b37db35ff83.json
Backend/cache/1e0ac55a4a21c14a74fd429b0b357a3d50362d6e.json
Backend/cache/1e1da9b433e1a94d4eaf617b631ec5f82e187b14.json
Backend/cache/1ef63924661c2e882f163b350652f6d35fe9e0cf.json
Backend/cache/1f4bff5ed536c22704a570584700db496c2a2e90.json
Backend/cache/1f897dad7839189fc20c082518ba268a712781ef.json
Backend/cache/20dd71cadaf937ae0b8277f1afa7c1708838c66a.json
Backend/cache/212dfbb4a0d3f4a14c3463953c8c5e0699fe1599.json
Backend/cache/220cfc6f043925b90796c31a59c737be65bc9372.json
Backend/cache/228a0bc7fd15d192d3b99a69acc9f359f61f0214.json
Backend/cache/22bc87817df0521794e9b90ed233949ce957acf3.json
Backend/cache/22ed80e57e69e98d4474d5e79eb2ebec134fb9c9.json
Backend/cache/23804c9374e33710f8c9e85118e7e1cbe2e1841d.json
Backend/cache/260fb3003e843ce9b1033e8290c123f7dac8b17c.json
Backend/cache/262909e7e49800490720a5d87d5e5dd3eb836402.json
Backend/cache/2665bb100bdd8c54f50f40a1d5e94fcf6d26f08b.json
Backend/cache/268944b75cb8b5e0e27822829cac414431262446.json
Backend/cache/269febdf55b8650b576cac8b20119a1581995129.json
Backend/cache/26a88d0c617a0a48991362e4ec7903aaf28c1829.json
Backend/cache/281da81045a971e240914e3a7898292fe3b2a70a.json
Backend/cache/29571b5dd9910bce8124776a7620b03b6dcd2fdc.json
Backend/cache/29cbb82f429616cb71126db227198b8e33ecd987.json
Backend/cache/29df0a5e0147669f3563144a16b94cfa5a4c3242.json
Backend/cache/2a6d2f657e9a54d78daa4c2c43ddc1518c6d6914.json
Backend/cache/2acdcc99906e4fa12dccd0bd047174fe0519193b.json
Backend/cache/2dad4ac9f19ddbd835e2bcc006ed10c507fbdd94.json
Backend/cache/2de1d7fcb725ca4072c3cef39595ca455cadedb1.json
Backend/cache/2f5e8b1e49ca198fd28da39efbc20f9aa0e1eb1f.json
Backend/cache/30402b426158fc656606c48de9465f9c70751952.json
Backend/cache/30e9e72bd020d2e0c5ba844e9c54a81855307509.json
Backend/cache/3119c65bf0a0288d9f14554d3f4a22e339cd0f12.json
Backend/cache/311e441fc1942207ba9b0def39d99677c2c46237.json
Backend/cache/31559dd32a59483d2478723cb7702fd009a016ab.json
Backend/cache/31c920f899a0128ccaff6a3d89b2bd2f91dcdc3d.json
Backend/cache/324764ac5a40a7a2e6adfaee837a6a611d20619c.json
Backend/cache/326a56730f4c1ec67ef284500ee0979e08272253.json
Backend/cache/32a7f498d33570fa8e476ad53250dd055daf8717.json
Backend/cache/32f5aad9588e8b5cb9d16df37d0ed6ee02cbcd00.json
Backend/cache/33111cd38f8861ba170cbd0724b8be658b1b7f3a.json
Backend/cache/34e6c5e0469365daefbfe74500150be85251c2b4.json
Backend/cache/351d03ebe44f3be16ba2fb6025ea88ee1bb8645a.json
Backend/cache/3546ede473f5cd1ba5ea5b4a6a529a6a22b4c242.json
Backend/cache/354b374356cee4cc35a2ce09d1f02eb32ab5ff59.json
Backend/cache/36631d902613e5ca80131ccad030b9c46f7b7d8f.json
[453 more files omitted for size]
```

### Dependencies

- Backend/requirements.txt: aiohttp@==3.9.1, asyncpg@==0.29.0, beautifulsoup4@==4.12.2, fastapi@==0.104.1, geoalchemy2@==0.14.2, groq@==0.4.1, httpx@==0.27.0, numpy@>=1.26.0, pandas@>=2.2.0, psycopg2-binary@==2.9.11, pydantic@==2.5.0, python-dotenv@==1.0.0, python-multipart@==0.0.6, requests@==2.31.0, schedule@==1.2.0, selenium@==4.15.2, sqlalchemy@==2.0.23, uvicorn@==0.24.0
- frontend/package.json: axios@^1.5.0, mapbox-gl@^2.15.0, react@^18.2.0, react-dom@^18.2.0, react-icons@^4.12.0, react-router-dom@^6.20.0, react-scripts@5.0.1

### Recent commits (newest first)

- w
- w
- w
- w
- w
- maps n shi prototype
- d
- w
- w
- visual map interface improvements
- w
- remove the venv eek
- MapInterfaceForm
- Merge branch 'main' of https://github.com/Christopher-Vu/TheTakeoutBoxCalHacks
- mapinterfaceform
- w
- w
- Merge branch 'main' of https://github.com/Christopher-Vu/TheTakeoutBoxCalHacks
- fuck this ts
- Merge branch 'main' of https://github.com/Christopher-Vu/TheTakeoutBoxCalHacks

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

### docs/API.md

```markdown
# API Documentation

## Overview
This document describes the REST API endpoints for TheTakeoutBoxCalHacks application.

## Endpoints

### Crime Data
- `GET /api/crimes` - Retrieve crime data
- `GET /api/crimes/{id}` - Get specific crime details

### Routing
- `POST /api/routes` - Calculate safe routes between points
- `GET /api/routes/{id}` - Get route details

### Locations
- `POST /api/locations` - Save user locations
- `GET /api/locations` - Retrieve saved locations
- `DELETE /api/locations/{id}` - Remove saved location

### Letta Integration
- `POST /api/memory` - Store memory with Letta
- `GET /api/memory` - Retrieve memories

```

### docs/DEMO_SCRIPT.md

```markdown
# Demo Script

## Presentation Flow

### 1. Introduction (2 minutes)
- Problem: Students need safe routes for food delivery
- Solution: Crime-aware routing with Letta memory integration

### 2. Live Demo (5 minutes)
- Show map interface with crime data overlay
- Demonstrate route comparison
- Save locations (Home/Work) with Letta integration
- Show memory persistence across sessions

### 3. Technical Highlights (3 minutes)
- Real-time crime data scraping
- Advanced routing algorithms
- Letta memory system for user preferences
- Responsive React frontend

### 4. Q&A (2 minutes)
- Address questions about scalability
- Discuss future enhancements
- Technical implementation details

## Demo Scenarios
1. **New User**: First-time setup with location saving
2. **Returning User**: Quick access to saved locations
3. **Route Comparison**: Show multiple route options with crime data
4. **Memory Integration**: Demonstrate Letta's learning capabilities

```

### docker-compose.yml

```yaml
version: '3.8'

services:
  postgres:
    image: postgis/postgis:15-3.3
    environment:
      POSTGRES_DB: safepath_spatial
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: password
    ports:
      - "5432:5432"
    volumes:
      - postgres_data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 10s
      timeout: 5s
      retries: 5

  init-db:
    build: ./backend
    environment:
      - DATABASE_URL=postgresql://postgres:password@postgres:5432/safepath_spatial
    depends_on:
      postgres:
        condition: service_healthy
    volumes:
      - ./backend:/app
      - ./scraper:/app/scraper
    working_dir: /app
    command: python init_database.py

  scraper:
    build: ./backend
    environment:
      - DATABASE_URL=postgresql://postgres:password@postgres:5432/safepath_spatial
    depends_on:
      init-db:
        condition: service_completed_successfully
    volumes:
      - ./backend:/app
      - ./scraper:/app/scraper
    working_dir: /app
    command: python -c "import asyncio; from real_time_fetcher import fetch_real_time_data; asyncio.run(fetch_real_time_data())"

  app:
    build: ./backend
    ports:
      - "8000:8000"
    environment:
      - DATABASE_URL=postgresql://postgres:password@postgres:5432/safepath_spatial
      - MAPBOX_ACCESS_TOKEN=pk.eyJ1IjoiYW5keXltYW9vIiwiYSI6ImNtaDYzMGhrdzA4dnAya29vbW4wcHZ6ODEifQ.NNhIooCa7yGJzYEegxEdAw
    depends_on:
      init-db:
        condition: service_completed_successfully
    volumes:
      - ./backend:/app
      - ./scraper:/app/scraper
    command: uvicorn main:app --host 0.0.0.0 --port 8000 --reload

volumes:
  postgres_data:

```

### Backend/requirements.txt

```
fastapi==0.104.1
uvicorn==0.24.0
sqlalchemy==2.0.23
aiohttp==3.9.1
pandas>=2.2.0
numpy>=1.26.0
requests==2.31.0
python-multipart==0.0.6
pydantic==2.5.0
python-dotenv==1.0.0
schedule==1.2.0
beautifulsoup4==4.12.2
selenium==4.15.2
groq==0.4.1
httpx==0.27.0

# PostgreSQL + PostGIS dependencies
psycopg2-binary==2.9.11
geoalchemy2==0.14.2
asyncpg==0.29.0

```

### Backend/Dockerfile

```
FROM python:3.11-slim

WORKDIR /app

# Install system dependencies
RUN apt-get update && apt-get install -y \
    gcc \
    g++ \
    libpq-dev \
    && rm -rf /var/lib/apt/lists/*

# Copy requirements and install Python dependencies
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# Copy application code
COPY . .

# Expose port
EXPOSE 8000

# Run the application
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]

```

### frontend/package.json

```
{
  "name": "thetakeoutbox-frontend",
  "version": "1.0.0",
  "private": true,
  "dependencies": {
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "react-scripts": "5.0.1",
    "react-router-dom": "^6.20.0",
    "react-icons": "^4.12.0",
    "mapbox-gl": "^2.15.0",
    "axios": "^1.5.0"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": [
      "react-app",
      "react-app/jest"
    ]
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  }
}

```

### frontend/src/index.js

```javascript
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);

```

### frontend/src/App.jsx

```javascript
import React from 'react';
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
import LandingPage from './components/LandingPage';
import ReportIncident from './components/ReportIncident';
import RoutePlanning from './components/RoutePlanning';

function App() {
  return (
    <Router>
      <div className="app">
        <Routes>
          <Route path="/" element={<LandingPage />} />
          <Route path="/report-incident" element={<ReportIncident />} />
          <Route path="/route-planning" element={<RoutePlanning />} />
        </Routes>
      </div>
    </Router>
  );
}

export default App;

```

### Backend/main.py

```python
"""
Enhanced API endpoints for SAFEPATH crime data aggregation
Supports multiple data sources with comprehensive filtering and analytics
"""

from fastapi import FastAPI, HTTPException, Query, Depends, Form, File, UploadFile
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import JSONResponse
from typing import List, Dict, Optional, Any
from datetime import datetime, timedelta
import logging
import json
import os
import sys
import uuid
import base64
from dotenv import load_dotenv

# Load environment variables
load_dotenv()

# Import Groq at module level to catch import errors early
try:
    from groq import Groq
    GROQ_AVAILABLE = True
    print("Groq module imported successfully")
except ImportError as e:
    print(f"Groq import failed: {e}")
    print(f"Python path: {sys.path}")
    print(f"Python executable: {sys.executable}")
    GROQ_AVAILABLE = False

# Import modules that may not exist yet - handle gracefully
try:
    from database_sqlite import db_manager, CrimeReport
    from data_manager import DataManager
    from incremental_sync import IncrementalSync
    # Instantiate the classes
    data_manager = DataManager()
    incremental_sync = IncrementalSync()
except ImportError:
    print("Warning: database module not found. Some features will be disabled.")
    db_manager = None
    CrimeReport = None
    data_manager = None
    incremental_sync = None

try:
    from safety_analyzer import SafetyAnalyzerAPI
    from safe_router import SafeRouterAPI
    from crime_aware_router import CrimeAwareRouter
    from real_time_alerts import RealTimeAlertsAPI
except ImportError:
    print("Warning: Safety analysis modules not found. Some features will be disabled.")
    SafetyAnalyzerAPI = None
    SafeRouterAPI = None
    CrimeAwareRouter = None
    RealTimeAlertsAPI = None

try:
    from data_aggregator import aggregator, SourceType
except ImportError:
    print("Warning: data_aggregator module not found. Some features will be disabled.")
    aggregator = None
    SourceType = None

try:
    from routing import calculate_routes
except ImportError:
    print("Warning: routing module not found. Using mock routing.")
    def calculate_routes(start, end, safety_weight):
        return {
            "fastest_route": {"path": [start, end], "distance": 1000, "time": 8, "safety_score": 6},
            "safest_route": {"path": [start, end], "distance": 1200, "time": 11, "safety_score": 8},
            "crime_points": []
        }

import json

# Configure logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

# Initialize FastAPI app
app = FastAPI(
    title="SAFEPATH Crime Data API",
    description="Multi-source crime data aggregation and routing API",
    version="1.0.0"
)

# CORS middleware
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],  # Configure appropriately for production
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

# Initialize database if available
if db_manager:
    try:
        db_manager.create_tables()
        print("Database tables created successfully")
    except Exception as e:
        print(f"Warning: Could not create database tables: {e}")
else:
    print("Warning: Database not available. Some features will be disabled.")

# Initialize crime-aware router
crime_router = None
if CrimeAwareRouter is not None:
    try:
        database_url = "postgresql://postgres:password@postgres:5432/safepath_spatial"
        crime_router = CrimeAwareRouter(database_url)
        print("Crime-aware router initialized successfully")
    except Exception as e:
        print(f"Warning: Could not initialize crime-aware router: {e}")
        crime_router = None

@app.get("/")
async def health_check():
    """Health check endpoint"""
    return {"status": "ok", "message": "SAFEPATH API is running"}

@app.get("/crimes")
async def get_crimes(
    min_lat: float = Query(..., description="Minimum latitude"),
    max_lat: float = Query(..., description="Maximum latitude"),
    min_lng: float = Query(..., description="Minimum longitude"),
    max_lng: float = Query(..., description="Maximum longitude"),
    crime_types: Optional[str] = Query(None, description="Comma-separated crime types"),
    severity_min: Optional[int] = Query(None, description="Minimum severity (1-10)"),
    days_back: Optional[int] = Query(30, description="Days back to include"),
    sources: Optional[str] = Query(None, description="Comma-separated data sources"),
    include_duplicates: bool = Query(False, description="Include duplicate reports")
):
    """Get crimes within geographic bounds with filtering"""
    try:
        # Parse filters
        crime_type_filter = crime_types.split(',') if crime_types else None
        source_filter = sources.split(',') if sources else None
        
        # Calculate date filter
        date_filter = datetime.utcnow() - timedelta(days=days_back)
        
        # Get crimes from database
        if db_manager:
            crimes = db_manager.get_crimes_in_bounds(min_lat, max_lat, min_lng, max_lng)
        else:
            crimes = []  # Return empty list if database not available
        
        # Apply filters
        filtered_crimes = []
        for crime in crimes:
            # Date filter
            if crime.get('occurred_at'):
                crime_date = datetime.fromisoformat(crime['occurred_at'].replace('Z', '+00:00'))
                if crime_date < date_filter:
                    continue
            
            # Crime type filter
            if crime_type_filter and crime['crime_type'] not in crime_type_filter:
                continue
            
            # Severity filter
            if severity_min and crime['severity'] < severity_min:
                continue
            
            # Source filter
            if source_filter and crime['source'] not in source_filter:
                continue
            
            # Duplicate filter
            if not 
[truncated — 32856 more characters]
```

### diagnose_backend.py

```python
"""
Diagnostic script to check backend status
"""
import socket
import sys

def check_port(host='localhost', port=8000):
    """Check if port is open"""
    print(f"\n=== Checking Port {port} ===")
    try:
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.settimeout(2)
        result = sock.connect_ex((host, port))
        sock.close()

        if result == 0:
            print(f"Port {port} is OPEN and accepting connections")
            return True
        else:
            print(f"Port {port} is CLOSED (error code: {result})")
            return False
    except Exception as e:
        print(f"Error checking port: {e}")
        return False

def check_http_response(host='localhost', port=8000):
    """Try to get HTTP response"""
    print(f"\n=== Testing HTTP Response ===")
    try:
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.settimeout(5)
        sock.connect((host, port))

        # Send HTTP GET request
        request = b"GET / HTTP/1.1\r\nHost: localhost\r\n\r\n"
        sock.sendall(request)

        # Try to receive response
        response = sock.recv(1024)
        sock.close()

        if response:
            print(f"Received response ({len(response)} bytes):")
            print(response.decode('utf-8', errors='ignore')[:500])
            return True
        else:
            print("No response received (server not responding to HTTP)")
            return False

    except socket.timeout:
        print("TIMEOUT: Server accepted connection but didn't respond")
        print("This usually means:")
        print("  - Server process is hung")
        print("  - Wrong application running on port")
        print("  - Database connection blocking the server")
        return False
    except Exception as e:
        print(f"Error: {e}")
        return False

def check_database_connection():
    """Check if we can import required modules"""
    print(f"\n=== Checking Dependencies ===")
    modules = ['fastapi', 'uvicorn', 'sqlalchemy', 'asyncpg', 'psycopg2']

    for module in modules:
        try:
            __import__(module)
            print(f"OK: {module}")
        except ImportError:
            print(f"MISSING: {module}")

if __name__ == "__main__":
    print("="*60)
    print(" Backend Diagnostic Tool")
    print("="*60)

    port_open = check_port()

    if port_open:
        http_ok = check_http_response()

        if not http_ok:
            print("\nRECOMMENDATION:")
            print("  The port is open but not responding to HTTP requests.")
            print("  You may need to:")
            print("    1. Stop the hung process")
            print("    2. Check database connectivity")
            print("    3. Restart the backend server")
    else:
        print("\nRECOMMENDATION:")
        print("  Backend server is not running.")
        print("  Start it with: python Backend/main.py")

    check_database_connection()

    print("\n" + "="*60)

```

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