Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
YasserCoconut committed Oct 8, 2024
2 parents 1d95d54 + d3f7077 commit 27c8230
Show file tree
Hide file tree
Showing 9 changed files with 154 additions and 92 deletions.
215 changes: 130 additions & 85 deletions backend/main.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,19 @@
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from fastapi import FastAPI, HTTPException, Depends
from sqlalchemy import create_engine, Column, Integer, String, Float, DateTime
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker, Session
from typing import List
from pydantic import BaseModel
from fastapi.middleware.cors import CORSMiddleware
from datetime import datetime

# Database setu
DATABASE_URL = "postgresql://alibabapost:[email protected]:5432/alibabapost123"

engine = create_engine(DATABASE_URL)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
Base = declarative_base()

app = FastAPI()

# Adding CORS middleware to allow requests from React frontend
Expand All @@ -19,112 +29,147 @@
allow_headers=["*"],
)

# Accident Hotspot model
class AccidentHotspot(BaseModel):
# SQLAlchemy Models
class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True, index=True)
username = Column(String, unique=True, index=True, nullable=False)
password = Column(String, nullable=False)
first_name = Column(String)
last_name = Column(String)
role = Column(String, nullable=False) # 'driver' or 'customer'

class AccidentHotspot(Base):
__tablename__ = 'accident_hotspots'
id = Column(Integer, primary_key=True, index=True)
lat = Column(Float, nullable=False)
lng = Column(Float, nullable=False)
intensity = Column(Integer, nullable=False)
description = Column(String)

class BusyPoint(Base):
__tablename__ = 'busy_points'
id = Column(Integer, primary_key=True, index=True)
lat = Column(Float, nullable=False)
lng = Column(Float, nullable=False)
weekday = Column(String, nullable=False)
time_interval = Column(String, nullable=False)
max_drivers = Column(Integer, nullable=False)
current_drivers = Column(Integer, nullable=False)
assigned_drivers = Column(String) # Comma-separated driver IDs


class UserLogin(BaseModel):
username: str
password: str


# Create tables in the database
Base.metadata.create_all(bind=engine)

# Pydantic Models
class UserCreate(BaseModel):
username: str
password: str
first_name: str = None
last_name: str = None
role: str # 'driver' or 'customer'

class AccidentHotspotCreate(BaseModel):
lat: float
lng: float
intensity: int
description: str

# Updated mock data with accident hotspots in Sharjah, UAE
mock_hotspots = [
{"lat": 25.319000, "lng": 55.375000, "intensity": 6, "description": "High accident risk, close to your location."},
{"lat": 25.3573, "lng": 55.4033, "intensity": 5, "description": "Moderate accident risk, located further away."},
{"lat": 25.3625, "lng": 55.4307, "intensity": 4, "description": "Occasional accidents in residential zone, located far away."},
]

# Busy Point model
class BusyPoint(BaseModel):
class BusyPointCreate(BaseModel):
lat: float
lng: float
weekday: str
time_interval: str
max_drivers: int
current_drivers: int
assigned_drivers: List[str] # Track assigned drivers by their unique IDs

# Request model for updating busy points
class BusyPointUpdateRequest(BaseModel):
lat: float
lng: float
driver_id: str # Unique identifier for the driver (e.g., username)
current_drivers: int = 0
assigned_drivers: List[str] = []

# Dependency to get DB session
def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()

# API Endpoints
@app.post("/signup")
async def signup(user: UserCreate, db: Session = Depends(get_db)):
db_user = db.query(User).filter(User.username == user.username).first()
if db_user:
raise HTTPException(status_code=400, detail="Username already exists")
new_user = User(
username=user.username,
password=user.password,
first_name=user.first_name,
last_name=user.last_name,
role=user.role
)
db.add(new_user)
db.commit()
db.refresh(new_user)
return {"message": "Signup successful"}

