# Project export: TreeCycle

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: TreeHacks 2025
- Tagline: TreeCycle uses VR to show kids how everyday recycling choices shape our planet. Through immersive visualization and interactive gameplay, we're making environmental education engaging and impactful.
- Devpost: https://devpost.com/software/treecycle-umd2yx
- GitHub: https://github.com/FeoluK/Treehacks-Sustainability-Project
- Video: https://www.youtube.com/embed/scCDiJHVQx4?enablejsapi=1&hl=en_US&rel=0&start=&version=3&wmode=transparent
- Team: 4 GitHub contributor(s) — FeoluK (8 commits), kesavanramakrishnan (7 commits), Yogesh Seenichamy (2 commits), Nick Rui (2 commits)

## Devpost submission (written by the team)

### Inspiration

After awkwardly staring between the trash can and recycling bin trying to figure out where our empty Roost & Roast takeout containers should go, we realized that none of us really knew the answer. Despite seeming like such a simple and straightforward binary problem, there is so much ambiguity and misinformation regarding recycling. We wanted to tackle this issue from the bottom up by building something for environmental education. After some initial research, we found two main causes of unsustainable habits. The first is a lack of environmental curricula, specifically for students in grades K-6. The second was the "one person can't make a difference" mindset—a sort of diffusion of responsibility that many use to justify making unsustainable decisions. Brainstorming ways to tackle these issues, TreeCycle was born. We decided that we could gamify this process of learning to discard waste and turn it into a VR application that would be a fun and engaging method to teach kids how to get rid of their waste. In addition, being able to control the environment of the virtual world allowed us to change the scenery depending on whether or not the user chose the right bin, helping teach kids that their choices do directly impact our Earth.

### What it does

Our product sets up an environment for people to explore how to discard their waste through two methods: "practice" and "clean mess". For the practice method, we created a welcoming environment that allows users to interact with the world around them and practice discarding the various articles of waste scattered across the ground, updating the dynamic world around them to reflect the effects that their choices would have on the environment. An additional feature that is extremely useful is the clean mess method that is built from a mobile application where you are able to take a picture of articles of waste that you want to clean up, and a model that we've trained identifies what waste they are, and populates the VR game with those exact waste articles so you can practice cleaning up your mess in a fun environment, while simultaneously learning how to actually clean up your mess.

### How we built it

Our product consists of three parts, the iOS application, the ML model, and the VR Application. Our ML model was trained using NVIDIA's Brev.dev platform where we rigorously trained data using a finetuned YOLO model to identify pieces of trash from a picture containing multiple articles of trash. The model identifies what trash it is and creates a JSON file with the objects it found. In order to get an image of the trash, the iOS application has been built to have the capability to take a picture and then send it to an API that handles the image and returns data containing what objects it found. Then, the VR application is able to access that same data and create a game to work with sorting the pieces of trash that you have taken a picture of. Additionally, the VR Application has access to common trash items and can create a randomly generated game that helps people learn to sort their trash even when they don't have a mess.

### Challenges we ran into

One of the main issues we ran into was that we worked using Apple's Vision Pro, and due to the fact that it was recently released, there isn't a great deal of documentation for the device, and we often had to do rigorous research to get even basic features implemented due to how complex the Vision Pro is. Another issue was being able to integrate all of the moving parts of this product since there were so many different factors that came into play, whether it was the iOS Application, the classification model, or the VR app, being able to get everything to work between each other was difficult and challenging to integrate.

### What we learned

Aside from tackling the technical challenges of integrating VR, iOS, and computer vision, this project that designing meaningful educational experiences requires extensive consideration for the intended audience. Through researching current discussions on environmental education, we learned that creating learning experiences for young students is far more than telling someone "recycling is important." Showing them the direct impact of their choices through immersive visualization can fundamentally change behavior. The immediate visual feedback in our VR environment—seeing the trees around you grow when you make the correct decision—helps break down the common "one person can't make a difference" mindset. Our most important takeaway is that developing human-centered technologies requires consideration for human psychology and cognition.

### What's next

