# Project export: SlugSpot

This document was generated by HackStack to give an AI agent context about a hackathon project. Sections are labeled with their provenance; content marked as truncated was cut to keep this document small.

## Project metadata

- Hackathon: CruzHacks 2024
- Tagline: Hate leaving early and still not being on time all because you can't find anywhere to park? Meet SlugSpot, the app revolutionizing campus parking. Say goodbye to parking woes and hello to punctuality.
- Devpost: https://devpost.com/software/slug-spot
- GitHub: https://github.com/zm2002/dubiousscoob
- Demo: https://drive.google.com/file/d/1zSWql3ZrDdOr9AnOSTTQ3Rf8mVle9RDx/view?usp=sharing
- Video: https://www.youtube.com/embed/lqpig52Iyf4?enablejsapi=1&hl=en_US&rel=0&start=&version=3&wmode=transparent
- Team: 3 GitHub contributor(s) — Rylee Bao (29 commits), merrickfort (13 commits), Animesh Tiwary (12 commits)

## Devpost submission (written by the team)

### Inspiration

. Many of us have experienced the frustration of driving for hours, only to find that there's no available parking. This issue is particularly acute on campus during busy periods, such as class times, making parking a challenge. For those living off-campus and relying solely on driving to fulfill their commitments, this often leads to tardiness due to the scarcity of accessible parking spots. Moreover, there is an absence of mobile solutions in most cities to update drivers on parking garage availability. This is leading to traffic congestion, contributing to unnecessary fuel consumption and heightened driver irritation. The endeavor to ease this process inspired us to create SlugSpot.

### What it does

. SlugSpot tracks real-time availability in parking garages near your destination, delivering instant updates directly to your phone. The app also analyzes parking patterns to recommend the best times for hassle-free parking allowing you to arrive at your destination on time.

### How we built it

. SlugSpot calculates the number of parking spots available through images captured on a video camera. To develop SlugSpot, we used React-Native to build our user interface and FireBase to create our database and backend. We built our car detection software using open-cv. In order to observe the output of our application, we used Expo Go. Figma served as our go-to way to create our designs and GitHub was our main resource to store and share files.

### Challenges we ran into

. Creating an API that would communicate between Firebase and our programs is the most challenging part of our project. Our project utilizes several different languages that each require different methods of query to access the data. Creating a React Native app was a first for all of us and posed its own challenges.

### Accomplishments we're proud of

. We are very proud of how we managed to ensure scalability if we wanted to continue this project after the hackathon, and we feel our efforts rewarded us with a very developed and professional full-stack project that could benefit our community.

### What we learned

. Through the course of this project, our team learned a whole new language in the form of React-Native. React-Native is a framework that allows you to build mobile applications natively across multiple platforms. Learning React-Native was a challenge. Furthermore, collaborating through git and Liveshare on VScode presented its own challenges. We spent a lot of time learning workflow prioritizing to ensure that when each member finished, we could integrate our programs together quickly and without pain. Through a lot of research and collective debugging, we were able to tie a lot of different programs together and create a project we are proud of.

### What's next

for Slug Spot. Sleep, and then we’ve already discussed creating our own hardware for real-world testing around campus. This would be a camera microcomputer machine that we could mount in several parking lots. This would involve purchasing equipment, designing parts, and a lot more experimentation than what we have done so far.

## README (from the GitHub repository)

## Installation
`npm install`
- You must have Expo and React Native to be able to run this application!

## Project Breakdown
- These project contains two main components. The Car vision scanner `car_counter` and the React Native app "SlugSpot" in the `ParkingTrackerApp` directory. 

