# Project export: Cal Housing

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: Cal Hacks 10.0
- Tagline: Revolutionizing scattered house searching with AI. Cal Housing finds your dream home, perfectly balancing budget and distance. Goodbye to compromises and searching stress. Your ideal housing awaits!
- Devpost: https://devpost.com/software/cal-housing
- GitHub: https://github.com/mjkwak0184/hacks-housing
- Team: 4 GitHub contributor(s) — yaowenc2 (25 commits), Minjae Kwak (14 commits), Zixun (3 commits), Terry Kim (1 commits)

## Devpost submission (written by the team)

### Overview

As a former student, I personally experienced the frustration and challenges of finding suitable housing near the campus. The scattered information, countless websites, and tedious manual searches made the process daunting. This personal experience inspired me to create "Cal Housing", a revolutionary platform to transform the way people find their housing.

### Inspiration

The idea behind "Cal Housing" was born from my own struggles. I understood the pain points of students and professionals looking for housing near dynamic regions like Berkeley. I wanted to eliminate the compromise between price and distance, making the entire process more efficient, personalized, and stress-free. What I Learned My journey involved diving deep into the real estate market, understanding the nuances of different neighborhoods, and learning about the preferences and pain points of prospective renters (especially students). I also delved into the potential of advanced AI technologies to solve these problems. Building the Project Market Research: I conducted extensive market research to identify gaps in the existing housing search platforms and the unique needs of our target audience. Market Research: I conducted extensive market research to identify gaps in the existing housing search platforms and the unique needs of our target audience. AI Integration: Leveraging LLM and AI models, we integrated algorithms that could process user preferences and property data efficiently, providing tailored recommendations. AI Integration: Leveraging LLM and AI models, we integrated algorithms that could process user preferences and property data efficiently, providing tailored recommendations. User-Centric Design: We designed the platform with the user in mind, making it intuitive, easy to navigate, and highly customizable. Users can specify their budget, proximity to Berkeley, and other preferences with just a few clicks. User-Centric Design: We designed the platform with the user in mind, making it intuitive, easy to navigate, and highly customizable. Users can specify their budget, proximity to Berkeley, and other preferences with just a few clicks. Challenges Data Integration: Gathering and integrating property data from sources was a significant challenge. Ensuring the data was up-to-date and accurate required a dedicated effort. Processing the back-end and managing the data baed on user preference was also one of the challenges. Data Integration: Gathering and integrating property data from sources was a significant challenge. Ensuring the data was up-to-date and accurate required a dedicated effort. Processing the back-end and managing the data baed on user preference was also one of the challenges. Algorithm Refinement: Developing AI algorithms that could accurately predict the ideal housing options for users while considering their individual preferences and budgets was complex and required continuous refinement. Algorithm Refinement: Developing AI algorithms that could accurately predict the ideal housing options for users while considering their individual preferences and budgets was complex and required continuous refinement. Competitive Market: The real estate and housing market is highly competitive. We faced challenges in differentiating ourselves and gaining trust among users. Competitive Market: The real estate and housing market is highly competitive. We faced challenges in differentiating ourselves and gaining trust among users. Conclusion My personal experience as a student struggling to find suitable housing near the campus was the driving force behind the creation of "Cal Housing". Through dedication, innovation, and a commitment to solving the challenges of housing searches, we've built a platform that offers a streamlined, efficient, and personalized solution. Our mission is to ensure that no one has to compromise when finding their ideal home, and we're excited to continue improving and expanding our services in the future.

## README (from the GitHub repository)

# My Housing Search Journey: From Frustration to Innovation

As a former student, I personally experienced the frustration and challenges of finding suitable housing near the campus. The scattered information, countless websites, and tedious manual searches made the process daunting. This personal experience inspired me to created "Cal Housing", a revolutionary platform to transform the way people find their dream homes.

## **Inspiration**
The idea behind "Cal Housing" was born from my own struggles. I understood the pain points of students and professionals looking for housing near dynamic regions like Berkeley. I wanted to eliminate the compromise between price and distance, making the entire process more efficient, personalized, and stress-free.

