From 5dffc71e67458a68e2523138b7c06a0a4e11d791 Mon Sep 17 00:00:00 2001 From: Shankari Date: Tue, 22 Sep 2020 17:20:08 -0700 Subject: [PATCH 01/11] Simple changes for the NREL location history project - Launch a survey - Autogenerate a random token - Change the text on the login page - Display the random token for the user to enter - Once we have the newer version of emTripLog, we can set this automatically --- www/js/intro.js | 30 +++++++++++++++++++++++++++--- www/templates/intro/login.html | 15 ++++++++------- 2 files changed, 35 insertions(+), 10 deletions(-) diff --git a/www/js/intro.js b/www/js/intro.js index 742d9e1c7..440828396 100644 --- a/www/js/intro.js +++ b/www/js/intro.js @@ -2,6 +2,7 @@ angular.module('emission.intro', ['emission.splash.startprefs', 'emission.splash.updatecheck', + 'emission.survey.launch', 'ionic-toast']) .config(function($stateProvider) { @@ -20,7 +21,7 @@ angular.module('emission.intro', ['emission.splash.startprefs', }) .controller('IntroCtrl', function($scope, $state, $window, $ionicSlideBoxDelegate, - $ionicPopup, $ionicHistory, ionicToast, $timeout, CommHelper, StartPrefs, UpdateCheck, $translate) { + $ionicPopup, $ionicHistory, ionicToast, $timeout, CommHelper, StartPrefs, SurveyLaunch, UpdateCheck, $translate) { $scope.platform = $window.device.platform; $scope.osver = $window.device.version.split(".")[0]; @@ -135,12 +136,25 @@ angular.module('emission.intro', ['emission.splash.startprefs', }); }; + // Adapted from https://stackoverflow.com/a/63363662/4040267 + // made available under a CC BY-SA 4.0 license + + $scope.generateRandomToken = function(length) { + var randomInts = window.crypto.getRandomValues(new Uint8Array(length * 2)); + var randomChars = Array.from(randomInts).map((b) => String.fromCharCode(b)); + var randomString = randomChars.join(""); + var validRandomString = window.btoa(randomString).replace(/[+/]/g, ""); + return validRandomString.substring(0, length); + } + $scope.disagree = function() { $state.go('root.main.heatmap'); }; $scope.agree = function() { StartPrefs.markConsented().then(function(response) { + $scope.randomToken = $scope.generateRandomToken(8); + window.Logger.log("Signing in with random token "+$scope.randomToken); $ionicHistory.clearHistory(); if ($state.is('root.intro')) { $scope.next(); @@ -166,10 +180,19 @@ angular.module('emission.intro', ['emission.splash.startprefs', }); alertPopup.then(function(res) { - window.Logger.log(window.Logger.LEVEL_INFO, errorMsg + ' ' + res); - }); + window.Logger.log(window.Logger.LEVEL_INFO, errorMsg + ' ' + res); }); } + $scope.startSurvey = function () { + SurveyLaunch.startSurveyWithXPath( + 'https://ee.kobotoolbox.org/x/hEkHk50v', + '/html/body/div[1]/article/form/section[2]/label[1]/input'); + } + + $scope.tokenToClipboard = function() { + navigator.clipboard.writeText($scope.randomToken); + }; + $scope.login = function() { window.cordova.plugins.BEMJWTAuth.signIn().then(function(userEmail) { // ionicToast.show(message, position, stick, time); @@ -184,6 +207,7 @@ angular.module('emission.intro', ['emission.splash.startprefs', client: retVal }); }); + $scope.startSurvey(); $scope.finish(); }, function(errorResult) { $scope.alertError('User registration error', errorResult); diff --git a/www/templates/intro/login.html b/www/templates/intro/login.html index 409173bc0..97d323e29 100644 --- a/www/templates/intro/login.html +++ b/www/templates/intro/login.html @@ -1,15 +1,16 @@
-

Login via google

+

Login via token

+
Suggestion: {{randomToken}}
-Currently, we only support logging in via google, since they support techniques -such as two factor authentication for greater security. Participants at UC -Berkeley can choose to login using either their CalNet ID or a personal gmail -account. +We will now ask you to select a unique passphrase that will be used to identify +you in the system. If you prefer an autogenerated value, you can use {{randomToken}}. +

 

+You will need the passphrase if you want to access your data from another +device such as your laptop or a new phone.
- +
-
From ce41917c199372f7af23f8d26315edf1291d5197 Mon Sep 17 00:00:00 2001 From: Shankari Date: Wed, 30 Sep 2020 23:30:18 -0700 Subject: [PATCH 02/11] Switch the login to an autogenerated token that is set directly Finally we get to use the new `setPromptedAuthToken` method. This raises a bunch of new questions: - if the user switches phones or uninstalls + reinstalls, how do they enter their old token? - how do they write their old token down - should we give them a choice between autogenerated and human generated Fortunately, since this is going to collect data for 2-3 days, none of these need to be answered right now. --- www/js/intro.js | 2 +- www/templates/intro/login.html | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/www/js/intro.js b/www/js/intro.js index 440828396..7d94a3462 100644 --- a/www/js/intro.js +++ b/www/js/intro.js @@ -194,7 +194,7 @@ angular.module('emission.intro', ['emission.splash.startprefs', }; $scope.login = function() { - window.cordova.plugins.BEMJWTAuth.signIn().then(function(userEmail) { + window.cordova.plugins.BEMJWTAuth.setPromptedAuthToken($scope.randomToken).then(function(userEmail) { // ionicToast.show(message, position, stick, time); // $scope.next(); ionicToast.show(userEmail, 'middle', false, 2500); diff --git a/www/templates/intro/login.html b/www/templates/intro/login.html index 97d323e29..cc4c25240 100644 --- a/www/templates/intro/login.html +++ b/www/templates/intro/login.html @@ -1,16 +1,16 @@
-

Login via token

-
Suggestion: {{randomToken}}
+

Login via anonymous token

+
Token {{randomToken}}
-We will now ask you to select a unique passphrase that will be used to identify -you in the system. If you prefer an autogenerated value, you can use {{randomToken}}. +This unique randomly generated token is your identifier in the system.

 

-You will need the passphrase if you want to access your data from another -device such as your laptop or a new phone. +Nobody other than you knows that you are associated with this token. If you +want to communicate with the research team about the data collected about you, +please be prepared to provide this token.
- +
From 2c894129c73c52235e91bcf4009bf952f71b15bd Mon Sep 17 00:00:00 2001 From: Shankari Date: Sun, 18 Oct 2020 20:22:13 -0700 Subject: [PATCH 03/11] Add a button to the profile to support the weekly survey This allow users to answer the survey in-app even if they are not able to respond to the push notification in real time Testing done: - Launched the app - Clicked on the button - Confirmed that the weekly survey was launched --- www/i18n/en.json | 2 +- www/js/control/general-settings.js | 9 ++++++++- www/templates/control/main-control.html | 9 ++------- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/www/i18n/en.json b/www/i18n/en.json index 59a544dbd..c06616cad 100644 --- a/www/i18n/en.json +++ b/www/i18n/en.json @@ -54,7 +54,7 @@ "profile": "Profile", "tracking": "Tracking", "medium-accuracy": "Medium accuracy", - "dark-theme": "Dark theme", + "weekly-survey": "Weekly Survey", "force-sync": "Force sync", "share": "Share", "check-ui-updates": "Check for UI updates", diff --git a/www/js/control/general-settings.js b/www/js/control/general-settings.js index 8beb89ceb..7142e1348 100644 --- a/www/js/control/general-settings.js +++ b/www/js/control/general-settings.js @@ -21,7 +21,7 @@ angular.module('emission.main.control',['emission.services', ControlCollectionHelper, ControlSyncHelper, ControlTransitionNotifyHelper, CarbonDatasetHelper, - UpdateCheck, + SurveyLaunch, UpdateCheck, CalorieCal, ClientStats, CommHelper, Logger, $translate) { @@ -484,6 +484,13 @@ angular.module('emission.main.control',['emission.services', } }); }; + + $scope.launchWeeklySurvey = function() { + SurveyLaunch.startSurveyPrefilled( + 'https://docs.google.com/forms/d/e/1FAIpQLSfJ7qNRtHTYjobW6qFGMmtC8-axg_6MZU0HDCIYfD78ru8RBg/viewform', + 'entry.1942864803'); + } + $scope.expandDeveloperZone = function() { if ($scope.collectionExpanded()) { $scope.expanded = false; diff --git a/www/templates/control/main-control.html b/www/templates/control/main-control.html index 21fa43ff5..39f238172 100644 --- a/www/templates/control/main-control.html +++ b/www/templates/control/main-control.html @@ -23,13 +23,8 @@
-
{{'.dark-theme'}}
- +
{{'.weekly-survey'}}
+
{{carbonDatasetString}}
From c77aca93769fc2a62f97f6bbd39f25f255d790b1 Mon Sep 17 00:00:00 2001 From: Shankari Date: Thu, 19 Nov 2020 08:57:28 -0800 Subject: [PATCH 04/11] Switch the kobotoolbox survey to use prefilled values as well + add a button to launch the survey from the profile so current users can fill it in Testing done: - launched survey during onboarding + from the profile screen - confirmed with Bingrong that the UUID was filled in This partially fixes https://github.com/e-mission/e-mission-docs/issues/587 Full fix will involve updating the documentation --- www/i18n/en.json | 2 +- www/js/control/general-settings.js | 6 +++--- www/js/intro.js | 2 +- www/templates/control/main-control.html | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/www/i18n/en.json b/www/i18n/en.json index c06616cad..d53b633c2 100644 --- a/www/i18n/en.json +++ b/www/i18n/en.json @@ -54,7 +54,7 @@ "profile": "Profile", "tracking": "Tracking", "medium-accuracy": "Medium accuracy", - "weekly-survey": "Weekly Survey", + "demographic-survey": "Demographic Survey", "force-sync": "Force sync", "share": "Share", "check-ui-updates": "Check for UI updates", diff --git a/www/js/control/general-settings.js b/www/js/control/general-settings.js index 7142e1348..c8abeca71 100644 --- a/www/js/control/general-settings.js +++ b/www/js/control/general-settings.js @@ -485,10 +485,10 @@ angular.module('emission.main.control',['emission.services', }); }; - $scope.launchWeeklySurvey = function() { + $scope.launchDemographicSurvey = function() { SurveyLaunch.startSurveyPrefilled( - 'https://docs.google.com/forms/d/e/1FAIpQLSfJ7qNRtHTYjobW6qFGMmtC8-axg_6MZU0HDCIYfD78ru8RBg/viewform', - 'entry.1942864803'); + 'https://ee.kobotoolbox.org/x/hEkHk50v', + 'd[/arcEm5iPB4F9CQZR258k4r/group_hg4zz25/Here_is_your_UUID_wh_ake_any_change_to_it]'); } $scope.expandDeveloperZone = function() { diff --git a/www/js/intro.js b/www/js/intro.js index 7d94a3462..1625e3e6e 100644 --- a/www/js/intro.js +++ b/www/js/intro.js @@ -186,7 +186,7 @@ angular.module('emission.intro', ['emission.splash.startprefs', $scope.startSurvey = function () { SurveyLaunch.startSurveyWithXPath( 'https://ee.kobotoolbox.org/x/hEkHk50v', - '/html/body/div[1]/article/form/section[2]/label[1]/input'); + 'd[/arcEm5iPB4F9CQZR258k4r/group_hg4zz25/Here_is_your_UUID_wh_ake_any_change_to_it]'); } $scope.tokenToClipboard = function() { diff --git a/www/templates/control/main-control.html b/www/templates/control/main-control.html index 39f238172..b988a1757 100644 --- a/www/templates/control/main-control.html +++ b/www/templates/control/main-control.html @@ -23,8 +23,8 @@
-
{{'.weekly-survey'}}
-
+
{{'.demographic-survey'}}
+
{{carbonDatasetString}}
From 4a39072c75bdad4594f11b9ac1dd385616846108 Mon Sep 17 00:00:00 2001 From: Shankari Date: Fri, 20 Nov 2020 11:28:05 -0800 Subject: [PATCH 05/11] Use the online form so that it gets submitted immediately --- www/js/control/general-settings.js | 2 +- www/js/intro.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/www/js/control/general-settings.js b/www/js/control/general-settings.js index c8abeca71..3481bfea4 100644 --- a/www/js/control/general-settings.js +++ b/www/js/control/general-settings.js @@ -487,7 +487,7 @@ angular.module('emission.main.control',['emission.services', $scope.launchDemographicSurvey = function() { SurveyLaunch.startSurveyPrefilled( - 'https://ee.kobotoolbox.org/x/hEkHk50v', + 'https://ee.kobotoolbox.org/hEkHk50v', 'd[/arcEm5iPB4F9CQZR258k4r/group_hg4zz25/Here_is_your_UUID_wh_ake_any_change_to_it]'); } diff --git a/www/js/intro.js b/www/js/intro.js index 1625e3e6e..3cf80f8f9 100644 --- a/www/js/intro.js +++ b/www/js/intro.js @@ -184,8 +184,8 @@ angular.module('emission.intro', ['emission.splash.startprefs', } $scope.startSurvey = function () { - SurveyLaunch.startSurveyWithXPath( - 'https://ee.kobotoolbox.org/x/hEkHk50v', + SurveyLaunch.startSurveyPrefilled( + 'https://ee.kobotoolbox.org/hEkHk50v', 'd[/arcEm5iPB4F9CQZR258k4r/group_hg4zz25/Here_is_your_UUID_wh_ake_any_change_to_it]'); } From 9978e50d1a7b190bd1d7353a95658604d92daf06 Mon Sep 17 00:00:00 2001 From: Shankari Date: Fri, 28 Aug 2020 09:18:38 -0700 Subject: [PATCH 06/11] Switch the trip confirm screen to also go to the diary directly Avoids race conditions and confusion; highlights the diary We may want to merge this to master based on feedback from the CEO project --- www/js/diary/list.js | 8 ++++++-- www/js/splash/startprefs.js | 6 ++---- www/js/tripconfirm/post-trip-prompt.js | 5 +++++ 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/www/js/diary/list.js b/www/js/diary/list.js index e7e7da76d..2f21c9de6 100644 --- a/www/js/diary/list.js +++ b/www/js/diary/list.js @@ -245,7 +245,12 @@ angular.module('emission.main.diary.list',['ui-leaflet', $scope.populateBasicClasses(tripgj); $scope.populateCommonInfo(tripgj); }); - $ionicScrollDelegate.scrollTop(true); + if ($rootScope.displayingIncident) { + $ionicScrollDelegate.scrollBottom(true); + $rootScope.displayingIncident = false; + } else { + $ionicScrollDelegate.scrollTop(true); + } }); }); @@ -610,7 +615,6 @@ angular.module('emission.main.diary.list',['ui-leaflet', } else { Logger.log("currDay is not defined, load not complete"); } - $rootScope.displayingIncident = false; } }); }); diff --git a/www/js/splash/startprefs.js b/www/js/splash/startprefs.js index a58bdbcb3..ad794d232 100644 --- a/www/js/splash/startprefs.js +++ b/www/js/splash/startprefs.js @@ -167,11 +167,9 @@ angular.module('emission.splash.startprefs', ['emission.plugin.logger', var temp = ReferralHandler.getReferralNavigation(); if (temp == 'goals') { return {state: 'root.main.goals', params: {}}; - } else if ($rootScope.tripConfirmParams) { + } else if ($rootScope.displayingIncident) { logger.log("Showing tripconfirm from startprefs"); - var startEndParams = $rootScope.tripConfirmParams; - $rootScope.tripConfirmParams = angular.undefined; - return {state: 'root.main.tripconfirm', params: startEndParams}; + return {state: 'root.main.diary'}; } else if (angular.isDefined($rootScope.redirectTo)) { var redirState = $rootScope.redirectTo; $rootScope.redirectTo = undefined; diff --git a/www/js/tripconfirm/post-trip-prompt.js b/www/js/tripconfirm/post-trip-prompt.js index bd456f281..e9b011427 100644 --- a/www/js/tripconfirm/post-trip-prompt.js +++ b/www/js/tripconfirm/post-trip-prompt.js @@ -119,10 +119,15 @@ angular.module('emission.tripconfirm.posttrip.prompt', ['emission.plugin.logger' }; var displayCompletedTrip = function(notification, eventOpts) { + /* $rootScope.tripConfirmParams = notification.data; Logger.log("About to display completed trip from notification "+ JSON.stringify(notification.data)); $state.go("root.main.tripconfirm", notification.data); + */ + Logger.log("About to go to diary, which now displays draft information"); + $rootScope.displayingIncident = true; + $state.go("root.main.diary"); }; var checkCategory = function(notification) { From 985745eb6c398fca21e22b3fb18afe5e58a4e254 Mon Sep 17 00:00:00 2001 From: Shankari Date: Mon, 7 Dec 2020 17:59:28 -0800 Subject: [PATCH 07/11] Allow users to enter a prior token in the login screen Can change this based on feedback from initial testers --- www/js/intro.js | 45 ++++++++++++++++++++++++++++++++-- www/templates/intro/login.html | 6 ++++- 2 files changed, 48 insertions(+), 3 deletions(-) diff --git a/www/js/intro.js b/www/js/intro.js index 3cf80f8f9..e644d29a8 100644 --- a/www/js/intro.js +++ b/www/js/intro.js @@ -193,8 +193,49 @@ angular.module('emission.intro', ['emission.splash.startprefs', navigator.clipboard.writeText($scope.randomToken); }; - $scope.login = function() { - window.cordova.plugins.BEMJWTAuth.setPromptedAuthToken($scope.randomToken).then(function(userEmail) { + $scope.loginNew = function() { + $scope.login($scope.randomToken); + }; + + $scope.loginExisting = function() { + $scope.data = {}; + const tokenPopup = $ionicPopup.show({ + template: '', + title: 'Enter the existing token that you have', + scope: $scope, + buttons: [ + { + text: 'OK', + type: 'button-positive', + onTap: function(e) { + if (!$scope.data.existing_token) { + //don't allow the user to close unless he enters a username + + e.preventDefault(); + } else { + return $scope.data.existing_token; + } + } + },{ + text: 'Cancel', + type: 'button-stable', + onTap: function(e) { + return null; + } + } + ] + }); + tokenPopup.then(function(token) { + if (token != null) { + $scope.login($scope.randomToken); + } + }).catch(function(err) { + $scope.alertError(err); + }); + }; + + $scope.login = function(token) { + window.cordova.plugins.BEMJWTAuth.setPromptedAuthToken(token).then(function(userEmail) { // ionicToast.show(message, position, stick, time); // $scope.next(); ionicToast.show(userEmail, 'middle', false, 2500); diff --git a/www/templates/intro/login.html b/www/templates/intro/login.html index cc4c25240..23f045e2a 100644 --- a/www/templates/intro/login.html +++ b/www/templates/intro/login.html @@ -10,7 +10,11 @@ want to communicate with the research team about the data collected about you, please be prepared to provide this token.
- + + +If you already have a token from a previous install, you can use it instead to retain the same account. Note that there are no incorrect tokens. If you enter a token that does not match an existing one, we will create a new account. +
+
From 5a88766d47a0d336cdcb5b04d62000cb4652db83 Mon Sep 17 00:00:00 2001 From: Shankari Date: Mon, 7 Dec 2020 18:12:01 -0800 Subject: [PATCH 08/11] Switch back to the offline version of the surveys --- www/js/control/general-settings.js | 2 +- www/js/intro.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/www/js/control/general-settings.js b/www/js/control/general-settings.js index 3481bfea4..c8abeca71 100644 --- a/www/js/control/general-settings.js +++ b/www/js/control/general-settings.js @@ -487,7 +487,7 @@ angular.module('emission.main.control',['emission.services', $scope.launchDemographicSurvey = function() { SurveyLaunch.startSurveyPrefilled( - 'https://ee.kobotoolbox.org/hEkHk50v', + 'https://ee.kobotoolbox.org/x/hEkHk50v', 'd[/arcEm5iPB4F9CQZR258k4r/group_hg4zz25/Here_is_your_UUID_wh_ake_any_change_to_it]'); } diff --git a/www/js/intro.js b/www/js/intro.js index e644d29a8..4f8100409 100644 --- a/www/js/intro.js +++ b/www/js/intro.js @@ -185,7 +185,7 @@ angular.module('emission.intro', ['emission.splash.startprefs', $scope.startSurvey = function () { SurveyLaunch.startSurveyPrefilled( - 'https://ee.kobotoolbox.org/hEkHk50v', + 'https://ee.kobotoolbox.org/x/hEkHk50v', 'd[/arcEm5iPB4F9CQZR258k4r/group_hg4zz25/Here_is_your_UUID_wh_ake_any_change_to_it]'); } @@ -227,7 +227,7 @@ angular.module('emission.intro', ['emission.splash.startprefs', }); tokenPopup.then(function(token) { if (token != null) { - $scope.login($scope.randomToken); + $scope.login(token); } }).catch(function(err) { $scope.alertError(err); From 21ab3fa7c88c3b85201c3873c8cee1d4cc185234 Mon Sep 17 00:00:00 2001 From: Shankari Date: Wed, 16 Dec 2020 22:51:42 -0800 Subject: [PATCH 09/11] Improve the matching of user inputs to cleaned trips While matching user inputs on the server, found that user input matching was broken for some cleaned trips on the phone. https://github.com/e-mission/e-mission-docs/issues/476#issuecomment-747115640 Expanded the user input end check to fix. https://github.com/e-mission/e-mission-docs/issues/476#issuecomment-747222181 Will merge into master after additional testing on the branch. + bump up the allowed delta to 15 minutes since the time threshold default for the distance filter is 10 minutes. --- www/js/diary/list.js | 8 ++++---- www/js/diary/services.js | 35 ++++++++++++++++++++++++++--------- 2 files changed, 30 insertions(+), 13 deletions(-) diff --git a/www/js/diary/list.js b/www/js/diary/list.js index 2f21c9de6..6045054e4 100644 --- a/www/js/diary/list.js +++ b/www/js/diary/list.js @@ -165,8 +165,8 @@ angular.module('emission.main.diary.list',['ui-leaflet', /** * Embed 'inputType' to the trip */ - $scope.populateInputFromTimeline = function (tripgj, inputType, inputList) { - var userInput = DiaryHelper.getUserInputForTrip(tripgj, inputList); + $scope.populateInputFromTimeline = function (tripgj, nextTripgj, inputType, inputList) { + var userInput = DiaryHelper.getUserInputForTrip(tripgj, nextTripgj, inputList); if (angular.isDefined(userInput)) { // userInput is an object with data + metadata // the label is the "value" from the options @@ -237,10 +237,10 @@ angular.module('emission.main.diary.list',['ui-leaflet', DiaryHelper.directiveForTrip); Timeline.setTripWrappers(currDayTripWrappers); - $scope.data.currDayTripWrappers.forEach(function(tripgj, index, array) { + $scope.data.currDayTripWrappers.forEach(function(tripgj, tripIndex, array) { tripgj.userInput = {}; ConfirmHelper.INPUTS.forEach(function(item, index) { - $scope.populateInputFromTimeline(tripgj, item, $scope.data.unifiedConfirmsResults[item]); + $scope.populateInputFromTimeline(tripgj, array[tripIndex+1], item, $scope.data.unifiedConfirmsResults[item]); }); $scope.populateBasicClasses(tripgj); $scope.populateCommonInfo(tripgj); diff --git a/www/js/diary/services.js b/www/js/diary/services.js index 5dcdfaf5c..8cc75465e 100644 --- a/www/js/diary/services.js +++ b/www/js/diary/services.js @@ -405,7 +405,7 @@ angular.module('emission.main.diary.services', ['emission.plugin.logger', " " + ui.data.label + " logged at "+ ui.metadata.write_ts; } - dh.getUserInputForTrip = function(tripgj, userInputList) { + dh.getUserInputForTrip = function(tripgj, nextTripgj, userInputList) { if (userInputList.length < 20) { console.log("Input list = "+userInputList.map(printUserInput)); } @@ -431,13 +431,15 @@ angular.module('emission.main.diary.services', ['emission.plugin.logger', +" trip = "+fmtTs(tripProp.start_ts, userInput.metadata.time_zone) +" -> "+fmtTs(tripProp.end_ts, userInput.metadata.time_zone) +" checks are ("+(userInput.data.start_ts >= tripProp.start_ts) - +" || "+(-(userInput.data.start_ts - tripProp.start_ts) <= 5 * 60) + +" && "+(userInput.data.start_ts <= tripProp.end_ts) + +" || "+(-(userInput.data.start_ts - tripProp.start_ts) <= 15 * 60) +") && "+(userInput.data.end_ts <= tripProp.end_ts); console.log(logStr); // Logger.log(logStr); } return (userInput.data.start_ts >= tripProp.start_ts - || -(userInput.data.start_ts - tripProp.start_ts) <= 5 * 60) + && userInput.data.start_ts <= tripProp.end_ts + || -(userInput.data.start_ts - tripProp.start_ts) <= 15 * 60) && userInput.data.end_ts <= tripProp.end_ts; } else { // we know that the trip is cleaned so we can use the fmt_time @@ -448,14 +450,29 @@ angular.module('emission.main.diary.services', ['emission.plugin.logger', +" -> "+fmtTs(userInput.data.end_ts, userInput.metadata.time_zone) +" trip = "+tripProp.start_fmt_time +" -> "+tripProp.end_fmt_time - +" checks are "+(userInput.data.start_ts >= tripProp.start_ts) - +" && ("+(userInput.data.end_ts <= tripProp.end_ts) - +" || "+((userInput.data.end_ts - tripProp.end_ts) <= 5 * 60)+")"; + +" start checks are "+(userInput.data.start_ts >= tripProp.start_ts) + +" && "+(userInput.data.start_ts <= tripProp.end_ts) + +" end checks are "+(userInput.data.end_ts <= tripProp.end_ts) + +" || "+((userInput.data.end_ts - tripProp.end_ts) <= 15 * 60)+")"; Logger.log(logStr); } - return userInput.data.start_ts >= tripProp.start_ts - && (userInput.data.end_ts <= tripProp.end_ts || - (userInput.data.end_ts - tripProp.end_ts) <= 5 * 60); + // https://github.com/e-mission/e-mission-docs/issues/476#issuecomment-747222181 + const startChecks = userInput.data.start_ts >= tripProp.start_ts && + userInput.data.start_ts <= tripProp.end_ts; + var endChecks = (userInput.data.end_ts <= tripProp.end_ts || + (userInput.data.end_ts - tripProp.end_ts) <= 15 * 60); + if (!endChecks) { + if (angular.isDefined(nextTripgj)) { + endChecks = userInput.data.end_ts <= nextTripgj.start_ts; + Logger.log("Second level of end checks when the next trip is defined "+endChecks); + } else { + // next trip is not defined, last trip + endChecks = (userInput.data.end_local_dt.day == userInput.data.start_local_dt.day) + Logger.log("Second level of end checks for the last trip of the day"); + Logger.log("compare "+userInput.data.end_local_dt.day + " with " + userInput.data.start_local_dt.day + " = " + endChecks); + } + } + return startChecks && endChecks; } }); if (potentialCandidates.length === 0) { From 6bd731aabe3b30ffbf090aafad98c58636b5db0e Mon Sep 17 00:00:00 2001 From: Shankari Date: Thu, 17 Dec 2020 11:35:02 -0800 Subject: [PATCH 10/11] Fix regression in enhanced trip matching The enhanced trip matching (75129dbbe4e7d85e7e263f550ec96b3e078c6c01) caused a regression in which a spurious trip (not a trip) that occurred after the real trip fit the criteria for a match. And since it was confirmed after the real trip, as you would expect while going down the trip list, it was matched preferentially. https://github.com/e-mission/e-mission-docs/issues/476#issuecomment-747587041 Fixed by checking the degree over overlap and rejecting too short matches --- www/js/diary/services.js | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/www/js/diary/services.js b/www/js/diary/services.js index 8cc75465e..2ad24e8c2 100644 --- a/www/js/diary/services.js +++ b/www/js/diary/services.js @@ -461,16 +461,24 @@ angular.module('emission.main.diary.services', ['emission.plugin.logger', userInput.data.start_ts <= tripProp.end_ts; var endChecks = (userInput.data.end_ts <= tripProp.end_ts || (userInput.data.end_ts - tripProp.end_ts) <= 15 * 60); - if (!endChecks) { + if (startChecks && !endChecks) { if (angular.isDefined(nextTripgj)) { - endChecks = userInput.data.end_ts <= nextTripgj.start_ts; - Logger.log("Second level of end checks when the next trip is defined "+endChecks); + endChecks = userInput.data.end_ts <= nextTripgj.data.properties.start_ts; + Logger.log("Second level of end checks when the next trip is defined("+userInput.data.end_ts+" <= "+ nextTripgj.data.properties.start_ts+") = "+endChecks); } else { // next trip is not defined, last trip endChecks = (userInput.data.end_local_dt.day == userInput.data.start_local_dt.day) Logger.log("Second level of end checks for the last trip of the day"); Logger.log("compare "+userInput.data.end_local_dt.day + " with " + userInput.data.start_local_dt.day + " = " + endChecks); } + if (endChecks) { + // If we have flipped the values, check to see that there + // is sufficient overlap + const overlapDuration = Math.min(userInput.data.end_ts, tripProp.end_ts) - Math.max(userInput.data.start_ts, tripProp.start_ts) + Logger.log("Flipped endCheck, overlap("+overlapDuration+ + ")/trip("+tripProp.duration+") = "+ (overlapDuration / tripProp.duration)); + endChecks = (overlapDuration/tripProp.duration) > 0.5; + } } return startChecks && endChecks; } From d20f2cfa82a1886eae1f185538fc3b27bda550ab Mon Sep 17 00:00:00 2001 From: Shankari Date: Wed, 17 Feb 2021 20:07:46 -0800 Subject: [PATCH 11/11] Fix the infinite scroll user input matching to be consistent with the refactor in 21ab3fa7c88c3b85201c3873c8cee1d4cc185234 and 6bd731aabe3b30ffbf090aafad98c58636b5db0e --- www/js/diary/infinite_scroll_list.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/www/js/diary/infinite_scroll_list.js b/www/js/diary/infinite_scroll_list.js index 9a1c67290..30a5c6637 100644 --- a/www/js/diary/infinite_scroll_list.js +++ b/www/js/diary/infinite_scroll_list.js @@ -68,10 +68,10 @@ angular.module('emission.main.diary.infscrolllist',['ui-leaflet', Logger.log("Received batch of size "+ctList.length); ctList.reverse(); ctList.forEach($scope.populateBasicClasses); - ctList.forEach((trip) => { + ctList.forEach((trip, tIndex) => { trip.userInput = {}; ConfirmHelper.INPUTS.forEach(function(item, index) { - $scope.populateManualInputs(trip, item, $scope.data.manualResultMap[item]); + $scope.populateManualInputs(trip, ctList[tIndex+1], item, $scope.data.manualResultMap[item]); }); }); ctList.forEach(function(trip, index) { @@ -252,11 +252,12 @@ angular.module('emission.main.diary.infscrolllist',['ui-leaflet', /** * Embed 'inputType' to the trip */ - $scope.populateManualInputs = function (tripgj, inputType, inputList) { + $scope.populateManualInputs = function (tripgj, nextTripgj, inputType, inputList) { // Check unprocessed labels first since they are more recent // Massage the input to meet getUserInputForTrip expectations const unprocessedLabelEntry = DiaryHelper.getUserInputForTrip( {data: {properties: tripgj, features: [{}, {}, {}]}}, + {data: {properties: nextTripgj, features: [{}, {}, {}]}}, inputList); var userInputLabel = unprocessedLabelEntry? unprocessedLabelEntry.data.label : undefined; if (!angular.isDefined(userInputLabel)) {