# Mock data for busy points for taxi dispatch (added `assigned_drivers` field)
mock_busy_points = [
# Busy point near your location on Monday between 8 PM and 10 PM
{"lat": 25.318250, "lng": 55.374100, "weekday": "Monday", "time_interval": "20:00-22:00", "max_drivers": 3, "current_drivers": 0, "assigned_drivers": []},
@app.post("/login")
async def login(user: UserLogin, db: Session = Depends(get_db)):
# Query the database for the user with given username and password
db_user = db.query(User).filter(User.username == user.username, User.password == user.password).first()

# Another point on Monday but at a different time
{"lat": 25.3500, "lng": 55.4000, "weekday": "Monday", "time_interval": "12:00-14:00", "max_drivers": 2, "current_drivers": 0, "assigned_drivers": []},

# A point for Tuesday for variety
{"lat": 25.3300, "lng": 55.4100, "weekday": "Tuesday", "time_interval": "17:00-19:00", "max_drivers": 4, "current_drivers": 0, "assigned_drivers": []},
]
# If user does not exist, raise an HTTP exception
if not db_user:
raise HTTPException(status_code=400, detail="Incorrect username or password")

# If the user is found, return success with user details
return {
"message": "Login successful",
"first_name": db_user.first_name,
"last_name": db_user.last_name,
"role": db_user.role
}

@app.get("/api/accident-hotspots", response_model=List[AccidentHotspot])
async def get_accident_hotspots():
return mock_hotspots
@app.get("/api/accident-hotspots", response_model=List[AccidentHotspotCreate])
async def get_accident_hotspots(db: Session = Depends(get_db)):
return db.query(AccidentHotspot).all()

@app.get("/api/busy-points", response_model=List[BusyPoint])
async def get_busy_points():
@app.get("/api/busy-points", response_model=List[BusyPointCreate])
async def get_busy_points(db: Session = Depends(get_db)):
# Get current weekday and time
now = datetime.now()
current_weekday = now.strftime("%A")
current_time = now.strftime("%H:%M")

# Filter busy points based on current weekday and time interval
relevant_points = []
for point in mock_busy_points:
if point["weekday"] == current_weekday:
start_time, end_time = point["time_interval"].split("-")
if start_time <= current_time <= end_time and point["current_drivers"] < point["max_drivers"]:
for point in db.query(BusyPoint).all():
if point.weekday == current_weekday:
start_time, end_time = point.time_interval.split("-")
if start_time <= current_time <= end_time and point.current_drivers < point.max_drivers:
relevant_points.append(point)

return relevant_points

@app.post("/api/update-busy-point")
async def update_busy_point(request: BusyPointUpdateRequest):
# Update current drivers count for a busy point when a driver approaches
for point in mock_busy_points:
if point["lat"] == request.lat and point["lng"] == request.lng:
if request.driver_id not in point["assigned_drivers"]:
if point["current_drivers"] < point["max_drivers"]:
point["current_drivers"] += 1
point["assigned_drivers"].append(request.driver_id)
return {"message": "Driver assigned successfully"}
else:
return {"message": "Max drivers reached for this point"}
else:
return {"message": "Driver has already been assigned to this point"}

return {"message": "Busy point not found"}

# User authentication endpoints
class User(BaseModel):
username: str
password: str
first_name: str = None
last_name: str = None

fake_user_db = {}

@app.post("/signup")
async def signup(user: User):
if user.username in fake_user_db:
raise HTTPException(status_code=400, detail="Username already exists")
fake_user_db[user.username] = {
"password": user.password,
"first_name": user.first_name,
"last_name": user.last_name,
}
return {"message": "Signup successful"}

@app.post("/login")
async def login(user: User):
if user.username not in fake_user_db or fake_user_db[user.username]["password"] != user.password:
raise HTTPException(status_code=400, detail="Incorrect username or password")
return {
"message": "Login successful",
"first_name": fake_user_db[user.username]["first_name"],
"last_name": fake_user_db[user.username]["last_name"]
}
async def update_busy_point(request: BusyPointCreate, db: Session = Depends(get_db)):
busy_point = db.query(BusyPoint).filter(BusyPoint.lat == request.lat, BusyPoint.lng == request.lng).first()
if not busy_point:
return {"message": "Busy point not found"}

