functional datastructure. Needs to be able to write to storage as well
This commit is contained in:
		| @@ -1,56 +1,69 @@ | ||||
| class Landmark { | ||||
|   final String name; | ||||
|   final List location; | ||||
|   final LandmarkType type; | ||||
|   final String imageURL; | ||||
|   // final String description; | ||||
|   // final Duration duration; | ||||
|   // final bool visited; | ||||
| import 'dart:collection'; | ||||
| import 'dart:convert'; | ||||
|  | ||||
|   const Landmark({ | ||||
| import 'package:shared_preferences/shared_preferences.dart'; | ||||
|  | ||||
| final class Landmark extends LinkedListEntry<Landmark>{ | ||||
|   // A linked node of a list of Landmarks | ||||
|   final String uuid; | ||||
|   final String name; | ||||
|   final List<double> location; | ||||
|   final LandmarkType type; | ||||
|   final bool? isSecondary; | ||||
|  | ||||
|   // description to be shown in the overview | ||||
|   final String? imageURL; | ||||
|   final String? description; | ||||
|   final Duration? duration; | ||||
|   final bool? visited; | ||||
|  | ||||
|   // Next node | ||||
|   // final Landmark? next; | ||||
|   final Duration? tripTime; | ||||
|  | ||||
|   Landmark({ | ||||
|     required this.uuid, | ||||
|     required this.name, | ||||
|     required this.location, | ||||
|     required this.type, | ||||
|     this.imageURL = 'https://upload.wikimedia.org/wikipedia/commons/thumb/a/a8/Tour_Eiffel_Wikimedia_Commons.jpg/1037px-Tour_Eiffel_Wikimedia_Commons.jpg', | ||||
|     // required this.description, | ||||
|     // required this.duration, | ||||
|     // required this.visited, | ||||
|     this.isSecondary, | ||||
|  | ||||
|     this.imageURL, | ||||
|     this.description, | ||||
|     this.duration, | ||||
|     this.visited, | ||||
|  | ||||
|     // this.next, | ||||
|     this.tripTime, | ||||
|   }); | ||||
|  | ||||
|   factory Landmark.fromJson(Map<String, dynamic> json) { | ||||
|     return switch (json) { | ||||
|       { | ||||
|         'loc': List location, | ||||
|     if (json | ||||
|       case { // automatically match all the non-optionals and cast them to the right type | ||||
|         'uuid': String uuid, | ||||
|         'name': String name, | ||||
|         'type': String type, | ||||
|         // 'description': String description, | ||||
|         // 'duration': int duration, | ||||
|         // 'visited': bool visited | ||||
|  | ||||
|       } => | ||||
|         Landmark( | ||||
|           name: name, | ||||
|           location: location, | ||||
|           type: LandmarkType(name: type) | ||||
|           // description: description, | ||||
|           // duration: Duration(minutes: duration), | ||||
|           // visited: visited | ||||
|         ), | ||||
|       _ => throw const FormatException('Failed to load destination.'), | ||||
|     }; | ||||
|         'location': List<double> location, | ||||
|         'type': LandmarkType type, | ||||
|       }) { | ||||
|         // parse the rest separately, they could be missing | ||||
|         final isSecondary = json['is_secondary'] as bool?; | ||||
|         final imageURL = json['image_url'] as String?; | ||||
|         final description = json['description'] as String?; | ||||
|         final duration = json['duration'] as Duration?; | ||||
|         final visited = json['visited'] as bool?; | ||||
|          | ||||
|         return Landmark( | ||||
|           uuid: uuid, name: name, location: location, type: type, isSecondary: isSecondary, imageURL: imageURL, description: description, duration: duration, visited: visited); | ||||
|     } else { | ||||
|       throw FormatException('Invalid JSON: $json'); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|  | ||||
|     Map<String, dynamic> toJson() { | ||||
|       return { | ||||
|         'name': name, | ||||
|         'location': location, | ||||
|         'type': type.name, | ||||
|         // 'description': description, | ||||
|         // 'duration': duration.inMinutes, | ||||
|         // 'visited': visited | ||||
|       }; | ||||
|     } | ||||
|   @override | ||||
|   bool operator ==(Object other) { | ||||
|     return other is Landmark && uuid == other.uuid; | ||||
|   } | ||||
| } | ||||
|  | ||||
|  | ||||
| @@ -67,3 +80,12 @@ class LandmarkType { | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| // Helper | ||||
| (Landmark, String?) getLandmarkFromPrefs(SharedPreferences prefs, String uuid) { | ||||
|   String? content = prefs.getString('landmark_$uuid'); | ||||
|   Map<String, dynamic> json = jsonDecode(content!); | ||||
|   String? nextUUID = json['next_uuid']; | ||||
|   return (Landmark.fromJson(json), nextUUID); | ||||
| } | ||||
|  | ||||
|   | ||||
							
								
								
									
										46
									
								
								frontend/lib/structs/linked_landmarks.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								frontend/lib/structs/linked_landmarks.dart
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,46 @@ | ||||
| // import "package:fast_network_navigation/structs/landmark.dart"; | ||||
|  | ||||
| // class Linked<Landmark> { | ||||
| //   Landmark? head; | ||||
|    | ||||
| //   Linked(); | ||||
|  | ||||
| //   // class methods | ||||
| //   bool get isEmpty => head == null; | ||||
|  | ||||
| //   // Add a new node to the end of the list | ||||
| //   void add(Landmark value) { | ||||
| //     if (isEmpty) { | ||||
| //       // If the list is empty, set the new node as the head | ||||
| //       head = value; | ||||
| //     } else { | ||||
| //       Landmark? current = head; | ||||
| //       while (current!.next != null) { | ||||
| //         // Traverse the list to find the last node | ||||
| //         current = current.next; | ||||
| //       } | ||||
| //       current.next = value; // Set the new node as the next node of the last node | ||||
| //     } | ||||
| //   } | ||||
|  | ||||
| //   // Remove the first node with the given value | ||||
| //   void remove(Landmark value) { | ||||
| //     if (isEmpty) return; | ||||
|  | ||||
| //     // If the value is in the head node, update the head to the next node | ||||
| //     if (head! == value) { | ||||
| //       head = head.next; | ||||
| //       return; | ||||
| //     } | ||||
|  | ||||
| //     var current = head; | ||||
| //     while (current!.next != null) { | ||||
| //       if (current.next! == value) { | ||||
| //         // If the value is found in the next node, skip the next node | ||||
| //         current.next = current.next.next; | ||||
| //         return; | ||||
| //       } | ||||
| //       current = current.next; | ||||
| //     } | ||||
| //   } | ||||
| // } | ||||
| @@ -67,16 +67,16 @@ class UserPreferences { | ||||
|  | ||||
|  | ||||
|   void save() async { | ||||
|     SharedPreferences prefs = await SharedPreferences.getInstance(); | ||||
|     SharedPreferences sharedPrefs = await SharedPreferences.getInstance(); | ||||
|     for (SinglePreference pref in preferences) { | ||||
|       prefs.setInt(pref.key, pref.value); | ||||
|       sharedPrefs.setInt(pref.key, pref.value); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   void load() async { | ||||
|     SharedPreferences prefs = await SharedPreferences.getInstance(); | ||||
|     SharedPreferences sharedPrefs = await SharedPreferences.getInstance(); | ||||
|     for (SinglePreference pref in preferences) { | ||||
|       pref.value = prefs.getInt(pref.key) ?? 0; | ||||
|       pref.value = sharedPrefs.getInt(pref.key) ?? 0; | ||||
|     } | ||||
|   } | ||||
| } | ||||
| @@ -5,7 +5,7 @@ class Route { | ||||
|   final String name; | ||||
|   final Duration duration; | ||||
|   final List<Landmark> landmarks; | ||||
|    | ||||
|  | ||||
|   Route({ | ||||
|     required this.name, | ||||
|     required this.duration, | ||||
|   | ||||
| @@ -1,25 +1,49 @@ | ||||
| // Represents a collection of landmarks that represent a journey | ||||
| // Different instances of a Trip can be saved and loaded by the user | ||||
|  | ||||
| import 'dart:collection'; | ||||
| import 'dart:convert'; | ||||
|  | ||||
| import 'package:fast_network_navigation/structs/landmark.dart'; | ||||
| import 'package:shared_preferences/shared_preferences.dart'; | ||||
|  | ||||
| class Trip { | ||||
|   final String uuid; | ||||
|   final String cityName; | ||||
|   final List<Landmark> landmarks; | ||||
|   // TODO: cityName should be inferred from coordinates of the Landmarks | ||||
|   final LinkedList<Landmark> landmarks; | ||||
|   // could be empty as well | ||||
|  | ||||
|  | ||||
|   Trip({required this.uuid, required this.cityName, required this.landmarks}); | ||||
|   Trip({ | ||||
|     required this.uuid, | ||||
|     required this.cityName, | ||||
|     required this.landmarks, | ||||
|     }); | ||||
|  | ||||
|   factory Trip.fromJson(Map<String, dynamic> json) { | ||||
|     List<Landmark> landmarks = []; | ||||
|     for (var landmark in json['landmarks']) { | ||||
|       landmarks.add(Landmark.fromJson(landmark)); | ||||
|     } | ||||
|     return Trip( | ||||
|       uuid: json['uuid'], | ||||
|       cityName: json['cityName'], | ||||
|       landmarks: landmarks, | ||||
|       landmarks: LinkedList() | ||||
|     ); | ||||
|   } | ||||
| } | ||||
|  | ||||
|   factory Trip.fromPrefs(SharedPreferences prefs, String uuid) { | ||||
|     String? content = prefs.getString('trip_$uuid'); | ||||
|     Map<String, dynamic> json = jsonDecode(content!); | ||||
|     Trip trip = Trip.fromJson(json); | ||||
|     String? firstUUID = json['entry_uuid']; | ||||
|     appendLandmarks(trip.landmarks, prefs, firstUUID); | ||||
|     return trip; | ||||
|   } | ||||
| } | ||||
|  | ||||
| // Helper | ||||
|  | ||||
| appendLandmarks(LinkedList<Landmark> landmarks, SharedPreferences prefs, String? firstUUID) { | ||||
|   while (firstUUID != null) { | ||||
|     var (head, nextUUID) = getLandmarkFromPrefs(prefs, firstUUID); | ||||
|     landmarks.add(head); | ||||
|     firstUUID = nextUUID; | ||||
|   } | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user