anyway/frontend/lib/structs/landmark.dart

173 lines
4.8 KiB
Dart

import 'dart:collection';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
LandmarkType typeSightseeing = LandmarkType(name: 'sightseeing');
LandmarkType typeNature = LandmarkType(name: 'nature');
LandmarkType typeShopping = LandmarkType(name: 'shopping');
// LandmarkType museum = LandmarkType(name: 'Museum');
// LandmarkType restaurant = LandmarkType(name: 'Restaurant');
LandmarkType typeStart = LandmarkType(name: 'start');
LandmarkType typeFinish = LandmarkType(name: 'finish');
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? nameEN;
final String? websiteURL;
String? imageURL; // not final because it can be patched
final String? description;
final Duration? duration;
bool visited;
// Next node is implicitly available through the LinkedListEntry mixin
// final Landmark? next;
Duration? tripTime;
// the trip time depends on the next landmark, so it is not final
Landmark({
required this.uuid,
required this.name,
required this.location,
required this.type,
this.isSecondary,
this.nameEN,
this.websiteURL,
this.imageURL,
this.description,
this.duration,
this.visited = false,
// this.next,
this.tripTime,
});
factory Landmark.fromJson(Map<String, dynamic> json) {
if (json
case { // automatically match all the non-optionals and cast them to the right type
'uuid': String uuid,
'name': String name,
'location': List<dynamic> location,
'type': String type,
}) {
// refine the parsing on a few fields
List<double> locationFixed = List<double>.from(location);
// parse the rest separately, they could be missing
LandmarkType typeFixed = LandmarkType(name: type);
final isSecondary = json['is_secondary'] as bool?;
final nameEN = json['name_en'] as String?;
final websiteURL = json['website_url'] as String?;
final imageURL = json['image_url'] as String?;
final description = json['description'] as String?;
var duration = Duration(minutes: json['duration']);
final visited = json['visited'] ?? false;
var tripTime = Duration(minutes: json['time_to_reach_next'] ?? 0) as Duration?;
return Landmark(
uuid: uuid,
name: name,
location: locationFixed,
type: typeFixed,
isSecondary: isSecondary,
nameEN: nameEN,
websiteURL: websiteURL,
imageURL: imageURL,
description: description,
duration: duration,
visited: visited,
tripTime: tripTime
);
} else {
throw FormatException('Invalid JSON: $json');
}
}
@override
bool operator ==(Object other) {
return other is Landmark && uuid == other.uuid;
}
Map<String, dynamic> toJson() => {
'uuid': uuid,
'name': name,
'location': location,
'type': type.name,
'is_secondary': isSecondary,
'name_en': nameEN,
'website_url': websiteURL,
'image_url': imageURL,
'description': description,
'duration': duration?.inMinutes,
'visited': visited,
'trip_time': tripTime?.inMinutes,
};
}
class LandmarkType {
final String name;
// final String description;
Icon icon;
LandmarkType({required this.name, this.icon = const Icon(Icons.location_on)}) {
switch (name) {
case 'sightseeing':
icon = const Icon(Icons.castle);
break;
case 'nature':
icon = const Icon(Icons.eco);
break;
case 'shopping':
icon = const Icon(Icons.shopping_cart);
break;
case 'start':
icon = const Icon(Icons.play_arrow);
break;
case 'finish':
icon = const Icon(Icons.flag);
break;
default:
icon = const Icon(Icons.location_on);
}
}
@override
bool operator ==(Object other) {
if (other is LandmarkType) {
return name == other.name;
} else {
return false;
}
}
}
// Helpers
// Handling the landmarks requires a little bit of special care because the linked list is not directly representable in json
(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);
}
void landmarkToPrefs(SharedPreferences prefs, Landmark current, Landmark? next) {
Map<String, dynamic> json = current.toJson();
json['next_uuid'] = next?.uuid;
prefs.setString('landmark_${current.uuid}', jsonEncode(json));
}