We intend to reach out to elementary school teachers for feedback on our product. We are working toward conducting testing sessions with students and gathering direct feedback on the game's engagement. We also recognize the price of VR headsets raises concerns regarding our product's accessibility in underresourced communities and intend to start conversations with educational nonprofits to ensure our product isn't furthering socioeconomic gaps. What it does Our product sets up an environment for people to explore how to discard their waste through two methods: practice and clean mess. For the practice method, we created a welcoming environment that allows users to interact with the world around them and practice discarding the various articles of waste scattered across the ground, updating the dynamic world around them to reflect the effects that their choices would have on the environment. An additional feature that is extremely useful is the clean mess method that is built from a mobile application where you are able to take a picture of articles of waste that you want to clean up, and a model that we've trained identifies what waste they are, and populates the VR game with those exact waste articles so you can practice cleaning up your mess in a fun environment, while simultaneously learning how to actually clean up your mess. How we built it Our product consists of three parts, the iOS application, the ML model, and the VR Application. Our ML model was trained using NVIDIA's Brev.dev platform where we rigorously trained data using a finetuned YOLO model to identify pieces of trash from a picture containing multiple articles of trash. The model identifies what trash it is and creates a JSON file with the objects it found. In order to get an image of the trash, the iOS application has been built to have the capability to take a picture and then send it to an API that handles the image and returns data containing what objects it found. Then, the VR application is able to access that same data and create a game to work with sorting the pieces of trash that you have taken a picture of. Additionally, the VR Application has access to common trash items and can create a randomly generated game that helps people learn to sort their trash even when they don't have a mess. Challenges we ran into One of the main issues we ran into was that we worked using Apple's Vision Pro, and due to the fact that it was recently released, there isn't a great deal of documentation for the device, and we often had to do rigorous research to get even basic features implemented due to how complex the Vision Pro is. Another issue was being able to integrate all of the moving parts of this product since there were so many different factors that came into play, whether it was the iOS Application, the classification model, or the VR app, being able to get everything to work between each other was difficult and challenging to integrate. What we learned Aside from tackling the technical challenges of integrating VR, iOS, and computer vision, this project that designing meaningful educational experiences requires extensive consideration for the intended audience. Through researching current discussions on environmental education, we learned that creating learning experiences for young students is far more than telling someone "recycling is important." Showing them the direct impact of their choices through immersive visualization can fundamentally change behavior. The immediate visual feedback in our VR environment—seeing the trees around you grow when you make the correct decision—helps break down the common "one person can't make a difference" mindset. Our most important takeaway is that developing human-centered technologies requires consideration for human psychology and cognition. What's next for TreeCycle We intend to reach out to elementary school teachers for feedback on our product. We are working toward conducting testing sessions with students and gathering direct feedback on the game's engagement. We also recognize the price of VR headsets raises concerns regarding our product's accessibility in underresourced communities and intend to start conversations with educational nonprofits to ensure our product isn't furthering socioeconomic gaps.

## README (from the GitHub repository)

