2024-05-27 14:40:46 +02:00
|
|
|
import 'dart:math';
|
|
|
|
|
2024-05-30 16:37:34 +02:00
|
|
|
import '../models/user_profile.dart';
|
|
|
|
|
2024-05-31 03:20:42 +02:00
|
|
|
/// Approximate determination of age
|
|
|
|
int calcAge(int? birthYear) {
|
|
|
|
if (birthYear != null) {
|
|
|
|
return (DateTime.now().year - birthYear);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2024-06-09 03:01:52 +02:00
|
|
|
/// Returns the approximate age in parentheses,
|
|
|
|
/// or an empty string if [birthYear] is the current year or null.
|
|
|
|
String ageInfo(int? birthYear) {
|
|
|
|
int age = calcAge(birthYear);
|
|
|
|
String ageInfo = age > 0 ? '($age)' : '';
|
|
|
|
return ageInfo;
|
|
|
|
}
|
|
|
|
|
2024-05-27 14:40:46 +02:00
|
|
|
///
|
|
|
|
/// Convert decimal coordinate to degrees minutes seconds (DMS).
|
|
|
|
///
|
|
|
|
String convertDecimalToDMS(double decimalValue, {required bool isLatitude}) {
|
|
|
|
bool isNegative = decimalValue < 0;
|
|
|
|
double absoluteValue = decimalValue.abs();
|
|
|
|
|
|
|
|
int degrees = absoluteValue.toInt();
|
|
|
|
double minutesDecimal = (absoluteValue - degrees) * 60;
|
|
|
|
int minutes = minutesDecimal.toInt();
|
|
|
|
double secondsDecimal = (minutesDecimal - minutes) * 60;
|
|
|
|
double seconds = double.parse(secondsDecimal.toStringAsFixed(2));
|
|
|
|
|
|
|
|
String direction;
|
|
|
|
if (isLatitude) {
|
|
|
|
direction = isNegative ? 'S' : 'N';
|
|
|
|
} else {
|
|
|
|
direction = isNegative ? 'W' : 'E';
|
|
|
|
}
|
|
|
|
|
|
|
|
// return formatted string
|
|
|
|
return '${degrees.abs()}° ${minutes.abs()}\' ${seconds.abs().toStringAsFixed(2)}" $direction';
|
|
|
|
}
|
|
|
|
|
|
|
|
///
|
|
|
|
/// Distance in kilometers between two location coordinates
|
|
|
|
///
|
|
|
|
double calculateDistance(double lat1, double lon1, double lat2, double lon2) {
|
|
|
|
const R = 6371; // earth radius in kilometers
|
|
|
|
|
|
|
|
// distance between latitudes and longitudes
|
|
|
|
final dLat = _degreesToRadians(lat2 - lat1);
|
|
|
|
final dLon = _degreesToRadians(lon2 - lon1);
|
|
|
|
|
|
|
|
final a = sin(dLat / 2) * sin(dLat / 2) +
|
2024-06-09 03:01:52 +02:00
|
|
|
cos(_degreesToRadians(lat1)) *
|
|
|
|
cos(_degreesToRadians(lat2)) *
|
|
|
|
sin(dLon / 2) *
|
|
|
|
sin(dLon / 2);
|
2024-05-27 14:40:46 +02:00
|
|
|
final c = 2 * atan2(sqrt(a), sqrt(1 - a));
|
|
|
|
|
|
|
|
return R * c;
|
|
|
|
}
|
|
|
|
|
|
|
|
double _degreesToRadians(double degrees) {
|
|
|
|
return degrees * pi / 180;
|
|
|
|
}
|
2024-05-30 16:37:34 +02:00
|
|
|
|
|
|
|
///
|
|
|
|
/// Shortest distance between two users locations
|
|
|
|
///
|
|
|
|
double shortestDistanceBetweenUsers(
|
|
|
|
UserProfile currentUser, UserProfile otherUser) {
|
|
|
|
try {
|
|
|
|
if (currentUser.locations.isEmpty || otherUser.locations.isEmpty) {
|
|
|
|
return double.nan;
|
|
|
|
}
|
|
|
|
|
|
|
|
double shortestDistance = double.nan;
|
|
|
|
// locations currentUser
|
|
|
|
for (var loc1 in currentUser.locations.values) {
|
|
|
|
if (loc1 != null && loc1.latitude != null && loc1.longitude != null) {
|
|
|
|
for (var loc2 in otherUser.locations.values) {
|
|
|
|
if (loc2 != null && loc2.latitude != null && loc2.longitude != null) {
|
|
|
|
double distance = calculateDistance(loc1.latitude!, loc1.longitude!,
|
|
|
|
loc2.latitude!, loc2.longitude!);
|
|
|
|
if (shortestDistance.isNaN || distance < shortestDistance) {
|
|
|
|
shortestDistance = distance;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return shortestDistance;
|
|
|
|
} catch (e) {
|
|
|
|
return double.nan;
|
|
|
|
}
|
|
|
|
}
|