Distorted lines in Travel Tracking in Flutter - flutter

I am trying to implement a functionality, that if a user travels, then his/her live location will be captured in every interval of 10 sec. I am saving the captured lat-longs in local database and then run a API after every 10 mins to save data on server.
In every 10 secs I am calculating the distance between last last lat-long captured and updated lat-long captured.
When I tested it, I travelled around 35 KM, but total distance calculate was around 400 KM.
On again testing, I travelled around 15 KM, but total distance calculate was around 150 KM.
Please anyone suggest what am I doing wrong. Or is there any alternative solution to track my path on which I travelled and total distance I covered.
For this I am using the below code to run the timer in every 10 secs
Timer.periodic(const Duration(seconds: 10), (timer) async {
await CommonMethods.getCurrentLocationDateTime();
});
In every 10 secs, I run the below code:
static Future getCurrentLocationDateTime() async {
_result = await Geolocator.getCurrentPosition(
desiredAccuracy: LocationAccuracy.bestForNavigation,
);
if (_updatedLatitude == null && _updatedLongitude == null) {
_previousLatitude = _result!.latitude;
_previousLongitude = _result!.longitude;
} else {
_previousLatitude = _updatedLatitude;
_previousLongitude = _updatedLongitude;
}
_updatedLatitude = _result!.latitude;
_updatedLongitude = _result!.longitude;
// Save data in a local variable
Map<String, String> _currentLatLong = {
"lat": _result!.latitude.toStringAsFixed(8),
"long": _result!.longitude.toStringAsFixed(8),
};
CommonEntities.travelHistoryLatLng.add(_currentLatLong);
// Update previous and current location names
await placemarkFromCoordinates(_updatedLatitude!, _updatedLongitude!)
.then((List<Placemark> placemarks) {
_previousLocationName = (_currentLocationName == "")
? placemarks[0].name!
: _currentLocationName;
_currentLocationName = placemarks[0].subLocality!;
}).catchError((e) {
debugPrint(e.toString());
});
// Check if device is not moved for more than 2 hours
// if not moved then stop the timer
if (CommonEntities.travelHistoryLatLng.toSet().length == 1) {
CommonEntities.idealStateTravelTimeSpent += 10;
if (CommonEntities.idealStateTravelTimeSpent >= 7200) {
CommonEntities.idealStateTravelTimeSpent = 0;
// BackgroundLocation.stopLocationService();
if (CommonEntities.travelTimer != null) {
CommonEntities.travelTimer!.cancel();
}
CommonEntities.isTravelTimerActive = false;
CommonEntities.workEndTime =
CommonEntities.travelTrackingDetails["current_date_time"];
}
} else {
CommonEntities.idealStateTravelTimeSpent = 0;
}
// Get Current date time of captured lat-longs
_currentDateTime = DateTime.now();
_currentDateTimeString = _currentDateTime.year.toString() +
"-" +
_currentDateTime.month.toString() +
"-" +
_currentDateTime.day.toString() +
" " +
_currentDateTime.hour.toString() +
":" +
_currentDateTime.minute.toString();
if (CommonEntities.workStartTime == "00:00") {
CommonEntities.workStartTime = _currentDateTime.hour.toString() +
":" +
_currentDateTime.minute.toString();
// LocalSharedPreferences().setWorkStartTime();
}
// Update the total distance covered in 10 min
updateDistanceTraveled();
print("Total Distance Covered: " + CommonEntities.travelTrackingDetails["total_distance_covered"]);
// Call API to save travel data in every 10 minutes.
if (CommonEntities.totalTravelsecondsCount == 600) {
// Calculate the time before 10 min and for time interval in post params
String _currentTime = _currentDateTime.hour.toString() +
':' +
_currentDateTime.minute.toString();
DateTime _dateTimeBeforeTenMin =
_currentDateTime.subtract(const Duration(minutes: 10));
String _timeBeforeTenMin = _dateTimeBeforeTenMin.hour.toString() +
':' +
_dateTimeBeforeTenMin.minute.toString();
String _tempDistanceTravelled =
CommonEntities.travelTrackingDetails["total_distance_covered"];
CommonEntities.travelTrackingDetails["total_distance_covered"] = "";
_distanceTravelled = 0.0;
// Create post params value
Map<String, dynamic> params = {
'lat_long': jsonEncode(CommonEntities.travelHistoryLatLng),
'date': _currentDateTime.day.toString() +
'-' +
_currentDateTime.month.toString() +
'-' +
_currentDateTime.year.toString() +
' ' +
_currentDateTime.hour.toString() +
':' +
_currentDateTime.minute.toString() +
':' +
_currentDateTime.second.toString(),
'distance_covered': _tempDistanceTravelled,
'userID': await LocalSharedPreferences().getUserId(),
'time_interval': _timeBeforeTenMin + '-' + _currentTime,
'location_name': _currentLocationName,
'status': 'progress',
};
// Call the API to save travel history of 10 min of server
HomeProvider().saveTravelDetails(params);
// await LocalSharedPreferences().saveTravelHistoryLatLng();
// Reset the timer of 10 min, clear lat-long history of 10 min
CommonEntities.totalTravelsecondsCount = 0;
CommonEntities.travelHistoryLatLng = [];
}
CommonEntities.totalTravelsecondsCount += 10;
// Save latlong and date time
// BOC: commented logging of lat-long as the same is not required in final app
// by shubham.bansal2
AppLogs().logToFile(
_result!.latitude.toString() + "-" + _result!.longitude.toString(),
_currentDateTimeString);
CommonEntities.travelTrackingDetails["updated_latitude"] =
_updatedLatitude!.toStringAsFixed(8);
CommonEntities.travelTrackingDetails["updated_longitude"] =
_updatedLongitude!.toStringAsFixed(8);
CommonEntities.travelTrackingDetails["updated_location_name"] =
_currentLocationName;
CommonEntities.travelTrackingDetails["previous_latitude"] =
_previousLatitude!.toStringAsFixed(8);
CommonEntities.travelTrackingDetails["previous_longitude"] =
_previousLongitude!.toStringAsFixed(8);
CommonEntities.travelTrackingDetails["previous_location_name"] =
_previousLocationName;
CommonEntities.travelTrackingDetails["total_distance_covered"] =
_distanceTravelled.toStringAsFixed(8);
CommonEntities.travelTrackingDetails["current_date_time"] =
_currentDateTimeString;
}
Also for Distance, I am using the below code:
static updateDistanceTraveled() {
var p = 0.017453292519943295;
var c = cos;
var a = 0.5 -
c((_updatedLatitude! - _previousLatitude!) * p) / 2 +
c(_previousLatitude! * p) *
c(_updatedLatitude! * p) *
(1 - c((_updatedLongitude! - _previousLongitude!) * p)) /
2;
_distanceTravelled = double.parse(CommonEntities.travelTrackingDetails["total_distance_covered"]);
_distanceTravelled += (12742 * asin(sqrt(a))).toDouble();
CommonEntities.travelTrackingDetails["total_distance_covered"] =
_distanceTravelled.toStringAsFixed(5);
}