# TreeCycle
[![Watch Video](https://img.shields.io/badge/YouTube-Watch-red?logo=youtube&style=for-the-badge)](https://youtu.be/yDez3BDtcOo)

## Brief Overview
TreeCycle uses VR to show kids how everyday recycling choices shape our planet. Through immersive visualization and interactive gameplay, we're making environmental education engaging and impactful.

## Inspiration
After awkwardly staring between the trash can and recycling bin trying to figure out where our empty Roost & Roast takeout containers should go, we realized that none of us really knew the answer. Despite seeming like such a simple and straightforward binary problem, there is so much ambiguity and misinformation regarding recycling. We wanted to tackle this issue from the bottom up by building something for environmental education.

After some initial research, we found two main causes of unsustainable habits. The first is a lack of environmental curricula, specifically for students in grades K-6. The second was the "one person can't make a difference" mindset—a sort of diffusion of responsibility that many use to justify making unsustainable decisions. Brainstorming ways to tackle these issues, TreeCycle was born.

We decided that we could gamify this process of learning to discard waste and turn it into a VR application that would be a fun and engaging method to teach kids how to get rid of their waste. In addition, being able to control the environment of the virtual world allowed us to change the scenery depending on whether or not the user chose the right bin, helping teach kids that their choices do directly impact our Earth.

## What it does
Our product sets up an environment for people to explore how to discard their waste through two methods: "practice" and "clean mess". For the practice method, we created a welcoming environment that allows users to interact with the world around them and practice discarding the various articles of waste scattered across the ground, updating the dynamic world around them to reflect the effects that their choices would have on the environment. An additional feature that is extremely useful is the clean mess method that is built from a mobile application where you are able to take a picture of articles of waste that you want to clean up, and a model that we've trained identifies what waste they are, and populates the VR game with those exact waste articles so you can practice cleaning up your mess in a fun environment, while simultaneously learning how to actually clean up your mess.

## How we built it
Our product consists of three parts, the iOS application, the ML model, and the VR Application. Our ML model was trained using NVIDIA's Brev.dev platform where we rigorously trained data using a finetuned YOLO model to identify pieces of trash from a picture containing multiple articles of trash. The model identifies what trash it is and creates a JSON file with the objects it found. In order to get an image of the trash, the iOS application has been built to have the capability to take a picture and then send it to an API that handles the image and returns data containing what objects it found. Then, the VR application is able to access that same data and create a game to work with sorting the pieces of trash that you have taken a picture of. Additionally, the VR Application has access to common trash items and can create a randomly generated game that helps people learn to sort their trash even when they don't have a mess.

## Challenges we ran into
One of the main issues we ran into was that we worked using Apple's Vision Pro, and due to the fact that it was recently released, there isn't a great deal of documentation for the device, and we often had to do rigorous research to get even basic features implemented due to how complex the Vision Pro is. 

Another issue was being able to integrate all of the moving parts of this product since there were so many different factors that came into play, whether it was the iOS Application, the classification model, or the VR app, being able to get everything to work between each other was difficult and challenging to integrate.

## What we learned
Aside from tackling the technical challenges of integrating VR, iOS, and computer vision, this project that designing meaningful educational experiences requires extensive consideration for the intended audience. Through researching current discussions on environmental education, we learned that creating learning experiences for young students is far more than telling someone "recycling is important." Showing them the direct impact of their choices through immersive visualization can fundamentally change behavior. The immediate visual feedback in our VR environment—seeing the trees around you grow when you make the correct decision—helps break down the common "one person can't make a difference" mindset. Our most important takeaway is that **developing human-centered technologies requires consideration for human psychology and cognition.**

## What's next for TreeCycle
We intend to reach out to elementary school teachers for feedback on our product. We are working toward conducting testing sessions with students and gathering direct feedback on the game's engagement. We also recognize the price of VR headsets raises concerns regarding our product's accessibility in underresourced communities and intend to start conversations with educational nonprofits to ensure our product isn't furthering socioeconomic gaps.


## Detected evidence (automated analysis)

Indexed codebase: 18 recognized source files, 43 KB.
- Python (language) — detected in the code
- Swift (language) — detected in the code
- FastAPI (technology) — claimed on Devpost, not found in the code

## Codebase structure (from repository index)

### Files (79 of 79)

```
.DS_Store
.gitignore
.gitmodules
app.py
code/.DS_Store
README.md
Treehacks 2025 Project/Packages/Food can.usdz
Treehacks 2025 Project/Packages/RealityKitContent/Package.realitycomposerpro/ProjectData/main.json
Treehacks 2025 Project/Packages/RealityKitContent/Package.realitycomposerpro/WorkspaceData/SceneMetadataList.json
Treehacks 2025 Project/Packages/RealityKitContent/Package.realitycomposerpro/WorkspaceData/Settings.rcprojectdata
Treehacks 2025 Project/Packages/RealityKitContent/Package.swift
Treehacks 2025 Project/Packages/RealityKitContent/README.md
Treehacks 2025 Project/Packages/RealityKitContent/Sources/RealityKitContent/RealityKitContent.rkassets/Immersive.usda
Treehacks 2025 Project/Packages/RealityKitContent/Sources/RealityKitContent/RealityKitContent.rkassets/Materials/GridMaterial.usda
Treehacks 2025 Project/Packages/RealityKitContent/Sources/RealityKitContent/RealityKitContent.rkassets/Pizza box.usdz
Treehacks 2025 Project/Packages/RealityKitContent/Sources/RealityKitContent/RealityKitContent.rkassets/Scene.usda
Treehacks 2025 Project/Packages/RealityKitContent/Sources/RealityKitContent/RealityKitContent.swift
Treehacks 2025 Project/Treehacks 2025 Project.xcodeproj/project.pbxproj
Treehacks 2025 Project/Treehacks 2025 Project.xcodeproj/project.xcworkspace/contents.xcworkspacedata
Treehacks 2025 Project/Treehacks 2025 Project/AppModel.swift
Treehacks 2025 Project/Treehacks 2025 Project/Assets.xcassets/AccentColor.colorset/Contents.json
Treehacks 2025 Project/Treehacks 2025 Project/Assets.xcassets/AppIcon.solidimagestack/Back.solidimagestacklayer/Content.imageset/Contents.json
Treehacks 2025 Project/Treehacks 2025 Project/Assets.xcassets/AppIcon.solidimagestack/Back.solidimagestacklayer/Contents.json
Treehacks 2025 Project/Treehacks 2025 Project/Assets.xcassets/AppIcon.solidimagestack/Contents.json
Treehacks 2025 Project/Treehacks 2025 Project/Assets.xcassets/AppIcon.solidimagestack/Front.solidimagestacklayer/Content.imageset/Contents.json
Treehacks 2025 Project/Treehacks 2025 Project/Assets.xcassets/AppIcon.solidimagestack/Front.solidimagestacklayer/Contents.json
Treehacks 2025 Project/Treehacks 2025 Project/Assets.xcassets/AppIcon.solidimagestack/Middle.solidimagestacklayer/Content.imageset/Contents.json
Treehacks 2025 Project/Treehacks 2025 Project/Assets.xcassets/AppIcon.solidimagestack/Middle.solidimagestacklayer/Contents.json
Treehacks 2025 Project/Treehacks 2025 Project/Assets.xcassets/Background.imageset/Contents.json
Treehacks 2025 Project/Treehacks 2025 Project/Assets.xcassets/Beach 1.imageset/Contents.json
Treehacks 2025 Project/Treehacks 2025 Project/Assets.xcassets/Beach 2.imageset/Contents.json
Treehacks 2025 Project/Treehacks 2025 Project/Assets.xcassets/Beach 3.imageset/Contents.json
Treehacks 2025 Project/Treehacks 2025 Project/Assets.xcassets/Beach 4.imageset/Contents.json
Treehacks 2025 Project/Treehacks 2025 Project/Assets.xcassets/Beach 5.imageset/Contents.json
Treehacks 2025 Project/Treehacks 2025 Project/Assets.xcassets/Contents.json
Treehacks 2025 Project/Treehacks 2025 Project/Assets.xcassets/Food can.dataset/Contents.json
Treehacks 2025 Project/Treehacks 2025 Project/Assets.xcassets/Food can.dataset/Food can.usdz
Treehacks 2025 Project/Treehacks 2025 Project/Assets.xcassets/Test Image.imageset/Contents.json
Treehacks 2025 Project/Treehacks 2025 Project/ContentView.swift
Treehacks 2025 Project/Treehacks 2025 Project/DetectionResponse.swift
Treehacks 2025 Project/Treehacks 2025 Project/ImmersiveView.swift
Treehacks 2025 Project/Treehacks 2025 Project/Info.plist
Treehacks 2025 Project/Treehacks 2025 Project/LifeView.swift
Treehacks 2025 Project/Treehacks 2025 Project/NetworkManager.swift
Treehacks 2025 Project/Treehacks 2025 Project/Preview Content/Models/Aerosol.usdz
Treehacks 2025 Project/Treehacks 2025 Project/Preview Content/Models/Cigarette.usdz
Treehacks 2025 Project/Treehacks 2025 Project/Preview Content/Models/Clear plastic bottle.usdz
Treehacks 2025 Project/Treehacks 2025 Project/Preview Content/Models/Crisp packet.usdz
Treehacks 2025 Project/Treehacks 2025 Project/Preview Content/Models/Disposable plastic cup.usdz
Treehacks 2025 Project/Treehacks 2025 Project/Preview Content/Models/Drink can.usdz
Treehacks 2025 Project/Treehacks 2025 Project/Preview Content/Models/Drink carton.usdz
Treehacks 2025 Project/Treehacks 2025 Project/Preview Content/Models/Egg carton.usdz
Treehacks 2025 Project/Treehacks 2025 Project/Preview Content/Models/Foam cup.usdz
Treehacks 2025 Project/Treehacks 2025 Project/Preview Content/Models/Food can.usdz
Treehacks 2025 Project/Treehacks 2025 Project/Preview Content/Models/Food waste.usdz
Treehacks 2025 Project/Treehacks 2025 Project/Preview Content/Models/Forest 1.usdc
Treehacks 2025 Project/Treehacks 2025 Project/Preview Content/Models/Forest 2.usdc
Treehacks 2025 Project/Treehacks 2025 Project/Preview Content/Models/Forest 3.usdc
Treehacks 2025 Project/Treehacks 2025 Project/Preview Content/Models/Forest 4.usdc
Treehacks 2025 Project/Treehacks 2025 Project/Preview Content/Models/Forest 5.usdc
Treehacks 2025 Project/Treehacks 2025 Project/Preview Content/Models/Glass bottle.usdz
Treehacks 2025 Project/Treehacks 2025 Project/Preview Content/Models/Normal paper.usdz
Treehacks 2025 Project/Treehacks 2025 Project/Preview Content/Models/Paper cup.usdz
Treehacks 2025 Project/Treehacks 2025 Project/Preview Content/Models/Pizza box.usdz
Treehacks 2025 Project/Treehacks 2025 Project/Preview Content/Models/Plastic straw.usdz
Treehacks 2025 Project/Treehacks 2025 Project/Preview Content/Models/Plastic utensils.usdz
Treehacks 2025 Project/Treehacks 2025 Project/Preview Content/Models/Recycle Bin.usdz
Treehacks 2025 Project/Treehacks 2025 Project/Preview Content/Models/Scrap metal.usdz
Treehacks 2025 Project/Treehacks 2025 Project/Preview Content/Models/Single-use carrier bag.usdz
Treehacks 2025 Project/Treehacks 2025 Project/Preview Content/Models/Squeezable tube.usdz
Treehacks 2025 Project/Treehacks 2025 Project/Preview Content/Models/Trash Can.usdz
Treehacks 2025 Project/Treehacks 2025 Project/Preview Content/Preview Assets.xcassets/Contents.json
Treehacks 2025 Project/Treehacks 2025 Project/Skyboxes.swift
Treehacks 2025 Project/Treehacks 2025 Project/ToggleImmersiveSpaceButton.swift
Treehacks 2025 Project/Treehacks 2025 Project/ToggleLifeSpaceButton.swift
Treehacks 2025 Project/Treehacks 2025 Project/TogglePicture.swift
Treehacks 2025 Project/Treehacks 2025 Project/TogglePractice.swift
Treehacks 2025 Project/Treehacks 2025 Project/Treehacks_2025_ProjectApp.swift
Treehacks 2025 Project/Treehacks 2025 ProjectTests/Treehacks_2025_ProjectTests.swift
```

### Dependencies

No dependency index available.

### Recent commits (newest first)

- Update README.md
- Update README.md
- Added ML code
- Update README.md
- Updating README
- Moved .gitignore inside Treehacks 2025 Project
- Rest API Code
- Integration
- Added iOS
- Remove TreeCycle iOS directory to set up as a submodule
- New app
- Added IOS App
- iOS application
- Create TreeCycle iOS
- iOS Application
- Integration
- VR Mostly Done
- Seperate Immersive Views
- Initial commit - Treehacks 2025 Project
- Initial commit - Treehacks 2025 Project

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

### app.py

```python
from fastapi import FastAPI, File, UploadFile
from ultralytics import YOLO
import cv2
import numpy as np
from PIL import Image
import io
import random

# Initialize FastAPI app
app = FastAPI()

# Load YOLO model (assuming it's already trained and available in your notebook)
# model = YOLO("/home/ubuntu/model_training/Object Detection/code/runs/detect/train10/weights/best.pt")  # Update with correct model path
# model = YOLO("yolov8x.pt")
model = YOLO("/home/ubuntu/model_training/Object Detection/code/runs/detect/train11/weights/last.pt")  # Update with correct model path


annotations = None
names = ['Aluminium foil', 'Battery', 'Aluminium blister pack', 'Carded blister pack', 'Bottle', 'Bottle', 'Bottle', 'Plastic bottle cap', 'Metal bottle cap', 'Broken glass', 'Food Can', 'Aerosol', 'Drink can', 'Toilet tube', 'Other carton', 'Egg carton', 'Drink carton', 'Corrugated carton', 'Meal carton', 'Pizza box', 'Paper cup', 'Plastic cup', 'Foam cup', 'Glass cup', 'Plastic cup', 'Food waste', 'Glass jar', 'Plastic lid', 'Metal lid', 'Other plastic', 'Magazine paper', 'Tissues', 'Wrapping paper', 'Normal paper', 'Paper bag', 'Chip bag', 'Plastic film', 'Six pack rings', 'Plastic bag', 'Chip bag', 'Single-use carrier bag', 'Polypropylene bag', 'Chip bag', 'Spread tub', 'Tupperware', 'Disposable food container', 'Foam food container', 'Other plastic container', 'Plastic glooves', 'Plastic utensils', 'Pop tab', 'Rope & strings', 'Scrap metal', 'Shoe', 'Squeezable tube', 'Plastic straw', 'Paper straw', 'Styrofoam piece', 'Unlabeled litter', 'Cigarette']
# likelihood = [0.5, 0.3, 0.2, 0.3, 0.95, 0.95, 0.7, 0.8, 0.6, 0.4, 0.7, 0.5, 0.9, 0.4, 0.3, 0.6, 0.7, 0.4, 0.3, 0.9, 0.8, 0.85, 0.75, 0.4, 0.85, 1.0, 0.5, 0.6, 0.5, 0.4, 0.3, 0.7, 0.6, 0.85, 0.75, 0.95, 0.9, 0.2, 0.95, 0.9, 0.8, 0.7, 0.9, 0.5, 0.3, 0.8, 0.75, 0.5, 0.2, 0.6, 0.1, 0.2, 0.4, 0.2, 0.3, 0.5, 0.4, 0.6, 0.1, 0.9]
items_we_want = {'Aluminium foil','Aerosol', 'Cigarette', 'Plastic bottle', 'Chip bag', 'Plastic cup', 'Drink can', 'Drink carton', 'Egg carton', 'Foam cup', 'Food can', 'Food waste', 'Bottle', 'Normal paper', 'Paper cup', 'Pizza box', 'Plastic straw', 'Plastic utensils', 'Scrap metal', 'Squeezable tube'}
# likelihood = [1 if name in items_we_want else 0.2 for name in names]
recyclable = {
    'Aluminium foil', 'Aerosol', 'Bottle', 'Plastic cup', 'Drink can', 
    'Drink carton', 'Egg carton', 'Food can', 'Normal paper', 'Scrap metal'
}

not_recyclable = {
    'Cigarette', 'Chip bag', 'Foam cup', 'Paper cup', 'Pizza box', 
    'Plastic straw', 'Plastic utensils', 'Squeezable tube'
}

compostable = {'Food waste'}

@app.post("/predict")
async def predict(file: UploadFile = File(...)):
    global annotations

    # Read image file
    image_bytes = await file.read()
    image = Image.open(io.BytesIO(image_bytes)).convert("RGB")
    
    # Convert PIL image to NumPy array
    image_np = np.array(image)
    
    # Run YOLO inference
    results = model.predict(image_np)

    # Extract detections
    detections = []
    for result in results:
        for box in result.boxes:
            x1, y1, x2, y2 = box.xyxy[0].tolist()
            conf = float(box.conf[0])
            class_id = int(box.cls[0])
            class_name = names[class_id]

            if class_name in items_we_want:
                detections.append({
                    "object": class_name,
                    "confidence": conf,
                    "bbox": [x1, y1, x2, y2],
                    "class_name": "recyclable" if class_name in recyclable 
                        else "compostable" if class_name in compostable 
                        else "not recyclable"
                })
            # else:
            #     detections.append({
            #         "object": f'unknown ({class_name})',
            #         "confidence": conf,
            #         "bbox": [x1, y1, x2, y2]
            #     })

    annotations = detections
    detections.sort(key=lambda x: x["confidence"], reverse=True)

    return {"detections": detections}

@app.get("/latest")
async def latest():
    global annotations
    return {"detections": annotations}
```

### Treehacks 2025 Project/Treehacks 2025 Project/Skyboxes.swift

```swift
//
//  Skybox.swift
//  Treehacks 2025 Project
//
//  Created by Feolu Kolawole on 2/15/25.
//

import Foundation

enum Skybox: String, CaseIterable {
    case beach = "Beach"
    
    static let defaultSkybox: Skybox = .beach
}

```

### Treehacks 2025 Project/Treehacks 2025 ProjectTests/Treehacks_2025_ProjectTests.swift

```swift
//
//  Treehacks_2025_ProjectTests.swift
//  Treehacks 2025 ProjectTests
//
//  Created by Feolu Kolawole on 2/15/25.
//

import Testing
@testable import Treehacks_2025_Project

struct Treehacks_2025_ProjectTests {

    @Test func example() async throws {
        // Write your test here and use APIs like `#expect(...)` to check expected conditions.
    }

}