<img src="systemDesignDiagram2.jpg" alt="Image Caption" width="50%" />
<img src="housing.jpeg" alt="Image Caption" width="50%" />


## **What I Learned**
My journey involved diving deep into the real estate market, understanding the nuances of different neighborhoods, and learning about the preferences and pain points of prospective renters. I also delved into the potential of advanced AI technologies to solve these problems.

## **Building the Project**
- **Market Research**: I conducted extensive market research to identify gaps in the existing housing search platforms and the unique needs of our target audience.

- **AI Integration**: Leveraging LLM and AI models, we integrated algorithms that could process user preferences and property data efficiently, providing tailored recommendations.

- **User-Centric Design**: We designed the platform with the user in mind, making it intuitive, easy to navigate, and highly customizable. Users can specify their budget, proximity to Berkeley, and other preferences with just a few clicks.

## **Challenges**
- **Data Integration**: Gathering and integrating property data from various sources was a significant challenge. Ensuring the data was up-to-date and accurate required a dedicated effort.

- **Algorithm Refinement**: Developing AI algorithms that could accurately predict the ideal housing options for users while considering their individual preferences and budgets was complex and required continuous refinement.

- **Competitive Market**: The real estate and housing market is highly competitive. We faced challenges in differentiating ourselves and gaining trust among users.

## **Conclusion**
My personal experience as a student struggling to find suitable housing near the campus was the driving force behind the creation of "Cal Housing". Through dedication, innovation, and a commitment to solving the challenges of housing searches, we've built a platform that offers a streamlined, efficient, and personalized solution. Our mission is to ensure that no one has to compromise when finding their ideal home, and we're excited to continue improving and expanding our services in the future.


## Detected evidence (automated analysis)

Indexed codebase: 50 recognized source files, 289 KB.
- CSS (language) — detected in the code
- JavaScript (language) — detected in the code
- Next.js (technology) — detected in the code
- Python (language) — detected in the code
- React (technology) — detected in the code
- SQL (language) — detected in the code
- Tailwind CSS (technology) — detected in the code

## Codebase structure (from repository index)

### Files (65 of 65)

```
.gitignore
app/.gitignore
app/.web/.gitignore
app/.web/bun.lockb
app/.web/components/reflex/chakra_color_mode_provider.js
app/.web/components/reflex/radix_themes_color_mode_provider.js
app/.web/env.json
app/.web/jsconfig.json
app/.web/next.config.js
app/.web/package.json
app/.web/pages/_app.js
app/.web/pages/_document.js
app/.web/pages/404.js
app/.web/pages/form.js
app/.web/pages/housing.js
app/.web/pages/index.js
app/.web/pages/login.js
app/.web/postcss.config.js
app/.web/reflex.json
app/.web/styles/code/prism.js
app/.web/styles/styles.css
app/.web/styles/tailwind.css
app/.web/tailwind.config.js
app/.web/utils/client_side_routing.js
app/.web/utils/components.js
app/.web/utils/context.js
app/.web/utils/helpers/dataeditor.js
app/.web/utils/state.js
app/.web/utils/theme.js
app/alembic.ini
app/alembic/env.py
app/alembic/README
app/alembic/script.py.mako
app/alembic/versions/d9525c3047c1_.py
app/app/__init__.py
app/app/app.py
app/app/components/__init__.py
app/app/components/ListingCategory.py
app/app/components/ListingComponent.py
app/app/components/sidebar.py
app/app/data/data process.py
app/app/data/Listing.py
app/app/data/post.json
app/app/data/User-Listing.py
app/app/pages/__init__.py
app/app/pages/form.py
app/app/pages/housing.py
app/app/pages/index.py
app/app/pages/login.py
app/app/pages/logout.py
app/app/states/base.py
app/app/states/post_state.py
app/app/states/user_state.py
app/app/styles.py
app/app/templates/__init__.py
app/app/templates/template.py
app/README.md
app/requirements.txt
app/rxconfig.py
mindsdb/Classifier.sql
README.md
requirements.txt
scraper/facebook_parser.py
scraper/postgresql.py
scraper/requirements.txt
```

### Dependencies

