diff --git a/common/api/hooks/service.ts b/common/api/hooks/service.ts index cf98dfc54..fb9f4d14e 100644 --- a/common/api/hooks/service.ts +++ b/common/api/hooks/service.ts @@ -1,10 +1,10 @@ import { useQuery } from '@tanstack/react-query'; -import type { FetchTripCountsOptions } from '../../types/api'; +import type { FetchScheduledServiceOptions } from '../../types/api'; import { ONE_HOUR } from '../../constants/time'; -import { fetchTripCounts } from '../service'; +import { fetchScheduledService } from '../service'; -export const useTripCounts = (params: FetchTripCountsOptions, enabled?: boolean) => { - return useQuery(['trips', params], () => fetchTripCounts(params), { +export const useScheduledService = (params: FetchScheduledServiceOptions, enabled?: boolean) => { + return useQuery(['scheduledservice', params], () => fetchScheduledService(params), { enabled: enabled, staleTime: ONE_HOUR, }); diff --git a/common/api/service.ts b/common/api/service.ts index 91ac2296d..9239278dc 100644 --- a/common/api/service.ts +++ b/common/api/service.ts @@ -1,13 +1,13 @@ -import type { FetchTripCountsOptions } from '../types/api'; -import { FetchTripCountsParams } from '../types/api'; -import type { TripCounts } from '../types/dataPoints'; +import type { FetchScheduledServiceOptions } from '../types/api'; +import { FetchScheduledServiceParams } from '../types/api'; +import type { ScheduledService } from '../types/dataPoints'; import { APP_DATA_BASE_PATH } from '../utils/constants'; -export const fetchTripCounts = async ( - params: FetchTripCountsOptions -): Promise => { - if (!params[FetchTripCountsParams.routeId]) return undefined; - const url = new URL(`${APP_DATA_BASE_PATH}/api/tripcounts`, window.location.origin); +export const fetchScheduledService = async ( + params: FetchScheduledServiceOptions +): Promise => { + if (!params[FetchScheduledServiceParams.routeId]) return undefined; + const url = new URL(`${APP_DATA_BASE_PATH}/api/scheduledservice`, window.location.origin); Object.keys(params).forEach((paramKey) => { url.searchParams.append(paramKey, params[paramKey]); }); diff --git a/common/types/api.ts b/common/types/api.ts index 6cfa152d4..91e16402e 100644 --- a/common/types/api.ts +++ b/common/types/api.ts @@ -63,11 +63,11 @@ export enum FetchSpeedsParams { line = 'line', } -export type FetchTripCountsOptions = { - [key in FetchTripCountsParams]?: string; +export type FetchScheduledServiceOptions = { + [key in FetchScheduledServiceParams]?: string; }; -export enum FetchTripCountsParams { +export enum FetchScheduledServiceParams { startDate = 'start_date', endDate = 'end_date', routeId = 'route_id', diff --git a/common/types/dataPoints.ts b/common/types/dataPoints.ts index 2d7f1f66d..fc7467159 100644 --- a/common/types/dataPoints.ts +++ b/common/types/dataPoints.ts @@ -118,7 +118,7 @@ export type ServiceLevels = { }; }; -export type TripCounts = { +export type ScheduledService = { counts: number[]; start_date: string; end_date: string; diff --git a/modules/service/PercentageServiceGraphWrapper.tsx b/modules/service/PercentageServiceGraphWrapper.tsx index 4b292563e..6374660d0 100644 --- a/modules/service/PercentageServiceGraphWrapper.tsx +++ b/modules/service/PercentageServiceGraphWrapper.tsx @@ -1,6 +1,6 @@ import React from 'react'; import type { SetStateAction } from 'react'; -import type { DeliveredTripMetrics, TripCounts } from '../../common/types/dataPoints'; +import type { DeliveredTripMetrics, ScheduledService } from '../../common/types/dataPoints'; import { WidgetCarousel } from '../../common/components/general/WidgetCarousel'; import { PercentageWidgetValue } from '../../common/types/basicWidgets'; import { WidgetForCarousel } from '../../common/components/widgets/internal/WidgetForCarousel'; @@ -14,7 +14,7 @@ import { getPercentageData, getAverageWithNaNs } from './utils/utils'; interface PercentageServiceGraphWrapperProps { data: DeliveredTripMetrics[]; - predictedData: TripCounts; + predictedData: ScheduledService; config: ParamsType; startDate: string; endDate: string; diff --git a/modules/service/ServiceDetails.tsx b/modules/service/ServiceDetails.tsx index e5dfb6ea6..8c1988116 100644 --- a/modules/service/ServiceDetails.tsx +++ b/modules/service/ServiceDetails.tsx @@ -4,7 +4,7 @@ import dayjs from 'dayjs'; import utc from 'dayjs/plugin/utc'; import { useDelimitatedRoute } from '../../common/utils/router'; import { ChartPlaceHolder } from '../../common/components/graphics/ChartPlaceHolder'; -import { useTripCounts } from '../../common/api/hooks/service'; +import { useScheduledService } from '../../common/api/hooks/service'; import { Layout } from '../../common/layouts/layoutTypes'; import { PageWrapper } from '../../common/layouts/PageWrapper'; import { getSpeedGraphConfig } from '../speed/constants/speeds'; @@ -34,7 +34,7 @@ export function ServiceDetails() { enabled ); - const predictedData = useTripCounts( + const predictedData = useScheduledService( { start_date: startDate, end_date: endDate, diff --git a/modules/service/ServiceGraph.tsx b/modules/service/ServiceGraph.tsx index 0c0e17506..17b7a524e 100644 --- a/modules/service/ServiceGraph.tsx +++ b/modules/service/ServiceGraph.tsx @@ -16,12 +16,12 @@ import { useBreakpoint } from '../../common/hooks/useBreakpoint'; import { watermarkLayout } from '../../common/constants/charts'; import { ChartBorder } from '../../common/components/charts/ChartBorder'; import { ChartDiv } from '../../common/components/charts/ChartDiv'; -import type { DeliveredTripMetrics, TripCounts } from '../../common/types/dataPoints'; +import type { DeliveredTripMetrics, ScheduledService } from '../../common/types/dataPoints'; import { getShuttlingBlockAnnotations } from './utils/graphUtils'; interface ServiceGraphProps { data: DeliveredTripMetrics[]; - predictedData: TripCounts; + predictedData: ScheduledService; config: ParamsType; startDate: string; endDate: string; diff --git a/modules/service/ServiceGraphWrapper.tsx b/modules/service/ServiceGraphWrapper.tsx index ec6f97829..cbec6ad9b 100644 --- a/modules/service/ServiceGraphWrapper.tsx +++ b/modules/service/ServiceGraphWrapper.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import type { DeliveredTripMetrics, TripCounts } from '../../common/types/dataPoints'; +import type { DeliveredTripMetrics, ScheduledService } from '../../common/types/dataPoints'; import type { ParamsType } from '../speed/constants/speeds'; import { WidgetCarousel } from '../../common/components/general/WidgetCarousel'; import { TripsWidgetValue } from '../../common/types/basicWidgets'; @@ -10,7 +10,7 @@ import { getServiceWidgetValues } from './utils/utils'; import { ServiceGraph } from './ServiceGraph'; interface ServiceGraphWrapperProps { data: DeliveredTripMetrics[]; - predictedData: TripCounts; + predictedData: ScheduledService; config: ParamsType; startDate: string; endDate: string; diff --git a/modules/service/ServiceOverviewWrapper.tsx b/modules/service/ServiceOverviewWrapper.tsx index d43d55438..529ebd05d 100644 --- a/modules/service/ServiceOverviewWrapper.tsx +++ b/modules/service/ServiceOverviewWrapper.tsx @@ -1,6 +1,6 @@ import React from 'react'; import classNames from 'classnames'; -import type { DeliveredTripMetrics, TripCounts } from '../../common/types/dataPoints'; +import type { DeliveredTripMetrics, ScheduledService } from '../../common/types/dataPoints'; import { BasicWidgetDataLayout } from '../../common/components/widgets/internal/BasicWidgetDataLayout'; import { PercentageWidgetValue, TripsWidgetValue } from '../../common/types/basicWidgets'; import type { ParamsType } from '../speed/constants/speeds'; @@ -9,7 +9,7 @@ import { getServiceWidgetValues } from './utils/utils'; interface ServiceOverviewWrapperProps { data: DeliveredTripMetrics[]; - predictedData: TripCounts; + predictedData: ScheduledService; config: ParamsType; startDate: string; endDate: string; diff --git a/modules/service/ServiceWidget.tsx b/modules/service/ServiceWidget.tsx index a2cebbb89..f6f648199 100644 --- a/modules/service/ServiceWidget.tsx +++ b/modules/service/ServiceWidget.tsx @@ -3,7 +3,7 @@ import dayjs from 'dayjs'; import { useDelimitatedRoute } from '../../common/utils/router'; import { ChartPlaceHolder } from '../../common/components/graphics/ChartPlaceHolder'; import { WidgetDiv } from '../../common/components/widgets/WidgetDiv'; -import { useTripCounts } from '../../common/api/hooks/service'; +import { useScheduledService } from '../../common/api/hooks/service'; import { OVERVIEW_OPTIONS, TODAY_STRING } from '../../common/constants/dates'; import { useDeliveredTripMetrics } from '../../common/api/hooks/tripmetrics'; import { getSpeedGraphConfig } from '../speed/constants/speeds'; @@ -25,7 +25,7 @@ export const ServiceWidget: React.FC = () => { }, enabled ); - const predictedServiceData = useTripCounts({ + const predictedServiceData = useScheduledService({ start_date: startDate, end_date: endDate, route_id: lineShort, diff --git a/modules/service/utils/utils.ts b/modules/service/utils/utils.ts index 3f1f0b403..1dd5de5bc 100644 --- a/modules/service/utils/utils.ts +++ b/modules/service/utils/utils.ts @@ -1,5 +1,5 @@ import { PEAK_SCHEDULED_SERVICE } from '../../../common/constants/baselines'; -import type { DeliveredTripMetrics, TripCounts } from '../../../common/types/dataPoints'; +import type { DeliveredTripMetrics, ScheduledService } from '../../../common/types/dataPoints'; import type { Line } from '../../../common/types/lines'; export const getServiceWidgetValues = ( @@ -32,7 +32,7 @@ export const getServiceWidgetValues = ( export const getPercentageData = ( data: DeliveredTripMetrics[], - predictedData: TripCounts, + predictedData: ScheduledService, line?: Line ) => { const scheduled = data.map((datapoint, index) => { diff --git a/server/.chalice/policy.json b/server/.chalice/policy.json index 96331a818..5489ee841 100644 --- a/server/.chalice/policy.json +++ b/server/.chalice/policy.json @@ -23,7 +23,7 @@ "arn:aws:dynamodb:*:*:table/DeliveredTripMetrics", "arn:aws:dynamodb:*:*:table/DeliveredTripMetricsWeekly", "arn:aws:dynamodb:*:*:table/DeliveredTripMetricsMonthly", - "arn:aws:dynamodb:*:*:table/TripCounts", + "arn:aws:dynamodb:*:*:table/ScheduledServiceDaily", "arn:aws:dynamodb:*:*:table/Ridership" ] } diff --git a/server/app.py b/server/app.py index d5a1d211e..58486c7c3 100644 --- a/server/app.py +++ b/server/app.py @@ -176,14 +176,14 @@ def get_trips_by_line(): return json.dumps(response, indent=4, sort_keys=True) -@app.route("/api/tripcounts", cors=cors_config) -def get_trip_counts(): +@app.route("/api/scheduledservice", cors=cors_config) +def get_scheduled_service(): query = app.current_request.query_params start_date = parse_user_date(query["start_date"]) end_date = parse_user_date(query["end_date"]) route_id = query.get("route_id") agg = query["agg"] - response = service_levels.get_trip_counts( + response = service_levels.get_scheduled_service( start_date=start_date, end_date=end_date, route_id=route_id, diff --git a/server/chalicelib/dynamo.py b/server/chalicelib/dynamo.py index 898c8fae0..9a9da70fe 100644 --- a/server/chalicelib/dynamo.py +++ b/server/chalicelib/dynamo.py @@ -26,8 +26,8 @@ def query_daily_trips_on_line(table_name, line, start_date, end_date): return results -def query_trip_counts(start_date: date, end_date: date, route_id: str = None): - table = dynamodb.Table("TripCounts") +def query_scheduled_service(start_date: date, end_date: date, route_id: str = None): + table = dynamodb.Table("ScheduledServiceDaily") line_condition = Key("routeId").eq(route_id) date_condition = Key("date").between(start_date.isoformat(), end_date.isoformat()) condition = line_condition & date_condition diff --git a/server/chalicelib/service_levels.py b/server/chalicelib/service_levels.py index 2345e8299..2e29973fd 100644 --- a/server/chalicelib/service_levels.py +++ b/server/chalicelib/service_levels.py @@ -2,13 +2,13 @@ from typing import List, Dict, TypedDict, Union, Literal import pandas as pd -from .dynamo import query_trip_counts +from .dynamo import query_scheduled_service from .data_funcs import index_by, date_range ByHourServiceLevels = List[int] DayKind = Union[Literal["weekday"], Literal["saturday"], Literal["sunday"]] AggTypes = Union[Literal["daily"], Literal["weekly"], Literal["monthly"]] -TripCounts = List[Dict] +ScheduledService = List[Dict] class ByDayKindServiceLevels(TypedDict): @@ -22,7 +22,7 @@ class ByDayKindServiceLevels(TypedDict): sunday: ByDayKindServiceLevels -class GetTripCountsResponse(TypedDict): +class GetScheduledServiceResponse(TypedDict): start_date_service_levels: ByDayKindServiceLevels end_date_service_levels: ByDayKindServiceLevels start_date: str @@ -31,11 +31,11 @@ class GetTripCountsResponse(TypedDict): def get_next_day_kind_service_levels( - trip_counts: TripCounts, + scheduled_service: ScheduledService, day_kind: DayKind, ) -> ByDayKindServiceLevels: - def predicate(trip_count): - day_of_week = datetime.fromisoformat(trip_count["date"]).weekday() + def predicate(scheduled_service_day): + day_of_week = datetime.fromisoformat(scheduled_service_day["date"]).weekday() if day_kind == "weekday": return day_of_week < 5 elif day_kind == "saturday": @@ -44,30 +44,30 @@ def predicate(trip_count): return day_of_week == 6 return False - for trip_count in trip_counts: - if predicate(trip_count): + for daily_service_count in scheduled_service: + if predicate(daily_service_count): return { - "date": trip_count["date"], - "service_levels": trip_count.get("byHour", {}).get("totals", []), + "date": daily_service_count["date"], + "service_levels": daily_service_count.get("byHour", {}).get("totals", []), } return None def get_service_levels( - trip_counts: TripCounts, + scheduled_service: ScheduledService, search_from_end: bool, ) -> ByDayKindServiceLevels: if search_from_end: - trip_counts = list(reversed(trip_counts)) + scheduled_service = list(reversed(scheduled_service)) return { - "weekday": get_next_day_kind_service_levels(trip_counts, "weekday"), - "saturday": get_next_day_kind_service_levels(trip_counts, "saturday"), - "sunday": get_next_day_kind_service_levels(trip_counts, "sunday"), + "weekday": get_next_day_kind_service_levels(scheduled_service, "weekday"), + "saturday": get_next_day_kind_service_levels(scheduled_service, "saturday"), + "sunday": get_next_day_kind_service_levels(scheduled_service, "sunday"), } -def get_weekly_trip_counts(trip_counts_arr, start_date, end_date): - df = pd.DataFrame({'value': trip_counts_arr}, index=pd.date_range(start_date, end_date)) +def get_weekly_scheduled_service(scheduled_service_arr, start_date, end_date): + df = pd.DataFrame({'value': scheduled_service_arr}, index=pd.date_range(start_date, end_date)) weekly_df = df.resample('W-SUN').median() # Drop the first week if it is incomplete if datetime.fromisoformat(start_date.isoformat()).weekday() != 6: @@ -75,8 +75,8 @@ def get_weekly_trip_counts(trip_counts_arr, start_date, end_date): return weekly_df['value'].tolist() -def get_monthly_trip_counts(trip_counts_arr, start_date, end_date): - df = pd.DataFrame({'value': trip_counts_arr}, index=pd.date_range(start_date, end_date)) +def get_monthly_scheduled_service(scheduled_service_arr, start_date, end_date): + df = pd.DataFrame({'value': scheduled_service_arr}, index=pd.date_range(start_date, end_date)) monthly_df = df.resample('M').median() # Drop the first month if it is incomplete if datetime.fromisoformat(start_date.isoformat()).day != 1: @@ -84,38 +84,38 @@ def get_monthly_trip_counts(trip_counts_arr, start_date, end_date): return monthly_df['value'].tolist() -def get_trip_counts( +def get_scheduled_service( start_date: date, end_date: date, agg: AggTypes, route_id: str = None, -) -> GetTripCountsResponse: - trip_counts = query_trip_counts( +) -> GetScheduledServiceResponse: + scheduled_service = query_scheduled_service( start_date=start_date, end_date=end_date, route_id=route_id, ) - trip_counts_by_date = index_by(trip_counts, "date") - trip_counts_arr = [] + scheduled_service_by_day = index_by(scheduled_service, "date") + scheduled_service_arr = [] for current_day in date_range(start_date, end_date): current_day_iso = current_day.isoformat() - if current_day_iso in trip_counts_by_date: - trip_count = trip_counts_by_date[current_day_iso]["count"] + if current_day_iso in scheduled_service_by_day: + scheduled_service_count = scheduled_service_by_day[current_day_iso]["count"] else: - trip_count = 0 - trip_counts_arr.append(trip_count) + scheduled_service_count = 0 + scheduled_service_arr.append(scheduled_service_count) counts = [] if agg == 'daily': - counts = trip_counts_arr + counts = scheduled_service_arr if agg == 'weekly': - counts = get_weekly_trip_counts(trip_counts_arr, start_date, end_date) + counts = get_weekly_scheduled_service(scheduled_service_arr, start_date, end_date) if agg == 'monthly': - counts = get_monthly_trip_counts(trip_counts_arr, start_date, end_date) + counts = get_monthly_scheduled_service(scheduled_service_arr, start_date, end_date) return { "counts": counts, "start_date": start_date.isoformat(), "end_date": end_date.isoformat(), - "start_date_service_levels": get_service_levels(trip_counts, False), - "end_date_service_levels": get_service_levels(trip_counts, True), + "start_date_service_levels": get_service_levels(scheduled_service, False), + "end_date_service_levels": get_service_levels(scheduled_service, True), }