From 7bf8c09bb774f2996ef85274adfef6966d284c25 Mon Sep 17 00:00:00 2001 From: Ian Holloway Date: Tue, 7 May 2024 14:05:31 -0700 Subject: [PATCH] locations will update on there own now --- app/[dh_choice]/page.tsx | 10 ++-- app/global_search/page.tsx | 2 +- app/page.tsx | 6 +-- app/search/page.tsx | 6 +-- backend/myapi/db_functions/dining_halls.py | 31 ----------- backend/myapi/db_functions/locations.py | 31 +++++++++++ backend/myapi/db_functions/tasks.py | 61 ++++++++++++++++++++++ backend/myapi/models.py | 32 +++++++----- backend/myapi/urls.py | 2 +- backend/myapi/views.py | 47 ++++++++++++++--- 10 files changed, 163 insertions(+), 65 deletions(-) delete mode 100644 backend/myapi/db_functions/dining_halls.py create mode 100644 backend/myapi/db_functions/locations.py create mode 100644 backend/myapi/db_functions/tasks.py diff --git a/app/[dh_choice]/page.tsx b/app/[dh_choice]/page.tsx index e41a0cdf..5ee7c2dc 100644 --- a/app/[dh_choice]/page.tsx +++ b/app/[dh_choice]/page.tsx @@ -81,7 +81,7 @@ export default function Page({ searchParams }) { useEffect(() => { axios - .get("http://localhost:8000/myapi/dining-halls/") + .get("http://localhost:8000/myapi/locations/") .then((response) => { const dhs = response.data.locations; const dh_index = name_to_dh_index(searchParams.name, dhs); @@ -95,7 +95,7 @@ export default function Page({ searchParams }) { alert("No food categories found"); return; } - const timeOfDay = getTimeOfDay(); + const timeOfDay = getTimeOfDay(); const timeIndex = a_dh.categories.findIndex(category => category.name.toLowerCase() === timeOfDay); if (timeIndex !== -1) { setExpandedCategory(timeIndex); @@ -109,7 +109,7 @@ export default function Page({ searchParams }) { useEffect(() => { - const timeOfDay = getTimeOfDay(); + const timeOfDay = getTimeOfDay(); const timeIndex = categories.findIndex(category => category.name.toLowerCase() === timeOfDay); if (timeIndex !== -1) { setExpandedCategory(timeIndex); @@ -131,7 +131,7 @@ export default function Page({ searchParams }) { function getTimeOfDay(): string { const currentTime = new Date(); const currentHour = currentTime.getHours(); - + if (currentHour >= 7 && currentHour < 11) { return "breakfast"; } else if (currentHour >= 11 && currentHour < 16) { @@ -161,7 +161,7 @@ export default function Page({ searchParams }) {

{searchParams.name}

- + {/* Search button */}
diff --git a/app/global_search/page.tsx b/app/global_search/page.tsx index d200c17d..2fb7a97e 100644 --- a/app/global_search/page.tsx +++ b/app/global_search/page.tsx @@ -30,7 +30,7 @@ const BarebonesComponent = () => { useEffect(() => { axios - .get('http://localhost:8000/myapi/dining-halls/') + .get('http://localhost:8000/myapi/locations/') .then((response) => { const dhsData: DiningHall[] = response.data.locations; setDhs(dhsData); diff --git a/app/page.tsx b/app/page.tsx index 8cc2072a..420c703a 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -56,7 +56,7 @@ function Home() { useEffect(() => { axios - .get("http://localhost:8000/myapi/dining-halls/") + .get("http://localhost:8000/myapi/locations/") .then((response) => { const dhs: DiningHall[] = response.data["locations"]; setDhs(dhs); @@ -119,7 +119,7 @@ function Home() {
)} - + {noFoodsFound && (

No foods found at this dining hall.

@@ -183,4 +183,4 @@ export default function Page() { ); -} \ No newline at end of file +} diff --git a/app/search/page.tsx b/app/search/page.tsx index f2d1596c..cc85bcde 100644 --- a/app/search/page.tsx +++ b/app/search/page.tsx @@ -32,7 +32,7 @@ const BarebonesComponent = () => { useEffect(() => { axios - .get('http://localhost:8000/myapi/dining-halls/') + .get('http://localhost:8000/myapi/locations/') .then((response) => { const dhsData: DiningHall[] = response.data.locations; setDhs(dhsData); @@ -70,7 +70,7 @@ const BarebonesComponent = () => {
{/* Dining Hall Name */}

{diningHall} Search

- + {/* Search bar */}
{/* Adjust margin as needed */} { />
- + {/* Display search results if button clicked */} {showSearchResults && (
diff --git a/backend/myapi/db_functions/dining_halls.py b/backend/myapi/db_functions/dining_halls.py deleted file mode 100644 index f5645aea..00000000 --- a/backend/myapi/db_functions/dining_halls.py +++ /dev/null @@ -1,31 +0,0 @@ -from ..models import dining_hall_collection - - -def remove_dining_halls_from_db(names: list[str]) -> None: - for name in names: - dining_hall_collection.delete_many({"name": name}) - - -def add_dining_halls_to_db(dining_halls: list[dict]) -> None: - for dh in dining_halls: - dining_hall_collection.insert_one(dh) - - -def get_names_of_dining_halls(dining_halls: list[dict]) -> list[str]: - names = [] - for dh in dining_halls: - names.append(dh["name"]) - return names - - -def remove_add_dining_halls_to_db(dining_halls: list[dict]) -> None: - # get names of dining halls - names = get_names_of_dining_halls(dining_halls) - # remove dining halls with the names - remove_dining_halls_from_db(names) - # add dining halls to db - add_dining_halls_to_db(dining_halls) - - -def get_all_dining_halls_from_db() -> list[dict]: - return list(dining_hall_collection.find({})) diff --git a/backend/myapi/db_functions/locations.py b/backend/myapi/db_functions/locations.py new file mode 100644 index 00000000..97559e2a --- /dev/null +++ b/backend/myapi/db_functions/locations.py @@ -0,0 +1,31 @@ +from ..models import locations_collection + + +def remove_locations_from_db(names: list[str]) -> None: + for name in names: + locations_collection.delete_many({"name": name}) + + +def add_locations_to_db(locations: list[dict]) -> None: + for dh in locations: + locations_collection.insert_one(dh) + + +def get_names_of_locations(locations: list[dict]) -> list[str]: + names = [] + for dh in locations: + names.append(dh["name"]) + return names + + +def remove_add_locations_to_db(locations: list[dict]) -> None: + # get names of locations + names = get_names_of_locations(locations) + # remove locations with the names + remove_locations_from_db(names) + # add locations to db + add_locations_to_db(locations) + + +def get_all_locations_from_db() -> list[dict]: + return list(locations_collection.find({})) diff --git a/backend/myapi/db_functions/tasks.py b/backend/myapi/db_functions/tasks.py new file mode 100644 index 00000000..9ad7efc1 --- /dev/null +++ b/backend/myapi/db_functions/tasks.py @@ -0,0 +1,61 @@ +from celery.app import task +from ..models import tasks_collection +from datetime import datetime + +# import time from django +from django.utils import timezone + +""" +name: str +last_update: str +""" + +def set_task_last_update(task_name: str) -> None: + """ + Set the time that the task were last update the time should be based upon the database time + """ + # get the time from django + time_now: datetime = timezone.now() + + # convert the time to a string + time_str = time_now.strftime("%Y-%m-%d %H:%M:%S") + + # get the task from the tasks collection + task: dict | None = tasks_collection.find_one({"name": task_name}) + + # check if the task exists + if task is None: + # create a new task + task = { + "name": task_name, + "last_update": time_str + } + # insert the task into the tasks collection + tasks_collection.insert_one(task) + else: + # update the task + tasks_collection.update_one( + {"name": task_name}, + {"$set": {"last_update": time_str}} + ) + +def get_task_last_update(task_name: str) -> datetime | None: + """ + Get the last update time of the task from the database + """ + # find the task in the tasks collection + task: dict | None = tasks_collection.find_one({"name": task_name}) + + # check if the location exists + if task is None: + return None + + # get the last update time + last_update = task["last_update"] + + # convert the string to a datetime object + last_update_time = datetime.strptime(last_update, "%Y-%m-%d %H:%M:%S") + + return last_update_time + + diff --git a/backend/myapi/models.py b/backend/myapi/models.py index cf19c061..5fad0881 100644 --- a/backend/myapi/models.py +++ b/backend/myapi/models.py @@ -1,26 +1,32 @@ from django.db import models +from django.conf.locale import ta +from celery.app import task +from requests import get from db_connection import db # Create your models here. -# Dining Hall Model -dining_hall_collection = db["dining_hall"] +# locations Model +locations_collection = db["locations"] -# Food Rating Model -foods_collection = db["food_rating"] +# Food Model +foods_collection = db["food"] # Users Model users_collection = db["users"] +# Tasks Model +tasks_collection = db["tasks"] -# NOTE: This is temporary and will be replaced with a background task -from webscraper.food_locations import FoodLocations -# Fetch dining halls -fo = FoodLocations() -# Get dining halls as a list of json objects -dining_halls: list[dict] = [dh.to_dict() for dh in fo.get_locations()] -# Add dining halls to db -from .db_functions.dining_halls import remove_add_dining_halls_to_db +# # NOTE: This is temporary and will be replaced with a background task +# from webscraper.food_locations import FoodLocations -remove_add_dining_halls_to_db(dining_halls) +# # Fetch dining halls +# fo = FoodLocations() +# # Get dining halls as a list of json objects +# dining_halls: list[dict] = [dh.to_dict() for dh in fo.get_locations()] +# # Add dining halls to db +# from .db_functions.dining_halls import remove_add_dining_halls_to_db + +# remove_add_dining_halls_to_db(dining_halls) diff --git a/backend/myapi/urls.py b/backend/myapi/urls.py index 49ca2dfb..0e34851d 100644 --- a/backend/myapi/urls.py +++ b/backend/myapi/urls.py @@ -3,5 +3,5 @@ urlpatterns = [ path("hello-world/", views.hello_world, name="hello_world"), - path("dining-halls/", views.get_dining_halls, name="dining_halls"), + path("locations/", views.get_locations, name="locations"), ] diff --git a/backend/myapi/views.py b/backend/myapi/views.py index cf635087..ae87d952 100644 --- a/backend/myapi/views.py +++ b/backend/myapi/views.py @@ -1,26 +1,57 @@ +from django.conf.locale import fr from rest_framework.response import Response from rest_framework.decorators import api_view -from .db_functions.dining_halls import get_all_dining_halls_from_db +from .db_functions.locations import get_all_locations_from_db, remove_add_locations_to_db +from .db_functions.tasks import set_task_last_update, get_task_last_update +from webscraper.food_locations import FoodLocations +from django.utils import timezone +from datetime import datetime + # Create your views here. @api_view(["GET"]) def hello_world(request): return Response({"message": "Hello, world!"}) -# Get the list of dining halls +# Get the list of locations at UCSC and their information @api_view(["GET"]) -def get_dining_halls(request): - # Get all dining halls from the db - dining_halls: list[dict] = get_all_dining_halls_from_db() +def get_locations(request): + # Get the last update time of the locations + last_update: datetime | None = get_task_last_update(task_name="locations") + + # get the current time and make it naive + time_now: datetime = timezone.now() + time_now = time_now.replace(tzinfo=None) + + print("Last time : ", last_update) + print("Current time: ", time_now) + + # check if not updated in the last hour + if last_update is None or (time_now - last_update).seconds > 3600: + print("Locations need to be updated...") + # fetch the locations from the web scraper and add them to the db + fo = FoodLocations() + locations: list[dict] = [dh.to_dict() for dh in fo.get_locations()] + # add the locations to the db + remove_add_locations_to_db(locations) + + # update the last update time + set_task_last_update(task_name="locations") + + else: + print("Locations are up to date. Getting from DB...") + # Get all locations from the db + locations: list[dict] = get_all_locations_from_db() # remove the _id field from each dining hall - for dh in dining_halls: - dh.pop("_id") + for dh in locations: + if "_id" in dh: + dh.pop("_id") # Convert the list of dining halls to json - json_data = {"locations": dining_halls} + json_data = {"locations": locations} return Response(json_data)