95 lines
3.6 KiB
Dart
95 lines
3.6 KiB
Dart
import 'package:shared_preferences/shared_preferences.dart';
|
|
import 'package:qyuota/config/api_config.dart';
|
|
import 'dart:math' show asin, cos, pow, sin, sqrt;
|
|
|
|
class LocationConfig {
|
|
// Singleton pattern
|
|
static final LocationConfig _instance = LocationConfig._internal();
|
|
factory LocationConfig() => _instance;
|
|
LocationConfig._internal();
|
|
|
|
// Mendapatkan latitude kantor dari SharedPreferences atau default
|
|
Future<double> getOfficeLatitude() async {
|
|
SharedPreferences prefs = await SharedPreferences.getInstance();
|
|
return prefs.getDouble(ApiConfig.officeLatitudeKey) ?? ApiConfig.defaultOfficeLatitude;
|
|
}
|
|
|
|
// Mendapatkan longitude kantor dari SharedPreferences atau default
|
|
Future<double> getOfficeLongitude() async {
|
|
SharedPreferences prefs = await SharedPreferences.getInstance();
|
|
return prefs.getDouble(ApiConfig.officeLongitudeKey) ?? ApiConfig.defaultOfficeLongitude;
|
|
}
|
|
|
|
// Mendapatkan radius presensi dari SharedPreferences atau default
|
|
Future<double> getRadiusInMeters() async {
|
|
SharedPreferences prefs = await SharedPreferences.getInstance();
|
|
return prefs.getDouble(ApiConfig.radiusInMetersKey) ?? ApiConfig.defaultRadiusInMeters;
|
|
}
|
|
|
|
// Menyimpan konfigurasi lokasi kantor baru
|
|
Future<bool> saveOfficeLocation(double latitude, double longitude) async {
|
|
SharedPreferences prefs = await SharedPreferences.getInstance();
|
|
await prefs.setDouble(ApiConfig.officeLatitudeKey, latitude);
|
|
return await prefs.setDouble(ApiConfig.officeLongitudeKey, longitude);
|
|
}
|
|
|
|
// Menyimpan radius presensi baru
|
|
Future<bool> saveRadius(double radius) async {
|
|
SharedPreferences prefs = await SharedPreferences.getInstance();
|
|
return await prefs.setDouble(ApiConfig.radiusInMetersKey, radius);
|
|
}
|
|
|
|
// Menghitung jarak antara dua koordinat (Haversine formula)
|
|
double calculateDistance(double lat1, double lon1, double lat2, double lon2) {
|
|
const double earthRadius = 6371000; // Radius bumi dalam meter
|
|
const double tolerance = 50.0; // Toleransi 50 meter untuk akurasi GPS
|
|
|
|
// Konversi derajat ke radian
|
|
final double dLat = _toRadians(lat2 - lat1);
|
|
final double dLon = _toRadians(lon2 - lon1);
|
|
|
|
// Rumus haversine
|
|
final double a = pow(sin(dLat / 2), 2) +
|
|
cos(_toRadians(lat1)) *
|
|
cos(_toRadians(lat2)) *
|
|
pow(sin(dLon / 2), 2);
|
|
|
|
final double c = 2 * asin(sqrt(a));
|
|
|
|
// Jarak dalam meter dengan toleransi
|
|
double distance = (earthRadius * c) - tolerance;
|
|
|
|
print('\n=== DETAIL PERHITUNGAN JARAK ===');
|
|
print('Koordinat 1: ($lat1, $lon1)');
|
|
print('Koordinat 2: ($lat2, $lon2)');
|
|
print('dLat (radian): ${dLat.toStringAsFixed(6)}');
|
|
print('dLon (radian): ${dLon.toStringAsFixed(6)}');
|
|
print('a: ${a.toStringAsFixed(6)}');
|
|
print('c: ${c.toStringAsFixed(6)}');
|
|
print('Jarak akhir: ${distance.toStringAsFixed(2)} meter');
|
|
print('Toleransi: ${tolerance.toStringAsFixed(2)} meter');
|
|
|
|
return distance > 0 ? distance : 0; // Pastikan jarak tidak negatif
|
|
}
|
|
|
|
// Konversi derajat ke radian
|
|
double _toRadians(double degree) {
|
|
return degree * (3.141592653589793 / 180);
|
|
}
|
|
|
|
// Memeriksa apakah lokasi berada dalam radius yang ditentukan
|
|
Future<bool> isLocationInRadius(double latitude, double longitude) async {
|
|
double officeLatitude = await getOfficeLatitude();
|
|
double officeLongitude = await getOfficeLongitude();
|
|
double radiusInMeters = await getRadiusInMeters();
|
|
|
|
double distance = calculateDistance(
|
|
latitude,
|
|
longitude,
|
|
officeLatitude,
|
|
officeLongitude
|
|
);
|
|
|
|
return distance <= radiusInMeters;
|
|
}
|
|
} |