if request.driver_id not in busy_point.assigned_drivers.split(","):
if busy_point.current_drivers < busy_point.max_drivers:
busy_point.current_drivers += 1
assigned_drivers = busy_point.assigned_drivers.split(",") if busy_point.assigned_drivers else []
assigned_drivers.append(request.driver_id)
busy_point.assigned_drivers = ",".join(assigned_drivers)
db.commit()
db.refresh(busy_point)
return {"message": "Driver assigned successfully"}
else:
return {"message": "Max drivers reached for this point"}
else:
return {"message": "Driver has already been assigned to this point"}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
8 changes: 4 additions & 4 deletions frontend/alibabarta-frontend/src/components/accidentmap.js
Original file line number Diff line number Diff line change
Expand Up @@ -133,8 +133,8 @@ const AccidentMap = ({ onHotspotsNearbyChange }) => {
key={index}
position={[hotspot.lat, hotspot.lng]}
icon={L.icon({
iconUrl: hotspot.intensity > 5 ? `${process.env.PUBLIC_URL}/red_marker.png` : `${process.env.PUBLIC_URL}/yellow_marker.png`,
iconSize: [25, 41],
iconUrl: hotspot.intensity > 5 ? `${process.env.PUBLIC_URL}/icons/redaccidentmarker.png` : `${process.env.PUBLIC_URL}/icons/yellowaccidentmarker.png`,
iconSize: [41, 41],
iconAnchor: [12, 41],
popupAnchor: [1, -34],
})}
Expand All @@ -154,8 +154,8 @@ const AccidentMap = ({ onHotspotsNearbyChange }) => {
key={index}
position={[point.lat, point.lng]}
icon={L.icon({
iconUrl: `${process.env.PUBLIC_URL}/blue_marker.png`,
iconSize: [25, 41],
iconUrl: `${process.env.PUBLIC_URL}/icons/busypointmarker.png`,
iconSize: [41, 41],
iconAnchor: [12, 41],
popupAnchor: [1, -34],
})}
Expand Down
8 changes: 7 additions & 1 deletion frontend/alibabarta-frontend/src/components/loginform.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,13 @@ const LoginForm = ({ onLogin }) => {
setMessage(response.data.message);
onLogin(response.data.first_name, response.data.last_name);
} catch (error) {
setMessage(error.response?.data?.detail || 'Login failed');
if (error.response && error.response.data && typeof error.response.data.detail === 'string') {
setMessage(error.response.data.detail);
} else if (error.response && error.response.data && Array.isArray(error.response.data.detail)) {
setMessage(error.response.data.detail.map((err) => err.msg).join(', '));
} else {
setMessage('Login failed');
}
}
};

Expand Down
15 changes: 13 additions & 2 deletions frontend/alibabarta-frontend/src/components/signupform.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,12 @@ import React, { useState } from 'react';
import axios from 'axios';
import { useNavigate, Link } from 'react-router-dom';



const SignupForm = () => {
const [username, setUsername] = useState('');
const [password, setPassword] = useState('');
const [firstName, setFirstName] = useState('');
const [lastName, setLastName] = useState('');
const [role, setRole] = useState('customer'); // Default role to 'customer'
const [message, setMessage] = useState('');
const navigate = useNavigate();

Expand All @@ -20,6 +19,7 @@ const SignupForm = () => {
password,
first_name: firstName,
last_name: lastName,
role, // Add the role to the request payload
});
navigate('/dashboard');
} catch (error) {
Expand Down Expand Up @@ -68,6 +68,17 @@ const SignupForm = () => {
className="w-full px-4 py-2 border border-gray-300 rounded focus:outline-none focus:ring-primary focus:border-primary"
/>
</div>
<div>
<label className="block mb-1 text-sm font-medium text-gray-700">Role:</label>
<select
value={role}
onChange={(e) => setRole(e.target.value)}
className="w-full px-4 py-2 border border-gray-300 rounded focus:outline-none focus:ring-primary focus:border-primary"
>
<option value="customer">Customer</option>
<option value="driver">Driver</option>
</select>
</div>
<button
type="submit"
className="w-full px-4 py-2 text-white bg-primary rounded hover:bg-red-700 transition duration-200"
Expand Down

0 comments on commit 27c8230

Please sign in to comment.