- app/.web/package.json: @chakra-ui/icons@2.0.19, @chakra-ui/react@2.6.1, @chakra-ui/system@2.5.7, @emotion/react@^11.11.0, @emotion/styled@^11.11.0, autoprefixer@10.4.14, axios@1.4.0, focus-visible@5.2.0, framer-motion@10.16.4, json5@2.2.3, next@13.5.4, next-sitemap@4.1.8, next-themes@0.2.0, postcss@8.4.24, react@18.2.0, react-debounce-input@3.3.0, react-dom@18.2.0, socket.io-client@4.6.1, tailwindcss@3.3.2, universal-cookie@4.0.4
- app/requirements.txt: python-dotenv, reflex@==0.3.1
- requirements.txt: reflex@==0.3.1
- scraper/requirements.txt: facebook-scraper@>= 0.2.3, psycopg2-binary

### Recent commits (newest first)

- Merge branch 'main' of https://github.com/mjkwak0184/hacks-housing
- latest
- Update README.md
- Add files via upload
- Fix Design
- Fix design
- Update README.md
- improved housing grid
- form submission working
- Merge remote-tracking branch 'refs/remotes/origin/main'
- fix bug indexing
- Fix more bug
- Fix layout bug
- housemate
- post
- Ensure Diagram addded
- Add System Design Diagram
- updated readme intro
- updated check box
- main home page designed

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

### requirements.txt

```

reflex==0.3.1

```

### app/requirements.txt

```

reflex==0.3.1
python-dotenv
```

### scraper/requirements.txt

```
facebook-scraper >= 0.2.3
psycopg2-binary

```

### app/.web/package.json

```
{
  "name": "reflex",
  "scripts": {
    "dev": "next dev",
    "export": "next build && next export -o _static",
    "export-sitemap": "next build && next-sitemap && next export -o _static",
    "prod": "next start"
  },
  "dependencies": {
    "@chakra-ui/icons": "2.0.19",
    "@chakra-ui/react": "2.6.1",
    "@chakra-ui/system": "2.5.7",
    "@emotion/react": "^11.11.0",
    "@emotion/styled": "^11.11.0",
    "axios": "1.4.0",
    "focus-visible": "5.2.0",
    "framer-motion": "10.16.4",
    "json5": "2.2.3",
    "next": "13.5.4",
    "next-sitemap": "4.1.8",
    "next-themes": "0.2.0",
    "react": "18.2.0",
    "react-debounce-input": "3.3.0",
    "react-dom": "18.2.0",
    "socket.io-client": "4.6.1",
    "universal-cookie": "4.0.4"
  },
  "devDependencies": {
    "autoprefixer": "10.4.14",
    "postcss": "8.4.24",
    "tailwindcss": "3.3.2"
  }
}
```

### app/app/app.py

```python
"""Welcome to Reflex!."""

from app import styles
from dotenv import load_dotenv
load_dotenv()

# Import all the pages.
from app.pages import *

import reflex as rx

# Create the app and compile it.
app = rx.App(style=styles.base_style)

app.compile()

```

### app/app/pages/index.py

