generateItinerariesFromEntries static method
- List<
DiaryEntry> entries
Generates 5 suggested itineraries based on a list of DiaryEntry objects.
The function sends the entries to the Gemini API, prompting it to return five imaginative travel itineraries inspired by the diary entries, each composed of a list of Google Maps Marker objects. The generated itineraries suggest new locations and are not limited to those found in the original entries.
Returns a Future containing a list of 5 itineraries, where each itinerary is a List of Markers.
Throws:
- SocketException if there is no internet connection.
- FormatException if the response from the AI model cannot be decoded as JSON.
- Exception if the response is empty or if any other unexpected error occurs during parsing.
Implementation
static Future<List<Map<String, dynamic>>> generateItinerariesFromEntries(
List<DiaryEntry> entries,
) async {
// Build entry summaries
String entrySummaries = entries
.map((entry) {
return '''
Titolo: ${entry.title}
Data: ${entry.date.toIso8601String()}
Descrizione: ${entry.description}
Luogo: lat=${entry.latitude}, lon=${entry.longitude}
''';
})
.join('\n\n');
// Updated schema with 'title' for each itinerary
final jsonSchema = Schema.object(
properties: {
'itineraries': Schema.array(
items: Schema.object(
properties: {
'title': Schema.string(),
'stops': Schema.array(
items: Schema.object(
properties: {
'name': Schema.string(),
'latitude': Schema.number(),
'longitude': Schema.number(),
},
),
),
},
),
),
},
);
// Updated prompt
final prompt = TextPart('''
Ti fornisco un elenco di voci di diario di viaggio (titolo, descrizione, luogo).
Crea **5 diversi itinerari turistici** ispirati a questi racconti, proponendo nuove località **simili o collegate** per atmosfera, tema o interesse.
Per ogni itinerario fornisci:
- **title**: un titolo suggestivo per l’itinerario, in inglese
- **stops**: un array di 5 tappe, ognuna con:
- "name": il nome del luogo, in inglese
- "latitude": la latitudine
- "longitude": la longitudine
Le tappe devono essere **geograficamente vicine** (massimo 200 km l’una dall’altra).
Ecco le voci di diario da cui prendere ispirazione:
$entrySummaries
''');
final model = FirebaseAI.googleAI().generativeModel(
model: 'gemini-2.0-flash-001',
generationConfig: GenerationConfig(
responseMimeType: 'application/json',
responseSchema: jsonSchema,
),
);
try {
final response = await model.generateContent([Content.text(prompt.text)]);
if (response.text == null) {
throw Exception('Empty response.');
}
final rawText = response.text!;
final jsonResponse = jsonDecode(rawText);
final itineraries = jsonResponse['itineraries'] as List;
return itineraries.map<Map<String, dynamic>>((itinerary) {
final title = itinerary['title'] as String;
final stops =
(itinerary['stops'] as List).map<Marker>((stop) {
return Marker(
markerId: MarkerId(stop['name']),
position: LatLng(
(stop['latitude'] as num).toDouble(),
(stop['longitude'] as num).toDouble(),
),
infoWindow: InfoWindow(title: stop['name']),
);
}).toList();
return {'title': title, 'markers': stops};
}).toList();
} on SocketException {
throw Exception('No connection. Could not generate new itineraries.');
} catch (e) {
throw Exception('Error parsing response: ${e.toString()}');
}
}