Compare commits

...

3 commits

13 changed files with 185 additions and 57 deletions

41
LICENSE Normal file
View file

@ -0,0 +1,41 @@
Copyright (c) 2025 Spencer Powell & Levi Lesches
At time of writing this software is not licensed under a permissive license.
If you are Professor Steven Moore of Binghamton University you may access the code as it exists on May 5th 2025 under an MIT license for the purposes of grading.
A copy of the MIT license can be found at https://choosealicense.com/licenses/mit/ or at the bottom of this file.
If you are anyone else you ARE NOT granted permission to read, use, modify, copy, merge, publich, distribute, sublicense or sell the software or any other rights to this software.
Versions of this software written/published after May 5th 2025 may fall under a different license.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
-----------------------------------------------------
Example of MIT License THIS IS NOT THE LICENSE THIS SOFTWARE FALLS UNDER barring relicensing.
Copyright (c) [year] [fullname]
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View file

@ -1,47 +1,60 @@
[![Review Assignment Due Date](https://classroom.github.com/assets/deadline-readme-button-22041afd0340ce965d47ae6ef1cefeee28c7c493a6346c4f15d667ab976d596c.svg)](https://classroom.github.com/a/vfKrPwQS)
# << Project Title >>
# Binghamton Better Bus (BBB) v2
## CS 445 Final Project
### Spring, 2025
### Team: << team name >>
### Team: Team 4
- Spencer Powell
- Levi Lesches
## Getting Started
<<One paragraph of project description goes here>>
This project is a website which allows for picking a source and destination and getting the ideal bus route between the 2 given static information.
### Roadmap
<<
A list of features, function or non-functional, you would like to add in the future if you had time, i.e. Phase 2 stuff
- [ ] Add Changelog
- [ ] Add back to top links
- [ ] Add Additional Templates w/ Examples
- [ ] Add "components" document to easily copy & paste sections of the readme
>>
- [ ] Make use of time/direction information available in static scheduling information
- [ ] Place our hardware on OCCT buses to remove ETA Spot dependence/legal question mark
- [ ] Design/build hardware
- Keyword reminder for mobile data: IoT data plan and/or M2M
- [ ] Negotiate placing hardware on OCCT buses
- [ ] Chat with BCT about getting their live bus info
- [ ] Use machine learning to predict bus locations based on current position, current time of day and current route,
## SRS
[doc](https://docs.google.com/document/d/1kSWMxsK0NakhvHRQnNx0wRlL6wDgYGO-tA7JB_4qldE/edit?usp=sharing)
### Prerequisites
* [Docker](https://www.docker.com/)
* <<any additional software. Be specific about versions.>>
* Docker Compose
* [Just](https://github.com/casey/just)
### Installing
<<
A step by step series of examples that tell you how to get a development env running
Clearly outline each step and repeat until the environment is set up.
End with an example of getting some output from the system, such as a menu or prompt
>>
cd into the `src` directory and run `just setup` then run `docker-compose build`.
To run just run `docker-compose up` in the `src` directory, the site will be up on `localhost:8080`
## Built With
<< list all frameworks and modules used here >>
* [requests](https://docs.python-requests.org/en/latest/user/quickstart/#make-a-request) - request for humans
* [Deno](https://deno.com/)
- [Acorn](https://oakserver.org/acorn)
* [Dart](https://dart.dev/)
* [Flutter](https://flutter.dev/)
- Google maps
* [Caddy](https://caddyserver.com/)
## License
<< Add a [license](https://choosealicense.com/) >>
DIY license written out which grants MIT rights to professor moore for the version of this submitted for grading and no rights to anyone else.
## Acknowledgments
* Hat tip to anyone whose code was used
* Inspiration
* etc
* Claude and chatGPT were used for the creation of scripts for certain rote data conversion tasks
* This project would not exist with the data it has if not for prior instances of attempts to make this idea by US, of particular note is the usage of GTFS data which was only learned of in a prior attempt with Lucy Loerker

BIN
demo.mp4 Normal file

Binary file not shown.

13
src/Justfile Normal file
View file

@ -0,0 +1,13 @@
setup:
# this is a hack that is done due to a lack of communication
# towards the end of this project
# a slightly better hack could be done which avoids this but I
# don't wanna write things to work that way
cp -r client shared/client-dir
cp -r shared client/shared-dir
cp -r server/data shared/server-data
cp pubspec.yaml client/root-pubspec.yaml
cp pubspec.yaml shared/root-pubspec.yaml
clean:
rm -rf client/root-pubspec.yaml shared/root-pubspec.yaml shared/client-dir client/shared-dir shared/server-data

View file

@ -45,3 +45,6 @@ app.*.map.json
/android/app/debug
/android/app/profile
/android/app/release
shared-dir
root-pubspec.yaml

View file

@ -20,11 +20,15 @@ RUN flutter upgrade
RUN flutter doctor
COPY ./ /client/
COPY root-pubspec.yaml /client/pubspec.yaml
COPY ./shared-dir /client/shared
COPY ./ /client/client
WORKDIR /client/client
RUN flutter build web --dart-define-from-file=.env
WORKDIR /client/build/web
WORKDIR /client/client/build/web
EXPOSE 80/tcp

View file

@ -23,7 +23,7 @@ class ApiService extends Service {
required Coordinates start,
required Coordinates end,
}) async {
final uri = _base.resolve("/path").replace(
final uri = Uri.parse("/tmp-api/path").replace(
queryParameters: {
"start_lat": start.lat.toString(),
"start_lon": start.long.toString(),

View file

@ -6,12 +6,17 @@ services:
depends_on:
- server
- client
- hack
restart: unless-stopped
client:
build: ./client
restart: unless-stopped
hack:
build: ./shared
restart: unless-stopped
server:
build: ./server
environment:
@ -19,29 +24,30 @@ services:
#ports:
# - "127.0.0.1:8080:80"
restart: unless-stopped
depends_on:
neo4j:
condition: service_healthy
neo4j:
image: neo4j:latest
volumes:
- neo4jconfig:/config
- neo4jdata:/data
- neo4jplugins:/plugins
environment:
# neo4j isn't exposed to the internet so having the password checked into version control doesn't matter
- NEO4J_AUTH=neo4j/your_password
ports:
# useful for dev
- "127.0.0.1:7474:7474"
- "127.0.0.1:7687:7687"
restart: unless-stopped
healthcheck:
test: wget http://localhost:7474 || exit 1
interval: 1s
timeout: 10s
retries: 20
start_period: 3s
# depends_on:
# neo4j:
# condition: service_healthy
#neo4j:
# image: neo4j:latest
# volumes:
# - neo4jconfig:/config
# - neo4jdata:/data
# - neo4jplugins:/plugins
# environment:
# # neo4j isn't exposed to the internet so having the password checked into version control doesn't matter
# - NEO4J_AUTH=neo4j/your_password
# ports:
# # useful for dev
# - "127.0.0.1:7474:7474"
# - "127.0.0.1:7687:7687"
# restart: unless-stopped
# healthcheck:
# test: wget http://localhost:7474 || exit 1
# interval: 1s
# timeout: 10s
# retries: 20
# start_period: 3s
volumes:
neo4jconfig:

View file

@ -3,4 +3,7 @@
handle_path /api/* {
reverse_proxy server:80
}
handle_path /tmp-api/* {
reverse_proxy hack:8001
}
}

View file

@ -24,13 +24,13 @@ const substitute_base_name = substitute_base_name_.bind(
const { hostname, port } = { hostname: "0.0.0.0", port: 80 };
const neo4jHost = usingDocker ? "neo4j" : "127.0.0.1"; // localhost does NOT work
const graph_driver = neo4j.driver(
`neo4j://${neo4jHost}:7687`,
neo4j.auth.basic("neo4j", "your_password"),
);
console.log("initializing graph with static data");
await graph_setup(graph_driver);
console.log("graph initialization complete");
//const graph_driver = neo4j.driver(
// `neo4j://${neo4jHost}:7687`,
// neo4j.auth.basic("neo4j", "your_password"),
//);
//console.log("initializing graph with static data");
//await graph_setup(graph_driver);
//console.log("graph initialization complete");
const db = new DatabaseSync(":memory:");
db_setup(db);

View file

@ -2,5 +2,8 @@
# Created by `dart pub`
.dart_tool/
pubspec.lock
client-dir
server-data
root-pubspec.yaml
path.log
notes.md

42
src/shared/Dockerfile Normal file
View file

@ -0,0 +1,42 @@
FROM alpine:3.21
RUN mkdir /client
RUN apk add bash curl file git unzip which zip gcompat wget tar xz
#ENTRYPOINT bash
WORKDIR /client
RUN wget -O flutter.tar.xz https://storage.googleapis.com/flutter_infra_release/releases/stable/linux/flutter_linux_3.29.0-stable.tar.xz
RUN tar xf flutter.tar.xz
ENV PATH="/client/flutter/bin/:${PATH}"
RUN git config --global --add safe.directory /client/flutter
RUN flutter upgrade
RUN flutter doctor
COPY root-pubspec.yaml /client/pubspec.yaml
COPY ./ /client/shared
RUN mkdir /client/client
COPY ./client-dir/* /client/client
RUN mkdir /client/server
COPY server-data /client/server/data
RUN dart pub get
WORKDIR /client/shared
EXPOSE 80/tcp
CMD ["dart", "bin/server.dart"]

View file

@ -20,6 +20,6 @@ void main() async {
router.get("/path", handlers.getPath);
router.get("/stops", handlers.getStops);
router.get("/routes", handlers.getRoutes);
await io.serve(router.call, "localhost", 8001);
print("Listening on localhost:8001");
await io.serve(router.call, "0.0.0.0", 8001);
print("Listening on 0.0.0.0:8001");
}