From 052236e20aadf678b10a4cbe9eb757ea3dfa0f2c Mon Sep 17 00:00:00 2001 From: Michael Fatemi Date: Wed, 14 Jul 2021 13:08:25 -0400 Subject: [PATCH] organize code for optimal path, ensure miles are used --- src/components/Event/EventCarpools.tsx | 101 +++++++++++-------------- src/components/Event/EventSignups.tsx | 8 +- src/components/useOptimalPath.ts | 32 ++++++++ src/lib/furthestpoint.ts | 2 +- src/lib/getdistance.ts | 5 +- 5 files changed, 86 insertions(+), 62 deletions(-) create mode 100644 src/components/useOptimalPath.ts diff --git a/src/components/Event/EventCarpools.tsx b/src/components/Event/EventCarpools.tsx index 009b313..788c5be 100644 --- a/src/components/Event/EventCarpools.tsx +++ b/src/components/Event/EventCarpools.tsx @@ -1,10 +1,9 @@ import CancelIcon from '@material-ui/icons/Cancel'; import CheckIcon from '@material-ui/icons/Check'; import EmojiPeopleIcon from '@material-ui/icons/EmojiPeople'; -import { useEffect } from 'react'; -import { useCallback, useContext, useMemo, useState } from 'react'; +import { useCallback, useContext, useEffect, useMemo, useState } from 'react'; import { lightgrey } from '../../lib/colors'; -import furthestPoint from '../../lib/furthestpoint'; +import { Location } from '../../lib/estimateoptimalpath'; import { useCancelCarpoolRequest, useInvitationState, @@ -15,9 +14,33 @@ import { useMe } from '../hooks'; import { IEvent } from '../types'; import UIButton from '../UI/UIButton'; import UILink from '../UI/UILink'; -import EventContext from './EventContext'; -import estimateOptimalPath, { Location } from '../../lib/estimateoptimalpath'; +import useOptimalPath from '../useOptimalPath'; import usePlace from '../usePlace'; +import EventContext from './EventContext'; + +function useMemberLocations(members: IEvent['carpools'][0]['members']) { + const { signups } = useContext(EventContext); + + return useMemo( + () => + members + .map((member) => { + const signup = signups[member.id]; + if (!signup) { + return null; + } + if (signup.latitude === null) { + return null; + } + return { + latitude: signup.latitude, + longitude: signup.longitude, + }; + }) + .filter(Boolean) as Location[], + [members, signups] + ); +} function CarpoolRow({ carpool, @@ -32,8 +55,6 @@ function CarpoolRow({ const cancelCarpoolRequest = useCancelCarpoolRequest(); const sendCarpoolRequest = useSendCarpoolRequest(); - const { signups } = useContext(EventContext); - const sendButton = useCallback(() => { sendCarpoolRequest(carpool.id); }, [sendCarpoolRequest, carpool.id]); @@ -49,53 +70,25 @@ function CarpoolRow({ const myLocation = usePlace(myPlaceId); - const extraDistance = useMemo(() => { - if (!myLocation) { - console.log('!myLocation'); - return null; - } + const memberLocations = useMemberLocations(carpool.members); - // Calculates the minimum distance if I'm in the carpool - // and subtracts the distance if I'm not in the carpool + const pathInCarpool = useOptimalPath(memberLocations, { + latitude, + longitude, + }); - const memberLocations = carpool.members - .map((member) => { - const signup = signups[member.id]; - if (!signup) { - return null; - } - return { - latitude: signup.latitude, - longitude: signup.longitude, - }; - }) - .filter(Boolean) as Location[]; - - const { maxLocation: driverLocation } = furthestPoint(memberLocations, { + const pathNotInCarpool = useOptimalPath( + myLocation ? [...memberLocations, myLocation] : [], + { latitude, longitude, - }); + } + ); - const passengerLocations = memberLocations.filter( - (location) => location !== driverLocation - ); - - const { distance: distanceInCarpool } = estimateOptimalPath({ - from: driverLocation, - waypoints: [...passengerLocations, myLocation], - to: { latitude, longitude }, - }); - - const { distance: distanceNotInCarpool } = estimateOptimalPath({ - from: driverLocation, - waypoints: passengerLocations, - to: { latitude, longitude }, - }); - - return distanceInCarpool - distanceNotInCarpool; - }, [carpool.members, latitude, longitude, myLocation, signups]); - - console.log(carpool.id, extraDistance); + const extraDistance = + myLocation && pathInCarpool && pathNotInCarpool + ? pathInCarpool.distance - pathNotInCarpool.distance + : null; return (
{/*
*/} { window.location.href = '/carpools/' + carpool.id; }} > - {carpool.name} {extraDistance !== null && '+ ' + extraDistance} + {carpool.name} + {extraDistance !== null && ' +' + extraDistance.toFixed(1) + ' miles'}

- {/*
- {' '} - {carpool.extraDistance} miles -
*/} - {/*
*/} {!inCarpoolAlready && ( <> {inviteState === 'none' ? ( diff --git a/src/components/Event/EventSignups.tsx b/src/components/Event/EventSignups.tsx index a7ec3b6..bb1211f 100644 --- a/src/components/Event/EventSignups.tsx +++ b/src/components/Event/EventSignups.tsx @@ -28,7 +28,7 @@ function EventSignup({ hasCarpool, } = useContext(EventContext); - let extraDistance = useMemo(() => { + const extraDistance = useMemo(() => { if (myPlaceDetails != null && !(latitude === null || longitude === null)) { const myLatitude = myPlaceDetails.latitude; const myLongitude = myPlaceDetails.longitude; @@ -90,8 +90,10 @@ function EventSignup({ }} key={user.id} > - {user.name} - {extraDistance ? `: +${extraDistance.toFixed(1)} miles` : ''} + + {user.name} + {extraDistance ? ` +${extraDistance.toFixed(1)} miles` : ''} + {!hasCarpool && (isTentativelyInvited ? ( diff --git a/src/components/useOptimalPath.ts b/src/components/useOptimalPath.ts new file mode 100644 index 0000000..b51ee5c --- /dev/null +++ b/src/components/useOptimalPath.ts @@ -0,0 +1,32 @@ +import { useMemo } from 'react'; +import estimateOptimalPath, { Location } from '../lib/estimateoptimalpath'; +import furthestPoint from '../lib/furthestpoint'; + +export default function useOptimalPath( + memberLocations: Location[], + destination: Location +) { + return useMemo(() => { + if (memberLocations.length === 0) { + return null; + } + + // O(n) + const { maxLocation: driverLocation } = furthestPoint( + memberLocations, + destination + ); + + // O(n) + const passengerLocations = memberLocations.filter( + (location) => location !== driverLocation + ); + + // O(n) + return estimateOptimalPath({ + from: driverLocation!, + waypoints: passengerLocations, + to: destination, + }); + }, [destination, memberLocations]); +} diff --git a/src/lib/furthestpoint.ts b/src/lib/furthestpoint.ts index e97ab8b..a68ee75 100644 --- a/src/lib/furthestpoint.ts +++ b/src/lib/furthestpoint.ts @@ -6,7 +6,7 @@ export default function furthestPoint( destination: Location ) { let maxDistance = 0; - let maxLocation = { latitude: 0, longitude: 0 }; + let maxLocation = null; for (let i = 0; i < locations.length; i++) { let distance = getDistance(locations[i], destination); diff --git a/src/lib/getdistance.ts b/src/lib/getdistance.ts index d051038..b06515c 100644 --- a/src/lib/getdistance.ts +++ b/src/lib/getdistance.ts @@ -1,5 +1,5 @@ import { Location } from './estimateoptimalpath'; -import latlongdist from './latlongdist'; +import latlongdist, { R_miles } from './latlongdist'; export default function getDistance(...locations: Location[]): number { let distance = 0; @@ -10,7 +10,8 @@ export default function getDistance(...locations: Location[]): number { from.latitude, from.longitude, to.latitude, - to.longitude + to.longitude, + R_miles ); } return distance;