## Car Scanner /  OpenCV application
- To run the OpenCV application `car_counter`, you must be on Python3 and have the [weights](https://drive.google.com/file/d/1zSWql3ZrDdOr9AnOSTTQ3Rf8mVle9RDx/view?usp=sharing) file installed, which should be placed under the `dnn_model` directory. To be able to run the project, you can simulate two parking areas at UCSC by running `python3 EastRemote.py` or `python3 WestRemote.py` on different machines!

## React Native App
- To run the main UI interface "SlugSpot", you must be under the `ParkingTrackerApp` directory. You can run the application by doing `npx export run`. Our main component `App.js` is responsible for rendering all the subcomponents with proper state management.
- Additionally, we have created additional service.js files for ease of data retrieval from Firebase. Feel free to add your own data and make your own requests by calling these files `FirebaseService.js` and `parkingDataConversion.js`. (Very scalabale as we used the same file for both our Main Page and Graph data retrieval!)
- You can run the app by doing `npx expo start`


## Inspiration 
Many of us have experienced the frustration of driving for hours, only to find that there's no available parking. This issue is particularly acute on campus during busy periods, such as class times, making parking a challenge. For those living off-campus and relying solely on driving to fulfill their commitments, this often leads to tardiness due to the scarcity of accessible parking spots. Moreover, there is an absence of mobile solutions in most cities to update drivers on parking garage availability. This is leading to traffic congestion, contributing to unnecessary fuel consumption and heightened driver irritation. The endeavor to ease this process inspired us to create SlugSpot.  
  
## What it does 
SlugSpot tracks real-time availability in parking garages near your destination, delivering instant updates directly to your phone. The app also analyzes parking patterns to recommend the best times for hassle-free parking allowing you to arrive at your destination on time.  
  
## How we built it 
SlugSpot calculates the number of parking spots available through images captured on a video camera. To develop SlugSpot, we used React-Native to build our user interface and FireBase to create our database and backend. We built our car detection software using open-cv. In order to observe the output of our application, we used Expo Go. Figma served as our go-to way to create our designs and GitHub was our main resource to store and share files.    
  
## Challenges we ran into  
Creating an API that would communicate between Firebase and our programs is the most challenging part of our project. Our project utilizes several different languages that each require different methods of query to access the data. Creating a React Native app was a first for all of us and posed its own challenges.  
  
## Accomplishments that we're proud of 
We are very proud of how we managed to ensure scalability if we wanted to continue this project after the hackathon, and we feel our efforts rewarded us with a very developed and professional full-stack project that could benefit our community.  
  
## What we learned 
Through the course of this project, our team learned a whole new language in the form of React-Native. React-Native is a framework that allows you to build mobile applications natively across multiple platforms. Learning React-Native was a challenge. Furthermore, collaborating through git and Liveshare on VScode presented its own challenges. We spent a lot of time learning workflow prioritizing to ensure that when each member finished, we could integrate our programs together quickly and without pain. Through a lot of research and collective debugging, we were able to tie a lot of different programs together and create a project we are proud of.  
  
## What's next for PyLot 
Sleep, and then we’ve already discussed creating our own hardware for real-world testing around campus. This would be a camera microcomputer machine that we could mount in several parking lots. This would involve purchasing equipment, designing parts, and a lot more experimentation than what we have done so far.

Made by:
- Zahra (ML Engineer, Front-end, UI/UX)
- Rylee (Front-end, UI/UX, Back-end)
- Animesh (API Integration, Back-end, Data Analytics)
- Merrick (API Integration, Back-end, Data Analytics, ML Engineer)


## Detected evidence (automated analysis)

Indexed codebase: 19 recognized source files, 55 KB.
- Firebase (technology) — detected in the code
- JavaScript (language) — detected in the code
- Python (language) — detected in the code
- React (technology) — detected in the code

## Codebase structure (from repository index)

### Files (29 of 29)

```
car_counter/bananaspot-249e7-firebase-adminsdk-29dme-85861daf07.json
car_counter/EastRemote.py
car_counter/source_code/.DS_Store
car_counter/source_code/dnn_model/.DS_Store
car_counter/source_code/dnn_model/yolov4.cfg
car_counter/source_code/vehicle_counting.py
car_counter/source_code/vehicle_detector.py
car_counter/WestRemote.py
package.json
ParkingTrackerApp/.gitignore
ParkingTrackerApp/App.js
ParkingTrackerApp/app.json
ParkingTrackerApp/assets/Montserrat/OFL.txt
ParkingTrackerApp/assets/Montserrat/README.txt
ParkingTrackerApp/babel.config.js
ParkingTrackerApp/firebaseConfig.js
ParkingTrackerApp/FirebaseService.js
ParkingTrackerApp/package.json
ParkingTrackerApp/Pages/AppBar.jsx
ParkingTrackerApp/Pages/ArtLot.jsx
ParkingTrackerApp/Pages/EastRemote.jsx
ParkingTrackerApp/Pages/Loading.jsx
ParkingTrackerApp/Pages/MainPage.jsx
ParkingTrackerApp/Pages/WestCore.jsx
ParkingTrackerApp/Pages/WestRemote.jsx
ParkingTrackerApp/parkingDataConversion.js
README.md
server.py
test.py
```

### Dependencies

- package.json: @expo/webpack-config@^19.0.1, firebase@^10.7.2, react-dom@^18.2.0, react-native-web@^0.19.10
- ParkingTrackerApp/package.json: @babel/core@^7.20.0, @react-native-firebase/app@^18.7.3, @react-native-firebase/database@^18.7.3, @react-navigation/native@^6.1.9, @react-navigation/native-stack@^6.9.17, @react-navigation/stack@^6.3.20, expo@~50.0.2, expo-font@^11.10.2, expo-linear-gradient@^12.7.0, expo-splash-screen@^0.26.3, expo-status-bar@~1.11.1, firebase@^10.7.2, install@^0.13.0, npm@^10.3.0, react@18.2.0, react-native@0.73.2, react-native-chart-kit@^6.12.0, react-native-maps@^1.9.1, react-native-safe-area-context@^4.8.2, react-native-screens@^3.29.0, react-native-svg@^14.1.0, react-native-swipe-up-down@^1.2.0, react-navigation@^5.0.0

### Recent commits (newest first)

- Update README.md
- Update README.md
- Update README.md
- Update README.md
- final maybe?
- Fixed labels dates and now displays max parking spots available
- East now Working
- West remote
- East Remote Clean
- Merge remote-tracking branch 'origin/chart-updates-550am' into ui-501am
- push
- graph is working for artlot
- art list working graphing
- Cleaned up pages pt32139391
- stuff
- Headers cleaned up
- counts are fixed
- Marker Pins
- loading page with firebase integration working
- Merge branch 'integrate-frontend-firebase' into ui-501am

## Key source files (fetched from GitHub, selected and truncated for size)

### package.json

```
{
  "dependencies": {
    "@expo/webpack-config": "^19.0.1",
    "firebase": "^10.7.2",
    "react-dom": "^18.2.0",
    "react-native-web": "^0.19.10"
  }
}

```

### ParkingTrackerApp/package.json

```
{
  "name": "parkingtrackerapp",
  "version": "1.0.0",
  "main": "node_modules/expo/AppEntry.js",
  "scripts": {
    "start": "expo start",
    "android": "expo start --android",
    "ios": "expo start --ios",
    "web": "expo start --web"
  },
  "dependencies": {
    "@react-native-firebase/app": "^18.7.3",
    "@react-native-firebase/database": "^18.7.3",
    "@react-navigation/native": "^6.1.9",
    "@react-navigation/native-stack": "^6.9.17",
    "@react-navigation/stack": "^6.3.20",
    "expo": "~50.0.2",
    "expo-font": "^11.10.2",
    "expo-linear-gradient": "^12.7.0",
    "expo-splash-screen": "^0.26.3",
    "expo-status-bar": "~1.11.1",
    "firebase": "^10.7.2",
    "install": "^0.13.0",
    "npm": "^10.3.0",
    "react": "18.2.0",
    "react-native": "0.73.2",
    "react-native-chart-kit": "^6.12.0",
    "react-native-maps": "^1.9.1",
    "react-native-safe-area-context": "^4.8.2",
    "react-native-screens": "^3.29.0",
    "react-native-svg": "^14.1.0",
    "react-native-swipe-up-down": "^1.2.0",
    "react-navigation": "^5.0.0"
  },
  "devDependencies": {
    "@babel/core": "^7.20.0"
  },
  "private": true
}

```

### server.py

```python
from flask import Flask, jsonify
# <call custom parking API here>

app = Flask(__name__)

@app.route('/')
def getCarData():
    return "Welcome to the Banana Spot app!!!"

@app.route('/get_parking_data', methods=['GET'])
def get_parking_data():
    # Your OpenCV logic to get the parking data
    cars_entering = 10  # Replace with actual data
    cars_leaving = 5    # Replace with actual data

    data = {'cars_entering': cars_entering, 'cars_leaving': cars_leaving}
    return jsonify(data)

if __name__ == '__main__':
    app.run(debug=True)

```

### ParkingTrackerApp/App.js

```javascript
import { StatusBar } from 'expo-status-bar';
import { useState, useEffect } from 'react';
import { Image } from 'react-native';
import React from 'react';
import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import MainPage from './Pages/MainPage';
import EastRemotePage from './Pages/EastRemote';
import WestRemotePage from './Pages/WestRemote';
import LoadingScreen from './Pages/Loading';
import ArtsLotPage from './Pages/ArtLot';
import WestCorePage from './Pages/WestCore';
import slugLogo from './slugLogo.png'; // Adjust the path to your image accordingly
// import EastRemoteSwipe from './Pages/EastRemoteSwipe';

// Firebase imports
import { convertJsonToLocationsArray } from './parkingDataConversion';
import { fetchDataFromFirebase } from './FirebaseService';

import ProgressBar from './Pages/AppBar';
// import WestRemotePage from './Pages/WestRemote';
// import ArtLotPage from './Pages/ArtLot';

// Import other location pages here

const Stack = createNativeStackNavigator();

export default function App() {
  const [data, setData] = useState(null);
  const [graphingData, setGraphingData] = useState({});


  useEffect(() => {
    const cleanupFunction = fetchDataFromFirebase(setData, setGraphingData);

    // Cleanup the listener when the component unmounts
    return cleanupFunction;
  }, []);

  const bruh = graphingData;
  console.log(bruh);

  const locationsArray = data ? convertJsonToLocationsArray(data) : [];
  const eastRemoteData = locationsArray.find(location => location.name === "East Remote");
  const westRemoteData = locationsArray.find(location => location.name === "West Remote");
  const artsLotData = locationsArray.find(location => location.name === "Arts Lot");
  const westCoreData = locationsArray.find(location => location.name === "West Core");

  console.log("west remote:")
  console.log(graphingData['West Remote'])

  return (
    <NavigationContainer>
      <Stack.Navigator initialRouteName="Main" screenOptions={{
      headerStyle: {
        backgroundColor: '#000', // Set your header color here
        color: '#fff',
      },
      headerTitleStyle: {
        fontWeight: 'bold',
        fontSize: 25,
      },
      headerTintColor: 'white',
      headerBackTitleVisible: false,
      headerRight: () => (
        <Image
          source={slugLogo}
          style={{
            width: 100,
            height: 100,
            position: 'absolute', 
            top: -45,
            right: -30,
            zIndex: 10,
          }} // Adjust the size and margin as needed
        />
      ),
      }}>
        <Stack.Screen
          name="Loading Screen"
          options={{ headerShown: false }}
        >
          {(props) => {
            return <LoadingScreen {...props} locationsArray={locationsArray} />;
          }}
        </Stack.Screen>

        <Stack.Screen 
          name="EastRemote" 
          options={{ title: 'East Remote', headerBackTitle: null }}
        >
          {(props) => {
            return <EastRemotePage {...props} parkingData={eastRemoteData} graphingData={graphingData['East Remote']}/>;
          }}
        </Stack.Screen>

        <Stack.Screen 
          name="WestRemote" 
          options={{ title: 'West Remote', headerBackTitle: null }}
        >
          {(props) => {
            return <WestRemotePage {...props} parkingData={westRemoteData} graphingData={graphingData['West Remote']}/>;
          }}
        </Stack.Screen>

        <Stack.Screen 
          name="ArtsLot" 
          options={{ title: 'Art Lot' }}
        >
          {(props) => {
            return <ArtsLotPage {...props} parkingData={artsLotData} graphingData={graphingData['Arts Lot']} />;
          }}
        </Stack.Screen>

        <Stack.Screen 
          name="WestCore" 
          options={{ title: 'West Core' }}
        >
          {(props) => {
            return <WestCorePage {...props} parkingData={westCoreData} graphingData={graphingData['West Core']}/>;
          }}
        </Stack.Screen>

      </Stack.Navigator>
      <StatusBar style="auto" />
    </NavigationContainer>
  );
}
```

### test.py

```python
import requests
import json

url = 'https://bananaspot-249e7-default-rtdb.firebaseio.com/'

while True:
    response = requests.put(f'{url}/West_Core/data.json', json.dumps({'West_Core': '10'}))
    print(response.json())
# response = requests.delete(f'{url}/path/to/data.json')

```

### ParkingTrackerApp/babel.config.js

```javascript
module.exports = function(api) {
  api.cache(true);
  return {
    presets: ['babel-preset-expo'],
  };
};

```

### ParkingTrackerApp/parkingDataConversion.js

```javascript
export const convertJsonToLocationsArray = (jsonData) => {
    const locations = [];

    // console.log("INSIDE converJsonToLocationsArray!...");
    // console.log(jsonData);
  
    for (const [locationName, locationData] of Object.entries(jsonData)) {
      const { cars, time } = locationData.data;
      const formattedLocation = {
        name: locationName.replace(/_/g, ' '), // Replace underscores with spaces
        cars,
        time,
      };
      locations.push(formattedLocation);
    }
  
    return locations;
  };
  
```

### ParkingTrackerApp/firebaseConfig.js

```javascript
import firebase from 'firebase';
// Import the functions you need from the SDKs you need
import { initializeApp } from "firebase/app";
import { getAnalytics } from "firebase/analytics";
// TODO: Add SDKs for Firebase products that you want to use
// https://firebase.google.com/docs/web/setup#available-libraries

// Your web app's Firebase configuration
// For Firebase JS SDK v7.20.0 and later, measurementId is optional
const firebaseConfig = {
  apiKey: "AIzaSyAX52lk1_u3DWIzlGC7UDOgqFkPNf719qo",
  authDomain: "bananaspot-249e7.firebaseapp.com",
  projectId: "bananaspot-249e7",
  storageBucket: "bananaspot-249e7.appspot.com",
  messagingSenderId: "455136843141",
  appId: "1:455136843141:web:d5ba57f58f25de43c260ec",
  measurementId: "G-VQ5BYW0YGB"
};

// Initialize Firebase
const app = initializeApp(firebaseConfig);
const analytics = getAnalytics(app);

export default firebase;
```

### ParkingTrackerApp/FirebaseService.js

```javascript
// FirebaseService.js
import { initializeApp } from 'firebase/app';
import { getDatabase, ref, onValue } from 'firebase/database';

const firebaseConfig = {
    apiKey: "AIzaSyAX52lk1_u3DWIzlGC7UDOgqFkPNf719qo",
    authDomain: "bananaspot-249e7.firebaseapp.com",
    projectId: "bananaspot-249e7",
    storageBucket: "bananaspot-249e7.appspot.com",
    messagingSenderId: "455136843141",
    appId: "1:455136843141:web:d5ba57f58f25de43c260ec",
    measurementId: "G-VQ5BYW0YGB"
  };

const firebaseApp = initializeApp(firebaseConfig);
const rootRef = ref(getDatabase(firebaseApp));

export const fetchDataFromFirebase = (setDataCallback, setGraphingDataCallback) => {
  const dataRef = onValue(rootRef, (snapshot) => {
    const newData = snapshot.val();

    
    setDataCallback(newData);

    setGraphingDataCallback(newData.Graphing.data.Location);
  });

  // Return the cleanup function to stop listening when needed
  return () => {
    dataRef.off();
  };
};
```

### car_counter/EastRemote.py

```python
# import the opencv library 
import cv2
import time
from source_code.vehicle_detector import VehicleDetector
import json
import requests
from datetime import datetime
SPACES_COUNT = 8
import firebase_admin
from firebase_admin import credentials
url = 'https://bananaspot-249e7-default-rtdb.firebaseio.com/'
cred = credentials.Certificate("./bananaspot-249e7-firebase-adminsdk-29dme-85861daf07.json")
firebase_admin.initialize_app(cred, {
    'databaseURL': url
})

from firebase_admin import db



# define a video capture object 
vid = cv2.VideoCapture(0) 
detector = VehicleDetector()

try:
    while(True): 
        graph = db.reference('Graphing/data/Location/East Remote/Spots Remaining').get()
        graph = list(graph)
        times = db.reference('Graphing/data/Location/East Remote/Time').get()
        times = list(times)
        check30 = db.reference('Graphing/data/Location/East Remote/30Check').get()
        # Capture the video frame 
        # by frame 
        ret, frame = vid.read()
        boxes = detector.detect_vehicles(frame)
        # Display the resulting frame 
        for box in boxes:
            x, y, w, h = box
            cv2.rectangle(frame, (x, y), (x + w, y + h), (25, 0, 180), 3)
        cv2.imshow('frame', frame)
        print("Total current count", len(boxes))
        # append the count to the graph
        #check if first 30 minutes using date time, append and swap bool if true
        if check30 == False and datetime.now().minute <=30 and datetime.now().minute >=0:
            print("first 30 minutes")
            print(graph)
            print(check30)
            graph.append(SPACES_COUNT-len(boxes))
            times.append(datetime.now().strftime("%H:%M:%S"))
            if len(graph) >336:
                graph.pop(0)
            response = requests.put(f'{url}/Graphing/data/Location/East%20Remote/Spots%20Remaining.json', json.dumps(graph))
            response = requests.put(f'{url}/Graphing/data/Location/East%20Remote/Time.json', json.dumps(times))
            check30 = True
            response = requests.put(f'{url}/Graphing/data/Location/East%20Remote/30Check.json', json.dumps(check30))
        elif check30 == True and datetime.now().minute >30 and datetime.now().minute <=59:
            print("second 30 minutes")
            check30 = False
            graph.append(str(len(boxes)))
            times.append(datetime.now().strftime("%H:%M:%S"))
            if len(graph) >336:
                graph.pop(0)
            response = requests.put(f'{url}/Graphing/data/Location/East%20Remote/Spots%20Remaining.json', json.dumps(graph))
            response = requests.put(f'{url}/Graphing/data/Location/East%20Remote/Time.json', json.dumps(times))
            response = requests.put(f'{url}/Graphing/data/Location/East%20Remote/30Check.json', json.dumps(check30))

        
        # the 'q' button is set as the 
        # quitting button you may use any 
        # desired button of your choice 
        if cv2.waitKey(1) & 0xFF == ord('b'):
            break


        now = datetime.now()

        current_time = now.strftime("%H:%M:%S")
        dic = {'cars': 8-len(boxes), 'time': current_time}
        print("Current Time =", current_time)
        response = requests.put(f'{url}/East_Remote/data.json', str(json.dumps(dic)))
        time.sleep(10)
except KeyboardInterrupt:
    pass
  
# After the loop release the cap object 
vid.release() 
# Destroy all the windows 
cv2.destroyAllWindows() 
```

[10 more indexed source files omitted to keep this export small. The full file list is in the Codebase structure section above.]