Frontend: A React + TypeScript + Tailwind CSS Chrome extension that calculates monthly energy costs for San Francisco listings and provides safe route planning.
Backend: A Flask-based backend API for estimating monthly electricity bills for SF residential apartments using building energy data and safety analysis.
โโโ backend/
โ โโโ app.py # Main Flask application
โ โโโ data_processor.py # CSV data loading and processing
โ โโโ address_matcher.py # Fuzzy address matching
โ โโโ bill_estimator.py # Core estimation algorithms
โ โโโ seasonality_factors.py # Monthly usage patterns
โ โโโ rate_calculator.py # PG&E utility rate calculations
โ โโโ safety_analyzer.py # SF crime and safety analysis
โ โโโ route_analyzer.py # Route planning and analysis
โ โโโ reviews_analyzer.py # AI-powered reviews analysis
โ โโโ SF_Building_Energy_Filtered_Clean.csv # SF building energy data
โโโ frontend/ # Chrome extension
โโโ safe-route/ # Next.js route planner
โโโ env/ # Python virtual environment
- Activate virtual environment:
source env/bin/activate- Install dependencies:
cd backend
pip install -r requirements.txt- Ensure the SF data file is present:
ls -la SF_Building_Energy_Filtered_Clean.csv- Test the system:
python test_system.py- Start the Flask application:
python app.pyThe API will be available at http://localhost:5000 (or dynamically assigned port)
- Install dependencies:
cd frontend
npm install- Build the extension:
npm run build:extension- Install dependencies:
cd safe-route
npm install- Start development server:
npm run dev- Open Chrome and navigate to
chrome://extensions/ - Enable "Developer mode" (toggle in top right)
- Click "Load unpacked"
- Select the
frontend/distfolder (created after building) - The extension will appear in your Chrome toolbar
GET /healthPOST /api/estimate
Content-Type: application/json
{
"address": "1015 Ashbury St, San Francisco",
"num_rooms": 2,
"apartment_type": "1br",
"building_type": "residential",
"include_demand_charges": false
}POST /api/safety
Content-Type: application/json
{
"address": "1015 Ashbury St, San Francisco"
}GET /api/search?q=Ashbury&limit=5GET /api/building/<property_id>- Base Consumption: Uses building's weather-normalized electricity intensity (kWh/ftยฒ)
- Apartment Sizing: Estimates apartment size based on room count
- Building Efficiency: Adjusts for building age and type
- Seasonality: Applies SF-specific monthly usage patterns
- Rate Calculation: Uses current PG&E rate structures
# Building efficiency by age
if year_built >= 2010: efficiency_factor = 0.85 # More efficient
elif year_built >= 1980: efficiency_factor = 1.00 # Average
else: efficiency_factor = 1.10 # Less efficient
# Apartment size estimates (SF adjusted)
apartment_sizes = {
0: 400, # Studio
1: 650, # 1BR
2: 850, # 2BR
3: 1100, # 3BR
4: 1400 # 4BR+
}
# Seasonal factors (SF climate)
monthly_factors = {
1: 1.15, # January (mild winter)
7: 1.10, # July (cool summer)
5: 0.90 # May (pleasant weather)
}# Estimate bill for 2BR apartment
curl -X POST http://localhost:5000/api/estimate \
-H "Content-Type: application/json" \
-d '{
"address": "1015 Ashbury St, San Francisco",
"num_rooms": 2,
"apartment_type": "1br"
}'
# Safety analysis
curl -X POST http://localhost:5000/api/safety \
-H "Content-Type: application/json" \
-d '{
"address": "1015 Ashbury St, San Francisco"
}'
# Search for buildings
curl "http://localhost:5000/api/search?q=Ashbury&limit=5"import requests
# Estimate electricity bill
response = requests.post('http://localhost:5000/api/estimate', json={
'address': '1015 Ashbury St, San Francisco',
'num_rooms': 2,
'apartment_type': '1br',
'building_type': 'residential'
})
if response.status_code == 200:
data = response.json()
print(f"Annual total: ${data['annual_summary']['total_bill']}")
print(f"Average monthly: ${data['annual_summary']['average_monthly_bill']}")
# Safety analysis
safety_response = requests.post('http://localhost:5000/api/safety', json={
'address': '1015 Ashbury St, San Francisco'
})
if safety_response.status_code == 200:
safety_data = safety_response.json()
print(f"Safety rating: {safety_data['safety_rating']}/100"){
"building_info": {
"property_name": "1015 Ashbury St",
"address": "1015 Ashbury St",
"city": "San Francisco",
"neighborhood": "Haight-Ashbury",
"property_type": "Multifamily Housing",
"year_built": "1920",
"building_efficiency": "average"
},
"estimation_parameters": {
"num_rooms": 2,
"estimated_apartment_sqft": 850,
"building_intensity_kwh_per_sqft": 12.5,
"efficiency_factor": 1.10
},
"monthly_estimates": [
{
"month": "January",
"kwh_estimate": 425,
"estimated_bill": 85.50,
"seasonal_factor": 1.15
}
],
"annual_summary": {
"total_kwh": 4200,
"total_bill": 945.00,
"average_monthly_bill": 78.75,
"peak_month": "August",
"peak_bill": 95.20
},
"rate_structure": {
"utility": "PG&E",
"base_charge": 12.50,
"first_tier_rate": 0.28,
"tier_threshold": 300
}
}Update rates in rate_calculator.py:
self.pge_residential = {
'base_charge': 12.50,
'delivery_rate_tier1': 0.15,
'supply_rate': 0.13,
'tier_threshold': 300
}Modify patterns in seasonality_factors.py:
monthly_factors = {
1: 1.15, # January
7: 1.10, # July
# ... other months
}- Building Data: SF Building Energy Benchmark Data (Local Law 20)
- Utility Rates: PG&E 2024 rate schedules
- Seasonality: SF energy usage patterns and mild climate data
- Safety Data: SF Open Data APIs (311 service requests, SFPD crime data)
- Crime Data: SF Police Department Incident Reports (2018-Present)
- Routing: OpenStreetMap routing via OSRM
- Geocoding: Nominatim geocoding service
- Crime Heatmaps: SF crime data visualization
- Annual Data Only: Building data is annual; monthly breakdowns are estimated
- Rate Accuracy: Utility rates change periodically and may not reflect current tariffs
- Building Match: Address matching may not be perfect for all addresses
- Apartment Assumptions: Size estimates are approximations based on room count
- Crime Data: Limited to reported incidents; may not reflect all safety concerns
Run comprehensive tests:
cd backend
python test_system.pyTest individual components:
from data_processor import DataProcessor
from bill_estimator import BillEstimator
# Test data loading
dp = DataProcessor('SF_Building_Energy_Filtered_Clean.csv')
dp.load_data()
# Test estimation
be = BillEstimator(dp)
# ... estimation testsThe API returns appropriate HTTP status codes:
200: Success400: Bad request (missing fields, invalid data)404: Building not found500: Internal server error
- Real-time Rates: Integration with PG&E APIs for current rates
- Weather Data: Historical weather data for better seasonality
- Machine Learning: Improve estimates with ML models
- Time-of-Use: Support for time-of-use rate plans
- Solar Integration: Account for rooftop solar generation
- Enhanced Safety: Real-time crime alerts and neighborhood insights
For issues or questions:
- Check the test script output:
python test_system.py - Review log files for error details
- Verify CSV data integrity and column mappings
This project uses SF open data and is intended for educational/research purposes.