```python
"""The home page of the app."""
import reflex as rx

from app import styles
from app.templates import template
from app.styles import accent_color, accent_text_color




@template(route="/", title="Home")
def index() -> rx.Component:
    """The home page.

    Returns:
        The UI for the home page.
    """
    
    style = {
    "color": "#333",              
    "font-weight": "600",
    "font-size": "1em",
    "padding": "12px 12px",
    "border-radius": "8px",
    }


    return rx.vstack(
            rx.hstack(
                rx.vstack(
                rx.text("Make Campus Housing Easy.", height="100%", font_size = "2.5em", font_weight="bold"),
                rx.text("Navigating the housing market, especially around dynamic regions like Berkeley, \
                    can be daunting. But what if there was a smarter way to find your dream home, without the usual \
                    hassles?", width="100%", style = style),
                ),
                rx.spacer(size="2em"),
                rx.image(src="https://www.brayerelectric.com/wp-content/uploads/2020/11/AnnaHead_Final.jpg", 
                         width="50%", 
                         height = "50%",
                         border="1px solid #555",
                         box_shadow="lg")
            ),
            rx.hstack (
                rx.image(src="  https://images.unsplash.com/photo-1555854877-bab0e564b8d5?auto=format&fit=crop&q=80&w=1000&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxzZWFyY2h8Mnx8c3R1ZGVudCUyMGhvdXNpbmd8ZW58MHx8MHx8fDA%3D", 
                         width="50%", 
                         height = "50%", 
                         align = "left",
                         border="1px solid #555",
                         box_shadow="lg"),
                rx.vstack(
                rx.text("Personalized AI Solution", height="100%", font_size = "2.5em", font_weight="bold"),
                rx.text("Enter [Your Startup Name]. Our platform, powered by advanced AI, is not just about finding a home\
                    – it's about finding the right home for you. Share with us your budget and how close or far\
                    you'd like to be from Berkeley, and our system will carefully analyze these preferences, \
                    along with other specifics you provide.", width="100%", style = style),
            ),
            ),
            rx.hstack(
                rx.stack(
                rx.text("Bringing You Joy", height = "100%", font_size = "2.5em", font_weight="bold"),
                rx.spacer(size="4em"),
                rx.text("No more compromise between price and distance. \
                    Whether you want a cozy spot just a stone's throw from Berkeley or a serene escape a little further out, \
                    our platform is designed to find the best matches, tailored just for you. Enjoy a streamlined, efficient, and personalized home hunting experience with [Your Startup Name]. \
                    Because your ideal home, at the right price and distance, is waiting.", width="100%", style = style),
                ),
                rx.spacer(size="2em"),
                rx.image(src="https://www.pace.edu/sites/default/files/styles/16_9_1600x900/public/2022-04/housing-interior-hero.jpg?h=993b43e0&itok=PEYH6fLR", 
                         width="50%", 
                         align = "right",
                         height = "50%",
                         border="1px solid #555",
                         box_shadow="lg"),
            ),
        )

    

```

### app/.web/pages/index.js

```javascript
import { Fragment, useContext, useEffect, useRef, useState } from "react"
import { useRouter } from "next/router"
import { Event, getAllLocalStorageItems, getRefValue, getRefValues, isTrue, preventDefault, refs, spreadArraysOrObjects, uploadFiles, useEventLoop } from "/utils/state"
import { ColorModeContext, EventLoopContext, initialEvents, StateContext } from "/utils/context.js"
import "focus-visible/dist/focus-visible"
import { Box, HStack, Image, Link, Modal, ModalBody, ModalContent, ModalHeader, ModalOverlay, Spacer, Stack, Text, Tooltip, VStack } from "@chakra-ui/react"
import { getEventURL } from "/utils/state.js"
import NextLink from "next/link"
import NextHead from "next/head"



export default function Component() {
  const state = useContext(StateContext)
  const router = useRouter()
  const [ colorMode, toggleColorMode ] = useContext(ColorModeContext)
  const focusRef = useRef();
  
  // Main event loop.
  const [addEvents, connectError] = useContext(EventLoopContext)

  // Set focus to the specified element.
  useEffect(() => {
    if (focusRef.current) {
      focusRef.current.focus();
    }
  })

  // Route after the initial page hydration.
  useEffect(() => {
    const change_complete = () => addEvents(initialEvents())
    router.events.on('routeChangeComplete', change_complete)
    return () => {
      router.events.off('routeChangeComplete', change_complete)
    }
  }, [router])


  return (
    <Fragment>
  <Fragment>
  {isTrue(connectError !== null) ? (
  <Fragment>
  <Modal isOpen={connectError !== null}>
  <ModalOverlay>
  <ModalContent>
  <ModalHeader>
  {`Connection Error`}
</ModalHeader>
  <ModalBody>
  <Text>
  {`Cannot connect to server: `}
  {(connectError !== null) ? connectError.message : ''}
  {`. Check if server is reachable at `}
  {getEventURL().href}
</Text>
</ModalBody>
</ModalContent>
</ModalOverlay>
</Modal>
</Fragment>
) : (
  <Fragment/>
)}
</Fragment>
  <VStack alignItems={`flex-start`} sx={{"transition": "left 0.5s, width 0.5s", "position": "relative"}}>
  <Box sx={{"display": ["none", "none", "block"], "minWidth": "22em", "width": "100%", "top": "0px", "borderRight": "1px solid #E2E2E2"}}>
  <HStack>
  <HStack sx={{"width": "100%", "padding": "1em"}}>
  <Image src={`/calhouse.svg`} sx={{"height": "7em", "width": "10em"}}/>
  <Spacer/>
</HStack>
  <Spacer sx={{"size": "2em"}}/>
  <HStack alignItems={`flex-start`} sx={{"width": "100%", "overflowY": "auto", "padding": "1em"}}>
  <Tooltip label={`Home Page`}>
  <Link as={NextLink} href={isTrue((false && !state.is_logged_in)) ? `` : `/`} sx={{"width": "100%"}}>
  <HStack sx={{"bg": isTrue((false && !state.is_logged_in)) ? `lightgray` : isTrue((state.router.page.path === "/home") || ((state.router.page.path === "/") && true)) ? `#FDB515` : `transparent`, "color": isTrue((false && !state.is_logged_in)) ? `gray` : isTrue((state.router.page.path === "/home") || ((state.router.page.path === "/") && true)) ? `#003262` : `#333`, "borderRadius": "0.5rem", "boxShadow": "0px 4px 10px rgba(0, 0, 0, 0.1)", "width": "100%", "paddingX": "1em"}}>
  <Text sx={{"fontWeight": "bold", "height": "2.5em", "padding": "0.5em"}}>
  {`Home`}