```

### Treehacks 2025 Project/Treehacks 2025 Project/AppModel.swift

```swift
//
//  AppModel.swift
//  Treehacks 2025 Project
//
//  Created by Feolu Kolawole on 2/15/25.
//

import SwiftUI

@MainActor
@Observable
class AppModel: ObservableObject {
    var immersiveSpaceID: String = "mainImmersive"
    var immersiveSpaceState: ImmersiveSpaceState = .closed

    // Add a second state for the "lifeImmersive" space:
    var lifeImmersiveSpaceState: ImmersiveSpaceState = .closed
}

enum ImmersiveSpaceState {
    case open, closed, inTransition
}



```

### Treehacks 2025 Project/Treehacks 2025 Project/Treehacks_2025_ProjectApp.swift

```swift
import SwiftUI

@main
struct Treehacks_2025_ProjectApp: App {
    @State private var immersionStyle: ImmersionStyle = .progressive(0.0...1.0, initialAmount: 1.0)
    @StateObject private var appState = AppState()
    @State private var appModel = AppModel()

    var body: some Scene {
        WindowGroup {
            ContentView()
                .environment(appState)
                .environment(appModel)
        }

        // Existing main immersive space
        ImmersiveSpace(id: appModel.immersiveSpaceID) {
            ImmersiveView()
                .environment(appState)
                .environment(appModel)
                .onAppear {
                    appModel.immersiveSpaceState = .open
                }
                .onDisappear {
                    appModel.immersiveSpaceState = .closed
                }
        }
        .immersionStyle(selection: $immersionStyle, in: .progressive)

        ImmersiveSpace(id: "lifeImmersive") {
            LifeView()
                .environment(appState)
                .environment(appModel)
                .onAppear {
                    // Mark the second space as open
                    appModel.lifeImmersiveSpaceState = .open
                }
                .onDisappear {
                    appModel.lifeImmersiveSpaceState = .closed
                }
        }
        .immersionStyle(selection: .constant(.full), in: .full)
    }
}


