From 8bf5cfee09b9c7660a27cdcdd9ad77b938eb67ed Mon Sep 17 00:00:00 2001 From: Zachary Mooney Date: Wed, 17 Jan 2024 23:12:35 +0100 Subject: [PATCH 01/20] Add styling --- admin-interface/src/assets/button.css | 33 +++++++++++++++++++++++++++ admin-interface/src/assets/form.css | 4 ++-- admin-interface/src/assets/image.css | 7 ++++++ admin-interface/src/assets/main.css | 3 +++ 4 files changed, 45 insertions(+), 2 deletions(-) create mode 100644 admin-interface/src/assets/button.css diff --git a/admin-interface/src/assets/button.css b/admin-interface/src/assets/button.css new file mode 100644 index 0000000..5b24082 --- /dev/null +++ b/admin-interface/src/assets/button.css @@ -0,0 +1,33 @@ +.city-button { + border-color: #000000; + border-width: 2px; + margin: 5px; + background-color: #f1f1f1; +} + + +.title-page-button { + border-color: #000000; + border-width: 2px; + margin: 5px; + background-color: #f1f1f1; + height: 100px; + width: 100px; +} + +.title-page-button { + display: grid; + grid-template-columns: 1fr 1fr 1fr 1fr; + grid-gap: 5px; +} + +.title-page-button div { + border-color: #000000; + border-width: 1px; + border-style: solid; + margin: 5px; + background-color: #f1f1f1; + height: 100px; + width: 100px; + aspect-ratio: 1; +} \ No newline at end of file diff --git a/admin-interface/src/assets/form.css b/admin-interface/src/assets/form.css index 2ddc4ca..8eb1a76 100644 --- a/admin-interface/src/assets/form.css +++ b/admin-interface/src/assets/form.css @@ -8,7 +8,7 @@ margin: 5px; background-color: #90ee90; border-radius: 25px; - display: block + display: block; } .edit-form { @@ -17,5 +17,5 @@ margin: 5px; background-color: #ffa07a; border-radius: 25px; - display: block + display: block; } \ No newline at end of file diff --git a/admin-interface/src/assets/image.css b/admin-interface/src/assets/image.css index 025ffa7..52d871d 100644 --- a/admin-interface/src/assets/image.css +++ b/admin-interface/src/assets/image.css @@ -44,4 +44,11 @@ .map-icon:hover { filter: invert(100%) sepia(0%) saturate(31%) hue-rotate(156deg) brightness(107%) contrast(108%); +} + +.home-images { + width: 100%; + height: 100%; + object-fit: contain; + } \ No newline at end of file diff --git a/admin-interface/src/assets/main.css b/admin-interface/src/assets/main.css index f63f9c8..cf19201 100644 --- a/admin-interface/src/assets/main.css +++ b/admin-interface/src/assets/main.css @@ -5,6 +5,7 @@ @import './image.css'; @import './form.css'; @import './map.css'; +@import './button.css'; body { margin: 0; @@ -52,6 +53,8 @@ body { font-weight: 600; color: #ff0000; } + + /* @import './base.css'; */ /* #app { From b9ec08c124736073f928908b87d380ba7a766bd7 Mon Sep 17 00:00:00 2001 From: Zachary Mooney Date: Wed, 17 Jan 2024 23:13:17 +0100 Subject: [PATCH 02/20] Add new images for home page --- admin-interface/src/assets/cart-shopping-solid.svg | 1 + admin-interface/src/assets/gear-solid.svg | 1 + admin-interface/src/assets/user-solid.svg | 1 + 3 files changed, 3 insertions(+) create mode 100644 admin-interface/src/assets/cart-shopping-solid.svg create mode 100644 admin-interface/src/assets/gear-solid.svg create mode 100644 admin-interface/src/assets/user-solid.svg diff --git a/admin-interface/src/assets/cart-shopping-solid.svg b/admin-interface/src/assets/cart-shopping-solid.svg new file mode 100644 index 0000000..8ca4d59 --- /dev/null +++ b/admin-interface/src/assets/cart-shopping-solid.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/admin-interface/src/assets/gear-solid.svg b/admin-interface/src/assets/gear-solid.svg new file mode 100644 index 0000000..96e5d3b --- /dev/null +++ b/admin-interface/src/assets/gear-solid.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/admin-interface/src/assets/user-solid.svg b/admin-interface/src/assets/user-solid.svg new file mode 100644 index 0000000..821ec63 --- /dev/null +++ b/admin-interface/src/assets/user-solid.svg @@ -0,0 +1 @@ + \ No newline at end of file From 87467bb435e02797dfbf50821a6801329fce4928 Mon Sep 17 00:00:00 2001 From: Zachary Mooney Date: Wed, 17 Jan 2024 23:17:45 +0100 Subject: [PATCH 03/20] Add link to API documentation --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index f919c17..17774a6 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,8 @@ You can run this service individually by executing `docker-compose up database`. This is the system's API. The current version is v1 and documentation can be found in the `server/v1` directory. +You can look at the API documentation [here](https://github.com/Mooney91/vteam6-HT23/blob/main/server/v1/API.md). + You can run this service individually by executing `docker-compose up database server`. The database for the server/API to function. ## admin-interface (Administrative Interface) From ee8c0d097ac4da3d24b51e342610d7fc71826d5e Mon Sep 17 00:00:00 2001 From: Zachary Mooney Date: Wed, 17 Jan 2024 23:18:33 +0100 Subject: [PATCH 04/20] Change to work with docker --- simulation/utils.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/simulation/utils.js b/simulation/utils.js index 7a582f3..ec47f7b 100644 --- a/simulation/utils.js +++ b/simulation/utils.js @@ -1,8 +1,8 @@ const sqlite3 = require('sqlite3').verbose(); const fetchHelper = { - BASE_URL: "http://localhost:1337", - // BASE_URL: "http://vteam6_server:1337", + // BASE_URL: "http://localhost:1337", + BASE_URL: "http://vteam6_server:1337", async getData(endpoint) { const response = await fetch(`${this.BASE_URL}/v1/${endpoint}`, @@ -149,9 +149,11 @@ const scooterHelper = { async updateScooter(scooter) { const data = { + "Status": scooter.Status, "Location": scooter.Location, "Speed": scooter.Speed, - "Battery": scooter.Battery + "Battery": scooter.Battery, + "StationID": scooter.StationID }; const endpoint = `scooter/${scooter.ScooterID}`; From 5f9654489d57ddfa1b3224c7db419128a6a995bb Mon Sep 17 00:00:00 2001 From: Zachary Mooney Date: Wed, 17 Jan 2024 23:19:10 +0100 Subject: [PATCH 05/20] Adjust maxClients --- simulation/simulator.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/simulation/simulator.js b/simulation/simulator.js index 7263c68..59ffe54 100644 --- a/simulation/simulator.js +++ b/simulation/simulator.js @@ -2,7 +2,7 @@ const publicHelper = require("./utils").publicHelper; const SC = require("./SimulatedClient").SimulatedClient; async function startSimulator() { - const maxClients = 5; + const maxClients = 500; const clientInterval = 5; setInterval(() => { From 8ef6fb41744591c949a86479ac2bb8e452758699 Mon Sep 17 00:00:00 2001 From: Zachary Mooney Date: Wed, 17 Jan 2024 23:20:45 +0100 Subject: [PATCH 06/20] Change waypoint coordinates to correct string format --- simulation/SimulatedClient.js | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/simulation/SimulatedClient.js b/simulation/SimulatedClient.js index 5aae9e3..cd3858c 100644 --- a/simulation/SimulatedClient.js +++ b/simulation/SimulatedClient.js @@ -50,12 +50,14 @@ class SimulatedClient { this.batteryDrainage = 0; } - // if (this.tripIndex === this.trip.Waypoints.length) { - if (this.tripIndex === 5) { + if (this.tripIndex === this.trip.Waypoints.length) { + // if (this.tripIndex === 5) { const zero = 0; this.scooter.Speed = zero.toFixed(2); - this.scooter.Location = this.trip.Destination; + const waypointCoordsString = String(this.trip.Destination) + this.scooter.Location = waypointCoordsString.replace(/[\[\]']+/g,''); + // this.scooter.Location = this.trip.Destination; // Update scooter in database when trip has ended publicHelper.updateScooter(this.scooter); @@ -68,10 +70,13 @@ class SimulatedClient { } else { this.scooter.Speed = (Math.random() * 30).toFixed(2); - this.scooter.Location = this.trip.Waypoints[this.tripIndex]; + const waypointCoordsString = String(this.trip.Waypoints[this.tripIndex]) + this.scooter.Location = waypointCoordsString.replace(/[\[\]']+/g,''); + // this.scooter.Location = this.trip.Waypoints[this.tripIndex]; // Update scooter in database every 5 waypoints if (this.tripIndex % 3 === 0) { + console.log("The scooter " + this.scooter.ScooterID + "is now at " + this.scooter.Location) publicHelper.updateScooter(this.scooter); } From e36f34bbba1c79f6f72f0274f4acd329e88ba8ec Mon Sep 17 00:00:00 2001 From: Zachary Mooney Date: Wed, 17 Jan 2024 23:21:12 +0100 Subject: [PATCH 07/20] Reset users --- server/users.json | 4 ---- 1 file changed, 4 deletions(-) diff --git a/server/users.json b/server/users.json index 27632fb..2a5fa22 100644 --- a/server/users.json +++ b/server/users.json @@ -8,10 +8,6 @@ { "date": "2024-01-01", "count": 0 - }, - { - "date": "2024-01-09", - "count": 22 } ] }, From 8634bbf2dce830e51e837dd05c1c662076f9a459 Mon Sep 17 00:00:00 2001 From: Zachary Mooney Date: Wed, 17 Jan 2024 23:21:34 +0100 Subject: [PATCH 08/20] Add links --- admin-interface/src/views/HomeView.vue | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/admin-interface/src/views/HomeView.vue b/admin-interface/src/views/HomeView.vue index adf13ee..4ede2d7 100644 --- a/admin-interface/src/views/HomeView.vue +++ b/admin-interface/src/views/HomeView.vue @@ -31,10 +31,22 @@ import HomeItem from '../components/HomeItem.vue'

This is the administrative interface (admin panel) for Svenska Elsparkscyklar AB.

Here you can view and manage data in the system.

+
+
+
+
+
+
+
+
+
+
+ - + diff --git a/admin-interface/src/assets/base.css b/admin-interface/src/assets/base.css deleted file mode 100644 index 6cd0798..0000000 --- a/admin-interface/src/assets/base.css +++ /dev/null @@ -1,86 +0,0 @@ -/* color palette from -:root { - --vt-c-white: #ffffff; - --vt-c-white-soft: #f8f8f8; - --vt-c-white-mute: #f2f2f2; - - --vt-c-black: #181818; - --vt-c-black-soft: #222222; - --vt-c-black-mute: #282828; - - --vt-c-indigo: #2c3e50; - - --vt-c-divider-light-1: rgba(60, 60, 60, 0.29); - --vt-c-divider-light-2: rgba(60, 60, 60, 0.12); - --vt-c-divider-dark-1: rgba(84, 84, 84, 0.65); - --vt-c-divider-dark-2: rgba(84, 84, 84, 0.48); - - --vt-c-text-light-1: var(--vt-c-indigo); - --vt-c-text-light-2: rgba(60, 60, 60, 0.66); - --vt-c-text-dark-1: var(--vt-c-white); - --vt-c-text-dark-2: rgba(235, 235, 235, 0.64); -} */ - -/* semantic color variables for this project */ -/* :root { - --color-background: var(--vt-c-white); - --color-background-soft: var(--vt-c-white-soft); - --color-background-mute: var(--vt-c-white-mute); - - --color-border: var(--vt-c-divider-light-2); - --color-border-hover: var(--vt-c-divider-light-1); - - --color-heading: var(--vt-c-text-light-1); - --color-text: var(--vt-c-text-light-1); - - --section-gap: 160px; -} - -@media (prefers-color-scheme: dark) { - :root { - --color-background: var(--vt-c-black); - --color-background-soft: var(--vt-c-black-soft); - --color-background-mute: var(--vt-c-black-mute); - - --color-border: var(--vt-c-divider-dark-2); - --color-border-hover: var(--vt-c-divider-dark-1); - - --color-heading: var(--vt-c-text-dark-1); - --color-text: var(--vt-c-text-dark-2); - } -} - -*, -*::before, -*::after { - box-sizing: border-box; - margin: 0; - font-weight: normal; -} - -body { - min-height: 100vh; - color: var(--color-text); - background: var(--color-background); - transition: - color 0.5s, - background-color 0.5s; - line-height: 1.6; - font-family: - Inter, - -apple-system, - BlinkMacSystemFont, - 'Segoe UI', - Roboto, - Oxygen, - Ubuntu, - Cantarell, - 'Fira Sans', - 'Droid Sans', - 'Helvetica Neue', - sans-serif; - font-size: 15px; - text-rendering: optimizeLegibility; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; -} */ diff --git a/admin-interface/src/assets/button.css b/admin-interface/src/assets/button.css index 5b24082..bdfcc75 100644 --- a/admin-interface/src/assets/button.css +++ b/admin-interface/src/assets/button.css @@ -1,33 +1,32 @@ .city-button { - border-color: #000000; - border-width: 2px; - margin: 5px; - background-color: #f1f1f1; + border-color: #000000; + border-width: 2px; + margin: 5px; + background-color: #f1f1f1; } - .title-page-button { - border-color: #000000; - border-width: 2px; - margin: 5px; - background-color: #f1f1f1; - height: 100px; - width: 100px; + border-color: #000000; + border-width: 2px; + margin: 5px; + background-color: #f1f1f1; + height: 100px; + width: 100px; } .title-page-button { - display: grid; - grid-template-columns: 1fr 1fr 1fr 1fr; - grid-gap: 5px; + display: grid; + grid-template-columns: 1fr 1fr 1fr 1fr; + grid-gap: 5px; } .title-page-button div { - border-color: #000000; - border-width: 1px; - border-style: solid; - margin: 5px; - background-color: #f1f1f1; - height: 100px; - width: 100px; - aspect-ratio: 1; -} \ No newline at end of file + border-color: #000000; + border-width: 1px; + border-style: solid; + margin: 5px; + background-color: #f1f1f1; + height: 100px; + width: 100px; + aspect-ratio: 1; +} diff --git a/admin-interface/src/assets/form.css b/admin-interface/src/assets/form.css index 8eb1a76..b11fab0 100644 --- a/admin-interface/src/assets/form.css +++ b/admin-interface/src/assets/form.css @@ -1,21 +1,21 @@ .form { - display: block; + display: block; } .add-form { - height: 100%; - padding: 10px; - margin: 5px; - background-color: #90ee90; - border-radius: 25px; - display: block; + height: 100%; + padding: 10px; + margin: 5px; + background-color: #90ee90; + border-radius: 25px; + display: block; } .edit-form { - height: 100%; - padding: 10px; - margin: 5px; - background-color: #ffa07a; - border-radius: 25px; - display: block; -} \ No newline at end of file + height: 100%; + padding: 10px; + margin: 5px; + background-color: #ffa07a; + border-radius: 25px; + display: block; +} diff --git a/admin-interface/src/assets/header.css b/admin-interface/src/assets/header.css index ca1e5ef..b36863e 100644 --- a/admin-interface/src/assets/header.css +++ b/admin-interface/src/assets/header.css @@ -1,33 +1,29 @@ .header { - position: sticky; - top: 0; - height: 50px; - grid-area: header; - background-color: #333; - color: #fff; - padding: 10px; - vertical-align: middle; - z-index: 100; - display: flex; - align-items: center; + position: sticky; + top: 0; + height: 50px; + grid-area: header; + background-color: #333; + color: #fff; + padding: 10px; + vertical-align: middle; + z-index: 100; + display: flex; + align-items: center; } -/* .title { - grid-area: header; -} */ - .login-button { - grid-area: login; - vertical-align: middle; - float: right; - color: #000000; - padding: 16px; - text-decoration: none; - background-color:#f1f1f1; - margin-left: auto; + grid-area: login; + vertical-align: middle; + float: right; + color: #000000; + padding: 16px; + text-decoration: none; + background-color: #f1f1f1; + margin-left: auto; } .login-button:hover { - background-color: #555; - color: white; - } \ No newline at end of file + background-color: #555; + color: white; +} diff --git a/admin-interface/src/assets/image.css b/admin-interface/src/assets/image.css index 52d871d..bc57ecc 100644 --- a/admin-interface/src/assets/image.css +++ b/admin-interface/src/assets/image.css @@ -1,54 +1,53 @@ .add { - vertical-align: middle; - padding-right: 5px; - filter: invert(25%) sepia(68%) saturate(6837%) hue-rotate(116deg) brightness(94%) contrast(103%); + vertical-align: middle; + padding-right: 5px; + filter: invert(25%) sepia(68%) saturate(6837%) hue-rotate(116deg) brightness(94%) contrast(103%); } .edit { - filter: invert(62%) sepia(100%) saturate(1821%) hue-rotate(1deg) brightness(104%) contrast(103%); + filter: invert(62%) sepia(100%) saturate(1821%) hue-rotate(1deg) brightness(104%) contrast(103%); } .delete { - filter: invert(11%) sepia(98%) saturate(6844%) hue-rotate(7deg) brightness(109%) contrast(116%); + filter: invert(11%) sepia(98%) saturate(6844%) hue-rotate(7deg) brightness(109%) contrast(116%); } .charging { - filter: invert(60%) sepia(40%) saturate(1687%) hue-rotate(2deg) brightness(106%) contrast(104%); - height: 25px; - width: 25px; + filter: invert(60%) sepia(40%) saturate(1687%) hue-rotate(2deg) brightness(106%) contrast(104%); + height: 25px; + width: 25px; } .parking { - filter: invert(20%) sepia(91%) saturate(1754%) hue-rotate(180deg) brightness(95%) contrast(101%); - height: 25px; - width: 25px; + filter: invert(20%) sepia(91%) saturate(1754%) hue-rotate(180deg) brightness(95%) contrast(101%); + height: 25px; + width: 25px; } .scooter { - filter: invert(4%) sepia(97%) saturate(6587%) hue-rotate(341deg) brightness(112%) contrast(101%); - height: 25px; - width: 25px; + filter: invert(4%) sepia(97%) saturate(6587%) hue-rotate(341deg) brightness(112%) contrast(101%); + height: 25px; + width: 25px; } .custom-icon { - background: none; - border: none; + background: none; + border: none; } .map-icon { - filter: invert(0%) sepia(91%) saturate(7463%) hue-rotate(105deg) brightness(113%) contrast(108%); - height: 125px; - width: auto; - text-align: center; + filter: invert(0%) sepia(91%) saturate(7463%) hue-rotate(105deg) brightness(113%) contrast(108%); + height: 125px; + width: auto; + text-align: center; } .map-icon:hover { - filter: invert(100%) sepia(0%) saturate(31%) hue-rotate(156deg) brightness(107%) contrast(108%); + filter: invert(100%) sepia(0%) saturate(31%) hue-rotate(156deg) brightness(107%) contrast(108%); } .home-images { - width: 100%; - height: 100%; - object-fit: contain; - -} \ No newline at end of file + width: 100%; + height: 100%; + object-fit: contain; +} diff --git a/admin-interface/src/assets/main.css b/admin-interface/src/assets/main.css index cf19201..37d6935 100644 --- a/admin-interface/src/assets/main.css +++ b/admin-interface/src/assets/main.css @@ -9,33 +9,27 @@ body { margin: 0; - font-family: "Lato", sans-serif; + font-family: 'Lato', sans-serif; } .main { grid-template-columns: 200px 50px 50px 50px; grid-template-rows: auto; - grid-template-areas: - "logo header header login" - "navigation content content content" - "footer footer footer footer"; + grid-template-areas: + 'logo header header login' + 'navigation content content content' + 'footer footer footer footer'; } /* CONTAINER FOR PAGES WITH A MAP */ .about { - display:grid; + display: grid; grid-template-columns: 50% 50%; grid-template-rows: auto; - grid-template-areas: - "small-content map"; + grid-template-areas: 'small-content map'; } -/* THE CONTAINER FOR PAGES WITHOUT AMAP */ -/* .other { - -} */ - -/* */ +/* THE CONTAINER FOR PAGES WITHOUT A MAP */ .content { grid-area: content; padding: 10px; @@ -53,40 +47,3 @@ body { font-weight: 600; color: #ff0000; } - - -/* @import './base.css'; */ - -/* #app { - max-width: 1280px; - margin: 0 auto; - padding: 2rem; - - font-weight: normal; -} - -a, -.green { - text-decoration: none; - color: hsla(160, 100%, 37%, 1); - transition: 0.4s; -} - -@media (hover: hover) { - a:hover { - background-color: hsla(160, 100%, 37%, 0.2); - } -} - -@media (min-width: 1024px) { - body { - display: flex; - place-items: center; - } - - #app { - display: grid; - grid-template-columns: 1fr 1fr; - padding: 0 2rem; - } -} */ diff --git a/admin-interface/src/assets/map.css b/admin-interface/src/assets/map.css index 40b96c5..17b8160 100644 --- a/admin-interface/src/assets/map.css +++ b/admin-interface/src/assets/map.css @@ -1,8 +1,8 @@ .map { - grid-area: map; - z-index: 0; - float: right; - display: flex; - justify-content: center; - align-items: center; -} \ No newline at end of file + grid-area: map; + z-index: 0; + float: right; + display: flex; + justify-content: center; + align-items: center; +} diff --git a/admin-interface/src/assets/navigation.css b/admin-interface/src/assets/navigation.css index 45fb023..22da3a5 100644 --- a/admin-interface/src/assets/navigation.css +++ b/admin-interface/src/assets/navigation.css @@ -1,55 +1,59 @@ body { - margin: 0; - font-family: "Lato", sans-serif; - } - + margin: 0; + font-family: 'Lato', sans-serif; +} + +.navigation { + margin: 0; + padding: 0; + width: 200px; + background-color: #f1f1f1; + position: fixed; + height: 100%; + overflow: auto; + grid-area: navigation; +} + +.navigation a { + display: block; + color: black; + padding: 16px; + text-decoration: none; +} + +.navigation a.active { + background-color: #04aa6d; + color: white; +} + +.navigation a:hover:not(.active) { + background-color: #555; + color: white; +} + +div.content { + margin-left: 200px; + padding: 1px 16px; + height: 1000px; +} + +@media screen and (max-width: 700px) { .navigation { - margin: 0; - padding: 0; - width: 200px; - background-color: #f1f1f1; - position: fixed; - height: 100%; - overflow: auto; - grid-area: navigation; + width: 100%; + height: auto; + position: relative; } - .navigation a { - display: block; - color: black; - padding: 16px; - text-decoration: none; - } - - .navigation a.active { - background-color: #04AA6D; - color: white; + float: left; } - - .navigation a:hover:not(.active) { - background-color: #555; - color: white; - } - div.content { - margin-left: 200px; - padding: 1px 16px; - height: 1000px; + margin-left: 0; } - - @media screen and (max-width: 700px) { - .navigation { - width: 100%; - height: auto; - position: relative; - } - .navigation a {float: left;} - div.content {margin-left: 0;} +} + +@media screen and (max-width: 400px) { + .navigation a { + text-align: center; + float: none; } - - @media screen and (max-width: 400px) { - .navigation a { - text-align: center; - float: none; - } - } \ No newline at end of file +} diff --git a/admin-interface/src/assets/normalize.css b/admin-interface/src/assets/normalize.css index 8c331ec..e1348b6 100644 --- a/admin-interface/src/assets/normalize.css +++ b/admin-interface/src/assets/normalize.css @@ -8,343 +8,344 @@ * 2. Prevent adjustments of font size after orientation changes in iOS. */ - html { - line-height: 1.15; /* 1 */ - -webkit-text-size-adjust: 100%; /* 2 */ - } - - /* Sections +html { + line-height: 1.15; /* 1 */ + -webkit-text-size-adjust: 100%; /* 2 */ +} + +/* Sections ========================================================================== */ - - /** + +/** * Remove the margin in all browsers. */ - - body { - margin: 0; - } - - /** + +body { + margin: 0; +} + +/** * Render the `main` element consistently in IE. */ - - main { - display: block; - } - - /** + +main { + display: block; +} + +/** * Correct the font size and margin on `h1` elements within `section` and * `article` contexts in Chrome, Firefox, and Safari. */ - - h1 { - font-size: 2em; - margin: 0.67em 0; - } - - /* Grouping content + +h1 { + font-size: 2em; + margin: 0.67em 0; +} + +/* Grouping content ========================================================================== */ - - /** + +/** * 1. Add the correct box sizing in Firefox. * 2. Show the overflow in Edge and IE. */ - - hr { - box-sizing: content-box; /* 1 */ - height: 0; /* 1 */ - overflow: visible; /* 2 */ - } - - /** + +hr { + box-sizing: content-box; /* 1 */ + height: 0; /* 1 */ + overflow: visible; /* 2 */ +} + +/** * 1. Correct the inheritance and scaling of font size in all browsers. * 2. Correct the odd `em` font sizing in all browsers. */ - - pre { - font-family: monospace, monospace; /* 1 */ - font-size: 1em; /* 2 */ - } - - /* Text-level semantics + +pre { + font-family: monospace, monospace; /* 1 */ + font-size: 1em; /* 2 */ +} + +/* Text-level semantics ========================================================================== */ - - /** + +/** * Remove the gray background on active links in IE 10. */ - - a { - background-color: transparent; - } - - /** + +a { + background-color: transparent; +} + +/** * 1. Remove the bottom border in Chrome 57- * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari. */ - - abbr[title] { - border-bottom: none; /* 1 */ - text-decoration: underline; /* 2 */ - text-decoration: underline dotted; /* 2 */ - } - - /** + +abbr[title] { + border-bottom: none; /* 1 */ + text-decoration: underline; /* 2 */ + text-decoration: underline dotted; /* 2 */ +} + +/** * Add the correct font weight in Chrome, Edge, and Safari. */ - - b, - strong { - font-weight: bolder; - } - - /** + +b, +strong { + font-weight: bolder; +} + +/** * 1. Correct the inheritance and scaling of font size in all browsers. * 2. Correct the odd `em` font sizing in all browsers. */ - - code, - kbd, - samp { - font-family: monospace, monospace; /* 1 */ - font-size: 1em; /* 2 */ - } - - /** + +code, +kbd, +samp { + font-family: monospace, monospace; /* 1 */ + font-size: 1em; /* 2 */ +} + +/** * Add the correct font size in all browsers. */ - - small { - font-size: 80%; - } - - /** + +small { + font-size: 80%; +} + +/** * Prevent `sub` and `sup` elements from affecting the line height in * all browsers. */ - - sub, - sup { - font-size: 75%; - line-height: 0; - position: relative; - vertical-align: baseline; - } - - sub { - bottom: -0.25em; - } - - sup { - top: -0.5em; - } - - /* Embedded content + +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} + +sub { + bottom: -0.25em; +} + +sup { + top: -0.5em; +} + +/* Embedded content ========================================================================== */ - - /** + +/** * Remove the border on images inside links in IE 10. */ - - img { - border-style: none; - } - - /* Forms + +img { + border-style: none; +} + +/* Forms ========================================================================== */ - - /** + +/** * 1. Change the font styles in all browsers. * 2. Remove the margin in Firefox and Safari. */ - - button, - input, - optgroup, - select, - textarea { - font-family: inherit; /* 1 */ - font-size: 100%; /* 1 */ - line-height: 1.15; /* 1 */ - margin: 0; /* 2 */ - } - - /** + +button, +input, +optgroup, +select, +textarea { + font-family: inherit; /* 1 */ + font-size: 100%; /* 1 */ + line-height: 1.15; /* 1 */ + margin: 0; /* 2 */ +} + +/** * Show the overflow in IE. * 1. Show the overflow in Edge. */ - - button, - input { /* 1 */ - overflow: visible; - } - - /** + +button, +input { + /* 1 */ + overflow: visible; +} + +/** * Remove the inheritance of text transform in Edge, Firefox, and IE. * 1. Remove the inheritance of text transform in Firefox. */ - - button, - select { /* 1 */ - text-transform: none; - } - - /** + +button, +select { + /* 1 */ + text-transform: none; +} + +/** * Correct the inability to style clickable types in iOS and Safari. */ - - button, - [type="button"], - [type="reset"], - [type="submit"] { - -webkit-appearance: button; - } - - /** + +button, +[type='button'], +[type='reset'], +[type='submit'] { + -webkit-appearance: button; +} + +/** * Remove the inner border and padding in Firefox. */ - - button::-moz-focus-inner, - [type="button"]::-moz-focus-inner, - [type="reset"]::-moz-focus-inner, - [type="submit"]::-moz-focus-inner { - border-style: none; - padding: 0; - } - - /** + +button::-moz-focus-inner, +[type='button']::-moz-focus-inner, +[type='reset']::-moz-focus-inner, +[type='submit']::-moz-focus-inner { + border-style: none; + padding: 0; +} + +/** * Restore the focus styles unset by the previous rule. */ - - button:-moz-focusring, - [type="button"]:-moz-focusring, - [type="reset"]:-moz-focusring, - [type="submit"]:-moz-focusring { - outline: 1px dotted ButtonText; - } - - /** + +button:-moz-focusring, +[type='button']:-moz-focusring, +[type='reset']:-moz-focusring, +[type='submit']:-moz-focusring { + outline: 1px dotted ButtonText; +} + +/** * Correct the padding in Firefox. */ - - fieldset { - padding: 0.35em 0.75em 0.625em; - } - - /** + +fieldset { + padding: 0.35em 0.75em 0.625em; +} + +/** * 1. Correct the text wrapping in Edge and IE. * 2. Correct the color inheritance from `fieldset` elements in IE. * 3. Remove the padding so developers are not caught out when they zero out * `fieldset` elements in all browsers. */ - - legend { - box-sizing: border-box; /* 1 */ - color: inherit; /* 2 */ - display: table; /* 1 */ - max-width: 100%; /* 1 */ - padding: 0; /* 3 */ - white-space: normal; /* 1 */ - } - - /** + +legend { + box-sizing: border-box; /* 1 */ + color: inherit; /* 2 */ + display: table; /* 1 */ + max-width: 100%; /* 1 */ + padding: 0; /* 3 */ + white-space: normal; /* 1 */ +} + +/** * Add the correct vertical alignment in Chrome, Firefox, and Opera. */ - - progress { - vertical-align: baseline; - } - - /** + +progress { + vertical-align: baseline; +} + +/** * Remove the default vertical scrollbar in IE 10+. */ - - textarea { - overflow: auto; - } - - /** + +textarea { + overflow: auto; +} + +/** * 1. Add the correct box sizing in IE 10. * 2. Remove the padding in IE 10. */ - - [type="checkbox"], - [type="radio"] { - box-sizing: border-box; /* 1 */ - padding: 0; /* 2 */ - } - - /** + +[type='checkbox'], +[type='radio'] { + box-sizing: border-box; /* 1 */ + padding: 0; /* 2 */ +} + +/** * Correct the cursor style of increment and decrement buttons in Chrome. */ - - [type="number"]::-webkit-inner-spin-button, - [type="number"]::-webkit-outer-spin-button { - height: auto; - } - - /** + +[type='number']::-webkit-inner-spin-button, +[type='number']::-webkit-outer-spin-button { + height: auto; +} + +/** * 1. Correct the odd appearance in Chrome and Safari. * 2. Correct the outline style in Safari. */ - - [type="search"] { - -webkit-appearance: textfield; /* 1 */ - outline-offset: -2px; /* 2 */ - } - - /** + +[type='search'] { + -webkit-appearance: textfield; /* 1 */ + outline-offset: -2px; /* 2 */ +} + +/** * Remove the inner padding in Chrome and Safari on macOS. */ - - [type="search"]::-webkit-search-decoration { - -webkit-appearance: none; - } - - /** + +[type='search']::-webkit-search-decoration { + -webkit-appearance: none; +} + +/** * 1. Correct the inability to style clickable types in iOS and Safari. * 2. Change font properties to `inherit` in Safari. */ - - ::-webkit-file-upload-button { - -webkit-appearance: button; /* 1 */ - font: inherit; /* 2 */ - } - - /* Interactive + +::-webkit-file-upload-button { + -webkit-appearance: button; /* 1 */ + font: inherit; /* 2 */ +} + +/* Interactive ========================================================================== */ - - /* + +/* * Add the correct display in Edge, IE 10+, and Firefox. */ - - details { - display: block; - } - - /* + +details { + display: block; +} + +/* * Add the correct display in all browsers. */ - - summary { - display: list-item; - } - - /* Misc + +summary { + display: list-item; +} + +/* Misc ========================================================================== */ - - /** + +/** * Add the correct display in IE 10+. */ - - template { - display: none; - } - - /** + +template { + display: none; +} + +/** * Add the correct display in IE 10. */ - - [hidden] { - display: none; - } - \ No newline at end of file + +[hidden] { + display: none; +} diff --git a/admin-interface/src/assets/table.css b/admin-interface/src/assets/table.css index 6f4256c..8716c66 100644 --- a/admin-interface/src/assets/table.css +++ b/admin-interface/src/assets/table.css @@ -1,21 +1,22 @@ .database-table { - font-family: arial, sans-serif; - border-collapse: collapse; - width: 100%; - border-radius: 25%; - margin-top: 10px + font-family: arial, sans-serif; + border-collapse: collapse; + width: 100%; + border-radius: 25%; + margin-top: 10px; } - -.database-table td, th { - border: 1px solid #f1f1f1; - text-align: left; - padding: 8px; + +.database-table td, +th { + border: 1px solid #f1f1f1; + text-align: left; + padding: 8px; } - + .database-table tr:nth-child(even) { - background-color: #f1f1f1; + background-color: #f1f1f1; } .database-table tr:hover { - background: #fbdbff; -} \ No newline at end of file + background: #fbdbff; +} diff --git a/admin-interface/src/components/HomeItem.vue b/admin-interface/src/components/HomeItem.vue index a707197..ecfcd27 100644 --- a/admin-interface/src/components/HomeItem.vue +++ b/admin-interface/src/components/HomeItem.vue @@ -1,14 +1,16 @@ - + - \ No newline at end of file + diff --git a/admin-interface/src/components/MapItem.vue b/admin-interface/src/components/MapItem.vue index 19df01e..56d418b 100644 --- a/admin-interface/src/components/MapItem.vue +++ b/admin-interface/src/components/MapItem.vue @@ -1,66 +1,70 @@ - + - + \ No newline at end of file + diff --git a/admin-interface/src/components/NavigationItem.vue b/admin-interface/src/components/NavigationItem.vue index 2fdab89..01b0615 100644 --- a/admin-interface/src/components/NavigationItem.vue +++ b/admin-interface/src/components/NavigationItem.vue @@ -3,37 +3,34 @@ import { RouterLink } from 'vue-router' // import { useAuth0 } from '@auth0/auth0-vue'; export default { - components: { - RouterLink, - }, - setup() { - // const auth0 = useAuth0(); - - // return { - // user: auth0.user, - // isAuthenticated: auth0.isAuthenticated - // }; - } + components: { + RouterLink + }, + setup() { + // const auth0 = useAuth0(); + // return { + // user: auth0.user, + // isAuthenticated: auth0.isAuthenticated + // }; + } } - - \ No newline at end of file + diff --git a/admin-interface/src/components/ScooterMapItem.vue b/admin-interface/src/components/ScooterMapItem.vue index 846e528..3468a16 100644 --- a/admin-interface/src/components/ScooterMapItem.vue +++ b/admin-interface/src/components/ScooterMapItem.vue @@ -1,6 +1,12 @@ - - + - + \ No newline at end of file + diff --git a/admin-interface/src/components/TitleItem.vue b/admin-interface/src/components/TitleItem.vue index 5a44217..2cbceb9 100644 --- a/admin-interface/src/components/TitleItem.vue +++ b/admin-interface/src/components/TitleItem.vue @@ -3,41 +3,40 @@ import { RouterLink } from 'vue-router' // import { useAuth0 } from '@auth0/auth0-vue'; export default { - setup() { - // const auth0 = useAuth0(); - - // return { - // login() { - // auth0.loginWithRedirect(); - // }, - // logout() { - // auth0.logout(); - // }, - // user: auth0.user, - // isAuthenticated: auth0.isAuthenticated - // }; - } -}; + setup() { + // const auth0 = useAuth0(); + // return { + // login() { + // auth0.loginWithRedirect(); + // }, + // logout() { + // auth0.logout(); + // }, + // user: auth0.user, + // isAuthenticated: auth0.isAuthenticated + // }; + }, + components: { + RouterLink + } +} // - \ No newline at end of file + diff --git a/admin-interface/src/components/__tests__/TitleItem.spec.js b/admin-interface/src/components/__tests__/TitleItem.spec.js index 6bf4622..0d759f1 100644 --- a/admin-interface/src/components/__tests__/TitleItem.spec.js +++ b/admin-interface/src/components/__tests__/TitleItem.spec.js @@ -1,11 +1,11 @@ -import { describe, it, expect } from 'vitest'; -import { mount } from '@vue/test-utils'; -import TitleItem from '../TitleItem.vue'; +import { describe, it, expect } from 'vitest' +import { mount } from '@vue/test-utils' +import TitleItem from '../TitleItem.vue' describe('TitleItem', () => { it('renders properly', () => { - const wrapper = mount(TitleItem); + const wrapper = mount(TitleItem) - expect(wrapper.exists()).toBe(true); - }); -}); \ No newline at end of file + expect(wrapper.exists()).toBe(true) + }) +}) diff --git a/admin-interface/src/main.js b/admin-interface/src/main.js index 57040fc..2d63bad 100644 --- a/admin-interface/src/main.js +++ b/admin-interface/src/main.js @@ -6,7 +6,7 @@ import { createPinia } from 'pinia' import App from './App.vue' import router from './router' -import "leaflet" +import 'leaflet' const app = createApp(App) diff --git a/admin-interface/src/router/index.js b/admin-interface/src/router/index.js index 53b6860..1f3e86d 100644 --- a/admin-interface/src/router/index.js +++ b/admin-interface/src/router/index.js @@ -69,7 +69,7 @@ const router = createRouter({ { path: '/map', name: 'BigMap', - component: BigMapView, + component: BigMapView } // { // path: '/about', diff --git a/admin-interface/src/views/BigMapView.vue b/admin-interface/src/views/BigMapView.vue index 695b708..05afa8e 100644 --- a/admin-interface/src/views/BigMapView.vue +++ b/admin-interface/src/views/BigMapView.vue @@ -1,229 +1,254 @@ - - - - \ No newline at end of file +} + + + diff --git a/admin-interface/src/views/ChargingView.vue b/admin-interface/src/views/ChargingView.vue index 00061a7..1905786 100644 --- a/admin-interface/src/views/ChargingView.vue +++ b/admin-interface/src/views/ChargingView.vue @@ -1,311 +1,353 @@ - - - - \ No newline at end of file +} + + + diff --git a/admin-interface/src/views/CitySingle.vue b/admin-interface/src/views/CitySingle.vue index b9f8405..1e3a0f3 100644 --- a/admin-interface/src/views/CitySingle.vue +++ b/admin-interface/src/views/CitySingle.vue @@ -1,251 +1,277 @@ \ No newline at end of file + diff --git a/admin-interface/src/views/CityView.vue b/admin-interface/src/views/CityView.vue index 045680d..6a3a25a 100644 --- a/admin-interface/src/views/CityView.vue +++ b/admin-interface/src/views/CityView.vue @@ -1,224 +1,248 @@ - \ No newline at end of file + diff --git a/admin-interface/src/views/HomeView.vue b/admin-interface/src/views/HomeView.vue index 4ede2d7..16769ba 100644 --- a/admin-interface/src/views/HomeView.vue +++ b/admin-interface/src/views/HomeView.vue @@ -11,7 +11,6 @@ import HomeItem from '../components/HomeItem.vue' --> diff --git a/admin-interface/src/views/LoginView.vue b/admin-interface/src/views/LoginView.vue index 319b0d4..466c011 100644 --- a/admin-interface/src/views/LoginView.vue +++ b/admin-interface/src/views/LoginView.vue @@ -1,12 +1,5 @@ - - + - - - \ No newline at end of file + diff --git a/admin-interface/src/views/ParkingView.vue b/admin-interface/src/views/ParkingView.vue index 91c4e64..e113247 100644 --- a/admin-interface/src/views/ParkingView.vue +++ b/admin-interface/src/views/ParkingView.vue @@ -1,309 +1,350 @@ - - - - \ No newline at end of file +} + + + diff --git a/admin-interface/src/views/RentalView.vue b/admin-interface/src/views/RentalView.vue index fe24aea..59071c4 100644 --- a/admin-interface/src/views/RentalView.vue +++ b/admin-interface/src/views/RentalView.vue @@ -1,252 +1,277 @@ - \ No newline at end of file + diff --git a/admin-interface/src/views/ScooterView.vue b/admin-interface/src/views/ScooterView.vue index c63bced..43d0d51 100644 --- a/admin-interface/src/views/ScooterView.vue +++ b/admin-interface/src/views/ScooterView.vue @@ -1,402 +1,453 @@ - \ No newline at end of file + diff --git a/admin-interface/src/views/SettingsView.vue b/admin-interface/src/views/SettingsView.vue index c193feb..f1421db 100644 --- a/admin-interface/src/views/SettingsView.vue +++ b/admin-interface/src/views/SettingsView.vue @@ -1,151 +1,153 @@ - \ No newline at end of file + diff --git a/admin-interface/src/views/UserSingle.vue b/admin-interface/src/views/UserSingle.vue index 83eeac1..6524a2d 100644 --- a/admin-interface/src/views/UserSingle.vue +++ b/admin-interface/src/views/UserSingle.vue @@ -1,172 +1,179 @@ - - - - \ No newline at end of file +} + + + diff --git a/admin-interface/src/views/UserView.vue b/admin-interface/src/views/UserView.vue index 47293d8..8204de4 100644 --- a/admin-interface/src/views/UserView.vue +++ b/admin-interface/src/views/UserView.vue @@ -1,254 +1,279 @@ - \ No newline at end of file + diff --git a/admin-interface/src/views/__tests__/BigMapView.spec.js b/admin-interface/src/views/__tests__/BigMapView.spec.js index e27dfe2..a350489 100644 --- a/admin-interface/src/views/__tests__/BigMapView.spec.js +++ b/admin-interface/src/views/__tests__/BigMapView.spec.js @@ -1,19 +1,18 @@ import { describe, it, expect } from 'vitest' -import { mount } from '@vue/test-utils'; -import BigMapView from '../BigMapView.vue'; +import { mount } from '@vue/test-utils' +import BigMapView from '../BigMapView.vue' describe('BigMapView', () => { it('renders properly', async () => { const wrapper = mount(BigMapView, { props: { id: 'some-id', - backend: 'http://localhost:1337', - }, - }); + backend: 'http://localhost:1337' + } + }) - expect(wrapper.find('p').text()).toBe('Charging Station Parking Scooter'); + expect(wrapper.find('p').text()).toBe('Charging Station Parking Scooter') - await wrapper.vm.$nextTick(); - - }); -}); + await wrapper.vm.$nextTick() + }) +}) diff --git a/admin-interface/src/views/__tests__/ChargingView.spec.js b/admin-interface/src/views/__tests__/ChargingView.spec.js index 6380bd4..91f1ee5 100644 --- a/admin-interface/src/views/__tests__/ChargingView.spec.js +++ b/admin-interface/src/views/__tests__/ChargingView.spec.js @@ -1,20 +1,20 @@ import { describe, it, expect } from 'vitest' -import { mount } from '@vue/test-utils'; -import ChargingView from '../ChargingView.vue'; +import { mount } from '@vue/test-utils' +import ChargingView from '../ChargingView.vue' describe('ChargingView', () => { it('renders properly', async () => { const wrapper = mount(ChargingView, { props: { id: 'some-id', - backend: 'http://localhost:1337', - }, - }); + backend: 'http://localhost:1337' + } + }) - expect(wrapper.find('h1').text()).toBe('Charging Stations'); + expect(wrapper.find('h1').text()).toBe('Charging Stations') - await wrapper.vm.$nextTick(); + await wrapper.vm.$nextTick() - expect(wrapper.find('.database-table').exists()).toBe(true); - }); -}); + expect(wrapper.find('.database-table').exists()).toBe(true) + }) +}) diff --git a/admin-interface/src/views/__tests__/CityView.spec.js b/admin-interface/src/views/__tests__/CityView.spec.js index ec939cb..e9006bc 100644 --- a/admin-interface/src/views/__tests__/CityView.spec.js +++ b/admin-interface/src/views/__tests__/CityView.spec.js @@ -1,20 +1,20 @@ import { describe, it, expect } from 'vitest' -import { mount } from '@vue/test-utils'; -import CityView from '../CityView.vue'; +import { mount } from '@vue/test-utils' +import CityView from '../CityView.vue' describe('CityView', () => { it('renders properly', async () => { const wrapper = mount(CityView, { props: { id: 'some-id', - backend: 'http://localhost:1337', - }, - }); + backend: 'http://localhost:1337' + } + }) - expect(wrapper.find('h1').text()).toBe('Cities'); + expect(wrapper.find('h1').text()).toBe('Cities') - await wrapper.vm.$nextTick(); + await wrapper.vm.$nextTick() - expect(wrapper.find('.database-table').exists()).toBe(true); - }); -}); + expect(wrapper.find('.database-table').exists()).toBe(true) + }) +}) diff --git a/admin-interface/src/views/__tests__/HomeView.spec.js b/admin-interface/src/views/__tests__/HomeView.spec.js index 79417a8..cfe81cd 100644 --- a/admin-interface/src/views/__tests__/HomeView.spec.js +++ b/admin-interface/src/views/__tests__/HomeView.spec.js @@ -1,18 +1,18 @@ import { describe, it, expect } from 'vitest' -import { mount } from '@vue/test-utils'; -import HomeView from '../HomeView.vue'; +import { mount } from '@vue/test-utils' +import HomeView from '../HomeView.vue' describe('HomeView', () => { it('renders properly', async () => { const wrapper = mount(HomeView, { props: { id: 'some-id', - backend: 'http://localhost:1337', - }, - }); + backend: 'http://localhost:1337' + } + }) - expect(wrapper.find('h1').text()).toBe('Welcome!'); + expect(wrapper.find('h1').text()).toBe('Welcome!') - await wrapper.vm.$nextTick(); - }); -}); + await wrapper.vm.$nextTick() + }) +}) diff --git a/admin-interface/src/views/__tests__/ParkingView.spec.js b/admin-interface/src/views/__tests__/ParkingView.spec.js index 8be7b98..78f72f9 100644 --- a/admin-interface/src/views/__tests__/ParkingView.spec.js +++ b/admin-interface/src/views/__tests__/ParkingView.spec.js @@ -1,20 +1,20 @@ import { describe, it, expect } from 'vitest' -import { mount } from '@vue/test-utils'; -import ParkingView from '../ParkingView.vue'; +import { mount } from '@vue/test-utils' +import ParkingView from '../ParkingView.vue' describe('ParkingView', () => { it('renders properly', async () => { const wrapper = mount(ParkingView, { props: { id: 'some-id', - backend: 'http://localhost:1337', - }, - }); + backend: 'http://localhost:1337' + } + }) - expect(wrapper.find('h1').text()).toBe('Parking Stations'); + expect(wrapper.find('h1').text()).toBe('Parking Stations') - await wrapper.vm.$nextTick(); + await wrapper.vm.$nextTick() - expect(wrapper.find('.database-table').exists()).toBe(true); - }); -}); + expect(wrapper.find('.database-table').exists()).toBe(true) + }) +}) diff --git a/admin-interface/src/views/__tests__/RentalView.spec.js b/admin-interface/src/views/__tests__/RentalView.spec.js index 497f6b4..c7bb3da 100644 --- a/admin-interface/src/views/__tests__/RentalView.spec.js +++ b/admin-interface/src/views/__tests__/RentalView.spec.js @@ -1,20 +1,20 @@ import { describe, it, expect } from 'vitest' -import { mount } from '@vue/test-utils'; -import RentalView from '../RentalView.vue'; +import { mount } from '@vue/test-utils' +import RentalView from '../RentalView.vue' describe('RentalView', () => { it('renders properly', async () => { const wrapper = mount(RentalView, { props: { id: 'some-id', - backend: 'http://localhost:1337', - }, - }); + backend: 'http://localhost:1337' + } + }) - expect(wrapper.find('h1').text()).toBe('Rental Logs'); + expect(wrapper.find('h1').text()).toBe('Rental Logs') - await wrapper.vm.$nextTick(); + await wrapper.vm.$nextTick() - expect(wrapper.find('.database-table').exists()).toBe(true); - }); -}); + expect(wrapper.find('.database-table').exists()).toBe(true) + }) +}) diff --git a/admin-interface/src/views/__tests__/ScooterView.spec.js b/admin-interface/src/views/__tests__/ScooterView.spec.js index cc90f2f..2971c89 100644 --- a/admin-interface/src/views/__tests__/ScooterView.spec.js +++ b/admin-interface/src/views/__tests__/ScooterView.spec.js @@ -1,19 +1,19 @@ import { describe, it, expect } from 'vitest' -import { mount } from '@vue/test-utils'; -import ScooterView from '../ScooterView.vue'; +import { mount } from '@vue/test-utils' +import ScooterView from '../ScooterView.vue' describe('ScooterView', () => { it('renders properly', async () => { const wrapper = mount(ScooterView, { props: { - backend: 'http://localhost:1337', - }, - }); + backend: 'http://localhost:1337' + } + }) - expect(wrapper.find('h1').text()).toBe('Scooters'); + expect(wrapper.find('h1').text()).toBe('Scooters') - await wrapper.vm.$nextTick(); + await wrapper.vm.$nextTick() - expect(wrapper.find('.database-table').exists()).toBe(true); - }); -}); + expect(wrapper.find('.database-table').exists()).toBe(true) + }) +}) diff --git a/admin-interface/src/views/__tests__/SettingsView.spec.js b/admin-interface/src/views/__tests__/SettingsView.spec.js index 031968f..e1c4974 100644 --- a/admin-interface/src/views/__tests__/SettingsView.spec.js +++ b/admin-interface/src/views/__tests__/SettingsView.spec.js @@ -1,19 +1,19 @@ import { describe, it, expect } from 'vitest' -import { mount } from '@vue/test-utils'; -import SettingsView from '../SettingsView.vue'; +import { mount } from '@vue/test-utils' +import SettingsView from '../SettingsView.vue' describe('SettingsView', () => { it('renders properly', async () => { const wrapper = mount(SettingsView, { props: { - backend: 'http://localhost:1337', - }, - }); + backend: 'http://localhost:1337' + } + }) - expect(wrapper.find('h1').text()).toBe('Settings'); + expect(wrapper.find('h1').text()).toBe('Settings') - await wrapper.vm.$nextTick(); + await wrapper.vm.$nextTick() - expect(wrapper.find('.database-table').exists()).toBe(true); - }); -}); \ No newline at end of file + expect(wrapper.find('.database-table').exists()).toBe(true) + }) +}) diff --git a/admin-interface/src/views/__tests__/UserView.spec.js b/admin-interface/src/views/__tests__/UserView.spec.js index 63a6dc4..3018a08 100644 --- a/admin-interface/src/views/__tests__/UserView.spec.js +++ b/admin-interface/src/views/__tests__/UserView.spec.js @@ -1,19 +1,19 @@ import { describe, it, expect } from 'vitest' -import { mount } from '@vue/test-utils'; -import UserView from '../UserView.vue'; +import { mount } from '@vue/test-utils' +import UserView from '../UserView.vue' describe('UserView', () => { it('renders properly', async () => { const wrapper = mount(UserView, { props: { - backend: 'http://localhost:1337', - }, - }); + backend: 'http://localhost:1337' + } + }) - expect(wrapper.find('h1').text()).toBe('Users'); + expect(wrapper.find('h1').text()).toBe('Users') - await wrapper.vm.$nextTick(); + await wrapper.vm.$nextTick() - expect(wrapper.find('.database-table').exists()).toBe(true); - }); -}); \ No newline at end of file + expect(wrapper.find('.database-table').exists()).toBe(true) + }) +}) From 88d95f2041f401b7bcc644225d7f4acb8a284c41 Mon Sep 17 00:00:00 2001 From: JockeTS Date: Thu, 18 Jan 2024 12:58:22 +0100 Subject: [PATCH 17/20] updated trip-gen --- simulation/trip-generator.js | 10 +++++----- simulation/utils.js | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/simulation/trip-generator.js b/simulation/trip-generator.js index 360027b..a435f25 100644 --- a/simulation/trip-generator.js +++ b/simulation/trip-generator.js @@ -1,14 +1,14 @@ -const helper = require("./utils").helper; -const SQLiter = require("./utils").SQLiter; +const stationHelper = require("./utils").stationHelper; +const SQLiteHelper = require("./utils").SQLiteHelper; let requestsMade = 0; // Generate trips for all stations async function generateTrips() { - const stations = await helper.getAllStations(); + const stations = await stationHelper.getStations(); // Open connection to SQLite database - const dbc = SQLiter.getDBConnection(); + const dbc = SQLiteHelper.getDBConnection(); for (i = 0; i < stations.length; i++) { const currentStation = stations[i]; @@ -29,7 +29,7 @@ async function generateTrips() { } // Close connection to SQLite database - SQLiter.closeDBConnection(dbc); + SQLiteHelper.closeDBConnection(dbc); } // Generate a single trip diff --git a/simulation/utils.js b/simulation/utils.js index 7a582f3..ee4a423 100644 --- a/simulation/utils.js +++ b/simulation/utils.js @@ -350,4 +350,4 @@ const publicHelper = { } } -module.exports = { publicHelper }; +module.exports = { publicHelper, stationHelper, SQLiteHelper }; From 4c43feb510ca273911d25166e05b4046192257dd Mon Sep 17 00:00:00 2001 From: Robin Johannesson Date: Thu, 18 Jan 2024 21:41:22 +0100 Subject: [PATCH 18/20] Fixed customer app with API calls Committed by Robin Johannesson in development branch --- customer-app/src/main.js | 26 ++-- customer-app/src/utils.js | 58 ++++---- customer-app/src/views/AccountView.vue | 134 +++++++++++++----- customer-app/src/views/ActiveScooterView.vue | 31 ++-- customer-app/src/views/HomeView.vue | 8 +- customer-app/src/views/LoginView.vue | 48 ++++++- .../src/views/ScooterSelectionView.vue | 36 +++-- 7 files changed, 244 insertions(+), 97 deletions(-) diff --git a/customer-app/src/main.js b/customer-app/src/main.js index a2aff31..baf519b 100644 --- a/customer-app/src/main.js +++ b/customer-app/src/main.js @@ -1,23 +1,25 @@ import { createApp } from 'vue' -import { createPinia } from 'pinia' -import { createAuth0 } from '@auth0/auth0-vue' +// import { createPinia } from 'pinia' +// import { createAuth0 } from '@auth0/auth0-vue' import App from './App.vue' import router from './router' import './assets/tailwind.css' const app = createApp(App) -app.use(createPinia()) +// app.use(createPinia()) app.use(router) -app.use( - createAuth0({ - domain: "dev-yl46b5m8hfqpht5q.us.auth0.com", - clientId: "sD3sE4NcrhKampbYzR0wzpf3spojmDx5", - authorizationParams: { - redirect_uri: "http://localhost:1339/authCallback" - } - }) -) +// app.use( +// createAuth0({ +// domain: "dev-yl46b5m8hfqpht5q.us.auth0.com", +// clientId: "sD3sE4NcrhKampbYzR0wzpf3spojmDx5", +// authorizationParams: { +// redirect_uri: "http://localhost:1339/authCallback" +// } +// }) +// ) app.mount('#app') + +// localStorage.clear() diff --git a/customer-app/src/utils.js b/customer-app/src/utils.js index f4e85e3..16e28fa 100644 --- a/customer-app/src/utils.js +++ b/customer-app/src/utils.js @@ -1,5 +1,5 @@ -const BASE_URL = "http://localhost:1337"; -const API_KEY = "n7fov6opbjzqllsd53aduh1k1xcgx0mtqbi0" +const BASE_URL = `${location.protocol}//${location.hostname}:1337` +const API_KEY = "p6jzni39z780u50kd3p0d14sh7uekpby5qpz" export class utils { /** @@ -9,7 +9,7 @@ export class utils { */ static async getUser(email) { try { - const response = await fetch(`${this.backend}/v1/user/${email}`, { + const response = await fetch(`${BASE_URL}/v1/user/email/${email}`, { headers: { 'Content-Type': 'application/json', 'x-api-key': API_KEY, @@ -17,10 +17,23 @@ export class utils { }) const result = await response.json() - console.log("Result: ", result) + return result[0] - return result + } catch (err) { + console.error(err) + } + } + /** + * Tries to login the specific user + * @param email The user's email + * @param password The user's password + * @return A boolean, whether the user was logged in successfully. + */ + static async loginUser(email, password) { + try { + const user = await this.getUser(email) + return user.Password == password } catch (err) { console.error(err) } @@ -36,20 +49,21 @@ export class utils { * @param role The user's email * @return A message */ - static async updateUser(firstName, lastName, password, email, paymentType, role) { + static async updateUser(user) { try { const data = { - 'FirstName': firstName, - 'LastName': lastName, - 'Password': password, - 'Email': email, - 'PaymentType': paymentType, - 'Role': role, + 'FirstName': user.FirstName, + 'LastName': user.LastName, + 'Password': user.Password, + 'Email': user.Email, + 'AccountBalance': user.AccountBalance, + 'PaymentType': user.PaymentType, + 'Role': user.Role, } - const response = await fetch(`${BASE_URL}/v1/rental-log`, + const response = await fetch(`${BASE_URL}/v1/user/${user.UserID}`, { - method: 'POST', + method: 'PUT', headers: { 'Content-Type': 'application/json', 'x-api-key': API_KEY, @@ -97,7 +111,8 @@ export class utils { } }) - return await response.json() + const res = await response.json() + return res[0] } catch (err) { console.error(err) } @@ -151,13 +166,8 @@ export class utils { const data = { "ScooterID": scooterId, "UserID": userId, - "StartTime": new Date().toUTCString(), - // "EndTime": "2023-01-01T09:30:00", "StartStation": stationId, - // "EndStation": 2, - // "Cost": 10.00, - // "Paid": true - }; + } const response = await fetch(`${BASE_URL}/v1/rental-log`, { @@ -167,7 +177,7 @@ export class utils { 'x-api-key': API_KEY, }, body: JSON.stringify(data), - }); + }) return response.json() } @@ -178,7 +188,7 @@ export class utils { * @param endStation The end station's id (optional). * @return A message */ - static async getScooterRent(scooterId) { + static async getRentDetails(scooterId) { const response = await fetch(`${BASE_URL}/v1/rental-log/${scooterId}`, { method: 'GET', @@ -197,7 +207,7 @@ export class utils { * @param endStation The end station's id (optional). * @return A message */ - static async stopScooterRent(scooterId, endStation = null) { + static async stopRent(scooterId, endStation) { const data = { 'EndStation': endStation, } diff --git a/customer-app/src/views/AccountView.vue b/customer-app/src/views/AccountView.vue index d8d12c2..0c0cd89 100644 --- a/customer-app/src/views/AccountView.vue +++ b/customer-app/src/views/AccountView.vue @@ -9,44 +9,78 @@
-
-
-
+
+
+
-
+
-
+
-
+
-
+
-
+
+
@@ -102,7 +133,9 @@ import { ref, onMounted } from 'vue' import { utils } from '../utils.js' import SiteNavigation from '../components/SiteNavigation.vue' +import router from '../router' +const showPassword = ref(false) const firstName = ref("") const lastName = ref("") const email = ref("") @@ -111,21 +144,48 @@ const accountBalance = ref(0) const paymentType = ref("1") const role = ref("Customer") -onMounted(async() => { - if (localStorage.user) { - firstName.value = localStorage.user.FirstName - lastName.value = localStorage.user.LastName - password.value = localStorage.user.Password - email.value = localStorage.user.Email - accountBalance.value = localStorage.user.AccountBalance - paymentType.value = localStorage.user.PaymentType - role.value = localStorage.user.Role +onMounted(() => { + if (!localStorage.user) { + router.push({ name: 'login' }) + return } + + const user = JSON.parse(localStorage.user) + + firstName.value = user.FirstName + lastName.value = user.LastName + password.value = user.Password + email.value = user.Email + accountBalance.value = user.AccountBalance + paymentType.value = user.PaymentType + role.value = user.Role }) const updateAccount = async () => { - await utils.updateAccount(firstName.value, lastName.value, password.value, email.value, paymentType.value, role.value) + const user = JSON.parse(localStorage.user) + + user.FirstName = firstName.value + user.LastName = lastName.value + user.Password = password.value + user.Email = email.value + user.AccountBalance = accountBalance.value + user.PaymentType = paymentType.value + user.Role = role.value + + const wasSuccessful = await utils.updateUser(user) + + if (!wasSuccessful) { + alert("Could not update your account! Please try again in a few minutes.") + return + } + + localStorage.user = JSON.stringify(user) }; + +const signOut = () => { + localStorage.removeItem('user') + location.reload() +} diff --git a/customer-app/src/views/ActiveScooterView.vue b/customer-app/src/views/ActiveScooterView.vue index 546d31d..f12d1dc 100644 --- a/customer-app/src/views/ActiveScooterView.vue +++ b/customer-app/src/views/ActiveScooterView.vue @@ -24,6 +24,7 @@ import { ref, onMounted } from 'vue' import { utils } from '../utils.js' import ScooterImage from '../assets/img/Scooter.png' import CardItem from '../components/CardItem.vue' +import router from '../router' let id = ref("null") let status = ref("null") @@ -31,7 +32,12 @@ let speed = ref(0) let battery = ref(0) onMounted(async () => { - if (localStorage.scooterId) { + if (!localStorage.user) { + router.push({ name: 'login' }) + return + } + + if (localStorage.rentId && localStorage.scooterId) { try { const scooter = await utils.getScooter(localStorage.scooterId) @@ -40,12 +46,14 @@ onMounted(async () => { speed.value = scooter.Speed battery.value = scooter.Battery - // const rent = await utils.getScooterRent(localStorage.scooterId) - // rent.Paid - // rent.StartTime - // rent.EndTime - // rent.StartStation - // rent.Cost + const rentDetails = await utils.getRentDetails(localStorage.rentId) + console.log(rentDetails) + + // rentDetails.Paid + // rentDetails.StartTime + // rentDetails.EndTime + // rentDetails.StartStation + // rentDetails.Cost } catch (err) { console.error(err) @@ -56,9 +64,16 @@ onMounted(async () => { const returnScooter = async () => { if (localStorage.scooterId) { try { - await utils.stopScooterRent(localStorage.scooterId) + const wasSuccessful = await utils.stopRent(localStorage.scooterId, 5 /* stopStationId */) + + if (!wasSuccessful) { + alert("Could not return the scooter! Please try again in a few minutes.") + return + } localStorage.removeItem('scooterId') + localStorage.removeItem('rentId') + window.location.reload() } catch (err) { console.error(err) diff --git a/customer-app/src/views/HomeView.vue b/customer-app/src/views/HomeView.vue index 0269aba..4511991 100644 --- a/customer-app/src/views/HomeView.vue +++ b/customer-app/src/views/HomeView.vue @@ -9,11 +9,17 @@ import { ref, onMounted } from 'vue' import ScooterSelectionView from './ScooterSelectionView.vue' import ActiveScooterView from './ActiveScooterView.vue' import SiteNavigation from '../components/SiteNavigation.vue' +import router from '../router' let hasScooter = ref(false) onMounted(() => { - hasScooter.value = !!localStorage.scooterId + if (!localStorage.user) { + router.push({ name: 'login' }) + return + } + + hasScooter.value = !!localStorage.rentId }) diff --git a/customer-app/src/views/LoginView.vue b/customer-app/src/views/LoginView.vue index 2f18cfd..ce81aee 100644 --- a/customer-app/src/views/LoginView.vue +++ b/customer-app/src/views/LoginView.vue @@ -7,14 +7,37 @@
@@ -35,20 +58,31 @@ diff --git a/customer-app/src/views/ScooterSelectionView.vue b/customer-app/src/views/ScooterSelectionView.vue index 4b2e1df..f3a848d 100644 --- a/customer-app/src/views/ScooterSelectionView.vue +++ b/customer-app/src/views/ScooterSelectionView.vue @@ -4,7 +4,7 @@

- Welcome Back! + Welcome Back, {{ userName }}!

You have no active scooter in progress. @@ -44,10 +44,10 @@ @@ -69,21 +69,41 @@ From c67a82aa53047f9b98b1af35b0b04fb8fc9a5b1c Mon Sep 17 00:00:00 2001 From: Zachary Mooney Date: Fri, 19 Jan 2024 11:27:36 +0100 Subject: [PATCH 19/20] Update API documentation --- server/v1.html | 94 +++++++++++++++++++++++++----------------------- server/v1/API.md | 10 ++++-- 2 files changed, 56 insertions(+), 48 deletions(-) diff --git a/server/v1.html b/server/v1.html index 4039c77..98d6f80 100644 --- a/server/v1.html +++ b/server/v1.html @@ -87,26 +87,26 @@

Attributes

GET /v1/activity-type
     

Results:

[
-    {
+      {
         "ActivityTypeID": 1,
         "ActivityTypeDesc": "Parked"
-    },
-    {
+      },
+      {
         "ActivityTypeID": 2,
         "ActivityTypeDesc": "Maintenance"
-    },
-    {
+      },
+      {
         "ActivityTypeID": 3,
         "ActivityTypeDesc": "Charging"
-    },
-    {
+      },
+      {
         "ActivityTypeID": 4,
         "ActivityTypeDesc": "In use"
-    },
-    {
+      },
+      {
         "ActivityTypeID": 5,
         "ActivityTypeDesc": "Free Parking"
-    }
+      }
     ]
     

Get one entry

@@ -157,15 +157,18 @@

Attributes

[
         {
             "CityID": 1,
-            "CityName": "Stockholm"
+            "CityName": "Stockholm",
+            "CityPosition": "59.334591, 18.063240"
         },
         {
             "CityID": 2,
-            "CityName": "Gothenburg"
+            "CityName": "Gothenburg",
+            "CityPosition": "57.708870, 11.974560"
         },
         {
             "CityID": 3,
-            "CityName": "Malmö"
+            "CityName": "Malmö",
+            "CityPosition": "55.60587, 13.00073"
         }
     ]
     
@@ -177,6 +180,7 @@

Get one entry

{ "CityID": 1, "CityName": "Stockholm", + "CityPosition": "59.334591, 18.063240" } ] @@ -346,7 +350,7 @@

Attributes

GET /v1/rental-log
     

Results:

[
-    {
+      {
         "RentalLogID": 1,
         "Active": 1,
         "ScooterID": 179,
@@ -357,8 +361,8 @@ 

Attributes

"EndStation": null, "Cost": "10.00", "Paid": 0 - }, - { + }, + { "RentalLogID": 2, "Active": 1, "ScooterID": 184, @@ -369,8 +373,8 @@

Attributes

"EndStation": null, "Cost": "10.00", "Paid": 0 - }, - { + }, + { "RentalLogID": 3, "Active": 1, "ScooterID": 189, @@ -381,8 +385,8 @@

Attributes

"EndStation": null, "Cost": "10.00", "Paid": 0 - }, - { + }, + { "RentalLogID": 4, "Active": 1, "ScooterID": 194, @@ -393,8 +397,8 @@

Attributes

"EndStation": null, "Cost": "10.00", "Paid": 0 - }, - { + }, + { "RentalLogID": 5, "Active": 1, "ScooterID": 199, @@ -405,7 +409,7 @@

Attributes

"EndStation": null, "Cost": "10.00", "Paid": 0 - } + } ]

Get one entry

@@ -413,7 +417,7 @@

Get one entry

GET /v1/rental-log/:id
     

Results:

[
-    {
+      {
         "RentalLogID": 1,
         "Active": 1,
         "ScooterID": 179,
@@ -424,7 +428,7 @@ 

Get one entry

"EndStation": null, "Cost": "10.00", "Paid": 0 - } + } ]

Create a Rental

@@ -471,46 +475,46 @@

Attributes

GET /v1/scooter
     

Results:

[
-    {
+      {
         "ScooterID": 1,
         "Status": "Parked",
         "Location": "59.3293, 18.0686",
         "Speed": "0.00",
         "Battery": 61,
         "StationID": 1
-    },
-    {
+      },
+      {
         "ScooterID": 2,
         "Status": "Parked",
         "Location": "59.3293, 18.0686",
         "Speed": "0.00",
         "Battery": 55,
         "StationID": 1
-    },
-    {
+      },
+      {
         "ScooterID": 3,
         "Status": "Parked",
         "Location": "59.3293, 18.0686",
         "Speed": "0.00",
         "Battery": 18,
         "StationID": 1
-    },
-    {
+      },
+      {
         "ScooterID": 4,
         "Status": "Parked",
         "Location": "59.3293, 18.0686",
         "Speed": "0.00",
         "Battery": 45,
         "StationID": 1
-    },
-    {
+      },
+      {
         "ScooterID": 5,
         "Status": "Parked",
         "Location": "59.3293, 18.0686",
         "Speed": "0.00",
         "Battery": 41,
         "StationID": 1
-    }
+      }
     ]
     

Get one entry

@@ -930,26 +934,26 @@

Attributes

GET /v1/cost-structure
     

Results:

[
-    {
+      {
         "CostID": 1,
         "CostDesc": "Fixed",
         "CostAmount": "10.00"
-    },
-    {
+      },
+      {
         "CostID": 2,
         "CostDesc": "Time-based",
         "CostAmount": "3.00"
-    },
-    {
+      },
+      {
         "CostID": 3,
         "CostDesc": "Fine",
         "CostAmount": "10.00"
-    },
-    {
+      },
+      {
         "CostID": 4,
         "CostDesc": "Discount",
         "CostAmount": "-5.00"
-    }
+      }
     ]
     

Get one entry

@@ -957,11 +961,11 @@

Get one entry

GET /v1/cost-structure/:id
     

Results:

[
-    {
+      {
         "CostID": 1,
         "CostDesc": "Fixed",
         "CostAmount": "10.00"
-    }
+      }
     ]
     

Create a new entry

diff --git a/server/v1/API.md b/server/v1/API.md index ae004c9..de41007 100644 --- a/server/v1/API.md +++ b/server/v1/API.md @@ -171,15 +171,18 @@ Results: [ { "CityID": 1, - "CityName": "Stockholm" + "CityName": "Stockholm", + "CityPosition": "59.334591, 18.063240" }, { "CityID": 2, - "CityName": "Gothenburg" + "CityName": "Gothenburg", + "CityPosition": "57.708870, 11.974560" }, { "CityID": 3, - "CityName": "Malmö" + "CityName": "Malmö", + "CityPosition": "55.60587, 13.00073" } ] ``` @@ -199,6 +202,7 @@ Results: { "CityID": 1, "CityName": "Stockholm", + "CityPosition": "59.334591, 18.063240" } ] ``` From b07b0d60d8e475e9172c02a256ef918cfaf279b9 Mon Sep 17 00:00:00 2001 From: JockeTS Date: Fri, 19 Jan 2024 11:44:23 +0100 Subject: [PATCH 20/20] free parked --- simulation/SimulatedClient.js | 14 +++++-- simulation/simulator.js | 11 +++-- simulation/utils.js | 75 ++++++++++++++++++++++++++++++++++- 3 files changed, 89 insertions(+), 11 deletions(-) diff --git a/simulation/SimulatedClient.js b/simulation/SimulatedClient.js index 418d5bb..8adc2ea 100644 --- a/simulation/SimulatedClient.js +++ b/simulation/SimulatedClient.js @@ -38,10 +38,16 @@ class SimulatedClient { async useScooter() { console.log(`User ${this.user.FirstName} with ID ${this.user.UserID} using Scooter with ID ${this.scooter.ScooterID}!`); - this.trip = await publicHelper.getRandomMatchingTrip(this.scooter.Location.replace(/\s/g, "")); - + if (this.scooter.Status != "Free Parking") { + this.trip = await publicHelper.getRandomMatchingTrip(this.scooter.Location.replace(/\s/g, "")); + } else { + this.trip = await publicHelper.generateFreeTrip(this.scooter.Location.replace(/\s/g, "")); + } + if (this.trip) { this.intervalID = setInterval(() => this.moveScooter(), SimulatedClient.waypointInterval * 1000); + } else { + console.log("No trip available."); } } @@ -85,7 +91,7 @@ class SimulatedClient { publicHelper.updateScooter(this.scooter); } - console.log("Moving scooter to: " + JSON.stringify(this.scooter.Location)); + // console.log("Moving scooter to: " + JSON.stringify(this.scooter.Location)); this.tripIndex++; } @@ -94,7 +100,7 @@ class SimulatedClient { // Return scooter async returnScooter() { SimulatedClient.numClients--; - + console.log("Returning a scooter!"); await publicHelper.stopRent(this.rentalLogID, this.user, this.scooter); diff --git a/simulation/simulator.js b/simulation/simulator.js index 9fbe6c8..a42abac 100644 --- a/simulation/simulator.js +++ b/simulation/simulator.js @@ -2,19 +2,18 @@ const publicHelper = require("./utils").publicHelper; const SC = require("./SimulatedClient").SimulatedClient; // Max number of clients at any given time -const maxClients = 1000; +const maxClients = 500; // Time (in seconds) between new clients being activated -const clientInterval = 1; +const clientInterval = 3; // Time (in seconds) it takes for a scooter to move from one waypoint to another const waypointInterval = 1; // Number of waypoints between a scooter's properties being updated in database -const updateInterval = 1; +const updateInterval = 3; async function startSimulator() { - SC.waypointInterval = waypointInterval; SC.updateInterval = updateInterval; @@ -27,10 +26,10 @@ async function startSimulator() { async function createNewClient() { const user = await publicHelper.getRandomAvailableUser(); - console.log(user); + // console.log(user); const scooter = await publicHelper.getRandomAvailableScooter(); - console.log(scooter); + // console.log(scooter); new SC(user, scooter); } diff --git a/simulation/utils.js b/simulation/utils.js index 05ab6ee..95ad94a 100644 --- a/simulation/utils.js +++ b/simulation/utils.js @@ -84,6 +84,7 @@ const rentHelper = { const stationHelper = { stations: [], + requestsMade: 0, async initStations() { if (this.stations.length === 0) { @@ -107,6 +108,72 @@ const stationHelper = { return station.StationID; } } + }, + + // Get a trip to a random station in same city as freely parked scooter + async getTripToStationInCity(location) { + await this.initStations(); + + if (this.requestsMade >= 40) { + return; + } + + let index = publicHelper._getRndInteger(0, this.stations.length - 1); + let station = this.stations[index]; + + while (station.Location.charAt(1) != location.charAt(1)) { + index = publicHelper._getRndInteger(0, this.stations.length - 1); + station = this.stations[index]; + } + + const waypoints = await this.fetchWaypoints(location, station.Location); + + const trip = { + Origin: location, + Destination: station.Location, + Waypoints: waypoints + }; + + return trip; + }, + + // Fetch waypoints between origin and destination from API + async fetchWaypoints(origin, destination) { + const url = "https://api.openrouteservice.org/v2/directions/cycling-electric" + const apiKey = "5b3ce3597851110001cf624820729cd7892e4b7488a775715f073283"; + + const originArr = origin.split(","); + const destinationArr = destination.split(","); + + const response = await fetch(`${url}?api_key=${apiKey}&start=${originArr[1]},${originArr[0]}&end=${destinationArr[1]},${destinationArr[0]}`); + + this.requestsMade++; + + if (this.requestsMade === 40) { + const timeoutID = setTimeout(function() { + this.requestsMade = 0; + clearTimeout(timeoutID); + }.bind(this), 60 * 1000); + } + + const obj = await response.json(); + + const waypoints = obj.features[0].geometry.coordinates; + + this.switchLatLon(waypoints); + + return waypoints; + }, + + // Swap the order of lat and lon in coordinates + switchLatLon(waypoints) { + for (const waypoint of waypoints) { + const lat = waypoint[1]; + const lon = waypoint[0]; + + waypoint[0] = lat; + waypoint[1] = lon; + } } } @@ -277,7 +344,7 @@ const publicHelper = { let index = this._getRndInteger(0, scooters.length - 1); - while (scooters[index].Status != "Parked") { + while (scooters[index].Status === "In Use") { index = this._getRndInteger(0, scooters.length - 1); } @@ -316,6 +383,12 @@ const publicHelper = { return selectedTrip; }, + async generateFreeTrip(location) { + const trip = await stationHelper.getTripToStationInCity(location); + + return trip; + }, + async startRent(user, scooter) { // Temporary? stationHelper.initStations();