From 9cd81af4d9aa37652904edfe588e65685d9973eb Mon Sep 17 00:00:00 2001 From: moshe vilner Date: Wed, 11 Oct 2023 16:37:15 +0300 Subject: [PATCH 1/3] refactor: move data process logic to utils --- src/api/gapsService.ts | 2 +- src/pages/components/utils/index.test.ts | 54 +++++++++++++++++++++++- src/pages/components/utils/index.ts | 30 +++++++++++++ src/pages/useGapsList.ts | 31 ++------------ 4 files changed, 87 insertions(+), 30 deletions(-) diff --git a/src/api/gapsService.ts b/src/api/gapsService.ts index 801120f6..f610b533 100644 --- a/src/api/gapsService.ts +++ b/src/api/gapsService.ts @@ -10,7 +10,7 @@ type RawGapsList = { gtfs_ride_id?: number }[] -const parseTime = (time: string): Moment | null => { +export const parseTime = (time: string): Moment | null => { const utcMoment: Moment = moment.utc(time).tz('Asia/Jerusalem') if (!utcMoment.isValid()) { return null diff --git a/src/pages/components/utils/index.test.ts b/src/pages/components/utils/index.test.ts index 9a0be611..84775ee2 100644 --- a/src/pages/components/utils/index.test.ts +++ b/src/pages/components/utils/index.test.ts @@ -1,4 +1,6 @@ -import { HourlyData, sortByMode } from '.' +import { parseTime } from 'src/api/gapsService' +import { HourlyData, processData, sortByMode } from '.' +import { GapsList } from 'src/model/gaps' describe('sortByMode', () => { it('when mode param is "hour" - should be sorted properly', () => { @@ -36,4 +38,54 @@ describe('sortByMode', () => { /* record with less actual rides should come first */ expect(res[0].actual_rides).toBe(0) }) + + it('should convert gapList to HourlyData structure', () => { + const list: GapsList = [ + { + gtfsTime: parseTime('2023-10-04T02:00:00'), + siriTime: parseTime('2023-10-04T02:00:00'), + }, + ] + const [results] = processData(list) + expect(results).toEqual({ + actual_rides: 1, + planned_hour: "05:00", + planned_rides: 1, + }) + }) + + it('should convert gapList time entry with null value to - 0', () => { + const list: GapsList = [ + { + gtfsTime: parseTime('2023-10-04T02:20:00'), + siriTime: parseTime(null), + }, + ] + const [results] = processData(list) + + expect(results).toEqual({ + planned_hour: "05:20", + planned_rides: 1, + actual_rides: 0, + }) + }) + + it('should convert entries at same time to single entry with sum of actual and planned rides', () => { + const list: GapsList = [ + { + gtfsTime: parseTime('2023-10-04T02:00:00'), + siriTime: parseTime('2023-10-04T02:00:00'), + }, + { + gtfsTime: parseTime('2023-10-04T02:00:00'), + siriTime: parseTime('2023-10-04T02:00:00'), + }, + ] + const [results] = processData(list) + expect(results).toEqual({ + actual_rides: 2, + planned_hour: "05:00", + planned_rides: 2, + }) + }) }) diff --git a/src/pages/components/utils/index.ts b/src/pages/components/utils/index.ts index e2b0f613..0e74cdc3 100644 --- a/src/pages/components/utils/index.ts +++ b/src/pages/components/utils/index.ts @@ -1,3 +1,4 @@ +import { GapsList } from 'src/model/gaps' export interface HourlyData { planned_hour: string actual_rides: number @@ -38,3 +39,32 @@ export const mapColorByExecution = (planned: number, actual: number) => { return 'red' } } + +export type HourlyDataList = HourlyData[] + // Convert gapsList into HourlyDataList structure +export const processData = (gapsList: GapsList): HourlyDataList => { + // Convert gapsList data to hourly mapping structure, where hour is a key + const hourlyMapping: Record = {} + + for (const ride of gapsList) { + if (ride.gtfsTime === null) { + continue + } + const plannedHour = ride.gtfsTime.format('HH:mm') + + if (!hourlyMapping[plannedHour]) { + hourlyMapping[plannedHour] = { planned_rides: 0, actual_rides: 0 } + } + + hourlyMapping[plannedHour].planned_rides += 1 + if (ride.siriTime) { + hourlyMapping[plannedHour].actual_rides += 1 + } + } + // coverts hourlyMapping data to objects array where hour is a field + return Object.entries(hourlyMapping).map(([hour, data]) => ({ + planned_hour: hour, + actual_rides: data.actual_rides, + planned_rides: data.planned_rides, + })) +} diff --git a/src/pages/useGapsList.ts b/src/pages/useGapsList.ts index aefefedd..c1efd1cb 100644 --- a/src/pages/useGapsList.ts +++ b/src/pages/useGapsList.ts @@ -2,36 +2,9 @@ import { useEffect, useState } from 'react' import { Moment } from 'moment' import { getGapsAsync } from '../api/gapsService' -import { sortByMode, HourlyData } from './components/utils' +import { sortByMode, HourlyData, processData } from './components/utils' import { GapsList } from 'src/model/gaps' -export const processData = (gapsList: GapsList): HourlyData[] => { - // Convert gapsList data to hourly mapping structure, where hour is a key - const hourlyMapping: Record = {} - - for (const ride of gapsList) { - if (ride.gtfsTime === null) { - continue - } - const plannedHour = ride.gtfsTime.format('HH:mm') - - if (!hourlyMapping[plannedHour]) { - hourlyMapping[plannedHour] = { planned_rides: 0, actual_rides: 0 } - } - - hourlyMapping[plannedHour].planned_rides += 1 - if (ride.siriTime) { - hourlyMapping[plannedHour].actual_rides += 1 - } - } - // coverts hourlyMapping data to objects array where hour is a field - return Object.entries(hourlyMapping).map(([hour, data]) => ({ - planned_hour: hour, - actual_rides: data.actual_rides, - planned_rides: data.planned_rides, - })) -} - export const useGapsList = ( fromDate: Moment, toDate: Moment, @@ -39,12 +12,14 @@ export const useGapsList = ( lineRef: number, sortingMode: string, ): HourlyData[] => { + const [hourlyData, setHourlyData] = useState([]) useEffect(() => { const fetchData = async () => { try { const gapsList: GapsList = await getGapsAsync(fromDate, toDate, operatorRef, lineRef) + console.log(gapsList[0]) const result = processData(gapsList) setHourlyData(sortByMode(result, sortingMode)) } catch (error) { From 1de57c2607eb30036e7babf54ebdd0c16efc2978 Mon Sep 17 00:00:00 2001 From: moshe vilner Date: Wed, 11 Oct 2023 17:59:09 +0300 Subject: [PATCH 2/3] restore back the useGapsLists file --- src/pages/components/utils/index.test.ts | 15 ++++++----- src/pages/components/utils/index.ts | 30 --------------------- src/pages/useGapsList.ts | 33 +++++++++++++++++++++--- 3 files changed, 38 insertions(+), 40 deletions(-) diff --git a/src/pages/components/utils/index.test.ts b/src/pages/components/utils/index.test.ts index 84775ee2..a5c02ec7 100644 --- a/src/pages/components/utils/index.test.ts +++ b/src/pages/components/utils/index.test.ts @@ -1,6 +1,7 @@ import { parseTime } from 'src/api/gapsService' -import { HourlyData, processData, sortByMode } from '.' +import { HourlyData, sortByMode } from '.' import { GapsList } from 'src/model/gaps' +import { processData } from 'src/pages/useGapsList' describe('sortByMode', () => { it('when mode param is "hour" - should be sorted properly', () => { @@ -49,7 +50,7 @@ describe('sortByMode', () => { const [results] = processData(list) expect(results).toEqual({ actual_rides: 1, - planned_hour: "05:00", + planned_hour: '05:00', planned_rides: 1, }) }) @@ -58,13 +59,13 @@ describe('sortByMode', () => { const list: GapsList = [ { gtfsTime: parseTime('2023-10-04T02:20:00'), - siriTime: parseTime(null), + siriTime: parseTime('null'), }, ] const [results] = processData(list) - expect(results).toEqual({ - planned_hour: "05:20", + expect(results).toEqual({ + planned_hour: '05:20', planned_rides: 1, actual_rides: 0, }) @@ -84,8 +85,8 @@ describe('sortByMode', () => { const [results] = processData(list) expect(results).toEqual({ actual_rides: 2, - planned_hour: "05:00", + planned_hour: '05:00', planned_rides: 2, }) - }) + }) }) diff --git a/src/pages/components/utils/index.ts b/src/pages/components/utils/index.ts index 0e74cdc3..e2b0f613 100644 --- a/src/pages/components/utils/index.ts +++ b/src/pages/components/utils/index.ts @@ -1,4 +1,3 @@ -import { GapsList } from 'src/model/gaps' export interface HourlyData { planned_hour: string actual_rides: number @@ -39,32 +38,3 @@ export const mapColorByExecution = (planned: number, actual: number) => { return 'red' } } - -export type HourlyDataList = HourlyData[] - // Convert gapsList into HourlyDataList structure -export const processData = (gapsList: GapsList): HourlyDataList => { - // Convert gapsList data to hourly mapping structure, where hour is a key - const hourlyMapping: Record = {} - - for (const ride of gapsList) { - if (ride.gtfsTime === null) { - continue - } - const plannedHour = ride.gtfsTime.format('HH:mm') - - if (!hourlyMapping[plannedHour]) { - hourlyMapping[plannedHour] = { planned_rides: 0, actual_rides: 0 } - } - - hourlyMapping[plannedHour].planned_rides += 1 - if (ride.siriTime) { - hourlyMapping[plannedHour].actual_rides += 1 - } - } - // coverts hourlyMapping data to objects array where hour is a field - return Object.entries(hourlyMapping).map(([hour, data]) => ({ - planned_hour: hour, - actual_rides: data.actual_rides, - planned_rides: data.planned_rides, - })) -} diff --git a/src/pages/useGapsList.ts b/src/pages/useGapsList.ts index c1efd1cb..98d71bcb 100644 --- a/src/pages/useGapsList.ts +++ b/src/pages/useGapsList.ts @@ -2,9 +2,38 @@ import { useEffect, useState } from 'react' import { Moment } from 'moment' import { getGapsAsync } from '../api/gapsService' -import { sortByMode, HourlyData, processData } from './components/utils' +import { sortByMode, HourlyData } from './components/utils' import { GapsList } from 'src/model/gaps' +export type HourlyDataList = HourlyData[] +// Convert gapsList into HourlyDataList structure +export const processData = (gapsList: GapsList): HourlyDataList => { + // Convert gapsList data to hourly mapping structure, where hour is a key + const hourlyMapping: Record = {} + + for (const ride of gapsList) { + if (ride.gtfsTime === null) { + continue + } + const plannedHour = ride.gtfsTime.format('HH:mm') + + if (!hourlyMapping[plannedHour]) { + hourlyMapping[plannedHour] = { planned_rides: 0, actual_rides: 0 } + } + + hourlyMapping[plannedHour].planned_rides += 1 + if (ride.siriTime) { + hourlyMapping[plannedHour].actual_rides += 1 + } + } + // coverts hourlyMapping data to objects array where hour is a field + return Object.entries(hourlyMapping).map(([hour, data]) => ({ + planned_hour: hour, + actual_rides: data.actual_rides, + planned_rides: data.planned_rides, + })) +} + export const useGapsList = ( fromDate: Moment, toDate: Moment, @@ -12,14 +41,12 @@ export const useGapsList = ( lineRef: number, sortingMode: string, ): HourlyData[] => { - const [hourlyData, setHourlyData] = useState([]) useEffect(() => { const fetchData = async () => { try { const gapsList: GapsList = await getGapsAsync(fromDate, toDate, operatorRef, lineRef) - console.log(gapsList[0]) const result = processData(gapsList) setHourlyData(sortByMode(result, sortingMode)) } catch (error) { From 610973e3a1a593c9fdcbdf262740bd36ef7a9d36 Mon Sep 17 00:00:00 2001 From: moshe vilner Date: Wed, 11 Oct 2023 19:32:23 +0300 Subject: [PATCH 3/3] change method name processData -> convertGapsToHourlyStruct --- src/pages/components/utils/index.test.ts | 2 +- src/pages/useGapsList.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/pages/components/utils/index.test.ts b/src/pages/components/utils/index.test.ts index a5c02ec7..594e471e 100644 --- a/src/pages/components/utils/index.test.ts +++ b/src/pages/components/utils/index.test.ts @@ -1,7 +1,7 @@ import { parseTime } from 'src/api/gapsService' import { HourlyData, sortByMode } from '.' import { GapsList } from 'src/model/gaps' -import { processData } from 'src/pages/useGapsList' +import { convertGapsToHourlyStruct as processData } from 'src/pages/useGapsList' describe('sortByMode', () => { it('when mode param is "hour" - should be sorted properly', () => { diff --git a/src/pages/useGapsList.ts b/src/pages/useGapsList.ts index 98d71bcb..8c450475 100644 --- a/src/pages/useGapsList.ts +++ b/src/pages/useGapsList.ts @@ -7,7 +7,7 @@ import { GapsList } from 'src/model/gaps' export type HourlyDataList = HourlyData[] // Convert gapsList into HourlyDataList structure -export const processData = (gapsList: GapsList): HourlyDataList => { +export const convertGapsToHourlyStruct = (gapsList: GapsList): HourlyDataList => { // Convert gapsList data to hourly mapping structure, where hour is a key const hourlyMapping: Record = {} @@ -47,7 +47,7 @@ export const useGapsList = ( const fetchData = async () => { try { const gapsList: GapsList = await getGapsAsync(fromDate, toDate, operatorRef, lineRef) - const result = processData(gapsList) + const result = convertGapsToHourlyStruct(gapsList) setHourlyData(sortByMode(result, sortingMode)) } catch (error) { console.error('Error fetching data:', error)