@Observable
class AppState: ObservableObject {
    var pLevel: Int = 1
    var fLevel: Double = 1
    var objects: [ClassificationResult] = []
    
}


```

### Treehacks 2025 Project/Treehacks 2025 Project/ContentView.swift

```swift
import SwiftUI
import RealityKit
import RealityKitContent
import AVFoundation

struct ContentView: View {
    @EnvironmentObject var appState: AppState
    @Environment(AppModel.self) private var appModel
    
    var body: some View {
        ZStack {
            // Background image
            Image("Background") // Replace with your image name
                .resizable()
                .scaledToFill()
                .ignoresSafeArea() // Ensures the image covers the entire screen
            
            VStack(spacing: 20) {
                // Title
                Text("Welcome to TreeCycle")
                    .font(.largeTitle)
                    .fontWeight(.bold)
                    .foregroundColor(.white)
                    .padding(.top, 40) // Adds spacing from the top
                
                Spacer() // Pushes the content below the title
                
                // 3D or 2D content in the window
                Model3D(named: "Scene", bundle: realityKitContentBundle)
                    .padding(.bottom, 50)
                
                // Existing button toggles the "mainImmersive" space
                ToggleImmersiveSpaceButton()
                
                // NEW button toggles the "lifeImmersive" space
                ToggleLifeSpaceButton()
                
                // Additional buttons
                TogglePractice()
                
                TogglePicture()
                
                Spacer() // Adds spacing at the bottom
            }
            .padding()
        }
    }
    
}

