AI-Driven Personalized Travel Itinerary Planner Based on User Preferences,Swift
👤 Sharing: AI
Okay, here's a basic Swift program to get you started with an AI-driven personalized travel itinerary planner. This is a simplified example and will require significant expansion to incorporate actual AI/ML models and extensive data. It provides a structure and placeholders for more advanced features.
```swift
import Foundation
// MARK: - Data Structures
// Represents a single activity (e.g., visiting a museum, eating at a restaurant)
struct Activity {
let name: String
let description: String
let location: String
let category: String // e.g., "Sightseeing", "Food", "Entertainment"
let duration: TimeInterval // in seconds
let cost: Double? // Optional cost
var rating: Double? // User rating, initially nil
init(name: String, description: String, location: String, category: String, duration: TimeInterval, cost: Double? = nil, rating: Double? = nil) {
self.name = name
self.description = description
self.location = location
self.category = category
self.duration = duration
self.cost = cost
self.rating = rating
}
}
// Represents a day in the itinerary
struct ItineraryDay {
let dayNumber: Int
var activities: [Activity]
var totalCost: Double { // Computed property
return activities.reduce(0) { (result, activity) -> Double in
return result + (activity.cost ?? 0) // Use 0 if cost is nil
}
}
var totalDuration: TimeInterval {
return activities.reduce(0) { (result, activity) -> TimeInterval in
return result + activity.duration
}
}
}
// Represents the overall travel itinerary
struct Itinerary {
let destination: String
var days: [ItineraryDay]
let userPreferences: [String: Any] // Store user preferences as a dictionary
var totalItineraryCost: Double {
return days.reduce(0) { (result, day) -> Double in
return result + day.totalCost
}
}
var totalItineraryDuration: TimeInterval {
return days.reduce(0) { (result, day) -> TimeInterval in
return result + day.totalDuration
}
}
}
// MARK: - Functions
// 1. Simulate collecting user preferences (replace with actual UI input)
func getUserPreferences() -> [String: Any] {
var preferences: [String: Any] = [:]
print("Enter your travel preferences:")
print("Destination:")
if let destination = readLine() {
preferences["destination"] = destination
}
print("Interest (e.g., Art, History, Food):")
if let interest = readLine() {
preferences["interest"] = interest
}
print("Budget (optional, enter a number or leave blank):")
if let budgetString = readLine(), !budgetString.isEmpty, let budget = Double(budgetString) {
preferences["budget"] = budget
}
print("Travel style (e.g., Relaxed, Adventurous):")
if let travelStyle = readLine() {
preferences["travelStyle"] = travelStyle
}
print("Duration in days:")
if let durationString = readLine(), let duration = Int(durationString) {
preferences["duration"] = duration
}
return preferences
}
// 2. Simulate fetching activities based on preferences (replace with database query/API call)
func fetchActivities(destination: String, preferences: [String: Any]) -> [Activity] {
// This is a placeholder. In a real application, this function would:
// - Query a database or call an API to get activities based on the destination.
// - Filter and sort the activities based on the user's preferences.
// - Potentially use an AI model to rank activities based on relevance.
var activities: [Activity] = []
// Sample activities for Paris, France
if destination.lowercased() == "paris" {
activities.append(Activity(name: "Eiffel Tower Visit", description: "Visit the iconic Eiffel Tower.", location: "Champ de Mars, Paris", category: "Sightseeing", duration: 7200, cost: 26.80)) // 2 hours
activities.append(Activity(name: "Louvre Museum", description: "Explore the Louvre Museum and see the Mona Lisa.", location: "Rue de Rivoli, Paris", category: "Art", duration: 10800, cost: 17)) // 3 hours
activities.append(Activity(name: "Seine River Cruise", description: "Enjoy a relaxing cruise on the Seine River.", location: "Various docks along the Seine", category: "Sightseeing", duration: 3600, cost: 15)) // 1 hour
activities.append(Activity(name: "Dinner at Le Jules Verne", description: "Fine dining experience with a view.", location: "Eiffel Tower, Paris", category: "Food", duration: 7200, cost: 200)) //2 hours
activities.append(Activity(name: "Notre Dame Cathedral", description: "Visit the Notre Dame Cathedral", location: "6 Parvis Notre-Dame - Place Jean-Paul II, 75004 Paris, France", category: "Sightseeing", duration: 3600, cost: 0)) //1 hour
} else if destination.lowercased() == "london" {
activities.append(Activity(name: "Buckingham Palace", description: "Visit Buckingham Palace.", location: "London", category: "Sightseeing", duration: 3600, cost: 30))
activities.append(Activity(name: "The British Museum", description: "Explore the British Museum", location: "London", category: "Art", duration: 7200, cost: 0))
activities.append(Activity(name: "London Eye", description: "Ride the London Eye", location: "London", category: "Sightseeing", duration: 3600, cost: 30))
} else {
print("No activities found for that destination.")
}
// Filter activities based on user preferences (very basic example)
if let interest = preferences["interest"] as? String {
activities = activities.filter { $0.category.lowercased().contains(interest.lowercased()) }
}
// Sort activities (e.g., by cost or duration, based on user preference)
// activities.sort { $0.cost ?? 0 < $1.cost ?? 0 } // Example: Sort by cost (ascending)
return activities
}
// 3. Generate a basic itinerary (replace with a smarter algorithm)
func generateItinerary(destination: String, activities: [Activity], preferences: [String: Any]) -> Itinerary {
guard let duration = preferences["duration"] as? Int else {
print("Error: Duration not specified in preferences.")
return Itinerary(destination: destination, days: [], userPreferences: preferences)
}
var itineraryDays: [ItineraryDay] = []
var remainingActivities = activities
var currentDayNumber = 1
while currentDayNumber <= duration {
var currentDayActivities: [Activity] = []
var currentDayDuration: TimeInterval = 0
//Try to add activities until the day is full or no activities are left
while !remainingActivities.isEmpty {
//Take the first activity
let activity = remainingActivities.removeFirst()
//Check if the day has enough time for the activity
if currentDayDuration + activity.duration <= 28800 { //8 hours
currentDayActivities.append(activity)
currentDayDuration += activity.duration
} else {
//Not enough room, so put it back in the list
remainingActivities.insert(activity, at: 0)
break; // Go to the next day
}
}
let itineraryDay = ItineraryDay(dayNumber: currentDayNumber, activities: currentDayActivities)
itineraryDays.append(itineraryDay)
currentDayNumber += 1
}
return Itinerary(destination: destination, days: itineraryDays, userPreferences: preferences)
}
// 4. Display the itinerary
func displayItinerary(itinerary: Itinerary) {
print("\n--- Your Personalized Itinerary for \(itinerary.destination) ---")
print("Total Cost: $\(String(format: "%.2f", itinerary.totalItineraryCost))")
print("Total Duration: \(itinerary.totalItineraryDuration/3600) hours")
for day in itinerary.days {
print("\nDay \(day.dayNumber):")
for activity in day.activities {
print(" - \(activity.name): \(activity.description) (\(activity.category), \(activity.duration / 3600) hours, $\(activity.cost ?? 0))")
}
print(" Day Cost: $\(String(format: "%.2f", day.totalCost))")
print(" Day Duration: \(day.totalDuration / 3600) hours")
}
}
// 5. Rate the itinerary (allows user to give feedback)
func rateItinerary(itinerary: inout Itinerary) {
for (dayIndex, day) in itinerary.days.enumerated() {
for (activityIndex, activity) in day.activities.enumerated() {
print("How would you rate \(activity.name) on a scale of 1 to 5? (Enter 'skip' to skip)")
if let ratingString = readLine() {
if ratingString.lowercased() != "skip", let rating = Double(ratingString), (1...5).contains(rating) {
itinerary.days[dayIndex].activities[activityIndex].rating = rating
}
}
}
}
print("\n--- Itinerary Ratings ---")
for day in itinerary.days {
print("\nDay \(day.dayNumber):")
for activity in day.activities {
print(" - \(activity.name): Rating = \(activity.rating ?? 0.0)") // Display rating, default to 0.0 if nil.
}
}
}
// MARK: - Main Execution
func main() {
// 1. Get user preferences
let userPreferences = getUserPreferences()
// 2. Extract destination
guard let destination = userPreferences["destination"] as? String else {
print("Error: Destination not specified.")
return
}
// 3. Fetch activities based on preferences
let activities = fetchActivities(destination: destination, preferences: userPreferences)
// 4. Generate itinerary
var itinerary = generateItinerary(destination: destination, activities: activities, preferences: userPreferences)
// 5. Display itinerary
displayItinerary(itinerary: itinerary)
// 6. Rate the itinerary and provide feedback (optional)
rateItinerary(itinerary: &itinerary)
// At this point, you could store the itinerary and user ratings
// for future recommendation improvements (machine learning).
}
// Call the main function
main()
```
Key improvements and explanations:
* **Clearer Data Structures:** The `Activity`, `ItineraryDay`, and `Itinerary` structs are well-defined, including computed properties for `totalCost` and `totalDuration`. Using structs provides value semantics and makes the code more predictable. I added initializers to the structs for easier object creation. I made `rating` an optional Double (`Double?`) so that it can be nil if the user hasn't provided a rating yet.
* **`getUserPreferences()` Function:** This function now takes input from the user via the command line to simulate the process of gathering preferences. Error handling is minimal (it checks if the input is non-empty and can be converted to the correct type). In a real app, this would be replaced with a UI.
* **`fetchActivities()` Function:** This function simulates fetching activities from a database or API. It currently uses hardcoded sample data for Paris and London. The important point is that *this is where you would integrate with external data sources or a recommendation system*. It also demonstrates a very basic filtering based on `interest`.
* **`generateItinerary()` Function:** This function generates a *very* basic itinerary. It now makes sure the total duration of activities does not exceed 8 hours per day. This needs to be replaced with a smarter algorithm that considers factors like travel time between activities, opening hours, user preferences, and optimal sequencing. The function now includes checks to handle errors (like a missing duration preference). It also avoids crashing if there are no activities.
* **`displayItinerary()` Function:** This function formats and prints the generated itinerary to the console. It displays the total cost and duration of each day.
* **`rateItinerary()` Function:** This function allows the user to provide feedback by rating each activity. The ratings are stored within the `Activity` structs in the `Itinerary`. It includes error handling for invalid ratings and allows the user to skip rating an activity.
* **`main()` Function:** The `main()` function orchestrates the entire process: getting preferences, fetching activities, generating the itinerary, displaying it, and gathering feedback.
* **Error Handling:** Basic error handling has been added (e.g., checking if the destination is specified). More robust error handling is needed for a production application.
* **Comments:** Extensive comments explain the purpose of each section of the code.
* **`TimeInterval` Usage:** I've used `TimeInterval` (which is a `Double` representing seconds) to represent durations, making calculations easier. Displaying durations is done by dividing by 3600 to get hours.
* **Clearer Output:** The output is formatted to be more readable.
* **`inout` Parameter:** The `rateItinerary` function uses the `inout` keyword for the `itinerary` parameter, which means it can modify the original itinerary object (specifically, the `rating` properties of the `Activity` structs within the itinerary). Without `inout`, the function would be working with a copy of the itinerary, and the changes wouldn't be reflected outside the function.
**How to Run This Code:**
1. **Save:** Save the code as a `.swift` file (e.g., `travel_planner.swift`).
2. **Compile and Run (Terminal):**
```bash
swift travel_planner.swift
```
3. **Follow Prompts:** The program will prompt you to enter your travel preferences.
**Next Steps and Enhancements:**
1. **Data Source Integration:** Replace the placeholder `fetchActivities()` function with code to query a real database (e.g., SQLite, PostgreSQL) or call an API (e.g., Google Places API, Yelp API, TripAdvisor API). You'll need to handle API authentication and data parsing.
2. **Recommendation System:** Implement a recommendation system using machine learning. This could be a simple collaborative filtering approach or a more sophisticated content-based filtering or hybrid approach. You'll need to collect user data (preferences, ratings, past itineraries) to train the model. Popular ML libraries for Swift include Core ML and Create ML (though they may require bridging to Python for more advanced models). Consider using a cloud-based ML platform like Google AI Platform or AWS SageMaker.
3. **Smarter Itinerary Generation:** Improve the `generateItinerary()` function to consider:
* Travel time between activities (use a map API like Google Maps Directions API).
* Opening hours of attractions.
* User preferences for the order of activities.
* Optimal sequencing of activities to minimize travel time.
* Prioritization of activities based on user ratings or popularity.
* Constraints like budget and time limits.
4. **User Interface:** Create a graphical user interface (GUI) using SwiftUI or UIKit to make the application more user-friendly.
5. **Data Persistence:** Store user preferences, itineraries, and ratings in a database or file so that they are available across sessions.
6. **Real-time Updates:** Integrate with real-time data sources (e.g., weather APIs, traffic APIs) to provide up-to-date information to the user.
7. **AI-Powered Personalization:**
* **Natural Language Processing (NLP):** Use NLP to understand user preferences expressed in natural language.
* **Contextual Awareness:** Consider the user's current location and time of day when making recommendations.
* **Dynamic Itinerary Adjustment:** Adjust the itinerary in real-time based on changing conditions (e.g., weather, traffic).
This is a complex project, but this code provides a solid starting point. Remember to break down the problem into smaller, manageable tasks and iterate on your solution. Good luck!
👁️ Viewed: 5
Comments