Leisure is an interactive web application that helps users discover and plan activities based on their available time and preferences. The application uses geolocation to find nearby attractions and provides detailed routing information to help users navigate to their chosen destinations.
Leisure solves the common problem of "What should I do today?" by suggesting personalized leisure activities based on:
- Date and time availability
- How far you're willing to travel
- How much time you have available
- Optional specific destination preferences
- Overview
- Video Preview
- Live Demo
- Team Members
- Team Contributions
- Features
- Local Development
- Core Technologies
- User Flow
- API Integration Flow
- Technology Details
- Screenshots
You can find each project component with these links:
- Javokhir Yuldoshev (Team Leader) [12214760]
- Muhammedov Mironshoh [12225252]
- Ilhomov Mansur [12225247]
- Bakhtiyorov Firdavs [12214762]
- Project architecture and team coordination
- Core application logic implementation
- API endpoint development and integration
- Component integration and deployment
- Documentation and best practices enforcement
- Gemini LLM integration specialist
- Prompt engineering and optimization
- Model selection and evaluation
- Response processing and data transformation
- GraphHopper API integration lead
- Routing service implementation
- Error handling and service reliability
- API performance optimization
- Frontend development lead
- UI/UX design implementation
- Geolocation feature development
- Responsive design optimization
- Responsive Design: Works seamlessly on both desktop and mobile devices
- Interactive Time Selector: Visual slider for selecting available time ranges
- Location Discovery: AI-powered suggestions based on user preferences
- Interactive Map: Detailed routing with distance markers and elevation data
- Sharing Options: Easy sharing of route information with others
- Python 3.8+
- GraphHopper API key
- Google API key with Gemini access
- Node.js (for Vercel CLI if deploying)
-
Clone the repository:
-
Install requirements
pip install -r requirements.txt
-
Run project
uvicorn src:app --host localhost --port 10002
Leisure is built on FastAPI, a modern, high-performance web framework for building APIs with Python. Key features used:
- Dependency Injection: For handling user data and location information
- Pydantic Models: For request/response validation with models like
UserDataandLocation - Async Support: For efficient API calls to external services
- Path Operations: Organized API endpoints for handling user data and route calculations
The application uses Google's Gemini LLM (Large Language Model) to generate personalized leisure recommendations:
- Context-Aware Suggestions: Analyzes user preferences, time constraints, and current location
- JSON Response Formatting: Processes responses to provide structured location data
- Natural Language Descriptions: Generates appealing descriptions of each location
- Prompt Engineering: Carefully crafted prompts to produce relevant and realistic recommendations
For route calculations and geospatial features, Leisure integrates with GraphHopper:
- Geocoding: Converts place names to coordinates and reverse geocodes user locations
- Route Calculation: Determines optimal routes between user and suggested destinations
- Distance & Duration Estimation: Provides accurate travel metrics
- Elevation Data: Includes terrain information for more detailed route planning
- Input Preferences: Users specify their available date, time range, maximum travel distance, and duration
- Discover Options: The application suggests personalized destinations based on the user's criteria
- Select Destination: Users choose from the suggested locations
- View Route: Detailed route information, including distance, duration, and an interactive map is displayed
- Navigate or Share: Users can get directions, download route information, or share their plans
- User submits location and preferences via FastAPI endpoint
- The backend retrieves user's location context via GraphHopper reverse geocoding
- User data and location context are formatted into a prompt for Gemini LLM
- Gemini generates location suggestions based on the contextual data
- User selects a destination from the suggestions
- GraphHopper calculates the optimal route between user and destination
- Results are displayed to user with interactive map visualization
# User data endpoint
@router.post("/user-data/", response_model=dict)
def handle_input(data: UserData, location: Location):
# Get user's address from coordinates
address = reverse_geocode(location.lat, location.lng)
if address:
address = Place(**address)
# Generate location suggestions with Gemini
generated_locations = generate_locations(data, address)
return {"locations": generated_locations}
# Route calculation endpoint
@router.post("/user-road/", response_model=dict)
def handle_input(selected: PlaceSelected):
# Get route information from GraphHopper
trip_info = get_trip_info(selected.lat, selected.lng, selected.name)
return trip_infodef generate_locations(data: UserData, address: Place):
# Structured prompt template with user data
prompt = Template("""
You are an intelligent location recommender for short leisure trips.
A user has submitted their availability and preferences...
Date: $date
Distance: $distance_km km
Duration: $duration_hours hours
Preferred destination: $destination
Start time: $start
End time: $end
Current street: $street
Current city: $city
Current country: $country
""")
# Generate content with Gemini API
genai.configure(api_key=os.environ.get("GOOGLE_API_KEY"))
model = genai.GenerativeModel("gemini-2.5-pro-exp-03-25")
response = model.generate_content(prompt)
# Parse results to structured format
return parse_json_response(response.text)def get_trip_info(lat, lng, destination_name):
# Convert destination name to coordinates
dest_coords = _get_coordinates(destination_name)
# Calculate detailed route
route_data = _get_route((lat, lng), dest_coords)
return route_data
def _get_route(start, end):
# Build GraphHopper API request
route_url = "https://graphhopper.com/api/1/route?"
response = requests.get(
route_url + urllib.parse.urlencode({
"key": os.getenv("GRAPH_HOPPER_API_KEY"),
"profile": "car",
"locale": "en",
"points_encoded": "false",
}) +
f"&point={start[0]},{start[1]}" +
f"&point={end[0]},{end[1]}"
)
return response.json()
The main form where users enter their availability and preferences
The application suggests personalized options based on user input
Interactive map showing the route to the selected destination