```

### Treehacks 2025 Project/Treehacks 2025 Project/NetworkManager.swift

```swift
//
//  NetworkManager.swift
//  Treehacks 2025 Project
//
//  Created by Kesavan Ramakrishnan on 2/16/25.
//

import Foundation

/// API Manager to handle network requests
struct NetworkManager {
    static let shared = NetworkManager() // Singleton instance

    /// Sends a GET request and decodes the response into `DetectionResponse`
    func fetchDetections(completion: @escaping (Result<DetectionResponse, NetworkError>) -> Void) {
        // Base URL of the API
        let baseURL = "https://8000-cuy5jl6fd.brevlab.com/latest" // Replace with your API endpoint

        // Ensure the URL is valid
        guard let url = URL(string: baseURL) else {
            completion(.failure(.invalidURL))
            return
        }

        // Create a URL request
        var request = URLRequest(url: url)
        request.httpMethod = "GET"

        // Perform the network request
        URLSession.shared.dataTask(with: request) { data, response, error in
            if let error = error {
                print("Error: \(error.localizedDescription)")
                completion(.failure(.noDataReceived))
                return
            }

            guard let data = data else {
                completion(.failure(.noDataReceived))
                return
            }

            // Decode the JSON response
            do {
                let decoder = JSONDecoder()
                let detectionResponse = try decoder.decode(DetectionResponse.self, from: data)
                completion(.success(detectionResponse))
            } catch {
                print("Decoding error: \(error.localizedDescription)")
                completion(.failure(.noDataReceived))
            }
        }.resume()
    }
}

