From dc7b1771d5ee9716aa9c1af8c81c6ffa4ac46618 Mon Sep 17 00:00:00 2001 From: "@shahapug" Date: Wed, 9 Apr 2025 10:07:55 +0100 Subject: [PATCH 01/14] method to update monthly distances in database --- server/src/sustainability.py | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/server/src/sustainability.py b/server/src/sustainability.py index 3b6babb..e55f22e 100644 --- a/server/src/sustainability.py +++ b/server/src/sustainability.py @@ -142,6 +142,40 @@ def db_fetch_year_sus_stats(self, user): print("Year stats not found") return None + def db_update_monthly_distances(self, user, journey_data): + table_name = "monthly_distance" + db = DataBase() + db.connect_db() + + # If user found + if db.search_user(table_name, user): + self.logger.info("Found user") + for transport_mode in journey_data: + if transport_mode not in self.vehicle_types: + self.logger.error( + f"Invalid transport mode: {transport_mode}" + ) + continue + + # Get distance for each transport mode + raw_distances = db.return_user_row(table_name, user) + self.logger.info(f"Raw distances: {raw_distances}") + # Add new distances to the existing ones + journey_data[transport_mode] += raw_distances[transport_mode] + self.logger.info(f"Updated distances: {journey_data[transport_mode]}") + # Update the database with new distances + db.update_entry( + table_name, user, transport_mode, journey_data[transport_mode] + ) + db.close_con() + return True + + else: + db.close_con() + print("Monthly distances not found") + return False + + def db_fetch_raw_distances(self, user): table_name = "monthly_distance" db = DataBase() From 93cdbd94632f8fdd689391b47562c6459ba0d08a Mon Sep 17 00:00:00 2001 From: Ma-Golden <125670894+Ma-Golden@users.noreply.github.com> Date: Wed, 9 Apr 2025 10:21:10 +0100 Subject: [PATCH 02/14] test for update monthly distances --- server/tests/test_sustainability.py | 48 +++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/server/tests/test_sustainability.py b/server/tests/test_sustainability.py index df9a0b3..5bbcc83 100644 --- a/server/tests/test_sustainability.py +++ b/server/tests/test_sustainability.py @@ -175,6 +175,54 @@ def test_emissions_savings(sustainability_instance): "walk": 510, } +def test_db_update_monthly_distances_success(sustainability_instance): + """ + Test for successful update of monthly distances + """ + with patch("src.sustainability.DataBase") as mock_db_class: + mock_db = MagicMock() + mock_db.search_user.return_value = True + mock_db.return_user_row.return_value = { + "username": "test_user", + "bike": 10, + "car": 20, + "luas": 30, + "train": 50, + "bus": 80, + "walk": 20, + "total": 210, + } + + mock_db_class.return_value = mock_db + + journey_data = { + "bike": 5, + "car": 15, + "luas": 10, + "train": 10, + "bus": 20, + "walk": 5 + } + + result = sustainability_instance.db_update_monthly_distances("test_user", journey_data) + + assert result is True + mock_db.search_user.assert_called_once_with("monthly_distance", "test_user") + + # Verify that update_entry was called with correct parameters for each transport mode + assert mock_db.update_entry.call_count == 6 + + assert mock_db.update_entry_any_call("monthly_distance", "test_user", "bike", 15) + assert mock_db.update_entry_any_call("monthly_distance", "test_user", "car", 35) + assert mock_db.update_entry_any_call("monthly_distance", "test_user", "luas", 40) + assert mock_db.update_entry_any_call("monthly_distance", "test_user", "train", 60) + assert mock_db.update_entry_any_call("monthly_distance", "test_user", "bus", 100) + assert mock_db.update_entry_any_call("monthly_distance", "test_user", "walk", 25) + + + + + def test_car_calc_emissions(sustainability_instance): assert sustainability_instance.calc_emissions(7, "car") == 714 From 5f89bcbd078bba15978e416465e5fd15d9129eb5 Mon Sep 17 00:00:00 2001 From: "@shahapug" Date: Wed, 9 Apr 2025 10:40:00 +0100 Subject: [PATCH 03/14] calculate route sustainability score --- server/src/sustainability.py | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/server/src/sustainability.py b/server/src/sustainability.py index e55f22e..4c6b947 100644 --- a/server/src/sustainability.py +++ b/server/src/sustainability.py @@ -284,6 +284,35 @@ def calc_scores(self, emissions_difference: float) -> float: return round(emissions_difference / 1000, 2) + def calc_scores_from_route(self, user, journey_data): + table_name = "monthly_distance" + db = DataBase() + db.connect_db() + + calc_emissions_savings = self.calc_emissions_savings(journey_data) + transport_score = 0 + + # If user found + if db.search_user(table_name, user): + self.logger.info("Found user") + for transport_mode in journey_data: + if transport_mode not in self.vehicle_types: + self.logger.error( + f"Invalid transport mode: {transport_mode}" + ) + continue + + transport_score += self.calc_scores( + calc_emissions_savings[transport_mode] + ) + db.close_con() + return transport_score + + else: + db.close_con() + print("Monthly distances not found") + return 0 + def calc_emissions_savings(self, monthly_distances): emissions_dif = { "bike": 0, From b0423ab230341e80e48c32498ada4f78c1b90691 Mon Sep 17 00:00:00 2001 From: JasonBoutlas Date: Wed, 9 Apr 2025 11:06:59 +0100 Subject: [PATCH 04/14] Integration between wf and sustainability --- client/package-lock.json | 172 ----------------------------------- client/src/SelectRoute.js | 24 +++++ server/src/sustainability.py | 28 +++++- 3 files changed, 50 insertions(+), 174 deletions(-) diff --git a/client/package-lock.json b/client/package-lock.json index 70ae650..2e4b7f3 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -2641,9 +2641,6 @@ } }, "node_modules/@expo/config": { - "version": "10.0.11", - "resolved": "https://registry.npmjs.org/@expo/config/-/config-10.0.11.tgz", - "integrity": "sha512-nociJ4zr/NmbVfMNe9j/+zRlt7wz/siISu7PjdWE4WE+elEGxWWxsGzltdJG0llzrM+khx8qUiFK5aiVcdMBww==", "version": "10.0.11", "resolved": "https://registry.npmjs.org/@expo/config/-/config-10.0.11.tgz", "integrity": "sha512-nociJ4zr/NmbVfMNe9j/+zRlt7wz/siISu7PjdWE4WE+elEGxWWxsGzltdJG0llzrM+khx8qUiFK5aiVcdMBww==", @@ -2652,8 +2649,6 @@ "@babel/code-frame": "~7.10.4", "@expo/config-plugins": "~9.0.17", "@expo/config-types": "^52.0.5", - "@expo/config-plugins": "~9.0.17", - "@expo/config-types": "^52.0.5", "@expo/json-file": "^9.0.2", "deepmerge": "^4.3.1", "getenv": "^1.0.0", @@ -2745,9 +2740,6 @@ } }, "node_modules/@expo/config-types": { - "version": "52.0.5", - "resolved": "https://registry.npmjs.org/@expo/config-types/-/config-types-52.0.5.tgz", - "integrity": "sha512-AMDeuDLHXXqd8W+0zSjIt7f37vUd/BP8p43k68NHpyAvQO+z8mbQZm3cNQVAMySeayK2XoPigAFB1JF2NFajaA==", "version": "52.0.5", "resolved": "https://registry.npmjs.org/@expo/config-types/-/config-types-52.0.5.tgz", "integrity": "sha512-AMDeuDLHXXqd8W+0zSjIt7f37vUd/BP8p43k68NHpyAvQO+z8mbQZm3cNQVAMySeayK2XoPigAFB1JF2NFajaA==", @@ -2784,28 +2776,6 @@ "xml2js": "0.6.0" } }, - "node_modules/@expo/config/node_modules/@expo/config-plugins": { - "version": "9.0.17", - "resolved": "https://registry.npmjs.org/@expo/config-plugins/-/config-plugins-9.0.17.tgz", - "integrity": "sha512-m24F1COquwOm7PBl5wRbkT9P9DviCXe0D7S7nQsolfbhdCWuvMkfXeoWmgjtdhy7sDlOyIgBrAdnB6MfsWKqIg==", - "license": "MIT", - "dependencies": { - "@expo/config-types": "^52.0.5", - "@expo/json-file": "~9.0.2", - "@expo/plist": "^0.2.2", - "@expo/sdk-runtime-versions": "^1.0.0", - "chalk": "^4.1.2", - "debug": "^4.3.5", - "getenv": "^1.0.0", - "glob": "^10.4.2", - "resolve-from": "^5.0.0", - "semver": "^7.5.4", - "slash": "^3.0.0", - "slugify": "^1.6.6", - "xcode": "^3.0.1", - "xml2js": "0.6.0" - } - }, "node_modules/@expo/config/node_modules/brace-expansion": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", @@ -4252,7 +4222,6 @@ "resolved": "https://registry.npmjs.org/@react-native-async-storage/async-storage/-/async-storage-2.1.2.tgz", "integrity": "sha512-dvlNq4AlGWC+ehtH12p65+17V0Dx7IecOWl6WanF2ja38O1Dcjjvn7jVzkUHJ5oWkQBlyASurTPlTHgKXyYiow==", "dev": true, - "dev": true, "license": "MIT", "dependencies": { "merge-options": "^3.0.4" @@ -6671,9 +6640,6 @@ "license": "ISC" }, "node_modules/@urql/core": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/@urql/core/-/core-5.1.1.tgz", - "integrity": "sha512-aGh024z5v2oINGD/In6rAtVKTm4VmQ2TxKQBAtk2ZSME5dunZFcjltw4p5ENQg+5CBhZ3FHMzl0Oa+rwqiWqlg==", "version": "5.1.1", "resolved": "https://registry.npmjs.org/@urql/core/-/core-5.1.1.tgz", "integrity": "sha512-aGh024z5v2oINGD/In6rAtVKTm4VmQ2TxKQBAtk2ZSME5dunZFcjltw4p5ENQg+5CBhZ3FHMzl0Oa+rwqiWqlg==", @@ -7778,99 +7744,6 @@ "@babel/preset-env": "^7.1.6" } }, - "node_modules/babel-preset-expo/node_modules/@react-native/babel-plugin-codegen": { - "version": "0.76.7", - "resolved": "https://registry.npmjs.org/@react-native/babel-plugin-codegen/-/babel-plugin-codegen-0.76.7.tgz", - "integrity": "sha512-+8H4DXJREM4l/pwLF/wSVMRzVhzhGDix5jLezNrMD9J1U1AMfV2aSkWA1XuqR7pjPs/Vqf6TaPL7vJMZ4LU05Q==", - "license": "MIT", - "dependencies": { - "@react-native/codegen": "0.76.7" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/babel-preset-expo/node_modules/@react-native/babel-preset": { - "version": "0.76.7", - "resolved": "https://registry.npmjs.org/@react-native/babel-preset/-/babel-preset-0.76.7.tgz", - "integrity": "sha512-/c5DYZ6y8tyg+g8tgXKndDT7mWnGmkZ9F+T3qNDfoE3Qh7ucrNeC2XWvU9h5pk8eRtj9l4SzF4aO1phzwoibyg==", - "license": "MIT", - "dependencies": { - "@babel/core": "^7.25.2", - "@babel/plugin-proposal-export-default-from": "^7.24.7", - "@babel/plugin-syntax-dynamic-import": "^7.8.3", - "@babel/plugin-syntax-export-default-from": "^7.24.7", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-transform-arrow-functions": "^7.24.7", - "@babel/plugin-transform-async-generator-functions": "^7.25.4", - "@babel/plugin-transform-async-to-generator": "^7.24.7", - "@babel/plugin-transform-block-scoping": "^7.25.0", - "@babel/plugin-transform-class-properties": "^7.25.4", - "@babel/plugin-transform-classes": "^7.25.4", - "@babel/plugin-transform-computed-properties": "^7.24.7", - "@babel/plugin-transform-destructuring": "^7.24.8", - "@babel/plugin-transform-flow-strip-types": "^7.25.2", - "@babel/plugin-transform-for-of": "^7.24.7", - "@babel/plugin-transform-function-name": "^7.25.1", - "@babel/plugin-transform-literals": "^7.25.2", - "@babel/plugin-transform-logical-assignment-operators": "^7.24.7", - "@babel/plugin-transform-modules-commonjs": "^7.24.8", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.24.7", - "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.7", - "@babel/plugin-transform-numeric-separator": "^7.24.7", - "@babel/plugin-transform-object-rest-spread": "^7.24.7", - "@babel/plugin-transform-optional-catch-binding": "^7.24.7", - "@babel/plugin-transform-optional-chaining": "^7.24.8", - "@babel/plugin-transform-parameters": "^7.24.7", - "@babel/plugin-transform-private-methods": "^7.24.7", - "@babel/plugin-transform-private-property-in-object": "^7.24.7", - "@babel/plugin-transform-react-display-name": "^7.24.7", - "@babel/plugin-transform-react-jsx": "^7.25.2", - "@babel/plugin-transform-react-jsx-self": "^7.24.7", - "@babel/plugin-transform-react-jsx-source": "^7.24.7", - "@babel/plugin-transform-regenerator": "^7.24.7", - "@babel/plugin-transform-runtime": "^7.24.7", - "@babel/plugin-transform-shorthand-properties": "^7.24.7", - "@babel/plugin-transform-spread": "^7.24.7", - "@babel/plugin-transform-sticky-regex": "^7.24.7", - "@babel/plugin-transform-typescript": "^7.25.2", - "@babel/plugin-transform-unicode-regex": "^7.24.7", - "@babel/template": "^7.25.0", - "@react-native/babel-plugin-codegen": "0.76.7", - "babel-plugin-syntax-hermes-parser": "^0.25.1", - "babel-plugin-transform-flow-enums": "^0.0.2", - "react-refresh": "^0.14.0" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@babel/core": "*" - } - }, - "node_modules/babel-preset-expo/node_modules/@react-native/codegen": { - "version": "0.76.7", - "resolved": "https://registry.npmjs.org/@react-native/codegen/-/codegen-0.76.7.tgz", - "integrity": "sha512-FAn585Ll65YvkSrKDyAcsdjHhhAGiMlSTUpHh0x7J5ntudUns+voYms0xMP+pEPt0XuLdjhD7zLIIlAWP407+g==", - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.25.3", - "glob": "^7.1.1", - "hermes-parser": "0.23.1", - "invariant": "^2.2.4", - "jscodeshift": "^0.14.0", - "mkdirp": "^0.5.1", - "nullthrows": "^1.1.1", - "yargs": "^17.6.2" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@babel/preset-env": "^7.1.6" - } - }, "node_modules/babel-preset-jest": { "version": "29.6.3", "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", @@ -8883,9 +8756,6 @@ } }, "node_modules/cross-spawn": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", - "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "version": "7.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", @@ -11883,15 +11753,12 @@ "devOptional": true, "license": "MIT", "dependencies": { - "call-bind-apply-helpers": "^1.0.2", "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", - "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", "get-proto": "^1.0.1", - "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", @@ -15426,15 +15293,6 @@ "node": ">=0.10.0" } }, - "node_modules/metro/node_modules/source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/metro/node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", @@ -16637,15 +16495,6 @@ "node": ">= 0.4" } }, - "node_modules/possible-typed-array-names": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", - "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, "node_modules/possible-typed-array-names": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", @@ -17814,13 +17663,6 @@ "dev": true, "license": "MIT" }, - "node_modules/safe-array-concat/node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true, - "license": "MIT" - }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -17865,13 +17707,6 @@ "dev": true, "license": "MIT" }, - "node_modules/safe-push-apply/node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true, - "license": "MIT" - }, "node_modules/safe-regex-test": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", @@ -20277,13 +20112,6 @@ "dev": true, "license": "MIT" }, - "node_modules/which-builtin-type/node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true, - "license": "MIT" - }, "node_modules/which-collection": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", diff --git a/client/src/SelectRoute.js b/client/src/SelectRoute.js index 59f4ac1..90431c8 100644 --- a/client/src/SelectRoute.js +++ b/client/src/SelectRoute.js @@ -16,6 +16,7 @@ export default function SelectRouteScreen({ navigation, route }) { const [errorMessage, setErrorMessage] = useState(''); const [polylineCoordinates, setPolylineCoordinates] = useState([]); const [currentRoute, setCurrentRoute] = useState(routeData.routes[0]); + // Get current location useEffect(() => { @@ -54,6 +55,29 @@ export default function SelectRouteScreen({ navigation, route }) { setPolylineCoordinates(decodedPath); }; + const getSustainabilityScore = (index) => { + let sustainabilityScore = { + "Bus": 0, + "Train": 0, + "WALKING": 0, + "Luas": 0, + "DRIVING": 0, + "BICYCLING": 0, + }; + routeData.routes[index].legs[0].steps.forEach((step) => { + let key = ''; + if (step.travel_mode === 'TRANSIT') { + key = step.html_instructions.split()[0] + } + else { + key = step.travel_mode; + } + sustainabilityScore[key] += step.distance.value/1000; + }) + + return sustainabilityScore; + } + return ( {errorMessage && ( diff --git a/server/src/sustainability.py b/server/src/sustainability.py index 4c6b947..ccdf6a2 100644 --- a/server/src/sustainability.py +++ b/server/src/sustainability.py @@ -1,6 +1,6 @@ from enum import Enum import logging -from fastapi import Query, HTTPException, APIRouter +from fastapi import Query, HTTPException, APIRouter, Body from dotenv import load_dotenv from .Database_class import DataBase @@ -101,7 +101,31 @@ async def get_sus_stats(user: str = Query(..., alias="sender")): "raw_distances": raw_distances, "friends_sus_scores": friends_sus_scores, } - + + + def api_update_sus_stats(self): + @self.app.post("/update_sus_stats") + async def update_sus_stats( + username: str = Body(..., alias="sender"), + flag: bool = Body(...), + modeDistances: dict = Body(...), + ): + journeyData = { + "username": username, + "bike": modeDistances["BICYCLING"], + "car": modeDistances["DRIVING"], + "luas": modeDistances["Luas"], + "train": modeDistances["Train"], + "bus": modeDistances["Bus"], + "walk": modeDistances["WALKING"], + } + if (flag): + self.db_update_monthly_distances(username, journeyData) + self.logger.info("Monthly distances updated") + + return self.calc_scores_from_route(username, journeyData) + + def db_fetch_month_sus_stats(self, user): table_name = "monthly_distance" db = DataBase() From d6a8ad2c70fe5801d6ff040cf025320c75bf7ac2 Mon Sep 17 00:00:00 2001 From: Ma-Golden <125670894+Ma-Golden@users.noreply.github.com> Date: Thu, 10 Apr 2025 17:07:05 +0100 Subject: [PATCH 05/14] fix:update monthly distances --- server/src/sustainability.py | 65 ++++++++++++++++++++---------------- 1 file changed, 36 insertions(+), 29 deletions(-) diff --git a/server/src/sustainability.py b/server/src/sustainability.py index ccdf6a2..11e6c19 100644 --- a/server/src/sustainability.py +++ b/server/src/sustainability.py @@ -166,38 +166,45 @@ def db_fetch_year_sus_stats(self, user): print("Year stats not found") return None - def db_update_monthly_distances(self, user, journey_data): - table_name = "monthly_distance" - db = DataBase() - db.connect_db() +def db_update_monthly_distances(self, user, journey_data): + table_name = "monthly_distance" + db = DataBase() + db.connect_db() + + # If user found + if db.search_user(table_name, user): + self.logger.info("Found user") + raw_distances = db.return_user_row(table_name, user) + self.logger.info(f"Raw distances: {raw_distances}") + + # Keep track of the updated total + updated_total = 0 + + # Update each transport mode in journey_data + for transport_mode in self.vehicle_types: + if transport_mode in journey_data: + # Add new distances to the existing ones + updated_distance = raw_distances[transport_mode] + journey_data[transport_mode] + db.update_entry(table_name, user, transport_mode, updated_distance) + self.logger.info(f"Updated {transport_mode} distance: {updated_distance}") + else: + # Keep the existing distance for modes not in current journey + updated_distance = raw_distances[transport_mode] + + # Add to the total regardless of whether it was updated + updated_total += updated_distance - # If user found - if db.search_user(table_name, user): - self.logger.info("Found user") - for transport_mode in journey_data: - if transport_mode not in self.vehicle_types: - self.logger.error( - f"Invalid transport mode: {transport_mode}" - ) - continue + # Update the total column + db.update_entry(table_name, user, "total", updated_total) + self.logger.info(f"Updated total distance: {updated_total}") - # Get distance for each transport mode - raw_distances = db.return_user_row(table_name, user) - self.logger.info(f"Raw distances: {raw_distances}") - # Add new distances to the existing ones - journey_data[transport_mode] += raw_distances[transport_mode] - self.logger.info(f"Updated distances: {journey_data[transport_mode]}") - # Update the database with new distances - db.update_entry( - table_name, user, transport_mode, journey_data[transport_mode] - ) - db.close_con() - return True + db.close_con() + return True - else: - db.close_con() - print("Monthly distances not found") - return False + else: + db.close_con() + self.logger.error("User not found in monthly distances table") + return False def db_fetch_raw_distances(self, user): From e997fa78f2c1e7f8dee3c96a972ee0af3e2f17e4 Mon Sep 17 00:00:00 2001 From: JasonBoutlas Date: Thu, 10 Apr 2025 18:54:38 +0100 Subject: [PATCH 06/14] wf and sust working together --- client/src/DisplayRoute.js | 6 +- client/src/SelectRoute.js | 222 +++++++++++++++++++++-------------- server/src/sustainability.py | 70 +++++------ 3 files changed, 171 insertions(+), 127 deletions(-) diff --git a/client/src/DisplayRoute.js b/client/src/DisplayRoute.js index c9e2246..5683a06 100644 --- a/client/src/DisplayRoute.js +++ b/client/src/DisplayRoute.js @@ -62,7 +62,11 @@ export default function DisplayRouteScreen({ navigation, route }) { }, [currentInstruction]); function removeHtmlTags(instruction) { - return instruction.replace(/<\/?[^>]+(>|$)/g, ''); + if(instruction) { + return instruction.replace(/<\/?[^>]+(>|$)/g, ''); + } else { + return instruction + } } // Creating a dictionary of step data for each step in the route diff --git a/client/src/SelectRoute.js b/client/src/SelectRoute.js index 90431c8..a6546c6 100644 --- a/client/src/SelectRoute.js +++ b/client/src/SelectRoute.js @@ -1,5 +1,5 @@ import React, { useEffect, useState } from 'react'; -import { View, Text, TouchableOpacity } from 'react-native'; +import { View, Text, TouchableOpacity, Platform } from 'react-native'; import MapView, { Polyline, Marker } from 'react-native-maps'; import { decodeRoute, @@ -8,15 +8,17 @@ import { } from './utils/mapUtils'; import locationCircleIcon from './assets/location-circle.png'; import selectRouteStyles from './components/styles/SelectRoute.styles'; +import { retrieveData } from './caching'; export default function SelectRouteScreen({ navigation, route }) { - const { origin, destination, routeData } = route.params; + const {origin, destination, routeData } = route.params; const [routes, setRoutes] = useState([]); const [location, setLocation] = useState(null); const [errorMessage, setErrorMessage] = useState(''); const [polylineCoordinates, setPolylineCoordinates] = useState([]); const [currentRoute, setCurrentRoute] = useState(routeData.routes[0]); - + const [scores, setScores] = useState([]); + // Get current location useEffect(() => { @@ -35,6 +37,16 @@ export default function SelectRouteScreen({ navigation, route }) { })(); }, [location]); + useEffect(() => { + for (let i = 0; i < routeData.routes.length; i++) { + setScores((prevScores) => [ + ...prevScores, + getSustainabilityScore(i, false), + ]); + print (`Sustainability score for route ${i}: ${scores[i]}`); + } + }, [routeData.routes]); + // Generate polyline // Decode and set polyline coordinates useEffect(() => { @@ -55,108 +67,142 @@ export default function SelectRouteScreen({ navigation, route }) { setPolylineCoordinates(decodedPath); }; - const getSustainabilityScore = (index) => { + const getSustainabilityScore = async (index, startRouteFlag) => { let sustainabilityScore = { "Bus": 0, "Train": 0, "WALKING": 0, - "Luas": 0, + "Tram": 0, "DRIVING": 0, "BICYCLING": 0, }; routeData.routes[index].legs[0].steps.forEach((step) => { let key = ''; if (step.travel_mode === 'TRANSIT') { - key = step.html_instructions.split()[0] + key = step.html_instructions.trim().split(' ')[0] + console.log("key: ", key); } else { key = step.travel_mode; } - sustainabilityScore[key] += step.distance.value/1000; + sustainabilityScore[key] += step.distance.value / 1000; + }) + console.log("sustainability score: ", sustainabilityScore); + const transportScore = await sendSustainabilityScore(startRouteFlag, sustainabilityScore); + return transportScore; + } + + const sendSustainabilityScore = async (startRouteFlag, sustainabilityScore) => { + try { + const baseUrl = + Platform.OS === 'web' + ? 'http://localhost:8000' + : process.env.EXPO_PUBLIC_API_URL; + console.log(`Sending request to ${baseUrl}/update_sus_stats`); + + const response = await fetch(`${baseUrl}/update_sus_stats`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + username: await retrieveData('username'), + flag: startRouteFlag , + modeDistances: sustainabilityScore, + }), + }); + + let data = await response.json(); + console.log("response (transport score): ", data); + return data; + } catch (error) { + console.log('Error sending sustainability scores and distances:', error); + }; + } + + const startJourney = (index, routeOption) => { + getSustainabilityScore(index, true); + navigation.navigate('DisplayRouteScreen', { + origin, + destination, + routeData: routeOption, + polylineCoordinates, }) - - return sustainabilityScore; } - return ( - - {errorMessage && ( - {errorMessage} - )} - {!errorMessage && location && ( - <> - 0 - ? routes[0].legs[0].start_location.lat - : location.latitude, - longitude: - routes.length > 0 - ? routes[0].legs[0].start_location.lng - : location.longitude, - latitudeDelta: 0.01, - longitudeDelta: 0.01, - }} - > - - {polylineCoordinates.length > 0 && ( + return ( + + {errorMessage && ( + {errorMessage} + )} + {!errorMessage && location && ( + <> + 0 + ? routes[0].legs[0].start_location.lat + : location.latitude, + longitude: + routes.length > 0 + ? routes[0].legs[0].start_location.lng + : location.longitude, + latitudeDelta: 0.01, + longitudeDelta: 0.01, + }} + > - )} - {polylineCoordinates.length > 0 && ( - - )} - - - {routes.map((routeOption, index) => ( - - displaySelectedRoute(index)} - style={selectRouteStyles.routeButton} - > - Route {index + 1} - Distance: {routeOption.legs[0].distance.text} - Duration: {routeOption.legs[0].duration.text} - - {/* routeData needs to rename the route variable because that is what react navigator calls its properties */} - - navigation.navigate('DisplayRouteScreen', { - origin, - destination, - routeData: routeOption, - polylineCoordinates, - }) - } - style={selectRouteStyles.startButton} + {polylineCoordinates.length > 0 && ( + + )} + {polylineCoordinates.length > 0 && ( + + )} + + + {routes.map((routeOption, index) => ( + - Start Journey - - - ))} - - - )} - {!errorMessage && !location && ( - Loading... - )} - - ); -} + displaySelectedRoute(index)} + style={selectRouteStyles.routeButton} + > + Route {index + 1} + Distance: {routeOption.legs[0].distance.text} + Duration: {routeOption.legs[0].duration.text} + Sustainability score: {scores[index]} + + {/* routeData needs to rename the route variable because that is what react navigator calls its properties */} + {startJourney(index, routeOption)}} + style={selectRouteStyles.startButton} + > + Start Journey + + + ))} + + + )} + {!errorMessage && !location && ( + Loading... + )} + + ); + } diff --git a/server/src/sustainability.py b/server/src/sustainability.py index 11e6c19..6f431fd 100644 --- a/server/src/sustainability.py +++ b/server/src/sustainability.py @@ -26,6 +26,7 @@ def __init__(self, api, logger: logging.Logger): load_dotenv() # Register Endpoints self.api_get_sus_stats() + self.api_update_sus_stats() def db_initialise_sustainability(self, username): db = DataBase() @@ -106,15 +107,14 @@ async def get_sus_stats(user: str = Query(..., alias="sender")): def api_update_sus_stats(self): @self.app.post("/update_sus_stats") async def update_sus_stats( - username: str = Body(..., alias="sender"), + username: str = Body(...), flag: bool = Body(...), modeDistances: dict = Body(...), ): journeyData = { - "username": username, "bike": modeDistances["BICYCLING"], "car": modeDistances["DRIVING"], - "luas": modeDistances["Luas"], + "luas": modeDistances["Tram"], "train": modeDistances["Train"], "bus": modeDistances["Bus"], "walk": modeDistances["WALKING"], @@ -123,6 +123,7 @@ async def update_sus_stats( self.db_update_monthly_distances(username, journeyData) self.logger.info("Monthly distances updated") + journeyData.pop('car', None) return self.calc_scores_from_route(username, journeyData) @@ -166,45 +167,38 @@ def db_fetch_year_sus_stats(self, user): print("Year stats not found") return None -def db_update_monthly_distances(self, user, journey_data): - table_name = "monthly_distance" - db = DataBase() - db.connect_db() - - # If user found - if db.search_user(table_name, user): - self.logger.info("Found user") - raw_distances = db.return_user_row(table_name, user) - self.logger.info(f"Raw distances: {raw_distances}") + def db_update_monthly_distances(self, user, journey_data): + table_name = "monthly_distance" + db = DataBase() + db.connect_db() - # Keep track of the updated total - updated_total = 0 + # If user found + if db.search_user(table_name, user): + self.logger.info("Found user") + for transport_mode in journey_data: + if transport_mode not in self.vehicle_types: + self.logger.error( + f"Invalid transport mode: {transport_mode}" + ) + continue - # Update each transport mode in journey_data - for transport_mode in self.vehicle_types: - if transport_mode in journey_data: + # Get distance for each transport mode + raw_distances = db.return_user_row(table_name, user) + self.logger.info(f"Raw distances: {raw_distances}") # Add new distances to the existing ones - updated_distance = raw_distances[transport_mode] + journey_data[transport_mode] - db.update_entry(table_name, user, transport_mode, updated_distance) - self.logger.info(f"Updated {transport_mode} distance: {updated_distance}") - else: - # Keep the existing distance for modes not in current journey - updated_distance = raw_distances[transport_mode] - - # Add to the total regardless of whether it was updated - updated_total += updated_distance - - # Update the total column - db.update_entry(table_name, user, "total", updated_total) - self.logger.info(f"Updated total distance: {updated_total}") - - db.close_con() - return True + journey_data[transport_mode] += raw_distances[transport_mode] + self.logger.info(f"Updated distances: {journey_data[transport_mode]}") + # Update the database with new distances + db.update_entry( + table_name, user, transport_mode, journey_data[transport_mode] + ) + db.close_con() + return True - else: - db.close_con() - self.logger.error("User not found in monthly distances table") - return False + else: + db.close_con() + print("Monthly distances not found") + return False def db_fetch_raw_distances(self, user): From ae8c627350edcb954eb60cfd66233934966c05fe Mon Sep 17 00:00:00 2001 From: Ma-Golden <125670894+Ma-Golden@users.noreply.github.com> Date: Thu, 10 Apr 2025 18:58:29 +0100 Subject: [PATCH 07/14] deleted unused files --- server/src/(legacy) main.py | 83 -------------------------------- server/src/bus_api.py | 26 ---------- server/src/luas_api.py | 77 ----------------------------- server/src/preferences_legacy.py | 59 ----------------------- server/src/sample_luas_api.py | 18 ------- 5 files changed, 263 deletions(-) delete mode 100644 server/src/(legacy) main.py delete mode 100644 server/src/bus_api.py delete mode 100644 server/src/luas_api.py delete mode 100644 server/src/preferences_legacy.py delete mode 100644 server/src/sample_luas_api.py diff --git a/server/src/(legacy) main.py b/server/src/(legacy) main.py deleted file mode 100644 index a6a4ff2..0000000 --- a/server/src/(legacy) main.py +++ /dev/null @@ -1,83 +0,0 @@ -from fastapi import FastAPI, Request -from fastapi.middleware.cors import CORSMiddleware -from pydantic import BaseModel -import logging -import uvicorn -import sys - -# Configure logging -logging.basicConfig( - level=logging.INFO, - format="%(asctime)s - %(levelname)s - %(message)s", - handlers=[logging.StreamHandler(sys.stdout)], -) -logger = logging.getLogger(__name__) - - -class Message(BaseModel): - text: str - - -class Login(BaseModel): - username: str - password: str - - -app = FastAPI() - -# Configure CORS with logging -origins = ["*"] # In production, replace with actual frontend URL -app.add_middleware( - CORSMiddleware, - allow_origins=origins, - allow_credentials=True, - allow_methods=["*"], - allow_headers=["*"], -) - - -@app.middleware("http") -async def log_requests(request: Request, call_next): - logger.info(f"Incoming {request.method} request to {request.url}") - response = await call_next(request) - logger.info(f"Returning response with status code: {response.status_code}") - return response - - -@app.get("/") -async def root(): - logger.info("Root endpoint accessed") - return {"message": "Hello World"} - - -@app.post("/echo") -async def echo_message(message: Message): - logger.info(f"Received message in echo endpoint: {message.text}") - try: - return {"message": f"'{message.text}' sent from server"} - except Exception as e: - logger.error(f"Error processing message: {str(e)}") - raise - - -@app.post("/login") -async def login_data(login: Login): - logger.info( - f"Received message in login endpoint: " - f"{login.username} {login.password}" - ) - try: - return { - "login details": f"'username={login.username}' " - f"'password={login.password}'sent from server" - } - except Exception as e: - logger.error(f"Error processing message: {str(e)}") - raise - - -if __name__ == "__main__": - logger.info("Starting FastAPI server...") - uvicorn.run( - app, host="10.6.124.10", port=8000, log_level="debug" - ) # changing host to Keith ipv4 address diff --git a/server/src/bus_api.py b/server/src/bus_api.py deleted file mode 100644 index fea2abe..0000000 --- a/server/src/bus_api.py +++ /dev/null @@ -1,26 +0,0 @@ -"""Python 3.2""" - -import urllib.request -import json - -try: - url = "https://api.nationaltransport.ie/gtfsr/v2/gtfsr?format=json" - - hdr = { - # Request headers - "Cache-Control": "no-cache", - "x-api-key": "704561a2a3964364bf1955be3e3ab53f", - } - - req = urllib.request.Request(url, headers=hdr) - - req.get_method = lambda: "GET" - response = urllib.request.urlopen(req) - print(response.getcode()) - # print(json.loads(response.read().decode())) - with open("data.json", "w") as f: - json.dump(json.loads(response.read().decode()), f) - # filetest.close() -except Exception as e: - print(e) -#################################### diff --git a/server/src/luas_api.py b/server/src/luas_api.py deleted file mode 100644 index 01bf48f..0000000 --- a/server/src/luas_api.py +++ /dev/null @@ -1,77 +0,0 @@ -import requests -import xml.etree.ElementTree as ET - - -class luasAPI: - - def __init__(self): - self.poll_interval = 10 - - def get(self, stop): - # URL of Open Data - self.stop = stop - self.url = f"http://luasforecasts.rpa.ie/xml/get.ashx?action=forecast&stop={self.stop}&encrypt=false" # noqa: E501 - - # while True: - # # Fetch the geoJSON data from the URL - # response = requests.get(url) - - # # Check if the request was successful - # if response.status_code == 200: - # for item in response.json(): - # print( - # item["name"], - # " ", - # item["available_bikes"], - # (int(item["last_update"])), - # ) - - # else: - # print("Failed to retrieve data:", response.status_code) - - # time.sleep(self.poll_interval) - - # fetch the real-time Luas data from the URL - self.response = requests.get(self.url) - - # check if the request was succesful - if self.response.status_code == 200: - - # parse xml content - root = ET.fromstring(self.response.content) - - # initialise dictionaries to store tram info by direction - tram_info = {"Inbound": [], "Outbound": []} - - # iterate through each direction - for direction in root.findall("direction"): - direction_name = direction.get("name") - for tram in direction.findall("tram"): - due_mins = tram.get("dueMins") - destination = tram.get("destination") - tram_info[direction_name].append( - {"dueMins": due_mins, "destination": destination} - ) - - # print the extracted tram information - print("Inbound Trams:", tram_info["Inbound"]) - print("Outbound Trams:", tram_info["Outbound"], "\n") - - else: - print("Failed to retrieve data:", self.response.status_code) - - # time.sleep(self.poll_interval) - - -if __name__ == "__main__": - luas = luasAPI() - while True: - stop = str( - input( - "Enter stop code to see live arrivals and departures," - ' or "exit" to leave: ' - ) - ) - if stop == "exit": - break - luas.get(stop) diff --git a/server/src/preferences_legacy.py b/server/src/preferences_legacy.py deleted file mode 100644 index 8718244..0000000 --- a/server/src/preferences_legacy.py +++ /dev/null @@ -1,59 +0,0 @@ -from src.Database_class import DataBase - - -class UserPersonalizedSettings: - - def __init__( - self, - walkspeed=0, - travelMode={ - "bus": False, - "car": False, - "train": False, - "walk": False, - "bike": False, - "tram": False, - }, - bike=False, - privateVehicle=False, - accessibility=None, - motorways=False, - tolls=False, - ): - - self.walkingSpeed = walkspeed - self.travelMode = travelMode - self.bike = bike - self.privateVehicle = privateVehicle - self.accessibility = accessibility - self.motorways = motorways - self.tolls = tolls - self.database = DataBase() - self.tablename = "personalisedSettings" - - def writePersonlisedSettings(self, username): - # TODO check if user info is in the database - """Writes personalise components. If no user data used add_entry - if user exists use update_entry. - - Args: - username (_type_): _description_ - """ - self.database.connect_db() - - databaseDict = { - "Username": username, - "WalkingSpeed": self.walkingSpeed, - "TravelMode": self.travelMode, - "Bike": self.bike, - "PrivateVehicle": self.privateVehicle, - "Accessibility": self.accessibility, - "Motorways": self.motorways, - "Toll": self.tolls, - } - - self.database.add_entry(self.tablename, databaseDict) - - self.database.close_con() - - return diff --git a/server/src/sample_luas_api.py b/server/src/sample_luas_api.py deleted file mode 100644 index 3cef997..0000000 --- a/server/src/sample_luas_api.py +++ /dev/null @@ -1,18 +0,0 @@ -from base_api import BaseAPI - - -class LuasAPI(BaseAPI): - def __init__(self): - super().__init__() - - def get(self): - return "LuasAPI" - - -def main(): - x = LuasAPI() - x.get() - - -if __name__ == "__main__": - main() From de511627d2c0d9e958fc186ca170389fa4b1cc04 Mon Sep 17 00:00:00 2001 From: Ma-Golden <125670894+Ma-Golden@users.noreply.github.com> Date: Thu, 10 Apr 2025 19:18:55 +0100 Subject: [PATCH 08/14] updating sus score for user --- server/src/sustainability.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/server/src/sustainability.py b/server/src/sustainability.py index 6f431fd..1b1d97b 100644 --- a/server/src/sustainability.py +++ b/server/src/sustainability.py @@ -122,6 +122,7 @@ async def update_sus_stats( if (flag): self.db_update_monthly_distances(username, journeyData) self.logger.info("Monthly distances updated") + self.update_user_sus_score(username) journeyData.pop('car', None) return self.calc_scores_from_route(username, journeyData) @@ -338,6 +339,28 @@ def calc_scores_from_route(self, user, journey_data): print("Monthly distances not found") return 0 + + def update_user_sus_score(self, user: str) -> float: + db = DataBase() + db.connect_db() + + monthly_data = db.return_user_row("monthly_distance", user) + if not monthly_data: + self.logger.warning(f"No monthly distance data found for {user}") + db.close_con() + return 0 + + emissions_savings = self.calc_emissions_savings(monthly_data) + total_score = 0 + for mode in emissions_savings: + total_score += self.calc_scores(emissions_savings[mode]) + + db.update_entry("user_table", user, "sus_score", total_score) + self.logger.info(f"Updated sustainability score for {user}: {total_score}") + db.close_con() + return total_score + + def calc_emissions_savings(self, monthly_distances): emissions_dif = { "bike": 0, From 33b3cfd4a48250a6f6a7cde1d6bebfff0e176486 Mon Sep 17 00:00:00 2001 From: FEguare <123463013+FEguare@users.noreply.github.com> Date: Fri, 11 Apr 2025 09:52:21 +0100 Subject: [PATCH 09/14] sustainability dashboard to 2 and 0 decimal places --- client/src/SustainabilityDashboard.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/client/src/SustainabilityDashboard.js b/client/src/SustainabilityDashboard.js index 3e8c825..5e7592c 100644 --- a/client/src/SustainabilityDashboard.js +++ b/client/src/SustainabilityDashboard.js @@ -95,7 +95,7 @@ const configurePieChartData = (emissionsSavings) => { // Map emissions savings JSON to PieChart data return Object.keys(emissionsSavings).map((key) => ({ name: key.charAt(0).toUpperCase() + key.slice(1), - emissions: emissionsSavings[key], + emissions: Math.round(emissionsSavings[key]), color: colors[key] || '#cccccc', // default color legendFontColor: '#7F7F7F', legendFontSize: 15, @@ -257,37 +257,37 @@ export default function Dashboard() { type: 'bike', label: 'Distance traveled by Bike', value: rawDistances.bike || 0, - total: 100, + total: Math.max(100, Math.ceil(rawDistances.bike / 100) * 100), }, { type: 'walk', label: 'Distance traveled by Walking', value: rawDistances.walk || 0, - total: 100, + total: Math.max(100, Math.ceil(rawDistances.walk / 100) * 100), }, { type: 'bus', label: 'Distance traveled by Bus', value: rawDistances.bus || 0, - total: 100, + total: Math.max(100, Math.ceil(rawDistances.bus / 100) * 100), }, { type: 'car', label: 'Distance traveled by Car', value: rawDistances.car || 0, - total: 100, + total: Math.max(100, Math.ceil(rawDistances.car / 100) * 100), }, { type: 'train', label: 'Distance traveled by Train', value: rawDistances.train || 0, - total: 100, + total: Math.max(100, Math.ceil(rawDistances.train / 100) * 100), }, { type: 'luas', label: 'Distance traveled by Luas', value: rawDistances.luas || 0, - total: 100, + total: Math.max(100, Math.ceil(rawDistances.luas / 100) * 100), }, ]; @@ -490,7 +490,7 @@ export default function Dashboard() { {item.label} - {item.ratio}/{item.total} + {item.ratio.toFixed(2)}/{item.total} Date: Fri, 11 Apr 2025 15:11:33 +0100 Subject: [PATCH 10/14] great changes that always work, great work everybody --- client/src/Map.js | 39 ++++++++++++++++++++++----------------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/client/src/Map.js b/client/src/Map.js index 5225edc..3c571aa 100644 --- a/client/src/Map.js +++ b/client/src/Map.js @@ -32,6 +32,7 @@ export default function MapScreen({ navigation }) { const [temperature, setTemperature] = useState(null); const [errorMessage, setErrorMessage] = useState(''); const mapRef = useRef(null); + const [pollingFlag, setPollingFlag] = useState(false); const pollIncident = async () => { try { @@ -83,7 +84,7 @@ export default function MapScreen({ navigation }) { } }; - const fetchWeather = async () => { + const fetchWeather = async (initialLocation) => { try { const baseUrl = Platform.OS === 'web' @@ -91,11 +92,11 @@ export default function MapScreen({ navigation }) { : process.env.EXPO_PUBLIC_API_URL; console.log( - `Sending request to ${baseUrl}/weather?longitude=${location.longitude}&latitude=${location.latitude}`, + `Sending request to ${baseUrl}/weather?longitude=${initialLocation.longitude}&latitude=${initialLocation.latitude}`, ); const response = await fetch( - `${baseUrl}/weather?longitude=${location.longitude}&latitude=${location.latitude}`, + `${baseUrl}/weather?longitude=${initialLocation.longitude}&latitude=${initialLocation.latitude}`, { method: 'GET', headers: { @@ -123,7 +124,7 @@ export default function MapScreen({ navigation }) { } }; - const fetchBikeApi = async () => { + const fetchBikeApi = async (initialLocation) => { try { const baseUrl = Platform.OS === 'web' @@ -131,11 +132,11 @@ export default function MapScreen({ navigation }) { : process.env.EXPO_PUBLIC_API_URL; console.log( - `Sending request to ${baseUrl}/BikeStand?longitude=${location.longitude}&latitude=${location.latitude}`, + `Sending request to ${baseUrl}/BikeStand?longitude=${initialLocation.longitude}&latitude=${initialLocation.latitude}`, ); const response = await fetch( - `${baseUrl}/BikeStand?longitude=${location.longitude}&latitude=${location.latitude}`, + `${baseUrl}/BikeStand?longitude=${initialLocation.longitude}&latitude=${initialLocation.latitude}`, { method: 'GET', headers: { @@ -169,6 +170,11 @@ export default function MapScreen({ navigation }) { try { const initialLocation = await getCurrentLocation(); setLocation(initialLocation); + //weatherBikePollIncident(initialLocation); + + fetchWeather(initialLocation); + fetchBikeApi(initialLocation); + pollIncident(); const locationSubscription = await startLocationTracking(setLocation); @@ -181,18 +187,17 @@ export default function MapScreen({ navigation }) { fetchLocation(); }, []); - useEffect(() => { - const pollOnce = async () => { - if (location) { - fetchWeather(); - fetchBikeApi(); - pollIncident(); - } - }; + const weatherBikePollIncident = async (initialLocation) => { + //await new Promise((resolve) => setTimeout(resolve, 15000)); + console.log("initial location: ", initialLocation) + if(initialLocation && location){ + fetchWeather(initialLocation); + fetchBikeApi(initialLocation); + pollIncident(); + } + } - pollOnce(); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [location]); // Empty dependency array ensures this runs only once when the component mounts + const renderContent = () => { if (errorMessage) { From 720d0a6781aece92eea2d8f1ae5bcead7c66d5dd Mon Sep 17 00:00:00 2001 From: Conor Powderly Date: Fri, 11 Apr 2025 15:35:47 +0100 Subject: [PATCH 11/14] Sustainable UI --- client/src/SustainabilityDashboard.js | 16 ++++++++++++++++ .../SustainablityDashboard/LuasBronze.png | Bin 0 -> 39991 bytes .../assets/SustainablityDashboard/LuasGold.png | Bin 0 -> 40996 bytes .../SustainablityDashboard/LuasSilver.png | Bin 0 -> 39890 bytes .../SustainablityDashboard/walkBronze.png | Bin 0 -> 45114 bytes .../assets/SustainablityDashboard/walkGold.png | Bin 0 -> 46440 bytes .../SustainablityDashboard/walkSilver.png | Bin 0 -> 44565 bytes 7 files changed, 16 insertions(+) create mode 100644 client/src/assets/SustainablityDashboard/LuasBronze.png create mode 100644 client/src/assets/SustainablityDashboard/LuasGold.png create mode 100644 client/src/assets/SustainablityDashboard/LuasSilver.png create mode 100644 client/src/assets/SustainablityDashboard/walkBronze.png create mode 100644 client/src/assets/SustainablityDashboard/walkGold.png create mode 100644 client/src/assets/SustainablityDashboard/walkSilver.png diff --git a/client/src/SustainabilityDashboard.js b/client/src/SustainabilityDashboard.js index 5e7592c..1564b37 100644 --- a/client/src/SustainabilityDashboard.js +++ b/client/src/SustainabilityDashboard.js @@ -28,6 +28,12 @@ import bronzeBus from './assets/SustainablityDashboard/BusBronze.png'; import goldTrain from './assets/SustainablityDashboard/GoldTrain.png'; import silverTrain from './assets/SustainablityDashboard/SilverTrain.png'; import bronzeTrain from './assets/SustainablityDashboard/BronzeTrain.png'; +import goldWalk from './assets/SustainablityDashboard/walkGold.png'; +import silverWalk from './assets/SustainablityDashboard/walkSilver.png'; +import bronzeWalk from './assets/SustainablityDashboard/walkBronze.png'; +import goldLuas from './assets/SustainablityDashboard/LuasGold.png'; +import silverLuas from './assets/SustainablityDashboard/LuasSilver.png'; +import bronzeLuas from './assets/SustainablityDashboard/LuasBronze.png'; // Define thresholds for medals const MEDAL_THRESHOLDS = { @@ -59,6 +65,16 @@ const getMedalImage = (value, vehicleType) => { silver: silverCar, bronze: bronzeCar, }, + walk: { + gold: goldWalk, + silver: silverWalk, + bronze: bronzeWalk, + }, + luas: { + gold: goldLuas, + silver: silverLuas, + bronze: bronzeLuas, + }, // Add default images for other vehicle types default: { gold: goldCar, diff --git a/client/src/assets/SustainablityDashboard/LuasBronze.png b/client/src/assets/SustainablityDashboard/LuasBronze.png new file mode 100644 index 0000000000000000000000000000000000000000..3316b4bd0767f68fa9e07a1e5108fb9e140b5ddf GIT binary patch literal 39991 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 literal 0 HcmV?d00001 diff --git a/client/src/assets/SustainablityDashboard/LuasSilver.png b/client/src/assets/SustainablityDashboard/LuasSilver.png new file mode 100644 index 0000000000000000000000000000000000000000..3503045302083e53aae4126373d0373691c7384a GIT binary patch literal 39890 zcmYhjc|6qL_XqwWiX_S&5)oM=NtPj^H?o#}jbz`q>>X`f7P<>MSK*N~QIWppad-$bV?D5HO>-(=lEG(m;Lqf&&$VXvC2ue*p`@Q>& z64q(=I+ja1XG*>vGqp1=UfealpEKbU?uV+<3nX1?0>!MFR!BE+lE=-e9fEj88KYv^UH2xqBiN`orOR{}b>tT?{U-=;_*h&Z3#4(Ui5r5L_3p{< zJzKZ9V?U18Va#*pn78VXU)ZR3S0hU0fcGidRc`R(kceY9q|C}rKuY>sRd7IS7l0Jh z1u-A0F2uDXdmDdL2lN~!&10Ga)%9PKK!ex)h@n^C^fu&wK6rdw&^%Q1w{dfGKHXOa z$4>^?!=D;h-eQsN#yeLXPAzU-w~j+@dfV?LlVw1}^1CF^i$&!wDeAFDyLhc@vn)4* z#Ne;gd~-z*WJy%Zamb3fNZYIbO&AuQg?Qz_dT|>U)4wkf=hPIfF6B`rgmrr*glW=W zAzHf(>lLbdSaTHcO&i&^=rBCJdi^321g8<+il<;Wh*0y)6P`<1$Sx-p5*I}(5Ri+>Pj ztoe#3sE`^#bj>-!P9t`vd_rH~Y!DS$8iWG+2!e#wC{j5BFIznzDu6HhQjerlzT*t{ zjw5kS&qm~2ckjcUas49FpmZ`M)MXw#Wj#D5Mg5XS_I5yz)SJ4gtC~WmO~Qh9-_`|Bh*(W{HWe`4I=rz#-8gnG`l{KnpFGFTK9%B1UU11hg-1dy9qD zc6{ov)Ac6Q#o76qSU>?>J?z5k^fUg5)?d@tAohc@zk?Ml!-6ETcYuIq!_zGIsp)fg zaiYmms)YA{>Yj2ktT6+l^FJ-1hs3tIm5PU>DRyBUP#O&D`0}*a5}6rtCxmr*p(u#H zA;779_9cbenSZ~2a;Shbl98fRUmt>xoF(Cpo&hHv#7o|rcO{nf4~X70=rQaJC0^n1 zBbIHZx4K8gRr}4593lyueGv2=h@(N&=}H{*nCxp%F!--;!Hv$FT7-sQEe4P?6+5jn z8IVh?T<@BDj(7Ga-+M$2{vjF-L_mLfz2@cH6?)f5pgN8aVtSyxN&4WaIaxy2FJgAc z`kWk(84>tyQHkqayq&NC1>~SWMtbD|Ff?66*PiWqaJK0qsG#D_wad|c-=;-W`=bl6-oIS{QZ}d;3DN`ztR-(wrgea$Q;%1w5d;h`{|~j zxp{LaCR5Xui=@S+T>DG;(=GjGsV|)r?`QO$-zm6k)O|HDdvA+B=^Ux!{aupD+Gf_| zVo{kvrMU+d;rwx%_cWBX^#33O0-1_ppNfQUTJBK0b&F)&h<3l3qj=Zj8PQ$8EP8(M*; zIgvgZwW*7WE-#rugubw{tl6eQ*}a^IB`V`N4}?y!A~@^Q5;T}vk=3zEa+U7Jw5?jS z*mM3f*2iv&zE4~02mEderdKwc2R`WJoJE7<-H^-TkHLqwl|Ip@=Z(;EVc}Dn_Evjq zPW)U&L6cwLI7*fFW;l7K^$+y~ulo}qJe*0VXo3i2$$EpXCF-%Wyx~TcHqYAH*>6W# zC_ZDiVNzzWQejATOg$S|>`j(Q5k3hNEgsSJHj&o*YbnoXd{uawM#`*m^lncjfAS-H zi*crROk)Z$2fEZ0a7p=_02a<}efNw4&d`r!onhsNAKw6Fwbs z@n&9w90$p}HS&g=z@0S+U3){0T;DSJRp|5sa?`=}gP$i*i$0yGxn0eOo4s&TOrC+Z z5d@cWlbN{B&G~m^$&EKl4||z9r1&_Qnq4wPRb@Oxy-ld_0=z=2WuOT9OYw5fHcd56oIP?{%>Di)TA)%sfIu`#4>{aX zBd#H0?XI)>S*}&yVo@;}N&OG>(l{+2F_;2L?gO;4?lTWwW>%6JDkAMS^c1ryi~L4D zdM%tjB4XNloSk&;6$b>|`rYKn=j}GD;Y{HXp776{tug&Mc>ePscziO$^Pc`V(?#!N+$;f;wJ#BQpF-H<(xp$ zHahQV7OC%k*Uhr*QOoD>wEt|Pd6XV}Xc?G`adiphg zt14Q1o8hq}H7nkY_AymO8zNt_wEO!?1mV%gxKIcKG@SFht*R5gRia_a*ze~Ah5ON; zvvRfQNr}`r-kimo!W5-qnIp&;IPep5mm_ zAh=P4;{`CW8F$j+X8Xo?$FO~teXLT#``#?20#Q|cdXjS4&l%x*I(^UiufIYAw?UPP z5AGR^4$jw<^2cCHg*u(GejQ%mo++1AQ7AD-{Y4E=NQ2{J!11c!czgR>EVcAI9un^w z$j!8AJLIjCZpGq60tfsq?9?vH1$lrq1rEaIzMLzI?mZqa-Es#P^Kes2+(EN@UCqX6 z)@NFrrzim+8M=6cV|3!q3Sga0VmM2-cYG*y&o+2#7QAt^PW(p6&3z~a^~0zu5(ln#`rsU{m>>p}A$1JVj6))MjO)GXR6#;uAcX4`0?#dPKo zfOS`8)qxF-K-zNt1$;Pl?~Q<=J*!4+=JQYS&wF#*Tx%PufTFkelM{H)ba@&LPuEVs zy8h{Tseu>Bs1987>)*ytmkc9f@#5LNxf}fTN32Dc6h5vj?KHb7LYVOB-CjMx8bUTe zXVwuxVm)BZE^t(l_nhBTOza1T+d2n#B5}kyEZ3{*_RBKPbiQmN4N(U?Ayh8#oAJY( zNa41uGP~l3!}K#KXn~$PH%+v{`0T*WeFD^WPeTugPTVZVjtS=d1)NQUDgGWjPK_0wpH%}8cb&vv@@L!KttO|MC zAwPbb+3xP8R@g$|BF@CjKx-TvqETz)Pg#=xhHLNYa7YB8YA@-(;)X9+L}tz8KJT@0Fti(Nt`vaS zN>~T=19vvNYjsf(vcB-4sW|=mQvN%v>Y|AQmaO10d;`OxVXt-r8e zmcpw7+tanWpNGm-K6}z~zg-r&)vC>(11fK)GkzQj(^_($4*RzlU37PhJvJYTq; zP0dWxb7^~S^zcxhpjv6v{7M-_2^J8kxP)`+)yZ`2S-0N_wG70OjfJ=vLSM~p7u~L; zpp5}gnxf|}Iq~0qqo;twjQpID`6#`twK&xR2{8{ZNTgD?7^5x%?IKWyO1}KXD)DMr zYW79O=YT88wRmeRBCHXw4uFc+7^Y~PM}b=k%u}Hjttr^#vwr~1{ij9S94<~}i(3Vz z@Op+JgP9pj`=keJaC^U9Zx&A4&3(?`2`{f7v>2s_=+ij0fAbWnl4#h6f`!%q2>=P> zryGgKesy~bB(J=hUa50QwnVszdy=|HBUg=CE}N4}so+Q&n0?Z2DBO;Yh?W^#D@u=_ z&WEo$SrXjbIO%=u#pKIC=5OSvX#;tvc|^RBQrxWM$sF5*wNWLpWSh-6DhV0M9mES| zEi{h(1#v?{8;7oN;;$FZ4m$0JEL;|hXMbIWp0J10G$%(bi^$1A&APzn&boNv9otI#{+Oo? zyW3(uk7U^7)gsiRp;TM<`^;O#phRiCr{M<*3sFF0S(SaRx7goB)reV&T*V1y>S)r= zcLtaO9Yb4_{MPA1uOft~5ib)2TI~N>ACX}6sHQ&O&Di&-NDC-4)kL#ET$QfbXuk_0 z<`D!cy<`5{(|3=*w|P$?Uu&Qf}}mIArNfnx1BM z`WvAJkLy8lpeoC0o-VaS4Lde4rmyc+_P2-By$0X^2Es3#rtackBm}sRMrQL~rx!To zI(zbBP2Q)hh1-r4(0~h<%Jt*FpqgB@X8@TEDXRdW=4A#NEOht^7V<_}EU&^)1L=N? z%yDGnWR(I4+vmytEf~w6N(|z@A|sHx(M`Zof5CoJ(~1rIiZUg-Z`Ff51)9A4IPdp! z5pQwdb5}e~doay%iX?A3xxWQBe_8&RvC1De9jdXiX!H>MDR0oCh5|C8Yc82q8}wvy z*t*|C_&>s&05BBw;|^~kx&IGOI^brL?<;W@%#PB>1$$&GSQN#5H!@@ceWjwMKM-Mh zNh&A*v13{Npl~x;z7trP>3qZ9__6#q5fRhwjdZ7O&T6 zOtv=9Jhf5kIYM0c*?Tp-I4h^a%Zs&Kv%6Fp!z8Od4SC+Z?1L0+T zT`rcpvWZRvsXz|wU`aE_i#i&-WPRRG*JNaJnT9nbyo#}ss$9#cu}90Og1A7BpWa94 z6}}=;_zKc=Zf5R!qZ_3Q3yl=fHR@UWyiy*ZDSE7^6G^Hi&^_Rn5`BjhtP!C_AF(3u zjzxOhMJkNL?{4oKe z#i!-7KDB~)aDuGm$9&Epo!Kx@@U;O&U$jD85~ZgY<40Ob$Y8FyJMt)*FRzx2(L-|d z3MJEmG`HyX68{xmB%Tj zk!E&20!u&8M}&?m``BaX2fLO>DRB-&kZuXNmzSmH;o~IE6IQUQC0?Dx>XZ+!bG|5= zw8yVRhb*I@AR&02OZ4HOe(aGU&ch58WF(d)-P>$G%)hFDbU!Bq5Whh`c}!k@DS%wnemgt|1jQHGXF!?O%M%1658ESl;h zd*)N`bzFs+zdNE^IU@hb_}gYVx&>uy?EU(jgDS7_poqT!l*&( ztB)`M#vBSFcVDmis`PU^t4bsq*_RMgwF+y8jh?K6Kds^s$A_AvID&22;OgmOO0YPB zfV@o9ryrvJ!VY9H#tRQuAFO>AR-7SF!2bOkr8uUR$I0$Z3@s=?W8>3@*`idb4?Xi6 zwZS)Rz&E=5(w8aPGxc=;gmx-gC8%YgRBS55qxzRcfH>A?iQFY^veQkEHW=DX16rk1 z9ohYwB>5T%@v~Y5APpzK>trl*kgXrI1PP*xhj`9&WuiXYcVg7|c;g&#jwBg!tqm{; z!TBd7>c&aNbB9Yw!nm`5r$OIBq3YyQ4QI@6#F1z`q()4=Q&{uko-YAg8#tCFt1^{2 z5CdO>aAc{85i@#$TbPNWy0_2*)Wlu$?XuLWp(x<3X zWU9YEv;J%TYo_Zf#odrH`bNTg)Z(|?pA-O)v{Kepvur@_UA_!KmGngJw{5cBJPvgd z&UM9!Es!%!(Wr5}=q%RU+kN^&%#gyTwrKiGFxcHIoSt*UQ~2@MIy8&2F5CD`+5cjhq`m$aSSaJIqDH()mYh583Wb*j$2b zg^Ve?N#w3te=t^D95tcbb6e?Qhb|3$6L*0j36{-%@F@jeaycUH4ZQ!(qu61=Mha7= z`k0K>D0Q{>R|L6vLe%x>Tw#6BguPE%b(clsVD2#~ZJ``f2HSTnX5CO}e`@#7rgraE z2&kCtbvrrn6pc;@i&WYC zBdhe=F2j1Qa1JoGh6x%e1&k3RoqvoP zOQR-^wnt{=FB6r!hNz3)_%rD(CSg(XK^_)2BrR$Ea7GLrIf3}JnbqiO@NVs`V#pOK zef~dL0kC(=iVp?(VoU=LG?GP+Mx0KZ{ap8}!McdGwHFwEc!w?Uo2b!3f+%6f+tau4uy#9S~+pIGEEAEAe+c|KW*JbE@Z2Xs6; zxN`jYFU6bj(jaT!5cNLuOHwEBw_rU;Oqtb3z?YQeEn{MKcA{=wS8WgDoG-~hQ^xd4 zgs49e{4r@0+1*OTHf+7f13T*O?`QGLmy@>Fru?_6?>aUIHWH^TQzJBUse`TbVcaPHZ<8rsr{kl? zhlN!zEgtX@KtR8R-wo0+^`><0nsLIYN9uL#Jy zyJJoP6`gFp-}kUMuqFm1k_SX*)r+*&&%lvo|C)d_MWgGpj{;6mGA(=9JJg7h60k^? z(C!gT2K??-_Cr|HW|EN;0b{EH7@eI@1SI;JpZWEO$vriKdeOjb0AucoYnvqShD$*Q zGWER6?gLdm3e$)9cVtLC!<@!Xl2S({gH|Bsf{dL{@PmaeTWy!|GWD<4-m2DIYNUw* zM?aCpY|<2Fmr#eL-lV#)J|OQW7lLvqD~ znTzC*to*c^Znw{1B#DKe@Ic^U{fXt6%rU4e0P_emHC0%dF{KvNAD!LPAyF6SKgFw5 zC9W~7kp0lnvqPN_^#VN-tXK3^L%~c>67@g@&5TnFfUY#}E>{HXEq_-%-i?4$+ntzc zFz?b~Rq}a`c~gB!>S$oua|mSCAX3YZ?Vp!^>Qw+|0jYTGkMS{#7&S#cMh|yGI6>BD zRod_LWc9fIV*eeiwI%bzZI$|wf`gl+QUNNvA;5xsaKAL&kwm>7W*R|f80(MZM&|8D zj{N8sb_H;bXBgUyQ%KZLwhoLvw5mbUs=T(cO{>5Xtlw7l=;ZiF#$n$v@aQN4pY72% z!z+O#qL>v_f0cdGBg*xH7@DO11URyD8~vF2&4zWuCaY9%Bn_!^9Cu@HAi)I(N@NIX zIRAZjnE@q!z%;rmFm+q@>*%b~nmvfb>sdY! zQ%9g)D|B-BqD=xX%t;`t_@s55wxPSsDqkvmk{P{jUJdA>C6lErH^3pia@+FeV|rA( zvm${0mE+^A)$M86(5zdPuh*D9G(X4bnC5EzA#E(d#-&u2@)tp(~JkWbD>jsHRg9vuCHH!8y1n!>)&0|P~fp#x6Oe@ErQHwdfA}_AM zzAhO)^98no)c1|A?EzJL!|F==u&bp`YbD9;+E)Pyu2;M$6KE_m-meveBlpFdS$U+x z@X_atbg}mnml3$){zM1zlx5JLQ@#v`CPKtAx72K}tEbkN*%ZT}^q#B2bB}tetQn}8 z8SGUk{CaYj!-XXucd8>~_tD|f@saOB#=O|-ei&-}NNLwT7o5xHFsRA!%IW|nY_gKy z{N~C)5N?qyYld2i2d@pwMUcuDj@e@_q>!2p83enI7ZI;yMowL1h=TrAZk1P-5UP&4f5hq&rNm>XU8UIve2m^vJ_$UkRln`SZV8h5{oZuNc zxa$=p`z3lE7aE2Wx*BcZx^;f4H_)lShg4o6mPX1DWYViKQ( z3-FH2u+Nb_*8d~YG9>uD`e3Jicz$elub=PI3E5$p-mOhF0T%QfI0>{ErwDvLZJ@&p z0Ez{r*^7gc-hth?6TFPg=DK}c*sfDu;QFDz!mMa`XSNkR#p|fPrpcRcCx^8(X>%t| zFZqF~8X28oDmCQoy6r(~sds;O6U(fGwP(-_izuUbWu@YQInBb5Zt;H$TbKn8FCWe0 zbEd^6?0!C=p#>U&!OId0w-EJ{g4kH)%P4TopnKq&RBWTTEp`)K4aFHUWQtxA;SdzN zee9q~noKQ)J5`@EU7}N_Q(aX)=lIR=+O?7crQOYj=_EY7@FhkHcM5FIF*hmVMV1UH zL7D<>5)9&ZBCoB@<*8n(htYtbrP+?o4m-li4JsBU9mAfdr;-Mxo^(O#=N4)ND_R`C zm%J>I_Z+kf9{*Rl#*8p4^^A6S=BSS{%ClUM{Fj0AQ-d`i!URfo=a1Nm^`Ruqk z1*#{Dj%__%QE{yU+H?O2wD>$@PB|bWTGE(xhD>{7ar{J zkt3ts_4?0fzgx2zo;HYK0H7KztOz&+&NB7+sacidwJaN~WM;$%#*UPMb%A1}3#MO! z{(QN$OJUo@NKv}2)pc+mRv1@P>50NXNcy6q*KXeP@wh(K8;wdKJZscogpnWexRv#p z{KesRqSFfRTfVo}YMwIW$n6@P_9E@4U=3&_oo*s_V-mKQ_SoLddqcqR25`T&xyQbRs-C!^STXxmDuT$Av+|s!14D^UeF)fE>Um#7&i-_3K3v=Y5U^G z^ADX&S&&IrpKO_diJ=(Wd;h!%yR>N47anZW@ia9t>^ic&a&?}WO<>QjE8J6M>;PKc z8lc9+kd_INt*Ca{GpE;oM{5U^h>04%sN={Qpi>k(CP1Qz| zLD1pTHm$E}4&zmi=LZab^-QxjS;6V^OocVZ;UmNU+4?W;UsVWI8mA5xjSl1T_u1Ll zkV$m~`}dvXcMCc{8i+XBopw+`n6V$3JiOEkoBfPss-Y9`&4)@x-tLkG`$X{KhEq6@ z1aM&Khq$;+BPj}pB~<*y`JvNJUahM_bRFDV)7lCi4_T{9Z?0Va2)r{IE7Fl=lz;iu zIfLFmN=-+5fmd`Zk8LXfa*U4IRXiI-f#wF%7(gT?+#i5;dHN(}R+n_aA`ZWO(92-` z4=xO}tHdSo1~IbklBeee#zVk2=i6cw835hza(jje$^)IlB5m>qEUgQkOmLJRi&%ca zBkU?&6>Pu3r}cm<2+WrNu{8dK3U)G~DHZ;;yPy{WL*2NAVxy0L0mk>OH-L!_8pL|a zfBPV-<;ksG03!xorT+jqZU|(L8ef^nUe^Z=lNyH{!~t9^rkhR*v-F-s^sHi5cs zWRW@PDzUVV6d$+Iy;oz6$pyc-U8%6YYx?x>8ju#+orAZM3gLF?)u<}{tm}C+54Np%(cr~z8;9fr>s=UyEQH5zq()zKLw%n zG0clh@_|y*>B>0rf&-@35}&b=8{;Yc!agdyHRE;_X1_Gxpqlr2eJz}0%lA}^L8SBu zE*orFw_y{W4u;uN1{b>C912eUXWh9+OyfOY6B4Pyv}LYM5maDBH`$A5rwBVTp9Tc< zSB@gpYoT_vYy;jVyt$uuT!;xgt^xy|Wsxoj_7OOs+D3iL_DA#5F!;|$nfho7Ar<`oalNHlu6<@0V9CJbRn(AW@cy