Skip to content

Commit

Permalink
Merge branch 'master' into customize-modes-step2
Browse files Browse the repository at this point in the history
  • Loading branch information
JGreenlee authored Mar 25, 2024
2 parents 15c994a + c61ed71 commit 45bfc2d
Show file tree
Hide file tree
Showing 104 changed files with 1,714 additions and 1,267 deletions.
12 changes: 9 additions & 3 deletions package.cordovabuild.json
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,10 @@
"cordova-plugin-androidx-adapter": {},
"phonegap-plugin-barcodescanner": {
"ANDROID_SUPPORT_V4_VERSION": "27.+"
}
},
"cordova-plugin-bluetooth-classic-serial-port": {},
"cordova-custom-config": {},
"cordova-plugin-ibeacon": {}
}
},
"dependencies": {
Expand All @@ -118,7 +121,7 @@
"cordova-plugin-app-version": "0.1.14",
"cordova-plugin-customurlscheme": "5.0.2",
"cordova-plugin-device": "2.1.0",
"cordova-plugin-em-datacollection": "git+https://github.com/e-mission/e-mission-data-collection.git#v1.8.2",
"cordova-plugin-em-datacollection": "git+https://github.com/e-mission/e-mission-data-collection.git#v1.8.3",
"cordova-plugin-em-opcodeauth": "git+https://github.com/e-mission/cordova-jwt-auth.git#v1.7.2",
"cordova-plugin-em-server-communication": "git+https://github.com/e-mission/cordova-server-communication.git#v1.2.6",
"cordova-plugin-em-serversync": "git+https://github.com/e-mission/cordova-server-sync.git#v1.3.2",
Expand All @@ -132,6 +135,9 @@
"cordova-plugin-ionic-webview": "5.0.0",
"cordova-plugin-local-notification-12": "github:e-mission/cordova-plugin-local-notification-12#v0.1.4-fix-android-action",
"cordova-plugin-x-socialsharing": "6.0.4",
"cordova-plugin-bluetooth-classic-serial-port": "git+https://github.com/louisg1337/cordova-plugin-bluetooth-classic-serial-port.git",
"cordova-custom-config": "^5.1.1",
"cordova-plugin-ibeacon": "git+https://github.com/louisg1337/cordova-plugin-ibeacon.git",
"core-js": "^2.5.7",
"enketo-core": "^6.1.7",
"enketo-transformer": "^4.0.0",
Expand All @@ -150,7 +156,7 @@
"react-chartjs-2": "^5.2.0",
"react-dom": "^18.2.*",
"react-i18next": "^13.5.0",
"react-native-paper": "^5.8.0",
"react-native-paper": "^5.11.0",
"react-native-paper-dates": "^0.18.12",
"react-native-safe-area-context": "^4.6.3",
"react-native-screens": "^3.22.0",
Expand Down
2 changes: 1 addition & 1 deletion package.serve.json
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@
"react-chartjs-2": "^5.2.0",
"react-dom": "^18.2.*",
"react-i18next": "^13.5.0",
"react-native-paper": "^5.8.0",
"react-native-paper": "^5.11.0",
"react-native-paper-dates": "^0.18.12",
"react-native-safe-area-context": "^4.6.3",
"react-native-screens": "^3.22.0",
Expand Down
1 change: 0 additions & 1 deletion setup/android_sdk_packages
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ build-tools;33.0.2
build-tools;34.0.0
emulator
extras;google;google_play_services
patcher;v4
platform-tools
platforms;android-30
platforms;android-31
Expand Down
1 change: 1 addition & 0 deletions setup/autoreload/macos-index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
const os = require('os');

const nameMap = new Map([
[23, ['Sonoma', '14.3.1']],
[22, ['Ventura', '13']],
[21, ['Monterey', '12']],
[20, ['Big Sur', '11']],
Expand Down
2 changes: 1 addition & 1 deletion setup/setup_shared_native.sh
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ sed -i -e "s|/usr/bin/env node|/usr/bin/env node --unhandled-rejections=strict|"

npx cordova prepare

EXPECTED_COUNT=23
EXPECTED_COUNT=26
INSTALLED_COUNT=`npx cordova plugin list | wc -l`
echo "Found $INSTALLED_COUNT plugins, expected $EXPECTED_COUNT"
if [ $INSTALLED_COUNT -lt $EXPECTED_COUNT ];
Expand Down
4 changes: 4 additions & 0 deletions www/__mocks__/fakeLabels.json
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,10 @@
"baseMode": "OTHER",
"met_equivalent": "UNKNOWN",
"kgCo2PerKm": 0
},
{
"value": "unicycle",
"baseMode": "UNICYCLE"
}
],
"PURPOSE": [
Expand Down
2 changes: 1 addition & 1 deletion www/__mocks__/fileSystemMocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ export const mockFileSystem = () => {
onerror: (e: any) => void;
write: (obj: Blob) => void;
};
window['resolveLocalFileSystemURL'] = function (parentDir, handleFS) {
window['resolveLocalFileSystemURL'] = (parentDir, handleFS) => {
const fs = {
filesystem: {
root: {
Expand Down
14 changes: 4 additions & 10 deletions www/__mocks__/pushNotificationMocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,10 @@ export const mockPushNotification = () => {
};
};

export const clearNotifMock = function () {
export function clearNotifMock() {
notifSettings = {};
onList = {};
called = null;
};

export const getOnList = function () {
return onList;
};

export const getCalled = function () {
return called;
};
}
export const getOnList = () => onList;
export const getCalled = () => called;
24 changes: 18 additions & 6 deletions www/__tests__/customMetricsHelper.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { getConfig } from '../js/config/dynamicConfig';
import {
_test_clearCustomMetrics,
getCustomFootprint,
getCustomMETs,
initCustomDatasetHelper,
Expand All @@ -12,6 +13,10 @@ import fakeConfig from '../__mocks__/fakeConfig.json';
mockBEMUserCache(fakeConfig);
mockLogger();

beforeEach(() => {
_test_clearCustomMetrics();
});

global.fetch = (url: string) =>
new Promise((rs, rj) => {
setTimeout(() =>
Expand All @@ -25,9 +30,15 @@ global.fetch = (url: string) =>
);
}) as any;

it('has no footprint or mets before initialized', () => {
expect(getCustomFootprint()).toBeUndefined();
expect(getCustomMETs()).toBeUndefined();
});

it('gets the custom mets', async () => {
const appConfig = await getConfig();
await initCustomDatasetHelper(appConfig);
//expecting the keys from fakeLabels.json NOT metrics/metDataset.ts
expect(getCustomMETs()).toMatchObject({
walk: expect.any(Object),
bike: expect.any(Object),
Expand All @@ -41,12 +52,13 @@ it('gets the custom mets', async () => {
it('gets the custom footprint', async () => {
const appConfig = await getConfig();
await initCustomDatasetHelper(appConfig);
//numbers from fakeLabels.json
expect(getCustomFootprint()).toMatchObject({
walk: expect.any(Number),
bike: expect.any(Number),
bikeshare: expect.any(Number),
'e-bike': expect.any(Number),
scootershare: expect.any(Number),
drove_alone: expect.any(Number),
walk: 0,
bike: 0,
bikeshare: 0,
'e-bike': 0.00728,
scootershare: 0.00894,
drove_alone: 0.22031,
});
});
31 changes: 28 additions & 3 deletions www/__tests__/footprintHelper.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import { initCustomDatasetHelper } from '../js/metrics/customMetricsHelper';
import {
_test_clearCustomMetrics,
initCustomDatasetHelper,
} from '../js/metrics/customMetricsHelper';
import {
clearHighestFootprint,
getFootprintForMetrics,
Expand Down Expand Up @@ -29,36 +32,58 @@ global.fetch = (url: string) =>

beforeEach(() => {
clearHighestFootprint();
_test_clearCustomMetrics();
});

const custom_metrics = [
{ key: 'walk', values: 3000 },
{ key: 'ON_FOOT', values: 3000 }, //hits fallback under custom paradigm
{ key: 'bike', values: 6500 },
{ key: 'drove_alone', values: 10000 },
{ key: 'scootershare', values: 25000 },
{ key: 'unicycle', values: 5000 },
];

/*
3*0 + 6.5*0 + 10*0.22031 + 25*0.00894 + 5*0
0 + 0 + 2.2031 + 0.2235 + 0
2.4266
*/
it('gets footprint for metrics (custom, fallback 0)', async () => {
const appConfig = await getConfig();
await initCustomDatasetHelper(appConfig);
expect(getFootprintForMetrics(custom_metrics, 0)).toBe(2.4266);
});

/*
3*0.1 + 6.5*0 + 10*0.22031 + 25*0.00894 + 5*0.1
0.3 + 0 + 2.2031 + 0.2235 + 0.5
0.3 2.4266 + 0.5
*/
it('gets footprint for metrics (custom, fallback 0.1)', async () => {
const appConfig = await getConfig();
await initCustomDatasetHelper(appConfig);
expect(getFootprintForMetrics(custom_metrics, 0.1)).toBe(2.4266 + 0.5);
expect(getFootprintForMetrics(custom_metrics, 0.1)).toBe(3.2266);
});

//expects TAXI from the fake labels
it('gets the highest footprint from the dataset, custom', async () => {
const appConfig = await getConfig();
await initCustomDatasetHelper(appConfig);
expect(getHighestFootprint()).toBe(0.30741);
});

/*
TAXI co2/km * meters/1000
*/
it('gets the highest footprint for distance, custom', async () => {
const appConfig = await getConfig();
await initCustomDatasetHelper(appConfig);
expect(getHighestFootprintForDistance(12345)).toBe(0.30741 * (12345 / 1000));
});

it('errors out if not initialized', () => {
const t = () => {
getFootprintForMetrics(custom_metrics, 0);
};
expect(t).toThrow(Error);
});
7 changes: 5 additions & 2 deletions www/__tests__/inputMatcher.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { mockBEMUserCache } from '../__mocks__/cordovaMocks';
import { mockLogger } from '../__mocks__/globalMocks';
import { unprocessedLabels, updateLocalUnprocessedInputs } from '../js/diary/timelineHelper';
import * as logger from '../js/plugin/logger';
import { EnketoUserInputEntry } from '../js/survey/enketo/enketoHelper';
import {
fmtTs,
Expand Down Expand Up @@ -148,11 +149,13 @@ describe('input-matcher', () => {
});

it('tests getNotDeletedCandidates called with 0 candidates', () => {
jest.spyOn(console, 'log');
jest.spyOn(logger, 'logDebug');
const candidates = getNotDeletedCandidates([]);

// check if the log printed collectly with
expect(console.log).toHaveBeenCalledWith('getNotDeletedCandidates called with 0 candidates');
expect(logger.logDebug).toHaveBeenCalledWith(
'getNotDeletedCandidates called with 0 candidates',
);
expect(candidates).toStrictEqual([]);
});

Expand Down
23 changes: 13 additions & 10 deletions www/__tests__/metHelper.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,19 +23,22 @@ global.fetch = (url: string) =>
}) as any;

it('gets met for mode and speed', () => {
expect(getMet('WALKING', 1.47523, 0)).toBe(4.3);
expect(getMet('BICYCLING', 4.5, 0)).toBe(6.8);
expect(getMet('UNICYCLE', 100, 0)).toBe(0);
expect(getMet('CAR', 25, 1)).toBe(0);
expect(getMet('WALKING', 1.47523, 0)).toBe(4.3); //1.47523 mps = 3.299 mph -> 4.3 METs
expect(getMet('BICYCLING', 4.5, 0)).toBe(6.8); //4.5 mps = 10.07 mph = 6.8 METs
expect(getMet('UNICYCLE', 100, 0)).toBe(0); //unkown mode, 0 METs
expect(getMet('CAR', 25, 1)).toBe(0); //0 METs in CAR
expect(getMet('ON_FOOT', 1.47523, 0)).toBe(4.3); //same as walking!
expect(getMet('WALKING', -2, 0)).toBe(0); //negative speed -> 0
});

it('gets custom met for mode and speed', async () => {
const appConfig = await getConfig();
await initCustomDatasetHelper(appConfig);
expect(getMet('walk', 1.47523, 0)).toBe(4.3);
expect(getMet('bike', 4.5, 0)).toBe(6.8);
expect(getMet('unicycle', 100, 0)).toBe(0);
expect(getMet('drove_alone', 25, 1)).toBe(0);
expect(getMet('e-bike', 6, 1)).toBe(4.9);
expect(getMet('e-bike', 12, 1)).toBe(4.9);
expect(getMet('walk', 1.47523, 0)).toBe(4.3); //1.47523 mps = 3.299 mph -> 4.3 METs
expect(getMet('bike', 4.5, 0)).toBe(6.8); //4.5 mps = 10.07 mph = 6.8 METs
expect(getMet('unicycle', 100, 0)).toBe(0); //unkown mode, 0 METs
expect(getMet('drove_alone', 25, 1)).toBe(0); //0 METs IN_VEHICLE
expect(getMet('e-bike', 6, 1)).toBe(4.9); //e-bike is 4.9 for all speeds
expect(getMet('e-bike', 12, 1)).toBe(4.9); //e-bike is 4.9 for all speeds
expect(getMet('walk', -2, 1)).toBe(0); //negative speed -> 0
});
6 changes: 6 additions & 0 deletions www/css/style.css → www/css/style.scss
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
/* This file is in Sassy CSS (SCSS) because Enketo uses SCSS and we want to extend on their styles.
Webpack will just compile this to plain CSS anyway */

@import 'leaflet/dist/leaflet.css';

html {
Expand All @@ -7,6 +10,9 @@ html {
/* Scoped styles for Enketo */
/* if we don't contain them here, they will leak into the rest of the app */
.enketo-plugin {
// Enketo's default theme uses orange; we can override with our own blue
$primary: #0080b9; // matches 'primary' in appTheme.ts
$brand-primary-color: darken($primary, 5%); // make it a bit darker for legibility in Enketo UI
@import 'enketo-core/src/sass/formhub/formhub.scss';
flex: 1;
.question.non-select {
Expand Down
44 changes: 34 additions & 10 deletions www/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
"user-data": "User data",
"erase-data": "Erase data",
"dev-zone": "Developer zone",
"bluetooth-scan": "Scan for Bluetooth",
"refresh": "Refresh",
"end-trip-sync": "End trip + sync",
"check-consent": "Check consent",
Expand Down Expand Up @@ -132,13 +133,13 @@
"to-label": "To Label",
"show-all": "All Trips",
"no-trips-found": "No trips found",
"choose-mode": "Mode 📝 ",
"choose-replaced-mode": "Replaces 📝",
"choose-purpose": "Purpose 📝",
"choose-survey": "Add Trip Details 📝 ",
"select-mode-scroll": "Mode (👇 for more)",
"select-replaced-mode-scroll": "Replaces (👇 for more)",
"select-purpose-scroll": "Purpose (👇 for more)",
"choose-mode": "Mode",
"choose-replaced-mode": "Replaces",
"choose-purpose": "Purpose",
"choose-survey": "Add Trip Details",
"select-mode-scroll": "Mode (scroll for more)",
"select-replaced-mode-scroll": "Replaces (scroll for more)",
"select-purpose-scroll": "Purpose (scroll for more)",
"delete-entry-confirm": "Are you sure you wish to delete this entry?",
"detected": "Detected:",
"labeled-mode": "Labeled Mode",
Expand Down Expand Up @@ -234,6 +235,27 @@
"list-datepicker-close": "Close",
"list-datepicker-set": "Set",

"bluetooth": {
"title": {
"ble": "BLE Beacon Scanner",
"classic": "Bluetooth Classic Scanner"
},
"scan": {
"for-ble": "Scan for BLE Beacons",
"for-bluetooth": "Scan for Classic Devices",
"stop": "Stop Scanning"
},
"is-scanning": "Scanning...",
"device-info": {
"id": "ID",
"name": "Name"
},
"switch-to": {
"classic": "Switch to Classic",
"ble": "Switch to BLE"
}
},

"service": {
"reading-server": "Reading from server...",
"reading-unprocessed-data": "Reading unprocessed data..."
Expand Down Expand Up @@ -376,6 +398,7 @@
"paste-code": "Paste code",
"scan-hint": "Scan the barcode with your phone camera",
"paste-hint": "Or, paste the code as text",
"more-info": "More Info",
"about-app-title": "About {{appName}}",
"about-app-para-1": "The National Renewable Energy Laboratory’s Open Platform for Agile Trip Heuristics (NREL OpenPATH) enables people to track their travel modes—car, bus, bike, walking, etc.—and measure their associated energy use and carbon footprint.",
"about-app-para-2": "The app empowers communities to understand their travel mode choices and patterns, experiment with options to make them more sustainable, and evaluate the results. Such results can inform effective transportation policy and planning and be used to build more sustainable and accessible cities.",
Expand Down Expand Up @@ -412,7 +435,8 @@
"while-repopulating-entry": "While repopulating timeline entry: ",
"while-loading-metrics": "While loading metrics: ",
"while-log-messages": "While getting messages from the log ",
"while-max-index": "While getting max index "
"while-max-index": "While getting max index ",
"while-scanning-bluetooth": "While scanning for Bluetooth Devices: "
},
"consent-text": {
"title": "NREL OPENPATH PRIVACY POLICY/TERMS OF USE",
Expand Down Expand Up @@ -445,8 +469,8 @@
"header": "Who gets to see the information",
"public-dash": "Aggregate metrics derived from the travel patterns will be made available on a public dashboard to provide transparency into the impact of the program. These metrics will focus on information summaries such as counts, distances and durations, and will not display individual travel locations or times.",
"individual-info": "Individual labeling rates and trip level information will only be made available to:",
"program-admins": "🧑 Program administrators from {{deployment_partner_name}} to {{raw_data_use}}, and",
"nrel-devs": "💻 NREL OpenPATH developers for debugging",
"program-admins": "Program administrators from {{deployment_partner_name}} to {{raw_data_use}}, and",
"nrel-devs": "NREL OpenPATH developers for debugging",
"TSDC-info": "The data will also be periodically archived in NREL’s Transportation Secure Data Center (TSDC) after a delay of 3 to 6 months. It will then be made available for legitimate research through existing, privacy-preserving TSDC operating procedures. Further information on the procedures is available",
"on-website": " on the website ",
"and-in": "and in",
Expand Down
Loading

0 comments on commit 45bfc2d

Please sign in to comment.