```

### Treehacks 2025 Project/Treehacks 2025 Project/ToggleLifeSpaceButton.swift

```swift
import SwiftUI

struct ToggleLifeSpaceButton: View {

    @Environment(AppModel.self) private var appModel

    @Environment(\.dismissImmersiveSpace) private var dismissImmersiveSpace
    @Environment(\.openImmersiveSpace) private var openImmersiveSpace

    var body: some View {
        Button {
            Task { @MainActor in
                switch appModel.lifeImmersiveSpaceState {
                    case .open:
                        appModel.lifeImmersiveSpaceState = .inTransition
                        await dismissImmersiveSpace()
                        // We'll rely on LifeView.onDisappear to set .closed.

                    case .closed:
                        appModel.lifeImmersiveSpaceState = .inTransition
                        // Open the "lifeImmersive" space
                        switch await openImmersiveSpace(id: "lifeImmersive") {
                            case .opened:
                                // We'll rely on LifeView.onAppear to set .open.
                                break
                            case .userCancelled, .error:
                                fallthrough
                            @unknown default:
                                appModel.lifeImmersiveSpaceState = .closed
                        }

                    case .inTransition:
                        // Shouldn't happen since the button is disabled in that state.
                        break
                }
            }
        } label: {
            Text(appModel.lifeImmersiveSpaceState == .open
                 ? "Hide Life Space"
                 : "Show Life Space")
        }
        .disabled(appModel.lifeImmersiveSpaceState == .inTransition)
        .animation(.none, value: 0)
        .fontWeight(.semibold)
    }
}