Related

LootLocker - How to show local rank

In my game, I am able to show the GlobalRank, however, I would also like to show the position of a player in Ranking according to the global results.
So in the bottom line, there should be the local (on this device) results.
Basically, on the left bottom corner, I want to get the RANK from the LootLocker, but I am struggling to get the rank...
IEnumerator ShowScores()
{
yield return new WaitForSeconds(2);
LootLockerSDKManager.GetScoreList(ID, maxScores, (response) =>
{
if (response.success)
{
LootLockerLeaderboardMember[] scores = response.items;
for (int i = 0; i < scores.Length; i++)
{
playerNames[i].text = (scores[i].member_id +"");
playerScores[i].text = (scores[i].score +"");
playerRank[i].text = (scores[i].rank + "");
//Rank of the localPlayer
Rank.text = (scores["here_Should_Be_This_Player_ID"].rank + "");
LootLockerSDKManager.GetPlayerName
// Entries[i].text = (scores[i].rank + ". " + scores[i].score + ". " + scores[i].member_id);
}
if (scores.Length < maxScores)
{
for (int i = scores.Length; i < maxScores; i++)
{
// Entries[i].text = (i + 1).ToString() + ". none";
}
}
}
else
{
}
});
}
Fixed it with the LootLocker support team
Step 1 - load LootLocker and get the resonse
Step 2 - load the rank and get the resonse2
Step 3 - use the "Response2.rank from the LootLocker
Rank.text = (response2.rank + "");
string playerIdentifier = "PlayerNameRecordOnThisDevice";
LootLockerSDKManager.StartSession(playerIdentifier, (response) =>
{
if (response.success)
{
Debug.Log("session with LootLocker started");
}
else
{
Debug.Log("failed to start sessions" + response.Error);
}
LootLockerSDKManager.GetMemberRank(ID, playerIdentifier, (response2) =>
{
if (response2.statusCode == 200)
{
Debug.Log("GetMemberRank Successful");
}
else
{
Debug.Log("GetMemberRank failed: " + response2.Error);
}
Rank.text = (response2.rank + "");
});
}); ```

Firebase fetch inside for loop not working properly

In my project, I took data from the android accessibility stream in a headless background function turned them into an array and split them into chunks for firebase limits, and used a for loop to iterate over them and check in firebase. Sometimes this is not working, especially since I can see the associability service runner but showing data from a bit ago. I think this happens when the user is offline and tried to fetch data from firebase. Can you please have a look at this code and tell me what the issue is and How I should solve it?
N.B: I changed some variable names for privacy purposes. There are no issues with them.
FlutterAccessibilityService.accessStream.listen((event) {
if (event.capturedText != null &&
event.capturedText != "" &&
isCold) {
text = event.capturedText!.toLowerCase();
List textList = getArray(text);
final sharedItems = getSimilarArray(fbtag, textList, sensitivity);
final sharedLocalItems =
getSimilarLocalArray(fbtag, textList, sensitivity);
final sharedAbsItems = getAbsLocalArray(fbtag, textList);
final sharedItemWithLastEval =
getSimilarArray(lastEvaluatedText, textList, sensitivity);
if (text != lastEventText &&
(sharedItemWithLastEval.length == 0 ||
lastEvaluatedText[0] == "first")) {
print("called related content");
print("bg currant text: " +
text.toString() +
" sensitivity: " +
sensitivity.toString() +
" minimumAbsMatch: " +
minimumAbsMatch.toString() +
" shared local items: " +
sharedLocalItems.toString() +
" shared abs items: " +
sharedAbsItems.toString() +
" shared items: " +
sharedItems.toString() +
" last : " +
lastEventText +
" last eval text: " +
lastEvaluatedText.toString() +
" Cold: " +
isCold.toString());
print("captured text: " + text.toString());
//GetRelatedContent(fbtag, event.capturedText);
print(sharedItems);
if (sharedLocalItems.length >= accuracy &&
sharedAbsItems.length >= minimumAbsMatch) {
print("main called");
List result = [];
lastEvaluatedText = sharedItems;
List chunkedList = chunking(sharedItems);
for (int i = 0; i < chunkedList.length; i++) {
FirebaseFirestore.instance
.collection('Content')
.where('keyWords', arrayContainsAny: chunkedList[i])
.get()
.then((value) {
for (int i = 0; i < value.docs.length; i++) {
result.add(value.docs[i].data());
print("sep");
print("result: " + result.toString());
}
if (i == chunkedList.length - 1) {
if (result.isNotEmpty) {
print("final result: " +
result[HighestMatchingIndex(sharedItems, result)[0]]
.toString());
print('result length called' +
' result: ' +
result.toString());
if (HighestMatchingIndex(sharedItems, result)[1] >=
accuracy) {
print('overlay called');
isCold = false;
Timer(Duration(seconds: 60), () {
print("Cold down");
isCold = true;
});
var FinalResult = result[
HighestMatchingIndex(sharedItems, result)[0]];
if (FinalResult['availableCountry']
.contains(country) &&
FinalResult['availableR']
.contains(r)) {
print("all passed");
String l = FinalResult[r]
[country] ??
FinalResult[r]['EN'];
String o =
FinalResult[r]['origin'];
ShowAlert(l, o, r);
}
}
}
}
});
}
}
//
}
lastEventText = text;
}
});

Calculate distance using geolocation in ionic 4

I already can get my map and the route between two points, i would like to calculate de distance in km between that points
the code to trace the route
displayDirection(_origin, destin) {
var ref = this;
console.log('DIRECTION');
var directionsService = new google.maps.DirectionsService();
var directionsDisplay = new google.maps.DirectionsRenderer();
directionsDisplay.setMap(ref.map)
directionsService.route({
origin: _origin,
destination: destin,
travelMode: 'DRIVING'
}, (response, status) => {
console.log("Response: " + response + " Status: " + status);
if (status === 'OK') {
directionsDisplay.setDirections(response);
} else {
console.log("Can't set directions due to " + response);
}
});
}
can someone help me?
If you take the response that you receive, there will be an Array of Routes that It will show under the object
response.routes
In your request object, the array will have one or many route objects in it. The route object will have an array of legs breaking down the journey to smaller pieces. Simply Iterate the Legs to find the total distance. You can use the following method to find it for a route.
findRouteDistance(route) {
var total_distance = 0;
var route_legs = route.legs;
for(var i=0; i < route_legs.length; i++) {
total_distance += route_legs[i].distance.value;
}
return total_distance;
}
If you have only 1 route object simply call
findRouteDistance(response.routes[0])
Or iterate over the response.routes object if you have many.
to get the distance between two points
getDistanceFromLatLonInKm(lat1,lon1,lat2,lon2) {
var R = 6371; // Radius of the earth in km
var dLat = this.deg2rad(lat2-lat1); // deg2rad below
var dLon = this.deg2rad(lon2-lon1);
var a =
Math.sin(dLat/2) * Math.sin(dLat/2) +
Math.cos(this.deg2rad(lat1)) * Math.cos(this.deg2rad(lat2)) *
Math.sin(dLon/2) * Math.sin(dLon/2)
;
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
var d = R * c; // Distance in km
return d.toFixed(2);
}

How to get the data without breaking the call in the Facebook Graph API?

What I need to do to circumvent this issue, because when I request data for 2 months I already receive this error, when there is a break per day, I have the following call. With Little data works perfect, but when I increase the period the server brings me
User request limit reached","type":"OAuthException","is_transient":true,"code":17,"error_subcode":2446079,"fbtrace_id":"...
function solicitacaoAssicrona(){
var service = getService()
var batch = [{"method": "GET", "relative_url":"v3.2/act_1125789557444919/insights/impressions,reach,frequency,spend,campaign_name,account_name,clicks,cost_per_10_sec_video_view,cpm,cpp?level=campaign&since=2016-03-03&until=2019-03-04&time_increment=1&limit=100"}]
// var batchUrl = encodeURIComponent(JSON.stringify(batch));
// Logger.log(batchUrl);
var url = "https://graph.facebook.com?include_headers=false&batch=" + encodeURIComponent(JSON.stringify(batch))
var response = UrlFetchApp.fetch(url, {
method: 'POST',
headers: {
Authorization: 'Bearer ' + service.getAccessToken()
}
});
var result = JSON.parse(response.getContentText());
Logger.log(result)
// response.forEach(function(resp){
// var resp = JSON.parse(resp.body);
// //Logger.log(JSON.stringify(resp, null, 2));
//
//// resp.data[0].values.forEach(function(response){
////
////
//// })
////
// })
}
I'Ve looked at the documentation, but to the moment without success!
https://developers.facebook.com/docs/marketing-api/insights/best-practices/
That's the call I have
var metricas = [
'impressions',
'reach',
'unique_clicks',
'account_currency',
'account_id',
'account_name',
'ad_id',
'ad_name',
'adset_id',
'adset_name',
'buying_type',
'campaign_id',
'campaign_name',
'clicks',
'cost_per_inline_link_click',
'cost_per_inline_post_engagement',
'cost_per_unique_click',
'cost_per_unique_inline_link_click',
'cpc',
'cpm',
'cpp',
'ctr',
'date_start',
//'date_stop',
'frequency',
'inline_link_click_ctr',
'inline_link_clicks',
'inline_post_engagement',
'objective',
'relevance_score',
'social_spend',
'spend',
'unique_ctr',
'unique_inline_link_click_ctr',
'unique_inline_link_clicks',
'unique_link_clicks_ctr',
//'website_ctr',
'video_10_sec_watched_actions',
'cost_per_10_sec_video_view',
'video_30_sec_watched_actions',
'video_avg_percent_watched_actions',
'video_avg_time_watched_actions',
'video_p100_watched_actions',
'video_p25_watched_actions',
'video_p50_watched_actions',
'video_p75_watched_actions',
'video_play_actions',
'video_thruplay_watched_actions',
'video_p95_watched_actions',
]
var parameters = metricas.join(',');
var url = 'https://graph.facebook.com/v3.2/act_xxxxxxxxxx/insights?fields= + parameters + '&level=ad&time_range[since]=2019-02-05&time_range[until]=2019-04-05&time_increment=1&limit=200'
It's to do with how much data you can retrieve with batch requests. For longer periods, you should divide it into smaller chunks, sequential to each other, thus retrieving the data needed in multiple requests. Have a look at this example:
Code.gs
From line 88 of the file, you can see how it can be divided in multiple requests.
https://github.com/halsandr/Facebook_Connector/blob/master/Code.gs
function dateDelta(dObj, num) {
if (isNaN(num)) {
var dateStart = new Date(dObj);
} else {
var dateStart = new Date(dObj);
var dateStart = new Date(dateStart.setDate(dateStart.getDate() + num));
}
var dd = dateStart.getDate();
var mm = dateStart.getMonth()+1; //January is 0!
var yyyy = dateStart.getFullYear();
if(dd<10){
dd='0'+dd;
}
if(mm<10){
mm='0'+mm;
}
var dateStart = yyyy + "-" + mm + "-" + dd;
return dateStart;
}
var gStartDate = new Date(request.dateRange.startDate);
var gStartDate = new Date(dateDelta(gStartDate, -1));
var gEndDate = new Date(request.dateRange.endDate);
var gEndDate = new Date(dateDelta(gEndDate, +1));
var gRange = Math.ceil(Math.abs(gEndDate - gStartDate) / (1000 * 3600 * 24));
var gBatches = Math.ceil(gRange / 92);
if (gBatches < 2) {
var batch = [{"method": "GET", "relative_url": request.configParams.pageID + "/insights/page_fans,page_impressions,page_post_engagements?since=" + dateDelta(gStartDate) + "&until=" + dateDelta(gEndDate)}];
//console.log(batch);
} else {
batch = [];
var iterRanges = gRange / gBatches;
for (i = 0; i < gBatches; i++) {
var iterStart = dateDelta(gStartDate, (iterRanges * i));
if (i == (gBatches - 1)) {
var iterEnd = dateDelta(gEndDate);
} else {
var iterEnd = dateDelta(gStartDate, (iterRanges * (i + 1)) + 1);
}
batch.push({"method": "GET", "relative_url": request.configParams.pageID + "/insights/page_fans,page_impressions,page_post_engagements?since=" + iterStart + "&until=" + iterEnd})
}
//console.log(batch);
}
// Fetch the data with UrlFetchApp
var url = "https://graph.facebook.com?include_headers=false&batch=" + encodeURIComponent(JSON.stringify(batch))

How can I count pulse inputs with some interval time?

I'm develop a pulse counter(coin counter) in raspberry pi with windows 10 iot core, and i need to count pulses that have a interval time of 25 miliseconds like this:
0,05€ - 1 pulse
0,10€ - 2 pulses
0,20€ - 4 pulses
0,50€ - 10 pulses
1€ - 20 pulses
2€ - 40 pulses
like this image: pulses
I need to print the number of pulses(to have the value inserted) when the interval time is diferent of 25 miliseconds.
I have this code:
public MainPage()
{
this.InitializeComponent();
InitGPIO();
}
private void InitGPIO()
{
var gpio = GpioController.GetDefault();
if (gpio == null)
{
GpioStatus.Text = "There is no GPIO controller on this device.";
}
coinPin = gpio.OpenPin(coin_Pin);
if (coinPin.IsDriveModeSupported(GpioPinDriveMode.InputPullUp))
{
coinPin.SetDriveMode(GpioPinDriveMode.InputPullUp);
} else
{
coinPin.SetDriveMode(GpioPinDriveMode.Input);
}
coinPin.DebounceTimeout = TimeSpan.FromMilliseconds(25);
coinPin.ValueChanged += coinPin_ValueChanged;
GpioStatus.Text = "GPIO pins initialized correctly.";
}
private void coinPin_ValueChanged(GpioPin sender, GpioPinValueChangedEventArgs e)
{
if (e.Edge == GpioPinEdge.FallingEdge)
{
counter++;
}
var task = Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
if (e.Edge == GpioPinEdge.FallingEdge)
{
//counter++;
var time = PulseIn(coinPin, e.Edge);
value = (counter * 5);
value100 = value / 100;
//money.Text = "Eur: " + (decimal)value100 + " €";
if (time != 25)
{
money.Text = "Eur: " + (decimal)value100 + " €";
GpioStatus.Text = "" + time;
} else
{
GpioStatus.IsEnabled = false;
}
//GpioStatus.Text = "" + time + "";
} else
{
///GpioStatus.Text = "" + coinPin.DebounceTimeout;
}
});
}
private double PulseIn(GpioPin pin, GpioPinEdge edge)
{
var sw = new Stopwatch();
while (edge.Equals(GpioPinEdge.RisingEdge))
{
//sw.Start();
}
sw.Start();
if (!edge.Equals(GpioPinEdge.RisingEdge))
{
//sw.Stop();
}
sw.Stop();
return sw.Elapsed.TotalMilliseconds;
}
private const int coin_Pin = 24;
private int counter = 0;
private double value = 0;
private double value100 = 0;
private GpioPin coinPin;
Can you help me please?
Thank you very much.
From your code,
sw.Start();
if (!edge.Equals(GpioPinEdge.RisingEdge))
{
//sw.Stop();
}
sw.Stop();
it actually measures the execute time of the if statement that between sw.Start() and sw.Stop(). This does not make sense. Record the watch.Elapsed.TotalMilliseconds when the falling edge arrived and restart the stopwatch to measure the pulse interval time. To do this, I add the following two code lines under counter++, remove var time = PulseIn(coinPin, e.Edge) and use timeinterval in GpioStatus.Text = "" + timeinterval instead.
timeinterval = watch.Elapsed.TotalMilliseconds;
watch.Restart();
The following is complete code piece:
private Stopwatch watch = new Stopwatch();
private void coinPin_ValueChanged(GpioPin sender, GpioPinValueChangedEventArgs e)
{
double timeinterval = 0;
if (e.Edge == GpioPinEdge.FallingEdge)
{
counter++;
timeinterval = watch.Elapsed.TotalMilliseconds;
watch.Restart();
}
var task = Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
if (e.Edge == GpioPinEdge.FallingEdge)
{
//var time = PulseIn(coinPin, e.Edge);
value = (counter * 5);
value100 = value / 100;
if (timeinterval != 25)
{
money.Text = "Eur: " + (decimal)value100 + " €";
GpioStatus.Text = "" + timeinterval;
}
//...
}
});
}
You can try above code piece to see if it meets your accuracy requirement.
Note: It is not suitable to measure hardware pulse interval in software level because the software jitter is always unpredictable.