</Text>
</HStack>
</Link>
</Tooltip>
  <Tooltip label={`Preference Form for AI housing recommendations, login required`}>
  <Link as={NextLink} href={isTrue((true && !state.is_logged_in)) ? `` : `/form`} sx={{"width": "100%"}}>
  <HStack sx={{"bg": isTrue((true && !state.is_logged_in)) ? `lightgray` : isTrue((state.router.page.path === "/form") || ((state.router.page.path === "/") && false)) ? `#FDB515` : `transparent`, "color": isTrue((true && !state.is_logged_in)) ? `gray` : isTrue((state.router.page.path === "/form") || ((state.router.page.path === "/") && false)) ? `#003262` : `#333`, "borderRadius": "0.5rem", "boxShadow": "0px 4px 10px rgba(0, 0, 0, 0.1)", "width": "100%", "paddingX": "1em"}}>
  <Text sx={{"fontWeight": "bold", "height": "2.5em", "padding": "0.5em"}}>
  {`Form`}
</Text>
</HStack>
</Link>
</Tooltip>
  <Tooltip label={`Display of housing lists/recommendations`}>
  <Link as={NextLink} href={isTrue((false && !state.is_logged_in)) ? `` : `/housing`} sx={{"width": "100%"}}>
  <HStack sx={{"bg": isTrue((false && !state.is_logged_in)) ? `lightgray` : isTrue((state.router.page.path === "/housing") || ((state.router.page.path === "/") && false)) ? `#FDB515` : `transparent`, "color": isTrue((false && !state.is_logged_in)) ? `gray` : isTrue((state.router.page.path === "/housing") || ((state.router.page.path === "/") && false)) ? `#003262` : `#333`, "borderRadius": "0.5rem", "boxShadow": "0px 4px 10px rgba(0, 0, 0, 0.1)", "width": "100%", "paddingX": "1em"}}>
  <Text sx={{"fontWeight": "bold", "height": "2.5em", "padding": "0.5em"}}>
  {`Housing`}
</Text>
</HStack>
</Link>
</Tooltip>
  <Tooltip label={`Login Page`}>
  <Link as={NextLink} href={isTrue((false && !state.is_logged_in)) ? `` : `/login`} sx={{"width": "100%"}}>
  <HStack sx={{"bg": isTrue((false && !state.is_logged_in)) ? `lightgray` : isTrue((state.router.page.path === "/login") || ((state.router.page.path === "/") && false)) ? `#FDB515` : `transparent`, "color": isTrue((false && !state.is_logged_in)) ? `gray` : isTrue((state.router.page.path === "/login") || ((state.router.page.path === "/") && false)) ? `#003262` : `#333`, "borderRadius": "0.5rem", "boxShadow": "0px 4px 10px rgba(0, 0, 0, 0.1)", "width": "100%", "paddingX": "1em"}}>
  <Text sx={{"fontWeight": "bold", "height": "2.5em", "padding": "0.5em"}}>
  {`Login`}
