Why do I have duplicates in Geoflutterfire `within`query? - flutter

I query my database for items within a distance from the user's position as follows:
/// Get a stream of nearby ads.
static Stream<List<DocumentSnapshot<Map<String, dynamic>>>> getNearbyStream(
{required Position center, required double radius}) {
final geo = Geoflutterfire();
final collectionReference =
FirebaseFirestore.instance.collection(collectionName);
final gfpCenter = GeoFirePoint(center.latitude, center.longitude);
return geo
.collection(collectionRef: collectionReference)
.within(
center: gfpCenter,
radius: radius,
field: 'position',
strictMode: true);
}
To my surprise, the results shows duplicates: each result is shown twice.
How it comes?

Related

flutter map problem : final Completer<Null> _readyCompleter = Completer<Null>();

I am trying to build an app using flutter map plugin. But I got this error -
Before this error I added this line -
Stream<List<DocumentSnapshot>> getDataCollectionByLocation({
required GeoFirePoint center,
required double radius,
required String field,
}) {
Stream<List<DocumentSnapshot>> stream = _geo
.collection(collectionRef: ref)
.within(center: center, radius: radius, field: field);
return stream;
}

how can i check if lat long of my current location is on polyline using flutter

I made a Google map using flutter and drew two polyline on the map. I want to check if the current location is on the polyline or not.
first i need to check if my current location is on the same
this code is for how i get polyline and list of polyline coordinates
i have current location LatLng and list of polyline LatLng
polyline
import 'package:flutter/foundation.dart';
import 'package:flutter_polyline_points/flutter_polyline_points.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
class Directions {
final LatLngBounds bounds;
final List<PointLatLng> polylinePoints;
final String polylinePointsString;
final String totalDistance;
final String totalDuration;
final String alternativeTotalDistance;
final String alternativeTotalDuration;
final List<PointLatLng> alternativePolylinePoints;
final String alternativePolylinePointsString;
const Directions(
{#required this.polylinePointsString,
#required this.alternativePolylinePointsString,
#required this.alternativePolylinePoints,
#required this.alternativeTotalDistance,
#required this.alternativeTotalDuration,
#required this.bounds,
#required this.polylinePoints,
#required this.totalDistance,
#required this.totalDuration});
factory Directions.fromMap(Map<String, dynamic> map) {
//check route is not available
if ((map['routes'] as List).isEmpty) return null;
final data = Map<String, dynamic>.from(map['routes'][0]);
final routeList = map['routes'] as List;
//bounds
final northeast = data['bounds']['northeast'];
final southwest = data['bounds']['southwest'];
final bounds = LatLngBounds(
southwest: LatLng(southwest['lat'], southwest['lng']),
northeast: LatLng(northeast['lat'], northeast['lng']));
//distance & duration
String distance = '';
String duration = '';
if ((data['legs'] as List).isNotEmpty) {
final leg = data['legs'][0];
distance = leg['distance']['text'];
duration = leg['duration']['text'];
}
// Map for allternative route
List<PointLatLng> alternativeRoutePolyLinePoints;
String alternativePolylinePointsString;
String alternativeDistance;
String alternativeDuration;
// If alternative is available
if ((map['routes'] as List).length > 1) {
final alternativeRoute = Map<String, dynamic>.from(map['routes'][1]);
alternativeRoutePolyLinePoints = PolylinePoints()
.decodePolyline(alternativeRoute['overview_polyline']['points']);
alternativePolylinePointsString =
alternativeRoute['overview_polyline']['points'];
alternativeDuration = alternativeRoute['legs'][0]['duration']['text'];
alternativeDistance = alternativeRoute['legs'][0]['distance']['text'];
} else {
alternativeRoutePolyLinePoints = null;
alternativeDuration = null;
alternativeDuration = null;
}
return Directions(
alternativePolylinePoints: alternativeRoutePolyLinePoints,
alternativeTotalDistance: alternativeDistance,
alternativeTotalDuration: alternativeDuration,
bounds: bounds,
polylinePointsString: data['overview_polyline']['points'],
alternativePolylinePointsString: alternativePolylinePointsString,
polylinePoints: PolylinePoints()
.decodePolyline(data['overview_polyline']['points']),
totalDistance: distance,
totalDuration: duration);
}
//get route information
}
import 'dart:developer';
import 'package:dio/dio.dart';
import 'package:flutter/cupertino.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import '../model/directions_model.dart';
class DirectionsRepository {
static const String _baseUrl =
'https://maps.googleapis.com/maps/api/directions/json?';
final Dio _dio;
DirectionsRepository({Dio dio}) : _dio = dio ?? Dio();
Future<Directions> getDirections({
#required bool alternative,
#required LatLng origin,
#required LatLng destination,
#required String mode,
}) async {
final response = await _dio.get(_baseUrl, queryParameters: {
'origin': '${origin.latitude},${origin.longitude}',
'destination': '${destination.latitude},${destination.longitude}',
'mode': '$mode',
// 'waypoints':'${waypoints}',
'alternatives': alternative ? 'true' : 'false',
'key': "google api key",
});
if (response.statusCode == 200) {
log(response.data.toString());
return Directions.fromMap(response.data);
}
return null;
}
}

Search for locations in arrays of geopoints Firestore

I'm able to find locations within firestore documents if those have the next structure:
But how to perform the same searching, if the JSON has a couple of geopoints? Like this:
I'm using geoflutterfire with cloud_firestore.
The code to save locations to the database:
final geo = Geoflutterfire();
final startPoint = geo.point(
latitude: 49.805378,
longitude: 23.982382,
);
final finishPoint = geo.point(
latitude: 49.79987621408566,
longitude: 24.035205183081246,
);
FirebaseFirestore.instance.collection('Drivers').doc('12345').set({
'location': [startPoint.data, finishPoint.data]
});
This code is for getting filtered locations:
final drivers = FirebaseFirestore.instance.collection('Drivers');
final geo = Geoflutterfire();
final center = geo.point(
latitude: 49.79987621408566,
longitude: 24.035205183081246,
);
final Stream<List<DocumentSnapshot>> stream =
geo.collection(collectionRef: drivers).within(
center: center,
radius: 4,
field: 'location',
strictMode: true,
);
stream.listen((List<DocumentSnapshot> documentList) {
// Always empty if there are arrays of locations.
print(documentList);
});

how to format snapshots from firebase to list or set markers for map

How can I store firebase data so that I can use it for markers on a googlemap?
late CollectionReference vendorLocCollection =
FirebaseFirestore.instance.collection('vendorlocations');
late List vendors = [];
Future <void> populateVendors() async {
Map<dynamic, dynamic> marker = <MarkerId, Marker> {}; //from dynamic in snapshot to marker
final _vendorSnapshots = await vendorLocCollection.snapshots();
_vendorSnapshots.listen((result) {
result.docs.forEach((result) { //how do i extract the result so i can use
// it as marker? :
vendors.add(result.data());
print(vendors);
});
});
}
Parsing firebase snapshot results and putting markers on Google Maps are two different things.
Step 1: Serialise the data
Since we get the data in JSON format, we first change it to dart data types.
We can use something like this.
class VendorLocations {
String uid;
double latitude;
double longitude;
VendorLocations(this.uid, this.latitude, this.longitude);
}
...
vendors = (result.data() as List)
.map((e) {
return VendorLocations(e['uid'], e['latitude'], e['longitude']);
})
.toList();
Step 2: Put marker on Google Map
Create marker objects from the vendors list.
final markerId = vendors[0].uid; /// or something else
final Marker m = Marker(
markerId: markerId,
position: LatLng(
vendors[0].latitude,
vendors[0].longitude,
),
/// specify other parameters as needed
);
marker[markerId] = m;
// update UI
This creates a new marker. All the markers can be added by running the above code snippet in a loop.
Reference : google_maps_flutter

Sort and Filter ListView based on ratings(acquired through an API call) in Flutter

I want to sort a listview based on ratings in descending order. I used the Zomato API to get the Restaurants data. On a button click, I want the List to be sorted.
Here is the API call :
Future<List<ZomatoCollection>> getCollections(int cityId) async {
http.Response response = await client.get(NetworkRouter.cityCollections(cityId));
Map<String,dynamic> list = json.decode(response.body);
List results = list['collections'];
return results.map((singleCollection){
return ZomatoCollection.fromJSON(singleCollection);
}).toList();
}
Here is the model class for Restaurants and Its API Call :
class Restaurant {
final String name;
final String imageUrl;
final String cuisines;
final int averageCost;
final String rating; // Text
final String ratingColor;
Restaurant.fromJSON(json):name=json['restaurant']['name'],
imageUrl = json['restaurant']['thumb'],
cuisines = json['restaurant']['cuisines'],
averageCost = json['restaurant']['average_cost_for_two'],
rating = json['restaurant']['user_rating']['aggregate_rating'],
ratingColor=json['restaurant']['user_rating']['rating_color'];
}
Future<List<Restaurant>> getNearbyCollections(int cityId, int collectionId) async {
http.Response response = await client.get(NetworkRouter.nearbyCollections(cityId,collectionId));
Map<String,dynamic> list = json.decode(response.body);
List results = list['restaurants'];
return results.map((singleRestaurant){
return Restaurant.fromJSON(singleRestaurant);
}).toList();
}
I used ListviewBuilder to display Image, Cuisines, average cost and ratings.
I want to sort the Listview according to the ratings.
Here is the ZomatoCollection model class:
class ZomatoCollection {
final int collectionId;
final int restauranteCount;
final String imageUrl;
final String url;
final String title;
final String description;
ZomatoCollection.fromJSON(json)
:title = json['collection']['title'],
restauranteCount = json['collection']['res_count'],
imageUrl = json['collection']['image_url'],
collectionId = json['collection']['collection_id'],
description = json['collection']['description'],
url = json['collection']['url'];
}
You can try this on the restaurant's List. See if it works or not.
for example, your future Restaurant List is stored in variable res. Return res after sorting.
res.sort((a,b) => b.rating.compareTo(a.rating);
);