```

### Treehacks 2025 Project/Treehacks 2025 Project/TogglePicture.swift

```swift
//
//  TogglePicture.swift
//  Treehacks 2025 Project
//
//  Created by Kesavan Ramakrishnan on 2/16/25.
//

import SwiftUI

struct TogglePicture: View {
    @Environment(AppModel.self) private var appModel
    @EnvironmentObject var appState: AppState
    
    var body: some View {
        Button(action: {
            // Call the API without parameters
            NetworkManager.shared.fetchDetections { result in
                switch result {
                case .success(let detectionResponse):
                    appState.objects.removeAll()
                    // Handle the successful response
                    print("Detections: \(detectionResponse.detections)")
                    for detection in detectionResponse.detections {
                        let classifacationResult = ClassificationResult(object: entityMap.mappedItems[detection.object] ?? "Drink can", confidence: detection.confidence, bbox: detection.bbox)
                        appState.objects.append(classifacationResult)
                    }
                case .failure(let error):
                    // Handle the error
                    print("Error: \(error.localizedDescription)")
                }
            }
        }) {
            Text("Clean Up Your Mess!")
                .font(.headline)
                .padding(.vertical, 12)
                .padding(.horizontal, 20)
                .background(
                    LinearGradient(
                        gradient: Gradient(colors: [Color.blue.opacity(0.8), Color.purple.opacity(0.8)]),
                        startPoint: .leading,
                        endPoint: .trailing
                    )
                )
                .foregroundColor(.white)
                .clipShape(Capsule())
                .shadow(color: Color.black.opacity(0.2), radius: 10, x: 0, y: 5)
        }
    }
}

```

### Treehacks 2025 Project/Treehacks 2025 Project/ToggleImmersiveSpaceButton.swift

```swift
//
//  ToggleImmersiveSpaceButton.swift
//  Treehacks 2025 Project
//
//  Created by Feolu Kolawole on 2/15/25.
//

import SwiftUI

struct ToggleImmersiveSpaceButton: View {

    @Environment(AppModel.self) private var appModel

    @Environment(\.dismissImmersiveSpace) private var dismissImmersiveSpace
    @Environment(\.openImmersiveSpace) private var openImmersiveSpace

    var body: some View {
        Button {
            Task { @MainActor in
                switch appModel.immersiveSpaceState {
                    case .open:
                        appModel.immersiveSpaceState = .inTransition
                        await dismissImmersiveSpace()
                        // Don't set immersiveSpaceState to .closed because there
                        // are multiple paths to ImmersiveView.onDisappear().
                        // Only set .closed in ImmersiveView.onDisappear().

                    case .closed:
                        appModel.immersiveSpaceState = .inTransition
                        switch await openImmersiveSpace(id: appModel.immersiveSpaceID) {
                            case .opened:
                                // Don't set immersiveSpaceState to .open because there
                                // may be multiple paths to ImmersiveView.onAppear().
                                // Only set .open in ImmersiveView.onAppear().
                                break

                            case .userCancelled, .error:
                                // On error, we need to mark the immersive space
                                // as closed because it failed to open.
                                fallthrough
                            @unknown default:
                                // On unknown response, assume space did not open.
                                appModel.immersiveSpaceState = .closed
                        }

                    case .inTransition:
                        // This case should not ever happen because button is disabled for this case.
                        break
                }
            }
        } label: {
            Text(appModel.immersiveSpaceState == .open ? "Hide Immersive Space" : "Show Immersive Space")
        }
        .disabled(appModel.immersiveSpaceState == .inTransition)
        .animation(.none, value: 0)
        .fontWeight(.semibold)
    }
}

```

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