</Text>
</HStack>
</Link>
</Tooltip>
</HStack>
  <Spacer/>
</HStack>
</Box>
  <Box>
  <Box>
  <VStack>
  <HStack>
  <VStack>
  <Text sx={{"height": "100%", "fontSize": "2.5em", "fontWeight": "bold"}}>
  {`Make Campus Housing Easy.`}
</Text>
  <Text sx={{"color": "#333", "font-weight": "600", "font-size": "1em", "padding": "12px 12px", "border-radius": "8px", "width": "100%"}}>
  {`Navigating the housing market, especially around dynamic regions like Berkeley,                     can be daunting. But w
[truncated — 2735 more characters]
```

### app/rxconfig.py

```python
import reflex as rx
import os

config = rx.Config(
    app_name="app",
    db_url = os.getenv('DB_URL')
)
```

### scraper/postgresql.py

```python
import psycopg2
from secrets import db_credentials


class PostgreSQL:
	connection = False
	
	@staticmethod
	def insert(table, data):
		assert len(data) > 0
		cursor = PostgreSQL.connection.cursor()
		keys = list(data.keys())
		values = list(data.values())
		placeholders = ", ".join(["%s"] * len(values))

		cols = ", ".join(keys)
		SQL = f"INSERT INTO {table} ({cols}) VALUES ({placeholders}) ON CONFLICT (id) DO NOTHING;"

		cursor.execute(SQL, values)
		PostgreSQL.connection.commit()
		cursor.close()

	@staticmethod
	def isconnected():
		return PostgreSQL.connection

	@staticmethod
	def connect():
		PostgreSQL.connection = psycopg2.connect(database=db_credentials["database"], user=db_credentials["user"], password=db_credentials["password"], host=db_credentials["host"], port=db_credentials["port"])
	
	@staticmethod
	def disconnect():
		if PostgreSQL.connection:
			PostgreSQL.connection.close()
```

### mindsdb/Classifier.sql

```sql
CREATE DATABASE example_db
WITH ENGINE = "postgres",
PARAMETERS = {
    "user": "demo_user",
    "password": "demo_password",
    "host": "3.220.66.106",
    "port": "5432",
    "database": "demo"
    };




CREATE ML_ENGINE openai_engine
FROM openai
USING
    api_key = 'your-openai-api-key';


CREATE MODEL mindsdb.combined_model_
PREDICT parsed_output
USING
  engine = 'openai_engine',
  prompt_template = 'You are a classifier for housing posts in Berkeley. 
  You want to provide classification only based on the post content. Respond to me in JSON format after analyzing :{{body}} 
  Only provide key-value pairs for "type", "price", "unit_type", "num_bed", "location", "distance". 
  For key "type", assign an integer 1 if the post is posted by people looking to renting a place to stay, 2 if the post is posted by landlord/current tenant looking for renters/subleases, 3 for unknown. 
  For key "price", assign a number for the rent the post is looking for. If rent is not specified, ignore this key. 
  For key "num_bed", assign a number for the number of bedrooms in the house, if the number of bedrooms is not specified, ignore this key.
  For "unit_type", assign 1 if a room is rented out, assign 2 if an entire house/apartment with multiple rooms is rented out, if the type of unit is not specified, ignore this key. 
  For "location", assign address mentioned the post, if the location of the housing is not specified, ignore this key. 
  For "distance", calculate and assign a number in miles for the distance between the housing location and UC Berkeley Sather Gate, if the location of the housing is not specified, ignore this key.';
  


CREATE OR REPLACE TABLE psql_datasource.posts_classification (
    SELECT input.id, input.url, input.timestamp, input.body, input.images, output.parsed_output
    FROM psql_datasource.posts AS input
    JOIN combined_model_ AS output
);


```

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